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
</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>
<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>
</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 -->
<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>
<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>
--- /dev/null
+/*-
+ * ============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);
+}
--- /dev/null
+/*-
+ * ============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());
+ }
+ }
+}
--- /dev/null
+{
+ "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
--- /dev/null
+/*-
+ * ============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);
+ }
+
+}
<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>
<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>
<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>
<descriptorRef>artifact</descriptorRef>
</assembly>
<runCmds>
- <runCmd>groupadd -r dcaemod && useradd -ms /bin/bash dcaemod -g dcaemod && mkdir -p /maven/data && chown -R dcaemod:dcaemod /maven/data</runCmd>
+ <runCmd>apt-get update && apt-get install -y wget</runCmd>
+ <runCmd>wget https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz && tar xvf helm-v3.0.2-linux-amd64.tar.gz && mv linux-amd64/helm /usr/local/bin/</runCmd>
+ <runCmd>groupadd -r dcaemod && useradd -ms /bin/bash dcaemod -g dcaemod && mkdir -p /maven/data && chown -R dcaemod:dcaemod /maven/data</runCmd>
</runCmds>
<workdir>/maven</workdir>
<volumes>
/*-
* ============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")
public class GraphController {
@Autowired
- private GraphServiceImpl graphService;
+ private GraphService graphService;
Logger logger = LoggerFactory.getLogger(GraphController.class);
/*-
* ============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.
*/
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;
JSONObject body = prepareBlueprintJsonObject(bpv.name, bpv.version, bpv.blueprint);
postToDashboard(body);
logger.info(String.format("Distributed: %s", bpv.toString()));
- //System.out.println(bpv.blueprint);
}
}
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;
}
--- /dev/null
+/*-
+ * ============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);
+ }
+}
--- /dev/null
+/*-
+ * ============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();
+ }
+}
/*-
* ============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;
@Autowired
private FlowGraphParser flowGraphParser;
+ @Autowired
+ private GraphActionsParser actionsParser;
+
@Override
public FlowGraph<Node, Edge> getMainGraph() {
if(mainFlowGraph == null){
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");
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);
- }
}
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=
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]
<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>
<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>
* 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
<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>
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;
* @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);
}
* @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) {
* @param srcLocation
* @return
*/
- public static File cloneFileToTempLocation(String srcLocation) {
+ public File cloneFileToTempLocation(String srcLocation) {
File cloneLocation = null;
try {
Path tempRootDir = Files.createTempDirectory("chart");
* 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) {
* @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);
}
@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;
}
/**
* @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);
}
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
@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;
}
/**
* @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;
}
}
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;
@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;
}
/**
*/
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));
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);
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) {
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"));
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);
}
}
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);
}
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));
}
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;
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.
@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");
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) {
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);
@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
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());
}
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)
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);
}
--- /dev/null
+/*
+ * # ============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");
+ }
+ }
+}
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;
@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
@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);
}
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
--- /dev/null
+ /** # ============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());
+ }
+}
--- /dev/null
+/*
+ * # ============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());
+ }
+
+}
--- /dev/null
+/*
+ * # ============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);
+ }
+}
+
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));
}
}
@BeforeEach
void setUp() {
- parser = new ComponentSpecParser(validator);
+ parser = new ComponentSpecParser(validator, new Utils());
}
@Test
assertThat(secret1.get("password")).isEqualTo("{{ .Values.postgres.config.pgUserPassword }}");
assertThat(secret1.get("passwordPolicy")).isEqualTo("generate");
}
-}
\ No newline at end of file
+}
+
@BeforeEach
void setUp() {
- validator = new ComponentSpecValidatorImpl();
+ validator = new ComponentSpecValidatorImpl(new Utils());
}
@Test
--- /dev/null
+/*
+ * # ============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;
+ }
+}
+
-lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = true
+
<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>