Add validation of manifest for helm packages. 23/117623/15
authorJan Malkiewicz <jan.malkiewicz@nokia.com>
Tue, 9 Feb 2021 07:39:23 +0000 (08:39 +0100)
committerChristophe Closset <christophe.closset@intl.att.com>
Sat, 20 Feb 2021 07:07:31 +0000 (07:07 +0000)
For ONAP native zip packages added validation of manifest file.
HELM package is only valid if:
 * isBase flag is set to 'true' for exactly one helm entry
 * isBase flag is present for all helm entries
Zip package is considered to be a helm package if it contains HELM entries but does not contain any HEAT entries (however it may contains entries of other types).

Refactored method OnboardingPackageProcessor.processPackage():
 * simplified logic
 * enhanced exception handling

Issue-ID: SDC-3185
Signed-off-by: Jan Malkiewicz <jan.malkiewicz@nokia.com>
Change-Id: Ica3b1f1504ce4fc3a671c4b8fa8de2bf0236bd77

13 files changed:
integration-tests/src/test/resources/Files/VNFs/vLB.zip
integration-tests/src/test/resources/Files/VNFs/vLBMS.zip [deleted file]
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-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/ManifestAnalyzer.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 [new file with mode: 0644]
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/ManifestAnalyzerTest.java [new file with mode: 0644]
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 [new file with mode: 0644]
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidatorTest.java [new file with mode: 0644]
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-invalid-missing-flag-isbase.zip [new file with mode: 0644]
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-valid.zip [new file with mode: 0644]
openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/Messages.java

index b61ca1b..c542870 100644 (file)
Binary files a/integration-tests/src/test/resources/Files/VNFs/vLB.zip and b/integration-tests/src/test/resources/Files/VNFs/vLB.zip differ
diff --git a/integration-tests/src/test/resources/Files/VNFs/vLBMS.zip b/integration-tests/src/test/resources/Files/VNFs/vLBMS.zip
deleted file mode 100644 (file)
index c542870..0000000
Binary files a/integration-tests/src/test/resources/Files/VNFs/vLBMS.zip and /dev/null differ
index c331deb..073400f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2016-2018 European Support Limited
+ * Copyright © 2021 Nokia
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -104,7 +105,7 @@ public class OrchestrationTemplateCandidateImpl implements OrchestrationTemplate
     final OnboardingPackageProcessor onboardingPackageProcessor = new OnboardingPackageProcessor(filename, fileToUploadBytes);
     if (onboardingPackageProcessor.hasErrors()) {
       final UploadFileResponseDto uploadFileResponseDto =
-          buildUploadResponseWithError(onboardingPackageProcessor.getErrorMessageSet().toArray(new ErrorMessage[0]));
+          buildUploadResponseWithError(onboardingPackageProcessor.getErrorMessages().toArray(new ErrorMessage[0]));
       return Response.ok(uploadFileResponseDto).build();
     }
 
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/ManifestAnalyzer.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/ManifestAnalyzer.java
new file mode 100644 (file)
index 0000000..ecb3ac6
--- /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.vendorsoftwareproduct.impl.onboarding;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+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;
+
+public class ManifestAnalyzer {
+
+    private final ManifestContent manifest;
+
+    private final static Set<Type> HEAT_TYPES = Collections.singleton(Type.HEAT);
+
+    private final static Set<Type> HELM_TYPES = Collections.singleton(Type.HELM);
+
+    public ManifestAnalyzer(ManifestContent manifest) {
+        this.manifest = manifest;
+    }
+
+    public boolean hasHeatEntries() {
+        return hasEntriesOfType(HEAT_TYPES);
+    }
+
+    public boolean hasHelmEntries() {
+        return hasEntriesOfType(HELM_TYPES);
+    }
+
+    public List<FileData> getHelmEntries() {
+        List<FileData> entries = new ArrayList<>();
+        if (hasFileData()) {
+            for (FileData d : manifest.getData()) {
+                if (HELM_TYPES.contains(d.getType())) {
+                    entries.add(d);
+                }
+            }
+        }
+        return entries;
+    }
+
+    private boolean hasEntriesOfType(Set<Type> types) {
+        boolean result = false;
+        if (hasFileData()) {
+            result = manifest.getData().stream().anyMatch(fileData -> types.contains(fileData.getType()));
+        }
+        return result;
+    }
+
+    private boolean hasFileData() {
+        return manifest != null && manifest.getData() != null && !manifest.getData().isEmpty();
+    }
+}
index a40f2eb..e863f34 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019 Nordix Foundation
+ *  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.
@@ -19,6 +20,7 @@
 
 package org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding;
 
+import static org.openecomp.sdc.common.errors.Messages.COULD_NOT_READ_MANIFEST_FILE;
 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_EMPTY_ERROR;
 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_INVALID_ERROR;
 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_INVALID_EXTENSION;
@@ -35,6 +37,7 @@ import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -47,89 +50,157 @@ import org.apache.commons.io.FilenameUtils;
 import org.openecomp.core.utilities.file.FileContentHandler;
 import org.openecomp.core.utilities.json.JsonUtil;
 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
+import org.openecomp.sdc.common.utils.CommonUtil;
 import org.openecomp.sdc.common.utils.SdcCommon;
 import org.openecomp.sdc.common.zip.exception.ZipException;
