From 05e7b934ad49c54c98ce840841528a13e882f8d3 Mon Sep 17 00:00:00 2001 From: "mark.j.leonard" Date: Tue, 27 Nov 2018 16:54:33 +0000 Subject: [PATCH] Process Service-level Instance Groups Create an InstanceGroup XML model for groups of the Service topology template in the case where there is no Resource model generated. Add a test CSAR file for a Service Proxy (an unsupported type). Assert that the Service is associated with the instance-group Models. Change-Id: If76bf7a1cfb960bc8692f1e136ee85176725915e Issue-ID: AAI-1963 Signed-off-by: mark.j.leonard --- .../xml/generator/api/AaiArtifactGenerator.java | 613 +++++++++++---------- .../parser/TestArtifactGeneratorToscaParser.java | 221 ++++---- .../aai/babel/service/CsarToXmlConverterTest.java | 10 + .../java/org/onap/aai/babel/testdata/CsarTest.java | 4 +- .../compressedArtifacts/service-S1-csar.csar | Bin 0 -> 67874 bytes .../AAI-Grouping Service for Test-service-1.0.xml | 69 +++ ...ortest..ResourceInstanceGroup..0-resource-1.xml | 32 ++ ...ortest..ResourceInstanceGroup..1-resource-1.xml | 32 ++ 8 files changed, 571 insertions(+), 410 deletions(-) create mode 100644 src/test/resources/compressedArtifacts/service-S1-csar.csar create mode 100644 src/test/resources/generatedXml/AAI-Grouping Service for Test-service-1.0.xml create mode 100644 src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..0-resource-1.xml create mode 100644 src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..1-resource-1.xml diff --git a/src/main/java/org/onap/aai/babel/xml/generator/api/AaiArtifactGenerator.java b/src/main/java/org/onap/aai/babel/xml/generator/api/AaiArtifactGenerator.java index bd7144f..531a044 100644 --- a/src/main/java/org/onap/aai/babel/xml/generator/api/AaiArtifactGenerator.java +++ b/src/main/java/org/onap/aai/babel/xml/generator/api/AaiArtifactGenerator.java @@ -26,7 +26,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; - import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.onap.aai.babel.logging.ApplicationMsgs; @@ -38,6 +37,7 @@ import org.onap.aai.babel.xml.generator.data.ArtifactType; import org.onap.aai.babel.xml.generator.data.GenerationData; import org.onap.aai.babel.xml.generator.data.GeneratorUtil; import org.onap.aai.babel.xml.generator.data.GroupType; +import org.onap.aai.babel.xml.generator.data.WidgetConfigurationUtil; import org.onap.aai.babel.xml.generator.model.Model; import org.onap.aai.babel.xml.generator.model.ProvidingService; import org.onap.aai.babel.xml.generator.model.Resource; @@ -46,305 +46,324 @@ import org.onap.aai.babel.xml.generator.model.TunnelXconnectWidget; import org.onap.aai.cl.api.Logger; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory; +import org.onap.sdc.toscaparser.api.Group; import org.onap.sdc.toscaparser.api.NodeTemplate; import org.slf4j.MDC; public class AaiArtifactGenerator implements ArtifactGenerator { - private static Logger log = LogHelper.INSTANCE; - - private static final String MDC_PARAM_MODEL_INFO = "ARTIFACT_MODEL_INFO"; - private static final String GENERATOR_AAI_GENERATED_ARTIFACT_EXTENSION = "xml"; - private static final String GENERATOR_AAI_ERROR_MISSING_SERVICE_TOSCA = "Service tosca missing from list of input artifacts"; - private static final String GENERATOR_AAI_ERROR_MISSING_SERVICE_VERSION = "Cannot generate artifacts. Service version is not specified"; - private static final String GENERATOR_AAI_INVALID_SERVICE_VERSION = "Cannot generate artifacts. Service version is incorrect"; - - private AaiModelGenerator modelGenerator = new AaiModelGeneratorImpl(); - - @Override - public GenerationData generateArtifact(byte[] csarArchive, List input, - Map additionalParams) { - Path csarPath; - - try { - csarPath = createTempFile(csarArchive); - } catch (IOException e) { - log.error(ApplicationMsgs.TEMP_FILE_ERROR, e); - return createErrorData(e); - } - - try { - ArtifactGeneratorToscaParser.initWidgetConfiguration(); - ArtifactGeneratorToscaParser.initGroupFilterConfiguration(); - ISdcCsarHelper csarHelper = SdcToscaParserFactory.getInstance() - .getSdcCsarHelper(csarPath.toAbsolutePath().toString()); - return generateAllArtifacts(validateServiceVersion(additionalParams), csarHelper); - } catch (Exception e) { - log.error(ApplicationMsgs.INVALID_CSAR_FILE, e); - return createErrorData(e); - } finally { - FileUtils.deleteQuietly(csarPath.toFile()); - } - } - - private GenerationData createErrorData(Exception e) { - GenerationData generationData = new GenerationData(); - generationData.add(ArtifactType.AAI.name(), e.getMessage()); - return generationData; - } - - /** - * Generate model artifacts for the Service and its associated Resources. - * - * @param serviceVersion - * @param csarHelper - * interface to the TOSCA parser - * @return the generated Artifacts (containing XML models) - */ - private GenerationData generateAllArtifacts(final String serviceVersion, ISdcCsarHelper csarHelper) { - List serviceNodeTemplates = csarHelper.getServiceNodeTemplates(); - if (serviceNodeTemplates == null) { - throw new IllegalArgumentException(GENERATOR_AAI_ERROR_MISSING_SERVICE_TOSCA); - } - - Service serviceModel = createServiceModel(serviceVersion, csarHelper.getServiceMetadataAllProperties()); - - MDC.put(MDC_PARAM_MODEL_INFO, serviceModel.getModelName() + "," + getArtifactLabel(serviceModel)); - - List resources = generateResourceModels(csarHelper, serviceNodeTemplates, serviceModel); - - // Generate the A&AI XML model for the Service. - final String serviceArtifact = modelGenerator.generateModelFor(serviceModel); - - // Build a Babel Artifact to be returned to the caller. - GenerationData generationData = new GenerationData(); - generationData.add(getServiceArtifact(serviceModel, serviceArtifact)); - - // For each Resource, generate the A&AI XML model and then create an additional Artifact for that model. - for (Resource resource : resources) { - generateResourceArtifact(generationData, resource); - for (Resource childResource : resource.getResources()) { - if (!(childResource instanceof ProvidingService)) { - generateResourceArtifact(generationData, childResource); - } - } - } - - return generationData; - } - - /** - * Create a Service from the provided metadata - * - * @param serviceVersion - * @param properties - * @return - */ - private Service createServiceModel(final String serviceVersion, Map properties) { - log.debug("Processing (TOSCA) Service object"); - Service serviceModel = new Service(); - serviceModel.setModelVersion(serviceVersion); - serviceModel.populateModelIdentificationInformation(properties); - return serviceModel; - } - - /** - * @param csarHelper - * @param serviceNodeTemplates - * @param serviceModel - * @return the generated Models - */ - private List generateResourceModels(ISdcCsarHelper csarHelper, List serviceNodeTemplates, - Service serviceModel) { - final ArtifactGeneratorToscaParser parser = new ArtifactGeneratorToscaParser(csarHelper); - - List resources = new ArrayList<>(); - - for (NodeTemplate nodeTemplate : serviceNodeTemplates) { - if (nodeTemplate.getMetaData() != null) { - generateModelFromNodeTemplate(csarHelper, serviceModel, resources, parser, nodeTemplate); - } else { - log.warn(ApplicationMsgs.MISSING_SERVICE_METADATA, nodeTemplate.getName()); - } - } - - return resources; - } - - private void generateModelFromNodeTemplate(ISdcCsarHelper csarHelper, Service serviceModel, - List resources, ArtifactGeneratorToscaParser parser, NodeTemplate nodeTemplate) { - String nodeTypeName = parser.normaliseNodeTypeName(nodeTemplate); - Model model = Model.getModelFor(nodeTypeName, nodeTemplate.getMetaData().getValue("type")); - if (model != null) { - if (nodeTemplate.getMetaData() != null) { - model.populateModelIdentificationInformation(nodeTemplate.getMetaData().getAllProperties()); - } - - parser.addRelatedModel(serviceModel, model); - if (model instanceof Resource) { - generateResourceModel(csarHelper, resources, parser, nodeTemplate, nodeTypeName); - } - } - } - - private void generateResourceModel(ISdcCsarHelper csarHelper, List resources, - ArtifactGeneratorToscaParser parser, NodeTemplate nodeTemplate, String nodeTypeName) { - log.debug("Processing resource " + nodeTypeName + ": " + nodeTemplate.getMetaData().getValue("UUID")); - Model resourceModel = Model.getModelFor(nodeTypeName, nodeTemplate.getMetaData().getValue("type")); - - Map serviceMetadata = nodeTemplate.getMetaData().getAllProperties(); - resourceModel.populateModelIdentificationInformation(serviceMetadata); - - parser.processResourceModels(resourceModel, csarHelper.getNodeTemplateChildren(nodeTemplate)); - - if (csarHelper.getServiceVfList() != null) { - parser.processVfModules(resources, resourceModel, nodeTemplate); - } - - if (parser.hasSubCategoryTunnelXConnect(serviceMetadata) && parser.hasAllottedResource(serviceMetadata)) { - resourceModel.addWidget(new TunnelXconnectWidget()); - } - - resources.addAll(parser.processInstanceGroups(resourceModel, nodeTemplate)); - resources.add((Resource) resourceModel); - } - - /** - * @param generationData - * @param resource - */ - private void generateResourceArtifact(GenerationData generationData, Resource resource) { - if (!isContained(generationData, getArtifactName(resource))) { - log.info(ApplicationMsgs.DISTRIBUTION_EVENT, "Generating resource model"); - generationData.add(getResourceArtifact(resource, modelGenerator.generateModelFor(resource))); - } - } - - private Path createTempFile(byte[] bytes) throws IOException { - log.debug("Creating temp file on file system for the csar"); - Path path = Files.createTempFile("temp", ".csar"); - Files.write(path, bytes); - return path; - } - - /** - * Create the artifact label for an AAI model. - * - * @param model - * @return the artifact label as String - */ - private String getArtifactLabel(Model model) { - StringBuilder artifactName = new StringBuilder(ArtifactType.AAI.name()); - artifactName.append("-"); - artifactName.append(model.getModelType().name().toLowerCase()); - artifactName.append("-"); - artifactName.append(hashCodeUuId(model.getModelNameVersionId())); - return (artifactName.toString()).replaceAll("[^a-zA-Z0-9 +]+", "-"); - } - - /** - * Method to generate the artifact name for an AAI model. - * - * @param model - * AAI artifact model - * @return Model artifact name - */ - private String getArtifactName(Model model) { - StringBuilder artifactName = new StringBuilder(ArtifactType.AAI.name()); - artifactName.append("-"); - - String truncatedArtifactName = truncateName(model.getModelName()); - artifactName.append(truncatedArtifactName); - - artifactName.append("-"); - artifactName.append(model.getModelType().name().toLowerCase()); - artifactName.append("-"); - artifactName.append(model.getModelVersion()); - - artifactName.append("."); - artifactName.append(GENERATOR_AAI_GENERATED_ARTIFACT_EXTENSION); - return artifactName.toString(); - } - - /** - * Create Resource artifact model from the AAI xml model string. - * - * @param resourceModel - * Model of the resource artifact - * @param aaiResourceModel - * AAI model as string - * @return Generated {@link Artifact} model for the resource - */ - private Artifact getResourceArtifact(Model resourceModel, String aaiResourceModel) { - final String resourceArtifactLabel = getArtifactLabel(resourceModel); - MDC.put(MDC_PARAM_MODEL_INFO, resourceModel.getModelName() + "," + resourceArtifactLabel); - final byte[] bytes = aaiResourceModel.getBytes(); - - Artifact artifact = new Artifact(ArtifactType.MODEL_INVENTORY_PROFILE.name(), GroupType.DEPLOYMENT.name(), - GeneratorUtil.checkSum(bytes), GeneratorUtil.encode(bytes)); - artifact.setName(getArtifactName(resourceModel)); - artifact.setLabel(resourceArtifactLabel); - artifact.setDescription(ArtifactGeneratorToscaParser.getArtifactDescription(resourceModel)); - return artifact; - } - - /** - * @param generationData - * @param artifactName - * @return - */ - private boolean isContained(GenerationData generationData, final String artifactName) { - return generationData.getResultData().stream() - .anyMatch(artifact -> StringUtils.equals(artifact.getName(), artifactName)); - } - - /** - * Create Service artifact model from the AAI XML model. - * - * @param serviceModel - * Model of the service artifact - * @param aaiServiceModel - * AAI model as string - * @return Generated {@link Artifact} model for the service - */ - private Artifact getServiceArtifact(Service serviceModel, String aaiServiceModel) { - Artifact artifact = new Artifact(ArtifactType.MODEL_INVENTORY_PROFILE.name(), GroupType.DEPLOYMENT.name(), - GeneratorUtil.checkSum(aaiServiceModel.getBytes()), GeneratorUtil.encode(aaiServiceModel.getBytes())); - String serviceArtifactName = getArtifactName(serviceModel); - String serviceArtifactLabel = getArtifactLabel(serviceModel); - artifact.setName(serviceArtifactName); - artifact.setLabel(serviceArtifactLabel); - String description = ArtifactGeneratorToscaParser.getArtifactDescription(serviceModel); - artifact.setDescription(description); - return artifact; - } - - private int hashCodeUuId(String uuId) { - int hashcode = 0; - for (int i = 0; i < uuId.length(); i++) { - hashcode = 31 * hashcode + uuId.charAt(i); - } - return hashcode; - } - - private String truncateName(String name) { - String truncatedName = name; - if (name.length() >= 200) { - truncatedName = name.substring(0, 199); - } - return truncatedName; - } - - private String validateServiceVersion(Map additionalParams) { - String serviceVersion = additionalParams.get(AdditionalParams.SERVICE_VERSION.getName()); - if (serviceVersion == null) { - throw new IllegalArgumentException(GENERATOR_AAI_ERROR_MISSING_SERVICE_VERSION); - } else { - String versionRegex = "^[1-9]\\d*(\\.0)$"; - if (!(serviceVersion.matches(versionRegex))) { - throw new IllegalArgumentException(String.format(GENERATOR_AAI_INVALID_SERVICE_VERSION)); - } - } - return serviceVersion; - } + private static Logger log = LogHelper.INSTANCE; + + private static final String MDC_PARAM_MODEL_INFO = "ARTIFACT_MODEL_INFO"; + private static final String GENERATOR_AAI_GENERATED_ARTIFACT_EXTENSION = "xml"; + private static final String GENERATOR_AAI_ERROR_MISSING_SERVICE_TOSCA = + "Service tosca missing from list of input artifacts"; + private static final String GENERATOR_AAI_ERROR_MISSING_SERVICE_VERSION = + "Cannot generate artifacts. Service version is not specified"; + private static final String GENERATOR_AAI_INVALID_SERVICE_VERSION = + "Cannot generate artifacts. Service version is incorrect"; + + private AaiModelGenerator modelGenerator = new AaiModelGeneratorImpl(); + + @Override + public GenerationData generateArtifact(byte[] csarArchive, List input, + Map additionalParams) { + Path csarPath; + + try { + csarPath = createTempFile(csarArchive); + } catch (IOException e) { + log.error(ApplicationMsgs.TEMP_FILE_ERROR, e); + return createErrorData(e); + } + + try { + ArtifactGeneratorToscaParser.initWidgetConfiguration(); + ArtifactGeneratorToscaParser.initGroupFilterConfiguration(); + ISdcCsarHelper csarHelper = + SdcToscaParserFactory.getInstance().getSdcCsarHelper(csarPath.toAbsolutePath().toString()); + return generateAllArtifacts(validateServiceVersion(additionalParams), csarHelper); + } catch (Exception e) { + log.error(ApplicationMsgs.INVALID_CSAR_FILE, e); + return createErrorData(e); + } finally { + FileUtils.deleteQuietly(csarPath.toFile()); + } + } + + private GenerationData createErrorData(Exception e) { + GenerationData generationData = new GenerationData(); + generationData.add(ArtifactType.AAI.name(), e.getMessage()); + return generationData; + } + + /** + * Generate model artifacts for the Service and its associated Resources. + * + * @param serviceVersion + * @param csarHelper + * interface to the TOSCA parser + * @return the generated Artifacts (containing XML models) + */ + private GenerationData generateAllArtifacts(final String serviceVersion, ISdcCsarHelper csarHelper) { + List serviceNodeTemplates = csarHelper.getServiceNodeTemplates(); + if (serviceNodeTemplates == null) { + throw new IllegalArgumentException(GENERATOR_AAI_ERROR_MISSING_SERVICE_TOSCA); + } + + Service serviceModel = createServiceModel(serviceVersion, csarHelper.getServiceMetadataAllProperties()); + + MDC.put(MDC_PARAM_MODEL_INFO, serviceModel.getModelName() + "," + getArtifactLabel(serviceModel)); + + List resources = generateResourceModels(csarHelper, serviceNodeTemplates, serviceModel); + + // Generate the A&AI XML model for the Service. + final String serviceArtifact = modelGenerator.generateModelFor(serviceModel); + + // Build a Babel Artifact to be returned to the caller. + GenerationData generationData = new GenerationData(); + generationData.add(getServiceArtifact(serviceModel, serviceArtifact)); + + // For each Resource, generate the A&AI XML model and then create an additional Artifact for that model. + for (Resource resource : resources) { + generateResourceArtifact(generationData, resource); + for (Resource childResource : resource.getResources()) { + if (!(childResource instanceof ProvidingService)) { + generateResourceArtifact(generationData, childResource); + } + } + } + + return generationData; + } + + /** + * Create a Service from the provided metadata + * + * @param serviceVersion + * @param properties + * @return + */ + private Service createServiceModel(final String serviceVersion, Map properties) { + log.debug("Processing (TOSCA) Service object"); + Service serviceModel = new Service(); + serviceModel.setModelVersion(serviceVersion); + serviceModel.populateModelIdentificationInformation(properties); + return serviceModel; + } + + /** + * @param csarHelper + * @param serviceNodeTemplates + * @param serviceModel + * @return the generated Models + */ + private List generateResourceModels(ISdcCsarHelper csarHelper, List serviceNodeTemplates, + Service serviceModel) { + final List serviceGroups = csarHelper.getGroupsOfTopologyTemplate(); + final ArtifactGeneratorToscaParser parser = new ArtifactGeneratorToscaParser(csarHelper); + + List resources = new ArrayList<>(); + + for (NodeTemplate nodeTemplate : serviceNodeTemplates) { + if (nodeTemplate.getMetaData() != null) { + generateModelFromNodeTemplate(csarHelper, serviceModel, resources, serviceGroups, parser, nodeTemplate); + } else { + log.warn(ApplicationMsgs.MISSING_SERVICE_METADATA, nodeTemplate.getName()); + } + } + + return resources; + } + + private void generateModelFromNodeTemplate(ISdcCsarHelper csarHelper, Service serviceModel, + List resources, final List serviceGroups, ArtifactGeneratorToscaParser parser, + NodeTemplate nodeTemplate) { + String nodeTypeName = parser.normaliseNodeTypeName(nodeTemplate); + Model model = Model.getModelFor(nodeTypeName, nodeTemplate.getMetaData().getValue("type")); + if (model != null) { + if (nodeTemplate.getMetaData() != null) { + model.populateModelIdentificationInformation(nodeTemplate.getMetaData().getAllProperties()); + } + + parser.addRelatedModel(serviceModel, model); + if (model instanceof Resource) { + generateResourceModel(csarHelper, resources, parser, nodeTemplate, nodeTypeName); + } + } else { + for (Group group : serviceGroups) { + if (group.getMembers().contains(nodeTemplate.getName()) + && WidgetConfigurationUtil.isSupportedInstanceGroup(group.getType())) { + log.debug(String.format("Adding group %s (type %s) with members %s", group.getName(), + group.getType(), group.getMembers())); + + Resource groupModel = parser.createInstanceGroupModel( + parser.mergeProperties(group.getMetadata().getAllProperties(), group.getProperties())); + serviceModel.addResource(groupModel); + resources.add(groupModel); + } + } + } + } + + private void generateResourceModel(ISdcCsarHelper csarHelper, List resources, + ArtifactGeneratorToscaParser parser, NodeTemplate nodeTemplate, String nodeTypeName) { + log.debug("Processing resource " + nodeTypeName + ": " + nodeTemplate.getMetaData().getValue("UUID")); + Model resourceModel = Model.getModelFor(nodeTypeName, nodeTemplate.getMetaData().getValue("type")); + + Map serviceMetadata = nodeTemplate.getMetaData().getAllProperties(); + resourceModel.populateModelIdentificationInformation(serviceMetadata); + + parser.processResourceModels(resourceModel, csarHelper.getNodeTemplateChildren(nodeTemplate)); + + if (csarHelper.getServiceVfList() != null) { + parser.processVfModules(resources, resourceModel, nodeTemplate); + } + + if (parser.hasSubCategoryTunnelXConnect(serviceMetadata) && parser.hasAllottedResource(serviceMetadata)) { + resourceModel.addWidget(new TunnelXconnectWidget()); + } + + resources.addAll(parser.processInstanceGroups(resourceModel, nodeTemplate)); + resources.add((Resource) resourceModel); + } + + /** + * @param generationData + * @param resource + */ + private void generateResourceArtifact(GenerationData generationData, Resource resource) { + if (!isContained(generationData, getArtifactName(resource))) { + log.info(ApplicationMsgs.DISTRIBUTION_EVENT, "Generating resource model"); + generationData.add(getResourceArtifact(resource, modelGenerator.generateModelFor(resource))); + } + } + + private Path createTempFile(byte[] bytes) throws IOException { + log.debug("Creating temp file on file system for the csar"); + Path path = Files.createTempFile("temp", ".csar"); + Files.write(path, bytes); + return path; + } + + /** + * Create the artifact label for an AAI model. + * + * @param model + * @return the artifact label as String + */ + private String getArtifactLabel(Model model) { + StringBuilder artifactName = new StringBuilder(ArtifactType.AAI.name()); + artifactName.append("-"); + artifactName.append(model.getModelType().name().toLowerCase()); + artifactName.append("-"); + artifactName.append(hashCodeUuId(model.getModelNameVersionId())); + return (artifactName.toString()).replaceAll("[^a-zA-Z0-9 +]+", "-"); + } + + /** + * Method to generate the artifact name for an AAI model. + * + * @param model + * AAI artifact model + * @return Model artifact name + */ + private String getArtifactName(Model model) { + StringBuilder artifactName = new StringBuilder(ArtifactType.AAI.name()); + artifactName.append("-"); + + String truncatedArtifactName = truncateName(model.getModelName()); + artifactName.append(truncatedArtifactName); + + artifactName.append("-"); + artifactName.append(model.getModelType().name().toLowerCase()); + artifactName.append("-"); + artifactName.append(model.getModelVersion()); + + artifactName.append("."); + artifactName.append(GENERATOR_AAI_GENERATED_ARTIFACT_EXTENSION); + return artifactName.toString(); + } + + /** + * Create Resource artifact model from the AAI xml model string. + * + * @param resourceModel + * Model of the resource artifact + * @param aaiResourceModel + * AAI model as string + * @return Generated {@link Artifact} model for the resource + */ + private Artifact getResourceArtifact(Model resourceModel, String aaiResourceModel) { + final String resourceArtifactLabel = getArtifactLabel(resourceModel); + MDC.put(MDC_PARAM_MODEL_INFO, resourceModel.getModelName() + "," + resourceArtifactLabel); + final byte[] bytes = aaiResourceModel.getBytes(); + + Artifact artifact = new Artifact(ArtifactType.MODEL_INVENTORY_PROFILE.name(), GroupType.DEPLOYMENT.name(), + GeneratorUtil.checkSum(bytes), GeneratorUtil.encode(bytes)); + artifact.setName(getArtifactName(resourceModel)); + artifact.setLabel(resourceArtifactLabel); + artifact.setDescription(ArtifactGeneratorToscaParser.getArtifactDescription(resourceModel)); + return artifact; + } + + /** + * @param generationData + * @param artifactName + * @return + */ + private boolean isContained(GenerationData generationData, final String artifactName) { + return generationData.getResultData().stream() + .anyMatch(artifact -> StringUtils.equals(artifact.getName(), artifactName)); + } + + /** + * Create Service artifact model from the AAI XML model. + * + * @param serviceModel + * Model of the service artifact + * @param aaiServiceModel + * AAI model as string + * @return Generated {@link Artifact} model for the service + */ + private Artifact getServiceArtifact(Service serviceModel, String aaiServiceModel) { + Artifact artifact = new Artifact(ArtifactType.MODEL_INVENTORY_PROFILE.name(), GroupType.DEPLOYMENT.name(), + GeneratorUtil.checkSum(aaiServiceModel.getBytes()), GeneratorUtil.encode(aaiServiceModel.getBytes())); + String serviceArtifactName = getArtifactName(serviceModel); + String serviceArtifactLabel = getArtifactLabel(serviceModel); + artifact.setName(serviceArtifactName); + artifact.setLabel(serviceArtifactLabel); + String description = ArtifactGeneratorToscaParser.getArtifactDescription(serviceModel); + artifact.setDescription(description); + return artifact; + } + + private int hashCodeUuId(String uuId) { + int hashcode = 0; + for (int i = 0; i < uuId.length(); i++) { + hashcode = 31 * hashcode + uuId.charAt(i); + } + return hashcode; + } + + private String truncateName(String name) { + String truncatedName = name; + if (name.length() >= 200) { + truncatedName = name.substring(0, 199); + } + return truncatedName; + } + + private String validateServiceVersion(Map additionalParams) { + String serviceVersion = additionalParams.get(AdditionalParams.SERVICE_VERSION.getName()); + if (serviceVersion == null) { + throw new IllegalArgumentException(GENERATOR_AAI_ERROR_MISSING_SERVICE_VERSION); + } else { + String versionRegex = "^[1-9]\\d*(\\.0)$"; + if (!(serviceVersion.matches(versionRegex))) { + throw new IllegalArgumentException(String.format(GENERATOR_AAI_INVALID_SERVICE_VERSION)); + } + } + return serviceVersion; + } } diff --git a/src/test/java/org/onap/aai/babel/parser/TestArtifactGeneratorToscaParser.java b/src/test/java/org/onap/aai/babel/parser/TestArtifactGeneratorToscaParser.java index 3cbaa13..b7957f7 100644 --- a/src/test/java/org/onap/aai/babel/parser/TestArtifactGeneratorToscaParser.java +++ b/src/test/java/org/onap/aai/babel/parser/TestArtifactGeneratorToscaParser.java @@ -30,7 +30,6 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Properties; - import org.junit.Test; import org.mockito.Mockito; import org.onap.aai.babel.xml.generator.data.WidgetConfigurationUtil; @@ -49,114 +48,114 @@ import org.onap.sdc.toscaparser.api.SubstitutionMappings; public class TestArtifactGeneratorToscaParser { - private static final String TEST_UUID = "1234"; - - /** - * Process an Allotted Resource that does not have a Providing Service. - */ - @Test(expected = IllegalArgumentException.class) - public void testMissingProvidingService() { - List nodeTemplateList = Collections.singletonList(buildNodeTemplate("name", "BlockStorage")); - new ArtifactGeneratorToscaParser(null).processResourceModels(new AllotedResource(), nodeTemplateList); - } - - /** - * - * Add a CR (a type of Resource which is not a Providing Service) to a Resource Model. - */ - @Test(expected = IllegalArgumentException.class) - public void testAddResourceNotProvidingService() { - List nodeTemplateList = Collections.singletonList(buildNodeTemplate("testCR", "CR")); - final Resource dummyResource = new AllotedResource(); // Any Resource to which the CR can be added - new ArtifactGeneratorToscaParser(null).processResourceModels(dummyResource, nodeTemplateList); - } - - /** - * Process a dummy Group object for a Service Resource. - */ - @Test - public void testInstanceGroups() { - final String instanceGroupType = "org.openecomp.groups.ResourceInstanceGroup"; - Properties props = new Properties(); - props.put("AAI.instance-group-types", instanceGroupType); - WidgetConfigurationUtil.setFilterConfig(props); - - ISdcCsarHelper helper = Mockito.mock(ISdcCsarHelper.class); - SubstitutionMappings sm = Mockito.mock(SubstitutionMappings.class); - - NodeTemplate serviceNodeTemplate = buildNodeTemplate("service", - "org.openecomp.resource.cr.a-collection-resource"); - serviceNodeTemplate.setSubMappingToscaTemplate(sm); - Mockito.when(helper.getNodeTemplateByName(serviceNodeTemplate.getName())).thenReturn(serviceNodeTemplate); - - ArrayList groups = new ArrayList<>(); - groups.add(buildGroup("group", instanceGroupType)); - Mockito.when(helper.getGroupsOfOriginOfNodeTemplate(serviceNodeTemplate)).thenReturn(groups); - - ArtifactGeneratorToscaParser parser = new ArtifactGeneratorToscaParser(helper); - List resources = parser.processInstanceGroups(new InstanceGroup(), serviceNodeTemplate); - - assertThat(resources.size(), is(1)); - Resource resource = resources.get(0); - assertThat(resource.getModelNameVersionId(), is(equalTo(TEST_UUID))); - } - - /** - * Create a NodeTemplate for unit testing purposes. In production code this object would only be created by the - * sdc-tosca parser. - * - * @param name - * name of the NodeTemplate - * @param type - * type of the NodeTemplate - * @return a new NodeTemplate object - */ - private NodeTemplate buildNodeTemplate(String name, String type) { - LinkedHashMap nodeTemplateMap = new LinkedHashMap<>(); - nodeTemplateMap.put(name, buildMap("type", type)); - nodeTemplateMap.put(type, buildNodeTemplateCustomDefs()); - return new NodeTemplate(name, nodeTemplateMap, nodeTemplateMap, null, null); - } - - private LinkedHashMap buildNodeTemplateCustomDefs() { - LinkedHashMap customDefs = buildCustomDefs(); - customDefs.put("attributes", null); - customDefs.put("requirements", null); - customDefs.put("capabilities", null); - customDefs.put("artifacts", null); - return customDefs; - } - - private Group buildGroup(String name, String type) { - LinkedHashMap template = new LinkedHashMap<>(); - template.put("type", type); - template.put("metadata", new LinkedHashMap<>()); - template.put("properties", buildMap("UUID", TEST_UUID)); - LinkedHashMap customDefMap = buildMap(name, template); - customDefMap.put(type, buildGroupCustomDefs()); - return new Group(name, template, null, customDefMap); - } - - private LinkedHashMap buildGroupCustomDefs() { - LinkedHashMap customDefs = buildCustomDefs(); - customDefs.put("members", null); - return customDefs; - } - - private LinkedHashMap buildCustomDefs() { - LinkedHashMap customDefs = new LinkedHashMap<>(); - customDefs.put("derived_from", null); - customDefs.put("metadata", null); - customDefs.put("version", null); - customDefs.put("description", null); - customDefs.put("interfaces", null); - customDefs.put("properties", buildMap("UUID", buildMap("type", "java.lang.String"))); - return customDefs; - } - - private LinkedHashMap buildMap(String key, Object value) { - LinkedHashMap map = new LinkedHashMap<>(); - map.put(key, value); - return map; - } + private static final String TEST_UUID = "1234"; + + /** + * Process an Allotted Resource that does not have a Providing Service. + */ + @Test(expected = IllegalArgumentException.class) + public void testMissingProvidingService() { + List nodeTemplateList = Collections.singletonList(buildNodeTemplate("name", "BlockStorage")); + new ArtifactGeneratorToscaParser(null).processResourceModels(new AllotedResource(), nodeTemplateList); + } + + /** + * + * Add a CR (a type of Resource which is not a Providing Service) to a Resource Model. + */ + @Test(expected = IllegalArgumentException.class) + public void testAddResourceNotProvidingService() { + List nodeTemplateList = Collections.singletonList(buildNodeTemplate("testCR", "CR")); + final Resource dummyResource = new AllotedResource(); // Any Resource to which the CR can be added + new ArtifactGeneratorToscaParser(null).processResourceModels(dummyResource, nodeTemplateList); + } + + /** + * Process a dummy Group object for a Service Resource. + */ + @Test + public void testInstanceGroups() { + final String instanceGroupType = "org.openecomp.groups.ResourceInstanceGroup"; + Properties props = new Properties(); + props.put("AAI.instance-group-types", instanceGroupType); + WidgetConfigurationUtil.setFilterConfig(props); + + ISdcCsarHelper helper = Mockito.mock(ISdcCsarHelper.class); + SubstitutionMappings sm = Mockito.mock(SubstitutionMappings.class); + + NodeTemplate serviceNodeTemplate = + buildNodeTemplate("service", "org.openecomp.resource.cr.a-collection-resource"); + serviceNodeTemplate.setSubMappingToscaTemplate(sm); + Mockito.when(helper.getNodeTemplateByName(serviceNodeTemplate.getName())).thenReturn(serviceNodeTemplate); + + ArrayList groups = new ArrayList<>(); + groups.add(buildGroup("group", instanceGroupType)); + Mockito.when(helper.getGroupsOfOriginOfNodeTemplate(serviceNodeTemplate)).thenReturn(groups); + + ArtifactGeneratorToscaParser parser = new ArtifactGeneratorToscaParser(helper); + List resources = parser.processInstanceGroups(new InstanceGroup(), serviceNodeTemplate); + + assertThat(resources.size(), is(1)); + Resource resource = resources.get(0); + assertThat(resource.getModelNameVersionId(), is(equalTo(TEST_UUID))); + } + + /** + * Create a NodeTemplate for unit testing purposes. In production code this object would only be created by the + * sdc-tosca parser. + * + * @param name + * name of the NodeTemplate + * @param type + * type of the NodeTemplate + * @return a new NodeTemplate object + */ + private NodeTemplate buildNodeTemplate(String name, String type) { + LinkedHashMap nodeTemplateMap = new LinkedHashMap<>(); + nodeTemplateMap.put(name, buildMap("type", type)); + nodeTemplateMap.put(type, buildNodeTemplateCustomDefs()); + return new NodeTemplate(name, nodeTemplateMap, nodeTemplateMap, null, null); + } + + private LinkedHashMap buildNodeTemplateCustomDefs() { + LinkedHashMap customDefs = buildCustomDefs(); + customDefs.put("attributes", null); + customDefs.put("requirements", null); + customDefs.put("capabilities", null); + customDefs.put("artifacts", null); + return customDefs; + } + + private Group buildGroup(String name, String type) { + LinkedHashMap template = new LinkedHashMap<>(); + template.put("type", type); + template.put("metadata", new LinkedHashMap<>()); + template.put("properties", buildMap("UUID", TEST_UUID)); + LinkedHashMap customDefMap = buildMap(name, template); + customDefMap.put(type, buildGroupCustomDefs()); + return new Group(name, template, null, customDefMap); + } + + private LinkedHashMap buildGroupCustomDefs() { + LinkedHashMap customDefs = buildCustomDefs(); + customDefs.put("members", null); + return customDefs; + } + + private LinkedHashMap buildCustomDefs() { + LinkedHashMap customDefs = new LinkedHashMap<>(); + customDefs.put("derived_from", null); + customDefs.put("metadata", null); + customDefs.put("version", null); + customDefs.put("description", null); + customDefs.put("interfaces", null); + customDefs.put("properties", buildMap("UUID", buildMap("type", "java.lang.String"))); + return customDefs; + } + + private LinkedHashMap buildMap(String key, Object value) { + LinkedHashMap map = new LinkedHashMap<>(); + map.put(key, value); + return map; + } } diff --git a/src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java b/src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java index 297bb4d..84a2934 100644 --- a/src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java +++ b/src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java @@ -191,6 +191,16 @@ public class CsarToXmlConverterTest { assertThatGeneratedFilesMatchExpected(createExpectedXmlFiles(filesToLoad), CsarTest.PORT_MIRROR_CSAR); } + @Test + public void generateXmlFromServiceProxyCsar() + throws CsarConverterException, IOException, XmlArtifactGenerationException { + List filesToLoad = new ArrayList<>(); + filesToLoad.add("AAI-Grouping Service for Test-service-1.0.xml"); + filesToLoad.add("AAI-groupingservicefortest..ResourceInstanceGroup..0-resource-1.xml"); + filesToLoad.add("AAI-groupingservicefortest..ResourceInstanceGroup..1-resource-1.xml"); + assertThatGeneratedFilesMatchExpected(createExpectedXmlFiles(filesToLoad), CsarTest.SERVICE_PROXY_CSAR_FILE); + } + public Matcher matches(final String expected) { return new BaseMatcher() { protected String theExpected = expected; diff --git a/src/test/java/org/onap/aai/babel/testdata/CsarTest.java b/src/test/java/org/onap/aai/babel/testdata/CsarTest.java index 0def88b..4f4c8ad 100644 --- a/src/test/java/org/onap/aai/babel/testdata/CsarTest.java +++ b/src/test/java/org/onap/aai/babel/testdata/CsarTest.java @@ -43,8 +43,8 @@ public enum CsarTest { NO_YAML_FILES("noYmlFilesArchive.zip"), PORT_MIRROR_CSAR("service_PortMirror.csar"), MULTIPLE_VNF_CSAR("catalog_csar_too_many_vnfConfigurations.csar"), - NETWORK_COLLECTION_CSAR_FILE("service_NetworkCollection.csar"); - + NETWORK_COLLECTION_CSAR_FILE("service_NetworkCollection.csar"), + SERVICE_PROXY_CSAR_FILE("service-S1-csar.csar"); // @formatter:on private String filename; diff --git a/src/test/resources/compressedArtifacts/service-S1-csar.csar b/src/test/resources/compressedArtifacts/service-S1-csar.csar new file mode 100644 index 0000000000000000000000000000000000000000..9bd988925d90695044396b7296603eb80992fa3b GIT binary patch literal 67874 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
  • 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 WEpz|?0Q>zA2LS-+1^K>Z0scQDo1hQ? literal 0 HcmV?d00001 diff --git a/src/test/resources/generatedXml/AAI-Grouping Service for Test-service-1.0.xml b/src/test/resources/generatedXml/AAI-Grouping Service for Test-service-1.0.xml new file mode 100644 index 0000000..2bafb2f --- /dev/null +++ b/src/test/resources/generatedXml/AAI-Grouping Service for Test-service-1.0.xml @@ -0,0 +1,69 @@ + + service-invariant-uuid + service + + + service-uuid + Grouping Service for Test + 1.0 + xxx + + + T + unbounded + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + instance-group-0-version-id + + + model.model-invariant-id + instance-group-0-invariant-id + + + + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + instance-group-1-version-id + + + model.model-invariant-id + instance-group-1-invariant-id + + + + + + + + model-ver + + model-ver.model-version-id + service-instance-version-id + + + model.model-invariant-id + service-instance-invariant-id + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..0-resource-1.xml b/src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..0-resource-1.xml new file mode 100644 index 0000000..b246667 --- /dev/null +++ b/src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..0-resource-1.xml @@ -0,0 +1,32 @@ + + instance-group-0-invariant-id + resource + + + instance-group-0-version-id + groupingservicefortest..ResourceInstanceGroup..0 + 1 + DDD0 + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + instance-group-version-id + + + model.model-invariant-id + instance-group-invariant-id + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..1-resource-1.xml b/src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..1-resource-1.xml new file mode 100644 index 0000000..d49e480 --- /dev/null +++ b/src/test/resources/generatedXml/AAI-groupingservicefortest..ResourceInstanceGroup..1-resource-1.xml @@ -0,0 +1,32 @@ + + instance-group-1-invariant-id + resource + + + instance-group-1-version-id + groupingservicefortest..ResourceInstanceGroup..1 + 1 + DDD1 + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + instance-group-version-id + + + model.model-invariant-id + instance-group-invariant-id + + + + + + + + -- 2.16.6