Integrate helm validator with SDC-BE 62/120762/26
authorJoanna Jeremicz <joanna.jeremicz@nokia.com>
Wed, 21 Apr 2021 11:59:12 +0000 (13:59 +0200)
committerMichael Morris <michael.morris@est.tech>
Fri, 14 May 2021 14:58:14 +0000 (14:58 +0000)
- 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:
integration-tests/environments/integration-test.json
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
openecomp-be/backend/openecomp-sdc-validation-manager/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java [new file with mode: 0644]
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessor.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidator.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/OnboardingPackageProcessorUnitTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/CsarSecurityValidatorTest.java
openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb
openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/helmvalidator-configuration.yaml.erb [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-core/src/main/resources/config-validaton.json
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/pom.xml
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReader.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClient.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtil.java
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HelmValidator.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/PmDictionaryValidator.java
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorConfig.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorErrorResponse.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/type/helmvalidator/HelmValidatorResponse.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorConfigReaderTest.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/util/HelmValidatorHttpClientTest.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/GlobalContextUtilTest.java
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/java/org/openecomp/sdc/validation/impl/validators/HelmValidatorTest.java [new file with mode: 0644]
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 with mode: 0644]
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/test/resources/org/openecomp/validation/validators/helm_validator/valid_chart/chart.tgz [new file with mode: 0644]
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 with mode: 0644]
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 [new file with mode: 0644]
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 [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js

index 1f804b8..e71e53b 100644 (file)
       "VnfRepo": {
          "vnfRepoPort": "8702",
          "vnfRepoHost": "10.0.14.1"
+      },
+      "HelmValidator": {
+         "validator_enabled": false,
+         "helm_version": "v3",
+         "deployable": true,
+         "lintable": false,
+         "strict_lintable": false
       }
    },
    "override_attributes": {
index 48ad75d..cd18cf9 100644 (file)
@@ -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 (file)
index 0000000..2246ca5
--- /dev/null
@@ -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) {
+    }
+}
index 640a157..0446103 100644 (file)
@@ -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() {
index 50f1fd8..6c886f8 100644 (file)
@@ -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;
     }
+
 }
index d632786..6c847a7 100644 (file)
@@ -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()));
index a97a0f6..795da77 100644 (file)
@@ -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() {
index 0fce606..27d8041 100644 (file)
@@ -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");
index e704842..1749568 100644 (file)
@@ -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 (file)
index 0000000..37021c7
--- /dev/null
@@ -0,0 +1,6 @@
+hValidatorEnabled: <%= @HVALIDATOR_ENABLED %>
+hValidatorUrl: <%= @HVALIDATOR_URL %>
+hValidatorVersion: <%= @HVALIDATOR_HELM_VERSION %>
+hValidatorDeployable: <%= @HVALIDATOR_DEPLOYABLE %>
+hValidatorLintable: <%= @HVALIDATOR_LINTABLE %>
+hValidatorStrictLintable: <%= @HVALIDATOR_STRICT_LINTABLE %>
index 75fd84c..46e3f84 100644 (file)
       "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",
   "_config":{
     "namespace": "validation"
   }
-}
\ No newline at end of file
+}
index a34e4da..d88e3f7 100644 (file)
@@ -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.
       <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 (file)
index 0000000..4d4fff7
--- /dev/null
@@ -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 (file)
index 0000000..299d996
--- /dev/null
@@ -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);
+    }
+
+}
index 0e199cc..b490f4b 100644 (file)
@@ -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);
-    }
 }
index 19b8892..fbfd9c7 100644 (file)
@@ -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 (file)
index 0000000..272d0a8
--- /dev/null
@@ -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));
+    }
+
+}
index 4dad4af..22b5efc 100644 (file)
@@ -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);
     }
 
index cb9469a..eb43925 100644 (file)
@@ -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 (file)
index 0000000..45d0377
--- /dev/null
@@ -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 (file)
index 0000000..c92b528
--- /dev/null
@@ -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 (file)
index 0000000..40deeb5
--- /dev/null
@@ -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 (file)
index 0000000..ba4728f
--- /dev/null
@@ -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 (file)
index 0000000..be1c1a8
--- /dev/null
@@ -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(" "));
+        }
+    }
+}
index df6fa06..c4d718a 100644 (file)
 
 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 (file)
index 0000000..f639aca
--- /dev/null
@@ -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 (file)
index 0000000..5f36629
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..166b74f
Binary files /dev/null and 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 differ
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 (file)
index 0000000..c478bdd
--- /dev/null
@@ -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
new file mode 100644 (file)
index 0000000..a33fa2d
Binary files /dev/null and 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 differ
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
new file mode 100644 (file)
index 0000000..8b92cee
Binary files /dev/null and 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 differ
index 02e5a24..38600a6 100644 (file)
@@ -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)
index a34dfe7..2ab60ac 100644 (file)
@@ -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
                 ? [