-import org.openecomp.sdc.common.utils.CommonUtil;
 import org.openecomp.sdc.datatypes.error.ErrorLevel;
 import org.openecomp.sdc.datatypes.error.ErrorMessage;
 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
+import org.openecomp.sdc.vendorsoftwareproduct.impl.onboarding.validation.CnfPackageValidator;
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackage;
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardSignedPackage;
 
 public class OnboardingPackageProcessor {
+
     private static final Logger LOGGER = LoggerFactory.getLogger(OnboardingPackageProcessor.class);
     private static final String CSAR_EXTENSION = "csar";
     private static final String ZIP_EXTENSION = "zip";
-    private static  boolean helmBase = false;
 
     private final String packageFileName;
     private final byte[] packageFileContent;
-    private FileContentHandler onboardPackageContentHandler;
-    private Set<ErrorMessage> errorMessageSet = new HashSet<>();
-    private OnboardPackageInfo onboardPackageInfo;
+    private FileContentHandler packageContent;
+    private final Set<ErrorMessage> errorMessages = new HashSet<>();
+    private final OnboardPackageInfo onboardPackageInfo;
+    private final CnfPackageValidator cnfPackageValidator;
 
     public OnboardingPackageProcessor(final String packageFileName, final byte[] packageFileContent) {
         this.packageFileName = packageFileName;
         this.packageFileContent = packageFileContent;
+        this.cnfPackageValidator = new CnfPackageValidator();
         onboardPackageInfo = processPackage();
     }
 
+    public Optional<OnboardPackageInfo> getOnboardPackageInfo() {
+        return Optional.ofNullable(onboardPackageInfo);
+    }
+
+    public boolean hasErrors() {
+        return !errorMessages.isEmpty();
+    }
+
+    public boolean hasNoErrors() {
+        return errorMessages.isEmpty();
+    }
+
+    public Set<ErrorMessage> getErrorMessages() {
+        return errorMessages;
+    }
+
     private OnboardPackageInfo processPackage() {
-        if (!hasValidExtension()) {
-            final String message = PACKAGE_INVALID_EXTENSION.formatMessage(packageFileName, String.join(", ", CSAR_EXTENSION, ZIP_EXTENSION));
-            reportError(ErrorLevel.ERROR, message);
-            return null;
-        }
-        try {
-            onboardPackageContentHandler = CommonUtil.getZipContent(packageFileContent);
-        } catch (final ZipException e) {
-            final String message = PACKAGE_PROCESS_ERROR.formatMessage(packageFileName);
-            LOGGER.error(message, e);
-            reportError(ErrorLevel.ERROR, message);
-            return null;
+        OnboardPackageInfo packageInfo = null;
+        validateFile();
+        if (hasNoErrors()) {
+            final String packageName = FilenameUtils.getBaseName(packageFileName);
+            final String packageExtension = FilenameUtils.getExtension(packageFileName);
+
+            if (hasSignedPackageStructure()) {
+                packageInfo = processSignedPackage(packageName, packageExtension);
+            } else {
+                if (packageExtension.equalsIgnoreCase(CSAR_EXTENSION)) {
+                    packageInfo = processCsarPackage(packageName, packageExtension);
+                } else if (packageExtension.equalsIgnoreCase(ZIP_EXTENSION)) {
+                    packageInfo = processOnapNativeZipPackage(packageName, packageExtension);
+                }
+            }
         }
-        if (isPackageEmpty()) {
-            final String message = PACKAGE_EMPTY_ERROR.formatMessage(packageFileName);
+        return packageInfo;
+    }
+
+    private void validateFile() {
+        if (!hasValidExtension()) {
+            String message = PACKAGE_INVALID_EXTENSION
+                .formatMessage(packageFileName, String.join(", ", CSAR_EXTENSION, ZIP_EXTENSION));
             reportError(ErrorLevel.ERROR, message);
-            return null;
+        } else {
+            try {
+                packageContent = CommonUtil.getZipContent(packageFileContent);
+                if (isPackageEmpty()) {
+                    String message = PACKAGE_EMPTY_ERROR.formatMessage(packageFileName);
+                    reportError(ErrorLevel.ERROR, message);
+                }
+            } catch (final ZipException e) {
+                String message = PACKAGE_PROCESS_ERROR.formatMessage(packageFileName);
+                reportError(ErrorLevel.ERROR, message);
+                LOGGER.error(message, e);
+            }
         }
+    }
 
-        final String packageName = FilenameUtils.getBaseName(packageFileName);
-        final String packageExtension = FilenameUtils.getExtension(packageFileName);
+    private OnboardPackageInfo processCsarPackage(String packageName, String packageExtension) {
+        OnboardPackage onboardPackage = new OnboardPackage(packageName, packageExtension,
+            ByteBuffer.wrap(packageFileContent), new OnboardingPackageContentHandler(packageContent));
+        return new OnboardPackageInfo(onboardPackage, OnboardingTypesEnum.CSAR);
+    }
 
-        if (hasSignedPackageStructure()) {
-            return processSignedPackage(packageName, packageExtension);
-        } else {
-            if (packageExtension.equalsIgnoreCase(CSAR_EXTENSION)) {
+    private OnboardPackageInfo processOnapNativeZipPackage(String packageName, String packageExtension) {
+        ManifestContent manifest = getManifest();
+        if (manifest != null) {
+            List<String> errors = validateZipPackage(manifest);
+            if (errors.isEmpty()) {
                 final OnboardPackage onboardPackage = new OnboardPackage(packageName, packageExtension,
-                    ByteBuffer.wrap(packageFileContent), new OnboardingPackageContentHandler(onboardPackageContentHandler));
-                return new OnboardPackageInfo(onboardPackage, OnboardingTypesEnum.CSAR);
-            } else if (packageExtension.equalsIgnoreCase(ZIP_EXTENSION)) {
-                addDummyHeat();
-                final OnboardPackage onboardPackage = new OnboardPackage(packageName, packageExtension,
-                    ByteBuffer.wrap(packageFileContent), onboardPackageContentHandler);
+                    ByteBuffer.wrap(packageFileContent), packageContent);
                 return new OnboardPackageInfo(onboardPackage, OnboardingTypesEnum.ZIP);
+            } else {
+                errors.forEach(message -> reportError(ErrorLevel.ERROR, message));
+            }
+        } else {
+            reportError(ErrorLevel.ERROR,
+                COULD_NOT_READ_MANIFEST_FILE.formatMessage(SdcCommon.MANIFEST_NAME, packageFileName));
+        }
+        return null;
+    }
+
+    List<String> validateZipPackage(ManifestContent manifest) {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest);
+        List<String> errors = Collections.emptyList();
+        if (analyzer.hasHelmEntries()) {
+            if (shouldValidateHelmPackage(analyzer)) {
+                errors = cnfPackageValidator.validateHelmPackage(analyzer.getHelmEntries());
             }
         }
+        addDummyHeat(manifest);
+        return errors;
+    }
 
-        reportError(ErrorLevel.ERROR, PACKAGE_INVALID_ERROR.formatMessage(packageFileName));
-        return null;
+    boolean shouldValidateHelmPackage(ManifestAnalyzer analyzer) {
+        return analyzer.hasHelmEntries() && !analyzer.hasHeatEntries();
     }
 
-    private void addDummyHeat() {
+    private ManifestContent getManifest() {
+        ManifestContent manifest = null;
+        try (InputStream zipFileManifest = packageContent.getFileContentAsStream(SdcCommon.MANIFEST_NAME)) {
+            manifest = JsonUtil.json2Object(zipFileManifest, ManifestContent.class);
+
+        } catch (Exception e) {
+            final String message = COULD_NOT_READ_MANIFEST_FILE.formatMessage(SdcCommon.MANIFEST_NAME, packageFileName);
+            LOGGER.error(message, e);
+        }
+        return manifest;
+    }
+
+    private void addDummyHeat(ManifestContent manifestContent) {
         // temporary fix for adding dummy base
         List<FileData> newfiledata = new ArrayList<>();
-        try (InputStream zipFileManifest = onboardPackageContentHandler.getFileContentAsStream(SdcCommon.MANIFEST_NAME)) {
-            ManifestContent manifestContent =
-                    JsonUtil.json2Object(zipFileManifest, ManifestContent.class);
+        try {
+            boolean heatBase = false;
             for (FileData fileData : manifestContent.getData()) {
                 if (Objects.nonNull(fileData.getType()) &&
-                        fileData.getType().equals(FileData.Type.HELM) && fileData.getBase()) {
-                    helmBase = true;
+                    fileData.getType().equals(FileData.Type.HELM) && fileData.getBase()) {
+                    heatBase = true;
                     fileData.setBase(false);
                     FileData dummyHeat = new FileData();
                     dummyHeat.setBase(true);
@@ -146,27 +217,28 @@ public class OnboardingPackageProcessor {
                     String filePath = new File("").getAbsolutePath() + "/resources";
                     File envFilePath = new File(filePath + "/base_template.env");
                     File baseFilePath = new File(filePath + "/base_template.yaml");
-                    try (
-                            InputStream envStream = new FileInputStream(envFilePath);
-                            InputStream baseStream = new FileInputStream(baseFilePath);) {
-                        onboardPackageContentHandler.addFile("base_template_dummy_ignore.env", envStream);
-                        onboardPackageContentHandler.addFile("base_template_dummy_ignore.yaml", baseStream);
+                    try (InputStream envStream = new FileInputStream(envFilePath);
+                        InputStream baseStream = new FileInputStream(baseFilePath)) {
+                        packageContent.addFile("base_template_dummy_ignore.env", envStream);
+                        packageContent.addFile("base_template_dummy_ignore.yaml", baseStream);
                     } catch (Exception e) {
                         LOGGER.error("Failed creating input stream {}", e);
                     }
                 }
             }
-            if (helmBase) {
+            if (heatBase) {
                 manifestContent.getData().addAll(newfiledata);
-                InputStream manifestContentStream = new ByteArrayInputStream((JsonUtil.object2Json(manifestContent)).getBytes(StandardCharsets.UTF_8));
-                onboardPackageContentHandler.remove(SdcCommon.MANIFEST_NAME);
-                onboardPackageContentHandler.addFile(SdcCommon.MANIFEST_NAME, manifestContentStream);
+                InputStream manifestContentStream = new ByteArrayInputStream(
+                    (JsonUtil.object2Json(manifestContent)).getBytes(StandardCharsets.UTF_8));
+                packageContent.remove(SdcCommon.MANIFEST_NAME);
+                packageContent.addFile(SdcCommon.MANIFEST_NAME, manifestContentStream);
             }
         } catch (Exception e) {
             final String message = PACKAGE_INVALID_ERROR.formatMessage(packageFileName);
             LOGGER.error(message, e);
         }
     }
+
     private boolean hasValidExtension() {
         final String packageExtension = FilenameUtils.getExtension(packageFileName);
         return packageExtension.equalsIgnoreCase(CSAR_EXTENSION) || packageExtension.equalsIgnoreCase(ZIP_EXTENSION);
@@ -182,12 +254,12 @@ public class OnboardingPackageProcessor {
         final String certificateFilePath = findCertificateFilePath().orElse(null);
         final OnboardSignedPackage onboardSignedPackage =
             new OnboardSignedPackage(packageName, packageExtension, ByteBuffer.wrap(packageFileContent),
-                onboardPackageContentHandler, signatureFilePath, internalPackagePath, certificateFilePath);
+                packageContent, signatureFilePath, internalPackagePath, certificateFilePath);
 
         final String internalPackageName = FilenameUtils.getName(internalPackagePath);
         final String internalPackageBaseName = FilenameUtils.getBaseName(internalPackagePath);
         final String internalPackageExtension = FilenameUtils.getExtension(internalPackagePath);
-        final byte[] internalPackageContent = onboardPackageContentHandler.getFileContent(internalPackagePath);
+        final byte[] internalPackageContent = packageContent.getFileContent(internalPackagePath);
         final OnboardPackage onboardPackage;
         try {
             final OnboardingPackageContentHandler fileContentHandler =
@@ -205,19 +277,11 @@ public class OnboardingPackageProcessor {
     }
 
     private void reportError(final ErrorLevel errorLevel, final String message) {
-        errorMessageSet.add(new ErrorMessage(errorLevel, message));
-    }
-
-    public boolean hasErrors() {
-        return !errorMessageSet.isEmpty();
-    }
-
-    public Set<ErrorMessage> getErrorMessageSet() {
-        return errorMessageSet;
+        errorMessages.add(new ErrorMessage(errorLevel, message));
     }
 
     private Optional<String> findInternalPackagePath() {
-        return onboardPackageContentHandler.getFileList().stream()
+        return packageContent.getFileList().stream()
             .filter(filePath -> {
                     final String extension = FilenameUtils.getExtension(filePath);
                     return CSAR_EXTENSION.equalsIgnoreCase(extension) || ZIP_EXTENSION.equalsIgnoreCase(extension);
@@ -227,24 +291,24 @@ public class OnboardingPackageProcessor {
     }
 
     private boolean isPackageEmpty() {
-        return MapUtils.isEmpty(onboardPackageContentHandler.getFiles());
+        return MapUtils.isEmpty(packageContent.getFiles());
     }
 
     private boolean hasSignedPackageStructure() {
-        if (MapUtils.isEmpty(onboardPackageContentHandler.getFiles()) || !CollectionUtils.isEmpty(
-            onboardPackageContentHandler.getFolderList())) {
+        if (MapUtils.isEmpty(packageContent.getFiles()) || !CollectionUtils.isEmpty(
+            packageContent.getFolderList())) {
             return false;
         }
-        final int numberOfFiles = onboardPackageContentHandler.getFileList().size();
+        final int numberOfFiles = packageContent.getFileList().size();
         if (numberOfFiles == 2) {
-            return hasOneInternalPackageFile(onboardPackageContentHandler) &&
-                hasOneSignatureFile(onboardPackageContentHandler);
+            return hasOneInternalPackageFile(packageContent) &&
+                hasOneSignatureFile(packageContent);
         }
 
         if (numberOfFiles == 3) {
-            return hasOneInternalPackageFile(onboardPackageContentHandler) &&
-                hasOneSignatureFile(onboardPackageContentHandler) &&
-                hasOneCertificateFile(onboardPackageContentHandler);
+            return hasOneInternalPackageFile(packageContent) &&
+                hasOneSignatureFile(packageContent) &&
+                hasOneCertificateFile(packageContent);
         }
 
         return false;
@@ -272,20 +336,19 @@ public class OnboardingPackageProcessor {
     }
 
     private Optional<String> findSignatureFilePath() {
-        final Map<String, byte[]> files = onboardPackageContentHandler.getFiles();
+        final Map<String, byte[]> files = packageContent.getFiles();
         return files.keySet().stream()
-            .filter(fileName -> ALLOWED_SIGNATURE_EXTENSIONS.contains(FilenameUtils.getExtension(fileName).toLowerCase()))
+            .filter(
+                fileName -> ALLOWED_SIGNATURE_EXTENSIONS.contains(FilenameUtils.getExtension(fileName).toLowerCase()))
             .findFirst();
     }
 
     private Optional<String> findCertificateFilePath() {
-        final Map<String, byte[]> files = onboardPackageContentHandler.getFiles();
+        final Map<String, byte[]> files = packageContent.getFiles();
         return files.keySet().stream()
-            .filter(fileName -> ALLOWED_CERTIFICATE_EXTENSIONS.contains(FilenameUtils.getExtension(fileName).toLowerCase()))
+            .filter(
+                fileName -> ALLOWED_CERTIFICATE_EXTENSIONS.contains(FilenameUtils.getExtension(fileName).toLowerCase()))
             .findFirst();
     }
 
-    public Optional<OnboardPackageInfo> getOnboardPackageInfo() {
-        return Optional.ofNullable(onboardPackageInfo);
-    }
 }
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
new file mode 100644 (file)
index 0000000..8520672
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * ============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.vendorsoftwareproduct.impl.onboarding.validation;
+
+import static org.openecomp.sdc.common.errors.Messages.MANIFEST_VALIDATION_HELM_IS_BASE_MISSING;
+import static org.openecomp.sdc.common.errors.Messages.MANIFEST_VALIDATION_HELM_IS_BASE_NOT_SET;
+import static org.openecomp.sdc.common.errors.Messages.MANIFEST_VALIDATION_HELM_IS_BASE_NOT_UNIQUE;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.openecomp.sdc.heat.datatypes.manifest.FileData;
+
+public class CnfPackageValidator {
+
+    public List<String> validateHelmPackage(List<FileData> modules) {
+        List<String> messages = Collections.emptyList();
+
+        if (modules != null && !modules.isEmpty()) {
+            Stats stats = calculateStats(modules);
+            messages = createErrorMessages(stats);
+        }
+
+        return messages;
+    }
+
+    private Stats calculateStats(List<FileData> modules) {
+        Stats stats = new Stats();
+        for (FileData mod : modules) {
+            if (mod.getBase() == null) {
+                stats.without++;
+            } else if (mod.getBase()) {
+                stats.base++;
+            }
+        }
+        return stats;
+    }
+
+    private List<String> createErrorMessages(Stats stats) {
+        List<String> messages = new ArrayList<>();
+
+        if (stats.without > 0) {
+            messages.add(MANIFEST_VALIDATION_HELM_IS_BASE_MISSING.formatMessage(stats.without));
+        }
+
+        if (stats.base == 0) {
+            messages.add(MANIFEST_VALIDATION_HELM_IS_BASE_NOT_SET.getErrorMessage());
+        } else if (stats.base > 1) {
+            messages.add(MANIFEST_VALIDATION_HELM_IS_BASE_NOT_UNIQUE.getErrorMessage());
+        }
+
+        return messages;
+    }
+
+    private static class Stats {
+
+        private int base = 0;
+        private int without = 0;
+    }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/ManifestAnalyzerTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/ManifestAnalyzerTest.java
new file mode 100644 (file)
index 0000000..51b34b6
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * ============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.vendorsoftwareproduct.impl.onboarding;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+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;
+
+
+public class ManifestAnalyzerTest {
+
+    @Test
+    public void shouldAnalyzeManifestWithOnlyHelmEntries() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(helmOnly()));
+
+        assertThat(analyzer.hasHelmEntries(), is(true));
+        assertThat(analyzer.hasHeatEntries(), is(false));
+        assertThat(analyzer.getHelmEntries().size(), is(3));
+        assertThatContainsOnlyHelm(analyzer.getHelmEntries());
+    }
+
+    @Test
+    public void shouldAnalyzeManifestWithoutHelmEntries() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(withoutHelm()));
+
+        assertThat(analyzer.hasHelmEntries(), is(false));
+        assertThat(analyzer.hasHeatEntries(), is(true));
+        assertThat(analyzer.getHelmEntries().size(), is(0));
+    }
+
+    @Test
+    public void shouldAnalyzeManifestWitoutyHelmAndHeatEntries() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(withoutHelmAndHeat()));
+
+        assertThat(analyzer.hasHelmEntries(), is(false));
+        assertThat(analyzer.hasHeatEntries(), is(false));
+        assertThat(analyzer.getHelmEntries().size(), is(0));
+    }
+
+    @Test
+    public void shouldAnalyzeManifestWithHelmAndHeatEntries() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(helmAndHeat()));
+
+        assertThat(analyzer.hasHelmEntries(), is(true));
+        assertThat(analyzer.hasHeatEntries(), is(true));
+        assertThat(analyzer.getHelmEntries().size(), is(2));
+        assertThatContainsOnlyHelm(analyzer.getHelmEntries());
+    }
+
+    @Test
+    public void shouldAnalyzeManifestWithMultipleTypeEntries() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(helmAndHeatAndOther()));
+
+        assertThat(analyzer.hasHelmEntries(), is(true));
+        assertThat(analyzer.hasHeatEntries(), is(true));
+        assertThat(analyzer.getHelmEntries().size(), is(2));
+        assertThatContainsOnlyHelm(analyzer.getHelmEntries());
+    }
+
+    private void assertThatContainsOnlyHelm(List<FileData> entries) {
+        entries.forEach(fileData -> assertThat(fileData.getType(), is(Type.HELM)));
+    }
+
+    private ManifestContent manifest(List<FileData> entries) {
+        ManifestContent manifest = new ManifestContent();
+        manifest.setData(entries);
+        return  manifest;
+    }
+
+    private List<FileData> withoutHelm() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.HEAT, true));
+        entries.add(createFileData(Type.CHEF, false));
+        entries.add(createFileData(Type.PM_DICTIONARY, false));
+
+        return entries;
+    }
+
+    private List<FileData> withoutHelmAndHeat() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.PUPPET, true));
+        entries.add(createFileData(Type.CHEF, false));
+        entries.add(createFileData(Type.PM_DICTIONARY, false));
+
+        return entries;
+    }
+
+    private List<FileData> helmOnly() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.HELM, true));
+        entries.add(createFileData(Type.HELM, false));
+        entries.add(createFileData(Type.HELM, false));
+
+        return entries;
+    }
+
+    private List<FileData> helmAndHeat() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.HELM, true));
+        entries.add(createFileData(Type.HELM, false));
+        entries.add(createFileData(Type.HEAT, false));
+
+        return entries;
+    }
+
+    private List<FileData> helmAndHeatAndOther() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.HELM, true));
+        entries.add(createFileData(Type.HELM, false));
+        entries.add(createFileData(Type.HEAT, false));
+        entries.add(createFileData(Type.PUPPET, false));
+        entries.add(createFileData(Type.CHEF, false));
+
+        return entries;
+    }
+
+    private FileData createFileData(Type type, Boolean base) {
+        FileData f = new FileData();
+        f.setType(type);
+        f.setBase(base);
+        return f;
+    }
+
+}
index a62aea7..d632786 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019 Nordix Foundation
+ *  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.
@@ -25,6 +26,9 @@ import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
+import static org.openecomp.sdc.common.errors.Messages.COULD_NOT_READ_MANIFEST_FILE;
+import static org.openecomp.sdc.common.errors.Messages.MANIFEST_VALIDATION_HELM_IS_BASE_MISSING;
+import static org.openecomp.sdc.common.errors.Messages.MANIFEST_VALIDATION_HELM_IS_BASE_NOT_SET;
 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_EMPTY_ERROR;
 import static org.openecomp.sdc.common.errors.Messages.PACKAGE_INVALID_EXTENSION;
 
