Add new SOL004 validator 78/117678/3
authordavsad <david.sadlier@est.tech>
Fri, 5 Feb 2021 13:12:57 +0000 (13:12 +0000)
committerChristophe Closset <christophe.closset@intl.att.com>
Sat, 20 Feb 2021 07:12:05 +0000 (07:12 +0000)
New validator for onboarding SOL 004 version 3.3.1

Issue-ID: SDC-2611

Signed-off-by: davsad <david.sadlier@est.tech>
Change-Id: I4f41d2fbd913011f42a8319a6594c973c735d2a0

18 files changed:
common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidator.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004Version3MetaDirectoryValidator.java [new file with mode: 0644]
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/ValidatorFactory.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidatorTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004Version3MetaDirectoryValidatorTest.java [new file with mode: 0644]
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-api/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/etsi/ETSIService.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/pom.xml
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/etsi/ETSIServiceImpl.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/etsi/ETSIServiceImplTest.java
openecomp-be/lib/openecomp-tosca-lib/pom.xml
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/CSARConstants.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/ManifestTokenType.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboarding.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/ToscaMetaEntry.java
openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidToscaVersion3.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/ValidToscaVersion3.mf [new file with mode: 0644]

index f5006dd..14fb755 100644 (file)
@@ -634,7 +634,6 @@ public class Configuration extends BasicConfiguration {
         this.gabConfig = gabConfig;
     }
 
-
     public static class CookieConfig {
         String securityKey = "";
         long maxSessionTimeOut = 600*1000;
index 6107383..5f81910 100644 (file)
@@ -55,8 +55,9 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.stream.Collectors;
-
 import java.util.stream.Stream;
+
+import com.google.common.collect.ImmutableSet;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.openecomp.core.impl.ToscaDefinitionImportHandler;
@@ -257,13 +258,12 @@ class SOL004MetaDirectoryValidator implements Validator {
                 validateCertificate(value);
                 break;
             default:
-                reportError(ErrorLevel.ERROR, Messages.METADATA_UNSUPPORTED_ENTRY.formatMessage(key));
-                LOGGER.warn(Messages.METADATA_UNSUPPORTED_ENTRY.getErrorMessage(), key);
+                handleOtherEntry(entry);
                 break;
         }
     }
 
