Merge "OAuth2 support"
[pti/o2.git] / helm_sdk / __init__.py
1 ########
2 # Copyright (c) 2019 Cloudify Platform Ltd. All rights reserved
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #        http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 #    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 #    * See the License for the specific language governing permissions and
14 #    * limitations under the License.
15
16 import json
17
18 from .exceptions import CloudifyHelmSDKError
19 from helm_sdk.utils import (
20     run_subprocess,
21     prepare_parameter,
22     prepare_set_parameters,
23     validate_no_collisions_between_params_and_flags)
24
25 # Helm cli flags names
26 HELM_KUBECONFIG_FLAG = 'kubeconfig'
27 HELM_KUBE_API_SERVER_FLAG = 'kube-apiserver'
28 HELM_KUBE_TOKEN_FLAG = 'kube-token'
29 HELM_VALUES_FLAG = 'values'
30 APPEND_FLAG_STRING = '--{name}={value}'
31
32
33 class Helm(object):
34
35     def __init__(self,
36                  logger,
37                  binary_path,
38                  environment_variables
39                  ):
40         self.binary_path = binary_path
41         self.logger = logger
42         if not isinstance(environment_variables, dict):
43             raise Exception(
44                 "Unexpected type for environment variables (should be a "
45                 "dict): {0}".format(type(
46                     environment_variables)))
47
48         self.env = environment_variables
49
50     def execute(self, command, return_output=False):
51         return run_subprocess(
52             command,
53             self.logger,
54             cwd=None,
55             additional_env=self.env,
56             additional_args=None,
57             return_output=return_output)
58
59     def _helm_command(self, args):
60         cmd = [self.binary_path]
61         cmd.extend(args)
62         return cmd
63
64     @staticmethod
65     def handle_auth_params(cmd,
66                            kubeconfig=None,
67                            token=None,
68                            apiserver=None):
69         """
70             Validation of authentication params.
71             Until helm will support --insecure, kubeconfig must be provided.
72             :param kubeconfig: Kubeconfig file path
73             :param: token: bearer token used for authentication.
74             :param: apiserver: the address and the port for the Kubernetes API
75             server.
76         """
77         if kubeconfig is None:
78             raise CloudifyHelmSDKError(
79                 'Must provide kubeconfig file path.')
80         else:
81             cmd.append(APPEND_FLAG_STRING.format(name=HELM_KUBECONFIG_FLAG,
82                                                  value=kubeconfig))
83
84         if token:
85             cmd.append(APPEND_FLAG_STRING.format(name=HELM_KUBE_TOKEN_FLAG,
86                                                  value=token))
87
88         if apiserver:
89             cmd.append(
90                 APPEND_FLAG_STRING.format(name=HELM_KUBE_API_SERVER_FLAG,
91                                           value=apiserver))
92
93     def install(self,
94                 name,
95                 chart,
96                 flags=None,
97                 set_values=None,
98                 values_file=None,
99                 kubeconfig=None,
100                 token=None,
101                 apiserver=None,
102                 **_):
103         """
104         Execute helm install command.
105         :param name: name for the created release.
106         :param chart: chart name to install.
107         :param flags: list of flags to add to the install command.
108         :param set_values: list of variables and their values for --set.
109         :param kubeconfig: path to kubeconfig file.
110         :param values_file: values file path.
111         :param token: bearer token used for authentication.
112         :param apiserver: the address and the port for the Kubernetes API
113         server.
114         :return output of install command.
115         """
116         cmd = ['install', name, chart, '--wait', '--output=json']
117         self.handle_auth_params(cmd, kubeconfig, token, apiserver)
118         if values_file:
119             cmd.append(APPEND_FLAG_STRING.format(name=HELM_VALUES_FLAG,
120                                                  value=values_file))
121         flags = flags or []
122         validate_no_collisions_between_params_and_flags(flags)
123         cmd.extend([prepare_parameter(flag) for flag in flags])
124         set_arguments = set_values or []
125         cmd.extend(prepare_set_parameters(set_arguments))
126         output = self.execute(self._helm_command(cmd), True)
127         return json.loads(output)
128
129     def uninstall(self,
130                   name,
131                   flags=None,
132                   kubeconfig=None,
133                   token=None,
134                   apiserver=None,
135                   **_):
136         cmd = ['uninstall', name]
137         self.handle_auth_params(cmd, kubeconfig, token, apiserver)
138         flags = flags or []
139         validate_no_collisions_between_params_and_flags(flags)
140         cmd.extend([prepare_parameter(flag) for flag in flags])
141         self.execute(self._helm_command(cmd))
142
143     def repo_add(self,
144                  name,
145                  repo_url,
146                  flags=None,
147                  **_):
148         cmd = ['repo', 'add', name, repo_url]
149         flags = flags or []
150         cmd.extend([prepare_parameter(flag) for flag in flags])
151         self.execute(self._helm_command(cmd))
152
153     def repo_remove(self,
154                     name,
155                     flags=None,
156                     **_):
157         cmd = ['repo', 'remove', name]
158         flags = flags or []
159         cmd.extend([prepare_parameter(flag) for flag in flags])
160         self.execute(self._helm_command(cmd))
161
162     def repo_list(self):
163         cmd = ['repo', 'list', '--output=json']
164         output = self.execute(self._helm_command(cmd), True)
165         return json.loads(output)
166
167     def repo_update(self, flags):
168         cmd = ['repo', 'update']
169         flags = flags or []
170         cmd.extend([prepare_parameter(flag) for flag in flags])
171         self.execute(self._helm_command(cmd))
172
173     def upgrade(self,
174                 release_name,
175                 chart=None,
176                 flags=None,
177                 set_values=None,
178                 values_file=None,
179                 kubeconfig=None,
180                 token=None,
181                 apiserver=None,
182                 **_):
183         """
184         Execute helm upgrade command.
185         :param release_name: name of the release to upgrade.
186         :param chart: The chart to upgrade the release with.
187         The chart argument can be either: a chart reference('example/mariadb'),
188         a packaged chart, or a fully qualified URL.
189         :param flags: list of flags to add to the upgrade command.
190         :param set_values: list of variables and their values for --set.
191         :param kubeconfig: path to kubeconfig file.
192         :param values_file: values file path.
193         :param token: bearer token used for authentication.
194         :param apiserver: the address and the port for the Kubernetes API
195         server.
196         :return output of helm upgrade command.
197         """
198         if not chart:
199             raise CloudifyHelmSDKError(
200                 'Must provide chart for upgrade release.')
201         cmd = ['upgrade', release_name, chart, '--atomic', '-o=json']
202         self.handle_auth_params(cmd, kubeconfig, token, apiserver)
203         if values_file:
204             cmd.append(APPEND_FLAG_STRING.format(name=HELM_VALUES_FLAG,
205                                                  value=values_file))
206         flags = flags or []
207         validate_no_collisions_between_params_and_flags(flags)
208         cmd.extend([prepare_parameter(flag) for flag in flags])
209         set_arguments = set_values or []
210         cmd.extend(prepare_set_parameters(set_arguments))
211         output = self.execute(self._helm_command(cmd), True)
212         return json.loads(output)