@@ -49,6 +53,7 @@ import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
 
 @RunWith(Parameterized.class)
 public class OnboardingPackageProcessorTest {
+
     private static final String BASE_DIR = "/vspmanager.csar/";
     private final String packageName;
     private final byte[] packageBytes;
@@ -56,8 +61,8 @@ public class OnboardingPackageProcessorTest {
     private final OnboardingTypesEnum expectedPackageType;
 
     public OnboardingPackageProcessorTest(final String packageName, final byte[] packageBytes,
-                                          final Set<ErrorMessage> expectedErrorSet,
-                                          final OnboardingTypesEnum expectedPackageType) {
+        final Set<ErrorMessage> expectedErrorSet,
+        final OnboardingTypesEnum expectedPackageType) {
         this.packageName = packageName;
         this.packageBytes = packageBytes;
         this.expectedErrorSet = expectedErrorSet;
@@ -87,23 +92,42 @@ public class OnboardingPackageProcessorTest {
             {"successfulUpload.csar", getFileBytes("successfulUpload.csar"), Collections.emptySet(),
                 OnboardingTypesEnum.CSAR},
 
-            {"fakeNonSignedZipPackage.zip", getFileBytes("signing/fakeNonSignedZipPackage.zip"), Collections.emptySet(),
+            {"helm-package-valid.zip", getFileBytes("helm-package-valid.zip"), Collections.emptySet(),
+                OnboardingTypesEnum.ZIP},
+
+            {"helm-package-invalid.zip", getFileBytes("helm-package-invalid-missing-flag-isbase.zip"), ImmutableSet.of(
+                new ErrorMessage(ErrorLevel.ERROR,
+                    MANIFEST_VALIDATION_HELM_IS_BASE_NOT_SET.getErrorMessage()),
+                new ErrorMessage(ErrorLevel.ERROR,
+                    MANIFEST_VALIDATION_HELM_IS_BASE_MISSING.formatMessage(3)
+                )
+            ),
+                OnboardingTypesEnum.ZIP},
+
+            {"fakeNonSignedZipPackage.zip", getFileBytes("signing/fakeNonSignedZipPackage.zip"), ImmutableSet.of(
+                new ErrorMessage(ErrorLevel.ERROR,
+                    COULD_NOT_READ_MANIFEST_FILE.formatMessage("MANIFEST.json", "fakeNonSignedZipPackage.zip")
+                )),
                 OnboardingTypesEnum.ZIP}
         });
     }
 
     @Test
     public void processPackage() {
-        final OnboardingPackageProcessor onboardingPackageProcessor = new OnboardingPackageProcessor(packageName, packageBytes);
+        final OnboardingPackageProcessor onboardingPackageProcessor = new OnboardingPackageProcessor(packageName,
+            packageBytes);
         assertThat("Should contains errors", onboardingPackageProcessor.hasErrors(), is(!expectedErrorSet.isEmpty()));
-        assertThat("Should have the same number of errors", onboardingPackageProcessor.getErrorMessageSet().size(), equalTo(expectedErrorSet.size()));
+        assertThat("Should have the same number of errors", onboardingPackageProcessor.getErrorMessages().size(),
+            equalTo(expectedErrorSet.size()));
         if (expectedErrorSet.size() > 0) {
-            assertThat("Should have the expected errors", onboardingPackageProcessor.getErrorMessageSet(), containsInAnyOrder(expectedErrorSet.toArray()));
+            assertThat("Should have the expected errors", onboardingPackageProcessor.getErrorMessages(),
+                containsInAnyOrder(expectedErrorSet.toArray()));
             return;
         }
         final OnboardPackageInfo onboardPackageInfo = onboardingPackageProcessor.getOnboardPackageInfo().orElse(null);
         assertThat("Should build onboardPackageInfo", onboardPackageInfo, is(notNullValue()));
-        assertThat("Should have the expected package type", onboardPackageInfo.getPackageType(), is(equalTo(expectedPackageType)));
+        assertThat("Should have the expected package type", onboardPackageInfo.getPackageType(),
+            is(equalTo(expectedPackageType)));
     }
 
     private static byte[] getFileBytes(final String filePath) {
@@ -117,4 +141,4 @@ public class OnboardingPackageProcessorTest {
         return null;
     }
 
-}
\ No newline at end of file
+}
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
new file mode 100644 (file)
index 0000000..a97a0f6
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * ============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.vendorsoftwareproduct.impl.onboarding;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+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;
+
+
+public class OnboardingPackageProcessorUnitTest {
+
+    private OnboardingPackageProcessor processor = new OnboardingPackageProcessor("unitTestPackage", null);
+
+    @Test
+    public void shouldValidateZipPackage_helmWithoutHeat() {
+        assertThat(processor.validateZipPackage(manifest(withHelmWithoutHeat())).size(), is(0));
+    }
+
+    @Test
+    public void shouldValidateZipPackage_withHelmAndHeat() {
+        assertThat(processor.validateZipPackage(manifest(withHelmAndHeat())).size(), is(0));
+    }
+
+    @Test
+    public void shouldValidateZipPackage_withHelmWithoutHeat() {
+        assertThat(processor.validateZipPackage(manifest(withoutHelmWithoutHeat())).size(), is(0));
+    }
+
+    @Test
+    public void shouldValidateZipPackage_helmInvalid() {
+        assertThat(processor.validateZipPackage(manifest(withHelmInvalid())).size(), is(1));
+    }
+
+    @Test
+    public void shouldValidateHelmPackage() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(withHelmWithoutHeat()));
+
+       assertThat(processor.shouldValidateHelmPackage(analyzer), is(true));
+    }
+
+    @Test
+    public void shouldNotValidateHelmPackage_emptyInput() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(empty()));
+
+        assertThat(processor.shouldValidateHelmPackage(analyzer), is(false));
+    }
+
+    @Test
+    public void shouldNotValidateHelmPackage_containsHeatModule() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(withHelmAndHeat()));
+
+        assertThat(processor.shouldValidateHelmPackage(analyzer), is(false));
+    }
+
+    @Test
+    public void shouldNotValidateHelmPackage_noHelmModule() {
+        ManifestAnalyzer analyzer = new ManifestAnalyzer(manifest(withoutHelmWithoutHeat()));
+
+        assertThat(processor.shouldValidateHelmPackage(analyzer), is(false));
+    }
+
+    private ManifestContent manifest(List<FileData> entries) {
+        ManifestContent manifest = new ManifestContent();
+        manifest.setData(entries);
+        return  manifest;
+    }
+
+    private List<FileData> empty() {
+        return Collections.emptyList();
+    }
+
+    private List<FileData> withHelmAndHeat() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.HEAT, true));
+        entries.add(createFileData(Type.HELM, false));
+        entries.add(createFileData(Type.PM_DICTIONARY, false));
+
+        return entries;
+    }
+
+    private List<FileData> withHelmWithoutHeat() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.HELM, true));
+        entries.add(createFileData(Type.CHEF, false));
+        entries.add(createFileData(Type.PM_DICTIONARY, false));
+
+        return entries;
+    }
+
+    private List<FileData> withHelmInvalid() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.HELM, false));
+        entries.add(createFileData(Type.CHEF, false));
+        entries.add(createFileData(Type.PM_DICTIONARY, false));
+
+        return entries;
+    }
+
+    private List<FileData> withoutHelmWithoutHeat() {
+        List<FileData> entries = new ArrayList<>();
+
+        entries.add(createFileData(Type.CHEF, false));
+        entries.add(createFileData(Type.PM_DICTIONARY, false));
+
+        return entries;
+    }
+
+
+    private FileData createFileData(Type type, Boolean base) {
+        FileData f = new FileData();
+        f.setType(type);
+        f.setBase(base);
+        return f;
+    }
+
+}
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidatorTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/onboarding/validation/CnfPackageValidatorTest.java
new file mode 100644 (file)
index 0000000..e969c3d
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * ============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.vendorsoftwareproduct.impl.onboarding.validation;
+
+import static org.hamcrest.Matchers.emptyIterable;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.openecomp.sdc.heat.datatypes.manifest.FileData;
+
+public class CnfPackageValidatorTest {
+
+    private CnfPackageValidator validator = new CnfPackageValidator();
+
+    @Test
+    public void shouldBeValidForNullInput() {
+        List<String> messages = validator.validateHelmPackage(null);
+
+        assertThat(messages, is(emptyIterable()));
+    }
+
+    @Test
+    public void shouldBeValidForEmptyInput() {
+        List<String> messages = validator.validateHelmPackage(Collections.emptyList());
+
+        assertThat(messages, is(emptyIterable()));
+    }
+
+    @Test
+    public void shouldBeValid() {
+        List<String> messages = validator.validateHelmPackage(createValidInput());
+
+        assertThat(messages, is(emptyIterable()));
+    }
+
+    @Test
+    public void shouldBeInvalidNoneIsMarkedAsBase() {
+        List<String> messages = validator.validateHelmPackage(noneIsMarkedAsBase());
+
+        assertThat(messages.size(), is(1));
+        assertThat(messages.get(0), is("None of charts is marked as 'isBase'."));
+    }
+
+    @Test
+    public void shouldBeInvalidMultipleAreMarkedAsBase() {
+        List<String> messages = validator.validateHelmPackage(multipleAreMarkedAsBase());
+
+        assertThat(messages.size(), is(1));
+        assertThat(messages.get(0), is("More than one chart is marked as 'isBase'."));
+    }
+
+    @Test
+    public void shouldBeInvalidIsBaseMissing() {
+        List<String> messages = validator.validateHelmPackage(isBaseMissing());
+
+        assertThat(messages.size(), is(1));
+        assertThat(messages.get(0), is("Definition of 'isBase' is missing in 2 charts."));
+    }
+
+    @Test
+    public void shouldBeInvalidDueMultipleReasons() {
+        List<String> messages = validator.validateHelmPackage(invalidMultipleReasons());
+
+        assertThat(messages.size(), is(2));
+        assertThat(messages.get(0), is("Definition of 'isBase' is missing in 1 charts."));
+        assertThat(messages.get(1), is("None of charts is marked as 'isBase'."));
+    }
+
+    private List<FileData> createValidInput() {
+        List<FileData> files = new ArrayList<>();
+        files.add(createFileData(true));
+        files.add(createFileData(false));
+        files.add(createFileData(false));
+        return files;
+    }
+
+    private List<FileData> noneIsMarkedAsBase() {
+        List<FileData> files = new ArrayList<>();
+        files.add(createFileData(false));
+        files.add(createFileData(false));
+        files.add(createFileData(false));
+        return files;
+    }
+
+    private List<FileData> multipleAreMarkedAsBase() {
+        List<FileData> files = new ArrayList<>();
+        files.add(createFileData(true));
+        files.add(createFileData(true));
+        files.add(createFileData(false));
+        return files;
+    }
+
+    private List<FileData> isBaseMissing() {
+        List<FileData> files = new ArrayList<>();
+        files.add(createFileData(true));
+        files.add(createFileData(null));
+        files.add(createFileData(null));
+        files.add(createFileData(false));
+        return files;
+    }
+
+    private List<FileData> invalidMultipleReasons() {
+        List<FileData> files = new ArrayList<>();
+        files.add(createFileData(false));
+        files.add(createFileData(null));
+        files.add(createFileData(false));
+        files.add(createFileData(false));
+        return files;
+    }
+
+    private FileData createFileData(Boolean base) {
+        FileData f = new FileData();
+        f.setBase(base);
+        return f;
+    }
+}
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-invalid-missing-flag-isbase.zip b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-invalid-missing-flag-isbase.zip
new file mode 100644 (file)
index 0000000..15b0f57
Binary files /dev/null and b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-invalid-missing-flag-isbase.zip differ
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-valid.zip b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-valid.zip
new file mode 100644 (file)
index 0000000..397dcee
Binary files /dev/null and b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/resources/vspmanager.csar/helm-package-valid.zip differ
index cf34984..ab088a4 100644 (file)
@@ -33,6 +33,7 @@ public enum Messages {
     PACKAGE_PROCESS_INTERNAL_PACKAGE_ERROR("Could not process internal package '%s'"),
     PACKAGE_INVALID_ERROR("Invalid package content '%s'"),
     PACKAGE_MISSING_INTERNAL_PACKAGE("Missing expected internal package"),
+    COULD_NOT_READ_MANIFEST_FILE("Could not read manifest file: %s [%s]"),
     INVALID_ZIP_FILE("Invalid zip file"),
     INVALID_CSAR_FILE("Invalid csar file"),
     CSAR_FILE_NOT_FOUND("Each CSAR file must contain %s file."),
@@ -71,6 +72,9 @@ public enum Messages {
     MANIFEST_ERROR_WITH_LINE("%s;%nAt line %s: '%s'."),
     MANIFEST_PARSER_INTERNAL("Invalid manifest file"),
     MANIFEST_UNEXPECTED_ERROR("An unexpected error occurred while validating manifest '%s': %s"),
+    MANIFEST_VALIDATION_HELM_IS_BASE_MISSING("Definition of 'isBase' is missing in %d charts."),
+    MANIFEST_VALIDATION_HELM_IS_BASE_NOT_UNIQUE("More than one chart is marked as 'isBase'."),
+    MANIFEST_VALIDATION_HELM_IS_BASE_NOT_SET("None of charts is marked as 'isBase'."),
     METADATA_PARSER_INTERNAL("Invalid Metadata file"),
     METADATA_MISSING_OPTIONAL_FOLDERS("Missing folder %s in package"),
     METADATA_UNSUPPORTED_ENTRY("Following entry not supported in TOSCA.meta %s"),