summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--Dockerfile25
-rw-r--r--Dockerfile-local21
-rw-r--r--Makefile18
-rw-r--r--README.md76
-rw-r--r--charts/correct-apiVersion-v1.tgzbin0 -> 393 bytes
-rw-r--r--charts/correct-apiVersion-v2.tgzbin0 -> 651 bytes
-rw-r--r--charts/error-bad-chart-yaml.tar.gzbin0 -> 209 bytes
-rw-r--r--charts/one-lint-one-render-error-apiVersion-v1.tgzbin0 -> 413 bytes
-rw-r--r--charts/one-lint-one-render-error-apiVersion-v2.tgzbin0 -> 668 bytes
-rw-r--r--charts/one-lint-warning-apiVersion-v2.tgzbin0 -> 738 bytes
-rw-r--r--charts/two-lint-warnings-apiVersion-v1.tgzbin0 -> 311 bytes
-rw-r--r--deployment.yaml44
-rw-r--r--pom.xml176
-rwxr-xr-xscripts/collect_helm_versions_from_web.sh43
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/HelmValidatorApplication.java33
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/api/SupportedVersionsController.java52
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/api/ValidationController.java68
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandler.java129
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorResponse.java34
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutor.java69
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/FileManager.java72
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/ValidationService.java221
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/BashExecutionException.java28
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/NotSupportedVersionException.java28
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/SaveFileException.java28
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/BashOutput.java43
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/LintValidationResult.java55
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/TemplateValidationResult.java48
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/ValidationResult.java98
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReader.java80
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProvider.java57
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProvider.java65
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReader.java47
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ApiVersionNotFoundException.java29
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/NotSupportedApiVersionException.java28
-rw-r--r--src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ReadFileException.java28
-rw-r--r--src/main/resources/application.properties4
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/HelmValidatorApplicationTests.java33
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/api/SupportedVersionsControllerTest.java67
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/api/ValidationControllerTest.java195
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandlerTest.java125
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutorTest.java43
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/helm/validation/FileManagerTest.java100
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/helm/validation/ValidationServiceTest.java314
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReaderTest.java128
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProviderTest.java73
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProviderTest.java72
-rw-r--r--src/test/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReaderTest.java69
-rw-r--r--version.properties6
50 files changed, 2986 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..23cc2f4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+/scripts/helm_tmp/*
+/scripts/helm_versions/*
+
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..e22a242
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,25 @@
+FROM nexus3.onap.org:10001/onap/integration-java11:8.0.0
+
+ARG VERSION=${version}
+
+USER root
+RUN adduser -G onap -D validator
+
+RUN apk add --no-cache bash vim curl wget
+
+ENV HELM_SUPPORTED_VERSIONS=3.5.2,3.4.1,3.3.4,2.17.0,2.14.3
+
+#Installing Helm
+COPY scripts/collect_helm_versions_from_web.sh ./opt/helmvalidator/tmp/collect_helm_versions_from_web.sh
+RUN chmod +x ./opt/helmvalidator/tmp/collect_helm_versions_from_web.sh
+RUN ./opt/helmvalidator/tmp/collect_helm_versions_from_web.sh
+RUN rm -r ./opt/helmvalidator/tmp
+
+RUN mkdir /charts
+RUN chown -R validator:onap /charts
+
+USER validator:onap
+
+COPY target/sdc-helm-validator-${VERSION}.jar ./opt/helmvalidator/helmvalidator.jar
+
+ENTRYPOINT ["java","-XX:+UseParallelGC","-XX:MinRAMPercentage=50","-XX:MaxRAMPercentage=50","-XX:MinHeapFreeRatio=10","-XX:MaxHeapFreeRatio=20","-jar","./opt/helmvalidator/helmvalidator.jar"]
diff --git a/Dockerfile-local b/Dockerfile-local
new file mode 100644
index 0000000..b1b378a
--- /dev/null
+++ b/Dockerfile-local
@@ -0,0 +1,21 @@
+FROM nexus3.onap.org:10001/onap/integration-java11:8.0.0
+
+ARG VERSION=${version}
+ENV HELM_SUPPORTED_VERSIONS=${HELM_SUPPORTED_VERSIONS}
+
+USER root
+RUN adduser -G onap -D validator
+
+RUN apk add --no-cache bash vim curl wget
+
+#Installing Helm
+COPY scripts/helm_versions/* /usr/local/bin/
+
+RUN mkdir /charts
+RUN chown -R validator:onap /charts
+
+USER validator:onap
+
+COPY target/sdc-helm-validator-${VERSION}.jar ./opt/helmvalidator/helmvalidator.jar
+
+ENTRYPOINT ["java","-XX:+UseParallelGC","-XX:MinRAMPercentage=50","-XX:MaxRAMPercentage=50","-XX:MinHeapFreeRatio=10","-XX:MaxHeapFreeRatio=20","-jar","./opt/helmvalidator/helmvalidator.jar"]
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a318769
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+build:
+ mvn clean install
+
+build-docker:
+ mvn clean install -Pdocker
+
+build-docker-local:
+ export HELM_SUPPORTED_VERSIONS=3.5.2,3.4.1,3.3.4,2.17.0 && \
+ cd scripts && \
+ ./collect_helm_versions_from_web.sh local && \
+ cd ../ && \
+ mvn clean install -Pdocker-local
+
+clean-local-files:
+ rm -rf ./scripts/helm_tmp ./scripts/helm_versions
+
+run-docker:
+ docker run -p 8080:8080 onap/org.onap.sdc.sdc-helm-validator:latest
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bb506c0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+# helm-client-validator
+
+Docker container with Spring-Boot application for validating helm charts.
+
+#### Development
+To build image use:
+```
+make build-docker
+```
+or
+```
+make build-docker-local
+```
+
+To modify helm versions:
+
+1. Modify `Dockerfile`, add desired version in line:
+```shell script
+ENV HELM_SUPPORTED_VERSIONS=3.5.2,3.4.1,3.3.4,2.17.0,2.14.3
+```
+2. In local development, edit file: `Makefile` and add desired version in lines:
+```shell script
+build-docker-local:
+ export HELM_SUPPORTED_VERSIONS=3.5.2,3.4.1,3.3.4,2.17.0
+```
+If you want to clean downloaded files run: `make clean-local-files`
+
+In order to run docker container locally use:
+```
+make run-docker
+```
+Example charts are located in the following directory:
+```
+./charts
+```
+
+## Available endpoints
+* Chart validation:
+
+ `http://localhost:[PORT]/validate`
+
+#### Request
+This should be a POST with `multipart/form-data` encoding with the following fields:
+
+ "versionDesired": [String] - helm version, which will be used for validation. If param not provided then version will be taken from apiVersion
+ "file": [FILE] - helm chart to be validated packed in .txz format
+ "isLinted": ["true"/"false"] - if false, there will be an attempt to render the chart without linting it first
+ "isStrictLinted": ["true"/"false"] - linting should be strict or not
+
+It is possible to provide helm version in three ways:
+1. Select exact version from supported versions e.g. "3.4.1"
+2. Select major helm version e.g. "v2" for Helm 2 or "v3" for Helm 3. In this case app will use the latest supported version.
+3. In case when field version is not present in request then app gets helm version from "apiVersion" field located in the main chart (Chart.yaml).
+Mapping rules:
+
+apiVersion: v1 -> the latest available helm 2
+
+apiVersion: v2 -> the latest available helm 3
+
+#### Response
+Json with the following fields:
+
+ "valid": ["true"/"false"] - passed linting without errors
+ "deployable": ["true"/"false"] - passed template rendering without errors
+ "lintErrors": [ARRAY OF STRINGS] - linting errors
+ "lintWarnings": [ARRAY OF STRINGS] - linting warnings
+ "renderErrors": [ARRAY OF STRINGS] - rendering errors
+
+* Supported versions [GET]
+
+ `http://localhost:[PORT]/versions`
+
+#### Response
+Following Json:
+
+ [ARRAY OF STRINGS] - supported helm versions
diff --git a/charts/correct-apiVersion-v1.tgz b/charts/correct-apiVersion-v1.tgz
new file mode 100644
index 0000000..9782071
--- /dev/null
+++ b/charts/correct-apiVersion-v1.tgz
Binary files differ
diff --git a/charts/correct-apiVersion-v2.tgz b/charts/correct-apiVersion-v2.tgz
new file mode 100644
index 0000000..a1a99ba
--- /dev/null
+++ b/charts/correct-apiVersion-v2.tgz
Binary files differ
diff --git a/charts/error-bad-chart-yaml.tar.gz b/charts/error-bad-chart-yaml.tar.gz
new file mode 100644
index 0000000..b7ce4e5
--- /dev/null
+++ b/charts/error-bad-chart-yaml.tar.gz
Binary files differ
diff --git a/charts/one-lint-one-render-error-apiVersion-v1.tgz b/charts/one-lint-one-render-error-apiVersion-v1.tgz
new file mode 100644
index 0000000..d17c118
--- /dev/null
+++ b/charts/one-lint-one-render-error-apiVersion-v1.tgz
Binary files differ
diff --git a/charts/one-lint-one-render-error-apiVersion-v2.tgz b/charts/one-lint-one-render-error-apiVersion-v2.tgz
new file mode 100644
index 0000000..874dd3c
--- /dev/null
+++ b/charts/one-lint-one-render-error-apiVersion-v2.tgz
Binary files differ
diff --git a/charts/one-lint-warning-apiVersion-v2.tgz b/charts/one-lint-warning-apiVersion-v2.tgz
new file mode 100644
index 0000000..51f4dd1
--- /dev/null
+++ b/charts/one-lint-warning-apiVersion-v2.tgz
Binary files differ
diff --git a/charts/two-lint-warnings-apiVersion-v1.tgz b/charts/two-lint-warnings-apiVersion-v1.tgz
new file mode 100644
index 0000000..54422c9
--- /dev/null
+++ b/charts/two-lint-warnings-apiVersion-v1.tgz
Binary files differ
diff --git a/deployment.yaml b/deployment.yaml
new file mode 100644
index 0000000..43b6f15
--- /dev/null
+++ b/deployment.yaml
@@ -0,0 +1,44 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: helm-client-validator
+ namespace: onap
+ labels:
+ app: helm-client-validator
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: helm-client-validator
+ template:
+ metadata:
+ labels:
+ app: helm-client-validator
+ spec:
+ containers:
+ - name: helm-client-validator
+ imagePullPolicy: IfNotPresent
+ image: onap-dev-local.esisoj70.emea.nsn-net.net/towrobel/helm-client-validator:1.5.0
+ resources:
+ requests:
+ memory: "256Mi"
+ limits:
+ memory: "256Mi"
+
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: helm-client-validator-service
+ namespace: onap
+ labels:
+ app: helm-client-validator
+spec:
+ selector:
+ app: helm-client-validator
+ type: NodePort
+ ports:
+ - port: 8244
+ targetPort: 8080
+ nodePort: 32244
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..d569680
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>3.2.0</version>
+ <relativePath/>
+ </parent>
+ <groupId>org.onap.sdc</groupId>
+ <artifactId>sdc-helm-validator</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>helmvalidator</name>
+ <description>Spring-Boot application for validating helm charts</description>
+
+ <properties>
+ <java.version>11</java.version>
+
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
+ <skipDockerPush>true</skipDockerPush>
+
+ <docker-maven-plugin.version>0.34.1</docker-maven-plugin.version>
+ <spring.version>2.4.3</spring.version>
+ <apache.commons.compress.version>1.20</apache.commons.compress.version>
+
+ <docker.dockerfile>Dockerfile</docker.dockerfile>
+ <docker-image.name>onap/${project.groupId}.${project.artifactId}</docker-image.name>
+ <docker-image.registry>${onap.nexus.dockerregistry.daily}</docker-image.registry>
+ <docker-image.tag.latest>latest</docker-image.tag.latest>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>${apache.commons.compress.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>${docker-maven-plugin.version}</version>
+ <configuration>
+ <skipPush>${skipDockerPush}</skipPush>
+ <verbose>true</verbose>
+ <imagePullPolicy>IfNotPresent</imagePullPolicy>
+ <images>
+ <image>
+ <alias>${project.artifactId}</alias>
+ <name>${docker-image.name}:${docker-image.tag.latest}</name>
+ <registry>${docker-image.registry}</registry>
+ <build>
+ <dockerFile>${docker.dockerfile}</dockerFile>
+ <contextDir>${project.basedir}</contextDir>
+ <tags>
+ <tag>${project.version}-${maven.build.timestamp}Z</tag>
+ </tags>
+ </build>
+ </image>
+ </images>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+<!--DEV-->
+ <profile>
+ <id>dev</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-devtools</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+ </profile>
+
+<!--DOCKER-->
+ <profile>
+ <id>docker</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>docker-build-image</id>
+ <phase>package</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
+ <profile>
+ <id>docker-local</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <properties>
+ <docker.dockerfile>Dockerfile-local</docker.dockerfile>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>docker-build-image</id>
+ <phase>package</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/scripts/collect_helm_versions_from_web.sh b/scripts/collect_helm_versions_from_web.sh
new file mode 100755
index 0000000..6155149
--- /dev/null
+++ b/scripts/collect_helm_versions_from_web.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+set -e
+
+HELM_TMP_DIR=helm_tmp
+HELM_VERSIONS_DIR=helm_versions
+IS_LOCAL=false
+if [ "$1" == "local" ]; then
+ IS_LOCAL=true
+fi
+
+readarray -d , -t SUPPORTED_VERSION_ARRAY <<<"$HELM_SUPPORTED_VERSIONS"
+
+mkdir -p $HELM_VERSIONS_DIR
+mkdir -p $HELM_TMP_DIR
+
+getHelm() {
+ VERSION=$1
+ echo "Attempt to collect HELM ${VERSION}"
+
+ if [ -a "$HELM_VERSIONS_DIR/helm-v${VERSION}" ]; then
+ echo "HELM ${VERSION} already exists"
+ else
+ mkdir -p $HELM_TMP_DIR/v${VERSION}
+ echo "Downloading..."
+ wget -q https://get.helm.sh/helm-v${VERSION}-linux-amd64.tar.gz -O $HELM_TMP_DIR/helm-v${VERSION}.tar.gz
+ echo "Archive Extracting..."
+ tar -zxvf $HELM_TMP_DIR/helm-v${VERSION}.tar.gz -C $HELM_TMP_DIR/v${VERSION} linux-amd64/helm
+ mv $HELM_TMP_DIR/v${VERSION}/linux-amd64/helm $HELM_VERSIONS_DIR/helm-v${VERSION}
+ fi
+
+ echo "DONE"
+}
+
+for i in "${SUPPORTED_VERSION_ARRAY[@]}"; do
+ getHelm $i
+done
+
+if [ $IS_LOCAL == false ]; then
+ mv $HELM_VERSIONS_DIR/* /usr/local/bin/
+ rm -r $HELM_VERSIONS_DIR
+ rm -r $HELM_TMP_DIR
+fi
diff --git a/src/main/java/org/onap/sdc/helmvalidator/HelmValidatorApplication.java b/src/main/java/org/onap/sdc/helmvalidator/HelmValidatorApplication.java
new file mode 100644
index 0000000..b8bed69
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/HelmValidatorApplication.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class HelmValidatorApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(HelmValidatorApplication.class, args);
+ }
+
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/api/SupportedVersionsController.java b/src/main/java/org/onap/sdc/helmvalidator/api/SupportedVersionsController.java
new file mode 100644
index 0000000..1a92624
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/api/SupportedVersionsController.java
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.api;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.onap.sdc.helmvalidator.helm.versions.SupportedVersionsProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class SupportedVersionsController {
+
+ private final SupportedVersionsProvider versionsProvider;
+
+ @Autowired
+ public SupportedVersionsController(SupportedVersionsProvider provider) {
+ this.versionsProvider = provider;
+ }
+
+ @GetMapping("/versions")
+ public ResponseEntity<Map<String, List<String>>> supportedVersions() {
+ return mapVersionsToResponseEntity(versionsProvider.getVersions());
+ }
+
+ private ResponseEntity<Map<String, List<String>>> mapVersionsToResponseEntity(List<String> versions) {
+
+ return new ResponseEntity<>(Collections.singletonMap("versions", versions), HttpStatus.OK);
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/api/ValidationController.java b/src/main/java/org/onap/sdc/helmvalidator/api/ValidationController.java
new file mode 100644
index 0000000..a4e476c
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/api/ValidationController.java
@@ -0,0 +1,68 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.api;
+
+import org.onap.sdc.helmvalidator.helm.validation.ValidationService;
+import org.onap.sdc.helmvalidator.helm.validation.model.ValidationResult;
+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.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+@RestController
+public class ValidationController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ValidationController.class);
+
+ private final ValidationService validationService;
+
+ @Autowired
+ public ValidationController(ValidationService validationService) {
+ this.validationService = validationService;
+ }
+
+ /**
+ * Validates Helm chart.
+ *
+ * @param version requested version of Helm client to be used
+ * @param file packaged Helm chart file
+ * @param isLinted flag deciding if chart should be linted
+ * @param isStrictLinted flag deciding if chart should be linted with strict option turned on
+ * @return Response with result of validation
+ */
+ @PostMapping("/validate")
+ public ResponseEntity<ValidationResult> validate(
+ @RequestParam(value = "versionDesired", required = false) String version,
+ @RequestParam("file") MultipartFile file,
+ @RequestParam(value = "isLinted", required = false, defaultValue = "false") boolean isLinted,
+ @RequestParam(value = "isStrictLinted", required = false, defaultValue = "false") boolean isStrictLinted) {
+ LOGGER.debug("Received file: {}, size: {}, helm version: {}",
+ file.getOriginalFilename(), file.getSize(), version);
+ ValidationResult result = validationService
+ .process(version, file, isLinted, isStrictLinted);
+ return new ResponseEntity<>(result, HttpStatus.OK);
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandler.java b/src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandler.java
new file mode 100644
index 0000000..332a923
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandler.java
@@ -0,0 +1,129 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.errorhandling;
+
+import org.onap.sdc.helmvalidator.api.ValidationController;
+import org.onap.sdc.helmvalidator.helm.validation.exception.BashExecutionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.NotSupportedVersionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.SaveFileException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ApiVersionNotFoundException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.NotSupportedApiVersionException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ReadFileException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice(assignableTypes = ValidationController.class)
+public class ValidationErrorHandler {
+
+ /**
+ * BashExecutionException handler.
+ *
+ * @param exception Exception that occurs during execution of bash command
+ * @return ResponseEntity with ValidationErrorResponse created from given exception
+ */
+ @ExceptionHandler(value = BashExecutionException.class)
+ public ResponseEntity<ValidationErrorResponse> handle(BashExecutionException exception) {
+ return getErrorResponseEntity(
+ exception.getMessage(),
+ HttpStatus.INTERNAL_SERVER_ERROR
+ );
+ }
+
+ /**
+ * SaveFileException handler.
+ *
+ * @param exception Exception that occurs during file saving
+ * @return ResponseEntity with ValidationErrorResponse created from given exception
+ */
+ @ExceptionHandler(value = SaveFileException.class)
+ public ResponseEntity<ValidationErrorResponse> handle(SaveFileException exception) {
+ return getErrorResponseEntity(
+ exception.getMessage(),
+ HttpStatus.INTERNAL_SERVER_ERROR
+ );
+ }
+
+ /**
+ * NotSupportedVersionException handler.
+ *
+ * @param exception Exception that occurs when not supported Helm version is requested for validation
+ * @return ResponseEntity with ValidationErrorResponse created from given exception
+ */
+ @ExceptionHandler(value = NotSupportedVersionException.class)
+ public ResponseEntity<ValidationErrorResponse> handle(NotSupportedVersionException exception) {
+ return getErrorResponseEntity(
+ exception.getMessage(),
+ HttpStatus.BAD_REQUEST
+ );
+ }
+
+ /**
+ * ApiVersionNotFoundException handler.
+ *
+ * @param exception Exception that occurs when API version cannot be derived from Helm chart
+ * @return ResponseEntity with ValidationErrorResponse created from given exception
+ */
+ @ExceptionHandler(value = ApiVersionNotFoundException.class)
+ public ResponseEntity<ValidationErrorResponse> handle(ApiVersionNotFoundException exception) {
+ return getErrorResponseEntity(
+ exception.getMessage(),
+ HttpStatus.BAD_REQUEST
+ );
+ }
+
+ /**
+ * NotSupportedApiVersionException handler.
+ *
+ * @param exception Exception that occurs when API version from Helm chart is not supported
+ * @return ResponseEntity with ValidationErrorResponse created from given exception
+ */
+ @ExceptionHandler(value = NotSupportedApiVersionException.class)
+ public ResponseEntity<ValidationErrorResponse> handle(NotSupportedApiVersionException exception) {
+ return getErrorResponseEntity(
+ exception.getMessage(),
+ HttpStatus.BAD_REQUEST
+ );
+ }
+
+ /**
+ * ReadFileException handler.
+ *
+ * @param exception Exception that occurs during reading of Helm chart
+ * @return ResponseEntity with ValidationErrorResponse created from given exception
+ */
+ @ExceptionHandler(value = ReadFileException.class)
+ public ResponseEntity<ValidationErrorResponse> handle(ReadFileException exception) {
+ return getErrorResponseEntity(
+ exception.getMessage(),
+ HttpStatus.INTERNAL_SERVER_ERROR
+ );
+ }
+
+ private ResponseEntity<ValidationErrorResponse> getErrorResponseEntity(String errorMessage, HttpStatus status) {
+ ValidationErrorResponse errorResponse = new ValidationErrorResponse(errorMessage);
+ return new ResponseEntity<>(
+ errorResponse,
+ status
+ );
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorResponse.java b/src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorResponse.java
new file mode 100644
index 0000000..0f1fded
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorResponse.java
@@ -0,0 +1,34 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.errorhandling;
+
+class ValidationErrorResponse {
+
+ private final String message;
+
+ ValidationErrorResponse(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutor.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutor.java
new file mode 100644
index 0000000..0bebc0a
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutor.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.onap.sdc.helmvalidator.helm.validation.exception.BashExecutionException;
+import org.onap.sdc.helmvalidator.helm.validation.model.BashOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BashExecutor {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(
+ ValidationService.class);
+
+ BashOutput execute(String helmCommand) {
+
+ try {
+ ProcessBuilder pb = new ProcessBuilder("bash", "-c", helmCommand);
+ pb.redirectErrorStream(true);
+ LOGGER.debug("Start process");
+ Process process = pb.start();
+
+ List<String> processOutput = readOutputAndCloseProcess(process);
+ return new BashOutput(process.exitValue(), processOutput);
+ } catch (IOException | InterruptedException e) {
+ throw new BashExecutionException("Error during bash execution: ", e);
+ }
+ }
+
+ private List<String> readOutputAndCloseProcess(Process process) throws IOException, InterruptedException {
+
+ final InputStream inputStream = process.getInputStream();
+ final List<String> lines = new BufferedReader(new InputStreamReader(inputStream))
+ .lines().collect(Collectors.toList());
+
+ // For compatibility with Helm2 and Helm3
+ process.waitFor();
+ inputStream.close();
+ process.destroy();
+
+ return lines;
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/FileManager.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/FileManager.java
new file mode 100644
index 0000000..3617df7
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/FileManager.java
@@ -0,0 +1,72 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.time.Instant;
+import org.onap.sdc.helmvalidator.helm.validation.exception.SaveFileException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service
+public class FileManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FileManager.class);
+ private final String basePath;
+
+ @Autowired
+ FileManager(@Value("${app.config.charts-base-path}") String basePath) {
+ this.basePath = basePath;
+ }
+
+ String saveFile(MultipartFile file) {
+ LOGGER.debug("Base PATH: {}", basePath);
+ try {
+ String filePath = basePath + File.separator + generateFileName(file.getOriginalFilename());
+ LOGGER.info("Attempt to save file : {}", filePath);
+ Files.copy(file.getInputStream(), Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);
+ return filePath;
+ } catch (IOException e) {
+ throw new SaveFileException("Cannot save file: " + file.getOriginalFilename(), e);
+ }
+ }
+
+ void removeFile(String path) {
+ try {
+ LOGGER.debug("Attempt to delete file : {}", path);
+ Files.deleteIfExists(Paths.get(path));
+ } catch (IOException e) {
+ LOGGER.warn("Cannot delete file: {}, Exception: {}", path, e.getStackTrace());
+ }
+ }
+
+ private String generateFileName(String fileName) {
+ return Instant.now().toEpochMilli() + "_" + fileName;
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/ValidationService.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/ValidationService.java
new file mode 100644
index 0000000..1e6cedb
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/ValidationService.java
@@ -0,0 +1,221 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import org.onap.sdc.helmvalidator.helm.validation.exception.BashExecutionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.NotSupportedVersionException;
+import org.onap.sdc.helmvalidator.helm.validation.model.BashOutput;
+import org.onap.sdc.helmvalidator.helm.validation.model.LintValidationResult;
+import org.onap.sdc.helmvalidator.helm.validation.model.TemplateValidationResult;
+import org.onap.sdc.helmvalidator.helm.validation.model.ValidationResult;
+import org.onap.sdc.helmvalidator.helm.versions.ChartBasedVersionProvider;
+import org.onap.sdc.helmvalidator.helm.versions.SupportedVersionsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service
+public class ValidationService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ValidationService.class);
+ private static final String TEMPLATE_OPTION = "template";
+ private static final String LINT_OPTION = "lint";
+ private static final String HELM_SUMMARY_MESSAGE_PATTERN =
+ "Error: \\d* chart\\(s\\) linted, \\d* chart\\(s\\) failed";
+ private static final boolean INVALID_RESULT = false;
+
+ private final FileManager fileManager;
+
+ private final BashExecutor executor;
+
+ private final SupportedVersionsProvider supportedVersionsProvider;
+
+ private final ChartBasedVersionProvider chartBasedVersionProvider;
+
+
+ /**
+ * Constructor for ValidationService.
+ *
+ * @param fileManager object responsible for file manging
+ * @param executor object responsible for running shell commands
+ * @param supportedVersionsProvider object providing supported versions of Helm
+ * @param chartBasedVersionProvider object allowing to derive Helm version from a chart
+ */
+ @Autowired
+ public ValidationService(
+ FileManager fileManager, BashExecutor executor,
+ SupportedVersionsProvider supportedVersionsProvider,
+ ChartBasedVersionProvider chartBasedVersionProvider) {
+ this.fileManager = fileManager;
+ this.executor = executor;
+ this.supportedVersionsProvider = supportedVersionsProvider;
+ this.chartBasedVersionProvider = chartBasedVersionProvider;
+ }
+
+ /**
+ * Process Helm chart package with given options.
+ *
+ * @param desiredVersion requested version of Helm client to be used
+ * @param file packaged Helm chart file
+ * @param isLinted flag deciding if chart should be linted
+ * @param isStrictLinted flag deciding if chart should be linted with strict option turned on
+ * @return Result of Helm chart validation
+ */
+ public ValidationResult process(String desiredVersion, MultipartFile file, boolean isLinted,
+ boolean isStrictLinted) {
+ String chartPath = fileManager.saveFile(file);
+ try {
+ String helmVersion = getSupportedHelmVersion(desiredVersion, chartPath);
+ return validateChart(helmVersion, file, isLinted, isStrictLinted, chartPath);
+ } finally {
+ LOGGER.info("File process finished");
+ fileManager.removeFile(chartPath);
+ }
+ }
+
+ private String getSupportedHelmVersion(String desiredVersion, String chartPath) {
+ String helmVersion = getHelmVersion(desiredVersion, chartPath);
+
+ if (isNotSupportedVersion(helmVersion)) {
+ throw new NotSupportedVersionException(helmVersion);
+ }
+
+ return helmVersion;
+ }
+
+ private String getHelmVersion(String desiredVersion, String chartPath) {
+ if (desiredVersion == null) {
+ return chartBasedVersionProvider.getVersion(chartPath);
+ }
+
+ if (desiredVersion.startsWith("v")) {
+ String helmMajorVersion = desiredVersion.substring(1);
+ return supportedVersionsProvider.getLatestVersion(helmMajorVersion);
+ }
+
+ return desiredVersion;
+ }
+
+ private ValidationResult validateChart(String version, MultipartFile file, boolean isLinted, boolean isStrictLinted,
+ String chartPath) {
+ LOGGER.info("Start validation of file: {}, with helm version: {}",
+ file.getOriginalFilename(), version);
+
+ TemplateValidationResult templateValidationResult = runHelmTemplate(
+ buildHelmTemplateCommand(version, chartPath));
+ LOGGER.info("Helm template finished");
+
+ if (isLinted) {
+ LOGGER.info("Start helm lint, strict: {}", isStrictLinted);
+ LintValidationResult lintValidationResult = runHelmLint(
+ buildHelmLintCommand(version, chartPath, isStrictLinted));
+ LOGGER.info("Helm lint finished");
+ return new ValidationResult(templateValidationResult, lintValidationResult, version);
+ }
+
+ return new ValidationResult(templateValidationResult, version);
+ }
+
+ private boolean isNotSupportedVersion(String version) {
+ return !supportedVersionsProvider.getVersions().contains(version);
+ }
+
+
+ private String buildHelmTemplateCommand(String version, String chartPath) {
+ return "helm-v" + version + " " + TEMPLATE_OPTION + " " + chartPath;
+ }
+
+ private TemplateValidationResult runHelmTemplate(String helmCommand)
+ throws BashExecutionException {
+
+ LOGGER.debug("Command executions: {} ", helmCommand);
+ BashOutput chartTemplateResult = executor.execute(helmCommand);
+ LOGGER.debug("Status code: " + chartTemplateResult.getExitValue());
+ if (chartTemplateResult.getExitValue() != 0) {
+ List<String> renderingErrors = parseTemplateError(chartTemplateResult.getOutputLines());
+ return new TemplateValidationResult(false, renderingErrors);
+ }
+ return new TemplateValidationResult(true, Collections.emptyList());
+ }
+
+ private String buildHelmLintCommand(String version, String chartPath, boolean isStrictLint) {
+ String command = "helm-v" + version + " " + LINT_OPTION + " " + chartPath;
+ if (isStrictLint) {
+ return command + " --strict";
+ }
+ return command;
+ }
+
+ private LintValidationResult runHelmLint(String helmCommand) {
+ BashOutput chartLintResult = executor.execute(helmCommand);
+
+ List<String> lintErrors = parseLintError(chartLintResult.getOutputLines());
+ List<String> lintWarnings = parseWarningError(chartLintResult.getOutputLines());
+
+ boolean isSuccessExitStatus = isSuccessExitStatus(chartLintResult.getExitValue());
+
+ if (isInvalidWithoutStandardError(isSuccessExitStatus, lintErrors, lintWarnings)) {
+ return new LintValidationResult(INVALID_RESULT, chartLintResult.getOutputLines(), new ArrayList<>());
+ }
+
+ return new LintValidationResult(isSuccessExitStatus, lintErrors, lintWarnings);
+ }
+
+ private boolean isInvalidWithoutStandardError(boolean isValid, List<String> lintErrors, List<String> lintWarnings) {
+ return !isValid && lintErrors.isEmpty() && lintWarnings.isEmpty();
+ }
+
+ private boolean isSuccessExitStatus(int exitValue) {
+ return exitValue == 0;
+ }
+
+ private List<String> parseTemplateError(List<String> outputLines) {
+
+ return outputLines.stream()
+ .filter(s -> s.startsWith("Error:"))
+ .collect(Collectors.toList());
+ }
+
+ private List<String> parseWarningError(List<String> outputLines) {
+ return outputLines.stream()
+ .filter(s -> s.startsWith("[WARNING]"))
+ .collect(Collectors.toList());
+ }
+
+ private List<String> parseLintError(List<String> outputLines) {
+ return outputLines.stream()
+ .filter(s -> s.startsWith("[ERROR]") || s.startsWith("Error"))
+ .filter(this::isNotHelmSummaryMessage)
+ .collect(Collectors.toList());
+ }
+
+ private boolean isNotHelmSummaryMessage(String line) {
+ Pattern pattern = Pattern.compile(HELM_SUMMARY_MESSAGE_PATTERN);
+ return !pattern.matcher(line).matches();
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/BashExecutionException.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/BashExecutionException.java
new file mode 100644
index 0000000..2d70d39
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/BashExecutionException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation.exception;
+
+public class BashExecutionException extends RuntimeException {
+
+ public BashExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/NotSupportedVersionException.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/NotSupportedVersionException.java
new file mode 100644
index 0000000..753a08d
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/NotSupportedVersionException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation.exception;
+
+public class NotSupportedVersionException extends RuntimeException {
+
+ public NotSupportedVersionException(String version) {
+ super("Version: " + version + " is not supported");
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/SaveFileException.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/SaveFileException.java
new file mode 100644
index 0000000..cdb9079
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/exception/SaveFileException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation.exception;
+
+public class SaveFileException extends RuntimeException {
+
+ public SaveFileException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/BashOutput.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/BashOutput.java
new file mode 100644
index 0000000..88942e5
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/BashOutput.java
@@ -0,0 +1,43 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation.model;
+
+import java.util.List;
+
+public class BashOutput {
+
+ private final int exitValue;
+
+ private final List<String> outputLines;
+
+ public BashOutput(int exitValue, List<String> outputLines) {
+ this.exitValue = exitValue;
+ this.outputLines = outputLines;
+ }
+
+ public int getExitValue() {
+ return exitValue;
+ }
+
+ public List<String> getOutputLines() {
+ return outputLines;
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/LintValidationResult.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/LintValidationResult.java
new file mode 100644
index 0000000..09cbe36
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/LintValidationResult.java
@@ -0,0 +1,55 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation.model;
+
+import java.util.List;
+
+public class LintValidationResult {
+
+ private final boolean isValid;
+
+ private final List<String> lintErrors;
+ private final List<String> lintWarnings;
+
+ /**
+ * Validation result of linting a Helm chart.
+ * @param isValid flag indicating if chart is valid
+ * @param lintErrors list of errors occurred during linting
+ * @param lintWarnings list of warning occurred during linting
+ */
+ public LintValidationResult(boolean isValid, List<String> lintErrors, List<String> lintWarnings) {
+ this.isValid = isValid;
+ this.lintErrors = lintErrors;
+ this.lintWarnings = lintWarnings;
+ }
+
+ boolean isValid() {
+ return isValid;
+ }
+
+ List<String> getLintErrors() {
+ return lintErrors;
+ }
+
+ List<String> getLintWarnings() {
+ return lintWarnings;
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/TemplateValidationResult.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/TemplateValidationResult.java
new file mode 100644
index 0000000..1ba20f9
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/TemplateValidationResult.java
@@ -0,0 +1,48 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation.model;
+
+import java.util.List;
+
+public class TemplateValidationResult {
+
+ private final boolean isDeployable;
+
+ private final List<String> renderErrors;
+
+ /**
+ * Validation result of templating a Helm chart.
+ * @param isDeployable flag indicating if chart can be templated
+ * @param renderErrors list of errors occurred during templating
+ */
+ public TemplateValidationResult(boolean isDeployable, List<String> renderErrors) {
+ this.isDeployable = isDeployable;
+ this.renderErrors = renderErrors;
+ }
+
+ boolean isDeployable() {
+ return isDeployable;
+ }
+
+ List<String> getRenderErrors() {
+ return renderErrors;
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/ValidationResult.java b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/ValidationResult.java
new file mode 100644
index 0000000..bb4fccc
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/validation/model/ValidationResult.java
@@ -0,0 +1,98 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation.model;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+public class ValidationResult {
+
+ private final Boolean isDeployable;
+ private final List<String> renderErrors;
+ private final Boolean isValid;
+ private final List<String> lintWarning;
+ private final List<String> lintError;
+ private final String versionUsed;
+
+
+ /**
+ * ValidationResult constructor when linting is enabled.
+ * @param templateValidationResult result of helm chart templating
+ * @param lintValidationResult result of helm chart linting
+ * @param versionUsed version of helm client used
+ */
+ public ValidationResult(
+ TemplateValidationResult templateValidationResult,
+ LintValidationResult lintValidationResult,
+ String versionUsed) {
+ this.isDeployable = templateValidationResult.isDeployable();
+ this.renderErrors = templateValidationResult.getRenderErrors();
+
+ this.isValid = lintValidationResult.isValid();
+ this.lintWarning = lintValidationResult.getLintWarnings();
+ this.lintError = lintValidationResult.getLintErrors();
+ this.versionUsed = versionUsed;
+ }
+
+ /**
+ * ValidationResult constructor when linting is disabled.
+ * @param templateValidationResult result of helm chart templating
+ * @param versionUsed version of helm client used
+ */
+ public ValidationResult(
+ TemplateValidationResult templateValidationResult, String versionUsed) {
+ this.isDeployable = templateValidationResult.isDeployable();
+ this.renderErrors = templateValidationResult.getRenderErrors();
+
+ this.isValid = null;
+ this.lintWarning = null;
+ this.lintError = null;
+ this.versionUsed = versionUsed;
+ }
+
+ public Boolean isDeployable() {
+ return isDeployable;
+ }
+
+ public List<String> getRenderErrors() {
+ return Optional.ofNullable(renderErrors)
+ .map(Collections::unmodifiableList).orElse(null);
+ }
+
+ public Boolean isValid() {
+ return isValid;
+ }
+
+ public List<String> getLintWarning() {
+ return Optional.ofNullable(lintWarning)
+ .map(Collections::unmodifiableList).orElse(null);
+ }
+
+ public List<String> getLintError() {
+ return Optional.ofNullable(lintError)
+ .map(Collections::unmodifiableList).orElse(null);
+ }
+
+ public String getVersionUsed() {
+ return versionUsed;
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReader.java b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReader.java
new file mode 100644
index 0000000..e5c1a2e
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReader.java
@@ -0,0 +1,80 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Path;
+import java.util.Optional;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ApiVersionNotFoundException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ReadFileException;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ApiVersionsReader {
+
+ private static final int MAIN_CHART_DIR_DEPTH = 2;
+ private static final String API_VERSION_PREFIX = "apiVersion:";
+ private static final Path CHART_FILE_NAME = Path.of("Chart.yaml");
+
+ String readVersion(String chartPath) {
+ return tryReadVersionFromChart(chartPath)
+ .orElseThrow(ApiVersionNotFoundException::new);
+ }
+
+ private Optional<String> tryReadVersionFromChart(String chartPath) {
+ try (TarArchiveInputStream tarInput = new TarArchiveInputStream(
+ new GzipCompressorInputStream(new FileInputStream(chartPath)))) {
+ return readVersionFromChart(tarInput);
+ } catch (IOException e) {
+ throw new ReadFileException("Cannot read tar from path: " + chartPath, e);
+ }
+ }
+
+ private Optional<String> readVersionFromChart(TarArchiveInputStream tarInput) throws IOException {
+ TarArchiveEntry currentEntry;
+ while ((currentEntry = tarInput.getNextTarEntry()) != null) {
+ if (isMainChartYaml(currentEntry)) {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(tarInput));
+ return bufferedReader.lines()
+ .filter(chartLine -> chartLine.contains(API_VERSION_PREFIX))
+ .map(apiVersionLine -> apiVersionLine.replaceAll(API_VERSION_PREFIX, ""))
+ .map(String::trim)
+ .findFirst();
+ }
+ }
+ return Optional.empty();
+ }
+
+ private boolean isMainChartYaml(TarArchiveEntry currentEntry) {
+ Path entryPath = Path.of(currentEntry.getName());
+ return currentEntry.isFile()
+ && CHART_FILE_NAME.equals(entryPath.getFileName())
+ && (entryPath.getNameCount() == MAIN_CHART_DIR_DEPTH);
+ }
+
+
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProvider.java b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProvider.java
new file mode 100644
index 0000000..b892a33
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProvider.java
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import org.onap.sdc.helmvalidator.helm.versions.exception.NotSupportedApiVersionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ChartBasedVersionProvider {
+
+ private final SupportedVersionsProvider supportedVersionsProvider;
+ private final ApiVersionsReader apiVersionsReader;
+
+ @Autowired
+ public ChartBasedVersionProvider(
+ SupportedVersionsProvider supportedVersionsProvider,
+ ApiVersionsReader apiVersionsReader) {
+ this.supportedVersionsProvider = supportedVersionsProvider;
+ this.apiVersionsReader = apiVersionsReader;
+ }
+
+ public String getVersion(String chartPath) {
+ String apiVersion = apiVersionsReader.readVersion(chartPath);
+ return mapToChartVersion(apiVersion);
+ }
+
+ private String mapToChartVersion(String apiVersion) {
+ switch (apiVersion) {
+ case "v1":
+ return supportedVersionsProvider.getLatestVersion("2");
+ case "v2":
+ return supportedVersionsProvider.getLatestVersion("3");
+ default:
+ throw new NotSupportedApiVersionException("Cannot obtain Helm version from API version: " + apiVersion);
+ }
+ }
+
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProvider.java b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProvider.java
new file mode 100644
index 0000000..ff1cdde
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProvider.java
@@ -0,0 +1,65 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import org.onap.sdc.helmvalidator.helm.validation.exception.NotSupportedVersionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SupportedVersionsProvider {
+
+ private final SystemEnvVersionsReader versionsReader;
+
+ @Autowired
+ public SupportedVersionsProvider(SystemEnvVersionsReader versionsReader) {
+ this.versionsReader = versionsReader;
+ }
+
+ /**
+ * Retrieves list of available Helm client versions.
+ *
+ * @return list of available Helm client versions
+ */
+ public List<String> getVersions() {
+ return versionsReader.readVersions().stream()
+ .filter(Predicate.not(String::isBlank))
+ .sorted(Comparator.reverseOrder())
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Retrieves latest available Helm client with given major version.
+ *
+ * @param helmMajorVersion major version of Helm client
+ * @return latest available Helm client with given major version
+ */
+ public String getLatestVersion(String helmMajorVersion) {
+ return getVersions().stream()
+ .filter(supportedVersion -> supportedVersion.startsWith(helmMajorVersion + "."))
+ .findFirst()
+ .orElseThrow(() -> new NotSupportedVersionException(helmMajorVersion));
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReader.java b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReader.java
new file mode 100644
index 0000000..8cccd2b
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReader.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SystemEnvVersionsReader {
+
+ private static final String HELM_SUPPORTED_VERSIONS = "HELM_SUPPORTED_VERSIONS";
+ private static final String DELIMITER = ",";
+
+ List<String> readVersions() {
+ return Arrays.stream(getSupportedVersionsFromEnv()
+ .split(DELIMITER))
+ .filter(Predicate.not(String::isBlank))
+ .collect(Collectors.toList());
+ }
+
+ String getSupportedVersionsFromEnv() {
+ return Optional.ofNullable(System.getenv(HELM_SUPPORTED_VERSIONS))
+ .orElse("");
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ApiVersionNotFoundException.java b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ApiVersionNotFoundException.java
new file mode 100644
index 0000000..fadcc2a
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ApiVersionNotFoundException.java
@@ -0,0 +1,29 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions.exception;
+
+public class ApiVersionNotFoundException extends RuntimeException {
+
+ public ApiVersionNotFoundException() {
+ super("Cannot find apiVersion value in a main chart");
+ }
+
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/NotSupportedApiVersionException.java b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/NotSupportedApiVersionException.java
new file mode 100644
index 0000000..368f9f1
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/NotSupportedApiVersionException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions.exception;
+
+public class NotSupportedApiVersionException extends RuntimeException {
+
+ public NotSupportedApiVersionException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ReadFileException.java b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ReadFileException.java
new file mode 100644
index 0000000..a6a1ec4
--- /dev/null
+++ b/src/main/java/org/onap/sdc/helmvalidator/helm/versions/exception/ReadFileException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions.exception;
+
+public class ReadFileException extends RuntimeException {
+
+ public ReadFileException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..3fef31f
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+logging.level.web="ERROR"
+spring.mvc.log-request-details=false
+app.config.charts-base-path=/charts
+spring.jackson.default-property-inclusion=NON_NULL
diff --git a/src/test/java/org/onap/sdc/helmvalidator/HelmValidatorApplicationTests.java b/src/test/java/org/onap/sdc/helmvalidator/HelmValidatorApplicationTests.java
new file mode 100644
index 0000000..5b81936
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/HelmValidatorApplicationTests.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class HelmValidatorApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/api/SupportedVersionsControllerTest.java b/src/test/java/org/onap/sdc/helmvalidator/api/SupportedVersionsControllerTest.java
new file mode 100644
index 0000000..ef93a90
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/api/SupportedVersionsControllerTest.java
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import java.util.Map;
+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.junit.jupiter.MockitoExtension;
+import org.onap.sdc.helmvalidator.helm.versions.SupportedVersionsProvider;
+import org.springframework.http.ResponseEntity;
+
+@ExtendWith(MockitoExtension.class)
+class SupportedVersionsControllerTest {
+
+ private static final String SAMPLE_VERSION1 = "3.4.1";
+ private static final String SAMPLE_VERSION2 = "3.3.4";
+ private static final String SAMPLE_VERSION3 = "2.17.0";
+ private static final String VERSIONS = "versions";
+ private static final int EXPECTED_SIZE = 3;
+
+ private SupportedVersionsController supportedVersionsController;
+
+ @Mock
+ private SupportedVersionsProvider versionsProvider;
+
+ @BeforeEach
+ void setUp() {
+ supportedVersionsController = new SupportedVersionsController(versionsProvider);
+ }
+
+ @Test
+ void shouldReturnVersions() {
+ when(versionsProvider.getVersions()).thenReturn(List.of(SAMPLE_VERSION1, SAMPLE_VERSION2, SAMPLE_VERSION3));
+
+ ResponseEntity<Map<String, List<String>>> supportedVersionsResponse = supportedVersionsController
+ .supportedVersions();
+ List<String> supportedVersions = supportedVersionsResponse.getBody().get(VERSIONS);
+
+ assertThat(supportedVersions).isNotNull();
+ assertThat(supportedVersions).hasSize(EXPECTED_SIZE);
+ assertThat(supportedVersions).contains(SAMPLE_VERSION1, SAMPLE_VERSION2, SAMPLE_VERSION3);
+ }
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/api/ValidationControllerTest.java b/src/test/java/org/onap/sdc/helmvalidator/api/ValidationControllerTest.java
new file mode 100644
index 0000000..03f976a
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/api/ValidationControllerTest.java
@@ -0,0 +1,195 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
+
+import java.util.ArrayList;
+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.junit.jupiter.MockitoExtension;
+import org.onap.sdc.helmvalidator.helm.validation.ValidationService;
+import org.onap.sdc.helmvalidator.helm.validation.exception.BashExecutionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.NotSupportedVersionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.SaveFileException;
+import org.onap.sdc.helmvalidator.helm.validation.model.LintValidationResult;
+import org.onap.sdc.helmvalidator.helm.validation.model.TemplateValidationResult;
+import org.onap.sdc.helmvalidator.helm.validation.model.ValidationResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.web.multipart.MultipartFile;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
+@AutoConfigureMockMvc
+@ExtendWith(SpringExtension.class)
+@ExtendWith(MockitoExtension.class)
+class ValidationControllerTest {
+
+ private static final String SAMPLE_VERSION = "3.3.4";
+ private static final String VERSION_PARAM = "versionDesired";
+ private static final String IS_LINTED_PARAM = "isLinted";
+ private static final String IS_STRICT_LINTED_PARAM = "isStrictLinted";
+ private static final String VALID = "valid";
+ private static final String DEPLOYABLE = "deployable";
+ private static final String RENDER_ERRORS = "renderErrors";
+ private static final String LINT_WARNING = "lintWarning";
+ private static final String LINT_ERROR = "lintError";
+ private static final String SAMPLE_ORIGINAL_FILENAME = "sampleChart.tar.gz";
+ private static final String FILE_KEY = "file";
+ private static final String VALIDATION_ENDPOINT = "/validate";
+ private static final String VERSION_USED = "versionUsed";
+
+ private ValidationController validationController;
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @MockBean
+ private ValidationService validationService;
+
+ @Mock
+ private MultipartFile multipartFile;
+
+ @BeforeEach
+ void setUp() {
+ validationController = new ValidationController(validationService);
+ }
+
+ @Test
+ void shouldReturnValidResponseForMockedFile() {
+ TemplateValidationResult templateValidationResult = new TemplateValidationResult(true, new ArrayList<>());
+ LintValidationResult lintValidationResult = new LintValidationResult(true, new ArrayList<>(),
+ new ArrayList<>());
+
+ when(validationService.process(SAMPLE_VERSION, multipartFile, true, true))
+ .thenReturn(new ValidationResult(templateValidationResult, lintValidationResult, SAMPLE_VERSION));
+
+ ResponseEntity<ValidationResult> result = validationController
+ .validate(SAMPLE_VERSION, multipartFile, true, true);
+
+ assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
+ assertThat(result.getBody().isDeployable()).isTrue();
+ assertThat(result.getBody().isValid()).isTrue();
+ assertThat(result.getBody().getRenderErrors()).isEmpty();
+ assertThat(result.getBody().getLintError()).isEmpty();
+ assertThat(result.getBody().getLintWarning()).isEmpty();
+ assertThat(result.getBody().getVersionUsed()).isEqualTo(SAMPLE_VERSION);
+
+ }
+
+ @Test
+ void shouldThrowExceptionWhenCannotSaveFile() {
+ when(validationService.process(SAMPLE_VERSION, multipartFile, true, true)).thenThrow(SaveFileException.class);
+
+ assertThatExceptionOfType(SaveFileException.class)
+ .isThrownBy(() -> validationController.validate(SAMPLE_VERSION, multipartFile, true, true));
+ }
+
+ @Test
+ void shouldThrowExceptionIfErrorOccursDuringBashExecution() {
+ when(validationService.process(SAMPLE_VERSION, multipartFile, true, true))
+ .thenThrow(BashExecutionException.class);
+
+ assertThatExceptionOfType(BashExecutionException.class)
+ .isThrownBy(() -> validationController.validate(SAMPLE_VERSION, multipartFile, true, true));
+ }
+
+ @Test
+ void shouldThrowExceptionWhenProvidedVersionIsNotSupported() {
+ when(validationService.process(SAMPLE_VERSION, multipartFile, true, true)).thenThrow(
+ NotSupportedVersionException.class);
+
+ assertThatExceptionOfType(NotSupportedVersionException.class)
+ .isThrownBy(() -> validationController.validate(SAMPLE_VERSION, multipartFile, true, true));
+ }
+
+ @Test
+ void shouldContainDeployAndValidParametersInResponseBodyIfLintedIsTrue() throws Exception {
+
+ TemplateValidationResult templateValidationResult = new TemplateValidationResult(true, new ArrayList<>());
+ LintValidationResult lintValidationResult = new LintValidationResult(true, new ArrayList<>(),
+ new ArrayList<>());
+ MockMultipartFile file = new MockMultipartFile(FILE_KEY, SAMPLE_ORIGINAL_FILENAME,
+ MediaType.MULTIPART_FORM_DATA_VALUE, "test".getBytes());
+
+ when(validationService.process(SAMPLE_VERSION, file, true, true))
+ .thenReturn(new ValidationResult(templateValidationResult, lintValidationResult, SAMPLE_VERSION));
+
+ MvcResult mvcResult = mockMvc.perform(
+ multipart(VALIDATION_ENDPOINT)
+ .file(file)
+ .param(VERSION_PARAM, SAMPLE_VERSION)
+ .param(IS_LINTED_PARAM, "true")
+ .param(IS_STRICT_LINTED_PARAM, "true"))
+ .andReturn();
+ String contentAsString = mvcResult.getResponse().getContentAsString();
+
+ assertThat(contentAsString).contains(VALID);
+ assertThat(contentAsString).contains(DEPLOYABLE);
+ assertThat(contentAsString).contains(RENDER_ERRORS);
+ assertThat(contentAsString).contains(LINT_WARNING);
+ assertThat(contentAsString).contains(LINT_ERROR);
+ assertThat(contentAsString).contains(VERSION_USED);
+ assertThat(mvcResult.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
+ }
+
+ @Test
+ void shouldNotContainValidParametersInResponseBodyIfLintedIsFalse() throws Exception {
+
+ TemplateValidationResult templateValidationResult = new TemplateValidationResult(true, new ArrayList<>());
+ MockMultipartFile file = new MockMultipartFile(FILE_KEY, SAMPLE_ORIGINAL_FILENAME,
+ MediaType.MULTIPART_FORM_DATA_VALUE, "test".getBytes());
+
+ when(validationService.process(SAMPLE_VERSION, file, false, false))
+ .thenReturn(new ValidationResult(templateValidationResult, SAMPLE_VERSION));
+
+ MvcResult mvcResult = mockMvc.perform(
+ multipart(VALIDATION_ENDPOINT)
+ .file(file)
+ .param(VERSION_PARAM, SAMPLE_VERSION)
+ .param(IS_LINTED_PARAM, "false")
+ .param(IS_STRICT_LINTED_PARAM, "false"))
+ .andReturn();
+ String contentAsString = mvcResult.getResponse().getContentAsString();
+
+ assertThat(contentAsString).doesNotContain(VALID);
+ assertThat(contentAsString).contains(DEPLOYABLE);
+ assertThat(contentAsString).contains(RENDER_ERRORS);
+ assertThat(contentAsString).doesNotContain(LINT_WARNING);
+ assertThat(contentAsString).doesNotContain(LINT_ERROR);
+ assertThat(contentAsString).contains(VERSION_USED);
+ assertThat(mvcResult.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
+ }
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandlerTest.java b/src/test/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandlerTest.java
new file mode 100644
index 0000000..5fbad30
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/errorhandling/ValidationErrorHandlerTest.java
@@ -0,0 +1,125 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.errorhandling;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+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.junit.jupiter.MockitoExtension;
+import org.onap.sdc.helmvalidator.helm.validation.exception.BashExecutionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.NotSupportedVersionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.SaveFileException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ApiVersionNotFoundException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.NotSupportedApiVersionException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ReadFileException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+@ExtendWith(MockitoExtension.class)
+class ValidationErrorHandlerTest {
+
+ private ValidationErrorHandler errorHandler;
+
+ @Mock
+ private Throwable cause;
+
+ @BeforeEach
+ void setUp() {
+ errorHandler = new ValidationErrorHandler();
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithMessageWhenCannotSaveFile() {
+ String expectedMessage = "Cannot save file test-chart.tar.gz";
+ SaveFileException saveFileException = new SaveFileException(expectedMessage, cause);
+
+ ResponseEntity<ValidationErrorResponse> responseEntity = errorHandler.handle(saveFileException);
+
+ assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
+ assertThat(responseEntity.getBody().getMessage()).isEqualTo(expectedMessage);
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithMessageWhenProvidedVersionIsNotSupported() {
+ String version = "3.3.3";
+ String expectedMessage = "Version: " + version + " is not supported";
+
+ NotSupportedVersionException notSupportedVersionException = new NotSupportedVersionException(version);
+
+ ResponseEntity<ValidationErrorResponse> responseEntity = errorHandler.handle(notSupportedVersionException);
+
+ assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
+ assertThat(responseEntity.getBody().getMessage()).isEqualTo(expectedMessage);
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithMessageWhenErrorOccursDuringBashExecution() {
+ String expectedMessage = "Error in bash executions";
+ BashExecutionException bashExecutionException = new BashExecutionException(expectedMessage, cause);
+
+ ResponseEntity<ValidationErrorResponse> responseEntity = errorHandler.handle(bashExecutionException);
+
+ assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
+ assertThat(responseEntity.getBody().getMessage()).isEqualTo(expectedMessage);
+
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithMessageWhenHelmApiVersionNotFoundInChart() {
+ String expectedMessage = "Cannot find apiVersion value in a main chart";
+ ApiVersionNotFoundException apiVersionNotFoundException = new ApiVersionNotFoundException();
+
+ ResponseEntity<ValidationErrorResponse> responseEntity = errorHandler.handle(apiVersionNotFoundException);
+
+ assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
+ assertThat(responseEntity.getBody().getMessage()).isEqualTo(expectedMessage);
+
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithMessageWhenHelmApiVersionIsNotSupported() {
+ String expectedMessage = "Cannot obtain Helm version from API version";
+ NotSupportedApiVersionException notSupportedApiVersionException = new NotSupportedApiVersionException(
+ expectedMessage);
+
+ ResponseEntity<ValidationErrorResponse> responseEntity = errorHandler.handle(notSupportedApiVersionException);
+
+ assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
+ assertThat(responseEntity.getBody().getMessage()).isEqualTo(expectedMessage);
+
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithMessageWhenCannotReadChartFile() {
+ String expectedMessage = "Cannot read tar file from path";
+ ReadFileException readFileException = new ReadFileException(expectedMessage, cause);
+
+ ResponseEntity<ValidationErrorResponse> responseEntity = errorHandler.handle(readFileException);
+
+ assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
+ assertThat(responseEntity.getBody().getMessage()).isEqualTo(expectedMessage);
+
+ }
+
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutorTest.java b/src/test/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutorTest.java
new file mode 100644
index 0000000..5f76b83
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/helm/validation/BashExecutorTest.java
@@ -0,0 +1,43 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.onap.sdc.helmvalidator.helm.validation.exception.BashExecutionException;
+import org.onap.sdc.helmvalidator.helm.validation.model.BashOutput;
+
+class BashExecutorTest {
+
+
+ @Test
+ @Disabled("Disabled due to Operating System dependency - allowed on Linux OS")
+ void testExecution() throws BashExecutionException {
+
+ BashExecutor executor = new BashExecutor();
+
+ BashOutput output = executor.execute("ls -al");
+
+ assertThat(output.getOutputLines()).isNotEmpty();
+ }
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/helm/validation/FileManagerTest.java b/src/test/java/org/onap/sdc/helmvalidator/helm/validation/FileManagerTest.java
new file mode 100644
index 0000000..2d05cd9
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/helm/validation/FileManagerTest.java
@@ -0,0 +1,100 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Comparator;
+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.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.web.multipart.MultipartFile;
+
+@ExtendWith(MockitoExtension.class)
+class FileManagerTest {
+
+ private static final String TEST_RESOURCES_TMP = "src/test/resources/tmp";
+ private static final File TEST_RESOURCES_DIR = new File(TEST_RESOURCES_TMP);
+ private static final ByteArrayInputStream TEST_INPUT_STREAM = new ByteArrayInputStream("test".getBytes());
+ private static final String SAMPLE_FILE_NAME = "sample_file";
+
+ private FileManager fileManager;
+
+ @Mock
+ private MultipartFile multipartFile;
+
+ @BeforeAll
+ static void createTmpDir() {
+ TEST_RESOURCES_DIR.mkdirs();
+ }
+
+ @AfterAll
+ static void cleanTmpDir() throws IOException {
+ Files.walk(Paths.get(TEST_RESOURCES_TMP))
+ .sorted(Comparator.reverseOrder())
+ .map(Path::toFile)
+ .filter(File::isFile)
+ .forEach(File::delete);
+ TEST_RESOURCES_DIR.delete();
+ }
+
+ @BeforeEach
+ void setUp() {
+ fileManager = new FileManager(TEST_RESOURCES_TMP);
+ }
+
+ @Test
+ void saveMultipartFileAndReturnFilePath() throws IOException {
+ mockMultipartFile();
+
+ String filePath = fileManager.saveFile(multipartFile);
+
+ assertThat(filePath).isNotBlank();
+ assertThat(Files.exists(Paths.get(filePath))).isTrue();
+ }
+
+
+ @Test
+ void removeFileByPath() throws IOException {
+ mockMultipartFile();
+
+ String filePath = fileManager.saveFile(multipartFile);
+ fileManager.removeFile(filePath);
+
+ assertThat(Files.exists(Paths.get(filePath))).isFalse();
+ }
+
+ private void mockMultipartFile() throws IOException {
+ when(multipartFile.getOriginalFilename()).thenReturn(SAMPLE_FILE_NAME);
+ when(multipartFile.getInputStream()).thenReturn(TEST_INPUT_STREAM);
+ }
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/helm/validation/ValidationServiceTest.java b/src/test/java/org/onap/sdc/helmvalidator/helm/validation/ValidationServiceTest.java
new file mode 100644
index 0000000..c3c4093
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/helm/validation/ValidationServiceTest.java
@@ -0,0 +1,314 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.validation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.sdc.helmvalidator.helm.validation.exception.BashExecutionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.NotSupportedVersionException;
+import org.onap.sdc.helmvalidator.helm.validation.exception.SaveFileException;
+import org.onap.sdc.helmvalidator.helm.validation.model.BashOutput;
+import org.onap.sdc.helmvalidator.helm.validation.model.ValidationResult;
+import org.onap.sdc.helmvalidator.helm.versions.ChartBasedVersionProvider;
+import org.onap.sdc.helmvalidator.helm.versions.SupportedVersionsProvider;
+import org.springframework.web.multipart.MultipartFile;
+
+@ExtendWith(MockitoExtension.class)
+class ValidationServiceTest {
+
+ private static final String HELM_ERROR_ON_TEMPLATE =
+ "Error: parse error at (sample/templates/fail.yaml:1): function \"deliberateSyntaxError\" not defined";
+ private static final String HELM_ERROR_ON_LINT =
+ "[ERROR] templates/: parse error at (sample/templates/fail.yaml:1): function \"deliberateSyntaxError\" "
+ + "not defined\n";
+ private static final String HELM_WARNING_ON_LINT =
+ "[WARNING] templates/: directory not found\n";
+ private static final String HELM_WITHOUT_STANDARD_ERROR_ON_LINT =
+ "unable to check Chart.yaml file in chart: stat /charts/1610528407457_apiv2.tar.gz/Chart.yaml: not a directory";
+ private static final String HELM_LINT_ERROR_SUMMARY_MESSAGE = "Error: 0 chart(s) linted, 1 chart(s) failed";
+ private static final String HELM_EMPTY_OUTPUT = "";
+
+ private static final boolean LINTED = true;
+ private static final boolean NOT_LINTED = false;
+ private static final boolean STRICT_LINTED = true;
+ private static final boolean NOT_STRICT_LINTED = false;
+ private static final int SUCCESS_HELM_EXIT_CODE = 0;
+ private static final int UNSUCCESSFUL_HELM_EXIT_CODE = 1;
+
+ private static final String SAMPLE_VERSION = "3.3.3";
+ private static final List<String> SAMPLE_VERSIONS = List.of("3.3.4", "3.3.3", "2.3.1", "2.1.4", "2.3.4");
+ private static final String NOT_SUPPORTED_VERSION = "not supported version";
+
+ private static final String SAMPLE_PATH = "samplePath";
+ private static final String HELM_TEMPLATE = "helm-v3.3.3 template samplePath";
+ private static final String HELM_LINT = "helm-v3.3.3 lint samplePath";
+ private static final String HELM_LINT_STRICT = "helm-v3.3.3 lint samplePath --strict";
+ private static final int EXPECTED_ONE = 1;
+
+ private ValidationService validationService;
+
+ @Mock
+ private FileManager fileManager;
+
+ @Mock
+ private SupportedVersionsProvider versionsProvider;
+
+ @Mock
+ private ChartBasedVersionProvider chartBasedProvider;
+
+ @Mock
+ private MultipartFile multipartFile;
+
+ @Mock
+ private BashExecutor bashExecutor;
+
+ @BeforeEach
+ void setUp() {
+ when(fileManager.saveFile(multipartFile)).thenReturn(SAMPLE_PATH);
+ lenient().when(versionsProvider.getVersions()).thenReturn(SAMPLE_VERSIONS);
+ this.validationService = new ValidationService(fileManager, bashExecutor, versionsProvider, chartBasedProvider);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenCannotSaveFile() {
+ when(fileManager.saveFile(multipartFile)).thenThrow(SaveFileException.class);
+
+ assertThatExceptionOfType(SaveFileException.class)
+ .isThrownBy(
+ () -> validationService.process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED));
+ }
+
+ @Test
+ void shouldThrowExceptionWhenVersionsIsNotSupported() {
+
+ assertThatExceptionOfType(NotSupportedVersionException.class)
+ .isThrownBy(
+ () -> validationService.process(NOT_SUPPORTED_VERSION, multipartFile, LINTED, STRICT_LINTED));
+ }
+
+ @Test
+ void shouldBeValidAndDeployableForNoErrorsAndNoWarning() {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT_STRICT, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isTrue();
+ assertThat(validationResult.isValid()).isTrue();
+ assertThat(validationResult.getRenderErrors()).isEmpty();
+ assertThat(validationResult.getLintError()).isEmpty();
+ assertThat(validationResult.getLintWarning()).isEmpty();
+ }
+
+ @ParameterizedTest
+ @CsvSource({"v2", "v3"})
+ void shouldBeDeployableForLatestHelmVersion(String desiredVersion) {
+ final String majorVersion = desiredVersion.substring(1);
+ final String helmVersion = getLatestSampleHelmVersion(majorVersion);
+ final String helmTemplate = String.format("helm-v%s template samplePath", helmVersion);
+ when(versionsProvider.getLatestVersion(Mockito.anyString())).thenReturn(helmVersion);
+ mockBashCommand(helmTemplate, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+
+ ValidationResult validationResult = validationService
+ .process(desiredVersion, multipartFile, NOT_LINTED, NOT_STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isTrue();
+ assertThat(validationResult.getRenderErrors()).isEmpty();
+ verify(versionsProvider).getLatestVersion(majorVersion);
+ }
+
+ @Test
+ void shouldBeValidAndDeployableForVersionTakenFromChart() {
+ when(chartBasedProvider.getVersion(Mockito.anyString())).thenReturn(SAMPLE_VERSION);
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT_STRICT, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+
+ ValidationResult validationResult = validationService
+ .process(null, multipartFile, LINTED, STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isTrue();
+ assertThat(validationResult.isValid()).isTrue();
+ assertThat(validationResult.getRenderErrors()).isEmpty();
+ assertThat(validationResult.getLintError()).isEmpty();
+ assertThat(validationResult.getLintWarning()).isEmpty();
+ verify(chartBasedProvider).getVersion(SAMPLE_PATH);
+ }
+
+ @Test
+ void shouldBeUndeployableForRenderErrorsWithMessages() {
+ mockBashCommand(HELM_TEMPLATE, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_ERROR_ON_TEMPLATE);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, NOT_LINTED, NOT_STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isFalse();
+ assertThat(validationResult.getRenderErrors()).isNotEmpty();
+ }
+
+ @Test
+ void shouldBeUndeployableAndValidWhenRenderFailAndLintSuccessfulWithMessages()
+ throws BashExecutionException, SaveFileException {
+ mockBashCommand(HELM_TEMPLATE, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_ERROR_ON_TEMPLATE);
+ mockBashCommand(HELM_LINT_STRICT, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isFalse();
+ assertThat(validationResult.isValid()).isTrue();
+ assertThat(validationResult.getRenderErrors()).isNotEmpty();
+ assertThat(validationResult.getLintError()).isEmpty();
+ assertThat(validationResult.getLintWarning()).isEmpty();
+ }
+
+ @Test
+ void shouldBeDeployableAndInvalidForErrorOnLintWithMessages() {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_ERROR_ON_LINT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, NOT_STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isTrue();
+ assertThat(validationResult.isValid()).isFalse();
+ assertThat(validationResult.getRenderErrors()).isEmpty();
+ assertThat(validationResult.getLintError()).isNotEmpty();
+ assertThat(validationResult.getLintWarning()).isEmpty();
+ }
+
+ @Test
+ void shouldBeDeployableAndInvalidForWarningOnLintAndStrictLintWithMessages()
+ throws BashExecutionException, SaveFileException {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT_STRICT, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_WARNING_ON_LINT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isTrue();
+ assertThat(validationResult.isValid()).isFalse();
+ assertThat(validationResult.getRenderErrors()).isEmpty();
+ assertThat(validationResult.getLintError()).isEmpty();
+ assertThat(validationResult.getLintWarning()).isNotEmpty();
+ }
+
+ @Test
+ void shouldBeUndeployableAndInvalidForErrorOnTemplateAndErrorOnLintWithMessages()
+ throws BashExecutionException, SaveFileException {
+ mockBashCommand(HELM_TEMPLATE, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_ERROR_ON_TEMPLATE);
+ mockBashCommand(HELM_LINT_STRICT, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_WARNING_ON_LINT, HELM_ERROR_ON_LINT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+
+ assertThat(validationResult.isDeployable()).isFalse();
+ assertThat(validationResult.isValid()).isFalse();
+ assertThat(validationResult.getRenderErrors()).isNotEmpty();
+ assertThat(validationResult.getLintError()).isNotEmpty();
+ assertThat(validationResult.getLintWarning()).isNotEmpty();
+ }
+
+ @Test
+ void shouldBeInvalidForWarningOnStrictLintWithMessages() throws BashExecutionException, SaveFileException {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT_STRICT, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_WARNING_ON_LINT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+
+ assertThat(validationResult.isValid()).isFalse();
+ assertThat(validationResult.getLintError()).isEmpty();
+ assertThat(validationResult.getLintWarning()).isNotEmpty();
+ }
+
+ @Test
+ void shouldAddUsedVersionToValidationResultOnLinted() {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT_STRICT, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+ assertThat(validationResult.getVersionUsed()).isEqualTo(SAMPLE_VERSION);
+ }
+
+ @Test
+ void shouldAddUsedVersionToValidationResultOnNotLinted() {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, NOT_LINTED, NOT_STRICT_LINTED);
+ assertThat(validationResult.getVersionUsed()).isEqualTo(SAMPLE_VERSION);
+ }
+
+ @Test
+ void shouldAddBashOutputToResultWhenHelmReturnNonStandardError() {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT_STRICT, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_WITHOUT_STANDARD_ERROR_ON_LINT);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+ assertThat(validationResult.getLintError()).isNotEmpty();
+ }
+
+ @Test
+ void shouldNotAddSummaryMessageToLintErrors() {
+ mockBashCommand(HELM_TEMPLATE, SUCCESS_HELM_EXIT_CODE, HELM_EMPTY_OUTPUT);
+ mockBashCommand(HELM_LINT_STRICT, UNSUCCESSFUL_HELM_EXIT_CODE, HELM_ERROR_ON_LINT,
+ HELM_LINT_ERROR_SUMMARY_MESSAGE);
+
+ ValidationResult validationResult = validationService
+ .process(SAMPLE_VERSION, multipartFile, LINTED, STRICT_LINTED);
+ assertThat(validationResult.getLintError()).isNotEmpty();
+ assertThat(validationResult.getLintError()).hasSize(EXPECTED_ONE);
+ }
+
+ private String getLatestSampleHelmVersion(String majorVersion) {
+ return SAMPLE_VERSIONS.stream()
+ .filter(version -> version.startsWith(majorVersion))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("Not supported version"));
+ }
+
+ private void mockBashCommand(String command, int exitValue, String... consoleOutput) {
+ when(bashExecutor.execute(command))
+ .thenReturn(new BashOutput(exitValue, mockBashConsoleLog(consoleOutput)));
+ }
+
+ private List<String> mockBashConsoleLog(String... args) {
+ return Arrays.stream(args).collect(Collectors.toList());
+ }
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReaderTest.java b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReaderTest.java
new file mode 100644
index 0000000..7343e59
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/ApiVersionsReaderTest.java
@@ -0,0 +1,128 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ApiVersionNotFoundException;
+import org.onap.sdc.helmvalidator.helm.versions.exception.ReadFileException;
+
+class ApiVersionsReaderTest {
+
+ private static final String TEST_RESOURCES_TMP = "src/test/resources/tmp";
+ private static final Path TEST_CHART_PATH = Path.of(TEST_RESOURCES_TMP).resolve(Path.of("Chart.yaml"));
+
+ private static final Path TEST_TAR_PATH = Path.of(TEST_RESOURCES_TMP, "test.tar");
+
+ private ApiVersionsReader apiVersionsReader;
+
+ @BeforeEach
+ void setUp() {
+ apiVersionsReader = new ApiVersionsReader();
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"v1", "v2"})
+ void shouldCorrectlyReadApiVersionFromTar(String apiVersion) throws IOException {
+ prepareTestTar(apiVersion);
+
+ String helmVersion = apiVersionsReader.readVersion(TEST_TAR_PATH.toString());
+
+ assertThat(helmVersion).isEqualTo(apiVersion);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenApiVersionIsNotProvided() throws IOException {
+ prepareTestTar(null);
+
+ Exception exception = assertThrows(ApiVersionNotFoundException.class,
+ () -> apiVersionsReader.readVersion(TEST_TAR_PATH.toString()));
+
+ assertThat(exception).hasMessageContaining("Cannot find apiVersion value in a main chart");
+ }
+
+ @Test
+ void shouldThrowExceptionForNotExistingPath() {
+ String notExistingChartPath = "not/exiting/chart/path";
+
+ Exception exception = assertThrows(ReadFileException.class,
+ () -> apiVersionsReader.readVersion(notExistingChartPath));
+
+ assertThat(exception).hasMessageContaining("Cannot read tar from path: " + notExistingChartPath);
+ }
+
+ @AfterEach
+ void cleanTmpDir() throws IOException {
+ Files.walk(Paths.get(TEST_RESOURCES_TMP))
+ .map(Path::toFile)
+ .filter(File::isFile)
+ .forEach(File::delete);
+ }
+
+ private void prepareTestTar(String apiVersion) throws IOException {
+ createTestChart(apiVersion);
+ createTestTar();
+ }
+
+ private void createTestTar() throws IOException {
+ TarArchiveOutputStream tarOutput = null;
+ try {
+ tarOutput = new TarArchiveOutputStream(
+ new GzipCompressorOutputStream(new FileOutputStream(String.valueOf(TEST_TAR_PATH))));
+
+ final String tarChartPath = "test/Chart.yaml";
+ TarArchiveEntry tarArchiveEntry = new TarArchiveEntry(TEST_CHART_PATH.toFile(), tarChartPath);
+ tarOutput.putArchiveEntry(tarArchiveEntry);
+
+ Files.copy(TEST_CHART_PATH, tarOutput);
+ } finally {
+ if (tarOutput != null) {
+ tarOutput.closeArchiveEntry();
+ tarOutput.close();
+ }
+ }
+ }
+
+ private void createTestChart(String apiVersion) throws IOException {
+ String apiVersionLine = apiVersion != null ? "apiVersion: " + apiVersion : "";
+
+ Files.createDirectories(TEST_CHART_PATH.getParent());
+ Files.createFile(TEST_CHART_PATH);
+ Files.write(TEST_CHART_PATH, List.of("appVersion: 1.0", apiVersionLine, "name: test-chart"));
+ }
+
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProviderTest.java b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProviderTest.java
new file mode 100644
index 0000000..64daf2d
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/ChartBasedVersionProviderTest.java
@@ -0,0 +1,73 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.sdc.helmvalidator.helm.versions.exception.NotSupportedApiVersionException;
+
+@ExtendWith(MockitoExtension.class)
+class ChartBasedVersionProviderTest {
+
+ private final String testChartPath = "test/path";
+ @Mock
+ private SupportedVersionsProvider versionsProvider;
+ @Mock
+ private ApiVersionsReader apiVersionsReader;
+ private ChartBasedVersionProvider chartBasedVersionProvider;
+
+ @BeforeEach
+ void setUp() {
+ chartBasedVersionProvider = new ChartBasedVersionProvider(versionsProvider, apiVersionsReader);
+ }
+
+ @ParameterizedTest
+ @CsvSource({"v1,2.18", "v2,3.11"})
+ void shouldGetLatestHelmVersionBasedOnApiVersion(String apiVersion, String expectedHelmVersion) {
+ when(apiVersionsReader.readVersion(testChartPath)).thenReturn(apiVersion);
+ when(versionsProvider.getLatestVersion(Mockito.anyString())).thenReturn(expectedHelmVersion);
+
+ String helmVersion = chartBasedVersionProvider.getVersion(testChartPath);
+
+ assertThat(helmVersion).isEqualTo(expectedHelmVersion);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenApiVersionIsNotSupported() {
+ when(apiVersionsReader.readVersion(testChartPath)).thenReturn("v3");
+
+ Exception exception = assertThrows(NotSupportedApiVersionException.class,
+ () -> chartBasedVersionProvider.getVersion(testChartPath));
+
+ assertThat(exception).hasMessageContaining("Cannot obtain Helm version from API version: v3");
+ }
+
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProviderTest.java b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProviderTest.java
new file mode 100644
index 0000000..c28d339
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/SupportedVersionsProviderTest.java
@@ -0,0 +1,72 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class SupportedVersionsProviderTest {
+
+ private static final List<String> UNSORTED_VERSIONS = List.of("1.0.0", "2.2.1", "2.0.0", "3.0.0");
+ private static final List<String> SORTED_VERSIONS = List.of("3.0.0", "2.2.1", "2.0.0", "1.0.0");
+ private static final List<String> SUPPORTED_VERSIONS = List.of("4.2.0", "3.11.3", "3.1.0", "3.0.4", "2.18.2",
+ "2.1.5", "1.5.6");
+
+ private SupportedVersionsProvider versionsProvider;
+
+ @Mock
+ private SystemEnvVersionsReader versionsReader;
+
+ @BeforeEach
+ void setUp() {
+ versionsProvider = new SupportedVersionsProvider(versionsReader);
+ }
+
+ @Test
+ void shouldReturnSortedVersionsInRevertOrder() {
+
+ when(versionsReader.readVersions()).thenReturn(UNSORTED_VERSIONS);
+
+ List<String> versions = versionsProvider.getVersions();
+
+ assertThat(versions).isEqualTo(SORTED_VERSIONS);
+ }
+
+ @ParameterizedTest
+ @CsvSource({"2,2.18.2", "3,3.11.3"})
+ void shouldGetLatestHelmVersionBasedOnDesiredMajorVersion(String desiredMajorVersion, String expectedHelmVersion) {
+ when(versionsProvider.getVersions()).thenReturn(SUPPORTED_VERSIONS);
+
+ String helmVersion = versionsProvider.getLatestVersion(desiredMajorVersion);
+
+ assertThat(helmVersion).isEqualTo(expectedHelmVersion);
+ }
+}
diff --git a/src/test/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReaderTest.java b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReaderTest.java
new file mode 100644
index 0000000..7748355
--- /dev/null
+++ b/src/test/java/org/onap/sdc/helmvalidator/helm/versions/SystemEnvVersionsReaderTest.java
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC-HELM-VALIDATOR
+ * ================================================================================
+ * Copyright (C) 2021 Nokia. 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.sdc.helmvalidator.helm.versions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class SystemEnvVersionsReaderTest {
+
+ private static final String SINGLE_VERSION_VALUE = "3.2.1";
+ private static final String MULTIPLE_VERSIONS_VALUE = "3.2.1,2.0.0,1.0.0";
+ private static final int EXPECTED_SIZE_ONE = 1;
+ private static final int EXPECTED_SIZE_THREE = 3;
+
+ @Spy
+ private SystemEnvVersionsReader versionsReader;
+
+ @Test
+ void canReadSingleValue() {
+ when(versionsReader.getSupportedVersionsFromEnv()).thenReturn(SINGLE_VERSION_VALUE);
+
+ List<String> versions = versionsReader.readVersions();
+
+ assertThat(versions).hasSize(EXPECTED_SIZE_ONE);
+ }
+
+ @Test
+ void canReadMultipleValues() {
+ when(versionsReader.getSupportedVersionsFromEnv()).thenReturn(MULTIPLE_VERSIONS_VALUE);
+
+ List<String> versions = versionsReader.readVersions();
+
+ assertThat(versions).hasSize(EXPECTED_SIZE_THREE);
+ }
+
+ @Test
+ void returnEmptyListWhenVariableIsNotPresent() {
+ when(versionsReader.getSupportedVersionsFromEnv()).thenReturn("");
+
+ List<String> versions = versionsReader.readVersions();
+
+ assertThat(versions).isEmpty();
+ }
+}
diff --git a/version.properties b/version.properties
new file mode 100644
index 0000000..e8f8e5a
--- /dev/null
+++ b/version.properties
@@ -0,0 +1,6 @@
+major=0
+minor=0
+patch=1
+base_version=${major}.${minor}.${patch}
+release_version=${base_version}
+snapshot_version=${base_version}-SNAPSHOT