diff options
author | vasraz <vasyl.razinkov@est.tech> | 2019-12-12 14:41:10 +0000 |
---|---|---|
committer | vasraz <vasyl.razinkov@est.tech> | 2019-12-13 10:28:21 +0000 |
commit | 02cd70328143803d94912634eab0afe378764ed1 (patch) | |
tree | 9128937d0301a971a0c939995521f2f0efcfa60c /csarvalidation/src/main/java | |
parent | 8db4db6563a98c4fac3e833707ab2b14098657d5 (diff) |
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 <vasyl.razinkov@est.tech>
Change-Id: I0518da5cdbf22b0086cf2c4f50194b47994273f7
Issue-ID: VNFSDK-531
Diffstat (limited to 'csarvalidation/src/main/java')
3 files changed, 441 insertions, 103 deletions
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<String, Map<String, List<String>>> nonMano, final List<SourcesParser.Source> sources) { + private void validateNonManoCohesionWithSources(final Map<String, Map<String, List<String>>> nonMano, + final List<SourcesParser.Source> sources) { final Collection<Map<String, List<String>>> values = nonMano.values(); final List<String> 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<String> 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<SourcesParser.Source> 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<String> data, String newLine) { - final String updatedData = data.stream().map(it -> it + newLine).collect(Collectors.joining()); - return updatedData.getBytes(Charset.defaultCharset()); + private byte[] toBytes(List<String> 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 = 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 = ValidateNonManoSection.getInstance(csar); - if(validateNonManoSection.isPresent()) { - List<CSARArchive.CSARError> 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<String, Map<String, List<String>>> nonMano; - private final List<CSARArchive.CSARError> errors = new ArrayList<>(); - - private ValidateNonManoSection(CSARArchive csar, String fileName, Map<String, Map<String, List<String>>> nonMano) { + private final List<CSARError> errors = new ArrayList<>(); + private final List<String> 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<String, Map<String, List<String>>> nonMano) { this.csar = csar; this.fileName = fileName; this.nonMano = nonMano; } - static Optional<ValidateNonManoSection> getInstance(CSARArchive csar) { + static Optional<ValidateNonManoSection> 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<String, Map<String, List<String>>> nonMano = csar.getManifest().getNonMano(); - return Optional.of(new ValidateNonManoSection(csar, fileName,nonMano)); + return Optional.of(new ValidateNonManoSection(csar, fileName, nonMano)); } - public List<CSARArchive.CSARError> validate() { - - List<String> attributeNames = Arrays.asList( - "onap_ves_events", - "onap_pm_dictionary", - "onap_yang_modules", - "onap_others" - ); - - for (String attributeName : attributeNames) { - validateAttribute(attributeName); + public List<CSARError> 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<String> 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<String, List<String>> attributeElements = this.nonMano.get(attributeName); - Set<String> attributeElementNames = attributeElements.keySet(); + final Map<String, List<String>> attributeElements = nonMano.get(attributeName); + final Set<String> 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<String, List<String>> attributeElements) { - for (String pathToFile : attributeElements.get(SOURCE_ELEMENT_TAG)) { - File fileFromCsar = this.csar.getFileFromCsar(pathToFile); + private void validateThatSourceFileExists(final String attributeName, final Map<String, List<String>> 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 + * <p> + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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 = ValidateNonManoSection.getInstance(csar); + if (validateNonManoSection.isPresent()) { + final List<CSARError> 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<String, Map<String, List<String>>> nonMano; + private final List<CSARError> errors = new ArrayList<>(); + private final List<String> attributeNames = Arrays.asList( + "onap_pnf_sw_information" + ); + + private ValidateNonManoSection(final CSARArchive csar, final String fileName, + final Map<String, Map<String, List<String>>> nonMano) { + this.csar = csar; + this.fileName = fileName; + this.nonMano = nonMano; + } + + static Optional<ValidateNonManoSection> getInstance(final CSARArchive csar) { + final File manifestMfFile = csar.getManifestMfFile(); + if (manifestMfFile == null) { + return Optional.empty(); + } + final String fileName = manifestMfFile.getName(); + final Map<String, Map<String, List<String>>> nonMano = csar.getManifest().getNonMano(); + return Optional.of(new ValidateNonManoSection(csar, fileName, nonMano)); + } + + private List<CSARError> 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<String, List<String>> attributeElements = nonMano.get(attributeName); + final Set<String> 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<String, List<String>> 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<PnfSoftwareInformation> 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<PnfSoftwareInformation> parse(final String swInformationFilePath) { + + final Map<String, Object> 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<String, Object>) 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<Map<String, String>> pnfSoftwareInformationYaml = (List<Map<String, String>>) 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<PnfSoftwareVersion> 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); + } + } + } +} |