--- /dev/null
+########
+# Copyright (c) 2019 Cloudify Platform Ltd. 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.
+
+import json
+
+from .exceptions import CloudifyHelmSDKError
+from helm_sdk.utils import (
+ run_subprocess,
+ prepare_parameter,
+ prepare_set_parameters,
+ validate_no_collisions_between_params_and_flags)
+
+# Helm cli flags names
+HELM_KUBECONFIG_FLAG = 'kubeconfig'
+HELM_KUBE_API_SERVER_FLAG = 'kube-apiserver'
+HELM_KUBE_TOKEN_FLAG = 'kube-token'
+HELM_VALUES_FLAG = 'values'
+APPEND_FLAG_STRING = '--{name}={value}'
+
+
+class Helm(object):
+
+ def __init__(self,
+ logger,
+ binary_path,
+ environment_variables
+ ):
+ self.binary_path = binary_path
+ self.logger = logger
+ if not isinstance(environment_variables, dict):
+ raise Exception(
+ "Unexpected type for environment variables (should be a "
+ "dict): {0}".format(type(
+ environment_variables)))
+
+ self.env = environment_variables
+
+ def execute(self, command, return_output=False):
+ return run_subprocess(
+ command,
+ self.logger,
+ cwd=None,
+ additional_env=self.env,
+ additional_args=None,
+ return_output=return_output)
+
+ def _helm_command(self, args):
+ cmd = [self.binary_path]
+ cmd.extend(args)
+ return cmd
+
+ @staticmethod
+ def handle_auth_params(cmd,
+ kubeconfig=None,
+ token=None,
+ apiserver=None):
+ """
+ Validation of authentication params.
+ Until helm will support --insecure, kubeconfig must be provided.
+ :param kubeconfig: Kubeconfig file path
+ :param: token: bearer token used for authentication.
+ :param: apiserver: the address and the port for the Kubernetes API
+ server.
+ """
+ if kubeconfig is None:
+ raise CloudifyHelmSDKError(
+ 'Must provide kubeconfig file path.')
+ else:
+ cmd.append(APPEND_FLAG_STRING.format(name=HELM_KUBECONFIG_FLAG,
+ value=kubeconfig))
+
+ if token:
+ cmd.append(APPEND_FLAG_STRING.format(name=HELM_KUBE_TOKEN_FLAG,
+ value=token))
+
+ if apiserver:
+ cmd.append(
+ APPEND_FLAG_STRING.format(name=HELM_KUBE_API_SERVER_FLAG,
+ value=apiserver))
+
+ def install(self,
+ name,
+ chart,
+ flags=None,
+ set_values=None,
+ values_file=None,
+ kubeconfig=None,
+ token=None,
+ apiserver=None,
+ **_):
+ """
+ Execute helm install command.
+ :param name: name for the created release.
+ :param chart: chart name to install.
+ :param flags: list of flags to add to the install command.
+ :param set_values: list of variables and their values for --set.
+ :param kubeconfig: path to kubeconfig file.
+ :param values_file: values file path.
+ :param token: bearer token used for authentication.
+ :param apiserver: the address and the port for the Kubernetes API
+ server.
+ :return output of install command.
+ """
+ cmd = ['install', name, chart, '--wait', '--output=json']
+ self.handle_auth_params(cmd, kubeconfig, token, apiserver)
+ if values_file:
+ cmd.append(APPEND_FLAG_STRING.format(name=HELM_VALUES_FLAG,
+ value=values_file))
+ flags = flags or []
+ validate_no_collisions_between_params_and_flags(flags)
+ cmd.extend([prepare_parameter(flag) for flag in flags])
+ set_arguments = set_values or []
+ cmd.extend(prepare_set_parameters(set_arguments))
+ output = self.execute(self._helm_command(cmd), True)
+ return json.loads(output)
+
+ def uninstall(self,
+ name,
+ flags=None,
+ kubeconfig=None,
+ token=None,
+ apiserver=None,
+ **_):
+ cmd = ['uninstall', name]
+ self.handle_auth_params(cmd, kubeconfig, token, apiserver)
+ flags = flags or []
+ validate_no_collisions_between_params_and_flags(flags)
+ cmd.extend([prepare_parameter(flag) for flag in flags])
+ self.execute(self._helm_command(cmd))
+
+ def repo_add(self,
+ name,
+ repo_url,
+ flags=None,
+ **_):
+ cmd = ['repo', 'add', name, repo_url]
+ flags = flags or []
+ cmd.extend([prepare_parameter(flag) for flag in flags])
+ self.execute(self._helm_command(cmd))
+
+ def repo_remove(self,
+ name,
+ flags=None,
+ **_):
+ cmd = ['repo', 'remove', name]
+ flags = flags or []
+ cmd.extend([prepare_parameter(flag) for flag in flags])
+ self.execute(self._helm_command(cmd))
+
+ def repo_list(self):
+ cmd = ['repo', 'list', '--output=json']
+ output = self.execute(self._helm_command(cmd), True)
+ return json.loads(output)
+
+ def repo_update(self, flags):
+ cmd = ['repo', 'update']
+ flags = flags or []
+ cmd.extend([prepare_parameter(flag) for flag in flags])
+ self.execute(self._helm_command(cmd))
+
+ def upgrade(self,
+ release_name,
+ chart=None,
+ flags=None,
+ set_values=None,
+ values_file=None,
+ kubeconfig=None,
+ token=None,
+ apiserver=None,
+ **_):
+ """
+ Execute helm upgrade command.
+ :param release_name: name of the release to upgrade.
+ :param chart: The chart to upgrade the release with.
+ The chart argument can be either: a chart reference('example/mariadb'),
+ a packaged chart, or a fully qualified URL.
+ :param flags: list of flags to add to the upgrade command.
+ :param set_values: list of variables and their values for --set.
+ :param kubeconfig: path to kubeconfig file.
+ :param values_file: values file path.
+ :param token: bearer token used for authentication.
+ :param apiserver: the address and the port for the Kubernetes API
+ server.
+ :return output of helm upgrade command.
+ """
+ if not chart:
+ raise CloudifyHelmSDKError(
+ 'Must provide chart for upgrade release.')
+ cmd = ['upgrade', release_name, chart, '--atomic', '-o=json']
+ self.handle_auth_params(cmd, kubeconfig, token, apiserver)
+ if values_file:
+ cmd.append(APPEND_FLAG_STRING.format(name=HELM_VALUES_FLAG,
+ value=values_file))
+ flags = flags or []
+ validate_no_collisions_between_params_and_flags(flags)
+ cmd.extend([prepare_parameter(flag) for flag in flags])
+ set_arguments = set_values or []
+ cmd.extend(prepare_set_parameters(set_arguments))
+ output = self.execute(self._helm_command(cmd), True)
+ return json.loads(output)