From 8c6980a4b3bf7ddcff8cc5757c29961385222606 Mon Sep 17 00:00:00 2001 From: "mark.j.leonard" Date: Fri, 22 Mar 2019 14:49:33 +0000 Subject: [PATCH] Simplify VNF Vendor Image extraction Refactoring of the software version extraction routines to reduce complexity. Pass the NodeTemplates directly to the extractSoftwareVersions() method and move the exception handling up the calling stack. Remove the creation/usage of an intermediate Pair object. Query for the Service VF list once only. Use Streams rather than converting from Stream to List and back. This change will simplify future work: either to convert sdc-tosca API methods (that will be deprecated), or to use an alternative parser. Change-Id: I745ced9e6095f389ee1bede37e8480dfaf65716a Issue-ID: AAI-2281 Signed-off-by: mark.j.leonard --- .../csar/vnfcatalog/VnfVendorImageExtractor.java | 195 +++++++++------------ .../vnfcatalog/VnfVendorImageExtractorTest.java | 22 +-- 2 files changed, 93 insertions(+), 124 deletions(-) diff --git a/src/main/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractor.java b/src/main/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractor.java index c272b35..49dd19f 100644 --- a/src/main/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractor.java +++ b/src/main/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractor.java @@ -24,26 +24,26 @@ package org.onap.aai.babel.csar.vnfcatalog; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; -import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.time.StopWatch; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.onap.aai.babel.logging.ApplicationMsgs; import org.onap.aai.babel.logging.LogHelper; import org.onap.aai.babel.service.data.BabelArtifact; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.tosca.parser.enums.SdcTypes; import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; +import org.onap.sdc.tosca.parser.impl.SdcPropertyNames; import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory; import org.onap.sdc.toscaparser.api.NodeTemplate; -import org.onap.sdc.toscaparser.api.SubstitutionMappings; /** * This class is responsible for extracting Virtual Network Function (VNF) information from a TOSCA 1.1 CSAR package. @@ -97,6 +97,9 @@ public class VnfVendorImageExtractor { // The name of the property (for a VNF Configuration type) storing the Vendor Information private static final String VNF_CONF_TYPE_PROPERTY_VENDOR_INFO_CONTAINER = "allowed_flavors"; + // Name of property key that contains the Vendor Information + private static final String VENDOR_INFO = "vendor_info"; + // Name of property key that contains the value of model of the Vendor application private static final String VENDOR_MODEL = "vendor_model"; @@ -177,150 +180,124 @@ public class VnfVendorImageExtractor { * Build VNF Vendor Image Configurations for the VNF Configuration node (if present) in the CSAR file referenced by * the supplied Path. * - * @param csarFilepath the path to the CSAR file + * @param csarFilepath + * the path to the CSAR file * @return a List of Vendor Image Configurations * @throws SdcToscaParserException * @throws ToscaToCatalogException * @throws InvalidNumberOfNodesException */ private List createVendorImageConfigurations(String csarFilepath) - throws SdcToscaParserException, ToscaToCatalogException, InvalidNumberOfNodesException { - List vendorImageConfigurations = new ArrayList<>(); - + throws SdcToscaParserException, InvalidNumberOfNodesException { ISdcCsarHelper csarHelper = SdcToscaParserFactory.getInstance().getSdcCsarHelper(csarFilepath); - NodeTemplate vnfConfigurationNode = findVnfConfigurationNode(csarHelper); - - applicationLogger.info(ApplicationMsgs.DISTRIBUTION_EVENT, - String.format("Found VNF Configuration node \"%s\"", vnfConfigurationNode)); - if (vnfConfigurationNode != null) { - for (NodeTemplate node : csarHelper.getServiceVfList()) { - vendorImageConfigurations.addAll(buildVendorImageConfigurations(vnfConfigurationNode, node)); - } - } + List serviceVfList = csarHelper.getServiceNodeTemplates().stream() // + .filter(filterOnType(SdcTypes.VF)).collect(Collectors.toList()); - return vendorImageConfigurations; - } - - /** - * Find VNF configuration node. - * - * @param csarHelper the csar helper - * @return the node template - * @throws InvalidNumberOfNodesException - */ - private NodeTemplate findVnfConfigurationNode(ISdcCsarHelper csarHelper) throws InvalidNumberOfNodesException { - List nodeTemplates = csarHelper.getServiceNodeTemplateBySdcType(SdcTypes.VF); - applicationLogger.debug(nodeTemplates.toString()); - - List configNodes = nodeTemplates.stream() // - .map(serviceNodeTemplate -> { - String uuid = csarHelper.getNodeTemplateCustomizationUuid(serviceNodeTemplate); - applicationLogger.debug(serviceNodeTemplate + " Customization UUID is " + uuid); - return csarHelper.getVnfConfig(uuid); - }) // + List vnfConfigs = serviceVfList.stream() + .flatMap(vf -> vf.getSubMappingToscaTemplate().getNodeTemplates().stream() + .filter(filterOnType(SdcTypes.VFC)) // + .filter(vfc -> vfc.getType().endsWith("VnfConfiguration"))) .filter(Objects::nonNull) // .collect(Collectors.toList()); - if (configNodes.size() > 1) { - throw new InvalidNumberOfNodesException("Only one vnf configuration node is allowed however " - + configNodes.size() + " nodes were found in the csar."); + if (!vnfConfigs.isEmpty()) { + NodeTemplate vnfConfigurationNode = vnfConfigs.get(0); + + applicationLogger.info(ApplicationMsgs.DISTRIBUTION_EVENT, + String.format("Found VNF Configuration node \"%s\"", vnfConfigurationNode)); + + if (vnfConfigs.size() > 1) { + throw new InvalidNumberOfNodesException("Only one VNF configuration node is allowed however " + + vnfConfigs.size() + " nodes were found in the CSAR."); + } + + return createVendorImageConfigurations(serviceVfList, vnfConfigurationNode); } - return configNodes.size() == 1 ? configNodes.get(0) : null; + return Collections.emptyList(); } /** - * Builds the Vendor image configurations. + * Build VNF Vendor Image Configurations for each Service VF, using the flavors of the specified VNF Configuration + * node. * - * @param vendorInfoNode the vendor info node - * @param node the node - * @return the list - * @throws ToscaToCatalogException if there are no software versions + * @param serviceVfList + * the Service level VF node templates + * @param vnfConfigurationNode + * the VNF node template + * @return a new List of Vendor Image Configurations */ - private List buildVendorImageConfigurations(NodeTemplate vendorInfoNode, - NodeTemplate node) throws ToscaToCatalogException { - List vendorImageConfigurations = new ArrayList<>(); + private List createVendorImageConfigurations(List serviceVfList, + NodeTemplate vnfConfigurationNode) { + List vendorImageConfigurations = Collections.emptyList(); - List softwareVersions = extractSoftwareVersions(node.getSubMappingToscaTemplate()); + Object allowedFlavorProperties = + vnfConfigurationNode.getPropertyValue(VNF_CONF_TYPE_PROPERTY_VENDOR_INFO_CONTAINER); - Consumer> buildConfigurations = - vi -> vendorImageConfigurations.addAll(softwareVersions.stream() // - .map(sv -> (new VendorImageConfiguration(vi.getRight(), vi.getLeft(), sv))) - .collect(Collectors.toList())); + if (allowedFlavorProperties instanceof Map) { + @SuppressWarnings("unchecked") + Collection>> flavorMaps = + ((Map>>) allowedFlavorProperties).values(); - String resourceVendor = node.getMetaData().getValue("resourceVendor"); - - applicationLogger.debug("Resource Vendor " + resourceVendor); - - buildVendorInfo(resourceVendor, vendorInfoNode).forEach(buildConfigurations); + vendorImageConfigurations = serviceVfList.stream() // + .flatMap(node -> buildVendorImageConfigurations(flavorMaps, node)) // + .collect(Collectors.toList()); - applicationLogger.info(ApplicationMsgs.DISTRIBUTION_EVENT, - "Built " + vendorImageConfigurations.size() + " Vendor Image Configurations"); + applicationLogger.info(ApplicationMsgs.DISTRIBUTION_EVENT, + "Built " + vendorImageConfigurations.size() + " Vendor Image Configurations"); + } return vendorImageConfigurations; } - /** - * Builds the Vendor info. - * - * @param resourceVendor the resource vendor - * @param vendorInfoNode the vendor info node - * @return the list - */ - @SuppressWarnings("unchecked") - private List> buildVendorInfo(String resourceVendor, NodeTemplate vendorInfoNode) { - Map otherFlavorProperties = - (Map) vendorInfoNode.getPropertyValue(VNF_CONF_TYPE_PROPERTY_VENDOR_INFO_CONTAINER); - - return otherFlavorProperties.keySet().stream() - .map(key -> createVendorInfoPair((Map) otherFlavorProperties.get(key), resourceVendor)) - .collect(Collectors.toList()); + private Predicate filterOnType(SdcTypes sdcType) { + return node -> (node.getMetaData() != null + && sdcType.getValue().equals(node.getMetaData().getValue(SdcPropertyNames.PROPERTY_NAME_TYPE))); } /** - * Creates the Vendor info pair. + * Builds the Vendor Image configurations. * - * @param otherFlavor the other flavor - * @param resourceVendor the resource Vendor - * @return the pair + * @param flavorMaps + * the collection of flavors and the properties for those flavors + * @param vfNodeTemplate + * the node template for the VF + * + * @return a stream of VendorImageConfiguration objects */ - private Pair createVendorInfoPair(Map otherFlavor, String resourceVendor) { - @SuppressWarnings("unchecked") - String vendorModel = otherFlavor.entrySet().stream() // - .filter(entry -> "vendor_info".equals(entry.getKey())) - .map(e -> ((Map) e.getValue()).get(VENDOR_MODEL)) // - .findFirst().orElse(null); - - applicationLogger.debug("Creating Vendor info pair object for vendorModel = " + vendorModel - + " and resourceVendor = " + resourceVendor); + private Stream buildVendorImageConfigurations( + Collection>> flavorMaps, NodeTemplate vfNodeTemplate) { + String resourceVendor = vfNodeTemplate.getMetaData().getValue("resourceVendor"); + applicationLogger.debug("Resource Vendor " + resourceVendor); - return new ImmutablePair<>(resourceVendor, vendorModel); + List softwareVersions = + extractSoftwareVersions(vfNodeTemplate.getSubMappingToscaTemplate().getNodeTemplates()); + applicationLogger.debug("Software Versions: " + softwareVersions); + + return flavorMaps.stream() // + .map(value -> value.entrySet().stream() // + .filter(entry -> VENDOR_INFO.equals(entry.getKey())) // + .map(e -> e.getValue().get(VENDOR_MODEL)) // + .findFirst()) // + .flatMap(vendorModel -> softwareVersions.stream().map( + version -> new VendorImageConfiguration(vendorModel.orElse(null), resourceVendor, version))); } /** - * Extract software versions. + * Extract Image software versions from node templates. * - * @param sm the substitution mappings + * @param nodeTemplates + * the node templates to search for software versions * @return a List of Software Version Strings - * @throws ToscaToCatalogException the tosca to catalog exception */ @SuppressWarnings("unchecked") - List extractSoftwareVersions(SubstitutionMappings sm) throws ToscaToCatalogException { - applicationLogger.debug("Extracting software versions from " + sm); - - List imagesNodes = sm.getNodeTemplates().stream() - .filter(nodeTemplate -> nodeTemplate.getPropertyValue(IMAGES) != null).collect(Collectors.toList()); - - if (imagesNodes != null && !imagesNodes.isEmpty()) { - return imagesNodes.stream() - .flatMap(imagesNode -> ((Map) imagesNode.getPropertyValue(IMAGES)) // - .entrySet().stream()) - .map(property -> findSoftwareVersion((Map) property.getValue())) - .collect(Collectors.toList()); - } else { - throw new ToscaToCatalogException("No software versions could be found for this CSAR file"); - } + List extractSoftwareVersions(Collection nodeTemplates) { + return nodeTemplates.stream() // + .filter(nodeTemplate -> nodeTemplate.getPropertyValue(IMAGES) != null) // + .flatMap(imagesNode -> ((Map) imagesNode.getPropertyValue(IMAGES)).entrySet().stream()) + .map(property -> findSoftwareVersion((Map) property.getValue())) + .collect(Collectors.toList()); } /** diff --git a/src/test/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractorTest.java b/src/test/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractorTest.java index a6f98b8..7a076c5 100644 --- a/src/test/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractorTest.java +++ b/src/test/java/org/onap/aai/babel/csar/vnfcatalog/VnfVendorImageExtractorTest.java @@ -95,24 +95,16 @@ public class VnfVendorImageExtractorTest { SdcToscaHelper helper = new SdcToscaHelper(); List versions; - try { - versions = extractor.extractSoftwareVersions(helper.buildMappings()); - assertThat(versions.size(), is(0)); - } catch (ToscaToCatalogException e) { - assertThat(e.getMessage(), containsString("No software versions")); - } + versions = extractor.extractSoftwareVersions(helper.buildMappings().getNodeTemplates()); + assertThat(versions.size(), is(0)); helper.addNodeTemplate(); - try { - versions = extractor.extractSoftwareVersions(helper.buildMappings()); - assertThat(versions.size(), is(0)); - } catch (ToscaToCatalogException e) { - assertThat(e.getMessage(), containsString("No software versions")); - } + versions = extractor.extractSoftwareVersions(helper.buildMappings().getNodeTemplates()); + assertThat(versions.size(), is(0)); helper.addNodeTemplate("string"); try { - versions = extractor.extractSoftwareVersions(helper.buildMappings()); + versions = extractor.extractSoftwareVersions(helper.buildMappings().getNodeTemplates()); assertThat(versions.size(), is(0)); } catch (ClassCastException e) { assertThat(e.getMessage(), containsString("java.lang.String")); @@ -122,7 +114,7 @@ public class VnfVendorImageExtractorTest { images.put("image", "string"); helper.addNodeTemplate(images); try { - versions = extractor.extractSoftwareVersions(helper.buildMappings()); + versions = extractor.extractSoftwareVersions(helper.buildMappings().getNodeTemplates()); assertThat(versions.size(), is(1)); } catch (ClassCastException e) { assertThat(e.getMessage(), containsString("java.lang.String")); @@ -133,7 +125,7 @@ public class VnfVendorImageExtractorTest { images.put("image", image); helper = new SdcToscaHelper(); helper.addNodeTemplate(images); - versions = extractor.extractSoftwareVersions(helper.buildMappings()); + versions = extractor.extractSoftwareVersions(helper.buildMappings().getNodeTemplates()); assertThat(versions.size(), is(1)); assertThat(versions.get(0), is("1.2.3")); } -- 2.16.6