From 398dcd3e75651e047e307a3207fb2b8dc1207ab0 Mon Sep 17 00:00:00 2001 From: Bogumil Zebek Date: Wed, 20 Jan 2021 14:53:39 +0100 Subject: Add release parameter to rules - All vnf/pnf rules where updated. Release parameter was added into the info->metadata section. - VNFSDK validation logic supports optional release parameter. Parameter defines which rules should be used during validation process. By default: all rules are used during validation process. --release parameter defines which rules (parent with ancestors) should be used. For example: if user run validation with --release=dublin, then amsterdam, casablanca and dublin rules will be used during validation. Rules order is defined in the vnfreqs.properties file. Change-Id: I3e9dc1e7a899fa51c266808cbcb73e04a2e252cc Issue-ID: VNFSDK-731 Signed-off-by: Zebek Bogumil --- .../main/java/org/onap/cvc/csar/CsarValidator.java | 156 +++++++++++++++++++++ .../java/org/onap/cvc/csar/ReleasesResolver.java | 62 ++++++++ .../java/org/onap/cvc/csar/RulesToValidate.java | 40 ++++++ .../java/org/onap/cvc/csar/VTPValidateCSAR.java | 123 ++++++---------- .../main/java/org/onap/cvc/csar/oclip/Command.java | 43 ++++++ .../org/onap/cvc/csar/oclip/CommandFactory.java | 61 ++++++++ 6 files changed, 403 insertions(+), 82 deletions(-) create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/CsarValidator.java create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/ReleasesResolver.java create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/RulesToValidate.java create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/oclip/Command.java create mode 100644 csarvalidation/src/main/java/org/onap/cvc/csar/oclip/CommandFactory.java (limited to 'csarvalidation/src/main/java/org/onap/cvc') diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/CsarValidator.java b/csarvalidation/src/main/java/org/onap/cvc/csar/CsarValidator.java new file mode 100644 index 0000000..cee45fe --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/CsarValidator.java @@ -0,0 +1,156 @@ +/* + * Copyright 2021 Nokia + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.cvc.csar; + +import org.apache.commons.lang3.tuple.Pair; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cvc.csar.oclip.Command; +import org.onap.cvc.csar.oclip.CommandFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class CsarValidator { + + private final CommandFactory commandFactory; + private final List ignoreCodes; + private final List activeRules; + private final ReleasesResolver releasesResolver; + private final RulesToValidate rulesToValidate; + + public CsarValidator(CommandFactory commandFactory, List ignoreCodes, + List activeRules, ReleasesResolver releasesResolver, + RulesToValidate rulesToValidate) { + this.commandFactory = commandFactory; + this.ignoreCodes = ignoreCodes; + this.activeRules = activeRules; + this.releasesResolver = releasesResolver; + this.rulesToValidate = rulesToValidate; + } + + Pair> validate(ValidationContext validationContext) { + + boolean overallPass = true; + List results = new ArrayList<>(); + + final List rules = getRulesToExecute(); + + for (String rule : rules) { + final Pair> pair = executeValidation(releasesResolver, ignoreCodes, rule, validationContext); + overallPass &= pair.getLeft(); + results.addAll(pair.getRight()); + } + + return Pair.of(overallPass, results); + } + + private List getRulesToExecute() { + final List rulesToExecute = rulesToValidate.get(); + + return activeRules.stream().filter( + it -> rulesToExecute.isEmpty() || rulesToExecute.contains(it) + ).collect(Collectors.toList()); + } + + private Pair> executeValidation( + ReleasesResolver releasesResolver, List ignoreCodes, + String reqName, ValidationContext validationContext) { + + boolean overallPass = true; + List results = new ArrayList<>(); + VTPValidateCSAR.CSARValidation.Result result = new VTPValidateCSAR.CSARValidation.Result(); + result.setVnfreqName(reqName); + + try { + Command cmd = getCommand(reqName, validationContext); + if (releasesResolver.resolveWithAncestors(validationContext.getRelease()).contains(cmd.getRelease())) { + final List errors = cmd.run(); + + result.setDescription(cmd.getDescription()); + + final Pair, List> segregateErrors = segregate(errors, ignoreCodes, reqName); + overallPass = segregateErrors.getLeft().isEmpty(); + result.addErrors(segregateErrors.getLeft()); + result.addErrorsAsWarnings(segregateErrors.getRight()); + result.setPassed(result.getErrors().isEmpty()); + results.add(result); + } + } catch (Exception e) { + result.setPassed(false); + overallPass = false; + result.addError(new CSARArchive.CSARErrorUnknown(e.getMessage())); + results.add(result); + } + return Pair.of(overallPass, results); + } + + private Command getCommand(String reqName, ValidationContext validationContext) throws OnapCommandException { + return validationContext.isPnf() ? commandFactory.createForPnf(reqName, validationContext.getPathToCsar(), validationContext.getProduct()) : commandFactory.createForVnf(reqName, validationContext.getPathToCsar(), validationContext.getProduct()); + } + + private Pair, List> segregate( + List errors, List ignoreCodes, String reqName){ + + final List errorsList = new ArrayList<>(); + final List warningsList = new ArrayList<>(); + + for (CSARArchive.CSARError error : errors) { + if (!isErrorIgnored(ignoreCodes, reqName, error)) { + errorsList.add(error); + } else { + warningsList.add(error); + } + } + + return Pair.of(errorsList,warningsList); + } + + private boolean isErrorIgnored(List ignoreCodes, String reqName, CSARArchive.CSARError error) { + return ignoreCodes.contains(error.getCode()) || ignoreCodes.contains(reqName + "-" + error.getCode()); + } + + public static class ValidationContext { + private final String pathToCsar; + private final String product; + private final String release; + private final boolean isPnf; + + + public ValidationContext(String pathToCsar, String product, String release, boolean isPnf) { + this.pathToCsar = pathToCsar; + this.product = product; + this.release = release; + this.isPnf = isPnf; + } + + public String getPathToCsar() { + return pathToCsar; + } + + public String getProduct() { + return product; + } + + public String getRelease() { + return release; + } + + public boolean isPnf() { + return isPnf; + } + } +} diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/ReleasesResolver.java b/csarvalidation/src/main/java/org/onap/cvc/csar/ReleasesResolver.java new file mode 100644 index 0000000..4a9c8d1 --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/ReleasesResolver.java @@ -0,0 +1,62 @@ +/* + * Copyright 2021 Nokia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.cvc.csar; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class ReleasesResolver { + public static final String SPLIT_BY_COMMA = ","; + public static final String SPECIAL_KEYWORD = "latest"; + public static final int NOT_FOUND = -1; + private final String[] releaseInOrder; + + private ReleasesResolver(String[] releaseInOrder) { + this.releaseInOrder = releaseInOrder; + } + + public static ReleasesResolver create(String releaseInOrder) { + return new ReleasesResolver(releaseInOrder.split(SPLIT_BY_COMMA)); + } + + public List resolveWithAncestors(String release) { + final int index = findIndexOf(release); + if (isReleaseAvailable(index)) { + throw new IllegalArgumentException(String.format("Release '%s' is not defined at the releases.order list in a vnfreqs.properties file!", release)); + } + return new LinkedList<>(getElements(this.releaseInOrder, index)); + } + + private boolean isReleaseAvailable(int index) { + return index == NOT_FOUND; + } + + private List getElements(String[] elements, int index) { + return Arrays.asList(elements).subList(0, index + 1); + } + + private int findIndexOf(String release) { + if (release.equals(SPECIAL_KEYWORD)) { + return getIndexOfLastElement(); + } + return Arrays.asList(this.releaseInOrder).indexOf(release); + } + + private int getIndexOfLastElement() { + return this.releaseInOrder.length - 1; + } +} diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/RulesToValidate.java b/csarvalidation/src/main/java/org/onap/cvc/csar/RulesToValidate.java new file mode 100644 index 0000000..7ca0dc5 --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/RulesToValidate.java @@ -0,0 +1,40 @@ +/* + * Copyright 2021 Nokia + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.cvc.csar; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class RulesToValidate { + private static final String RULES_ATTRIBUTE_SEPARATOR = ","; + private final String rulesToValidate; + + public RulesToValidate(String rulesToValidate) { + this.rulesToValidate = rulesToValidate; + } + + public List get(){ + List rules = new ArrayList<>(); + + if(!rulesToValidate.isEmpty()){ + String[] listOfRulesToValidate = rulesToValidate.split(RULES_ATTRIBUTE_SEPARATOR); + rules.addAll(Arrays.asList(listOfRulesToValidate)); + } + + return rules; + } +} diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java b/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java index 637a454..2e99be3 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/VTPValidateCSAR.java @@ -18,19 +18,21 @@ package org.onap.cvc.csar; import com.google.gson.Gson; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Properties; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.tuple.Pair; import org.onap.cli.fw.cmd.OnapCommand; import org.onap.cli.fw.error.OnapCommandException; import org.onap.cli.fw.error.OnapCommandExecutionFailed; -import org.onap.cli.fw.error.OnapCommandInvalidParameterValue; -import org.onap.cli.fw.input.OnapCommandParameter; import org.onap.cli.fw.output.OnapCommandResultType; -import org.onap.cli.fw.registrar.OnapCommandRegistrar; import org.onap.cli.fw.schema.OnapCommandSchema; import org.onap.cvc.csar.CSARArchive.CSARError; +import org.onap.cvc.csar.oclip.CommandFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,9 +42,9 @@ import org.slf4j.LoggerFactory; @OnapCommandSchema(schema = "vtp-validate-csar.yaml") public class VTPValidateCSAR extends OnapCommand { - private static Gson gson = new Gson(); + private static final Gson GSON = new Gson(); private static final Logger LOG = LoggerFactory.getLogger(VTPValidateCSAR.class); - private static final String RULES_ATTRIBUTE_SEPARATOR = ","; + private static final String RELEASE_ATTRIBUTE_NAME = "release"; private static final String PNF_ATTRIBUTE_NAME = "pnf"; private static final String CSAR_ATTRIBUTE_NAME = "csar"; private static final String RULES_ATTRIBUTE_NAME = "rules"; @@ -107,8 +109,8 @@ public class VTPValidateCSAR extends OnapCommand { private boolean passed; private String vnfreqName; private String description; - private List errors = new ArrayList<>(); - private List warnings = new ArrayList<>(); + private final List errors = new ArrayList<>(); + private final List warnings = new ArrayList<>(); public boolean isPassed() { return passed; @@ -149,6 +151,14 @@ public class VTPValidateCSAR extends OnapCommand { public void addErrorAsWarning(CSARError error) { this.warnings.add(error); } + + public void addErrors(List errors) { + this.errors.addAll(errors); + } + + public void addErrorsAsWarnings(List warnings) { + this.warnings.addAll(warnings); + } } private List results = new ArrayList<>(); @@ -206,11 +216,11 @@ public class VTPValidateCSAR extends OnapCommand { } } - private static Properties properties = new Properties(); + private static final Properties PROPERTIES = new Properties(); static { try { - properties.load(VTPValidateCSAR.class.getResourceAsStream("/vnfreqs.properties")); + PROPERTIES.load(VTPValidateCSAR.class.getResourceAsStream("/vnfreqs.properties")); } catch (Exception e) { LOG.error(e.getMessage(), e); } @@ -219,13 +229,14 @@ public class VTPValidateCSAR extends OnapCommand { @Override protected void run() throws OnapCommandException { //Read the input arguments - String path = (String) getParametersMap().get(CSAR_ATTRIBUTE_NAME).getValue(); + String release = (String) getParametersMap().get(RELEASE_ATTRIBUTE_NAME).getValue(); + String pathToCsarFile = (String) getParametersMap().get(CSAR_ATTRIBUTE_NAME).getValue(); boolean isPnf = (boolean) getParametersMap().get(PNF_ATTRIBUTE_NAME).getValue(); String rulesToValidate = (String) getParametersMap().get(RULES_ATTRIBUTE_NAME).getValue(); boolean overallPass = true; try (CSARArchive csar = isPnf ? new PnfCSARArchive() : new CSARArchive()) { - csar.init(path); + csar.init(pathToCsarFile); csar.parse(); CSARValidation validation = createCsarValidationFor(csar); @@ -248,26 +259,11 @@ public class VTPValidateCSAR extends OnapCommand { validation.getResults().add(resultSOL004); - String keyReqs = isPnf ? "pnfreqs.enabled" : "vnfreqs.enabled"; - List activeRules = this.getPropertiesList(keyReqs); - if(rulesToValidate.isEmpty()) { - // Run thru the vnfreqs requirement checks - for (String vnfreq : activeRules) { - CSARValidation.Result result = new CSARValidation.Result(); - result.setVnfreqName(vnfreq); - overallPass = validateVnfOrPnf(path, validation, ignoreCodes, vnfreq, result, isPnf, overallPass); - } - } else { - // Validate selected rules - String[] listOfRulesToValidate = rulesToValidate.split(RULES_ATTRIBUTE_SEPARATOR); - for (String rule : listOfRulesToValidate) { - if(activeRules.contains(rule)) { - CSARValidation.Result result = new CSARValidation.Result(); - result.setVnfreqName(rule); - overallPass = validateVnfOrPnf(path, validation, ignoreCodes, rule, result, isPnf, overallPass); - } - } - } + final Pair> validationResult = + validate(pathToCsarFile, release, isPnf, ignoreCodes, new RulesToValidate(rulesToValidate)); + + overallPass &= validationResult.getLeft(); + validation.getResults().addAll(validationResult.getRight()); validation.setDate(new Date().toString()); validation.setCriteria(overallPass ? "PASS" : "FAILED"); @@ -279,39 +275,15 @@ public class VTPValidateCSAR extends OnapCommand { } } - private boolean validateVnfOrPnf(String path, CSARValidation validation, - List ignoreCodes, String vnfreq, CSARValidation.Result result, boolean isPnf, boolean overallPass) { - try { - String command = "csar-validate-" + vnfreq; - OnapCommand cmd = OnapCommandRegistrar.getRegistrar().get(command, this.getInfo().getProduct()); - cmd.getParametersMap().get("csar").setValue(path); - setPnfValueIfAvailable(isPnf, cmd); - - result.setDescription(cmd.getDescription()); - cmd.execute(); - - for (CSARError error : (List) cmd.getResult().getOutput()) { - if (!isErrorIgnored(ignoreCodes, vnfreq, error)) { - result.addError(error); - overallPass = false; - } else { - result.addErrorAsWarning(error); - } - } - - result.setPassed(result.getErrors().isEmpty()); - validation.getResults().add(result); - } catch (Exception e) { - result.setPassed(false); - overallPass = false; - result.addError(new CSARArchive.CSARErrorUnknown(e.getMessage())); - validation.getResults().add(result); - } - return overallPass; - } + private Pair> validate(String path, String release, boolean isPnf, List ignoreCodes, RulesToValidate rulesToValidate) { + final String keyReqs = isPnf ? "pnfreqs.enabled" : "vnfreqs.enabled"; + final List activeRules = this.getPropertiesList(keyReqs); + final String releasesOrder = PROPERTIES.getProperty("releases.order"); + final ReleasesResolver releasesResolver = ReleasesResolver.create(releasesOrder); + final String product = this.getInfo().getProduct(); - private boolean isErrorIgnored(List ignoreCodes, String vnfreq, CSARError error) { - return ignoreCodes.contains(error.getCode()) || ignoreCodes.contains(vnfreq + "-" + error.getCode()); + return new CsarValidator(new CommandFactory(), ignoreCodes, activeRules, releasesResolver, rulesToValidate) + .validate(new CsarValidator.ValidationContext(path, product, release, isPnf)); } static CSARValidation createCsarValidationFor(CSARArchive csar) { @@ -325,33 +297,20 @@ public class VTPValidateCSAR extends OnapCommand { return validation; } - private void setOperationResult(CSARValidation validation) throws Exception { //NOSONAR + private void setOperationResult(CSARValidation validation) { this.getResult().getRecordsMap().get("vnf").getValues().add( - gson.toJson(validation.getVnf())); + GSON.toJson(validation.getVnf())); this.getResult().getRecordsMap().get("date").getValues().add(validation.getDate()); this.getResult().getRecordsMap().get("criteria").getValues().add(validation.getCriteria()); this.getResult().getRecordsMap().get("results").getValues().add( - gson.toJson(validation.getResults())); + GSON.toJson(validation.getResults())); - this.getResult().setOutput(gson.toJson(validation)); + this.getResult().setOutput(GSON.toJson(validation)); this.getResult().setType(OnapCommandResultType.TEXT); } - private void setPnfValueIfAvailable(boolean isPnf, OnapCommand cmd) throws OnapCommandInvalidParameterValue { - final OnapCommandParameter pnf = cmd.getParametersMap().get(PNF_ATTRIBUTE_NAME); - if (pnf != null) { - pnf.setValue(isPnf); - } - } - private List getPropertiesList(String key) { - String[] enabledReqs = properties.getProperty(key, "").split(","); - List list = new ArrayList<>(); - for (String req : enabledReqs) { - if (!req.isEmpty()) { - list.add(req); - } - } - return list; + String[] enabledReqs = PROPERTIES.getProperty(key, "").split(","); + return Arrays.stream(enabledReqs).filter(it->!it.isEmpty()).collect(Collectors.toList()); } } diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/oclip/Command.java b/csarvalidation/src/main/java/org/onap/cvc/csar/oclip/Command.java new file mode 100644 index 0000000..6c43cc5 --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/oclip/Command.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021 Nokia + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.cvc.csar.oclip; + +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cvc.csar.CSARArchive; + +import java.util.List; + +public class Command { + private final OnapCommand cmd; + + public Command(OnapCommand cmd) { + this.cmd = cmd; + } + + public List run() throws OnapCommandException { + cmd.execute(); + return (List) cmd.getResult().getOutput(); + } + + public String getDescription() { + return cmd.getDescription(); + } + + public String getRelease(){ + return cmd.getInfo().getMetadata().getOrDefault("release","unknown"); + } +} diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/oclip/CommandFactory.java b/csarvalidation/src/main/java/org/onap/cvc/csar/oclip/CommandFactory.java new file mode 100644 index 0000000..18c1a2c --- /dev/null +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/oclip/CommandFactory.java @@ -0,0 +1,61 @@ +/* + * Copyright 2021 Nokia + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.cvc.csar.oclip; + +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandInvalidParameterValue; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.registrar.OnapCommandRegistrar; + + +public class CommandFactory { + + private static final String PNF_ATTRIBUTE_NAME = "pnf"; + private static final String COMMAND_PREFIX = "csar-validate-"; + private static final String CSAR_PARAM_NAME = "csar"; + + public Command createForVnf(String req, String pathToCsarFile, String product) throws OnapCommandException { + OnapCommand cmd = createCommand(req, pathToCsarFile, product); + return new Command(cmd); + } + + public Command createForPnf(String req, String pathToCsarFile, String product) throws OnapCommandException { + OnapCommand cmd = createCommand(req, pathToCsarFile, product); + markCommandAsPnf(cmd); + return new Command(cmd); + } + + private OnapCommand createCommand(String req, String pathToCsarFile, String product) throws OnapCommandException { + String command = createCommandFor(req); + OnapCommand cmd = OnapCommandRegistrar.getRegistrar().get(command, product); + setPathToCsar(pathToCsarFile, cmd); + return cmd; + } + + private String createCommandFor(String req) { + return COMMAND_PREFIX + req; + } + + private void setPathToCsar(String pathToCsarFile, OnapCommand cmd) throws OnapCommandInvalidParameterValue { + cmd.getParametersMap().get(CSAR_PARAM_NAME).setValue(pathToCsarFile); + } + + private void markCommandAsPnf(OnapCommand cmd) throws OnapCommandInvalidParameterValue { + final OnapCommandParameter pnf = cmd.getParametersMap().get(PNF_ATTRIBUTE_NAME); + pnf.setValue(true); + } +} -- cgit 1.2.3-korg