-    private void validateOtherEntries(final Map.Entry entry) {
+    private void validateOtherEntries(final Map.Entry<String, String> entry) {
         final String manifestFile = toscaMetadata.getMetaEntries().get(ETSI_ENTRY_MANIFEST.getName());
         if (verifyFileExists(contentHandler.getFileList(), manifestFile)) {
             final Manifest onboardingManifest = new SOL004ManifestOnboarding();
@@ -299,7 +299,7 @@ class SOL004MetaDirectoryValidator implements Validator {
                 || CSAR_VERSION_1_0.equals(version));
     }
 
-    private void validateDefinitionFile(final String filePath) {
+    protected void validateDefinitionFile(final String filePath) {
         final Set<String> existingFiles = contentHandler.getFileList();
 
         if (verifyFileExists(existingFiles, filePath)) {
@@ -341,19 +341,15 @@ class SOL004MetaDirectoryValidator implements Validator {
     }
 
     private void verifyManifestMetadata(final Map<String, String> metadata) {
-        if (metadata.size() != MANIFEST_METADATA_LIMIT) {
+        if (!validMetaLimit(metadata)) {
             reportError(ErrorLevel.ERROR,
                     String.format(Messages.MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT.getErrorMessage(),
                             MANIFEST_METADATA_LIMIT));
         }
-        if (isPnfMetadata(metadata)) {
-            handleMetadataEntries(metadata, MANIFEST_PNF_METADATA);
-        } else {
-            handleMetadataEntries(metadata, MANIFEST_VNF_METADATA);
-        }
+        handleMetadataEntries(metadata);
     }
 
-    private boolean isPnfMetadata(final Map<String, String> metadata) {
+    protected boolean isPnfMetadata(final Map<String, String> metadata) {
         final String firstMetadataDefinition = metadata.keySet().iterator().next();
         final String expectedMetadataType =
                 firstMetadataDefinition.contains(TOSCA_TYPE_PNF) ? TOSCA_TYPE_PNF : TOSCA_TYPE_VNF;
@@ -365,12 +361,12 @@ class SOL004MetaDirectoryValidator implements Validator {
         return TOSCA_TYPE_PNF.equals(expectedMetadataType);
     }
 
-    private void handleMetadataEntries(final Map<String, String> metadata, final Set<String> manifestMetadata) {
-        manifestMetadata.stream()
+    private void handleMetadataEntries(final Map<String, String> metadata) {
+        getManifestMetadata(metadata).stream()
                 .filter(requiredEntry -> !metadata.containsKey(requiredEntry))
                 .forEach(requiredEntry ->
                         reportError(ErrorLevel.ERROR,
-                                String.format(Messages.MANIFEST_METADATA_MISSING_ENTRY.getErrorMessage(), requiredEntry)));
+                            String.format(Messages.MANIFEST_METADATA_MISSING_ENTRY.getErrorMessage(), requiredEntry)));
     }
 
     /**
@@ -524,10 +520,23 @@ class SOL004MetaDirectoryValidator implements Validator {
         }
     }
 
-    private void reportError(final ErrorLevel errorLevel, final String errorMessage) {
+    protected void reportError(final ErrorLevel errorLevel, final String errorMessage) {
         errorsByFile.add(new ErrorMessage(errorLevel, errorMessage));
     }
 
+    protected boolean validMetaLimit(Map<String, String> metadata) {
+        return metadata.size() == MANIFEST_METADATA_LIMIT;
+    }
+
+    protected ImmutableSet<String> getManifestMetadata(final Map<String, String> metadata) {
+        return isPnfMetadata(metadata) ? MANIFEST_PNF_METADATA : MANIFEST_VNF_METADATA;
+    }
+
+    protected void handleOtherEntry(final Map.Entry<String, String> entry) {
+        reportError(ErrorLevel.ERROR, Messages.METADATA_UNSUPPORTED_ENTRY.formatMessage(entry.getKey()));
+        LOGGER.warn(Messages.METADATA_UNSUPPORTED_ENTRY.getErrorMessage(), entry.getKey());
+    }
+
     private Map<String, List<ErrorMessage>> getAnyValidationErrors() {
         if (errorsByFile.isEmpty()) {
             return Collections.emptyMap();
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004Version3MetaDirectoryValidator.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004Version3MetaDirectoryValidator.java
new file mode 100644 (file)
index 0000000..473d68e
--- /dev/null
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * 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.orchestration.csar.validation;
+
+import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_PNF_METADATA_LIMIT_VERSION_3;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_PNF_METADATA_VERSION_3;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_VNF_METADATA_LIMIT_VERSION_3;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_VNF_METADATA_VERSION_3;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_TYPE_PNF;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_TYPE_VNF;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.COMPATIBLE_SPECIFICATION_VERSIONS;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.datatypes.error.ErrorLevel;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+import org.openecomp.sdc.tosca.csar.ToscaMetaEntry;
+import org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.exceptions.InvalidManifestMetadataException;
+import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Validates the contents of the package to ensure it complies with the "CSAR with TOSCA-Metadata directory" structure
+ * as defined in ETSI GS NFV-SOL 004 v3.3.1.
+ */
+class SOL004Version3MetaDirectoryValidator extends SOL004MetaDirectoryValidator {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SOL004Version3MetaDirectoryValidator.class);
+
+    public SOL004Version3MetaDirectoryValidator() {
+        super();
+    }
+
+    SOL004Version3MetaDirectoryValidator(final SecurityManager securityManager) {
+        super(securityManager);
+    }
+
+    @Override
+    protected void handleOtherEntry(final Map.Entry<String, String> entry) {
+        if (!ToscaMetaEntry.OTHER_DEFINITIONS.getName().equals(entry.getKey())) {
+            reportError(ErrorLevel.ERROR, Messages.METADATA_UNSUPPORTED_ENTRY.formatMessage(entry.getKey()));
+            LOGGER.warn(Messages.METADATA_UNSUPPORTED_ENTRY.getErrorMessage(), entry.getKey());
+        } else
+            validateDefinitionFile(entry.getValue());
+    }
+
+    @Override
+    protected boolean validMetaLimit(Map<String, String> metadata) {
+        int maxAllowedEntries = isPnfMetadata(metadata) ? MANIFEST_PNF_METADATA_LIMIT_VERSION_3 : MANIFEST_VNF_METADATA_LIMIT_VERSION_3;
+        return metadata.size() == maxAllowedEntries;
+    }
+
+    @Override
+    protected ImmutableSet<String> getManifestMetadata(final Map<String, String> metadata) {
+        return isPnfMetadata(metadata) ? MANIFEST_PNF_METADATA_VERSION_3 : MANIFEST_VNF_METADATA_VERSION_3;
+    }
+
+    @Override
+    protected boolean isPnfMetadata(final Map<String, String> metadata) {
+        List<String> keys = metadata.keySet().stream().collect(Collectors.toList());
+        //Both VNF and PNF share this attribute
+        keys.remove(COMPATIBLE_SPECIFICATION_VERSIONS.getToken());
+        final String expectedMetadataType =
+                keys.get(0).contains(TOSCA_TYPE_PNF) ? TOSCA_TYPE_PNF : TOSCA_TYPE_VNF;
+        if (keys.stream()
+            .anyMatch(k -> !k.contains(expectedMetadataType))) {
+            throw new InvalidManifestMetadataException(Messages.MANIFEST_METADATA_INVALID_ENTRY.getErrorMessage());
+        }
+        return expectedMetadataType.equals(TOSCA_TYPE_PNF);
+    }
+}
index 064a1c6..38c28f8 100644 (file)
 
 package org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation;
 
+import static org.openecomp.sdc.tosca.csar.CSARConstants.ETSI_VERSION_2_7_1;
+
+import java.io.IOException;
+
 import org.openecomp.core.utilities.file.FileContentHandler;
 import org.openecomp.sdc.vendorsoftwareproduct.services.impl.etsi.ETSIService;
 import org.openecomp.sdc.vendorsoftwareproduct.services.impl.etsi.ETSIServiceImpl;
-import java.io.IOException;
 
 public class ValidatorFactory {
 
@@ -39,7 +42,14 @@ public class ValidatorFactory {
      * @throws IOException when metafile is invalid
      */
     public static Validator getValidator(final FileContentHandler fileContentHandler) throws IOException {
-        ETSIService etsiService = new ETSIServiceImpl(null);
-        return etsiService.isSol004WithToscaMetaDirectory(fileContentHandler) ? new SOL004MetaDirectoryValidator() : new ONAPCsarValidator();
+        final ETSIService etsiService = new ETSIServiceImpl(null);
+        if (etsiService.isSol004WithToscaMetaDirectory(fileContentHandler)) {
+            if (!etsiService.getHighestCompatibleSpecificationVersion(fileContentHandler)
+                    .isLowerThan(ETSI_VERSION_2_7_1)){
+                return new SOL004Version3MetaDirectoryValidator();
+            }
+            return new SOL004MetaDirectoryValidator();
+        }
+        return new ONAPCsarValidator();
     }
 }
index dca4ecf..9461648 100644 (file)
@@ -39,7 +39,6 @@ import static org.openecomp.sdc.tosca.csar.ManifestTokenType.ATTRIBUTE_VALUE_SEP
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_ARCHIVE_VERSION;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_NAME;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_RELEASE_DATE_TIME;
-import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PACKAGE_VERSION;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PRODUCT_NAME;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PROVIDER_ID;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_RELEASE_DATE_TIME;
@@ -69,6 +68,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+
 import org.apache.commons.collections.CollectionUtils;
 import org.junit.Before;
 import org.junit.Test;
@@ -83,27 +83,65 @@ import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManagerException
 
 public class SOL004MetaDirectoryValidatorTest {
 
-    private SOL004MetaDirectoryValidator sol004MetaDirectoryValidator;
-    private OnboardingPackageContentHandler handler;
-    private StringBuilder metaFileBuilder;
+    private static int MANIFEST_DEFINITION_ERROR_COUNT = 1;
+
+    protected SOL004MetaDirectoryValidator sol004MetaDirectoryValidator;
+    protected OnboardingPackageContentHandler handler;
+    protected StringBuilder metaFileBuilder;
 
     @Before
     public void setUp() {
-        sol004MetaDirectoryValidator = new SOL004MetaDirectoryValidator();
+        sol004MetaDirectoryValidator = getSOL004MetaDirectoryValidator();
         handler = new OnboardingPackageContentHandler();
-        metaFileBuilder = new StringBuilder()
-                .append(TOSCA_META_FILE_VERSION_ENTRY.getName())
-                .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" 1.0").append("\n")
-                .append(CSAR_VERSION_ENTRY.getName())
-                .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" 1.1").append("\n")
-                .append(CREATED_BY_ENTRY.getName())
-                .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" Vendor").append("\n")
-                .append(ENTRY_DEFINITIONS.getName())
-                .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" ").append(TOSCA_DEFINITION_FILEPATH).append("\n")
-                .append(ETSI_ENTRY_MANIFEST.getName())
-                .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" ").append(TOSCA_MANIFEST_FILEPATH).append("\n")
-                .append(ETSI_ENTRY_CHANGE_LOG.getName())
-                .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" ").append(TOSCA_CHANGELOG_FILEPATH).append("\n");
+        metaFileBuilder = getMetaFileBuilder();
+    }
+
+    protected SOL004MetaDirectoryValidator getSOL004MetaDirectoryValidator() {
+        return new SOL004MetaDirectoryValidator();
+    }
+
+    protected SOL004MetaDirectoryValidator getSol004WithSecurity(SecurityManager securityManagerMock) {
+        return new SOL004MetaDirectoryValidator(securityManagerMock);
+    }
+
+    protected StringBuilder getMetaFileBuilder() {
+        return new StringBuilder()
+        .append(TOSCA_META_FILE_VERSION_ENTRY.getName())
+            .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" 1.0").append("\n")
+        .append(CSAR_VERSION_ENTRY.getName())
+            .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" 1.1").append("\n")
+        .append(CREATED_BY_ENTRY.getName())
+            .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" Vendor").append("\n")
+        .append(ENTRY_DEFINITIONS.getName())
+            .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" ").append(TOSCA_DEFINITION_FILEPATH).append("\n")
+        .append(ETSI_ENTRY_MANIFEST.getName())
+            .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" ").append(TOSCA_MANIFEST_FILEPATH).append("\n")
+        .append(ETSI_ENTRY_CHANGE_LOG.getName())
+            .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" ").append(TOSCA_CHANGELOG_FILEPATH).append("\n");
+    }
+
+    protected ManifestBuilder getPnfManifestSampleBuilder() {
+        return new ManifestBuilder()
+            .withMetaData(PNFD_NAME.getToken(), "myPnf")
+            .withMetaData(ManifestTokenType.PNFD_PROVIDER.getToken(), "ACME")
+            .withMetaData(PNFD_ARCHIVE_VERSION.getToken(), "1.0")
+            .withMetaData(PNFD_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
+    }
+
+    protected ManifestBuilder getVnfManifestSampleBuilder() {
+        return new ManifestBuilder()
+            .withMetaData(ManifestTokenType.VNF_PRODUCT_NAME.getToken(), "RadioNode")
+            .withMetaData(ManifestTokenType.VNF_PROVIDER_ID.getToken(), "ACME")
+            .withMetaData(ManifestTokenType.VNF_PACKAGE_VERSION.getToken(), "1.0")
+            .withMetaData(ManifestTokenType.VNF_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
+    }
+
+    /**
+     * ETSI Version 2.7.1 below contains one Definition File reference
+     * ETSI Version 2.7.1 onwards contains two possible Definition File reference
+     */
+    protected int getManifestDefintionErrorCount() {
+        return MANIFEST_DEFINITION_ERROR_COUNT;
     }
 
     @Test
@@ -153,6 +191,7 @@ public class SOL004MetaDirectoryValidatorTest {
         handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler);
+
         assertEquals(0, errors.size());
     }
 
@@ -220,7 +259,7 @@ public class SOL004MetaDirectoryValidatorTest {
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler);
         assertThat("Total of errors should be as expected", errors.size(), is(1));
         final List<ErrorMessage> errorMessages = errors.get(SdcCommon.UPLOAD_FILE);
-        assertThat("Total of errors messages should be as expected", errorMessages.size(), is(3));
+        assertThat("Total of errors messages should be as expected", errorMessages.size(), is((2 + getManifestDefintionErrorCount())));
     }
 
 
