e2ccda4d5e1dd2888f9ae980607e7e1679ca7c5d
[policy/clamp.git] /
1 /*-
2  * ========================LICENSE_START=================================
3  * Copyright (C) 2021-2022 Nordix Foundation. 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.policy.clamp.controlloop.participant.kubernetes.controller;
20
21 import io.swagger.annotations.Api;
22 import io.swagger.annotations.ApiOperation;
23 import io.swagger.annotations.ApiResponse;
24 import io.swagger.annotations.ApiResponses;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import org.onap.policy.clamp.controlloop.participant.kubernetes.exception.ServiceException;
28 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartInfo;
29 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.ChartList;
30 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.HelmRepository;
31 import org.onap.policy.clamp.controlloop.participant.kubernetes.models.InstallationInfo;
32 import org.onap.policy.clamp.controlloop.participant.kubernetes.service.ChartService;
33 import org.onap.policy.common.utils.coder.CoderException;
34 import org.onap.policy.common.utils.coder.StandardCoder;
35 import org.springframework.beans.factory.annotation.Autowired;
36 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
37 import org.springframework.http.HttpStatus;
38 import org.springframework.http.MediaType;
39 import org.springframework.http.ResponseEntity;
40 import org.springframework.web.bind.annotation.DeleteMapping;
41 import org.springframework.web.bind.annotation.GetMapping;
42 import org.springframework.web.bind.annotation.PathVariable;
43 import org.springframework.web.bind.annotation.PostMapping;
44 import org.springframework.web.bind.annotation.RequestBody;
45 import org.springframework.web.bind.annotation.RequestMapping;
46 import org.springframework.web.bind.annotation.RequestParam;
47 import org.springframework.web.bind.annotation.RequestPart;
48 import org.springframework.web.bind.annotation.RestController;
49 import org.springframework.web.multipart.MultipartFile;
50
51 @RestController("chartController")
52 @ConditionalOnExpression("${chart.api.enabled:false}")
53 @RequestMapping("helm")
54 @Api(tags = {"k8s-participant"})
55 public class ChartController {
56
57     @Autowired
58     private ChartService chartService;
59
60     private static final StandardCoder CODER = new StandardCoder();
61
62     /**
63      * REST endpoint to get all the charts.
64      *
65      * @return List of charts installed
66      */
67     @GetMapping(path = "/charts", produces = MediaType.APPLICATION_JSON_VALUE)
68     @ApiOperation(value = "Return all Charts")
69     @ApiResponses(value = {@ApiResponse(code = 200, message = "chart List")})
70     public ResponseEntity<ChartList> getAllCharts() {
71         return new ResponseEntity<>(ChartList.builder().charts(new ArrayList<>(chartService.getAllCharts())).build(),
72                 HttpStatus.OK);
73     }
74
75     /**
76      * REST endpoint to install a helm chart.
77      *
78      * @param info Info of the chart to be installed
79      * @return Status of the install operation
80      * @throws ServiceException in case of error
81      * @throws IOException in case of IO error
82      */
83     @PostMapping(path = "/install", consumes = MediaType.APPLICATION_JSON_VALUE,
84             produces = MediaType.APPLICATION_JSON_VALUE)
85     @ApiOperation(value = "Install the chart")
86     @ApiResponses(value = {@ApiResponse(code = 201, message = "chart Installed")})
87     public ResponseEntity<Object> installChart(@RequestBody InstallationInfo info)
88             throws ServiceException, IOException {
89         ChartInfo chart = chartService.getChart(info.getName(), info.getVersion());
90         if (chart == null) {
91             return new ResponseEntity<>(HttpStatus.NOT_FOUND);
92         }
93
94         chartService.installChart(chart);
95         return new ResponseEntity<>(HttpStatus.CREATED);
96     }
97
98     /**
99      * REST endpoint to uninstall a specific chart.
100      *
101      * @param name name of the chart
102      * @param version version of the chart
103      * @return Status of operation
104      * @throws ServiceException in case of error.
105      */
106     @DeleteMapping(path = "/uninstall/{name}/{version}", produces = MediaType.APPLICATION_JSON_VALUE)
107     @ApiOperation(value = "Uninstall the Chart")
108     @ApiResponses(value = {@ApiResponse(code = 201, message = "chart Uninstalled")})
109     public ResponseEntity<Object> uninstallChart(@PathVariable("name") String name,
110             @PathVariable("version") String version) throws ServiceException {
111         ChartInfo chart = chartService.getChart(name, version);
112         if (chart == null) {
113             return new ResponseEntity<>(HttpStatus.NOT_FOUND);
114         }
115
116         chartService.uninstallChart(chart);
117         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
118     }
119
120     /**
121      * REST endpoint to onboard a chart.
122      *
123      * @param chartFile Multipart file for the helm chart
124      * @param infoJson AppInfo of the chart
125      * @param overrideFile the file for overriding the chart
126      * @return Status of onboard operation
127      * @throws ServiceException in case of error
128      * @throws IOException in case of IO error
129      */
130     @PostMapping(path = "/onboard/chart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
131             produces = MediaType.APPLICATION_JSON_VALUE)
132     @ApiOperation(value = "Onboard the Chart")
133     @ApiResponses(value = {@ApiResponse(code = 201, message = "Chart Onboarded")})
134     public ResponseEntity<String> onboardChart(@RequestPart("chart") MultipartFile chartFile,
135             @RequestParam(name = "values", required = false) MultipartFile overrideFile,
136             @RequestParam("info") String infoJson) throws ServiceException, IOException {
137
138         ChartInfo info;
139         try {
140             info = CODER.decode(infoJson, ChartInfo.class);
141         } catch (CoderException e) {
142             throw new ServiceException("Error parsing the chart information", e);
143         }
144
145         chartService.saveChart(info, chartFile, overrideFile);
146         return new ResponseEntity<>(HttpStatus.OK);
147     }
148
149     /**
150      * REST endpoint to delete a specific helm chart.
151      *
152      * @param name name of the chart
153      * @param version version of the chart
154      * @return Status of operation
155      */
156     @DeleteMapping(path = "/chart/{name}/{version}")
157     @ApiOperation(value = "Delete the chart")
158     @ApiResponses(value = {@ApiResponse(code = 204, message = "Chart Deleted")})
159     public ResponseEntity<Object> deleteChart(@PathVariable("name") String name,
160             @PathVariable("version") String version) {
161
162         ChartInfo chart = chartService.getChart(name, version);
163         if (chart == null) {
164             return new ResponseEntity<>(HttpStatus.NOT_FOUND);
165         }
166
167         chartService.deleteChart(chart);
168         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
169     }
170
171     /**
172      * REST endpoint to configure a helm Repository.
173      *
174      * @param repo Helm repository to be configured
175      * @return Status of the operation
176      * @throws ServiceException in case of error
177      * @throws IOException in case of IO error
178      */
179     @PostMapping(path = "/repo", consumes = MediaType.APPLICATION_JSON_VALUE,
180             produces = MediaType.APPLICATION_JSON_VALUE)
181     @ApiOperation(value = "Configure helm repository")
182     @ApiResponses(value = {@ApiResponse(code = 201, message = "Repository added")})
183     public ResponseEntity<Object> configureRepo(@RequestBody String repo)
184             throws ServiceException, IOException {
185         HelmRepository repository;
186         try {
187             repository = CODER.decode(repo, HelmRepository.class);
188         } catch (CoderException e) {
189             throw new ServiceException("Error parsing the repository information", e);
190         }
191         chartService.configureRepository(repository);
192
193         return new ResponseEntity<>(HttpStatus.CREATED);
194     }
195 }