diff options
author | Joanna Jeremicz <joanna.jeremicz@nokia.com> | 2021-04-21 13:59:12 +0200 |
---|---|---|
committer | Michael Morris <michael.morris@est.tech> | 2021-05-14 14:58:14 +0000 |
commit | e3de4c9d214983d38a7d66e89dae5d4bba170ca3 (patch) | |
tree | 9f92e5fc15d06051ffff254588bbcc1e85214d3f | |
parent | df353be353e1ec25ac2a0e64a9eb617dcbc87703 (diff) |
Integrate helm validator with SDC-BE
- Read helm validator configuration
- Add call to helm validator during Helm validation
- Add JUnit tests
- Fix display message when CNF upload is unsuccessful
- Show warning messages from validation after CNF upload
Issue-ID: SDC-3185
Signed-off-by: Joanna Jeremicz <joanna.jeremicz@nokia.com>
Change-Id: If197d557e6ddef4a07bef986d7cf133aedcb2cc5
Signed-off-by: Piotr Marcinkiewicz <piotr.marcinkiewicz@nokia.com>
33 files changed, 1076 insertions, 50 deletions
diff --git a/integration-tests/environments/integration-test.json b/integration-tests/environments/integration-test.json index 1f804b81c6..e71e53b01d 100644 --- a/integration-tests/environments/integration-test.json +++ b/integration-tests/environments/integration-test.json @@ -38,6 +38,13 @@ "VnfRepo": { "vnfRepoPort": "8702", "vnfRepoHost": "10.0.14.1" + }, + "HelmValidator": { + "validator_enabled": false, + "helm_version": "v3", + "deployable": true, + "lintable": false, + "strict_lintable": false } }, "override_attributes": { diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImpl.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImpl.java index 48ad75d09c..cd18cf973b 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImpl.java +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/OrchestrationTemplateCandidateImpl.java @@ -52,6 +52,7 @@ import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails; import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor; +import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator; import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo; import org.openecomp.sdc.vendorsoftwareproduct.types.OrchestrationTemplateActionResponse; import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse; @@ -98,10 +99,12 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate final byte[] fileToUploadBytes = fileToUpload.getObject(byte[].class); final DataHandler dataHandler = fileToUpload.getDataHandler(); final String filename = ValidationUtils.sanitizeInputString(dataHandler.getName()); - final OnboardingPackageProcessor onboardingPackageProcessor = new OnboardingPackageProcessor(filename, fileToUploadBytes); + final OnboardingPackageProcessor onboardingPackageProcessor = + new OnboardingPackageProcessor(filename, fileToUploadBytes, new CnfPackageValidator()); + final ErrorMessage[] errorMessages = onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]); if (onboardingPackageProcessor.hasErrors()) { final UploadFileResponseDto uploadFileResponseDto = buildUploadResponseWithError( - onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0])); + errorMessages); return Response.status(Status.NOT_ACCEPTABLE).entity(uploadFileResponseDto).build(); } final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null); @@ -112,23 +115,30 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate } final VspDetails vspDetails = new VspDetails(ValidationUtils.sanitizeInputString(vspId), new Version(ValidationUtils.sanitizeInputString(versionId))); - return processOnboardPackage(onboardPackageInfo, vspDetails); + return processOnboardPackage(onboardPackageInfo, vspDetails, errorMessages); } - private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails) { + private Response processOnboardPackage(final OnboardPackageInfo onboardPackageInfo, final VspDetails vspDetails, final ErrorMessage... errorMessages) { final UploadFileResponse uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo); final UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto() .applyMapping(uploadFileResponse, UploadFileResponseDto.class); + if (errorMessages.length > 0) { + uploadFileResponseDto.setErrors(getErrorMap(errorMessages)); + } return Response.ok(uploadFileResponseDto).build(); } - private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) { - final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto(); + private Map<String, List<ErrorMessage>> getErrorMap(ErrorMessage[] errorMessages) { final Map<String, List<ErrorMessage>> errorMap = new HashMap<>(); final List<ErrorMessage> errorMessageList = new ArrayList<>(); Collections.addAll(errorMessageList, errorMessages); errorMap.put(SdcCommon.UPLOAD_FILE, errorMessageList); - uploadFileResponseDto.setErrors(errorMap); + return errorMap; + } + + private UploadFileResponseDto buildUploadResponseWithError(final ErrorMessage... errorMessages) { + final UploadFileResponseDto uploadFileResponseDto = new UploadFileResponseDto(); + uploadFileResponseDto.setErrors(getErrorMap(errorMessages)); return uploadFileResponseDto; } diff --git a/openecomp-be/backend/openecomp-sdc-validation-manager/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java b/openecomp-be/backend/openecomp-sdc-validation-manager/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java new file mode 100644 index 0000000000..2246ca52ea --- /dev/null +++ b/openecomp-be/backend/openecomp-sdc-validation-manager/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java @@ -0,0 +1,33 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2021 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.impl.validators; + +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.validation.Validator; + +/** + * Stub required for class creation in test scope + */ +public class HelmValidator implements Validator { + + @Override + public void validate(GlobalValidationContext globalContext) { + } +} diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessor.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessor.java index 640a15735f..0446103491 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessor.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessor.java @@ -75,10 +75,11 @@ public class OnboardingPackageProcessor { private final CnfPackageValidator cnfPackageValidator; private FileContentHandler packageContent; - public OnboardingPackageProcessor(final String packageFileName, final byte[] packageFileContent) { + public OnboardingPackageProcessor(final String packageFileName, final byte[] packageFileContent, + final CnfPackageValidator cnfPackageValidator) { this.packageFileName = packageFileName; this.packageFileContent = packageFileContent; - this.cnfPackageValidator = new CnfPackageValidator(); + this.cnfPackageValidator = cnfPackageValidator; onboardPackageInfo = processPackage(); } @@ -87,11 +88,13 @@ public class OnboardingPackageProcessor { } public boolean hasErrors() { - return !errorMessages.isEmpty(); + return errorMessages.stream() + .anyMatch(error -> error.getLevel() == ErrorLevel.ERROR); } public boolean hasNoErrors() { - return errorMessages.isEmpty(); + return errorMessages.stream() + .noneMatch(error -> error.getLevel() == ErrorLevel.ERROR); } public Set<ErrorMessage> getErrorMessages() { diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidator.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidator.java index 50f1fd8d06..6c886f8e74 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidator.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidator.java @@ -42,7 +42,7 @@ public class CnfPackageValidator { Stats stats = new Stats(); for (FileData mod : modules) { if (mod.getBase() == null) { - stats.without++; + stats.withoutBase++; } else if (mod.getBase()) { stats.base++; } @@ -50,14 +50,14 @@ public class CnfPackageValidator { return stats; } - private List<String> createErrorMessages(Stats stats) { + private List<String> createErrorMessages(Stats result) { List<String> messages = new ArrayList<>(); - if (stats.without > 0) { - messages.add(MANIFEST_VALIDATION_HELM_IS_BASE_MISSING.formatMessage(stats.without)); + if (result.withoutBase > 0) { + messages.add(MANIFEST_VALIDATION_HELM_IS_BASE_MISSING.formatMessage(result.withoutBase)); } - if (stats.base == 0) { + if (result.base == 0) { messages.add(MANIFEST_VALIDATION_HELM_IS_BASE_NOT_SET.getErrorMessage()); - } else if (stats.base > 1) { + } else if (result.base > 1) { messages.add(MANIFEST_VALIDATION_HELM_IS_BASE_NOT_UNIQUE.getErrorMessage()); } return messages; @@ -66,6 +66,7 @@ public class CnfPackageValidator { private static class Stats { private int base = 0; - private int without = 0; + private int withoutBase = 0; } + } diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorTest.java index d6327866f4..6c847a713e 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorTest.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorTest.java @@ -49,6 +49,7 @@ import org.junit.runners.Parameterized.Parameters; import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum; import org.openecomp.sdc.datatypes.error.ErrorLevel; import org.openecomp.sdc.datatypes.error.ErrorMessage; +import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator; import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo; @RunWith(Parameterized.class) @@ -59,6 +60,7 @@ public class OnboardingPackageProcessorTest { private final byte[] packageBytes; private final Set<ErrorMessage> expectedErrorSet; private final OnboardingTypesEnum expectedPackageType; + private final CnfPackageValidator cnfPackageValidator; public OnboardingPackageProcessorTest(final String packageName, final byte[] packageBytes, final Set<ErrorMessage> expectedErrorSet, @@ -67,6 +69,7 @@ public class OnboardingPackageProcessorTest { this.packageBytes = packageBytes; this.expectedErrorSet = expectedErrorSet; this.expectedPackageType = expectedPackageType; + this.cnfPackageValidator = new CnfPackageValidator(); } @Parameters(name = "Run {index} for {0}") @@ -115,7 +118,7 @@ public class OnboardingPackageProcessorTest { @Test public void processPackage() { final OnboardingPackageProcessor onboardingPackageProcessor = new OnboardingPackageProcessor(packageName, - packageBytes); + packageBytes, cnfPackageValidator); assertThat("Should contains errors", onboardingPackageProcessor.hasErrors(), is(!expectedErrorSet.isEmpty())); assertThat("Should have the same number of errors", onboardingPackageProcessor.getErrorMessages().size(), equalTo(expectedErrorSet.size())); diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorUnitTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorUnitTest.java index a97a0f639a..795da7780f 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorUnitTest.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorUnitTest.java @@ -19,6 +19,9 @@ package org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -26,14 +29,13 @@ import org.junit.Test; import org.openecomp.sdc.heat.datatypes.manifest.FileData; import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type; import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; +import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator; public class OnboardingPackageProcessorUnitTest { - private OnboardingPackageProcessor processor = new OnboardingPackageProcessor("unitTestPackage", null); + private OnboardingPackageProcessor processor = new OnboardingPackageProcessor("unitTestPackage", + null, new CnfPackageValidator()); @Test public void shouldValidateZipPackage_helmWithoutHeat() { diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/CsarSecurityValidatorTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/CsarSecurityValidatorTest.java index 0fce606052..27d80412bf 100644 --- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/CsarSecurityValidatorTest.java +++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/CsarSecurityValidatorTest.java @@ -34,6 +34,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.OnboardingPackageProcessor; +import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator; import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager; import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException; import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo; @@ -56,7 +57,7 @@ public class CsarSecurityValidatorTest { public void isSignatureValidTestCorrectStructureAndValidSignatureExists() throws SecurityManagerException { final byte[] packageBytes = getFileBytesOrFail("signing/signed-package.zip"); final OnboardSignedPackage onboardSignedPackage = loadSignedPackage("signed-package.zip", - packageBytes); + packageBytes, null); when(securityManager.verifySignedData(any(), any(), any())).thenReturn(true); final boolean isSignatureValid = csarSecurityValidator.verifyPackageSignature(onboardSignedPackage); assertThat("Signature should be valid", isSignatureValid, is(true)); @@ -66,7 +67,7 @@ public class CsarSecurityValidatorTest { public void isSignatureValidTestCorrectStructureAndNotValidSignatureExists() throws SecurityManagerException { final byte[] packageBytes = getFileBytesOrFail("signing/signed-package-tampered-data.zip"); final OnboardSignedPackage onboardSignedPackage = loadSignedPackage("signed-package-tampered-data.zip", - packageBytes); + packageBytes, null); //no mocked securityManager csarSecurityValidator = new CsarSecurityValidator(); csarSecurityValidator.verifyPackageSignature(onboardSignedPackage); @@ -86,9 +87,10 @@ public class CsarSecurityValidatorTest { CsarSecurityValidatorTest.class.getResource(BASE_DIR + path).toURI())); } - private OnboardSignedPackage loadSignedPackage(final String packageName, final byte[] packageBytes) { + private OnboardSignedPackage loadSignedPackage(final String packageName, final byte[] packageBytes, + CnfPackageValidator cnfPackageValidator) { final OnboardingPackageProcessor onboardingPackageProcessor = - new OnboardingPackageProcessor(packageName, packageBytes); + new OnboardingPackageProcessor(packageName, packageBytes, cnfPackageValidator); final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null); if (onboardPackageInfo == null) { fail("Unexpected error. Could not load original package"); diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb index e7048427c7..17495687c8 100644 --- a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb @@ -42,6 +42,22 @@ template "VnfrepoConfiguration" do end +template "HelmValidatorConfiguration" do + path "#{ENV['JETTY_BASE']}/config/onboarding-be/config-helmvalidator.yaml" + source "helmvalidator-configuration.yaml.erb" + owner "jetty" + group "jetty" + mode "0755" + variables({ + :HVALIDATOR_ENABLED => node['HelmValidator']['validator_enabled'], + :HVALIDATOR_URL => node['HelmValidator']['validator_url'], + :HVALIDATOR_HELM_VERSION => node['HelmValidator']['helm_version'], + :HVALIDATOR_DEPLOYABLE => node['HelmValidator']['deployable'], + :HVALIDATOR_LINTABLE => node['HelmValidator']['lintable'], + :HVALIDATOR_STRICT_LINTABLE => node['HelmValidator']['strict_lintable'] + }) +end + template "ExternalTestingConfiguration" do path "#{ENV['JETTY_BASE']}/config/onboarding-be/externaltesting-configuration.yaml" diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/helmvalidator-configuration.yaml.erb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/helmvalidator-configuration.yaml.erb new file mode 100644 index 0000000000..37021c7a9a --- /dev/null +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/helmvalidator-configuration.yaml.erb @@ -0,0 +1,6 @@ +hValidatorEnabled: <%= @HVALIDATOR_ENABLED %> +hValidatorUrl: <%= @HVALIDATOR_URL %> +hValidatorVersion: <%= @HVALIDATOR_HELM_VERSION %> +hValidatorDeployable: <%= @HVALIDATOR_DEPLOYABLE %> +hValidatorLintable: <%= @HVALIDATOR_LINTABLE %> +hValidatorStrictLintable: <%= @HVALIDATOR_STRICT_LINTABLE %> diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-core/src/main/resources/config-validaton.json b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-core/src/main/resources/config-validaton.json index 75fd84c574..46e3f8441f 100644 --- a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-core/src/main/resources/config-validaton.json +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-core/src/main/resources/config-validaton.json @@ -23,6 +23,10 @@ "enable": true, "implementationClass": "org.openecomp.sdc.validation.impl.validators.ContrailValidator" }, + "helmValidator": { + "enable": true, + "implementationClass": "org.openecomp.sdc.validation.impl.validators.HelmValidator" + }, "resourceHeatValidator": { "enable": true, "implementationClass": "org.openecomp.sdc.validation.impl.validators.HeatResourceValidator", @@ -96,4 +100,4 @@ "_config":{ "namespace": "validation" } -}
\ No newline at end of file +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/pom.xml b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/pom.xml index a34e4daa10..d88e3f7431 100644 --- a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/pom.xml +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/pom.xml @@ -1,6 +1,6 @@ <!-- ~ Copyright © 2016-2018 European Support Limited - ~ Copyright © 2020 Nokia + ~ Copyright © 2020-2021 Nokia ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -94,6 +94,12 @@ <artifactId>vavr</artifactId> <version>${io.vavr.version}</version> </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpmime</artifactId> + <version>${httpclient.version}</version> + <scope>compile</scope> + </dependency> </dependencies> </project> diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReader.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReader.java new file mode 100644 index 0000000000..4d4fff7971 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReader.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.validation.impl.util; + +import org.onap.config.api.Configuration; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorConfig; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorConfig.HelmValidationConfigBuilder; + +public class HelmValidatorConfigReader { + + private static final Logger LOGGER = LoggerFactory.getLogger(HelmValidatorConfigReader.class); + private static final String CONFIG_NAMESPACE = "helmvalidator"; + private static final String ERROR_MESSAGE = "Failed to read helm validator configuration key '{}', default value '{}' will be used"; + private final Configuration config; + + public HelmValidatorConfigReader(Configuration config) { + this.config = config; + } + + public HelmValidatorConfig getHelmValidatorConfig() { + String version = readValue("hValidatorVersion", "3.5.2"); + String validatorUrl = readValue("hValidatorUrl", "http://localhost:8082/validate"); + boolean enabled = readValue("hValidatorEnabled", false); + boolean deployable = readValue("hValidatorDeployable", false); + boolean lintable = readValue("hValidatorLintable", false); + boolean strictLintable = readValue("hValidatorStrictLintable", false); + + HelmValidationConfigBuilder validationConfigBuilder = new HelmValidationConfigBuilder(); + validationConfigBuilder.setValidatorUrl(validatorUrl); + validationConfigBuilder.setVersion(version); + validationConfigBuilder.setEnabled(enabled); + validationConfigBuilder.setDeployable(deployable); + validationConfigBuilder.setLintable(lintable); + validationConfigBuilder.setStrictLintable(strictLintable); + return validationConfigBuilder.build(); + } + + + private String readValue(String key, String defaultValue) { + try { + String value = config.getAsString(CONFIG_NAMESPACE, key); + return (value == null) ? defaultValue : value; + } catch (Exception e) { + LOGGER.error(ERROR_MESSAGE, key, defaultValue, e); + return defaultValue; + } + } + + private boolean readValue(String key, boolean defaultValue) { + try { + Boolean value = config.getAsBooleanValue(CONFIG_NAMESPACE, key); + return (value == null) ? defaultValue : value; + } catch (Exception e) { + LOGGER.error(ERROR_MESSAGE, key, defaultValue, e); + return defaultValue; + } + } + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClient.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClient.java new file mode 100644 index 0000000000..299d996562 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClient.java @@ -0,0 +1,73 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.impl.util; + +import org.apache.http.HttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.openecomp.sdc.common.http.client.api.HttpExecuteException; +import org.openecomp.sdc.common.http.client.api.HttpRequestHandler; +import org.openecomp.sdc.common.http.client.api.HttpResponse; +import org.openecomp.sdc.common.http.config.HttpClientConfig; +import org.openecomp.sdc.common.http.config.Timeouts; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorConfig; + +public class HelmValidatorHttpClient { + + private static final Logger LOGGER = LoggerFactory.getLogger(HelmValidatorHttpClient.class); + private static final int TIMEOUT_MS = 10000; + private static final String FILE = "file"; + private static final String IS_LINTED = "isLinted"; + private static final String IS_STRICT_LINTED = "isStrictLinted"; + private static final String VERSION_DESIRED = "versionDesired"; + private final HttpRequestHandler httpRequestHandler; + + public HelmValidatorHttpClient(HttpRequestHandler httpRequestHandler) { + this.httpRequestHandler = httpRequestHandler; + } + + public HttpResponse<String> execute(String fileName, byte[] helmChartFile, HelmValidatorConfig validatorConfig) throws Exception{ + LOGGER.info("Trying to execute Helm chart validation. File name: {}", fileName); + try { + HttpEntity entity = MultipartEntityBuilder.create() + .addBinaryBody(FILE, helmChartFile, ContentType.DEFAULT_BINARY, fileName) + .addTextBody(IS_LINTED, getString(validatorConfig.isLintable())) + .addTextBody(IS_STRICT_LINTED, getString(validatorConfig.isStrictLintable())) + .addTextBody(VERSION_DESIRED, validatorConfig.getVersion()) + .build(); + + HttpResponse<String> httpResponse = httpRequestHandler.post(validatorConfig.getValidatorUrl(), + null, entity, new HttpClientConfig(new Timeouts(TIMEOUT_MS, TIMEOUT_MS))); + LOGGER.info("Received response from Helm chart validator with code {}", httpResponse.getStatusCode()); + LOGGER.debug("Response from Helm chart validator: {}", httpResponse); + + return httpResponse; + } catch (HttpExecuteException e) { + LOGGER.info("Exception during call to Helm validator {}", e.getMessage()); + } + throw new Exception("Http response is invalid."); + } + + private String getString(boolean helmValidatorConfig) { + return Boolean.toString(helmValidatorConfig); + } + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtil.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtil.java index 0e199cc472..b490f4b35f 100644 --- a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtil.java +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtil.java @@ -25,6 +25,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import org.openecomp.core.validation.types.GlobalValidationContext; import org.openecomp.sdc.heat.datatypes.manifest.FileData; +import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type; import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; import org.openecomp.sdc.heat.services.manifest.ManifestUtil; import org.openecomp.sdc.validation.util.ValidationUtil; @@ -34,20 +35,22 @@ class GlobalContextUtil { private GlobalContextUtil() { } - static Set<String> findPmDictionaryFiles(GlobalValidationContext globalContext) { + static Set<String> findFilesByType(GlobalValidationContext globalContext, Type type) { if (isManifestMissing(globalContext)) { return Set.of(); } Map<String, FileData.Type> filesWithTypes = readAllFilesWithTypes(globalContext); - return filterPmDictionaryFiles(filesWithTypes); + return filterFilesByType(filesWithTypes, entry -> entry.getValue().equals(type)); } private static boolean isManifestMissing(GlobalValidationContext globalContext) { return globalContext.getFileContent("MANIFEST.json").isEmpty(); } - private static Set<String> filterPmDictionaryFiles(Map<String, FileData.Type> filesWithTypes) { - return filesWithTypes.entrySet().stream().filter(isPmDictionaryType()).map(Map.Entry::getKey).collect(Collectors.toSet()); + private static Set<String> filterFilesByType(Map<String, FileData.Type> filesWithTypes, + Predicate<Map.Entry<String, FileData.Type>> typePredicate) { + return filesWithTypes.entrySet().stream().filter(typePredicate).map(Map.Entry::getKey) + .collect(Collectors.toSet()); } private static Map<String, FileData.Type> readAllFilesWithTypes(GlobalValidationContext globalContext) { @@ -55,7 +58,4 @@ class GlobalContextUtil { return ManifestUtil.getFileTypeMap(manifestContent); } - private static Predicate<Map.Entry<String, FileData.Type>> isPmDictionaryType() { - return entry -> entry.getValue().equals(FileData.Type.PM_DICTIONARY); - } } diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java index 19b8892182..fbfd9c7b29 100644 --- a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java @@ -1,5 +1,6 @@ /* * Copyright © 2016-2017 European Support Limited + * Copyright (C) 2021 Nokia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +34,7 @@ import org.openecomp.sdc.common.errors.Messages; import org.openecomp.sdc.datatypes.error.ErrorLevel; import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes; import org.openecomp.sdc.heat.datatypes.manifest.FileData; +import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type; import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; import org.openecomp.sdc.heat.datatypes.model.Environment; import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate; @@ -453,7 +455,10 @@ public class HeatValidator implements Validator { globalContext.getFiles().stream().filter(fileName -> FileData.isHeatFile(fileTypeMap.get(fileName))).forEach( fileName -> validate(fileName, fileEnvMap.get(fileName) == null ? null : fileEnvMap.get(fileName).getFile(), artifacts, globalContext)); Set<String> manifestArtifacts = ManifestUtil.getArtifacts(manifestContent); - globalContext.getFiles().stream().filter(fileName -> isManifestArtifact(manifestArtifacts, fileName) && isNotArtifact(artifacts, fileName)) + globalContext.getFiles().stream() + .filter(fileName -> isManifestArtifact(manifestArtifacts, fileName) + && isNotArtifact(artifacts, fileName) + && isNotHelmType(fileTypeMap, fileName)) .forEach(fileName -> { globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder.getErrorWithParameters(ERROR_CODE_HOT_11, Messages.ARTIFACT_FILE_NOT_REFERENCED.getErrorMessage())); @@ -468,6 +473,10 @@ public class HeatValidator implements Validator { } } + private boolean isNotHelmType(Map<String, Type> fileTypeMap, String fileName) { + return !Type.HELM.equals(fileTypeMap.get(fileName)); + } + private boolean isManifestArtifact(Set<String> manifestArtifacts, String fileName) { return manifestArtifacts.contains(fileName); } diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java new file mode 100644 index 0000000000..272d0a88b9 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java @@ -0,0 +1,106 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.impl.validators; + +import com.google.gson.Gson; +import java.io.InputStream; +import java.util.Optional; +import java.util.Set; +import org.onap.config.api.ConfigurationManager; +import org.openecomp.core.validation.ErrorMessageCode; +import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.common.http.client.api.HttpRequestHandler; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.openecomp.sdc.validation.Validator; +import org.openecomp.sdc.validation.impl.util.HelmValidatorConfigReader; +import org.openecomp.sdc.validation.impl.util.HelmValidatorHttpClient; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorConfig; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorErrorResponse; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorResponse; + +public class HelmValidator implements Validator { + + private static final Logger LOGGER = LoggerFactory.getLogger(HelmValidator.class); + private static final ErrorMessageCode VALIDATOR_ERROR_CODE = new ErrorMessageCode("HELM VALIDATOR"); + private static final String EXCEPTION_MESSAGE = "Could not execute file %s validation using Helm"; + + private final HelmValidatorHttpClient helmValidatorHttpClient; + private final HelmValidatorConfig helmValidatorConfig; + + public HelmValidator() { + this(new HelmValidatorHttpClient(HttpRequestHandler.get()), + new HelmValidatorConfigReader(ConfigurationManager.lookup()).getHelmValidatorConfig()); + } + + HelmValidator(HelmValidatorHttpClient helmValidatorHttpClient, HelmValidatorConfig helmValidatorConfig) { + this.helmValidatorHttpClient = helmValidatorHttpClient; + this.helmValidatorConfig = helmValidatorConfig; + } + + @Override + public void validate(GlobalValidationContext globalContext) { + if (helmValidatorConfig.isEnabled()) { + Set<String> manifestFiles = GlobalContextUtil.findFilesByType(globalContext, Type.HELM); + manifestFiles.forEach(file -> tryValidateSingleChart(globalContext, file)); + } + } + + private void tryValidateSingleChart(GlobalValidationContext globalContext, String fileName) { + Optional<InputStream> fileContent = globalContext.getFileContent(fileName); + if (fileContent.isPresent()) { + try { + validateSingleHelmChart(fileName, fileContent.get().readAllBytes(), globalContext); + } catch (Exception exception) { + String validationErrorMessage = String.format(EXCEPTION_MESSAGE, fileName); + LOGGER.error(validationErrorMessage + " exception: " + exception.getMessage()); + addError(fileName, globalContext, validationErrorMessage, ErrorLevel.WARNING); + } + } else { + LOGGER.debug("File content is not present " + fileName); + } + } + + private void validateSingleHelmChart(String fileName, byte[] file, GlobalValidationContext globalContext) + throws Exception { + var httpResponse = helmValidatorHttpClient.execute(fileName, file, helmValidatorConfig); + if (httpResponse.getStatusCode() == 200) { + var helmValidatorResponse = new Gson() + .fromJson(httpResponse.getResponse(), HelmValidatorResponse.class); + helmValidatorResponse.getRenderErrors().forEach(error -> + addError(fileName, globalContext, error, ErrorLevel.ERROR)); + helmValidatorResponse.getLintError().forEach(lintError -> + addError(fileName, globalContext, lintError, ErrorLevel.WARNING)); + helmValidatorResponse.getLintWarning().forEach(lintWarning -> + addError(fileName, globalContext, lintWarning, ErrorLevel.WARNING)); + } else { + var errorResponse = new Gson().fromJson(httpResponse.getResponse(), HelmValidatorErrorResponse.class); + addError(fileName, globalContext, errorResponse.getMessage(), ErrorLevel.WARNING); + } + } + + private void addError(String fileName, GlobalValidationContext globalContext, String error, ErrorLevel level) { + globalContext.addMessage(fileName, level, ErrorMessagesFormatBuilder + .getErrorWithParameters(VALIDATOR_ERROR_CODE, error, fileName)); + } + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/PmDictionaryValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/PmDictionaryValidator.java index 4dad4afc16..22b5efc838 100644 --- a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/PmDictionaryValidator.java +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/PmDictionaryValidator.java @@ -30,6 +30,7 @@ import org.openecomp.core.validation.ErrorMessageCode; import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; import org.openecomp.core.validation.types.GlobalValidationContext; import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type; import org.openecomp.sdc.validation.Validator; public class PmDictionaryValidator implements Validator { @@ -38,7 +39,7 @@ public class PmDictionaryValidator implements Validator { @Override public void validate(GlobalValidationContext globalContext) { - Set<String> pmDictionaryFiles = GlobalContextUtil.findPmDictionaryFiles(globalContext); + Set<String> pmDictionaryFiles = GlobalContextUtil.findFilesByType(globalContext, Type.PM_DICTIONARY); validatePmDictionaryFiles(globalContext, pmDictionaryFiles); } diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java index cb9469a146..eb43925d02 100644 --- a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java @@ -28,6 +28,7 @@ import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; import org.openecomp.core.validation.types.GlobalValidationContext; import org.openecomp.sdc.common.errors.Messages; import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type; import org.openecomp.sdc.validation.Validator; import org.openecomp.sdc.validation.impl.util.YamlValidatorUtil; import org.yaml.snakeyaml.DumperOptions; @@ -44,7 +45,7 @@ public class YamlValidator implements Validator { @Override public void validate(GlobalValidationContext globalContext) { - Set<String> pmDictionaryFiles = GlobalContextUtil.findPmDictionaryFiles(globalContext); + Set<String> pmDictionaryFiles = GlobalContextUtil.findFilesByType(globalContext, Type.PM_DICTIONARY); Collection<String> files = globalContext .files((fileName, globalValidationContext) -> FileExtensionUtils.isYaml(fileName) && !pmDictionaryFiles.contains(fileName)); files.forEach(fileName -> validate(fileName, globalContext)); diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorConfig.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorConfig.java new file mode 100644 index 0000000000..45d0377651 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorConfig.java @@ -0,0 +1,78 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.type.helmvalidator; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class HelmValidatorConfig { + private final String validatorUrl; + private final String version; + private final boolean isEnabled; + private final boolean isDeployable; + private final boolean isLintable; + private final boolean isStrictLintable; + + public static class HelmValidationConfigBuilder { + + private String validatorUrl; + private String version; + private boolean enabled; + private boolean deployable; + private boolean lintable; + private boolean strictLintable; + + public HelmValidationConfigBuilder setVersion(String version) { + this.version = version; + return this; + } + + public HelmValidationConfigBuilder setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public HelmValidationConfigBuilder setDeployable(boolean deployable) { + this.deployable = deployable; + return this; + } + + public HelmValidationConfigBuilder setLintable(boolean lintable) { + this.lintable = lintable; + return this; + } + + public HelmValidationConfigBuilder setStrictLintable(boolean strictLintable) { + this.strictLintable = strictLintable; + return this; + } + + public HelmValidationConfigBuilder setValidatorUrl(String validatorUrl) { + this.validatorUrl = validatorUrl; + return this; + } + + public HelmValidatorConfig build() { + return new HelmValidatorConfig(validatorUrl, version, enabled, deployable, lintable, strictLintable); + } + } + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorErrorResponse.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorErrorResponse.java new file mode 100644 index 0000000000..c92b528d6f --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorErrorResponse.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.type.helmvalidator; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Helm validator error response + */ + +@AllArgsConstructor +public final class HelmValidatorErrorResponse { + + @Getter + private final String message; + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorResponse.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorResponse.java new file mode 100644 index 0000000000..40deeb57a3 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorResponse.java @@ -0,0 +1,66 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.type.helmvalidator; + +import com.google.gson.annotations.SerializedName; +import java.util.Collections; +import java.util.List; +import lombok.Getter; + +public final class HelmValidatorResponse { + + private List<String> renderErrors; + private List<String> lintWarning; + private List<String> lintError; + @Getter + private String versionUsed; + @SerializedName("valid") + @Getter + private Boolean isValid; + @SerializedName("deployable") + @Getter + private Boolean isDeployable; + + /** + * Get renderErrors + * + * @return renderErrors + **/ + public List<String> getRenderErrors() { + return renderErrors != null ? renderErrors : Collections.emptyList(); + } + + /** + * Get lintWarning + * + * @return lintWarning + **/ + public List<String> getLintWarning() { + return lintWarning != null ? lintWarning : Collections.emptyList(); + } + + /** + * Get lintError + * + * @return lintError + **/ + public List<String> getLintError() { + return lintError != null ? lintError : Collections.emptyList(); + } +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReaderTest.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReaderTest.java new file mode 100644 index 0000000000..ba4728f8d5 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReaderTest.java @@ -0,0 +1,113 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.validation.impl.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.config.api.Configuration; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorConfig; + +@ExtendWith(MockitoExtension.class) +class HelmValidatorConfigReaderTest { + + private final static String CONFIG_NAMESPACE = "helmvalidator"; + @Mock + private Configuration configuration; + + @ParameterizedTest + @ValueSource(strings = {"v3", "3.4.5"}) + void shouldReadVersionFromConfig(String helmVersion) { + //given + when(configuration.getAsString(CONFIG_NAMESPACE, "hValidatorVersion")).thenReturn(helmVersion); + HelmValidatorConfigReader helmValidatorConfigReader = new HelmValidatorConfigReader(configuration); + //when + HelmValidatorConfig helmValidatorConfig = helmValidatorConfigReader.getHelmValidatorConfig(); + //then + assertEquals(helmVersion, helmValidatorConfig.getVersion()); + } + + @ParameterizedTest + @ValueSource(strings = {"http://localhost:3211", "https://test-abc"}) + void shouldReadValidatorUrlFromConfig(String validatorUrl) { + //given + when(configuration.getAsString(CONFIG_NAMESPACE, "hValidatorUrl")).thenReturn(validatorUrl); + HelmValidatorConfigReader helmValidatorConfigReader = new HelmValidatorConfigReader(configuration); + //when + HelmValidatorConfig helmValidatorConfig = helmValidatorConfigReader.getHelmValidatorConfig(); + //then + assertEquals(validatorUrl, helmValidatorConfig.getValidatorUrl()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void shouldReadEnabledValueFromConfig(boolean isEnabled) { + //given + when(configuration.getAsBooleanValue(CONFIG_NAMESPACE, "hValidatorEnabled")).thenReturn(isEnabled); + HelmValidatorConfigReader helmValidatorConfigReader = new HelmValidatorConfigReader(configuration); + //when + HelmValidatorConfig helmValidatorConfig = helmValidatorConfigReader.getHelmValidatorConfig(); + //then + Assertions.assertEquals(isEnabled, helmValidatorConfig.isEnabled()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void shouldReadDeployableValueFromConfig(boolean isDeployable) { + //given + when(configuration.getAsBooleanValue(CONFIG_NAMESPACE, "hValidatorDeployable")).thenReturn(isDeployable); + HelmValidatorConfigReader helmValidatorConfigReader = new HelmValidatorConfigReader(configuration); + //when + HelmValidatorConfig helmValidatorConfig = helmValidatorConfigReader.getHelmValidatorConfig(); + //then + Assertions.assertEquals(isDeployable, helmValidatorConfig.isDeployable()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void shouldReadLintableValueFromConfig(boolean isLintable) { + //given + when(configuration.getAsBooleanValue(CONFIG_NAMESPACE, "hValidatorLintable")).thenReturn(isLintable); + HelmValidatorConfigReader helmValidatorConfigReader = new HelmValidatorConfigReader(configuration); + //when + HelmValidatorConfig helmValidatorConfig = helmValidatorConfigReader.getHelmValidatorConfig(); + //then + Assertions.assertEquals(isLintable, helmValidatorConfig.isLintable()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void shouldReadStrictLintableValueFromConfig(boolean isStrictLintable) { + //given + when(configuration.getAsBooleanValue(CONFIG_NAMESPACE, "hValidatorStrictLintable")) + .thenReturn(isStrictLintable); + HelmValidatorConfigReader helmValidatorConfigReader = new HelmValidatorConfigReader(configuration); + //when + HelmValidatorConfig helmValidatorConfig = helmValidatorConfigReader.getHelmValidatorConfig(); + //then + Assertions.assertEquals(isStrictLintable, helmValidatorConfig.isStrictLintable()); + } +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClientTest.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClientTest.java new file mode 100644 index 0000000000..be1c1a81e2 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClientTest.java @@ -0,0 +1,185 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.impl.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.MessageFormat; +import java.util.stream.Collectors; +import org.apache.http.HttpEntity; +import org.apache.http.protocol.HTTP; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openecomp.sdc.common.http.client.api.HttpExecuteException; +import org.openecomp.sdc.common.http.client.api.HttpRequestHandler; +import org.openecomp.sdc.common.http.client.api.HttpResponse; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorConfig; + +@ExtendWith(MockitoExtension.class) +class HelmValidatorHttpClientTest { + + private static final String EXAMPLE_RESPONSE = "{\"renderErrors\":[],\"lintWarning\":[\"[WARNING] warning description\"],\"lintError\":[],\"versionUsed\":\"3.5.2\",\"valid\":false,\"deployable\":true}"; + private static final String TEST_CHART_FILE_NAME = "testchart"; + private static final String HTTP_ENTITY_PATTERN = + "Content-Disposition: form-data; name=\"file\"; filename=\"{0}\" {1} " + + "Content-Disposition: form-data; name=\"isLinted\" {2} " + + "Content-Disposition: form-data; name=\"isStrictLinted\" {3} " + + "Content-Disposition: form-data; name=\"versionDesired\" {4}"; + private static final String HTTPS_TEST_URL = "https://test-url"; + private static final String TEST_VERSION = "3.5.6"; + @Mock + private HttpRequestHandler httpRequestHandler; + @Mock + private HelmValidatorConfig helmValidatorConfig; + @InjectMocks + private HelmValidatorHttpClient client; + @Captor + private ArgumentCaptor<HttpEntity> httpEntityCaptor; + @TempDir + static Path tempDir; + + @BeforeEach + void init() throws HttpExecuteException { + when(httpRequestHandler.post(any(), any(), any(), any())) + .thenReturn(new HttpResponse<>(EXAMPLE_RESPONSE, 215)); + when(helmValidatorConfig.getValidatorUrl()).thenReturn(HTTPS_TEST_URL); + when(helmValidatorConfig.getVersion()).thenReturn(TEST_VERSION); + } + + @ParameterizedTest + @ValueSource(strings = {"http://test123", "test-url:8080"}) + void shouldSendPostToValidatorUrl(String validatorUrl) throws Exception { + when(helmValidatorConfig.getValidatorUrl()).thenReturn(validatorUrl); + //given, when + var response = client.execute(TEST_CHART_FILE_NAME, "".getBytes(), helmValidatorConfig); + //then + Assertions.assertEquals(215, response.getStatusCode()); + Assertions.assertEquals(EXAMPLE_RESPONSE, response.getResponse()); + verify(httpRequestHandler).post(eq(validatorUrl), any(), any(), any()); + } + + @ParameterizedTest + @ValueSource(strings = {"3.5.4", "v3", "1.2.3"}) + void shouldPrepareRequestWithDesiredVersion(String desiredVersion) throws Exception { + //given + Path chartPath = getTestPath(TEST_CHART_FILE_NAME, ""); + when(helmValidatorConfig.getVersion()).thenReturn(desiredVersion); + //when + client.execute(chartPath.toString(), "".getBytes(), helmValidatorConfig); + //then + verify(httpRequestHandler).post(any(), any(), httpEntityCaptor.capture(), any()); + + Object[] testArgs = {chartPath, "", false, false, desiredVersion}; + String expectedHttpEntityContent = new MessageFormat(HTTP_ENTITY_PATTERN).format(testArgs); + String actualHttpEntityContent = getHttpEntityContent(); + + assertEquals(expectedHttpEntityContent, actualHttpEntityContent); + + } + + @ParameterizedTest + @CsvSource({"fileName,chart content 123", "b,content", "chart,12345\n21234"}) + void shouldPrepareRequestWithChartFromConfig(String testChartFileName, String testChartContent) + throws Exception { + //given + Path chartPath = getTestPath(testChartFileName, testChartContent); + //when + client.execute(chartPath.toString(), testChartContent.getBytes(), helmValidatorConfig); + //then + verify(httpRequestHandler).post(any(), any(), httpEntityCaptor.capture(), any()); + + Object[] testArgs = {chartPath, testChartContent, false, false, "3.5.6"}; + String expectedHttpEntityContent = new MessageFormat(HTTP_ENTITY_PATTERN).format(testArgs); + String actualHttpEntityContent = getHttpEntityContent(); + + assertEquals(expectedHttpEntityContent, actualHttpEntityContent); + } + + @Test + void shouldPrepareLintableRequest() throws Exception { + //given + Path chartPath = getTestPath(TEST_CHART_FILE_NAME, ""); + when(helmValidatorConfig.isLintable()).thenReturn(true); + //when + client.execute(chartPath.toString(), "".getBytes(), helmValidatorConfig); + //then + verify(httpRequestHandler).post(any(), any(), httpEntityCaptor.capture(), any()); + + Object[] testArgs = {chartPath, "", true, false, "3.5.6"}; + String expectedHttpEntityContent = new MessageFormat(HTTP_ENTITY_PATTERN).format(testArgs); + String actualHttpEntityContent = getHttpEntityContent(); + + assertEquals(expectedHttpEntityContent, actualHttpEntityContent); + } + + @Test + void shouldPrepareStrictLintableRequest() throws Exception { + //given + Path chartPath = getTestPath(TEST_CHART_FILE_NAME, ""); + when(helmValidatorConfig.isStrictLintable()).thenReturn(true); + //when + client.execute(chartPath.toString(), "".getBytes(), helmValidatorConfig); + //then + verify(httpRequestHandler).post(any(), any(), httpEntityCaptor.capture(), any()); + + Object[] testArgs = {chartPath, "", false, true, "3.5.6"}; + String expectedHttpEntityContent = new MessageFormat(HTTP_ENTITY_PATTERN).format(testArgs); + String actualHttpEntityContent = getHttpEntityContent(); + + assertEquals(expectedHttpEntityContent, actualHttpEntityContent); + } + + private Path getTestPath(String testChartFileName, String testChartContent) throws IOException { + Path chartPath = tempDir.resolve(testChartFileName); + Files.writeString(chartPath, testChartContent); + return chartPath; + } + + private String getHttpEntityContent() throws IOException { + final var httpEntityCaptorValue = httpEntityCaptor.getValue(); + try (InputStream content = httpEntityCaptorValue.getContent()) { + BufferedReader reader = new BufferedReader(new InputStreamReader(content, HTTP.DEF_CONTENT_CHARSET)); + return reader.lines() + .filter( + line -> line.startsWith("Content-Disposition:") || (!line.contains(":") && !line.contains("--"))) + .collect(Collectors.joining(" ")); + } + } +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtilTest.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtilTest.java index df6fa0676f..c4d718ab12 100644 --- a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtilTest.java +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtilTest.java @@ -20,14 +20,14 @@ package org.openecomp.sdc.validation.impl.validators; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Set; import org.junit.jupiter.api.Test; import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type; import org.openecomp.sdc.validation.util.ValidationTestUtil; -import java.util.Set; - -import static org.junit.jupiter.api.Assertions.assertEquals; - class GlobalContextUtilTest { private static final String TEST_MANIFEST_PATH = "/org/openecomp/validation/validators/global_context_util/"; @@ -37,7 +37,7 @@ class GlobalContextUtilTest { GlobalValidationContext globalContext = new ValidationTestUtil().createGlobalContextFromPath(TEST_MANIFEST_PATH); // when - Set<String> pmDictionaryFiles = GlobalContextUtil.findPmDictionaryFiles(globalContext); + Set<String> pmDictionaryFiles = GlobalContextUtil.findFilesByType(globalContext, Type.PM_DICTIONARY); // then assertEquals(1, pmDictionaryFiles.size()); diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidatorTest.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidatorTest.java new file mode 100644 index 0000000000..f639acafab --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidatorTest.java @@ -0,0 +1,141 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nokia + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.openecomp.sdc.validation.impl.validators; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openecomp.sdc.common.http.client.api.HttpResponse; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.validation.impl.util.HelmValidatorHttpClient; +import org.openecomp.sdc.validation.type.helmvalidator.HelmValidatorConfig; +import org.openecomp.sdc.validation.util.ValidationTestUtil; + +@ExtendWith(MockitoExtension.class) +class HelmValidatorTest { + + private static final String RESOURCE_PATH = "/org/openecomp/validation/validators/helm_validator"; + private static final String VALIDATOR_RESPONSE_WITH_ERRORS = "{\"renderErrors\":[\"[ERROR] render error\"],\"" + + "lintWarning\":[\"[WARNING] warning\"]," + + "\"lintError\":[\"[ERROR] lint error\"]," + + "\"versionUsed\":\"3.5.2\",\"valid\":false,\"deployable\":true}"; + private static final String VALIDATOR_RESPONSE_WITHOUT_LINTING = "{\"renderErrors\":[\"[ERROR] render error 1\"]," + + "\"versionUsed\":\"3.5.2\",\"valid\":false,\"deployable\":true}"; + private static final String VALIDATOR_ERROR_RESPONSE = "{\"message\":\"Error response message\"}"; + private static final String TEST_RESOURCES = "./src/test/resources/"; + + @InjectMocks + private HelmValidator validator; + @Mock + private HelmValidatorHttpClient helmValidatorHttpClient; + @Mock + private HelmValidatorConfig helmValidatorConfig; + + @Test + void shouldCallHelmValidatorForEveryChartWhenIsEnabled() throws Exception { + when(helmValidatorConfig.isEnabled()).thenReturn(true); + String chartPath = RESOURCE_PATH + "/valid_two_charts"; + + var messages = new ValidationTestUtil().testValidator(validator, chartPath); + + byte[] firstChartContent = Files.readAllBytes(Path.of(TEST_RESOURCES + chartPath + "/chart1.tgz")); + byte[] secondChartContent = Files.readAllBytes(Path.of(TEST_RESOURCES + chartPath + "/chart2.tgz")); + verify(helmValidatorHttpClient).execute("chart1.tgz", firstChartContent, helmValidatorConfig); + verify(helmValidatorHttpClient).execute("chart2.tgz", secondChartContent, helmValidatorConfig); + verify(helmValidatorHttpClient, times(2)).execute(any(), any(), any()); + assertEquals(2, messages.size()); + } + + @Test + void shouldNotCallHelmValidatorClientWhenIsDisabled() throws Exception { + when(helmValidatorConfig.isEnabled()).thenReturn(false); + String chartPath = RESOURCE_PATH + "/valid_two_charts"; + + var messages = new ValidationTestUtil().testValidator(validator, chartPath); + + verify(helmValidatorHttpClient, times(0)).execute(any(), any(), any()); + assertEquals(0, messages.size()); + } + + @Test + void shouldContainsMessagesForEveryChartWhenIsEnabled() throws Exception { + when(helmValidatorConfig.isEnabled()).thenReturn(true); + String chartPath = RESOURCE_PATH + "/valid_two_charts"; + when(helmValidatorHttpClient.execute(eq("chart1.tgz"), any(), any())) + .thenReturn(new HttpResponse<>(VALIDATOR_RESPONSE_WITH_ERRORS, 200)); + when(helmValidatorHttpClient.execute(eq("chart2.tgz"), any(), any())) + .thenReturn(new HttpResponse<>(VALIDATOR_RESPONSE_WITHOUT_LINTING, 200)); + + var messages = new ValidationTestUtil().testValidator(validator, chartPath); + + assertEquals(2, messages.size()); + var firstChartErrors = messages.get("chart1.tgz").getErrorMessageList(); + var secondChartErrors = messages.get("chart2.tgz").getErrorMessageList(); + assertEquals(3, firstChartErrors.size()); + assertEquals(1, secondChartErrors.size()); + assertEquals("ERROR: [HELM VALIDATOR]: [ERROR] render error", firstChartErrors.get(0).getMessage()); + assertEquals("WARNING: [HELM VALIDATOR]: [ERROR] lint error", firstChartErrors.get(1).getMessage()); + assertEquals("WARNING: [HELM VALIDATOR]: [WARNING] warning", firstChartErrors.get(2).getMessage()); + assertEquals("ERROR: [HELM VALIDATOR]: [ERROR] render error 1", secondChartErrors.get(0).getMessage()); + } + + @Test + void shouldCorectlySetErrorsAndWarningsFromHelmValidator() throws Exception { + String validChartPath = RESOURCE_PATH + "/valid_chart"; + when(helmValidatorConfig.isEnabled()).thenReturn(true); + when(helmValidatorHttpClient.execute(any(), any(), any())) + .thenReturn(new HttpResponse<>(VALIDATOR_RESPONSE_WITH_ERRORS, 200)); + + var messages = new ValidationTestUtil().testValidator(validator, validChartPath); + + var chartErrors = messages.get("chart.tgz").getErrorMessageList(); + assertEquals(1, messages.size()); + assertEquals(3, chartErrors.size()); + assertEquals("ERROR: [HELM VALIDATOR]: [ERROR] render error", chartErrors.get(0).getMessage()); + assertEquals("WARNING: [HELM VALIDATOR]: [ERROR] lint error", chartErrors.get(1).getMessage()); + assertEquals("WARNING: [HELM VALIDATOR]: [WARNING] warning", chartErrors.get(2).getMessage()); + } + + @Test + void shouldAddWarningWhenErrorResponseFromValidator() throws Exception { + String chartPath = RESOURCE_PATH + "/valid_chart"; + when(helmValidatorConfig.isEnabled()).thenReturn(true); + when(helmValidatorHttpClient.execute(any(), any(), any())) + .thenReturn(new HttpResponse<>(VALIDATOR_ERROR_RESPONSE, 400)); + + var messages = new ValidationTestUtil().testValidator(validator, chartPath); + + var chartErrors = messages.get("chart.tgz").getErrorMessageList(); + assertEquals(1, chartErrors.size()); + assertEquals(ErrorLevel.WARNING, chartErrors.get(0).getLevel()); + assertEquals("WARNING: [HELM VALIDATOR]: Error response message", chartErrors.get(0).getMessage()); + } + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_chart/MANIFEST.json b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_chart/MANIFEST.json new file mode 100644 index 0000000000..5f36629d16 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_chart/MANIFEST.json @@ -0,0 +1,11 @@ +{ + "name": "Valid package", + "description": "", + "data": [ + { + "file": "chart.tgz", + "type": "HELM", + "isBase": "true" + } + ] +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_chart/chart.tgz b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_chart/chart.tgz Binary files differnew file mode 100644 index 0000000000..166b74f548 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_chart/chart.tgz diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/MANIFEST.json b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/MANIFEST.json new file mode 100644 index 0000000000..c478bdd60f --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/MANIFEST.json @@ -0,0 +1,16 @@ +{ + "name": "Valid package", + "description": "", + "data": [ + { + "file": "chart1.tgz", + "type": "HELM", + "isBase": "true" + }, + { + "file": "chart2.tgz", + "type": "HELM", + "isBase": "false" + } + ] +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/chart1.tgz b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/chart1.tgz Binary files differnew file mode 100644 index 0000000000..a33fa2da4e --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/chart1.tgz diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/chart2.tgz b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/chart2.tgz Binary files differnew file mode 100644 index 0000000000..8b92cee8ab --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_two_charts/chart2.tgz diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js index 02e5a24f3b..38600a60b8 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js @@ -242,6 +242,17 @@ function parseUploadErrorMsg(error) { return message.replace(/\n$/, ''); } +function showWarningValidationInfo(dispatch, errors) { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + title: 'Validation messages', + msg: parseUploadErrorMsg(errors), + cancelButtonText: 'OK' + } + }); +} + function fetchSoftwareProductCategories(dispatch) { let handleResponse = response => dispatch({ @@ -447,6 +458,12 @@ const SoftwareProductActionHelper = { break; } closeTimingValidationInfo(dispatch); + if ( + response.errors !== null && + Object.keys(response.errors).length !== 0 + ) { + showWarningValidationInfo(dispatch, response.errors); + } } else { throw new Error(parseUploadErrorMsg(response.errors)); } @@ -460,7 +477,8 @@ const SoftwareProductActionHelper = { msg: error.message || (error.responseJSON && - error.responseJSON.message) + error.responseJSON.message) || + parseUploadErrorMsg(error.responseJSON.errors) } }, closeTimingValidationInfo(dispatch) diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js index a34dfe7b04..2ab60aca1f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js @@ -1,5 +1,6 @@ /*! * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2021 Nokia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -129,8 +130,13 @@ function createErrorList(node, parent, deep = 0, errorList = []) { } const mapValidationDataToTree = (validationData, packageName) => { - let { errors, heat, nested, volume, network, artifacts, other } = + let { errors, heat, helm, nested, volume, network, artifacts, other } = validationData.importStructure || {}; + let heatChildren = + heat && heat.length + ? heat.map(mapHeatData) + : nested ? nested.map(mapHeatData) : []; + let helmChildren = helm && helm.length ? helm.map(mapHeatData) : []; return { children: [ { @@ -139,10 +145,7 @@ const mapValidationDataToTree = (validationData, packageName) => { type: 'heat', header: true, errors: errors, - children: - heat && heat.length - ? heat.map(mapHeatData) - : nested ? nested.map(mapHeatData) : [] + children: heatChildren.concat(helmChildren) }, ...(artifacts ? [ |