@@ -310,7 +349,7 @@ public class SOL004MetaDirectoryValidatorTest {
         handler.addFile(TOSCA_MANIFEST_FILEPATH, manifest.getBytes(StandardCharsets.UTF_8));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler);
-        assertExpectedErrors("", errors, 1);
+        assertExpectedErrors("", errors, getManifestDefintionErrorCount());
     }
 
     /**
@@ -340,7 +379,7 @@ public class SOL004MetaDirectoryValidatorTest {
         handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler);
-        assertExpectedErrors("Manifest referenced import file missing", errors, 1);
+        assertExpectedErrors("Manifest referenced import file missing", errors, getManifestDefintionErrorCount());
     }
 
     @Test
@@ -422,7 +461,7 @@ public class SOL004MetaDirectoryValidatorTest {
         handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler);
-        assertExpectedErrors("Reference with invalid YAML format", errors, 1);
+        assertExpectedErrors("Reference with invalid YAML format", errors, getManifestDefintionErrorCount());
     }
 
     @Test
@@ -503,7 +542,7 @@ public class SOL004MetaDirectoryValidatorTest {
     }
 
     @Test
-    public void testGivenManifestAndDefinitionFile_withSameNames_thenNoErrorReturned() {
+    public void testGivenManifestAndDefinitionFile_withSameNames_thenNoErrorReturned()  {
         final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder();
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFileBuilder.toString().getBytes(StandardCharsets.UTF_8));
@@ -823,9 +862,10 @@ public class SOL004MetaDirectoryValidatorTest {
         final Map<String, List<ErrorMessage>> actualErrorMap = sol004MetaDirectoryValidator.validateContent(handler);
 
         final List<ErrorMessage> expectedErrorList = new ArrayList<>();
-        expectedErrorList.add(new ErrorMessage(ErrorLevel.ERROR
-                , Messages.MISSING_IMPORT_FILE.formatMessage("Definitions/etsi_nfv_sol001_pnfd_2_5_2_types.yaml"))
-        );
+        for (int i =0;i < getManifestDefintionErrorCount();i++)
+            expectedErrorList.add(new ErrorMessage(ErrorLevel.ERROR
+                    , Messages.MISSING_IMPORT_FILE.formatMessage("Definitions/etsi_nfv_sol001_pnfd_2_5_2_types.yaml"))
+                    );
 
         assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), expectedErrorList);
     }
@@ -861,9 +901,10 @@ public class SOL004MetaDirectoryValidatorTest {
         final Map<String, List<ErrorMessage>> actualErrorMap = sol004MetaDirectoryValidator.validateContent(handler);
 
         final List<ErrorMessage> expectedErrorList = new ArrayList<>();
-        expectedErrorList.add(new ErrorMessage(ErrorLevel.ERROR
+        for (int i =0;i < getManifestDefintionErrorCount();i++)
+            expectedErrorList.add(new ErrorMessage(ErrorLevel.ERROR
                 , Messages.INVALID_IMPORT_STATEMENT.formatMessage(definitionImportOne, "null"))
-        );
+         );
 
         assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), expectedErrorList);
     }
@@ -939,7 +980,7 @@ public class SOL004MetaDirectoryValidatorTest {
                 " in 'reader', line 2, column 7:\n" +
                 "    {}\n" +
                 "      ^\n")
-        );
+            );
 
         final Map<String, List<ErrorMessage>> actualErrorMap = sol004MetaDirectoryValidator
                 .validateContent(handler);
@@ -982,7 +1023,7 @@ public class SOL004MetaDirectoryValidatorTest {
         );
 
         final Map<String, List<ErrorMessage>> actualErrorMap = sol004MetaDirectoryValidator
-                .validateContent(handler);
+            .validateContent(handler);
 
         assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), expectedErrorList);
     }
@@ -1173,7 +1214,7 @@ public class SOL004MetaDirectoryValidatorTest {
 
         final SecurityManager securityManagerMock = mock(SecurityManager.class);
         when(securityManagerMock.verifySignedData(any(), any(), any())).thenReturn(true);
-        sol004MetaDirectoryValidator = new SOL004MetaDirectoryValidator(securityManagerMock);
+        sol004MetaDirectoryValidator = getSol004WithSecurity(securityManagerMock);
 
         //when
         Map<String, List<ErrorMessage>> actualErrorMap = sol004MetaDirectoryValidator.validateContent(handler);
@@ -1181,7 +1222,7 @@ public class SOL004MetaDirectoryValidatorTest {
         assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), Collections.emptyList());
 
         //given
-        sol004MetaDirectoryValidator = new SOL004MetaDirectoryValidator(securityManagerMock);
+        sol004MetaDirectoryValidator = getSol004WithSecurity(securityManagerMock);
         when(securityManagerMock.verifySignedData(any(), any(), any())).thenReturn(false);
 
         //when
@@ -1195,7 +1236,7 @@ public class SOL004MetaDirectoryValidatorTest {
         assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), expectedErrorList);
 
         //given
-        sol004MetaDirectoryValidator = new SOL004MetaDirectoryValidator(securityManagerMock);
+        sol004MetaDirectoryValidator = getSol004WithSecurity(securityManagerMock);
         when(securityManagerMock.verifySignedData(any(), any(), any()))
                 .thenThrow(new SecurityManagerException("SecurityManagerException"));
         //when
@@ -1204,16 +1245,31 @@ public class SOL004MetaDirectoryValidatorTest {
         //then
         expectedErrorList = new ArrayList<>();
         expectedErrorList.add(
-                new ErrorMessage(ErrorLevel.ERROR,
-                        Messages.ARTIFACT_SIGNATURE_VALIDATION_ERROR.formatMessage(fakeArtifactCmsPath,
-                                fakeArtifactPath, fakeCertificatePath, "SecurityManagerException")
-                )
+            new ErrorMessage(ErrorLevel.ERROR,
+                Messages.ARTIFACT_SIGNATURE_VALIDATION_ERROR.formatMessage(fakeArtifactCmsPath,
+                    fakeArtifactPath, fakeCertificatePath, "SecurityManagerException")
+            )
         );
         assertExpectedErrors(actualErrorMap.get(SdcCommon.UPLOAD_FILE), expectedErrorList);
     }
 
+    protected void assertExpectedErrors(List<ErrorMessage> actualErrorList, final List<ErrorMessage> expectedErrorList) {
+        if (actualErrorList == null) {
+            actualErrorList = new ArrayList<>();
+        }
+
+        printErrorMessages(actualErrorList);
+
+        assertThat("The actual error list should have the same size as the expected error list " + actualErrorList.toString() 
+                , actualErrorList, hasSize(expectedErrorList.size())
+        );
 
-    private void assertExpectedErrors(final String testCase, final Map<String, List<ErrorMessage>> errors, final int expectedErrors) {
+        assertThat("The actual error and expected error lists should be the same"
+                , actualErrorList, containsInAnyOrder(expectedErrorList.toArray(new ErrorMessage[0]))
+        );
+    }
+
+    protected void assertExpectedErrors(final String testCase, final Map<String, List<ErrorMessage>> errors, final int expectedErrors){
         final List<ErrorMessage> errorMessages = errors.get(SdcCommon.UPLOAD_FILE);
         printErrorMessages(errorMessages);
         if (expectedErrors > 0) {
@@ -1231,36 +1287,4 @@ public class SOL004MetaDirectoryValidatorTest {
         }
     }
 
-    private ManifestBuilder getPnfManifestSampleBuilder() {
-        return new ManifestBuilder()
-                .withMetaData(PNFD_NAME.getToken(), "myPnf")
-                .withMetaData(ManifestTokenType.PNFD_PROVIDER.getToken(), "ACME")
-                .withMetaData(PNFD_ARCHIVE_VERSION.getToken(), "1.0")
-                .withMetaData(PNFD_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
-    }
-
-    private ManifestBuilder getVnfManifestSampleBuilder() {
-        return new ManifestBuilder()
-                .withMetaData(VNF_PRODUCT_NAME.getToken(), "RadioNode")
-                .withMetaData(VNF_PROVIDER_ID.getToken(), "ACME")
-                .withMetaData(VNF_PACKAGE_VERSION.getToken(), "1.0")
-                .withMetaData(VNF_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
-    }
-
-    private void assertExpectedErrors(List<ErrorMessage> actualErrorList, final List<ErrorMessage> expectedErrorList) {
-        if (actualErrorList == null) {
-            actualErrorList = new ArrayList<>();
-        }
-
-        printErrorMessages(actualErrorList);
-
-        assertThat("The actual error list should have the same size as the expected error list"
-                , actualErrorList, hasSize(expectedErrorList.size())
-        );
-
-        assertThat("The actual error and expected error lists should be the same"
-                , actualErrorList, containsInAnyOrder(expectedErrorList.toArray(new ErrorMessage[0]))
-        );
-    }
-
 }
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004Version3MetaDirectoryValidatorTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004Version3MetaDirectoryValidatorTest.java
new file mode 100644 (file)
index 0000000..02ea3f2
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * 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.vendorsoftwareproduct.impl.orchestration.csar.validation;
+
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR;
+import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.OTHER_DEFINITIONS;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.TOSCA_DEFINITION_FILEPATH;
+
+import org.openecomp.sdc.tosca.csar.ManifestTokenType;
+import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager;
+
+public class SOL004Version3MetaDirectoryValidatorTest extends SOL004MetaDirectoryValidatorTest {
+
+    private static int MANIFEST_DEFINITION_ERROR_COUNT_VERSION_3 = 2;
+
+    @Override
+    public SOL004MetaDirectoryValidator getSOL004MetaDirectoryValidator() {
+        return new SOL004Version3MetaDirectoryValidator();
+    }
+
+    @Override
+    public StringBuilder getMetaFileBuilder() {
+        return super.getMetaFileBuilder().append(OTHER_DEFINITIONS.getName())
+        .append(ATTRIBUTE_VALUE_SEPARATOR.getToken()).append(" ").append(TOSCA_DEFINITION_FILEPATH).append("\n");
+    }
+
+    @Override
+    protected SOL004MetaDirectoryValidator getSol004WithSecurity(SecurityManager securityManagerMock) {
+        return new SOL004Version3MetaDirectoryValidator(securityManagerMock);
+    }
+
+    @Override
+    protected ManifestBuilder getVnfManifestSampleBuilder() {
+        return super.getVnfManifestSampleBuilder()
+            .withMetaData(ManifestTokenType.VNFD_ID.getToken(), "2116fd24-83f2-416b-bf3c-ca1964793aca")
+            .withMetaData(ManifestTokenType.COMPATIBLE_SPECIFICATION_VERSIONS.getToken(), "2.7.1,3.3.1")
+            .withMetaData(ManifestTokenType.VNF_SOFTWARE_VERSION.getToken(), "1.0.0")
+            .withMetaData(ManifestTokenType.VNFM_INFO.getToken(), "etsivnfm:v2.3.1,0:myGreatVnfm-1");
+    }
+
+    @Override
+    protected ManifestBuilder getPnfManifestSampleBuilder() {
+        return super.getPnfManifestSampleBuilder()
+            .withMetaData(ManifestTokenType.COMPATIBLE_SPECIFICATION_VERSIONS.getToken(), "2.7.1,3.3.1");
+    }
+
+    @Override
+    protected int getManifestDefintionErrorCount() {
+        return MANIFEST_DEFINITION_ERROR_COUNT_VERSION_3;
+    }
+}
index 0a271c9..7332505 100644 (file)
@@ -24,11 +24,14 @@ import java.io.IOException;
 import java.nio.file.Path;
 import java.util.Map;
 import java.util.Optional;
+
 import org.openecomp.core.utilities.file.FileContentHandler;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 import org.openecomp.sdc.tosca.csar.Manifest;
 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
 
+import com.vdurmont.semver4j.Semver;
+
 
 public interface ETSIService {
 
@@ -67,18 +70,26 @@ public interface ETSIService {
     Manifest getManifest(FileContentHandler handler) throws IOException;
 
     /**
-     * Determmines the type of resource that the CSAR represents
+     * Determines the type of resource that the CSAR represents
      * @param handler contains csar artifacts
      * @throws IOException when TOSCA.meta file or manifest file is invalid
      */
     ResourceTypeEnum getResourceType(FileContentHandler handler) throws IOException;
 
     /**
-     * Determmines the type of resource that the CSAR represents
+     * Determines the type of resource that the CSAR represents
      * @param manifest contains manifest content
      * @throws IOException when TOSCA.meta file or manifest file is invalid
      */
     ResourceTypeEnum getResourceType(Manifest manifest) throws IOException;
 
     Path getOriginalManifestPath(final FileContentHandler handler) throws IOException;
