From 02cd70328143803d94912634eab0afe378764ed1 Mon Sep 17 00:00:00 2001 From: vasraz Date: Thu, 12 Dec 2019 14:41:10 +0000 Subject: Implement PNF package validation on PNF software version 1. New requirement (R-972082) 2. Edit requirement (R-146092) 3. Remove unused dependencies. Signed-off-by: Vasyl Razinkov Change-Id: I0518da5cdbf22b0086cf2c4f50194b47994273f7 Issue-ID: VNFSDK-531 --- .../cvc/csar/cc/sol004/VTPValidateCSARR130206.java | 76 ++--- .../cvc/csar/cc/sol004/VTPValidateCSARR146092.java | 148 +++++----- .../cvc/csar/cc/sol004/VTPValidateCSARR972082.java | 320 +++++++++++++++++++++ .../services/org.onap.cli.fw.cmd.OnapCommand | 18 +- .../sol004/vtp-validate-csar-r146092.yaml | 9 +- .../sol004/vtp-validate-csar-r972082.yaml | 65 +++++ .../VTPValidateCSARR146092IntegrationTest.java | 52 ++-- .../VTPValidateCSARR972082IntegrationTest.java | 113 ++++++++ ...ngYamlFileReferedInSourceSessionOfManifest.csar | Bin 0 -> 24044 bytes .../missingFieldsInNonManoArtifactManifest.csar | Bin 0 -> 18052 bytes .../missingPnfSoftwareVersionInYamlFile.csar | Bin 0 -> 18000 bytes ...singVersionInPnfSoftwareVersionInformation.csar | Bin 0 -> 18029 bytes ...ngYamlFileReferedInSourceSessionOfManifest.csar | Bin 0 -> 18073 bytes .../src/test/resources/pnf/r972082/validFile.csar | Bin 0 -> 18069 bytes 14 files changed, 668 insertions(+), 133 deletions(-) create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java create mode 100644 csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r972082.yaml create mode 100644 csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java create mode 100644 csarvalidation/src/test/resources/pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar create mode 100644 csarvalidation/src/test/resources/pnf/r972082/missingFieldsInNonManoArtifactManifest.csar create mode 100644 csarvalidation/src/test/resources/pnf/r972082/missingPnfSoftwareVersionInYamlFile.csar create mode 100644 csarvalidation/src/test/resources/pnf/r972082/missingVersionInPnfSoftwareVersionInformation.csar create mode 100644 csarvalidation/src/test/resources/pnf/r972082/missingYamlFileReferedInSourceSessionOfManifest.csar create mode 100644 csarvalidation/src/test/resources/pnf/r972082/validFile.csar (limited to 'csarvalidation/src') diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java index 701c524..fefe65b 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java @@ -54,8 +54,8 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { private final ShaHashCodeGenerator shaHashCodeGenerator = new ShaHashCodeGenerator(); private final ManifestFileSignatureValidator manifestFileSignatureValidator = new ManifestFileSignatureValidator(); - public static class CSARErrorUnableToFindCertificate extends CSARArchive.CSARError { + CSARErrorUnableToFindCertificate(String paramName) { super("0x4001"); this.message = String.format("Unable to find cert file defined by %s!", paramName); @@ -63,6 +63,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } public static class CSARErrorUnableToFindCmsSection extends CSARArchive.CSARError { + CSARErrorUnableToFindCmsSection() { super("0x4002"); this.message = "Unable to find CMS section in manifest!"; @@ -70,6 +71,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } public static class CSARErrorUnableToFindCsarContent extends CSARArchive.CSARError { + CSARErrorUnableToFindCsarContent() { super("0x4003"); this.message = "Unable to find csar content!"; @@ -77,6 +79,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } public static class CSARErrorWrongHashCode extends CSARArchive.CSARError { + CSARErrorWrongHashCode(String path) { super("0x4004"); this.message = String.format("Source '%s' has wrong hash!", path); @@ -84,6 +87,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } public static class CSARErrorUnableToFindAlgorithm extends CSARArchive.CSARError { + CSARErrorUnableToFindAlgorithm(String path) { super("0x4005"); this.message = String.format("Source '%s' has hash, but unable to find algorithm tag!", path); @@ -91,6 +95,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } public static class CSARErrorUnableToFindSource extends CSARArchive.CSARError { + CSARErrorUnableToFindSource(String path) { super("0x4006"); this.message = String.format("Unable to calculate digest - file missing: %s", path); @@ -98,6 +103,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } public static class CSARErrorInvalidSignature extends CSARArchive.CSARError { + CSARErrorInvalidSignature() { super("0x4007"); this.message = "File has invalid CMS signature!"; @@ -105,6 +111,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } public static class CSARErrorContentMismatch extends CSARArchive.CSARError { + CSARErrorContentMismatch() { super("0x4008"); this.message = "Mismatch between contents of non-mano-artifact-sets and source files of the package"; @@ -146,21 +153,22 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } } - private void validateNonManoCohesionWithSources(final Map>> nonMano, final List sources) { + private void validateNonManoCohesionWithSources(final Map>> nonMano, + final List sources) { final Collection>> values = nonMano.values(); final List nonManoSourcePaths = values.stream() - .map(Map::values) - .flatMap(Collection::stream) - .flatMap(List::stream) - .filter(it -> !it.isEmpty()) - .collect(Collectors.toList()); + .map(Map::values) + .flatMap(Collection::stream) + .flatMap(List::stream) + .filter(it -> !it.isEmpty()) + .collect(Collectors.toList()); final List sourcePaths = sources.stream() - .map(SourcesParser.Source::getValue) - .collect(Collectors.toList()); + .map(SourcesParser.Source::getValue) + .collect(Collectors.toList()); - if(!sourcePaths.containsAll(nonManoSourcePaths)){ + if (!sourcePaths.containsAll(nonManoSourcePaths)) { this.errors.add(new CSARErrorContentMismatch()); } @@ -196,7 +204,8 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } } - private void validateSources(Path csarRootDirectory, CSARArchive.Manifest manifest) throws NoSuchAlgorithmException, IOException { + private void validateSources(Path csarRootDirectory, CSARArchive.Manifest manifest) + throws NoSuchAlgorithmException, IOException { final List sources = manifest.getSources(); for (SourcesParser.Source source : sources) { if (!source.getAlgorithm().isEmpty() || !source.getHash().isEmpty()) { @@ -205,7 +214,8 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } } - private void validateSource(Path csarRootDirectory, SourcesParser.Source source) throws NoSuchAlgorithmException, IOException { + private void validateSource(Path csarRootDirectory, SourcesParser.Source source) + throws NoSuchAlgorithmException, IOException { final Path sourcePath = csarRootDirectory.resolve(source.getValue()); if (!sourcePath.toFile().exists()) { this.errors.add(new CSARErrorUnableToFindSource(source.getValue())); @@ -218,14 +228,16 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } } - private void validateSourceHashCode(Path csarRootDirectory, SourcesParser.Source source) throws NoSuchAlgorithmException, IOException { + private void validateSourceHashCode(Path csarRootDirectory, SourcesParser.Source source) + throws NoSuchAlgorithmException, IOException { String hashCode = generateHashCode(csarRootDirectory, source); if (!hashCode.equals(source.getHash())) { this.errors.add(new CSARErrorWrongHashCode(source.getValue())); } } - private String generateHashCode(Path csarRootDirectory, SourcesParser.Source source) throws NoSuchAlgorithmException, IOException { + private String generateHashCode(Path csarRootDirectory, SourcesParser.Source source) + throws NoSuchAlgorithmException, IOException { final byte[] sourceData = Files.readAllBytes(csarRootDirectory.resolve(source.getValue())); final String algorithm = source.getAlgorithm(); @@ -244,27 +256,27 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } -} + class ManifestFileSignatureValidator { -class ManifestFileSignatureValidator { - private static final Logger LOG = LoggerFactory.getLogger(ManifestFileSignatureValidator.class); - private final ManifestFileSplitter manifestFileSplitter = new ManifestFileSplitter(); - private final CmsSignatureValidator cmsSignatureValidator = new CmsSignatureValidator(); + private final Logger LOG = LoggerFactory.getLogger(ManifestFileSignatureValidator.class); + private final ManifestFileSplitter manifestFileSplitter = new ManifestFileSplitter(); + private final CmsSignatureValidator cmsSignatureValidator = new CmsSignatureValidator(); - boolean isValid(File manifestFile) { - try { - ManifestFileModel mf = manifestFileSplitter.split(manifestFile); - return cmsSignatureValidator.verifySignedData(toBytes(mf.getCMS(), mf.getNewLine()), - Optional.empty(), - toBytes(mf.getData(), mf.getNewLine())); - } catch (CmsSignatureValidatorException e) { - LOG.error("Unable to verify signed data!", e); - return false; + boolean isValid(File manifestFile) { + try { + ManifestFileModel mf = manifestFileSplitter.split(manifestFile); + return cmsSignatureValidator.verifySignedData(toBytes(mf.getCMS(), mf.getNewLine()), + Optional.empty(), + toBytes(mf.getData(), mf.getNewLine())); + } catch (CmsSignatureValidatorException e) { + LOG.error("Unable to verify signed data!", e); + return false; + } } - } - private byte[] toBytes(List data, String newLine) { - final String updatedData = data.stream().map(it -> it + newLine).collect(Collectors.joining()); - return updatedData.getBytes(Charset.defaultCharset()); + private byte[] toBytes(List data, String newLine) { + final String updatedData = data.stream().map(it -> it + newLine).collect(Collectors.joining()); + return updatedData.getBytes(Charset.defaultCharset()); + } } } diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092.java index c9a4de1..fd6a32f 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092.java @@ -17,20 +17,20 @@ package org.onap.cvc.csar.cc.sol004; - -import org.onap.cli.fw.schema.OnapCommandSchema; -import org.onap.cvc.csar.CSARArchive; -import org.onap.cvc.csar.PnfCSARError; -import org.onap.cvc.csar.PnfCSARError.PnfCSARErrorEntryMissing; -import org.onap.cvc.csar.cc.VTPValidateCSARBase; - import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; +import org.onap.cli.fw.schema.OnapCommandSchema; +import org.onap.cvc.csar.CSARArchive; +import org.onap.cvc.csar.CSARArchive.CSARError; +import org.onap.cvc.csar.PnfCSARError; +import org.onap.cvc.csar.PnfCSARError.PnfCSARErrorEntryMissing; +import org.onap.cvc.csar.cc.VTPValidateCSARBase; @OnapCommandSchema(schema = "vtp-validate-csar-r146092.yaml") public class VTPValidateCSARR146092 extends VTPValidateCSARBase { @@ -38,116 +38,122 @@ public class VTPValidateCSARR146092 extends VTPValidateCSARBase { private static final int UNKNOWN_LINE_NUMBER = -1; private static final String SOURCE_ELEMENT_TAG = "Source"; - private static class MissingSourceElementUnderAttributeError extends PnfCSARError { - private MissingSourceElementUnderAttributeError(String attributeName, String fileName) { - super("0x2002", - String.format("Missing. Entry [%s under %s]", SOURCE_ELEMENT_TAG, attributeName), - UNKNOWN_LINE_NUMBER, - fileName); + @Override + protected void validateCSAR(final CSARArchive csar) { + if (csar.getManifest().isNonManoAvailable()) { + final Optional validateNonManoSection = ValidateNonManoSection.getInstance(csar); + if (validateNonManoSection.isPresent()) { + errors.addAll(validateNonManoSection.get().validate()); + } } } - private static class InvalidPathToFileError extends PnfCSARError { - private InvalidPathToFileError(String attributeName, String pathToSourceFile, String fileName) { + @Override + protected String getVnfReqsNo() { + return "R146092"; + } + + private static class MissingSourceElementUnderAttributeError extends PnfCSARError { + + private MissingSourceElementUnderAttributeError(final String attributeName, final String fileName) { super("0x2002", - String.format("Invalid. Entry [%s under %s has invalid '%s' path]", SOURCE_ELEMENT_TAG, attributeName, pathToSourceFile), - UNKNOWN_LINE_NUMBER, - fileName); + String.format("Missing. Entry [%s under %s]", SOURCE_ELEMENT_TAG, attributeName), + UNKNOWN_LINE_NUMBER, + fileName); } } - @Override - protected void validateCSAR(CSARArchive csar) { - if(csar.getManifest().isNonManoAvailable()) { - Optional validateNonManoSection = ValidateNonManoSection.getInstance(csar); - if(validateNonManoSection.isPresent()) { - List csarErrors = validateNonManoSection.get().validate(); - this.errors.addAll(csarErrors); - } + private static class InvalidPathToFileError extends PnfCSARError { + + private InvalidPathToFileError(final String attributeName, final String pathToSourceFile, final String fileName) { + super("0x2002", + String.format("Invalid. Entry [%s under %s has invalid '%s' path]", SOURCE_ELEMENT_TAG, attributeName, + pathToSourceFile), + UNKNOWN_LINE_NUMBER, + fileName); } } - private static class ValidateNonManoSection { + private final CSARArchive csar; private final String fileName; private final Map>> nonMano; - private final List errors = new ArrayList<>(); - - private ValidateNonManoSection(CSARArchive csar, String fileName, Map>> nonMano) { + private final List errors = new ArrayList<>(); + private final List attributeNames = Arrays.asList( + "onap_ansible_playbooks", + "onap_others", + "onap_pm_dictionary", + "onap_pnf_sw_information", + "onap_scripts", + "onap_ves_events", + "onap_yang_modules" + ); + + private ValidateNonManoSection(final CSARArchive csar, final String fileName, + final Map>> nonMano) { this.csar = csar; this.fileName = fileName; this.nonMano = nonMano; } - static Optional getInstance(CSARArchive csar) { + static Optional getInstance(final CSARArchive csar) { final File manifestMfFile = csar.getManifestMfFile(); - if(manifestMfFile == null){ + if (manifestMfFile == null) { return Optional.empty(); } final String fileName = manifestMfFile.getName(); final Map>> nonMano = csar.getManifest().getNonMano(); - return Optional.of(new ValidateNonManoSection(csar, fileName,nonMano)); + return Optional.of(new ValidateNonManoSection(csar, fileName, nonMano)); } - public List validate() { - - List attributeNames = Arrays.asList( - "onap_ves_events", - "onap_pm_dictionary", - "onap_yang_modules", - "onap_others" - ); - - for (String attributeName : attributeNames) { - validateAttribute(attributeName); + public List validate() { + if (nonMano.keySet().stream().filter(Objects::nonNull).count() > 0) { + nonMano.keySet().stream().filter(Objects::nonNull).forEach(this::validateAttribute); + } else { + errors.add(new PnfCSARErrorEntryMissing( + attributeNames.toString(), + fileName, + UNKNOWN_LINE_NUMBER) + ); } - return this.errors; + return errors; } - private void validateAttribute(String attributeName) { - Set nonManoAttributes = this.nonMano.keySet(); - if (!nonManoAttributes.contains(attributeName)) { - this.errors.add(new PnfCSARErrorEntryMissing( - attributeName, - this.fileName, - UNKNOWN_LINE_NUMBER) + private void validateAttribute(final String nonManoAttributes) { + + if (!attributeNames.contains(nonManoAttributes)) { + errors.add(new PnfCSARErrorEntryMissing( + nonManoAttributes, + fileName, + UNKNOWN_LINE_NUMBER) ); } else { - validateSourceElementsUnderAttribute(attributeName); + validateSourceElementsUnderAttribute(nonManoAttributes); } } - private void validateSourceElementsUnderAttribute(String attributeName) { + private void validateSourceElementsUnderAttribute(final String attributeName) { - Map> attributeElements = this.nonMano.get(attributeName); - Set attributeElementNames = attributeElements.keySet(); + final Map> attributeElements = nonMano.get(attributeName); + final Set attributeElementNames = attributeElements.keySet(); if (!attributeElementNames.contains(SOURCE_ELEMENT_TAG)) { - this.errors.add(new MissingSourceElementUnderAttributeError(attributeName, this.fileName)); + errors.add(new MissingSourceElementUnderAttributeError(attributeName, fileName)); } else { validateThatSourceFileExists(attributeName, attributeElements); } } - private void validateThatSourceFileExists(String attributeName, Map> attributeElements) { - for (String pathToFile : attributeElements.get(SOURCE_ELEMENT_TAG)) { - File fileFromCsar = this.csar.getFileFromCsar(pathToFile); + private void validateThatSourceFileExists(final String attributeName, final Map> attributeElements) { + attributeElements.get(SOURCE_ELEMENT_TAG).forEach(pathToFile -> { + final File fileFromCsar = csar.getFileFromCsar(pathToFile); if (!fileFromCsar.exists()) { - this.errors.add( - new InvalidPathToFileError(attributeName, - pathToFile, this.fileName) - ); + errors.add(new InvalidPathToFileError(attributeName, pathToFile, fileName)); } - } + }); } } - @Override - protected String getVnfReqsNo() { - return "R146092"; - } - - } diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java new file mode 100644 index 0000000..1061480 --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082.java @@ -0,0 +1,320 @@ +/* + * Copyright 2019 Nordix + *

+ * 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. + * + */ + +package org.onap.cvc.csar.cc.sol004; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.onap.cli.fw.schema.OnapCommandSchema; +import org.onap.cvc.csar.CSARArchive; +import org.onap.cvc.csar.CSARArchive.CSARError; +import org.onap.cvc.csar.PnfCSARError; +import org.onap.cvc.csar.PnfCSARError.PnfCSARErrorEntryMissing; +import org.onap.cvc.csar.cc.VTPValidateCSARBase; +import org.onap.cvc.csar.cc.sol004.VTPValidateCSARR972082.PnfSoftwareInformation.PnfSoftwareInformationField; +import org.onap.cvc.csar.cc.sol004.VTPValidateCSARR972082.PnfSoftwareInformation.PnfSoftwareVersion; +import org.onap.cvc.csar.cc.sol004.VTPValidateCSARR972082.PnfSoftwareInformation.PnfSoftwareVersion.PnfSoftwareVersionField; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.YAMLException; + +@OnapCommandSchema(schema = "vtp-validate-csar-r972082.yaml") +public class VTPValidateCSARR972082 extends VTPValidateCSARBase { + + private static final int UNKNOWN_LINE_NUMBER = -1; + private static final String SOURCE_ELEMENT_TAG = "Source"; + private static final String ERROR_CODE = "0x2002"; + + @Override + protected void validateCSAR(final CSARArchive csar) { + if (csar.getManifest().isNonManoAvailable()) { + final Optional validateNonManoSection = ValidateNonManoSection.getInstance(csar); + if (validateNonManoSection.isPresent()) { + final List csarErrors = validateNonManoSection.get().validate(); + errors.addAll(csarErrors); + } + } + } + + @Override + protected String getVnfReqsNo() { + return "R972082"; + } + + private static class MissingSourceElementUnderAttributeError extends PnfCSARError { + + private MissingSourceElementUnderAttributeError(final String attributeName, final String fileName) { + super(ERROR_CODE, + String.format("Missing. Entry [%s under %s]", SOURCE_ELEMENT_TAG, attributeName), + UNKNOWN_LINE_NUMBER, + fileName); + } + } + + private static class MissingSoftwareInformationError extends PnfCSARError { + + private MissingSoftwareInformationError(final String fileName) { + super(ERROR_CODE, + String.format("Missing. Entry [%s in %s]", "pnf_software_version", fileName), + UNKNOWN_LINE_NUMBER, + fileName); + } + } + + private static class InvalidPathToFileError extends PnfCSARError { + + private InvalidPathToFileError(final String attributeName, final String pathToSourceFile, final String fileName) { + super(ERROR_CODE, + String.format("Invalid. Entry [%s under %s has invalid '%s' path]", SOURCE_ELEMENT_TAG, attributeName, + pathToSourceFile), + UNKNOWN_LINE_NUMBER, + fileName); + } + } + + private static class InvalidYamlStructureError extends PnfCSARError { + + private InvalidYamlStructureError(final String fileName) { + super(ERROR_CODE, + String.format("Invalid. Yaml file %s is invalid", fileName), + UNKNOWN_LINE_NUMBER, + fileName); + } + } + + private static class ValidateNonManoSection { + + private final CSARArchive csar; + private final String fileName; + private final Map>> nonMano; + private final List errors = new ArrayList<>(); + private final List attributeNames = Arrays.asList( + "onap_pnf_sw_information" + ); + + private ValidateNonManoSection(final CSARArchive csar, final String fileName, + final Map>> nonMano) { + this.csar = csar; + this.fileName = fileName; + this.nonMano = nonMano; + } + + static Optional getInstance(final CSARArchive csar) { + final File manifestMfFile = csar.getManifestMfFile(); + if (manifestMfFile == null) { + return Optional.empty(); + } + final String fileName = manifestMfFile.getName(); + final Map>> nonMano = csar.getManifest().getNonMano(); + return Optional.of(new ValidateNonManoSection(csar, fileName, nonMano)); + } + + private List validate() { + if (nonMano.keySet().stream().filter(Objects::nonNull).count() > 0) { + nonMano.keySet().stream().filter(Objects::nonNull).forEach(this::validateAttribute); + } else { + errors.add(new PnfCSARErrorEntryMissing( + attributeNames.toString(), + fileName, + UNKNOWN_LINE_NUMBER) + ); + } + + return errors; + } + + private void validateAttribute(final String nonManoAttributes) { + + if (!attributeNames.contains(nonManoAttributes)) { + errors.add(new PnfCSARErrorEntryMissing( + nonManoAttributes, + fileName, + UNKNOWN_LINE_NUMBER) + ); + } else { + validateSourceElementsUnderAttribute(nonManoAttributes); + } + } + + private void validateSourceElementsUnderAttribute(final String attributeName) { + + final Map> attributeElements = nonMano.get(attributeName); + final Set attributeElementNames = attributeElements.keySet(); + + if (!attributeElementNames.contains(SOURCE_ELEMENT_TAG)) { + errors.add(new MissingSourceElementUnderAttributeError(attributeName, fileName)); + } else { + validateThatSourceFileExists(attributeName, attributeElements); + } + } + + private void validateThatSourceFileExists(final String attributeName, final Map> attributeElements) { + attributeElements.get(SOURCE_ELEMENT_TAG).forEach(pathToFile -> { + final File fileFromCsar = csar.getFileFromCsar(pathToFile); + if (!fileFromCsar.exists()) { + errors.add(new InvalidPathToFileError(attributeName, pathToFile, fileName)); + } else { + validateSoftwareInformationNonManoArtifact(pathToFile); + } + }); + } + + private void validateSoftwareInformationNonManoArtifact(final String swInformationFilePath) { + if (StringUtils.isEmpty(swInformationFilePath)) { + errors.add(new MissingSourceElementUnderAttributeError("", swInformationFilePath)); + return; + } + final Optional parsedYaml = parse(swInformationFilePath); + if (!parsedYaml.isPresent()) { + errors.add(new InvalidYamlStructureError(swInformationFilePath)); + } else { + final PnfSoftwareInformation pnfSoftwareInformation = parsedYaml.get(); + if (!pnfSoftwareInformation.isValid()) { + errors.add(new MissingSoftwareInformationError(swInformationFilePath)); + } + } + } + + private Object read(final InputStream yamlFileInputStream) { + final Yaml yaml = new Yaml(); + return yaml.load(yamlFileInputStream); + } + + private Optional parse(final String swInformationFilePath) { + + final Map softwareVersionYamlObject; + try (final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + Files.readAllBytes(csar.getFileFromCsar(swInformationFilePath).toPath()))) { + final Object yaml = read(byteArrayInputStream); + if (!(yaml instanceof Map)) { + return Optional.empty(); + } + + softwareVersionYamlObject = (Map) yaml; // unchecked warning suppressed + } catch (final IOException | YAMLException e) { + return Optional.empty(); + } + + final PnfSoftwareInformation pnfSoftwareInformation = new PnfSoftwareInformation(); + pnfSoftwareInformation.setDescription( + (String) softwareVersionYamlObject.get(PnfSoftwareInformationField.DESCRIPTION.getFieldName())); + pnfSoftwareInformation.setProvider( + (String) softwareVersionYamlObject.get(PnfSoftwareInformationField.PROVIDER.getFieldName())); + pnfSoftwareInformation.setVersion( + (String) softwareVersionYamlObject.get(PnfSoftwareInformationField.VERSION.getFieldName())); + final List> pnfSoftwareInformationYaml = (List>) softwareVersionYamlObject + .get(PnfSoftwareInformationField.PNF_SOFTWARE_INFORMATION + .getFieldName()); // unchecked warning suppressed + + if (CollectionUtils.isNotEmpty(pnfSoftwareInformationYaml)) { + pnfSoftwareInformationYaml.forEach(stringStringMap -> { + final String description = stringStringMap.get(PnfSoftwareVersionField.DESCRIPTION.getFieldName()); + final String version = stringStringMap + .get(PnfSoftwareVersionField.PNF_SOFTWARE_VERSION.getFieldName()); + pnfSoftwareInformation.addToSoftwareVersionSet(new PnfSoftwareVersion(version, description)); + }); + } + + return Optional.of(pnfSoftwareInformation); + } + } + + @Getter + @Setter + static class PnfSoftwareInformation { + + private String description; + private String provider; + private String version; + @Setter(AccessLevel.NONE) + private Set softwareVersionSet = new LinkedHashSet<>(); + + /** + * Adds a {@link PnfSoftwareVersion} instance to the software version set + * + * @param softwareVersion the pnf software version to add + */ + private void addToSoftwareVersionSet(final PnfSoftwareVersion softwareVersion) { + softwareVersionSet.add(softwareVersion); + } + + /** + * Stores the software information yaml field names. + */ + @AllArgsConstructor + @Getter + enum PnfSoftwareInformationField { + DESCRIPTION("description"), + PROVIDER("provider"), + VERSION("version"), + PNF_SOFTWARE_INFORMATION("pnf_software_information"); + + private final String fieldName; + + } + + private boolean isValid() { + if (CollectionUtils.isEmpty(softwareVersionSet)) { + return false; + } + + return softwareVersionSet.stream().allMatch(PnfSoftwareVersion::isValid); + } + + @AllArgsConstructor + @EqualsAndHashCode + @Getter + static class PnfSoftwareVersion { + + private final String version; + private final String description; + + /** + * Stores the pnf software version yaml fields. + */ + @Getter + @AllArgsConstructor + enum PnfSoftwareVersionField { + DESCRIPTION("description"), + PNF_SOFTWARE_VERSION("pnf_software_version"); + + private final String fieldName; + } + + private boolean isValid() { + return StringUtils.isNotEmpty(version); + } + } + } +} diff --git a/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand b/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand index aadb653..0695555 100644 --- a/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand +++ b/csarvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand @@ -13,9 +13,10 @@ # limitations under the License. org.onap.cvc.csar.VTPValidateCSAR -org.onap.cvc.csar.cc.sol001.VTPValidateCSARR17852 +org.onap.cvc.csar.cc.sol001.VTPValidateCSARR02454 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR09467 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR15837 +org.onap.cvc.csar.cc.sol001.VTPValidateCSARR17852 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR32155 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR35851 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR35854 @@ -24,28 +25,27 @@ org.onap.cvc.csar.cc.sol001.VTPValidateCSARR54356 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR65486 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR67895 org.onap.cvc.csar.cc.sol001.VTPValidateCSARR95321 -org.onap.cvc.csar.cc.sol001.VTPValidateCSARR02454 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR01123 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR04298 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR07879 -org.onap.cvc.csar.cc.sol004.VTPValidateCSARR13390 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR10087 +org.onap.cvc.csar.cc.sol004.VTPValidateCSARR130206 +org.onap.cvc.csar.cc.sol004.VTPValidateCSARR13390 +org.onap.cvc.csar.cc.sol004.VTPValidateCSARR146092 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR21322 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR23823 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR26881 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR26885 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR27310 +org.onap.cvc.csar.cc.sol004.VTPValidateCSARR293901 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR40293 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR40820 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR43958 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR51347 +org.onap.cvc.csar.cc.sol004.VTPValidateCSARR57019 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR66070 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR77707 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR77786 -org.onap.cvc.csar.cc.sol004.VTPValidateCSARR87234 -org.onap.cvc.csar.cc.sol004.VTPValidateCSARR293901 -org.onap.cvc.csar.cc.sol004.VTPValidateCSARR146092 -org.onap.cvc.csar.cc.sol004.VTPValidateCSARR57019 org.onap.cvc.csar.cc.sol004.VTPValidateCSARR787965 -org.onap.cvc.csar.cc.sol004.VTPValidateCSARR130206 - +org.onap.cvc.csar.cc.sol004.VTPValidateCSARR87234 +org.onap.cvc.csar.cc.sol004.VTPValidateCSARR972082 diff --git a/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r146092.yaml b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r146092.yaml index 5cb5d6f..0f4201e 100644 --- a/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r146092.yaml +++ b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r146092.yaml @@ -18,10 +18,13 @@ name: csar-validate-r146092 description: | The VNF/PNF package Manifest file MUST contain: non-mano artifact set with following ONAP public tag - -onap_ves_events - -onap_pm_dictionary - -onap_yang_module + -onap_ansible_playbooks -onap_others + -onap_pm_dictionary + -onap_pnf_sw_information + -onap_scripts + -onap_ves_events + -onap_yang_modules info: product: onap-dublin diff --git a/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r972082.yaml b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r972082.yaml new file mode 100644 index 0000000..53a6827 --- /dev/null +++ b/csarvalidation/src/main/resources/open-cli-schema/sol004/vtp-validate-csar-r972082.yaml @@ -0,0 +1,65 @@ +# Copyright 2019 Nordix +# +# 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. + +open_cli_schema_version: 1.0 + +name: csar-validate-r972082 + +description: | + The PNF software information file is included in the package and it MUST be compliant to: + - The file extension which contains the PNF software version must be .yaml + - The PNF software version information must be specified as following: + onap_pnf_sw_information: + - pnf_software_version: "" + +info: + product: onap-dublin + version: 1.0 + service: vnf-compliance + author: ONAP VTP Team onap-discuss@lists.onap.org + +parameters: + - name: csar + description: CSAR file path + long_option: csar + short_option: b + type: binary + is_optional: false + - name: pnf + description: CSAR file contains PNF + long_option: pnf + short_option: p + type: bool + is_optional: true + default_value: true + +results: + direction: landscape + attributes: + - name: code + description: Error code + scope: short + type: string + - name: message + description: Error message + scope: short + type: string + - name: file + description: File in which error occured + scope: short + type: string + - name: line-no + description: Line no at which error occured + scope: short + type: string diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java index 4e6daba..bf9b094 100644 --- a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java +++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR146092IntegrationTest.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.onap.cvc.csar.CSARArchive; import java.util.List; +import org.onap.cvc.csar.CSARArchive.CSARError; import static org.assertj.core.api.Assertions.assertThat; import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.configureTestCase; @@ -46,53 +47,51 @@ public class VTPValidateCSARR146092IntegrationTest { @Test public void shouldDoNotReportErrorWhenNonManoArtifactIsNotAvailable() throws Exception { // given - configureTestCase(testCase, "pnf/r146092/missingNonManoArtifactInManifest.csar", "vtp-validate-csar-r146092.yaml", IS_PNF); + configureTestCase(testCase, "pnf/r146092/missingNonManoArtifactInManifest.csar", + "vtp-validate-csar-r146092.yaml", IS_PNF); // when testCase.execute(); // then - List errors = testCase.getErrors(); + final List errors = testCase.getErrors(); assertThat(errors.size()).isEqualTo(0); } @Test public void shouldReportThatMandatoryNonManoArtifactSetEntryHasNotAllFields() throws Exception { // given - configureTestCase(testCase, "pnf/r146092/missingFieldsInNonManoArtifactManifest.csar", "vtp-validate-csar-r146092.yaml", IS_PNF); + configureTestCase(testCase, "pnf/r146092/missingFieldsInNonManoArtifactManifest.csar", + "vtp-validate-csar-r146092.yaml", IS_PNF); // when testCase.execute(); // then - List errors = testCase.getErrors(); - assertThat(errors.size()).isEqualTo(4); + final List errors = testCase.getErrors(); + assertThat(errors.size()).isEqualTo(1); assertThat(convertToMessagesList(errors)).contains( - "Missing. Entry [onap_ves_events]", - "Missing. Entry [onap_pm_dictionary]", - "Missing. Entry [onap_yang_modules]", - "Missing. Entry [onap_others]" + "Missing. Entry [[onap_ansible_playbooks, onap_others, onap_pm_dictionary, onap_pnf_sw_information, onap_scripts, onap_ves_events, onap_yang_modules]]" ); } - @Test public void shouldReportThatNonManoArtifactEntryHasAnySource() throws Exception { // given - configureTestCase(testCase, "pnf/r146092/noSourceElementInNonManoArtifactEntryManifest.csar", "vtp-validate-csar-r146092.yaml", IS_PNF); + configureTestCase(testCase, "pnf/r146092/noSourceElementInNonManoArtifactEntryManifest.csar", + "vtp-validate-csar-r146092.yaml", IS_PNF); // when testCase.execute(); // then - List errors = testCase.getErrors(); + final List errors = testCase.getErrors(); assertThat(errors.size()).isEqualTo(1); assertThat(convertToMessagesList(errors)).contains( - "Missing. Entry [Source under onap_ves_events]" + "Missing. Entry [Source under onap_ves_events]" ); } - @Test public void shouldReportThatNonManoArtifactEntryHasSourceWithUnknownFile() throws Exception { // given @@ -102,10 +101,10 @@ public class VTPValidateCSARR146092IntegrationTest { testCase.execute(); // then - List errors = testCase.getErrors(); + final List errors = testCase.getErrors(); assertThat(errors.size()).isEqualTo(1); assertThat(convertToMessagesList(errors)).contains( - "Invalid. Entry [Source under onap_ves_events has invalid 'Artifacts/Deployment/Events/RadioNode.yml' path]" + "Invalid. Entry [Source under onap_ves_events has invalid 'Artifacts/Deployment/Events/RadioNode.yml' path]" ); } @@ -118,10 +117,27 @@ public class VTPValidateCSARR146092IntegrationTest { testCase.execute(); // then - List errors = testCase.getErrors(); + final List errors = testCase.getErrors(); assertThat(errors.size()).isEqualTo(4); assertThat(convertToMessagesList(errors)).contains( - "Missing. Entry [Definition YAML]" + "Missing. Entry [Definition YAML]" + ); + } + + @Test + public void shouldReportThatEntryHasInvalidPathWhenYamlFileIsNotPresent() throws Exception { + // given + configureTestCase(testCase, "pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar", "vtp-validate-csar-r146092.yaml", + IS_PNF); + + // when + testCase.execute(); + + // then + final List errors = testCase.getErrors(); + assertThat(errors.size()).isEqualTo(1); + assertThat(convertToMessagesList(errors)).contains( + "Invalid. Entry [Source under onap_pnf_sw_information has invalid 'Files/pnf-sw-information/pnf-sw-information.yaml' path]" ); } diff --git a/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java new file mode 100644 index 0000000..fb9e431 --- /dev/null +++ b/csarvalidation/src/test/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR972082IntegrationTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2019 Nordix + *

+ * 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. + * + */ + +package org.onap.cvc.csar.cc.sol004; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.configureTestCase; +import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.convertToMessagesList; + +import java.util.List; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onap.cvc.csar.CSARArchive; +import org.onap.cvc.csar.CSARArchive.CSARError; + +public class VTPValidateCSARR972082IntegrationTest { + + private static final boolean IS_PNF = true; + private static final String VTP_VALIDATE_CSAR_R_972082_YAML = "vtp-validate-csar-r972082.yaml"; + private static final String PNF_R_972082 = "pnf/r972082/"; + private VTPValidateCSARR972082 testCase; + + @Before + public void setUp() { + testCase = new VTPValidateCSARR972082(); + } + + @Test + public void shouldReturnProperRequestNumber() { + assertThat(testCase.getVnfReqsNo()).isEqualTo("R972082"); + } + + @Test + public void shouldReturnNoErrorOnCorrectCsarFile() throws Exception { + // given + configureTestCase(testCase, PNF_R_972082 + "validFile.csar", VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF); + + // when + testCase.execute(); + + // then + final List errors = testCase.getErrors(); + assertThat(errors.size()).isEqualTo(0); + } + + @Test + public void shouldReportThatEntryHasInvalidPathWhenYamlFileIsNotPresent() throws Exception { + // given + configureTestCase(testCase, PNF_R_972082 + "missingYamlFileReferedInSourceSessionOfManifest.csar", + VTP_VALIDATE_CSAR_R_972082_YAML, + IS_PNF); + + // when + testCase.execute(); + + // then + final List errors = testCase.getErrors(); + assertThat(errors.size()).isEqualTo(1); + assertThat(convertToMessagesList(errors)).contains( + "Invalid. Entry [Source under onap_pnf_sw_information has invalid 'Files/pnf-sw-information/pnf-sw-information.yaml' path]" + ); + } + + @Test + public void shouldReportThatMandatoryNonManoArtifactSetEntryHasNotAllFields_() throws Exception { + // given + configureTestCase(testCase, PNF_R_972082 + "missingFieldsInNonManoArtifactManifest.csar", + VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF); + + // when + testCase.execute(); + + // then + final List errors = testCase.getErrors(); + assertThat(errors.size()).isEqualTo(1); + assertThat(convertToMessagesList(errors)).contains( + "Missing. Entry [[onap_pnf_sw_information]]" + ); + } + + @Test + public void shouldReportMissingPnfSoftwareVersionInYamlFile() throws Exception { + // given + configureTestCase(testCase, PNF_R_972082 + "missingPnfSoftwareVersionInYamlFile.csar", + VTP_VALIDATE_CSAR_R_972082_YAML, IS_PNF); + + // when + testCase.execute(); + + // then + final List errors = testCase.getErrors(); + assertThat(errors.size()).isEqualTo(1); + assertThat(convertToMessagesList(errors)).contains( + "Missing. Entry [pnf_software_version in Files/pnf-sw-information/pnf-sw-information.yaml]" + ); + } + +} \ No newline at end of file diff --git a/csarvalidation/src/test/resources/pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar b/csarvalidation/src/test/resources/pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar new file mode 100644 index 0000000..88ea0ce Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingFieldsInNonManoArtifactManifest.csar b/csarvalidation/src/test/resources/pnf/r972082/missingFieldsInNonManoArtifactManifest.csar new file mode 100644 index 0000000..2d157d1 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r972082/missingFieldsInNonManoArtifactManifest.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingPnfSoftwareVersionInYamlFile.csar b/csarvalidation/src/test/resources/pnf/r972082/missingPnfSoftwareVersionInYamlFile.csar new file mode 100644 index 0000000..6142499 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r972082/missingPnfSoftwareVersionInYamlFile.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingVersionInPnfSoftwareVersionInformation.csar b/csarvalidation/src/test/resources/pnf/r972082/missingVersionInPnfSoftwareVersionInformation.csar new file mode 100644 index 0000000..b2c9d03 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r972082/missingVersionInPnfSoftwareVersionInformation.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingYamlFileReferedInSourceSessionOfManifest.csar b/csarvalidation/src/test/resources/pnf/r972082/missingYamlFileReferedInSourceSessionOfManifest.csar new file mode 100644 index 0000000..402ea13 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r972082/missingYamlFileReferedInSourceSessionOfManifest.csar differ diff --git a/csarvalidation/src/test/resources/pnf/r972082/validFile.csar b/csarvalidation/src/test/resources/pnf/r972082/validFile.csar new file mode 100644 index 0000000..11d1945 Binary files /dev/null and b/csarvalidation/src/test/resources/pnf/r972082/validFile.csar differ -- cgit 1.2.3-korg