def __init__(self, **kw): super(KubernetesRunner, self).__init__(**kw) config.load_kube_config() c = Configuration() c.assert_hostname = False Configuration.set_default(c) self._kclient = core_v1_api.CoreV1Api() config.list_kube_config_contexts() self._namespace = self._config.resman_opts.get("namespace", "default") self._base_pod_name = pu.sanitized_name(f"pod", self._config.wid) self._base_pod_name = self._base_pod_name.replace("_", "-") self._init_pod_name = pu.sanitized_name("init-pod", self._config.wid) self._init_pod_name = self._init_pod_name.replace("_", "-") self._vol_claim_name = f"{self._base_pod_name}-pvc" self._vol_size = self._config.resman_opts.get("volume_size", "500Mi") self._init_pod_created = False self._vol_claim_created = False
def setUp(self): log.setLevel("CRITICAL") config.load_kube_config() c = Configuration() c.assert_hostname = False Configuration.set_default(c) self._kclient = core_v1_api.CoreV1Api() config.list_kube_config_contexts()
def get_all_pods(name): name = name.replace('*', '.*') try: all_contexts = [context['name'] for context in config.list_kube_config_contexts()[0]] except: # pylint:disable=bare-except return [] results = run_map(partial(get_pods_for_context, name=name), all_contexts, max_workers=2) instances = [] [[instances.append(Instance(cloud='k8s', # pylint: disable=expression-not-assigned zone=context, region=context, id=pod['metadata']['name'], name=pod['metadata']['name'], state=pod['status']['phase'].lower(), type='pod', autoscaling_group=None, public_dns_name=None, ip_address=None, iam_or_service_account=None, private_ip_address=None, project='k8s', security_groups=None, tags=None, created=datetime_to_str(pod['status']['start_time']), reservation_type='container', vpc_id=None)) for pod in pods] for context, pods in results.items()] return instances
def run_once(self): api_instance = client.CoreV1Api() config.list_kube_config_contexts() try: api_response = api_instance.list_pod_for_all_namespaces() self._pods = api_response.items self._namespaced_pods = [] for pod in self._pods: if pod.metadata.namespace == self.namespace: self._namespaced_pods.append(pod) except ApiException as e: print( "Exception when calling CoreV1Api->list_pod_for_all_namespaces: %s\n" % e) return int(time.time())
def list_context(self): (context_list, context_current ) = config.list_kube_config_contexts("/errbot/kubeconfig") result = [] for context in context_list: result.append(context["name"]) return result
def uninstall(ctx): """ Removes resources and deployments created by this installer from a Kubernetes cluster. """ if click.confirm(("Are you sure you wish to uninstall WALKOFF from your Kubernetes cluster? " "(This will only uninstall components that WALKOFF created through this installer.)")): k8s_api = None try: config_dir = os.environ.get('KUBECONFIG', os.path.join(os.path.expanduser("~"), ".kube", "config")) config_dir = click.prompt("Enter location of kubernetes config", default=config_dir) contexts, current = config.list_kube_config_contexts(config_file=config_dir) contexts = [context["name"] for context in contexts] current = current["name"] context = click.prompt("Available contexts: {}\nEnter context to uninstall WALKOFF from: ".format(contexts), default=current) config.load_kube_config(config_file=config_dir, context=context) k8s_api = k8s_client.CoreV1Api() except IOError as e: print("Could not open config: {}".format(e)) namespaces = k8s_api.list_namespace() namespaces = [ns.metadata.name for ns in namespaces.items] namespace = click.prompt( "Available namespaces: {}\nEnter namespace to uninstall WALKOFF from".format(namespaces), default="default") tiller_namespace = click.prompt('Enter the namespace your Tiller service resides in', default='kube-system') kubectl_command(['delete', 'cert', 'walkoff-cert'], namespace, exit_on_err=False) kubectl_command(['delete', 'issuer', 'walkoff-ca-issuer'], namespace, exit_on_err=False) kubectl_command(['delete', 'secrets', 'walkoff-redis-secret', 'walkoff-zmq-private-keys', 'walkoff-zmq-public-keys', 'walkoff-postgres-execution-secret', 'walkoff-postgres-secret', 'walkoff-ca-key-pair'], namespace, exit_on_err=False) kubectl_command(['delete', 'pvc', 'data-execution-db-postgresql-0', 'redis-data-walkoff-redis-master-0', 'data-walkoff-db-postgresql-0'], namespace, exit_on_err=False) kubectl_command(['delete', 'crd', 'certificates.certmanager.k8s.io', 'clusterissuers.certmanager.k8s.io', 'issuers.certmanager.k8s.io'], namespace, exit_on_err=False) helm_command(['del', '--purge', 'walkoff-redis'], tiller_namespace, exit_on_err=False) helm_command(['del', '--purge', 'walkoff-db'], tiller_namespace, exit_on_err=False) helm_command(['del', '--purge', 'execution-db'], tiller_namespace, exit_on_err=False) helm_command(['del', '--purge', 'walkoff-cert-manager'], tiller_namespace, exit_on_err=False) helm_command(['del', '--purge', 'walkoff-deployment'], tiller_namespace, exit_on_err=False)
def install_release(verbose: int): args = [ "helm", "install", "chaos-mesh", "helm/chaos-mesh", "--namespace=chaos-testing", ] print_to_output(verbose, "Ensuring namespace") ensure_namespace(verbose) print_to_output(verbose, "Current context check..") if "kind" in (config.list_kube_config_contexts()[1]["name"]): print_to_output(verbose, "Current context is kind") args = args + [ "--set", "chaosDaemon.runtime=containerd", "--set", "chaosDaemon.socketPath=/run/containerd/containerd.sock", ] print_to_output(verbose, "Installing release:") ui = os.environ.get("UI", "0") if ui == "1": args = args + ["--set", "dashboard.create=true"] subprocess.run( args, stdout=(subprocess.PIPE if verbose == 3 else subprocess.DEVNULL), stderr=(sys.stdout.buffer if verbose > 0 else subprocess.DEVNULL))
def get_clients(): """ Get clusters, clients for each cluster, and the active cluster :return: ((Dict) {cluster : context} (Dict) {cluster : {client_type : client}} (str) name of active cluster) """ clusters = k8s_config.update_available_clusters() contexts, active_context = config.list_kube_config_contexts( ) # assuming current active cluster is the hub active_cluster = active_context["context"]["cluster"] clients = {} for cluster in clusters: context = clusters[cluster] # building all clients for all clusters clients[cluster] = {} clients[cluster]["apps_client"] = client.AppsV1Api( api_client=config.new_client_from_config(context=context)) clients[cluster]["batch_client"] = client.BatchV1Api( api_client=config.new_client_from_config(context=context)) clients[cluster]["core_client"] = client.CoreV1Api( api_client=config.new_client_from_config(context=context)) clients[cluster]["ext_client"] = client.ExtensionsV1beta1Api( api_client=config.new_client_from_config(context=context)) clients[cluster]["api_client"] = client.ApiextensionsV1beta1Api( api_client=config.new_client_from_config(context=context)) clients[cluster]["customs_client"] = client.CustomObjectsApi( api_client=config.new_client_from_config(context=context)) return clusters, clients, active_cluster
def pickKubeConfigContext(): """ Allows you to pick a context and then lists all pods in the chosen context. :return: """ contexts, active_context = config.list_kube_config_contexts() if not contexts: print("Cannot find any context in kube-config file.") return contexts = [context['name'] for context in contexts] active_index = contexts.index(active_context['name']) option, _ = pick(contexts, title="Pick the context to load", default_index=active_index) # Configs can be set in Configuration class directly or using helper # utility config.load_kube_config(context=option) print("Active host is %s" % configuration.Configuration().host) v1 = client.CoreV1Api() print("Listing pods with their IPs:") ret = v1.list_pod_for_all_namespaces(watch=False) for item in ret.items: print( "%s\t%s\t%s" % (item.status.pod_ip, item.metadata.namespace, item.metadata.name))
def __init__(self, token=None, ca_file=None, context=None, host='127.0.0.1', port=443, user='******', debug=False, namespace=None, readwritemany=False): self.host = host self.port = port self.user = user self.ca_file = ca_file self.readwritemany = readwritemany self.context = context self.accessmode = 'ReadWriteMany' if readwritemany else 'ReadWriteOnce' self.conn = 'OK' self.namespace = namespace self.token = token api_client = None if host is not None and port is not None and token is not None: configuration = client.Configuration() configuration.host = "https://%s:%s" % (host, port) configuration.api_key = {"authorization": "Bearer " + token} if ca_file is not None: configuration.ssl_ca_cert = ca_file else: configuration.verify_ssl = False api_client = client.ApiClient(configuration) else: contexts, current = config.list_kube_config_contexts() if context is not None: contexts = [ entry for entry in contexts if entry['name'] == context ] if contexts: context = contexts[0] contextname = context['name'] else: self.conn = None else: context = current contextname = current['name'] self.contextname = contextname config.load_kube_config(context=contextname) if namespace is None and 'namespace' in context['context']: self.namespace = context['context']['namespace'] if 'cluster' in context['context'] and ':' in context['context'][ 'cluster']: self.host = context['context']['cluster'].split( ':')[0].replace('-', '.') self.core = client.CoreV1Api(api_client=api_client) self.v1beta = client.ExtensionsV1beta1Api(api_client=api_client) self.storageapi = client.StorageV1Api(api_client=api_client) self.api_client = api_client self.debug = debug if self.namespace is None: self.namespace = 'default' return
def check_aks_cluster(kube_config, kube_context): config_data = get_kubeconfig_node_dict(kube_config=kube_config) try: all_contexts, current_context = config.list_kube_config_contexts(config_file=kube_config) except Exception as e: # pylint: disable=broad-except logger.warning("Exception while trying to list kube contexts: %s\n", e) if kube_context is None: # Get name of the cluster from current context as kube_context is none. cluster_name = current_context.get('context').get('cluster') if cluster_name is None: logger.warning("Cluster not found in currentcontext: " + str(current_context)) else: cluster_found = False for context in all_contexts: if context.get('name') == kube_context: cluster_found = True cluster_name = context.get('context').get('cluster') break if not cluster_found or cluster_name is None: logger.warning("Cluster not found in kubecontext: " + str(kube_context)) clusters = config_data.safe_get('clusters') server_address = "" for cluster in clusters: if cluster.safe_get('name') == cluster_name: server_address = cluster.safe_get('cluster').get('server') break if server_address.find(".azmk8s.io:") == -1: return False else: return True
def main(): global_options = {} logging.basicConfig(level=logging.DEBUG, format='%(asctime)-15s %(message)s') logging.getLogger('kubernetes').setLevel(logging.WARNING) try: k8s_config.load_kube_config() _, context = k8s_config.list_kube_config_contexts() region = context['context']['cluster'] domain = 'cc.{}.cloud.sap'.format(region) global_options['own_namespace'] = 'kube-system' #context['context']['namespace'] except IOError: from os import environ environ['KUBERNETES_SERVICE_HOST'] = 'kubernetes.default' k8s_config.load_incluster_config() with open('/var/run/secrets/kubernetes.io/serviceaccount/namespace', 'r') as f: global_options['own_namespace'] = f.read() with open('/etc/resolv.conf', 'r') as f: for l in f: if re.match('^search\s+', l): _, domain = l.rsplit(' ', 1) domain = domain.strip() configurator = Configurator(domain, global_options) configurator.poll_config() discovery = DnsDiscovery(domain, configurator.global_options) discovery.register(re.compile(six.b('\Avc-[a-z]+-?\d+\Z')), configurator) while True: discovery.discover() configurator.poll() sleep(10)
def CreatePopupMenu(self): global context_names, active_index contexts, active_context = config.list_kube_config_contexts() if not contexts: print("Cannot find any context in kube-config file.") sys.exit(-1) context_names = [context['name'] for context in contexts] active_index = context_names.index(active_context['name']) menu = wx.Menu() index = 0 for name in context_names: item = menu.AppendRadioItem(index, name) menu.Bind(wx.EVT_MENU, partial(self.OnContextSelection, index), item) index = index + 1 menu.AppendSeparator() aboutm = wx.MenuItem(menu, wx.ID_ABOUT, 'About..') menu.Bind(wx.EVT_MENU, self.OnAbout, id=aboutm.GetId()) menu.Append(aboutm) menu.AppendSeparator() quitm = wx.MenuItem(menu, wx.ID_EXIT, 'Quit') menu.Bind(wx.EVT_MENU, self.OnQuit, id=quitm.GetId()) menu.Append(quitm) menu.Check(active_index, True) return menu
def __init__(self, k8s_config, storage_config): logger.debug("Creating Kubernetes Job client") self.name = 'k8s' self.k8s_config = k8s_config self.storage_config = storage_config self.kubecfg_path = k8s_config.get('kubecfg_path') self.user_agent = k8s_config['user_agent'] try: config.load_kube_config(config_file=self.kubecfg_path) contexts = config.list_kube_config_contexts(config_file=self.kubecfg_path) current_context = contexts[1].get('context') self.namespace = current_context.get('namespace', 'default') self.cluster = current_context.get('cluster') self.k8s_config['namespace'] = self.namespace self.k8s_config['cluster'] = self.cluster self.is_incluster = False except Exception: logger.debug('Loading incluster config') config.load_incluster_config() self.namespace = self.k8s_config.get('namespace', 'default') self.cluster = self.k8s_config.get('cluster', 'default') self.is_incluster = True logger.debug("Set namespace to {}".format(self.namespace)) logger.debug("Set cluster to {}".format(self.cluster)) self.batch_api = client.BatchV1Api() self.core_api = client.CoreV1Api() self.jobs = [] # list to store executed jobs (job_keys) msg = COMPUTE_CLI_MSG.format('Kubernetes Job') logger.info("{} - Namespace: {}".format(msg, self.namespace))
def main(): contexts, active_context = config.list_kube_config_contexts() if not contexts: print("Cannot find any context in kube-config file.") return contexts = [context['name'] for context in contexts] active_index = contexts.index(active_context['name']) cluster1, first_index = pick(contexts, title="Pick the first context", default_index=active_index) cluster2, _ = pick(contexts, title="Pick the second context", default_index=first_index) client1 = client.CoreV1Api( api_client=config.new_client_from_config(context=cluster1)) client2 = client.CoreV1Api( api_client=config.new_client_from_config(context=cluster2)) print("\nList of pods on %s:" % cluster1) for i in client1.list_pod_for_all_namespaces().items: print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name)) print("\n\nList of pods on %s:" % cluster2) for i in client2.list_pod_for_all_namespaces().items: print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))
def main(): args = _build_arg_parser().parse_args(sys.argv[1:]) global_options = {'dry_run': str(args.dry_run)} logging.basicConfig(level=logging.DEBUG, format='%(asctime)-15s %(process)d %(levelname)s %(message)s') logging.getLogger('kubernetes').setLevel(logging.WARNING) try: k8s_config.load_kube_config() _, context = k8s_config.list_kube_config_contexts() region = context['context']['cluster'] domain = 'cc.{}.cloud.sap'.format(region) global_options['own_namespace'] = 'kube-system' #context['context']['namespace'] except IOError: from os import environ environ['KUBERNETES_SERVICE_HOST'] = 'kubernetes.default' k8s_config.load_incluster_config() with open('/var/run/secrets/kubernetes.io/serviceaccount/namespace', 'r') as f: global_options['own_namespace'] = f.read() with open('/etc/resolv.conf', 'r') as f: for l in f: if re.match('^search\s+', l): _, domain = l.rsplit(' ', 1) domain = domain.strip() configurator = Configurator(domain, global_options) configurator.poll_config() discovery = DnsDiscovery(domain, configurator.global_options) discovery.register(re.compile(six.b('\Avc-[a-z]+-\d+\Z')), configurator) while True: discovery.discover() configurator.poll() sleep(10)
def update_available_clusters() -> Dict: """ Updates the cluster to context mapping variable with all contexts and corresponding clusters that the user is authorized to access. Usage: Call to refresh the list of accessible clusters. :return: (Dict) new cluster to context mapping """ contexts, _ = config.list_kube_config_contexts() new_cc_mapping = {} for context in contexts: context_name = context["name"] cluster_name = context["context"]["cluster"] # check to see if request times out (0.2 sec) liveness_test = multiprocessing.Process(target=test_liveness, name="list namespaces", args=(context_name, )) liveness_test.start() time.sleep(1) # check if thread is still running (timeout) or if # 404 unauthorized exception was thrown if liveness_test.is_alive() or test_liveness(context_name) == False: liveness_test.terminate() liveness_test.join() continue else: new_cc_mapping[cluster_name] = context_name global cc_mapping cc_mapping = new_cc_mapping return new_cc_mapping
def get_current_user() -> str: """ Returns name of a user from a current kubectl context :return: name of a user In case of any problems - it raises an exception """ return config.list_kube_config_contexts()[1]["context"]["user"]
def ingress(context=None): try: form = MyForm.FormK8sContexts() valus = [] if context: config.load_kube_config(config_file, context) else: _, active_contexts = config.list_kube_config_contexts(config_file) context = active_contexts['name'] v1 = client.ExtensionsV1beta1Api() keys = tables = ('name', 'request', 'domain', 'service_name', 'service_port') ret = v1.list_ingress_for_all_namespaces() for i in ret.items: try: for rule in i.spec.rules: valus.append([ i.metadata.name, 'http', rule.host, rule.http.paths[0].backend.service_name, rule.http.paths[0].backend.service_port ]) except Exception as e: logging.error(e) except Exception as e: logging.error(e) return render_template('k8s-resource.html', valus=valus, tables=tables, keys=keys, form=form, context=context, resource='Ingress')
def get_current_namespace() -> str: """ Returns namespace from a current kubectl context :return: namespace In case of any problems - it raises an exception """ return config.list_kube_config_contexts()[1]["context"]["namespace"]
def __init__(self, code_engine_config, storage_config): logger.debug("Creating Code Engine client") self.log_active = logger.getEffectiveLevel() != logging.WARNING self.name = 'code_engine' self.code_engine_config = code_engine_config self.is_lithops_worker = is_lithops_worker() self.storage_config = storage_config self.internal_storage = InternalStorage(storage_config) config.load_kube_config( config_file=code_engine_config.get('kubectl_config')) self.capi = client.CustomObjectsApi() self.user_agent = code_engine_config['user_agent'] contexts = config.list_kube_config_contexts( config_file=code_engine_config.get('kubectl_config')) current_context = contexts[1].get('context') self.user = current_context.get('user') self.user_key = self.user self.package = 'lithops_v{}_{}'.format(__version__, self.user_key) self.namespace = current_context.get('namespace', 'default') self.cluster = current_context.get('cluster') log_msg = ('Lithops v{} init for Code Engine - Namespace: {} - ' 'Cluster: {} - User {}'.format(__version__, self.namespace, self.cluster, self.user)) if not self.log_active: print(log_msg) self.job_def_ids = set() logger.info("Code Engine client created successfully")
def pick_cluster(self, cluster_name: str = None): """ Pick the cluster you will scale the workload """ try: # Load the context in kube-config file contexts, active_context = config.list_kube_config_contexts(config_file=self.kube_config) config.load_incluster_config() self.logger.debug(f"contexts: {contexts}, active_context: {active_context}") if not contexts: self.logger.error("Cannot locate any context in kube-config file") return contexts = [context['name'] for context in contexts] self.logger.debug(f"context list: {contexts}") if cluster_name is None: cluster_name = active_context['name'] target_cluster_index = next((i for i, j in enumerate(contexts) if cluster_name in j), None) if target_cluster_index is None: self.logger.error(f"Cannot find {cluster_name} in {contexts}") return picked_cluster = contexts[target_cluster_index] self.logger.debug(f"Picked cluster: {picked_cluster}") return { 'core_v1': client.CoreV1Api( api_client=config.new_client_from_config(config_file=self.kube_config, context=picked_cluster) ), 'apps_v1': client.AppsV1Api( api_client=config.new_client_from_config(config_file=self.kube_config, context=picked_cluster) ), } except Exception as e: self.logger.error(f"Can't pick a cluster: {e}") raise e
def cli(shodan_api_key, shodan_alert_name, run_outside_cluster, interval): """ kube-shodan registers all public IPs of a Kubernetes cluster to monitor.shodan.io. All options are also available as environment variables with the prefix KUBE_SHODAN, e.g. --shodan-api-key is KUBE_SHODAN_SHODAN_API_KEY. """ if not shodan_alert_name: cluster_name = config.list_kube_config_contexts( )[1]['context']['cluster'] shodan_alert_name = 'kube-shodan-{}'.format(cluster_name) LOGGER.info('No alert name specified, using default "%s".', shodan_alert_name) if run_outside_cluster: config.load_kube_config() else: config.load_incluster_config() kube_api = client.CoreV1Api() shodan_api = shodan.Shodan(shodan_api_key) while True: reconcile(kube_api, shodan_api, shodan_alert_name) sleep(interval)
def main(): contexts, active_context = config.list_kube_config_contexts() if not contexts: print("Cannot find any context in kube-config file.") return contexts = [context['name'] for context in contexts] active_index = contexts.index(active_context['name']) cluster1, first_index = pick(contexts, title="Pick the first context", default_index=active_index) cluster2, _ = pick(contexts, title="Pick the second context", default_index=first_index) client1 = client.CoreV1Api(api_client=config.new_client_from_config( context=cluster1)) client2 = client.CoreV1Api(api_client=config.new_client_from_config( context=cluster2)) print("\nList of pods on %s:" % cluster1) for i in client1.list_pod_for_all_namespaces().items: print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name)) print("\n\nList of pods on %s:" % cluster2) for i in client2.list_pod_for_all_namespaces().items: print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))
def __init__(self, code_engine_config, storage_config): logger.debug("Creating IBM Code Engine client") self.name = 'code_engine' self.code_engine_config = code_engine_config self.storage_config = storage_config self.kubecfg = code_engine_config.get('kubectl_config') self.user_agent = code_engine_config['user_agent'] config.load_kube_config(config_file=self.kubecfg) self.capi = client.CustomObjectsApi() self.coreV1Api = client.CoreV1Api() contexts = config.list_kube_config_contexts(config_file=self.kubecfg) current_context = contexts[1].get('context') self.namespace = current_context.get('namespace', 'default') logger.debug("Set namespace to {}".format(self.namespace)) self.cluster = current_context.get('cluster') logger.debug("Set cluster to {}".format(self.cluster)) try: self.region = self.cluster.split('//')[1].split('.')[1] except Exception: self.region = self.cluster.replace('http://', '').replace('https://', '') self.job_def_ids = set() msg = COMPUTE_CLI_MSG.format('IBM Code Engine') logger.info("{} - Region: {}".format(msg, self.region))
def try_to_read_namespace_from_context(): try: contexts, active_context = kube_config.list_kube_config_contexts() if contexts and "namespace" in active_context["context"]: return active_context["context"]["namespace"] except: # noqa: E722 pass return None
def init_k8s_config(): """初始化k8s客户端配置 :return: """ config.load_kube_config(KUBE_CONFIG) global _cluster_name _cluster_name = config.list_kube_config_contexts()[1]["context"]["cluster"]
def get_k8s_clients(kubeconfig: str) -> List[K8sClient]: contexts, _ = config.list_kube_config_contexts(kubeconfig) if not contexts: raise KubernetesContextNotFound("No context found in kubeconfig.") clients = list() for context in contexts: clients.append(K8sClient(context["name"])) return clients
def __init__(self, code_engine_config, internal_storage): logger.debug("Creating IBM Code Engine client") self.name = 'code_engine' self.type = 'batch' self.code_engine_config = code_engine_config self.internal_storage = internal_storage self.kubecfg_path = code_engine_config.get('kubecfg_path') self.user_agent = code_engine_config['user_agent'] self.iam_api_key = code_engine_config.get('iam_api_key', None) self.namespace = code_engine_config.get('namespace', None) self.region = code_engine_config.get('region', None) self.ibm_token_manager = None self.is_lithops_worker = is_lithops_worker() if self.namespace and self.region: self.cluster = ce_config.CLUSTER_URL.format(self.region) if self.iam_api_key and not self.is_lithops_worker: self._get_iam_token() else: try: config.load_kube_config(config_file=self.kubecfg_path) logger.debug("Loading kubecfg file") contexts = config.list_kube_config_contexts( config_file=self.kubecfg_path) current_context = contexts[1].get('context') self.namespace = current_context.get('namespace') self.cluster = current_context.get('cluster') if self.iam_api_key: self._get_iam_token() except Exception: logger.debug('Loading incluster kubecfg') config.load_incluster_config() self.code_engine_config['namespace'] = self.namespace self.code_engine_config['cluster'] = self.cluster logger.debug("Set namespace to {}".format(self.namespace)) logger.debug("Set cluster to {}".format(self.cluster)) self.custom_api = client.CustomObjectsApi() self.core_api = client.CoreV1Api() try: self.region = self.cluster.split('//')[1].split('.')[1] except Exception: self.region = self.cluster.replace('http://', '').replace('https://', '') self.jobs = [] # list to store executed jobs (job_keys) msg = COMPUTE_CLI_MSG.format('IBM Code Engine') logger.info("{} - Region: {}".format(msg, self.region))
def is_minikube(): """ Checks if the current context is minikube. This is needed for checks in the test code. """ try: contexts, active_context = config.list_kube_config_contexts() return active_context['context']['cluster'] == 'minikube' except Exception: return False
def context_get(): """Obtain active K8S context. Returns: object: Active context. """ _, active_context = config.list_kube_config_contexts() logging.debug(pretty_print(json.dumps(active_context))) return active_context
def get_context_from_user(): contexts, active_context = config.list_kube_config_contexts() if not contexts: error("Cannot find any context in kubeconfig file.") contexts = [context['name'] for context in contexts] active_index = contexts.index(active_context['name']) option, _ = pick.pick(contexts, title="Please select the context you wish to set as default", indicator='◇', default_index=active_index) return option
def deployment(context=None): try: form = MyForm.FormK8sContexts() valus = defaultdict() if context: config.load_kube_config(config_file, context) else: _, active_contexts = config.list_kube_config_contexts(config_file) context = active_contexts['name'] v1 = client.AppsV1Api() tables = ('name', 'namespace', 'replicas', 'strategy', 'containers', 'cpu_limit', 'mem_limit', 'available') keys = ('namespace', 'replicas', 'strategy', 'containers', 'cpu_limit', 'mem_limit', 'available') ret = v1.list_deployment_for_all_namespaces() for i in ret.items: try: containers = [] for info in i.spec.template.spec.containers: containers.append(info.name) if not i.status.unavailable_replicas: available = 100 else: available = int((float(i.spec.replicas) - float(i.status.unavailable_replicas)) / float(i.spec.replicas) * 100) cpu_limit = 'None' mem_limit = 'None' limits = i.spec.template.spec.containers[0].resources.limits if limits: if 'cpu' in limits: cpu_limit = limits['cpu'] if 'memory' in limits: mem_limit = limits['memory'] valus[i.metadata.name] = { 'namespace': i.metadata.namespace, 'replicas': i.spec.replicas, 'strategy': i.spec.strategy.type, 'containers': containers, 'cpu_limit': cpu_limit, 'mem_limit': mem_limit, 'available': available } except Exception as e: logging.error(e) except Exception as e: logging.error(e) return render_template('k8s-resource.html', valus=valus, tables=tables, keys=keys, form=form, context=context, resource='Deployment')
def main(): contexts, active_context = config.list_kube_config_contexts() if not contexts: print("Cannot find any context in kube-config file.") return contexts = [context['name'] for context in contexts] active_index = contexts.index(active_context['name']) option, _ = pick(contexts, title="Pick the context to load", default_index=active_index) # Configs can be set in Configuration class directly or using helper # utility config.load_kube_config(context=option) print("Active host is %s" % configuration.host) v1 = client.CoreV1Api() print("Listing pods with their IPs:") ret = v1.list_pod_for_all_namespaces(watch=False) for item in ret.items: print( "%s\t%s\t%s" % (item.status.pod_ip, item.metadata.namespace, item.metadata.name))
def online_install(ctx): click.echo('Installing WALKOFF to Kubernetes cluster with Internet access.') try: config_dir = os.environ.get('KUBECONFIG', os.path.join(os.path.expanduser("~"), ".kube", "config")) config_dir = click.prompt("Enter location of kubernetes config", default=config_dir) contexts, current = config.list_kube_config_contexts(config_file=config_dir) contexts = [context["name"] for context in contexts] current = current["name"] context = click.prompt("Available contexts: {}\nEnter context to install WALKOFF to".format(contexts), default=current) config.load_kube_config(config_file=config_dir, context=context) k8s_api = k8s_client.CoreV1Api() k8s_custom_api = k8s_client.CustomObjectsApi() except IOError as e: print("Could not open config: {}".format(e)) return namespaces = k8s_api.list_namespace() namespaces = [ns.metadata.name for ns in namespaces.items] namespace = click.prompt("Available namespaces: {}\nEnter namespace to install WALKOFF in".format(namespaces), default="default") if namespace not in namespaces: if click.confirm("{} does not exist - do you want to create it now?"): new_namespace = k8s_client.V1Namespace(metadata={'name': namespace}) try: k8s_api.create_namespace(new_namespace) except k8s_client.rest.ApiException as e: click.echo("Error creating namespace:\n{}".format(str(e))) click.echo('You should use the uninstall command to rollback changes made by this installer.') return tiller_namespace = click.prompt('Enter the namespace your Tiller service resides in', default='kube-system') click.echo("Generating ZMQ certificates for WALKOFF.") if subprocess.call(['python', 'scripts/generate_certificates.py']) != 0: click.echo("Error generating ZMQ certificates.") return click.echo("Adding ZMQ certificates to Kubernetes secrets.") kubectl_command(['create', 'secret', 'generic', 'walkoff-zmq-private-keys', '--from-file=server.key_secret=./.certificates/private_keys/server.key_secret', '--from-file=client.key_secret=./.certificates/private_keys/client.key_secret'], namespace) kubectl_command(['create', 'secret', 'generic', 'walkoff-zmq-public-keys', '--from-file=server.key=./.certificates/public_keys/server.key', '--from-file=client.key=./.certificates/public_keys/client.key'], namespace) existing_secrets = k8s_api.list_namespaced_secret(namespace) redis_secret_name = None redis_hostname = None if click.confirm('Is there an existing Redis instance WALKOFF should use?'): redis_hostname = click.prompt('Enter the Redis hostname (if it is not in the same Kubernetes namespace ' 'as WALKOFF, enter a fully qualified domain name)') if click.confirm("Is the Redis password already stored in a Kubernetes secret?"): redis_secret_name = click.prompt('Available secrets: {}\nEnter the name of the secret the Redis password ' 'is stored in with a key of "redis-password" (leave blank for none): ', default="") if redis_secret_name not in existing_secrets: redis_secret_name = None click.echo('No secret with that name in this namespace. Creating a new secret to store password.') if not redis_secret_name: redis_secret_name = "walkoff-redis-secret" new_pass = click.prompt('Enter a password for the Redis instance', hide_input=True, confirmation_prompt=True, default='walkoff') redis_secret_obj = k8s_client.V1Secret(metadata={'name': redis_secret_name}, data={'redis-password': b64encode(new_pass.encode('utf-8')) .decode('utf-8')}) try: k8s_api.create_namespaced_secret(namespace, redis_secret_obj) except k8s_client.rest.ApiException as e: click.echo("Error creating secret:\n{}".format(str(e))) click.echo('You should use the uninstall command to rollback changes made by this installer.') return with open("k8s_manifests/setupfiles/redis-helm-values.yaml", 'r+') as f: try: y = yaml.load(f) y['existingSecret'] = redis_secret_name f.seek(0) f.truncate() yaml.dump(y, f, default_flow_style=False) except yaml.YAMLError as e: click.echo("Error reading k8s_manifests/setupfiles/redis-helm-values.yaml") click.echo('You should use the uninstall command to rollback changes made by this installer.') return if not redis_hostname: redis_hostname = 'walkoff-redis' helm_command(['install', 'stable/redis', '--name', redis_hostname, '--values', 'k8s_manifests/setupfiles/redis-helm-values.yaml', '--set', 'existingSecret={}'.format(redis_secret_name)], tiller_namespace) execution_secret_name = None execution_db_hostname = None if click.confirm('Do you have an existing PostgreSQL database to store WALKOFF execution data in?'): execution_db_hostname = click.prompt('Enter the database hostname (if it is not in the same Kubernetes ' 'namespace as WALKOFF, enter a fully qualified domain name)') execution_db_username = click.prompt('Enter a username that is able to create/read/write/update databases') if click.confirm("Is the PostgreSQL password already stored in a Kubernetes secret?"): execution_secret_name = click.prompt('Available secrets: {}\nEnter the name of the secret the PostgreSQL ' 'password is stored in with a key of "postgres-password" ' '(leave blank for none): ', default="") if execution_secret_name not in existing_secrets: execution_secret_name = None click.echo('No secret with that name in this namespace. Creating a new secret to store password.') if not execution_secret_name: execution_secret_name = "walkoff-postgres-execution-secret" execution_db_username = click.prompt('Enter a username to create', default='walkoff') execution_db_password = click.prompt('Enter a password for the PostgreSQL instance', hide_input=True, confirmation_prompt=True, default='walkoff') execution_secret_obj = k8s_client.V1Secret(metadata={'name': execution_secret_name}, data={ 'postgres-password': b64encode(execution_db_password.encode('utf-8')).decode('utf-8')}) try: k8s_api.create_namespaced_secret(namespace, execution_secret_obj) except k8s_client.rest.ApiException as e: click.echo("Error creating secret:\n{}".format(str(e))) click.echo('You should use the uninstall command to rollback changes made by this installer.') return with open("k8s_manifests/setupfiles/execution-postgres-helm-values.yaml", 'r+') as f: try: y = yaml.load(f) y['postgresqlUsername'] = execution_db_username y['postgresqlPassword'] = execution_db_password f.seek(0) f.truncate() yaml.dump(y, f, default_flow_style=False) except yaml.YAMLError as e: click.echo("Error reading k8s_manifests/setupfiles/execution-postgres-helm-values.yaml") click.echo('You should use the uninstall command to rollback changes made by this installer.') return if not execution_db_hostname: helm_command(['install', 'stable/postgresql', '--name', 'execution-db', '--values', 'k8s_manifests/setupfiles/execution-postgres-helm-values.yaml'], tiller_namespace) execution_db_hostname = 'execution-db-postgresql' walkoff_db_secret_name = None walkoff_db_hostname = None if click.confirm('Do you have an existing PostgreSQL database to store WALKOFF application data in? ' '(This can be the same or different as the previous)'): walkoff_db_hostname = click.prompt('Enter the database hostname (if it is not in the same Kubernetes namespace ' 'as WALKOFF, enter a fully qualified domain name)') walkoff_db_username = click.prompt('Enter a username that is able to create/read/write/update databases') if click.confirm("Is the PostgreSQL password already stored in a Kubernetes secret?"): walkoff_db_secret_name = click.prompt('Available secrets: {}\nEnter the name of the secret the PostgreSQL ' 'password is stored in with a key of "postgres-password" ' '(leave blank for none): ', default="") if walkoff_db_secret_name not in existing_secrets: walkoff_db_secret_name = None click.echo('No secret with that name in this namespace. Creating a new secret to store password.') if not walkoff_db_secret_name: walkoff_db_secret_name = "walkoff-postgres-secret" walkoff_db_username = click.prompt('Enter a username to create', default='walkoff') walkoff_db_password = click.prompt('Enter a password for the PostgreSQL instance', hide_input=True, confirmation_prompt=True, default='walkoff') walkoff_db_secret_obj = k8s_client.V1Secret(metadata={'name': walkoff_db_secret_name}, data={ 'postgres-password': b64encode(walkoff_db_password.encode('utf-8')).decode('utf-8')}) try: k8s_api.create_namespaced_secret(namespace, walkoff_db_secret_obj) except k8s_client.rest.ApiException as e: click.echo("Error creating secret:\n{}".format(str(e))) click.echo('You should use the uninstall command to rollback changes made by this installer.') return with open("k8s_manifests/setupfiles/walkoff-postgres-helm-values.yaml", 'r+') as f: try: y = yaml.load(f) y['postgresqlUsername'] = walkoff_db_username y['postgresqlPassword'] = walkoff_db_password f.seek(0) f.truncate() yaml.dump(y, f, default_flow_style=False) except yaml.YAMLError as e: click.echo("Error reading k8s_manifests/setupfiles/walkoff-postgres-helm-values.yaml") click.echo('You should use the uninstall command to rollback changes made by this installer.') return if not walkoff_db_hostname: helm_command(['install', 'stable/postgresql', '--name', 'walkoff-db', '--values', 'k8s_manifests/setupfiles/walkoff-postgres-helm-values.yaml'], tiller_namespace) walkoff_db_hostname = 'walkoff-db-postgresql' walkoff_ca_key_pair = None if click.confirm('Do you have an existing CA signing key pair stored in Kubernetes secrets?'): walkoff_ca_key_pair = click.prompt( 'Available secrets: {}\nEnter the name of the secret the key pair is stored in (leave blank for none): ', default="") if walkoff_ca_key_pair not in existing_secrets: walkoff_ca_key_pair = None click.echo('No secret with that name in this namespace. Creating a new secret to store keypair.') if not walkoff_ca_key_pair: crt = None key = None if click.confirm('Do you have existing CA signing key pair files?'): while not crt: crt = click.prompt('Enter the path to a cert (.crt) file: ') try: with open(crt, 'rb') as f: crt = b64encode(f.read()).decode('ascii') click.echo('Successfully loaded cert') except IOError as e: click.echo('Error reading {}: {}'.format(crt, e)) crt = None while not key: key = click.prompt('Enter the path to the matching private key (.key) file: ') try: with open(key, 'rb') as f: key = b64encode(f.read()).decode('ascii') click.echo('Successfully loaded key.') except IOError as e: click.echo('Error reading {}: {}'.format(key, e)) key = None if not all((crt, key)): private_key = rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) public_key = private_key.public_key() builder = x509.CertificateBuilder() builder = builder.subject_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, u'walkoff') ])) builder = builder.issuer_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, u'walkoff'), ])) builder = builder.not_valid_before(datetime.datetime.today() - datetime.timedelta(days=1)) builder = builder.not_valid_after(datetime.datetime.today() + datetime.timedelta(days=3650)) builder = builder.serial_number(int(uuid.uuid4())) builder = builder.public_key(public_key) builder = builder.add_extension(x509.SubjectKeyIdentifier.from_public_key(public_key), critical=False) builder = builder.add_extension(x509.AuthorityKeyIdentifier.from_issuer_public_key(public_key), critical=False) builder = builder.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True) certificate = builder.sign( private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend() ) with open("ca.key", "wb") as f: byte_cert = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() ) key = b64encode(byte_cert).decode('ascii') f.write(byte_cert) with open("ca.crt", "wb") as f: byte_key = certificate.public_bytes( encoding=serialization.Encoding.PEM, ) crt = b64encode(byte_key).decode('ascii') f.write(byte_key) tls_secret = k8s_client.V1Secret(metadata={'name': 'walkoff-ca-key-pair'}, data={'tls.crt': crt, 'tls.key': key}, type='kubernetes.io/tls') try: k8s_api.create_namespaced_secret('default', tls_secret) except k8s_client.rest.ApiException as e: click.echo("Error creating secret:\n{}".format(str(e))) click.echo('You should use the uninstall command to rollback changes made by this installer.') return walkoff_ca_key_pair = 'walkoff-ca-key-pair' helm_command(['install', 'stable/cert-manager', '--name', 'walkoff-cert-manager'], tiller_namespace) with open("k8s_manifests/setupfiles/cert-issuer.yaml", 'r+') as f: try: y = yaml.load(f) y['spec']['ca']['secretName'] = walkoff_ca_key_pair f.seek(0) f.truncate() yaml.dump(y, f, default_flow_style=False) except yaml.YAMLError as e: click.echo("Error reading k8s_manifests/setupfiles/cert-issuer.yaml") click.echo('You should use the uninstall command to rollback changes made by this installer.') return kubectl_command(['apply', '-f', 'k8s_manifests/setupfiles/cert-issuer.yaml'], namespace) kubectl_command(['apply', '-f', 'k8s_manifests/setupfiles/cert.yaml'], namespace) with open("k8s_manifests/setupfiles/walkoff-values.yaml", 'r+') as f: try: y = yaml.load(f) y['namespace'] = namespace y['resources']['redis']['service_name'] = redis_hostname y['resources']['redis']['secret_name'] = redis_secret_name y['resources']['execution_db']['service_name'] = execution_db_hostname y['resources']['execution_db']['secret_name'] = execution_secret_name y['resources']['execution_db']['username'] = execution_db_username y['resources']['walkoff_db']['service_name'] = walkoff_db_hostname y['resources']['walkoff_db']['secret_name'] = walkoff_db_secret_name y['resources']['walkoff_db']['username'] = walkoff_db_username f.seek(0) f.truncate() yaml.dump(y, f, default_flow_style=False) except yaml.YAMLError as e: click.echo("Error reading k8s_manifests/setupfiles/walkoff-values.yaml") click.echo('You should use the uninstall command to rollback changes made by this installer.') return helm_command(['install', 'k8s_manifests/helm_charts/walkoff', '--name', 'walkoff-deployment'], tiller_namespace)