+
+
+    /**
+     * Determines the highest compatible specification version based on ETSI manifest file
+     * @param handler contains csar artifacts
+     * @return Semver representing highest compatible specification version
+     */
+    Semver getHighestCompatibleSpecificationVersion(final FileContentHandler handler);
 }
index ad52562..e6b686e 100644 (file)
       <artifactId>lombok</artifactId>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>com.vdurmont</groupId>
+      <artifactId>semver4j</artifactId>
+      <version>2.0.1</version>
+    </dependency>
+
   </dependencies>
 
 
index 1281d61..8ec76fe 100644 (file)
@@ -24,21 +24,25 @@ import static org.openecomp.sdc.tosca.csar.CSARConstants.ARTIFACTS_FOLDER;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.MAIN_SERVICE_TEMPLATE_MF_FILE_NAME;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_PNF_METADATA;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ORIG_PATH_FILE_NAME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.COMPATIBLE_SPECIFICATION_VERSIONS;
 import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.ENTRY_DEFINITIONS;
 import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.ETSI_ENTRY_CHANGE_LOG;
 import static org.openecomp.sdc.tosca.csar.ToscaMetaEntry.ETSI_ENTRY_MANIFEST;
 import static org.openecomp.sdc.tosca.csar.ToscaMetadataFileInfo.TOSCA_META_PATH_FILE_NAME;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.ETSI_VERSION_2_6_1;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Collectors;
