Improved helm-generator code to make it more testable and improved code coverage
[dcaegen2/platform.git] / mod2 / helm-generator / helmchartgenerator-core / src / main / java / org / onap / dcaegen2 / platform / helmchartgenerator / chartbuilder / HelmClientImpl.java
1 /*
2  * # ============LICENSE_START=======================================================
3  * # Copyright (c) 2021 AT&T Intellectual Property. All rights reserved.
4  * # ================================================================================
5  * # Licensed under the Apache License, Version 2.0 (the "License");
6  * # you may not use this file except in compliance with the License.
7  * # You may obtain a copy of the License at
8  * #
9  * #      http://www.apache.org/licenses/LICENSE-2.0
10  * #
11  * # Unless required by applicable law or agreed to in writing, software
12  * # distributed under the License is distributed on an "AS IS" BASIS,
13  * # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * # See the License for the specific language governing permissions and
15  * # limitations under the License.
16  * # ============LICENSE_END=========================================================
17  */
18
19 package org.onap.dcaegen2.platform.helmchartgenerator.chartbuilder;
20
21 import lombok.extern.slf4j.Slf4j;
22 import org.springframework.beans.factory.annotation.Value;
23 import org.springframework.stereotype.Component;
24
25 import java.io.BufferedReader;
26 import java.io.File;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30 import java.util.stream.Collectors;
31
32 /**
33  * HelmClient implementation which uses helm command installed in the runtime environment.
34  * @author Dhrumin Desai
35  */
36 @Component
37 @Slf4j
38 public class HelmClientImpl implements HelmClient {
39
40     private final String repoUrl;
41
42     private final String username;
43
44     private final String password;
45
46     public HelmClientImpl(@Value("${chartmuseum.baseurl}")String repoUrl,
47                           @Value("${chartmuseum.auth.basic.username}")String username,
48                           @Value("${chartmuseum.auth.basic.password}")String password) {
49         this.repoUrl = repoUrl;
50         this.username = username;
51         this.password = password;
52         try{
53             repoAdd(repoUrl, username,password);
54         }catch (Exception e){
55             log.warn("Could not add helm repo.");
56         }
57     }
58
59     private void repoAdd(String repoUrl, String username, String password) {
60         ProcessBuilder builder = new ProcessBuilder();
61         builder.inheritIO();
62         builder.command("helm", "repo", "add", "local",  repoUrl,
63                         "--username", username, "--password", password);
64         runProcess(builder, "repoAdd");
65     }
66
67     /**
68      * performs <code>helm lint</code> operation
69      * @param chartLocation helm chart location
70      */
71     @Override
72     public void lint(File chartLocation) {
73         helmDepUp(chartLocation.getAbsolutePath());
74         ProcessBuilder builder = new ProcessBuilder();
75         builder.command("helm", "lint", chartLocation.getAbsolutePath());
76         runProcess(builder, "lint");
77     }
78
79     /**
80      *  performs <code>helm package</code> operation
81      * @param chartLocation helm chart location
82      * @param outputLocation location to store the generated helm package
83      * @return generated helm tgz file
84      */
85     @Override
86     public File packageChart(File chartLocation, String outputLocation) {
87         ProcessBuilder builder = new ProcessBuilder();
88         builder.directory(new File(System.getProperty("user.dir")));
89         builder.command("helm", "package", "-d", outputLocation, chartLocation.getAbsolutePath());
90         return runProcess(builder, "package");
91     }
92
93     private void helmDepUp(String chartLocation) {
94         ProcessBuilder builder = new ProcessBuilder();
95         builder.inheritIO();
96         builder.command("helm", "dep", "up",chartLocation);
97         runProcess(builder, "helmDepUp");
98     }
99
100     private File runProcess(ProcessBuilder builder, String command) {
101         log.info("running: " + String.join(" ",builder.command()));
102         Process process = null;
103         String chartPath = "";
104         try {
105             process = builder.start();
106             if(command.equals("package")) {
107                 chartPath = printPackagingProcessOutput(process);
108             }
109             else {
110                 printProcessOutput(process);
111             }
112             assertExitCode(process);
113         }  catch (IOException e) {
114             log.error(e.getMessage(), e);
115             throw new RuntimeException("Error occurred while running helm command.");
116         } catch (InterruptedException e) {
117             log.error(e.getMessage(), e);
118             Thread.currentThread().interrupt();
119             throw new RuntimeException("execution interrupted");
120         }
121         return new File(chartPath);
122     }
123
124     private void printProcessOutput(Process process) throws IOException {
125         final InputStream inputStream = process.getInputStream();
126         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
127         reader.lines().forEach(log::info);
128         inputStream.close();
129     }
130
131     private String printPackagingProcessOutput(Process process) throws IOException {
132         String helmChartPath = "";
133         final InputStream inputStream = process.getInputStream();
134         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
135         String line;
136         while ((line = reader.readLine()) != null){
137             if (line.contains("Successfully packaged chart and saved it to: ")){
138                 helmChartPath = line.split("Successfully packaged chart and saved it to: ")[1];
139             }
140             log.info(line);
141         }
142         inputStream.close();
143         if(helmChartPath.isEmpty()){
144             throw new RuntimeException("Could not generate the chart.");
145         }
146         return helmChartPath;
147     }
148
149     private void assertExitCode(Process process) throws InterruptedException {
150         int exitCode = 0;
151         exitCode = process.waitFor();
152         process.destroy();
153         if (exitCode != 0){
154             throw new RuntimeException("Error occurred while running helm command.");
155         }
156     }
157 }