diff options
23 files changed, 970 insertions, 374 deletions
@@ -11,3 +11,4 @@ coverage-report/ *.iml *.log .idea +.attach_pid* diff --git a/csarvalidation/pom.xml b/csarvalidation/pom.xml index 16a48f9..547b4df 100644 --- a/csarvalidation/pom.xml +++ b/csarvalidation/pom.xml @@ -7,252 +7,192 @@ 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. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <!-- <parent> <groupId>org.onap.csarvalidation</groupId> <artifactId>csarvalidation</artifactId> - <version>1.0.0-SNAPSHOT</version> </parent> --> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <parent> - <groupId>org.onap.vnfsdk.validation</groupId> - <artifactId>validation</artifactId> - <version>1.2.2-SNAPSHOT</version> - </parent> - <modelVersion>4.0.0</modelVersion> + <parent> <groupId>org.onap.vnfsdk.validation</groupId> - <artifactId>validation-csar</artifactId> - <packaging>jar</packaging> - <name>csarvalidation/validation</name> + <artifactId>validation</artifactId> + <version>1.2.2-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>validation-csar</artifactId> + <packaging>jar</packaging> + <name>csarvalidation/validation</name> - <repositories> - <!-- <repository> <id>open-o</id> <name>OPEN-O repository</name> <url>https://nexus.open-o.org/content/repositories/public/</url> - </repository> --> - <repository> - <id>google-collections</id> - <name>Google collections repository</name> - <url>https://mvnrepository.com/artifact/com.google.collections/google-collections</url> - </repository> - <repository> - <id>onap</id> - <name>ONAP repository</name> - <url>https://nexus.onap.org/content/repositories/public/</url> - </repository> - </repositories> + <repositories> + <repository> + <id>google-collections</id> + <name>Google collections repository</name> + <url>https://mvnrepository.com/artifact/com.google.collections/google-collections</url> + </repository> + <repository> + <id>onap</id> + <name>ONAP repository</name> + <url>https://nexus.onap.org/content/repositories/public/</url> + </repository> + </repositories> - <dependencies> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-api</artifactId> - <version>1.7.16</version> - </dependency> - <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple --> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-simple</artifactId> - <version>1.7.16</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.yaml</groupId> - <artifactId>snakeyaml</artifactId> - <version>1.18</version> - </dependency> - <dependency> - <groupId>com.eclipsesource.jaxrs</groupId> - <artifactId>consumer</artifactId> - <exclusions> - <exclusion> - <groupId>com.eclipsesource.jaxrs</groupId> - <artifactId>jersey-all</artifactId> - </exclusion> - </exclusions> - <version>5.0</version> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-core</artifactId> - <version>2.9.4</version> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-annotations</artifactId> - <version>2.9.4</version> - </dependency> - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>2.8.2</version> - </dependency> - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava</artifactId> - </dependency> - <dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - <version>1.9</version> - </dependency> + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.16</version> + </dependency> + <dependency> + <groupId>org.yaml</groupId> + <artifactId>snakeyaml</artifactId> + <version>1.18</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>2.9.4</version> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.2.1</version> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.5</version> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcpkix-jdk15on</artifactId> + <version>1.61</version> + </dependency> + <dependency> + <groupId>org.onap.cli</groupId> + <artifactId>cli-framework</artifactId> + <version>3.0.0</version> + </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.12</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-lang3</artifactId> - <version>3.2.1</version> - </dependency> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-io</artifactId> - <version>1.3.2</version> - </dependency> - <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>2.5</version> - </dependency> - <dependency> - <groupId>org.bouncycastle</groupId> - <artifactId>bcpkix-jdk15on</artifactId> - <version>1.61</version> - </dependency> - <dependency> - <groupId>org.onap.cli</groupId> - <artifactId>cli-framework</artifactId> - <version>3.0.0</version> -<!-- <exclusions> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - </exclusion> - </exclusions> --> - </dependency> + <dependency> + <groupId>org.onap.cli</groupId> + <artifactId>cli-main</artifactId> + <version>3.0.0</version> + <scope>test</scope> + </dependency> - <dependency> - <groupId>org.onap.cli</groupId> - <artifactId>cli-main</artifactId> - <version>3.0.0</version> - <scope>test</scope> - <!-- <exclusions> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - </exclusion> - </exclusions> --> - </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.11.1</version> + <scope>test</scope> + </dependency> - <dependency> - <groupId>org.assertj</groupId> - <artifactId>assertj-core</artifactId> - <version>3.11.1</version> - <scope>test</scope> - </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.2</version> + </dependency> + <dependency> + <artifactId>commons-collections</artifactId> + <groupId>commons-collections</groupId> + <version>3.2.2</version> + </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <version>2.27.0</version> - <scope>test</scope> - </dependency> + </dependencies> - </dependencies> + <profiles> + <profile> + <id>all-tests</id> + <properties> + <build.profile.id>all-tests</build.profile.id> + <skip.unit.tests>true</skip.unit.tests> + </properties> + </profile> + </profiles> - <profiles> - <profile> - <id>all-tests</id> - <properties> - <build.profile.id>all-tests</build.profile.id> - <skip.unit.tests>true</skip.unit.tests> - </properties> - </profile> - </profiles> + <build> + <finalName>${project.artifactId}-${project.version}</finalName> - <build> - <finalName>${project.artifactId}-${project.version}</finalName> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.0.2</version> + <configuration> + <archive> + <manifest> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> + </manifest> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.1</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>3.0.2</version> - <configuration> - <archive> - <manifest> - <addDefaultImplementationEntries>true</addDefaultImplementationEntries> - <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> - </manifest> - </archive> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.1</version> - <configuration> - <source>1.8</source> - <target>1.8</target> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.0.0</version> + <executions> + <execution> + <id>copy-artifact</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + <type>${project.packaging}</type> + </artifactItem> + </artifactItems> + <outputDirectory>./target/lib</outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <outputDirectory>./target/lib</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>false</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <excludeArtifactIds>junit,jmockit</excludeArtifactIds> + </configuration> + </execution> + </executions> + </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <executions> - <execution> - <id>copy-artifact</id> - <phase>package</phase> - <goals> - <goal>copy</goal> - </goals> - <configuration> - <artifactItems> - <artifactItem> - <groupId>${project.groupId}</groupId> - <artifactId>${project.artifactId}</artifactId> - <version>${project.version}</version> - <type>${project.packaging}</type> - </artifactItem> - </artifactItems> - <outputDirectory>./target/lib</outputDirectory> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <version>3.0.0</version> - <executions> - <execution> - <id>copy-dependencies</id> - <phase>package</phase> - <goals> - <goal>copy-dependencies</goal> - </goals> - <configuration> - <outputDirectory>./target/lib</outputDirectory> - <overWriteReleases>false</overWriteReleases> - <overWriteSnapshots>false</overWriteSnapshots> - <overWriteIfNewer>true</overWriteIfNewer> - <excludeArtifactIds>junit,jmockit</excludeArtifactIds> - </configuration> - </execution> - </executions> - </plugin> - - <plugin> - <artifactId>maven-war-plugin</artifactId> - <configuration> - <failOnMissingWebXml>false</failOnMissingWebXml> - </configuration> - </plugin> - </plugins> - </build> + <plugin> + <artifactId>maven-war-plugin</artifactId> + <version>2.6</version> + <configuration> + <failOnMissingWebXml>false</failOnMissingWebXml> + </configuration> + </plugin> + </plugins> + </build> </project> diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/FileArchive.java b/csarvalidation/src/main/java/org/onap/cvc/csar/FileArchive.java index 86904b1..e2aa06b 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/FileArchive.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/FileArchive.java @@ -122,6 +122,11 @@ public class FileArchive { if(entry.isDirectory()){ filePath.mkdirs(); } else { + //create directories for sub directories in zip + File parentPathFile = filePath.getParentFile(); + if (parentPathFile != null) { + parentPathFile.mkdirs(); + } extract(zipInputStream, filePath); } } 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 e36314a..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"; @@ -124,7 +131,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } } catch (Exception e) { LOG.error("Internal VTPValidateCSARR130206 command error", e); - throw new OnapCommandException("0x3000", "Internal VTPValidateCSARR787966 command error. See logs."); + throw new OnapCommandException("0x3000", "Internal VTPValidateCSARR130206 command error. See logs."); } } @@ -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,25 +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()), Optional.empty(), toBytes(mf.getData())); - } 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) { - final String updatedData = data.stream().map(it -> it + "\r\n").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); + } + } + } +} diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileModel.java b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileModel.java index f6b42fd..ee7ade9 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileModel.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileModel.java @@ -23,10 +23,16 @@ import java.util.List; public class ManifestFileModel { private final List<String> data; private final List<String> cms; + private final String newLine; public ManifestFileModel(List<String> data, List<String> cms) { + this(data, cms, "\n"); + } + + public ManifestFileModel(List<String> data, List<String> cms, String newLine) { this.data = data; this.cms = cms; + this.newLine = newLine; } public List<String> getData() { @@ -36,4 +42,8 @@ public class ManifestFileModel { public List<String> getCMS() { return Collections.unmodifiableList(cms); } + + public String getNewLine() { + return newLine; + } } diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileSplitter.java b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileSplitter.java index d780e67..f8d920c 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileSplitter.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/ManifestFileSplitter.java @@ -21,8 +21,11 @@ package org.onap.cvc.csar.parser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedReader; import java.io.File; +import java.io.FileReader; import java.io.IOException; +import java.io.Reader; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; @@ -30,6 +33,48 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +class FileFormat { + public enum FileType { WINDOWS, UNIX, MAC, UNKNOWN } + + private static final char CR = '\r'; + private static final char LF = '\n'; + + private FileFormat() { + } + + public static FileType discover(String fileName) throws IOException { + + try (Reader reader = new BufferedReader(new FileReader(fileName))) { + return discover(reader); + } + } + + public static String getNewLine(String fileName) throws IOException { + switch(discover(fileName)) { + case WINDOWS: return String.valueOf(CR) + String.valueOf(LF); + case MAC: return String.valueOf(CR); + default: return String.valueOf(LF); + } + } + + private static FileType discover(Reader reader) throws IOException { + int c; + while ((c = reader.read()) != -1) { + switch(c) { + case LF: return FileType.UNIX; + case CR: { + if (reader.read() == LF) + return FileType.WINDOWS; + else + return FileType.MAC; + } + default: continue; + } + } + return FileType.UNKNOWN; + } +} + public class ManifestFileSplitter { private static final Logger LOG = LoggerFactory.getLogger(ManifestFileSplitter.class); @@ -41,7 +86,7 @@ public class ManifestFileSplitter { try (Stream<String> stream = Files.lines(Paths.get(fileName))) { List<String> lines = stream.collect(Collectors.toList()); - return createManifestFileModel(data, cms, lines); + return createManifestFileModel(data, cms, lines, FileFormat.getNewLine(fileName)); } catch (IOException e) { LOG.error("Unable to process manifest file!", e); @@ -49,7 +94,7 @@ public class ManifestFileSplitter { } } - private ManifestFileModel createManifestFileModel(List<String> data, List<String> cms, List<String> lines) { + private ManifestFileModel createManifestFileModel(List<String> data, List<String> cms, List<String> lines, String newLine) { boolean isCmsSection = false; for (String line : lines) { @@ -63,6 +108,6 @@ public class ManifestFileSplitter { data.add(line); } } - return new ManifestFileModel(data, cms); + return new ManifestFileModel(data, cms, newLine); } } 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: "<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/FileArchiveTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/FileArchiveTest.java index 738b4f6..1c66bbe 100644 --- a/csarvalidation/src/test/java/org/onap/cvc/csar/FileArchiveTest.java +++ b/csarvalidation/src/test/java/org/onap/cvc/csar/FileArchiveTest.java @@ -66,4 +66,37 @@ public class FileArchiveTest { assertTrue(workspace.getPathToCmsFile().isPresent()); } -}
\ No newline at end of file + @Test + public void shouldUnpackCsarNoDirectoryEntry() throws URISyntaxException, IOException { + /* + * We should be able to unpack the csar with the following simlary zip entries: + * $ unzip -l /tmp/output1.csar + * Archive: /tmp/output1.csar + * Length Date Time Name + * --------- ---------- ----- ---- + * 0 2019-11-01 14:29 ChangeLog.txt + * 1143 2019-11-01 14:29 test.crt + * 782 2019-11-01 14:29 test_entry.yaml + * 0 2019-11-01 14:29 Tests/test + * 1516 2019-11-12 09:52 test_entry.mf + * 237 2019-11-12 09:52 TOSCA-Metadata/TOSCA.meta + * --------- ------- + * 3678 7 files + */ + + // given + String absolutePath = folder.getRoot().getAbsolutePath(); + + // when + FileArchive.Workspace workspace = new FileArchive(absolutePath).unpack(absoluteFilePath("vnf/noDirectoryEntry.csar")); + + // then + assertFalse(workspace.isZip()); + assertTrue(workspace.getRootFolder().isPresent()); + assertTrue(workspace.getPathToCsarFolder().isPresent()); + assertFalse(workspace.getPathToCertFile().isPresent()); + assertFalse(workspace.getPathToCmsFile().isPresent()); + } + + +} 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<CSARArchive.CSARError> errors = testCase.getErrors(); + final List<CSARError> 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<CSARArchive.CSARError> errors = testCase.getErrors(); - assertThat(errors.size()).isEqualTo(4); + final List<CSARError> 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<CSARArchive.CSARError> errors = testCase.getErrors(); + final List<CSARError> 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<CSARArchive.CSARError> errors = testCase.getErrors(); + final List<CSARError> 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<CSARArchive.CSARError> errors = testCase.getErrors(); + final List<CSARError> 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<CSARError> 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 + * <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 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<CSARError> 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<CSARError> 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<CSARError> 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<CSARError> 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/java/org/onap/cvc/csar/parser/ManifestFileSplitterTest.java b/csarvalidation/src/test/java/org/onap/cvc/csar/parser/ManifestFileSplitterTest.java index b530691..11cddbe 100644 --- a/csarvalidation/src/test/java/org/onap/cvc/csar/parser/ManifestFileSplitterTest.java +++ b/csarvalidation/src/test/java/org/onap/cvc/csar/parser/ManifestFileSplitterTest.java @@ -21,19 +21,27 @@ import org.assertj.core.api.Assertions; import org.junit.Test; import java.io.File; +import java.net.URISyntaxException; + +import static org.onap.cvc.csar.cc.sol004.IntegrationTestUtils.absoluteFilePath; /* How to sing files see to README.txt file into test/resources folder */ public class ManifestFileSplitterTest { - @Test - public void shouldSplitManifestFileOnDataPartAndCMS() { - File file = new File("./src/test/resources/cvc/csar/parser/MainServiceTemplate.mf"); + private ManifestFileModel getModel(String resourceFilePath) throws URISyntaxException { + File file = new File(absoluteFilePath(resourceFilePath)); ManifestFileSplitter manifestFileSplitter = new ManifestFileSplitter(); + return manifestFileSplitter.split(file); + } - ManifestFileModel manifestFileModel = manifestFileSplitter.split(file); + @Test + public void shouldSplitManifestFileOnDataPartAndCMS() throws URISyntaxException { + String resource = "cvc/csar/parser/MainServiceTemplate.mf"; + ManifestFileModel manifestFileModel = getModel(resource); + Assertions.assertThat(manifestFileModel.getNewLine()).isEqualTo("\n"); Assertions.assertThat(manifestFileModel.getData()).contains("metadata:", " pnfd_name: RadioNode", " pnfd_provider: Ericsson", @@ -47,4 +55,11 @@ public class ManifestFileSplitterTest { "-----END CMS-----" ); } + + @Test + public void shouldBeWindowsStyle() throws URISyntaxException { + String resource = "cvc/csar/parser/MainServiceTemplate.windows.mf"; + ManifestFileModel manifestFileModel = getModel(resource); + Assertions.assertThat(manifestFileModel.getNewLine()).isEqualTo("\r\n"); + } } diff --git a/csarvalidation/src/test/resources/cvc/csar/parser/MainServiceTemplate.windows.mf b/csarvalidation/src/test/resources/cvc/csar/parser/MainServiceTemplate.windows.mf new file mode 100644 index 0000000..5703942 --- /dev/null +++ b/csarvalidation/src/test/resources/cvc/csar/parser/MainServiceTemplate.windows.mf @@ -0,0 +1,10 @@ +metadata:
+ pnfd_name: RadioNode
+ pnfd_provider: Ericsson
+ pnfd_archive_version: 1.0
+ pnfd_release_date_time: 2019-01-14T11:25:00+00:00
+
+-----BEGIN CMS-----
+MIIGDAYJKoZIhvcNAQcCoIIF/TCCBfkCAQExDTALBglghkgBZQMEAgEwCwYJKoZI
+hvcNAQcBoIIDRTCCA0EwggIpAhRJ6KO7OFR2BuRDZwcd2TT4/wrEqDANBgkqhkiG
+-----END CMS-----
diff --git a/csarvalidation/src/test/resources/pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar b/csarvalidation/src/test/resources/pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar Binary files differnew file mode 100644 index 0000000..88ea0ce --- /dev/null +++ b/csarvalidation/src/test/resources/pnf/r146092/missingYamlFileReferedInSourceSessionOfManifest.csar diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingFieldsInNonManoArtifactManifest.csar b/csarvalidation/src/test/resources/pnf/r972082/missingFieldsInNonManoArtifactManifest.csar Binary files differnew file mode 100644 index 0000000..2d157d1 --- /dev/null +++ b/csarvalidation/src/test/resources/pnf/r972082/missingFieldsInNonManoArtifactManifest.csar diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingPnfSoftwareVersionInYamlFile.csar b/csarvalidation/src/test/resources/pnf/r972082/missingPnfSoftwareVersionInYamlFile.csar Binary files differnew file mode 100644 index 0000000..6142499 --- /dev/null +++ b/csarvalidation/src/test/resources/pnf/r972082/missingPnfSoftwareVersionInYamlFile.csar diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingVersionInPnfSoftwareVersionInformation.csar b/csarvalidation/src/test/resources/pnf/r972082/missingVersionInPnfSoftwareVersionInformation.csar Binary files differnew file mode 100644 index 0000000..b2c9d03 --- /dev/null +++ b/csarvalidation/src/test/resources/pnf/r972082/missingVersionInPnfSoftwareVersionInformation.csar diff --git a/csarvalidation/src/test/resources/pnf/r972082/missingYamlFileReferedInSourceSessionOfManifest.csar b/csarvalidation/src/test/resources/pnf/r972082/missingYamlFileReferedInSourceSessionOfManifest.csar Binary files differnew file mode 100644 index 0000000..402ea13 --- /dev/null +++ b/csarvalidation/src/test/resources/pnf/r972082/missingYamlFileReferedInSourceSessionOfManifest.csar diff --git a/csarvalidation/src/test/resources/pnf/r972082/validFile.csar b/csarvalidation/src/test/resources/pnf/r972082/validFile.csar Binary files differnew file mode 100644 index 0000000..11d1945 --- /dev/null +++ b/csarvalidation/src/test/resources/pnf/r972082/validFile.csar diff --git a/csarvalidation/src/test/resources/vnf/noDirectoryEntry.csar b/csarvalidation/src/test/resources/vnf/noDirectoryEntry.csar Binary files differnew file mode 100644 index 0000000..1868264 --- /dev/null +++ b/csarvalidation/src/test/resources/vnf/noDirectoryEntry.csar |