+
 import org.apache.commons.collections.MapUtils;
 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
 import org.onap.sdc.tosca.services.YamlUtil;
@@ -55,6 +59,8 @@ import org.openecomp.sdc.tosca.csar.SOL004ManifestOnboarding;
 import org.openecomp.sdc.tosca.csar.ToscaMetadata;
 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
 
+import com.vdurmont.semver4j.Semver;
+
 public class ETSIServiceImpl implements ETSIService {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ETSIServiceImpl.class);
@@ -202,6 +208,22 @@ public class ETSIServiceImpl implements ETSIService {
             && metaDataEntries.containsKey(ETSI_ENTRY_CHANGE_LOG.getName());
     }
 
+    @Override
+    public Semver getHighestCompatibleSpecificationVersion(final FileContentHandler handler) {
+        try {
+            Map<String, String> metadata = getManifest(handler).getMetadata();
+            if (metadata.containsKey(COMPATIBLE_SPECIFICATION_VERSIONS.getToken())) {
+                return Arrays.asList(metadata.get(COMPATIBLE_SPECIFICATION_VERSIONS.getToken()).split(","))
+                        .stream().map(Semver::new).max((v1, v2) -> v1.compareTo(v2))
+                        .orElse(new Semver(ETSI_VERSION_2_6_1));
+            }
+        } catch (Exception ex) {
+            LOGGER.error("An error occurred while getting highest compatible version from manifest file", ex);
+        }
+        return new Semver(ETSI_VERSION_2_6_1);
+
+    }
+
     private boolean isMetaFilePresent(Map<String, byte[]> handler) {
         return handler.containsKey(TOSCA_META_PATH_FILE_NAME) || handler.containsKey(TOSCA_META_ORIG_PATH_FILE_NAME);
     }
