Merge "[MOD/onboarding] Switch to v3 component spec"
authorTony Hansen <tony@att.com>
Tue, 12 Oct 2021 20:19:19 +0000 (20:19 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 12 Oct 2021 20:19:19 +0000 (20:19 +0000)
37 files changed:
mod/runtimeapi/Changelog.md
mod/runtimeapi/pom.xml
mod/runtimeapi/runtime-core/pom.xml
mod/runtimeapi/runtime-core/src/main/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClient.java [new file with mode: 0644]
mod/runtimeapi/runtime-core/src/main/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClientImpl.java [new file with mode: 0644]
mod/runtimeapi/runtime-core/src/test/data/compspecs/vesWithDb.json [new file with mode: 0644]
mod/runtimeapi/runtime-core/src/test/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClientImplTest.java [new file with mode: 0644]
mod/runtimeapi/runtime-web/pom.xml
mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/controllers/GraphController.java
mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/BlueprintInventory.java
mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/GraphActionsParser.java [new file with mode: 0644]
mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/GraphServiceHelmProxy.java [new file with mode: 0644]
mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/GraphServiceImpl.java
mod/runtimeapi/runtime-web/src/main/resources/application.properties
mod2/helm-generator/Changelog.md
mod2/helm-generator/helmchartgenerator-cli/pom.xml
mod2/helm-generator/helmchartgenerator-cli/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/HelmChartGeneratorApplicationTests.java
mod2/helm-generator/helmchartgenerator-core/pom.xml
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/Utils.java
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/chartbuilder/ChartBuilder.java
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/chartbuilder/ChartGenerator.java
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/chartbuilder/ComponentSpecParser.java
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/chartbuilder/HelmClientImpl.java
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/distribution/ChartMuseumDistributor.java
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/validation/ChartTemplateStructureValidator.java
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/validation/ChartTemplateStructureValidatorImpl.java [new file with mode: 0644]
mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/validation/ComponentSpecValidatorImpl.java
mod2/helm-generator/helmchartgenerator-core/src/main/resources/application.properties
mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartBuilderTest.java [new file with mode: 0644]
mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartGeneratorTest.java [new file with mode: 0644]
mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartMuseumDistributorTest.java [new file with mode: 0644]
mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartTemplateStructureValidatorTest.java
mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ComponentSpecParserTest.java
mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ComponentSpecValidatorTest.java
mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/KeyValueMergerTest.java [new file with mode: 0644]
mod2/helm-generator/lombok.config
mod2/helm-generator/pom.xml

index 3dd643c..5baa372 100644 (file)
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](http://keepachangelog.com/) 
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
+## [1.3.0] - 2021-09-16
+- [DCAEGEN2-2694] Integrate helm chart generator
+    - create a switch to toggle between blueprint and helm based deployment types
+- [DCAEGEN2-2805] Update commons-io version to 2.8.0
+
 ## [1.2.3]
 - Update BPGenerator 1.7.3
   - Update default k8splugin import
index 11e5580..db6d2e2 100644 (file)
@@ -34,7 +34,7 @@ limitations under the License.
        </parent>
        <groupId>org.onap.dcaegen2.platform.mod</groupId>
        <artifactId>runtimeapi</artifactId>
-       <version>1.2.3</version>
+       <version>1.3.0</version>
        <name>dcaegen2-platform-mod-runtimeapi</name>
        <description>MOD Runtime API</description>
        <properties>
@@ -42,6 +42,7 @@ limitations under the License.
                <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
                <sonar.coverage.jacoco.xmlReportPaths>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml
                </sonar.coverage.jacoco.xmlReportPaths>
+               <enforcer.skip>true</enforcer.skip>
        </properties>
        <profiles>
                <profile>
@@ -66,7 +67,13 @@ limitations under the License.
                        </properties>
                </profile>
        </profiles>
-
+       <dependencies>
+               <dependency>
+                       <groupId>commons-io</groupId>
+                       <artifactId>commons-io</artifactId>
+                       <version>2.8.0</version>
+               </dependency>
+       </dependencies>
        <build>
                <plugins>
                        <!-- support sonar in multi-module project -->
index 5514cc9..ff22a58 100644 (file)
@@ -25,12 +25,12 @@ limitations under the License.
     <parent>
         <artifactId>runtimeapi</artifactId>
         <groupId>org.onap.dcaegen2.platform.mod</groupId>
-        <version>1.2.3</version>
+        <version>1.3.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>runtime-core</artifactId>
-    <version>1.2.3</version>
+    <version>1.3.0</version>
 
     <dependencies>
         <dependency>
@@ -48,11 +48,11 @@ limitations under the License.
             <artifactId>blueprint-generator-onap</artifactId>
             <version>1.7.3</version>
         </dependency>
-       <dependency>
-               <groupId>org.json</groupId>
-               <artifactId>json</artifactId>
-               <version>20190722</version>
-       </dependency>
+        <dependency>
+            <groupId>org.onap.dcaegen2.platform</groupId>
+            <artifactId>helmchartgenerator-core</artifactId>
+            <version>1.0.1-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
diff --git a/mod/runtimeapi/runtime-core/src/main/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClient.java b/mod/runtimeapi/runtime-core/src/main/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClient.java
new file mode 100644 (file)
index 0000000..cc5fdca
--- /dev/null
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.runtime.core.helm;
+
+import java.io.File;
+
+public interface HelmChartGeneratorClient {
+
+    File generateHelmChart(String componentSpec);
+
+    void distribute(File helmChart);
+}
diff --git a/mod/runtimeapi/runtime-core/src/main/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClientImpl.java b/mod/runtimeapi/runtime-core/src/main/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClientImpl.java
new file mode 100644 (file)
index 0000000..49ca3de
--- /dev/null
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.runtime.core.helm;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.ChartBuilder;
+import org.onap.dcaegen2.platform.helmchartgenerator.distribution.ChartDistributor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/**
+ * Implementation class for Helm Chart Generator Client
+ */
+@Slf4j
+@Component
+@ComponentScan(basePackages = "org.onap.dcaegen2.platform.helmchartgenerator")
+public class HelmChartGeneratorClientImpl implements HelmChartGeneratorClient {
+
+    @Autowired
+    private final ChartBuilder chartBuilder;
+
+    @Autowired
+    private final ChartDistributor distributor;
+
+    @Value("${helm.base.chart.template.location}")
+    private String templateLocation;
+
+    public HelmChartGeneratorClientImpl(ChartBuilder chartBuilder, ChartDistributor distributor) {
+        this.chartBuilder = chartBuilder;
+        this.distributor = distributor;
+    }
+
+    /**
+     * Generate Helm Chart for a component spec
+     * @param componentSpec component spec as String
+     * @return packaged helm chart
+     */
+    @Override
+    public File generateHelmChart(String componentSpec){
+        try {
+            return chartBuilder.build(createTempSpecFile(componentSpec),templateLocation,
+                    createTempChartOutputLocation(), "");
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new RuntimeException("Error while generating the helm chart.");
+        }
+    }
+
+    private String createTempChartOutputLocation() {
+        try {
+            return Files.createTempDirectory("chart").toAbsolutePath().toString();
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+            throw new RuntimeException("Error creating a temporary chart dir.");
+        }
+    }
+
+    private String createTempSpecFile(String componentSpec) throws IOException{
+            File tmpFile = File.createTempFile("spec",".json");
+        try (FileWriter writer = new FileWriter(tmpFile)) {
+            writer.write(componentSpec);
+        }
+        return tmpFile.getAbsolutePath();
+    }
+
+    /**
+     * Distributes helm chart to Chart Museum
+     * @param helmChart packaged chart location
+     */
+    @Override
+    public void distribute(File helmChart) {
+        try {
+            distributor.distribute(helmChart);
+        }catch (Exception e){
+            throw e;
+        } finally {
+            removeChartLocally(helmChart);
+        }
+    }
+
+    private void removeChartLocally(File helmChart) {
+        try {
+            FileUtils.forceDelete(helmChart);
+        } catch (IOException e) {
+            log.warn("Could not delete a temporary helm chart " + helmChart.getName());
+        }
+    }
+}
diff --git a/mod/runtimeapi/runtime-core/src/test/data/compspecs/vesWithDb.json b/mod/runtimeapi/runtime-core/src/test/data/compspecs/vesWithDb.json
new file mode 100644 (file)
index 0000000..207be6d
--- /dev/null
@@ -0,0 +1,452 @@
+{
+  "self": {
+    "version": "1.8.0",
+    "name": "dcae-ves-collector",
+    "description": "Collector for receiving VES events through restful interface",
+    "component_type": "docker"
+  },
+  "streams": {
+    "subscribes": [],
+    "publishes": [
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-fault"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-measurement"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-syslog"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-heartbeat"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-other"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-mobileflow"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-statechange"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-thresholdCrossingAlert"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-voicequality"
+      },
+      {
+        "format": "VES_specification",
+        "version": "5.28.4",
+        "type": "message router",
+        "config_key": "ves-sipsignaling"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-pnfRegistration"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-notification"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-perf3gpp"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-3gpp-fault-supervision"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-3gpp-provisioning"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-3gpp-heartbeat"
+      },
+      {
+        "format": "VES_specification",
+        "version": "7.30.2",
+        "type": "message router",
+        "config_key": "ves-3gpp-performance-assurance"
+      }
+    ]
+  },
+  "services": {
+    "calls": [],
+    "provides": [
+      {
+        "route": "/eventListener/v1",
+        "verb": "POST",
+        "request": {
+          "format": "VES_specification",
+          "version": "4.27.2"
+        },
+        "response": {
+          "format": "ves.coll.response",
+          "version": "1.0.0"
+        }
+      },
+      {
+        "route": "/eventListener/v2",
+        "verb": "POST",
+        "request": {
+          "format": "VES_specification",
+          "version": "4.27.2"
+        },
+        "response": {
+          "format": "ves.coll.response",
+          "version": "1.0.0"
+        }
+      },
+      {
+        "route": "/eventListener/v3",
+        "verb": "POST",
+        "request": {
+          "format": "VES_specification",
+          "version": "4.27.2"
+        },
+        "response": {
+          "format": "ves.coll.response",
+          "version": "1.0.0"
+        }
+      },
+      {
+        "route": "/eventListener/v4",
+        "verb": "POST",
+        "request": {
+          "format": "VES_specification",
+          "version": "4.27.2"
+        },
+        "response": {
+          "format": "ves.coll.response",
+          "version": "1.0.0"
+        }
+      },
+      {
+        "route": "/eventListener/v5",
+        "verb": "POST",
+        "request": {
+          "format": "VES_specification",
+          "version": "5.28.4"
+        },
+        "response": {
+          "format": "ves.coll.response",
+          "version": "1.0.0"
+        }
+      },
+      {
+        "route": "/eventListener/v7",
+        "verb": "POST",
+        "request": {
+          "format": "VES_specification",
+          "version": "7.30.2"
+        },
+        "response": {
+          "format": "ves.coll.response",
+          "version": "1.0.0"
+        }
+      }
+    ]
+  },
+  "parameters": [
+    {
+      "name": "streams_publishes",
+      "value": {
+        "ves-fault": {
+          "dmaap_info": {
+            "topic_url": "http://message-router:3904/events/unauthenticated.SEC_FAULT_OUTPUT"
+          },
+          "type": "message_router"
+        }
+      },
+      "description": "standard http port collector will open for listening;",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    }
+  ,
+    {
+      "name": "collector.service.port",
+      "value": 8080,
+      "description": "standard http port collector will open for listening;",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.service.secure.port",
+      "value": 8443,
+      "description": "secure http port collector will open for listening ",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": true
+    },
+    {
+      "name": "collector.keystore.file.location",
+      "value": "/opt/app/dcae-certificate/cert.jks",
+      "description": "fs location of keystore file in vm",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.keystore.passwordfile",
+      "value": "/opt/app/dcae-certificate/jks.pass",
+      "description": "location of keystore password file in vm",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.truststore.file.location",
+      "value": "/opt/app/dcae-certificate/trust.jks",
+      "description": "fs location of truststore file in vm",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.truststore.passwordfile",
+      "value": "/opt/app/dcae-certificate/trust.pass",
+      "description": "location of truststore password file in vm",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.dmaap.streamid",
+      "value": "fault=ves-fault|syslog=ves-syslog|heartbeat=ves-heartbeat|measurementsForVfScaling=ves-measurement|mobileFlow=ves-mobileflow|other=ves-other|stateChange=ves-statechange|thresholdCrossingAlert=ves-thresholdCrossingAlert|voiceQuality=ves-voicequality|sipSignaling=ves-sipsignaling|notification=ves-notification|pnfRegistration=ves-pnfRegistration|3GPP-FaultSupervision=ves-3gpp-fault-supervision|3GPP-Heartbeat=ves-3gpp-heartbeat|3GPP-Provisioning=ves-3gpp-provisioning|3GPP-PerformanceAssurance=ves-3gpp-performance-assurance",
+      "description": "domain-to-streamid mapping used by VESCollector to distributes events based on domain. Both primary and secondary config_key are included for resilency (multiple streamid can be included commma separated). The streamids MUST match to topic config_keys. For single site without resiliency deployment - configkeys with -secondary suffix can be removed",
+      "sourced_at_deployment": true,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "auth.method",
+      "value": "noAuth",
+      "description": "Property to manage application mode, possible configurations: noAuth - default option - no security (http) , certOnly - auth by certificate (https), basicAuth - auth by basic auth username and password (https),certBasicAuth - auth by certificate and basic auth username / password (https),",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "header.authlist",
+      "value": "sample1,$2a$10$pgjaxDzSuc6XVFEeqvxQ5u90DKJnM/u7TJTcinAlFJVaavXMWf/Zi|userid1,$2a$10$61gNubgJJl9lh3nvQvY9X.x4e5ETWJJ7ao7ZhJEvmfJigov26Z6uq|userid2,$2a$10$G52y/3uhuhWAMy.bx9Se8uzWinmbJa.dlm1LW6bYPdPkkywLDPLiy",
+      "description": "List of id and base 64 encoded password.For each onboarding VNF - unique userid and password should be assigned and communicated to VNF owner. Password value should be base64 encoded in config here",
+      "policy_editable": false,
+      "sourced_at_deployment": true,
+      "designer_editable": true
+    },
+    {
+      "name": "collector.schema.checkflag",
+      "value": 1,
+      "description": "Schema check validation flag. When enabled, collector will validate input VES events against VES Schema defined on collector.schema.file ",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.schema.file",
+      "value": "{\"v1\":\"./etc/CommonEventFormat_27.2.json\",\"v2\":\"./etc/CommonEventFormat_27.2.json\",\"v3\":\"./etc/CommonEventFormat_27.2.json\",\"v4\":\"./etc/CommonEventFormat_27.2.json\",\"v5\":\"./etc/CommonEventFormat_28.4.1.json\",\"v7\":\"./etc/CommonEventFormat_30.2.1_ONAP.json\"}",
+      "description": "VES schema file name per version used for validation",
+      "designer_editable": true,
+      "sourced_at_deployment": false,
+      "policy_editable": false
+    },
+    {
+      "name": "event.transform.flag",
+      "value": 1,
+      "description": "flag to enable tranformation rules defined under eventTransform.json; this is applicable when event tranformation rules preset should be activated for transforming <VES5.4 events to 5.4",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "tomcat.maxthreads",
+      "value": "200",
+      "description": "Tomcat control for concurrent request",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.externalSchema.checkflag",
+      "value": 1,
+      "description": "Schema stndDefined validation flag. When enabled, collector will validate stndDefined fields in stndDefined domain events against mapped local schemas listed in file from property collector.externalSchema.mappingFileLocation.",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": true
+    },
+    {
+      "name": "collector.externalSchema.schemasLocation",
+      "value": "./etc/externalRepo/",
+      "description": "External schemas repository. Path to schemas storage directory.",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.externalSchema.mappingFileLocation",
+      "value": "./etc/externalRepo/schema-map.json",
+      "description": "Path to JSON file containing mapping of externally located stndDefined schemas to local schema files.",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "event.externalSchema.schemaRefPath",
+      "value": "$.event.stndDefinedFields.schemaReference",
+      "description": "An internal path from validated JSON. Defines which field is taken as public schema reference, which is later mapped.",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "event.externalSchema.stndDefinedDataPath",
+      "value": "$.event.stndDefinedFields.data",
+      "description": "An internal path from validated JSON. Defines which field of event will be validated during stndDefined validation.",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    },
+    {
+      "name": "collector.description.api.version.location",
+      "value": "etc/api_version_description.json",
+      "description": "Path to the file containing description of api versions",
+      "sourced_at_deployment": false,
+      "policy_editable": false,
+      "designer_editable": false
+    }
+  ],
+  "auxilary": {
+    "helm": {
+      "applicationEnv": {
+        "PMSH_PG_URL": "dcae-pmsh-pg-primary",
+        "PMSH_PG_USERNAME": {
+          "secretUid": "pgUserCredsSecretUid",
+          "key": "login"
+        },
+        "PMSH_PG_PASSWORD": {
+          "secretUid": "pgUserCredsSecretUid",
+          "key": "password"
+        }
+      },
+      "service": {
+        "type": "NodePort",
+        "name": "dcae-ves-collector",
+        "has_internal_only_ports": true,
+        "ports": [
+          {
+            "name": "http",
+            "port": 8443,
+            "plain_port": 8080,
+            "port_protocol": "http",
+            "nodePort": 17,
+            "useNodePortExt": true
+          },
+          {
+            "name": "metrics",
+            "port": 4444,
+            "internal_only": true
+          }
+        ]
+      }
+    },
+    "healthcheck": {
+      "type": "http",
+      "interval": "15s",
+      "timeout": "1s",
+      "endpoint": "/healthcheck",
+      "port": 8080,
+      "initialDelaySeconds": 5
+    },
+    "volumes": [{
+      "config_volume": {
+        "name": "dcae-external-repo-configmap-schema-map"
+      },
+      "container": {
+        "bind": "/opt/app/VESCollector/etc/externalRepo/"
+      }
+    }, {
+      "config_volume": {
+        "name": "dcae-external-repo-configmap-sa88-rel16"
+      },
+      "container": {
+        "bind": "/opt/app/VESCollector/etc/externalRepo/3gpp/rep/sa5/MnS/blob/SA88-Rel16/OpenAPI/"
+      }
+    }],
+    "ports": [
+      "8080:0",
+      "8443:0"
+    ],
+    "log_info": {
+      "log_directory": "/opt/app/VESCollector/logs/"
+    },
+    "tls_info":{
+      "cert_directory":"/opt/app/dcae-certificate/",
+      "use_tls": true,
+      "use_external_tls": true
+    }
+  },
+  "policy_info":{
+    "policy":[
+      {
+        "node_label":"tca_policy_00",
+        "policy_model_id":"onap.policies.monitoring.cdap.tca.hi.lo.app",
+        "policy_id":"tca_policy_id_10"
+      },
+      {
+        "node_label":"tca_policy_11",
+        "policy_id":"tca_policy_id_11",
+        "policy_model_id":"onap.policies.monitoring.cdap.tca.hi.lo.app"
+      }
+    ]
+  },
+  "artifacts": [
+    {
+      "type": "docker image",
+      "uri": "nexus3.onap.org:10001/onap/org.onap.dcaegen2.collectors.ves.vescollector:latest"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/mod/runtimeapi/runtime-core/src/test/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClientImplTest.java b/mod/runtimeapi/runtime-core/src/test/java/org/onap/dcae/runtime/core/helm/HelmChartGeneratorClientImplTest.java
new file mode 100644 (file)
index 0000000..da58550
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.runtime.core.helm;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.ChartBuilder;
+import org.onap.dcaegen2.platform.helmchartgenerator.distribution.ChartDistributor;
+
+import java.io.File;
+import java.nio.file.Files;
+
+import static org.mockito.ArgumentMatchers.any;
+
+@RunWith(MockitoJUnitRunner.class)
+public class HelmChartGeneratorClientImplTest {
+
+    @Mock
+    private ChartBuilder chartBuilder;
+
+    @Mock
+    private ChartDistributor distributor;
+
+    private HelmChartGeneratorClientImpl client;
+
+    private File mockChartFile;
+
+    @Before
+    public void setUp() throws Exception {
+        client = new HelmChartGeneratorClientImpl(chartBuilder, distributor);
+        mockChartFile = Files.createTempFile("chart", ".tgz").toFile();
+    }
+
+    @Test
+    public void testGenerateHelmChart() throws Exception{
+        client.generateHelmChart("someSpec");
+        Mockito.verify(chartBuilder, Mockito.times(1)).build(any(), any(), any(), any());
+    }
+
+    @Test
+    public void testDistribute() throws Exception{
+        client.distribute(mockChartFile);
+        Mockito.verify(distributor, Mockito.times(1)).distribute(mockChartFile);
+    }
+
+}
index 8b70ea4..f2f3515 100644 (file)
@@ -24,10 +24,10 @@ limitations under the License.
        <parent>
                <groupId>org.onap.dcaegen2.platform.mod</groupId>
                <artifactId>runtimeapi</artifactId>
-               <version>1.2.3</version>
+               <version>1.3.0</version>
        </parent>
        <artifactId>runtime-web</artifactId>
-       <version>1.2.3-SNAPSHOT</version>
+       <version>1.3.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>runtime-web</name>
        <description>MOD Runtime Web Module</description>
@@ -35,7 +35,7 @@ limitations under the License.
                <dependency>
                        <groupId>org.onap.dcaegen2.platform.mod</groupId>
                        <artifactId>runtime-core</artifactId>
-                       <version>1.2.3</version>
+                       <version>1.3.0</version>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
@@ -73,11 +73,6 @@ limitations under the License.
                        <artifactId>springfox-swagger-ui</artifactId>
                        <version>3.0.0</version>
                </dependency>
-               <dependency>
-                       <groupId>org.json</groupId>
-                       <artifactId>json</artifactId>
-                       <version>20190722</version>
-               </dependency>
                <dependency>
                        <groupId>org.apache.httpcomponents</groupId>
                        <artifactId>httpclient</artifactId>
@@ -121,7 +116,9 @@ limitations under the License.
                                                                        <descriptorRef>artifact</descriptorRef>
                                                                </assembly>
                                                                <runCmds>
-                                                                 <runCmd>groupadd -r dcaemod &amp;&amp; useradd -ms /bin/bash dcaemod -g dcaemod &amp;&amp; mkdir -p /maven/data &amp;&amp; chown -R dcaemod:dcaemod /maven/data</runCmd>
+                                                                       <runCmd>apt-get update &amp;&amp; apt-get install -y wget</runCmd>
+                                                                       <runCmd>wget https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz &amp;&amp; tar xvf helm-v3.0.2-linux-amd64.tar.gz &amp;&amp; mv linux-amd64/helm /usr/local/bin/</runCmd>
+                                                                       <runCmd>groupadd -r dcaemod &amp;&amp; useradd -ms /bin/bash dcaemod -g dcaemod &amp;&amp; mkdir -p /maven/data &amp;&amp; chown -R dcaemod:dcaemod /maven/data</runCmd>
                                                                </runCmds>
                                                                <workdir>/maven</workdir>
                                                                <volumes>
index fc222f2..484a426 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 package org.onap.dcae.runtime.web.controllers;
 
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import org.onap.dcae.runtime.core.Edge;
 import org.onap.dcae.runtime.core.FlowGraph;
-import org.onap.dcae.runtime.core.Node;
 import org.onap.dcae.runtime.core.FlowGraphParser.BlueprintVessel;
+import org.onap.dcae.runtime.core.Node;
 import org.onap.dcae.runtime.web.exception.MainGraphNotFoundException;
-import org.onap.dcae.runtime.web.models.*;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
 import org.onap.dcae.runtime.web.models.DistributeGraphRequest;
 import org.onap.dcae.runtime.web.models.GraphRequest;
+import org.onap.dcae.runtime.web.service.GraphService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-import org.onap.dcae.runtime.web.service.GraphServiceImpl;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
-import java.util.Map;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @RestController
 @RequestMapping(value = "/api/graph")
@@ -46,7 +53,7 @@ import java.util.List;
 public class GraphController {
 
     @Autowired
-    private GraphServiceImpl graphService;
+    private GraphService graphService;
 
     Logger logger = LoggerFactory.getLogger(GraphController.class);
 
index 789c9d1..d63deeb 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
  */
 package org.onap.dcae.runtime.web.service;
 
+import org.json.JSONException;
 import org.onap.dcae.runtime.core.FlowGraphParser.BlueprintVessel;
 import org.onap.dcae.runtime.web.models.DashboardConfig;
 import org.json.JSONObject;
@@ -46,7 +47,6 @@ public class BlueprintInventory {
             JSONObject body = prepareBlueprintJsonObject(bpv.name, bpv.version, bpv.blueprint);
             postToDashboard(body);
             logger.info(String.format("Distributed: %s", bpv.toString()));
-            //System.out.println(bpv.blueprint);
         }
     }
 
@@ -74,12 +74,16 @@ public class BlueprintInventory {
 
     private JSONObject prepareBlueprintJsonObject(String blueprintName, int version, String blueprintContent) {
         JSONObject blueprintJsonObject = new JSONObject();
-        blueprintJsonObject.put("owner","dcae_mod");
-        blueprintJsonObject.put("typeName",blueprintName);
-        blueprintJsonObject.put("typeVersion",version);
-        blueprintJsonObject.put("blueprintTemplate",blueprintContent);
-        blueprintJsonObject.put("application","DCAE");
-        blueprintJsonObject.put("component","dcae");
+        try {
+            blueprintJsonObject.put("owner","dcae_mod");
+            blueprintJsonObject.put("typeName",blueprintName);
+            blueprintJsonObject.put("typeVersion",version);
+            blueprintJsonObject.put("blueprintTemplate",blueprintContent);
+            blueprintJsonObject.put("application","DCAE");
+            blueprintJsonObject.put("component","dcae");
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
         return blueprintJsonObject;
     }
 
diff --git a/mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/GraphActionsParser.java b/mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/GraphActionsParser.java
new file mode 100644 (file)
index 0000000..5d290a7
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.runtime.web.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onap.dcae.runtime.core.Edge;
+import org.onap.dcae.runtime.core.EdgeLocation;
+import org.onap.dcae.runtime.core.FlowGraph;
+import org.onap.dcae.runtime.core.FlowGraphParser;
+import org.onap.dcae.runtime.core.Node;
+import org.onap.dcae.runtime.web.exception.ActionsNotDefinedException;
+import org.onap.dcae.runtime.web.models.Action;
+import org.onap.dcae.runtime.web.models.DistributeGraphRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * A helper class that parses the actions from the request and apply them to the main graph
+ */
+@Component
+public class GraphActionsParser {
+
+    @Autowired
+    private FlowGraphParser flowGraphParser;
+
+    void applyActionsToGraph(FlowGraph<Node, Edge> mainFlowGraph, DistributeGraphRequest distributeGraphRequest) {
+        if(distributeGraphRequest.getActions() == null){
+            throw new ActionsNotDefinedException("Action(s) must be defined in the request");
+        }
+        for(Action action : distributeGraphRequest.getActions()){
+            if(action.getCommand().equals("addnode")){
+                Node node = prepareNodeFromAddNAddNodeAction(action);
+                mainFlowGraph.addNode(node);
+            }
+            else if(action.getCommand().equals("addedge")) {
+                Edge edge = prepareEdgeFromAddEdgeAction(action);
+                Node srcNode = flowGraphParser.getNodeFromId(edge.getSrc().getNode());
+                Node tgtNode = flowGraphParser.getNodeFromId(edge.getTgt().getNode());
+                srcNode = fillPlaceholderIfNodeIsEmpty(srcNode);
+                tgtNode =fillPlaceholderIfNodeIsEmpty(tgtNode);
+                mainFlowGraph.addEdge(srcNode,tgtNode,edge);
+            }
+        }
+    }
+
+    private Node fillPlaceholderIfNodeIsEmpty(Node node) {
+        if (node == null) {
+            node = flowGraphParser.getNodeFromId("dummy_id");
+        }
+        return node;
+    }
+
+
+    private Edge prepareEdgeFromAddEdgeAction(Action action) {
+        ObjectMapper objectMapper = new ObjectMapper();
+        Edge edge = objectMapper.convertValue(action.getPayload(),Edge.class);
+        return edge;
+    }
+
+    private void fillPlaceholderIfLocaionsAreEmpty(Edge edge) {
+        if(edge.getSrc().getNode() == null && edge.getSrc().getPort() == null){
+            EdgeLocation src = new EdgeLocation("node-id-placeholder", "node-port-placeholder");
+            edge.setSrc(src);
+        }
+        if(edge.getTgt().getNode() == null && edge.getTgt().getPort() == null){
+            EdgeLocation tgt = new EdgeLocation("node-id-placeholder", "node-port-placeholder");
+            edge.setTgt(tgt);
+        }
+    }
+
+    private Node prepareNodeFromAddNAddNodeAction(Action action) {
+        String componentId = (String) action.getPayload().get("component_id");
+        String componentName = (String) action.getPayload().get("name");
+        String componentSpec = (String) action.getPayload().get("component_spec");
+        return new Node(componentId,componentName,componentSpec);
+    }
+}
diff --git a/mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/GraphServiceHelmProxy.java b/mod/runtimeapi/runtime-web/src/main/java/org/onap/dcae/runtime/web/service/GraphServiceHelmProxy.java
new file mode 100644 (file)
index 0000000..89c9d47
--- /dev/null
@@ -0,0 +1,120 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcae.runtime.web.service;
+
+import org.onap.dcae.runtime.core.BlueprintData;
+import org.onap.dcae.runtime.core.Edge;
+import org.onap.dcae.runtime.core.FlowGraph;
+import org.onap.dcae.runtime.core.FlowGraphParser;
+import org.onap.dcae.runtime.core.Node;
+import org.onap.dcae.runtime.core.helm.HelmChartGeneratorClient;
+import org.onap.dcae.runtime.web.models.DistributeGraphRequest;
+import org.onap.dcae.runtime.web.models.GraphRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A proxy class which will be enable if artifact.type is set to HELM
+ */
+@Service
+@Primary
+@ConditionalOnProperty(
+        value="artifact.type",
+        havingValue = "HELM",
+        matchIfMissing = true)
+@ComponentScan(basePackages = "org.onap.dcae.runtime.core")
+public class GraphServiceHelmProxy implements GraphService {
+
+    @Autowired
+    private GraphService defaultGraphService;
+
+    @Autowired
+    private HelmChartGeneratorClient helmChartGeneratorClient;
+
+    @Autowired
+    private GraphActionsParser actionsParser;
+
+    /**
+     * returns a main graph
+     * @return main graph
+     */
+    @Override
+    public FlowGraph<Node, Edge> getMainGraph() {
+        return defaultGraphService.getMainGraph();
+    }
+
+    /**
+     * initialize a main graph
+     * @param mainGraph a main graph request
+     */
+    @Override
+    public boolean initializeMainGraph(GraphRequest mainGraph) {
+        return defaultGraphService.initializeMainGraph(mainGraph);
+    }
+
+    /**
+     * apply actions on the main graph and creates, distributes helm charts
+     * @param distributeGraphRequest distribute request
+     * @return list of distributed charts
+     */
+    @Override
+    public List<FlowGraphParser.BlueprintVessel> distribute(DistributeGraphRequest distributeGraphRequest) {
+        actionsParser.applyActionsToGraph(getMainGraph(), distributeGraphRequest);
+        return createHelmCharts();
+    }
+
+    public List<FlowGraphParser.BlueprintVessel> createHelmCharts() {
+        final FlowGraph<Node, Edge> flowGraph = getMainGraph();
+        List<FlowGraphParser.BlueprintVessel> blueprints = new ArrayList<>();
+        for(Node node : flowGraph.getNodes()){
+            if(node.getComponentId().equals("dummy_id")){
+                continue;
+            }
+            final File helmChart = helmChartGeneratorClient.generateHelmChart(node.getComponentSpec());
+            helmChartGeneratorClient.distribute(helmChart);
+            BlueprintData blueprintData = new BlueprintData("1", helmChart.getName());
+            node.setBlueprintData(blueprintData);
+            blueprints.add(createBlueprintVessel(helmChart));
+        }
+        return blueprints;
+    }
+
+    private FlowGraphParser.BlueprintVessel createBlueprintVessel(File helmChart) {
+        FlowGraphParser.BlueprintVessel bpv = new FlowGraphParser.BlueprintVessel();
+        bpv.blueprint = helmChart.getName();
+        bpv.version = 1;
+        bpv.name = helmChart.getName();
+        return bpv;
+    }
+
+    /**
+     * deletes main graph
+     */
+    @Override
+    public void deleteMainGraph() {
+        defaultGraphService.deleteMainGraph();
+    }
+}
index f1329c1..94d4b40 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 package org.onap.dcae.runtime.web.service;
 
-import org.onap.dcae.runtime.core.*;
+import org.onap.dcae.runtime.core.Edge;
+import org.onap.dcae.runtime.core.FlowGraph;
+import org.onap.dcae.runtime.core.FlowGraphParser;
 import org.onap.dcae.runtime.core.FlowGraphParser.BlueprintVessel;
-import org.onap.dcae.runtime.web.exception.ActionsNotDefinedException;
+import org.onap.dcae.runtime.core.Node;
 import org.onap.dcae.runtime.web.exception.MainGraphAlreadyExistException;
 import org.onap.dcae.runtime.web.exception.MainGraphNotFoundException;
-import org.onap.dcae.runtime.web.models.Action;
 import org.onap.dcae.runtime.web.models.DistributeGraphRequest;
 import org.onap.dcae.runtime.web.models.GraphRequest;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,6 +46,9 @@ public class GraphServiceImpl implements GraphService{
     @Autowired
     private FlowGraphParser flowGraphParser;
 
+    @Autowired
+    private GraphActionsParser actionsParser;
+
     @Override
     public FlowGraph<Node, Edge> getMainGraph() {
         if(mainFlowGraph == null){
@@ -74,7 +77,7 @@ public class GraphServiceImpl implements GraphService{
     public List<BlueprintVessel> distribute(DistributeGraphRequest distributeGraphRequest) {
         //1.Iterate through list of actions
         logger.info("applying actions to graph");
-        applyActionsToGraph(distributeGraphRequest);
+        actionsParser.applyActionsToGraph(mainFlowGraph, distributeGraphRequest);
 
         //2. generate blueprint from compspec of the node
         logger.info("generating blueprints for the affected nodes");
@@ -99,56 +102,5 @@ public class GraphServiceImpl implements GraphService{
         return flowGraphParser.createAndProcessBlueprints();
     }
 
-    private void applyActionsToGraph(DistributeGraphRequest distributeGraphRequest) {
-        if(distributeGraphRequest.getActions() == null){
-            throw new ActionsNotDefinedException("Action(s) must be defined in the request");
-        }
-        for(Action action : distributeGraphRequest.getActions()){
-            if(action.getCommand().equals("addnode")){
-                Node node = prepareNodeFromAddNAddNodeAction(action);
-                mainFlowGraph.addNode(node);
-            }
-            else if(action.getCommand().equals("addedge")) {
-                Edge edge = prepareEdgeFromAddEdgeAction(action);
-                Node srcNode = flowGraphParser.getNodeFromId(edge.getSrc().getNode());
-                Node tgtNode = flowGraphParser.getNodeFromId(edge.getTgt().getNode());
-                srcNode = fillPlaceholderIfNodeIsEmpty(srcNode);
-                tgtNode =fillPlaceholderIfNodeIsEmpty(tgtNode);
-                mainFlowGraph.addEdge(srcNode,tgtNode,edge);
-            }
-        }
-    }
-
-    private Node fillPlaceholderIfNodeIsEmpty(Node node) {
-        if (node == null) {
-            node = flowGraphParser.getNodeFromId("dummy_id");
-        }
-        return node;
-    }
-
-
-    private Edge prepareEdgeFromAddEdgeAction(Action action) {
-        ObjectMapper objectMapper = new ObjectMapper();
-        Edge edge = objectMapper.convertValue(action.getPayload(),Edge.class);
-        return edge;
-    }
-
-    private void fillPlaceholderIfLocaionsAreEmpty(Edge edge) {
-        if(edge.getSrc().getNode() == null && edge.getSrc().getPort() == null){
-            EdgeLocation src = new EdgeLocation("node-id-placeholder", "node-port-placeholder");
-            edge.setSrc(src);
-        }
-        if(edge.getTgt().getNode() == null && edge.getTgt().getPort() == null){
-            EdgeLocation tgt = new EdgeLocation("node-id-placeholder", "node-port-placeholder");
-            edge.setTgt(tgt);
-        }
-    }
-
-    private Node prepareNodeFromAddNAddNodeAction(Action action) {
-        String componentId = (String) action.getPayload().get("component_id");
-        String componentName = (String) action.getPayload().get("name");
-        String componentSpec = (String) action.getPayload().get("component_spec");
-        return new Node(componentId,componentName,componentSpec);
-    }
 
 }
index f3b06aa..31d56d8 100644 (file)
@@ -24,3 +24,15 @@ onap.import.postgresPlugin=https://nexus.onap.org/service/local/repositories/raw
 onap.import.clampPlugin=https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R6/clamppolicyplugin/1.1.0/clamppolicyplugin_types.yaml
 
 onap.import.dmaapPlugin= https://nexus.onap.org/content/repositories/raw/org.onap.ccsdk.platform.plugins/type_files/dmaap/dmaap.yaml
+
+# The artifact type can be BLUEPRINT or HELM
+artifact.type=BLUEPRINT
+
+#set these properties if artifact.type is HELM
+helm.base.chart.template.location=./data/helm-base-template
+
+chartmuseum.baseurl=http://localhost:8081
+
+chartmuseum.auth.basic.username=
+
+chartmuseum.auth.basic.password=
index d38f0b4..fa5463d 100644 (file)
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
+## [1.0.1]- 2021-10-04
+
+*  [DCAEGEN2-2911] Refactor the code to make it more testable
+    - Converted some static methods to instance methods
+*  [DCAEGEN2-2911] Distributor throws an error if distribution fails
+*  [DCAEGEN2-2917] Add helm repo registry step when initializing the helm client
+    - Add "helm repo add ..."
+    - Add "helm deployment update" before linting
 
 ## [1.0.0]
 
index 3c6de24..d7edca3 100644 (file)
@@ -5,10 +5,10 @@
   <parent>
     <groupId>org.onap.dcaegen2.platform</groupId>
     <artifactId>helmchartgenerator</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>1.0.1-SNAPSHOT</version>
   </parent>
     <artifactId>helmchartgenerator-cli</artifactId>
-  <version>1.0.0-SNAPSHOT</version>
+  <version>1.0.1-SNAPSHOT</version>
   <name>helmchartgenerator-cli</name>
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -17,7 +17,7 @@
     <dependency>
       <groupId>org.onap.dcaegen2.platform</groupId>
       <artifactId>helmchartgenerator-core</artifactId>
-      <version>1.0.0-SNAPSHOT</version>
+      <version>1.0.1-SNAPSHOT</version>
     </dependency>
   </dependencies>
   <build>
index 20b2c17..122a535 100644 (file)
@@ -26,7 +26,7 @@ import org.springframework.test.context.junit.jupiter.DisabledIf;
  * Disabling the test as it is using 'helm' command from the local environment.
  */
 @DisabledIf("true")
-@SpringBootTest(args = {"src/test/input/specs/ves.json", "src/test/input/blueprint", "src/test/output/charts"})
+@SpringBootTest(args = {"src/test/input-new/specs/ves.json", "src/test/input-new/blueprint", "src/test/output/charts", "--distribute"})
 class HelmChartGeneratorApplicationTests {
 
        @Test
index be8e39b..4dbbd3b 100644 (file)
@@ -5,10 +5,10 @@
     <parent>
         <groupId>org.onap.dcaegen2.platform</groupId>
         <artifactId>helmchartgenerator</artifactId>
-        <version>1.0.0-SNAPSHOT</version>
+        <version>1.0.1-SNAPSHOT</version>
     </parent>
     <artifactId>helmchartgenerator-core</artifactId>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>1.0.1-SNAPSHOT</version>
     <name>helmchartgenerator-core</name>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
index 83c67b1..a252886 100644 (file)
@@ -21,6 +21,7 @@ package org.onap.dcaegen2.platform.helmchartgenerator;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
+import org.springframework.stereotype.Component;
 
 import java.io.File;
 import java.io.IOException;
@@ -33,13 +34,12 @@ import java.util.Map;
  * @author Dhrumin Desai
  */
 @Slf4j
+@Component
 public class Utils {
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private final ObjectMapper MAPPER = new ObjectMapper();
 
-    private Utils() {}
-
-    public static <T> T deserializeJsonFileToModel(String filePath, Class<T> modelClass) {
+    public <T> T deserializeJsonFileToModel(String filePath, Class<T> modelClass) {
         return deserializeJsonFileToModel(new File(filePath), modelClass);
     }
 
@@ -49,7 +49,7 @@ public class Utils {
      * @param modelClass target model class for mapping
      * @return mapped model instance
      */
-    public static <T> T deserializeJsonFileToModel(File file, Class<T> modelClass) {
+    public <T> T deserializeJsonFileToModel(File file, Class<T> modelClass) {
         try {
             return MAPPER.readValue(file, modelClass);
         } catch (IOException e) {
@@ -63,7 +63,7 @@ public class Utils {
      * @param srcLocation
      * @return
      */
-    public static File cloneFileToTempLocation(String srcLocation) {
+    public File cloneFileToTempLocation(String srcLocation) {
         File cloneLocation = null;
         try {
             Path tempRootDir = Files.createTempDirectory("chart");
@@ -81,7 +81,7 @@ public class Utils {
      * deletes dir / file from temp location of OS
      * @param dir  dir to be deleted
      */
-    public static void deleteTempFileLocation(File dir) {
+    public void deleteTempFileLocation(File dir) {
         try {
             FileUtils.deleteDirectory(dir);
         } catch (IOException e) {
@@ -95,7 +95,7 @@ public class Utils {
      * @param key a key
      * @param value a value
      */
-    public static void putIfNotNull(Map<String, Object> map, String key, Object value){
+    public void putIfNotNull(Map<String, Object> map, String key, Object value){
         if(value != null){
             map.put(key, value);
         }
index ac73544..21f5dae 100644 (file)
@@ -41,14 +41,20 @@ public class ChartBuilder {
    @Autowired
    private ChartGenerator chartGenerator;
 
+   @Autowired
+   private ChartTemplateStructureValidator validator;
+
     /**
      * constructor of ChartBuilder
      * @param specParser implementation of ComponentSpecParser
      * @param chartGenerator implementation of ChartGenerator
+     * @param validator implementation of Chart Template Validator
      */
-    public ChartBuilder(ComponentSpecParser specParser, ChartGenerator chartGenerator) {
+    public ChartBuilder(ComponentSpecParser specParser, ChartGenerator chartGenerator,
+                        ChartTemplateStructureValidator validator) {
         this.specParser = specParser;
         this.chartGenerator = chartGenerator;
+        this.validator = validator;
     }
 
     /**
@@ -61,7 +67,7 @@ public class ChartBuilder {
      * @throws Exception
      */
     public File build(String specFileLocation, String chartTemplateLocation, String outputLocation, String specSchemaLocation ) throws Exception {
-        ChartTemplateStructureValidator.validateChartTemplateStructure(chartTemplateLocation);
+        validator.validateChartTemplateStructure(chartTemplateLocation);
         ChartInfo chartInfo = specParser.extractChartInfo(specFileLocation, chartTemplateLocation, specSchemaLocation);
         return chartGenerator.generate(chartTemplateLocation, chartInfo, outputLocation);
     }
index b9980d7..be02d68 100644 (file)
 
 package org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder;
 
-import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
+import org.onap.dcaegen2.platform.helmchartgenerator.Utils;
 import org.onap.dcaegen2.platform.helmchartgenerator.models.chartinfo.ChartInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.io.File;
 
-import static org.onap.dcaegen2.platform.helmchartgenerator.Utils.cloneFileToTempLocation;
-import static org.onap.dcaegen2.platform.helmchartgenerator.Utils.deleteTempFileLocation;
-
 /**
  * ChartGenerator interacts with HelmClient and generates a packaged helm chart
  * @author Dhrumin Desai
@@ -37,22 +34,25 @@ import static org.onap.dcaegen2.platform.helmchartgenerator.Utils.deleteTempFile
 @Slf4j
 public class ChartGenerator {
 
-    @Setter
     @Autowired
     private HelmClient helmClient;
 
-    @Setter
     @Autowired
     private KeyValueMerger merger;
 
+    @Autowired
+    private Utils utils;
+
     /**
      * Constructor for ChartGenerator
      * @param helmClient HelmClient implementation
      * @param merger KeyValueMerger implementation
+     * @param utils
      */
-    public ChartGenerator(HelmClient helmClient, KeyValueMerger merger) {
+    public ChartGenerator(HelmClient helmClient, KeyValueMerger merger, Utils utils) {
         this.helmClient = helmClient;
         this.merger = merger;
+        this.utils = utils;
     }
 
     /**
@@ -63,11 +63,11 @@ public class ChartGenerator {
      * @return generated helm chart tgz file
      */
     public File generate(String chartBlueprintLocation, ChartInfo chartInfo, String outputLocation) {
-        File newChartDir = cloneFileToTempLocation(chartBlueprintLocation + "/base");
+        File newChartDir = utils.cloneFileToTempLocation(chartBlueprintLocation + "/base");
         merger.mergeValuesToChart(chartInfo, newChartDir);
         helmClient.lint(newChartDir);
         final File chartLocation = helmClient.packageChart(newChartDir, outputLocation);
-        deleteTempFileLocation(newChartDir);
+        utils.deleteTempFileLocation(newChartDir);
         return chartLocation;
     }
 }
index 942e5ae..b0830d1 100644 (file)
@@ -18,7 +18,6 @@
 
 package org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder;
 
-import org.jetbrains.annotations.NotNull;
 import org.onap.dcaegen2.platform.helmchartgenerator.Utils;
 import org.onap.dcaegen2.platform.helmchartgenerator.models.chartinfo.ChartInfo;
 import org.onap.dcaegen2.platform.helmchartgenerator.models.chartinfo.Metadata;
@@ -55,12 +54,17 @@ public class ComponentSpecParser {
     @Autowired
     private ComponentSpecValidator specValidator;
 
+    @Autowired
+    private Utils utils;
+
     /**
      * Constructor for ComponentSpecParser
      * @param specValidator ComponentSpecValidator implementation
+     * @param utils
      */
-    public ComponentSpecParser(ComponentSpecValidator specValidator) {
+    public ComponentSpecParser(ComponentSpecValidator specValidator, Utils utils) {
         this.specValidator = specValidator;
+        this.utils = utils;
     }
 
     /**
@@ -73,7 +77,7 @@ public class ComponentSpecParser {
      */
     public ChartInfo extractChartInfo(String specFileLocation, String chartTemplateLocation, String specSchemaLocation) throws Exception {
         specValidator.validateSpecFile(specFileLocation, specSchemaLocation);
-        ComponentSpec cs = Utils.deserializeJsonFileToModel(specFileLocation, ComponentSpec.class);
+        ComponentSpec cs = utils.deserializeJsonFileToModel(specFileLocation, ComponentSpec.class);
         ChartInfo chartInfo = new ChartInfo();
         chartInfo.setMetadata(extractMetadata(cs.getSelf()));
         chartInfo.setValues(extractValues(cs, chartTemplateLocation));
@@ -83,14 +87,14 @@ public class ComponentSpecParser {
     private Map<String, Object> extractValues(ComponentSpec cs, String chartTemplateLocation) {
         Map<String, Object> outerValues = new LinkedHashMap<>();
         if(cs.getAuxilary() != null && cs.getAuxilary().getTlsInfo() != null){
-            Utils.putIfNotNull(outerValues,"certDirectory", cs.getAuxilary().getTlsInfo().getCertDirectory());
-            Utils.putIfNotNull(outerValues, "tlsServer", cs.getAuxilary().getTlsInfo().getUseTls());
+            utils.putIfNotNull(outerValues,"certDirectory", cs.getAuxilary().getTlsInfo().getCertDirectory());
+            utils.putIfNotNull(outerValues, "tlsServer", cs.getAuxilary().getTlsInfo().getUseTls());
         }
         if(cs.getAuxilary() != null && cs.getAuxilary().getLogInfo() != null) {
-            Utils.putIfNotNull(outerValues,"logDirectory", cs.getAuxilary().getLogInfo().get("log_directory"));
+            utils.putIfNotNull(outerValues,"logDirectory", cs.getAuxilary().getLogInfo().get("log_directory"));
         }
         if(imageUriExistsForFirstArtifact(cs)){
-            Utils.putIfNotNull(outerValues,"image", cs.getArtifacts()[0].getUri());
+            utils.putIfNotNull(outerValues,"image", cs.getArtifacts()[0].getUri());
         }
         populateApplicationConfigSection(outerValues, cs);
         populateReadinessSection(outerValues, cs);
@@ -115,7 +119,7 @@ public class ComponentSpecParser {
          for(Parameters param : parameters){
             applicationConfig.put(param.getName(), param.getValue());
          }
-         Utils.putIfNotNull(outerValues,"applicationConfig", applicationConfig);
+        utils.putIfNotNull(outerValues,"applicationConfig", applicationConfig);
     }
 
     private void populateReadinessSection(Map<String, Object> outerValues, ComponentSpec cs) {
@@ -124,7 +128,7 @@ public class ComponentSpecParser {
 
         Map<String, Object> readiness = new LinkedHashMap<>();
         final HealthCheck healthcheck = cs.getAuxilary().getHealthcheck();
-        Utils.putIfNotNull(readiness, "initialDelaySeconds", healthcheck.getInitialDelaySeconds());
+        utils.putIfNotNull(readiness, "initialDelaySeconds", healthcheck.getInitialDelaySeconds());
 
         if(healthcheck.getInterval() != null) {
             readiness.put("periodSeconds", getSeconds(healthcheck.getInterval(), "interval"));
@@ -159,7 +163,7 @@ public class ComponentSpecParser {
     private void populateApplicationEnvSection(Map<String, Object> outerValues, ComponentSpec cs){
         if(applicationEnvExists(cs)) {
             Object applicationEnv = cs.getAuxilary().getHelm().getApplicationEnv();
-            Utils.putIfNotNull(outerValues,"applicationEnv", applicationEnv);
+            utils.putIfNotNull(outerValues,"applicationEnv", applicationEnv);
         }
     }
 
@@ -178,10 +182,10 @@ public class ComponentSpecParser {
         if(serviceFromSpec.getPorts() != null){
             List<Object> ports = mapServicePorts(serviceFromSpec.getPorts());
             service.put("ports", ports);
-            Utils.putIfNotNull(service, "type", serviceFromSpec.getType());
+            utils.putIfNotNull(service, "type", serviceFromSpec.getType());
         }
-        Utils.putIfNotNull(service,"name", serviceFromSpec.getName());
-        Utils.putIfNotNull(service,"has_internal_only_ports", serviceFromSpec.getHasInternalOnlyPorts());
+        utils.putIfNotNull(service,"name", serviceFromSpec.getName());
+        utils.putIfNotNull(service,"has_internal_only_ports", serviceFromSpec.getHasInternalOnlyPorts());
         outerValues.put("service", service);
     }
 
@@ -230,8 +234,8 @@ public class ComponentSpecParser {
             keystore.put("outputType", List.of("jks"));
             keystore.put("passwordSecretRef", passwordsSecretRef);
             certificate.put("mountPath", mountPath);
-            Utils.putIfNotNull(certificate,"commonName", cs.getSelf().getName());
-            Utils.putIfNotNull(certificate,"dnsNames", List.of(cs.getSelf().getName()));
+            utils.putIfNotNull(certificate,"commonName", cs.getSelf().getName());
+            utils.putIfNotNull(certificate,"dnsNames", List.of(cs.getSelf().getName()));
             certificate.put("keystore", keystore);
             outerValues.put("certificates", List.of(certificate));
         }
index 098ddda..83bc477 100644 (file)
@@ -19,6 +19,7 @@
 package org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder;
 
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
 import java.io.BufferedReader;
@@ -26,6 +27,7 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.util.stream.Collectors;
 
 /**
  * HelmClient implementation which uses helm command installed in the runtime environment.
@@ -35,12 +37,40 @@ import java.io.InputStreamReader;
 @Slf4j
 public class HelmClientImpl implements HelmClient {
 
+    private final String repoUrl;
+
+    private final String username;
+
+    private final String password;
+
+    public HelmClientImpl(@Value("${chartmuseum.baseurl}")String repoUrl,
+                          @Value("${chartmuseum.auth.basic.username}")String username,
+                          @Value("${chartmuseum.auth.basic.password}")String password) {
+        this.repoUrl = repoUrl;
+        this.username = username;
+        this.password = password;
+        try{
+            repoAdd(repoUrl, username,password);
+        }catch (Exception e){
+            log.warn("Could not add helm repo.");
+        }
+    }
+
+    private void repoAdd(String repoUrl, String username, String password) {
+        ProcessBuilder builder = new ProcessBuilder();
+        builder.inheritIO();
+        builder.command("helm", "repo", "add", "local",  repoUrl,
+                        "--username", username, "--password", password);
+        runProcess(builder, "repoAdd");
+    }
+
     /**
      * performs <code>helm lint</code> operation
      * @param chartLocation helm chart location
      */
     @Override
     public void lint(File chartLocation) {
+        helmDepUp(chartLocation.getAbsolutePath());
         ProcessBuilder builder = new ProcessBuilder();
         builder.command("helm", "lint", chartLocation.getAbsolutePath());
         runProcess(builder, "lint");
@@ -60,16 +90,24 @@ public class HelmClientImpl implements HelmClient {
         return runProcess(builder, "package");
     }
 
+    private void helmDepUp(String chartLocation) {
+        ProcessBuilder builder = new ProcessBuilder();
+        builder.inheritIO();
+        builder.command("helm", "dep", "up",chartLocation);
+        runProcess(builder, "helmDepUp");
+    }
+
     private File runProcess(ProcessBuilder builder, String command) {
+        log.info("running: " + String.join(" ",builder.command()));
         Process process = null;
         String chartPath = "";
         try {
             process = builder.start();
-            if(command.equals("lint")) {
-                printLintingProcessOutput(process);
+            if(command.equals("package")) {
+                chartPath = printPackagingProcessOutput(process);
             }
             else {
-                chartPath = printPackagingProcessOutput(process);
+                printProcessOutput(process);
             }
             assertExitCode(process);
         }  catch (IOException e) {
@@ -83,7 +121,7 @@ public class HelmClientImpl implements HelmClient {
         return new File(chartPath);
     }
 
-    private void printLintingProcessOutput(Process process) throws IOException {
+    private void printProcessOutput(Process process) throws IOException {
         final InputStream inputStream = process.getInputStream();
         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
         reader.lines().forEach(log::info);
index ed861b0..ab0b964 100644 (file)
@@ -40,14 +40,19 @@ import java.util.Objects;
 @Slf4j
 public class ChartMuseumDistributor implements ChartDistributor {
 
-    @Value("${chartmuseum.baseurl}")
-    private String chartMuseumUrl;
+    private final String chartMuseumUrl;
 
-    @Value("${chartmuseum.auth.basic.username}")
-    private String username;
+    private final String username;
 
-    @Value("${chartmuseum.auth.basic.password}")
-    private String password;
+    private final String password;
+
+    public ChartMuseumDistributor( @Value("${chartmuseum.baseurl}") String chartMuseumUrl,
+                                   @Value("${chartmuseum.auth.basic.username}") String username,
+                                   @Value("${chartmuseum.auth.basic.password}")String password) {
+        this.chartMuseumUrl = chartMuseumUrl;
+        this.username = username;
+        this.password = password;
+    }
 
     /**
      * distributes chart to Chart Museum
@@ -60,6 +65,9 @@ public class ChartMuseumDistributor implements ChartDistributor {
         try {
             Response response = client.newCall(request).execute();
             log.info(Objects.requireNonNull(response.body()).string());
+            if(!response.isSuccessful()){
+                throw new RuntimeException("Distribution Failed.");
+            }
         } catch (IOException e) {
             throw new RuntimeException(e.getMessage());
         }
@@ -70,7 +78,7 @@ public class ChartMuseumDistributor implements ChartDistributor {
         MediaType mediaType = MediaType.parse("application/octet-stream");
         RequestBody body = RequestBody.create(chartFile, mediaType);
         return new Request.Builder()
-                .url(chartMuseumUrl)
+                .url(chartMuseumUrl + "/api/charts")
                 .method("POST", body)
                 .addHeader("Content-Type", "application/octet-stream")
                 .addHeader("Authorization", credential)
index 796ee91..07b97c9 100644 (file)
 
 package org.onap.dcaegen2.platform.helmchartgenerator.validation;
 
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
 /**
- * A class to validate structure of the base helm directory
+ * An interface to validate structure of the base helm directory
  */
-public class ChartTemplateStructureValidator {
-
-    /**
-     * validates base helm chart directory and throws error if the structure is not proper.
-     * @param chartTemplateLocation base helm chart dir location
-     */
-    public static void validateChartTemplateStructure(String chartTemplateLocation) {
-        checkBaseDirectory(chartTemplateLocation);
-    }
-
-    private static void checkBaseDirectory(String chartTemplateLocation) {
-        Path base = Paths.get(chartTemplateLocation, "base");
-        Path charts = Paths.get(chartTemplateLocation, "base/charts");
-        Path templates = Paths.get(chartTemplateLocation, "base/templates");
-        Path chart = Paths.get(chartTemplateLocation, "base/Chart.yaml");
-        Path values = Paths.get(chartTemplateLocation, "base/values.yaml");
-        if(!Files.exists(base)){
-            throw new RuntimeException("base directory not found in chart template location");
-        }
-        if(!Files.exists(charts)){
-            throw new RuntimeException("charts directory not found in base directory");
-        }
-        if(!Files.exists(templates)){
-            throw new RuntimeException("templates directory not found in base directory");
-        }
-        if(!Files.exists(chart)){
-            throw new RuntimeException("chart.yaml not found in base directory");
-        }
-        if(!Files.exists(values)){
-            throw new RuntimeException("values.yaml not found in base directory");
-        }
-    }
+public interface ChartTemplateStructureValidator {
+    void validateChartTemplateStructure(String chartTemplateLocation);
 }
diff --git a/mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/validation/ChartTemplateStructureValidatorImpl.java b/mod2/helm-generator/helmchartgenerator-core/src/main/java/org/onap/dcaegen2/platform/helmchartgenerator/validation/ChartTemplateStructureValidatorImpl.java
new file mode 100644 (file)
index 0000000..6c22108
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2021 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.platform.helmchartgenerator.validation;
+
+import org.springframework.stereotype.Component;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * A class to validate structure of the base helm directory
+ */
+@Component
+public class ChartTemplateStructureValidatorImpl implements ChartTemplateStructureValidator {
+
+    /**
+     * validates base helm chart directory and throws error if the structure is not proper.
+     * @param chartTemplateLocation base helm chart dir location
+     */
+    @Override
+    public void validateChartTemplateStructure(String chartTemplateLocation) {
+        checkBaseDirectory(chartTemplateLocation);
+    }
+
+    private void checkBaseDirectory(String chartTemplateLocation) {
+        Path base = Paths.get(chartTemplateLocation, "base");
+        Path templates = Paths.get(chartTemplateLocation, "base/templates");
+        Path chart = Paths.get(chartTemplateLocation, "base/Chart.yaml");
+        Path values = Paths.get(chartTemplateLocation, "base/values.yaml");
+        if(!Files.exists(base)){
+            throw new RuntimeException("base directory not found in chart template location");
+        }
+        if(!Files.exists(templates)){
+            throw new RuntimeException("templates directory not found in base directory");
+        }
+        if(!Files.exists(chart)){
+            throw new RuntimeException("chart.yaml not found in base directory");
+        }
+        if(!Files.exists(values)){
+            throw new RuntimeException("values.yaml not found in base directory");
+        }
+    }
+}
index a74cab1..fd1f19f 100644 (file)
@@ -26,6 +26,7 @@ import org.json.JSONObject;
 import org.json.JSONTokener;
 import org.onap.dcaegen2.platform.helmchartgenerator.Utils;
 import org.onap.dcaegen2.platform.helmchartgenerator.models.componentspec.base.ComponentSpec;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.stereotype.Service;
 
@@ -43,6 +44,13 @@ import java.io.InputStream;
 @Slf4j
 public class ComponentSpecValidatorImpl implements ComponentSpecValidator {
 
+    @Autowired
+    private Utils utils;
+
+    public ComponentSpecValidatorImpl(Utils utils) {
+        this.utils = utils;
+    }
+
     /**
      * Validates the spec json file  against schema and prints errors if found
      * @param specFileLocation specification json file location
@@ -52,7 +60,7 @@ public class ComponentSpecValidatorImpl implements ComponentSpecValidator {
     @Override
     public void validateSpecFile(String specFileLocation, String specSchemaLocation) throws IOException {
         File schemaFile = getSchemaFile(specSchemaLocation);
-        ComponentSpec cs = Utils.deserializeJsonFileToModel(specFileLocation, ComponentSpec.class);
+        ComponentSpec cs = utils.deserializeJsonFileToModel(specFileLocation, ComponentSpec.class);
         validateSpecSchema(new File(specFileLocation), schemaFile);
         validateHelmRequirements(cs);
     }
index df2005a..f033b65 100644 (file)
@@ -1,5 +1,5 @@
 spring.main.web-application-type=NONE
 
-chartmuseum.baseurl=http://localhost:8081/api/charts
+chartmuseum.baseurl=http://localhost:8081
 chartmuseum.auth.basic.username=TBD
 chartmuseum.auth.basic.password=TBD
\ No newline at end of file
diff --git a/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartBuilderTest.java b/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartBuilderTest.java
new file mode 100644 (file)
index 0000000..dd19382
--- /dev/null
@@ -0,0 +1,54 @@
+ /** # ============LICENSE_START=======================================================
+ * # Copyright (c) 2021 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+*/
+
+
+package org.onap.dcaegen2.platform.helmchartgenerator;
+
+ import org.junit.jupiter.api.Test;
+ import org.junit.jupiter.api.extension.ExtendWith;
+ import org.mockito.Mock;
+ import org.mockito.Mockito;
+ import org.mockito.junit.jupiter.MockitoExtension;
+ import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.ChartBuilder;
+ import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.ChartGenerator;
+ import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.ComponentSpecParser;
+ import org.onap.dcaegen2.platform.helmchartgenerator.validation.ChartTemplateStructureValidator;
+
+ import static org.mockito.ArgumentMatchers.any;
+
+ @ExtendWith(MockitoExtension.class)
+class ChartBuilderTest {
+
+    @Mock
+    private ChartGenerator chartGenerator;
+
+    @Mock
+    private ComponentSpecParser specParser;
+
+    @Mock
+    private ChartTemplateStructureValidator validator;
+
+    @Test
+    void testChartBuilderSteps() throws Exception{
+        ChartBuilder builder = new ChartBuilder(specParser, chartGenerator, validator);
+        builder.build("someSpec", "someChartLocation", "someOutputLocation", "someSpecSchemaLocation");
+
+        Mockito.verify(specParser, Mockito.times(1)).extractChartInfo(any(), any(), any());
+        Mockito.verify(chartGenerator, Mockito.times(1)).generate(any(), any(), any());
+        Mockito.verify(validator, Mockito.times(1)).validateChartTemplateStructure(any());
+    }
+}
diff --git a/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartGeneratorTest.java b/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartGeneratorTest.java
new file mode 100644 (file)
index 0000000..1c2c9bc
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2021 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+
+package org.onap.dcaegen2.platform.helmchartgenerator;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.ChartGenerator;
+import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.HelmClient;
+import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.KeyValueMerger;
+import org.onap.dcaegen2.platform.helmchartgenerator.models.chartinfo.ChartInfo;
+
+import static org.mockito.ArgumentMatchers.any;
+
+@ExtendWith(MockitoExtension.class)
+class ChartGeneratorTest {
+
+    @Mock
+    private KeyValueMerger kvMerger;
+
+    @Mock
+    private HelmClient helmClient;
+
+    @Mock
+    private Utils utils;
+
+    @Test
+    void testChartGenerationSteps() throws Exception{
+        ChartGenerator chartGenerator = new ChartGenerator(helmClient, kvMerger, utils);
+        Mockito.when(utils.cloneFileToTempLocation(any())).thenReturn(any());
+
+        chartGenerator.generate("src/test/input/blueprint", new ChartInfo(), "src/test/output");
+
+        Mockito.verify(kvMerger, Mockito.times(1)).mergeValuesToChart(any(), any());
+        Mockito.verify(helmClient, Mockito.times(1)).lint(any());
+        Mockito.verify(helmClient, Mockito.times(1)).packageChart(any(), any());
+    }
+
+}
diff --git a/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartMuseumDistributorTest.java b/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/ChartMuseumDistributorTest.java
new file mode 100644 (file)
index 0000000..c0d0663
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2021 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.platform.helmchartgenerator;
+
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.dcaegen2.platform.helmchartgenerator.distribution.ChartMuseumDistributor;
+
+import java.io.File;
+import java.io.IOException;
+
+public class ChartMuseumDistributorTest {
+
+    ChartMuseumDistributor distributor;
+
+    public static MockWebServer mockChartMuseumServer;
+
+    private static File mockChartFile;
+
+    @BeforeAll
+    static void init() throws IOException {
+        mockChartMuseumServer = new MockWebServer();
+        mockChartMuseumServer.start();
+        mockChartFile = File.createTempFile("dcae-ves-collector-1.8.0","tgz");
+    }
+
+    @BeforeEach
+    void setUp(){
+        String baseUrl = String.format("http://localhost:%s",
+                mockChartMuseumServer.getPort());
+        distributor = new ChartMuseumDistributor(baseUrl, "mockUsername", "mockPassword");
+    }
+
+    @Test
+    void distribute() throws Exception{
+        mockChartMuseumServer.enqueue(getMock201Response());
+        distributor.distribute(mockChartFile);
+    }
+
+    private MockResponse getMock201Response() {
+        return new MockResponse()
+                .setResponseCode(201)
+                .setBody("{\"saved\": true}");
+    }
+
+
+    @AfterAll
+    static void tearDown() throws IOException {
+        mockChartMuseumServer.shutdown();
+        FileUtils.deleteQuietly(mockChartFile);
+    }
+}
+
index 9bef191..3e94b64 100644 (file)
 
 package org.onap.dcaegen2.platform.helmchartgenerator;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.onap.dcaegen2.platform.helmchartgenerator.validation.ChartTemplateStructureValidator;
+import org.onap.dcaegen2.platform.helmchartgenerator.validation.ChartTemplateStructureValidatorImpl;
 
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 public class ChartTemplateStructureValidatorTest {
 
+    private ChartTemplateStructureValidatorImpl validator;
+
+    @BeforeEach
+    void setUp() {
+        validator = new ChartTemplateStructureValidatorImpl();
+    }
+
     @Test
     void validateTemplateStructure(){
         String validStructureLocation = "src/test/input/blueprint";
-        assertDoesNotThrow(() -> ChartTemplateStructureValidator.validateChartTemplateStructure(validStructureLocation));
+        assertDoesNotThrow(() -> validator.validateChartTemplateStructure(validStructureLocation));
     }
 
     @Test
     void invalidateTemplateStructureShouldThrowRuntimeError() {
         String invalidStructureLocation = "test";
-        assertThrows(RuntimeException.class, () -> ChartTemplateStructureValidator.validateChartTemplateStructure(invalidStructureLocation));
+        assertThrows(RuntimeException.class, () -> validator.validateChartTemplateStructure(invalidStructureLocation));
     }
 }
index c14edda..0f157d3 100644 (file)
@@ -44,7 +44,7 @@ class ComponentSpecParserTest {
 
     @BeforeEach
     void setUp() {
-        parser = new ComponentSpecParser(validator);
+        parser = new ComponentSpecParser(validator, new Utils());
     }
 
     @Test
@@ -183,4 +183,5 @@ class ComponentSpecParserTest {
         assertThat(secret1.get("password")).isEqualTo("{{ .Values.postgres.config.pgUserPassword }}");
         assertThat(secret1.get("passwordPolicy")).isEqualTo("generate");
     }
-}
\ No newline at end of file
+}
+
diff --git a/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/KeyValueMergerTest.java b/mod2/helm-generator/helmchartgenerator-core/src/test/java/org/onap/dcaegen2/platform/helmchartgenerator/KeyValueMergerTest.java
new file mode 100644 (file)
index 0000000..4082170
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2021 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.platform.helmchartgenerator;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder.KeyValueMerger;
+import org.onap.dcaegen2.platform.helmchartgenerator.models.chartinfo.ChartInfo;
+import org.onap.dcaegen2.platform.helmchartgenerator.models.chartinfo.Metadata;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.ArgumentMatchers.any;
+
+@ExtendWith(MockitoExtension.class)
+class KeyValueMergerTest {
+
+    private KeyValueMerger merger;
+
+    @Mock
+    private Yaml yamlHelper;
+
+    private File chartDir;
+
+    @BeforeEach
+    void setUp() {
+        merger = new KeyValueMerger(yamlHelper);
+    }
+
+    @Test
+    void mergeValuesToChart() throws IOException {
+        ChartInfo chartInfo = prepareChartInfo();
+        chartDir = prepareChartDir();
+
+        Mockito.when(yamlHelper.load(any(InputStream.class))).thenReturn(new HashMap<String, Object>());
+
+        merger.mergeValuesToChart(chartInfo, chartDir);
+        Mockito.verify(yamlHelper, Mockito.times(2)).dump(any(HashMap.class), any(PrintWriter.class));
+    }
+
+    @AfterEach
+    void tearDown(){
+        FileUtils.deleteQuietly(chartDir);
+    }
+
+    private File prepareChartDir() throws IOException {
+        final Path chartDir = Files.createTempDirectory("chartDir");
+        Files.createFile(chartDir.resolve("Chart.yaml"));
+        Files.createFile(chartDir.resolve("values.yaml"));
+        return chartDir.toFile();
+    }
+
+    private ChartInfo prepareChartInfo() {
+        ChartInfo chartInfo = new ChartInfo();
+
+        Metadata metadata = new Metadata();
+        metadata.setName("someComponent");
+        metadata.setVersion("someVersion");
+        metadata.setDescription("someDescription");
+
+        Map<String, Object> values = new HashMap<>();
+        values.put("someKey", "someValue");
+
+        chartInfo.setMetadata(metadata);
+        chartInfo.setValues(values);
+
+        return chartInfo;
+    }
+}
+
index 8f7e8aa..d4149f2 100644 (file)
@@ -1 +1,3 @@
-lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = true
+
index dc87a54..7f9801c 100644 (file)
@@ -33,7 +33,7 @@
 
        <groupId>org.onap.dcaegen2.platform</groupId>
        <artifactId>helmchartgenerator</artifactId>
-       <version>1.0.0-SNAPSHOT</version>
+       <version>1.0.1-SNAPSHOT</version>
        <name>helm-chart-generator</name>
        <description>Helm chart generator</description>
        <properties>
                        <artifactId>okhttp</artifactId>
                        <version>4.0.1</version>
                </dependency>
+               <dependency>
+                       <groupId>com.squareup.okhttp3</groupId>
+                       <artifactId>mockwebserver</artifactId>
+                       <version>4.0.1</version>
+                       <scope>test</scope>
+               </dependency>
        </dependencies>
        <dependencyManagement>
                <dependencies>