index f5570ae..4254a56 100644 (file)
@@ -30,6 +30,7 @@ import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.ETSI_VERSION_2_6_1;
 
 import java.io.File;
 import java.io.IOException;
@@ -45,6 +46,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -57,6 +59,8 @@ import org.openecomp.sdc.tosca.csar.Manifest;
 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
 import org.yaml.snakeyaml.Yaml;
 
+import com.vdurmont.semver4j.Semver;
+
 public class ETSIServiceImplTest {
 
     private ETSIService etsiService;
@@ -291,6 +295,14 @@ public class ETSIServiceImplTest {
             containsString(file2Path.toString()));
     }
 
+    @Test
+    public void extractETSIPackageVersionTest() {
+        final List<String> versions = Arrays.asList("2.6.1", "2.7.1", "1.1.1", "3.3.1", "3.1.1", "1.1.2", "2.2.1");
+        assertThat(versions.stream().map(Semver::new).max((v1, v2) -> v1.compareTo(v2))
+                .orElse(new Semver(ETSI_VERSION_2_6_1)),
+                is(new Semver("3.3.1")));
+    }
+
     private <T> T convert(final String fullFileName, final Class<T> className) throws IOException {
         assertTrue((new File(fullFileName)).exists());
 
index cd0c809..b05313f 100644 (file)
   </parent>
 
   <dependencies>
+    <dependency>
+      <groupId>com.vdurmont</groupId>
+      <artifactId>semver4j</artifactId>
+      <version>3.1.0</version>
+    </dependency>
     <dependency>
       <groupId>org.onap.sdc.common</groupId>
       <artifactId>onap-tosca-datatype</artifactId>
index 783636b..845d36c 100644 (file)
 package org.openecomp.sdc.tosca.csar;
 
 import static com.google.common.collect.ImmutableSet.of;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.COMPATIBLE_SPECIFICATION_VERSIONS;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_ARCHIVE_VERSION;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_NAME;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_PROVIDER;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_RELEASE_DATE_TIME;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PACKAGE_VERSION;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_SOFTWARE_VERSION;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PRODUCT_NAME;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PROVIDER_ID;
 import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_RELEASE_DATE_TIME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNFD_ID;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNFM_INFO;
 
 import com.google.common.collect.ImmutableSet;
 
@@ -41,13 +45,23 @@ public class CSARConstants {
     public static final ImmutableSet<String> MANIFEST_PNF_METADATA =
         of(PNFD_PROVIDER.getToken(), PNFD_NAME.getToken(), PNFD_RELEASE_DATE_TIME.getToken(),
             PNFD_ARCHIVE_VERSION.getToken());
+    public static final ImmutableSet<String> MANIFEST_PNF_METADATA_VERSION_3 =
+            of(PNFD_PROVIDER.getToken(), PNFD_NAME.getToken(), PNFD_RELEASE_DATE_TIME.getToken(),
+                PNFD_ARCHIVE_VERSION.getToken(), COMPATIBLE_SPECIFICATION_VERSIONS.getToken());
     public static final ImmutableSet<String> MANIFEST_VNF_METADATA =
             of(VNF_PROVIDER_ID.getToken(), VNF_PRODUCT_NAME.getToken(), VNF_RELEASE_DATE_TIME.getToken(),
                 VNF_PACKAGE_VERSION.getToken());
+    public static final ImmutableSet<String> MANIFEST_VNF_METADATA_VERSION_3 =
+            of(COMPATIBLE_SPECIFICATION_VERSIONS.getToken(), VNFD_ID.getToken(), VNF_PROVIDER_ID.getToken(), VNF_PRODUCT_NAME.getToken(), VNF_RELEASE_DATE_TIME.getToken(),
+                VNF_PACKAGE_VERSION.getToken(), VNF_SOFTWARE_VERSION.getToken(), VNFM_INFO.getToken());
     public static final int MANIFEST_METADATA_LIMIT = 4;
+    public static final int MANIFEST_VNF_METADATA_LIMIT_VERSION_3 = 8;
+    public static final int MANIFEST_PNF_METADATA_LIMIT_VERSION_3 = 5;
     public static final String TOSCA_META_ORIG_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta.original";
     public static final String CSAR_VERSION_1_0 = "1.0";
     public static final String CSAR_VERSION_1_1 = "1.1";
+    public static final String ETSI_VERSION_2_6_1 = "2.6.1";
+    public static final String ETSI_VERSION_2_7_1 = "2.7.1";
     public static final ImmutableSet<String> NON_FILE_IMPORT_ATTRIBUTES =
             ImmutableSet.of("repository", "namespace_uri", "namespace_prefix");
     public static final String TOSCA_TYPE_PNF = "pnf";
index 2e073a4..7caa09f 100644 (file)
@@ -36,12 +36,17 @@ public enum ManifestTokenType {
     VNF_PROVIDER_ID("vnf_provider_id"),
     VNF_PACKAGE_VERSION("vnf_package_version"),
     VNF_RELEASE_DATE_TIME("vnf_release_date_time"),
+    VNF_SOFTWARE_VERSION("vnf_software_version"),
+    VNFM_INFO("vnfm_info"),
+    VNFD_ID("vnfd_id"),
     PNFD_NAME("pnfd_name"),
     PNFD_PROVIDER("pnfd_provider"),
     PNFD_ARCHIVE_VERSION("pnfd_archive_version"),
     PNFD_RELEASE_DATE_TIME("pnfd_release_date_time"),
     SIGNATURE("Signature"),
-    CERTIFICATE("Certificate");
+    CERTIFICATE("Certificate"),
+    COMPATIBLE_SPECIFICATION_VERSIONS("compatible_specification_versions");
+
 
     private final String token;
 
@@ -67,6 +72,10 @@ public enum ManifestTokenType {
             case VNF_PROVIDER_ID:
             case VNF_PACKAGE_VERSION:
             case VNF_RELEASE_DATE_TIME:
+            case VNFD_ID:
+            case VNFM_INFO:
+            case VNF_SOFTWARE_VERSION:
+            case COMPATIBLE_SPECIFICATION_VERSIONS:
                 return true;
             default:
                 return false;
@@ -79,6 +88,7 @@ public enum ManifestTokenType {
             case PNFD_PROVIDER:
             case PNFD_ARCHIVE_VERSION:
             case PNFD_RELEASE_DATE_TIME:
+            case COMPATIBLE_SPECIFICATION_VERSIONS:
                 return true;
             default:
                 return false;
index 99ea9a5..97f5629 100644 (file)
 
 package org.openecomp.sdc.tosca.csar;
 
+import static org.openecomp.sdc.tosca.csar.CSARConstants.ETSI_VERSION_2_6_1;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.ETSI_VERSION_2_7_1;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_PNF_METADATA_LIMIT_VERSION_3;
+import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_VNF_METADATA_LIMIT_VERSION_3;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.COMPATIBLE_SPECIFICATION_VERSIONS;
+
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Optional;
+
 import org.apache.commons.lang.StringUtils;
 import org.openecomp.sdc.common.errors.Messages;
 
+import com.vdurmont.semver4j.Semver;
+
 /**
  * Processes a SOL004 Manifest.
  */
 public class SOL004ManifestOnboarding extends AbstractOnboardingManifest {
 
+    private int maxAllowedMetaEntries;
+
     @Override
     protected void processMetadata() {
         Optional<String> currentLine = getCurrentLine();
@@ -51,7 +63,7 @@ public class SOL004ManifestOnboarding extends AbstractOnboardingManifest {
             final String metadataLine = currentLine.get();
             final String metadataEntry = readEntryName(metadataLine).orElse(null);
             if (!isMetadataEntry(metadataEntry)) {
-                if (metadata.size() < MAX_ALLOWED_MANIFEST_META_ENTRIES) {
+                if (metadata.size() < getMaxAllowedManifestMetaEntries()) {
                     reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, metadataLine);
                     continueToProcess = false;
                     return;
@@ -225,12 +237,11 @@ public class SOL004ManifestOnboarding extends AbstractOnboardingManifest {
             reportError(Messages.MANIFEST_NO_METADATA);
             return false;
         }
-
-        final Entry<String, String> firstManifestEntry = metadata.entrySet().iterator().next();
-        final ManifestTokenType firstManifestEntryTokenType =
-            ManifestTokenType.parse(firstManifestEntry.getKey()).orElse(null);
+        String key = metadata.keySet().stream().filter(k -> !COMPATIBLE_SPECIFICATION_VERSIONS.getToken().equals(k))
+                .findFirst().orElse(null);
+        final ManifestTokenType firstManifestEntryTokenType = ManifestTokenType.parse(key).orElse(null);
         if (firstManifestEntryTokenType == null) {
-            reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, firstManifestEntry.getKey());
+            reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, key);
             return false;
         }
         for (final Entry<String, String> manifestEntry : metadata.entrySet()) {
@@ -247,8 +258,8 @@ public class SOL004ManifestOnboarding extends AbstractOnboardingManifest {
             }
         }
 
-        if (metadata.entrySet().size() != MAX_ALLOWED_MANIFEST_META_ENTRIES) {
-            reportError(Messages.MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT, MAX_ALLOWED_MANIFEST_META_ENTRIES);
+        if (metadata.entrySet().size() != getMaxAllowedManifestMetaEntries()) {
+            reportError(Messages.MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT, getMaxAllowedManifestMetaEntries());
             return false;
         }
 
@@ -372,4 +383,25 @@ public class SOL004ManifestOnboarding extends AbstractOnboardingManifest {
         readNextNonEmptyLine();
     }
 
+    private int getMaxAllowedManifestMetaEntries() {
+        if (maxAllowedMetaEntries == 0) {
+            boolean isVersion3 = metadata.containsKey(COMPATIBLE_SPECIFICATION_VERSIONS.getToken())
+                && !getHighestCompatibleVersion().isLowerThan(ETSI_VERSION_2_7_1);
+            //Both PNF and VNF share attribute COMPATIBLE_SPECIFICATION_VERSIONS
+            if (isVersion3)
+                maxAllowedMetaEntries = metadata.keySet().stream()
+                    .anyMatch(k -> !COMPATIBLE_SPECIFICATION_VERSIONS.getToken().equals(k)
+                            && isMetadataEntry(k) && ManifestTokenType.parse(k).get().isMetadataPnfEntry())
+                    ? MANIFEST_PNF_METADATA_LIMIT_VERSION_3 : MANIFEST_VNF_METADATA_LIMIT_VERSION_3;
+            else
+                maxAllowedMetaEntries = MAX_ALLOWED_MANIFEST_META_ENTRIES;
+        }
+        return maxAllowedMetaEntries;
+    }
+
+    private Semver getHighestCompatibleVersion() {
+        return Arrays.asList(metadata.get(COMPATIBLE_SPECIFICATION_VERSIONS.getToken()).split(","))
+                .stream().map(Semver::new).max((v1, v2) -> v1.compareTo(v2))
+                .orElse(new Semver(ETSI_VERSION_2_6_1));
+    }
 }
index c6ae0d1..3b66954 100644 (file)
@@ -38,7 +38,8 @@ public enum ToscaMetaEntry {
     ETSI_ENTRY_CHANGE_LOG("ETSI-Entry-Change-Log"),
     ETSI_ENTRY_TESTS("ETSI-Entry-Tests"),
     ETSI_ENTRY_LICENSES("ETSI-Entry-Licenses"),
-    ETSI_ENTRY_CERTIFICATE("ETSI-Entry-Certificate");
+    ETSI_ENTRY_CERTIFICATE("ETSI-Entry-Certificate"),
+    OTHER_DEFINITIONS("Other-Definitions");
 
     private final String name;
 
index 288995d..beae6af 100644 (file)
@@ -489,6 +489,29 @@ class SOL004ManifestOnboardingTest {
         }
     }
 
+    @Test
+    public void testSuccessfulParsingWithCompatibleSpecficationVersion() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/ValidToscaVersion3.mf")) {
+            manifest.parse(manifestAsStream);
+            assertValidManifest(8, 5, Collections.emptyMap(), ResourceTypeEnum.VF, false);
+        }
+    }
+
+    @Test
+    public void testFailedParsingWithCompatibleSpecficationVersion() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/InvalidToscaVersion3.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> errorList = Collections.singletonList(
+                    Messages.MANIFEST_ERROR_WITH_LINE.formatMessage(
+                        Messages.MANIFEST_METADATA_INVALID_ENTRY1.formatMessage("vnf_test: 1.0"),
+                        4, "vnf_test: 1.0")
+                );
+                assertInvalidManifest(errorList);
+        }
+    }
+
     private void assertValidManifest(final int expectedMetadataSize, final int expectedSourcesSize,
                                      final Map<String, Integer> expectedNonManoKeySize,
                                      final ResourceTypeEnum resourceType, final boolean isSigned) {
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidToscaVersion3.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidToscaVersion3.mf
new file mode 100644 (file)
index 0000000..c753e76
--- /dev/null
@@ -0,0 +1,19 @@
+metadata:
+    vnf_product_name: Mock
+    vnf_provider_id: ZTE
+    vnf_test: 1.0
+    vnf_release_date_time: 2017.01.01T10:00+03:00
+    vnf_software_version: 1.0.0
+    vnfd_id: 2116fd24-83f2-416b-bf3c-ca1964793aca
+    compatible_specification_versions: 2.7.1, 3.1.1
+    vnfm_info: etsivnfm:v2.3.1,0:myGreatVnfm-1
+
+Source: MainServiceTemplate.yaml
+
+Source: Definitions/GlobalSubstitutionTypesServiceTemplate.yaml
+
+Source: Artifacts/install.sh
+
+Source: Artifacts/create_stack.sh
+
+Source: Licenses/license.xml
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/ValidToscaVersion3.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/ValidToscaVersion3.mf
new file mode 100644 (file)
index 0000000..2cfa9a1
--- /dev/null
@@ -0,0 +1,19 @@
+metadata:
+    vnf_product_name: Mock
+    vnf_provider_id: ZTE
+    vnf_package_version: 1.0
+    vnf_release_date_time: 2017.01.01T10:00+03:00
+    vnf_software_version: 1.0.0
+    vnfd_id: 2116fd24-83f2-416b-bf3c-ca1964793aca
+    compatible_specification_versions: 2.7.1, 3.1.1
+    vnfm_info: etsivnfm:v2.3.1,0:myGreatVnfm-1
+
+Source: MainServiceTemplate.yaml
+
+Source: Definitions/GlobalSubstitutionTypesServiceTemplate.yaml
+
+Source: Artifacts/install.sh
+
+Source: Artifacts/create_stack.sh
+
+Source: Licenses/license.xml