def _resource_completion(self, short_mode=True): results = [] headers = ('NAME', 'SERVER', 'CLUSTER', 'CONTEXT') yaml = YAML() results.append(headers) if os.path.exists(settings.OMC_KUBE_CONFIG_DIR): resources = os.listdir(settings.OMC_KUBE_CONFIG_DIR) for one_resource in resources: try: with open( os.path.join(settings.OMC_KUBE_CONFIG_DIR, one_resource, 'config')) as f: content = yaml.load(f) one_item = (one_resource, ObjectUtils.get_node( content, "clusters[0].cluster.server"), ObjectUtils.get_node( content, "clusters[0].name"), ObjectUtils.get_node( content, "current-context")) results.append(one_item) except Exception as e: logger.error(e, exc_info=True) return CompletionContent(Formatter.format_completions(results))
def _save(self): 'save configuration in file cache to be restored' resource_name = self._get_one_resource_value() namespace = self.client.get_namespace( self._get_kube_api_resource_type(), resource_name) kube_instance = self._get_one_resource_value("kube") if not kube_instance: kube_instance = 'local' cache_folder = os.path.join(settings.OMC_KUBE_CACHE_DIR, kube_instance, namespace, self._get_kube_resource_type()) result = self._read_namespaced_resource(resource_name, namespace, _preload_content=False) stream = StringIO() the_result = json.loads(result.data.decode('UTF-8')) ObjectUtils.delete_node(the_result, 'metadata.creationTimestamp') ObjectUtils.delete_node(the_result, 'metadata.resourceVersion') yaml = YAML() yaml.dump(the_result, stream) content = stream.getvalue() make_directory(cache_folder) with open(os.path.join(cache_folder, resource_name + '.yaml'), 'w') as f: f.write(content)
def event(self): 'show event on the resource' # https://kubernetes.docker.internal:6443/api/v1/namespaces/default/events?fieldSelector= # involvedObject.uid=4bb31f4d-99f1-4acc-a024-8e2484573733, # involvedObject.name=itom-xruntime-rabbitmq-6464654786-vnjxz, # involvedObject.namespace=default resource = self._get_one_resource_value() namespace = self.client.get_namespace( self._get_kube_api_resource_type(), resource) result = self._read_namespaced_resource(resource, namespace) uid = ObjectUtils.get_node(result, 'metadata.uid') name = ObjectUtils.get_node(result, 'metadata.name') the_selector = { "involvedObject.uid": uid, "involvedObject.namespace": namespace, "involvedObject.name": name, } console.log( self.client.list_namespaced_event( namespace, field_selector=self._build_field_selector(the_selector)))
def _get_config_key_completion(self): resource = self._get_one_resource_value() namespace = self.client.get_namespace( self._get_kube_api_resource_type(), resource) result = self._read_namespaced_resource(resource, namespace) prompts = [] ObjectUtils.get_nodes(result.to_dict(), prompts) return CompletionContent(self._get_completion(prompts))
def _resource_completion(self, short_mode=True): ret = self._list_resource_for_all_namespaces( timeout_seconds=settings.COMPETION_TIMEOUT) results = Formatter.format_completions([( ObjectUtils.get_node(one, 'metadata.name'), ObjectUtils.get_node(one, 'metadata.namespace'), self._get_ready_status(one), time_util.calculate_age( time_util.fromisotime( ObjectUtils.get_node(one, 'metadata.creationTimestamp'))), ) for one in ret.get('items')]) return CompletionContent(results)
def _resource_completion(self, short_mode=True): results = [] kube_resource_type = self._get_kube_resource_type() completion_file_name = pkg_resources.resource_filename( 'omc_kube.assets', '_%(kube_resource_type)s_completion.json' % locals()) prompts = [] # get_all_dict_Keys(result.to_dict(), prompts) with open(completion_file_name) as f: result = json.load(f) ObjectUtils.get_nodes(result, prompts) results.extend(self._get_completion(prompts)) return CompletionContent(results)
def _get_cert_dir(self, config_file): import yaml with open(config_file) as f: result = yaml.load(f, yaml.FullLoader) path = (ObjectUtils.get_node( result, 'clusters[0].cluster.certificate-authority')) return os.path.dirname(path)
def get(self): 'get resource by configuration key' parent_resource = self._get_one_resource_value( self._get_kube_resource_type()) namespace = self.client.get_namespace( self._get_kube_api_resource_type(), parent_resource) result = self._read_namespaced_resource(parent_resource, namespace) # config resource is the item resource = self._get_one_resource_value() if not resource: console.log(ObjectUtils.format(result)) else: console.log( ObjectUtils.format(ObjectUtils.get_node(result, resource)))
def delete(self): 'delete node by configuration key' # todo@rain: to support delete entired resource and completion cache if 'completion' in self._get_params(): resource = self._get_one_resource_value() namespace = self.client.get_namespace( self._get_kube_api_resource_type(), resource) result = self._read_namespaced_resource(resource, namespace) prompts = [] ObjectUtils.get_nodes(result.to_dict(), prompts) self._print_completion(prompts) return config_key = self._get_one_resource_value() parent_resource = self._get_one_resource_value( self._get_kube_resource_type()) namespace = self.client.get_namespace( self._get_kube_api_resource_type(), parent_resource) the_result = self._read_namespaced_resource(parent_resource, namespace, _preload_content=False) result = json.loads(the_result.data.decode('UTF-8')) params = self._get_action_params() config_value = params[0] if len(params) > 0 else None # orig_value = ObjectUtils.get_node(result, config_key) # # convert type # config_value = type(orig_value)(config_value) # set_obj_value(result, config_key, config_value) # todo: use apply instead once apply provided patch_func = getattr( self.client, 'patch_namespaced_' + self._get_kube_api_resource_type()) # patch_object = utils.build_object(config_key, config_value) patch_object = StrategicMergePatch.get_instance( ).gen_strategic_merge_patch(result, config_key.split('.'), config_value, 'delete', []) new_result = patch_func(parent_resource, namespace, patch_object) console.log(new_result)
def set(self): 'update restore by configuration key' # https://github.com/kubernetes/kubernetes/blob/cea1d4e20b4a7886d8ff65f34c6d4f95efcb4742/staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/patch.go # implement Strategic merge patch myself # https://stackoverflow.com/questions/36307950/kubernetes-api-call-equivalent-to-kubectl-apply if 'completion' in self._get_params(): resource = self._get_one_resource_value() namespace = self.client.get_namespace( self._get_kube_api_resource_type(), resource) result = self._read_namespaced_resource(resource, namespace) prompts = [] ObjectUtils.get_nodes(result.to_dict(), prompts) self._print_completion(prompts) return config_key = self._get_one_resource_value() parent_resource = self._get_one_resource_value( self._get_kube_resource_type()) namespace = self.client.get_namespace( self._get_kube_api_resource_type(), parent_resource) result = self._read_namespaced_resource(parent_resource, namespace) params = self._get_action_params() config_value = params[0] orig_value = ObjectUtils.get_node(result, config_key) # convert type config_value = type(orig_value)(config_value) ObjectUtils.set_node(result, config_key, config_value) # todo: use apply instead once apply provided patch_func = getattr( self.client, 'patch_namespaced_' + self._get_kube_api_resource_type()) # patch_object = utils.build_object(config_key, config_value) patch_object = StrategicMergePatch.get_instance( ).gen_strategic_merge_patch(result, config_key.split('.'), config_value, 'set', []) new_result = patch_func(parent_resource, namespace, patch_object) console.log(new_result)
def _resource_completion(self, short_mode=True): results = [] pod_name = self._get_one_resource_value('pod') namespace = self.client.get_namespace('pod', pod_name) result = self.client.read_namespaced_pod(pod_name, namespace) # for one_container in result.spec.containers: results.extend( self._get_completion( [(one.get('name'), one.get('image')) for one in ObjectUtils.get_node(result, 'spec.containers')], False)) return CompletionContent(results)
def _get_ready_status(self, one): replicas = 0 if ObjectUtils.get_node( one, 'status.replicas') is None else ObjectUtils.get_node( one, 'status.replicas') unavailable_replicas = 0 if ObjectUtils.get_node( one, 'status.unavailableReplicas') is None else ObjectUtils.get_node( one, 'status.unavailableReplicas') updated_replicas = 0 if ObjectUtils.get_node( one, 'status.updatedReplicas') is None else ObjectUtils.get_node( one, 'status.updatedReplicas') available_replicas = replicas - unavailable_replicas return str(available_replicas) + '/' + str(replicas)
def _before_sub_resource(self): try: if self._have_resource_value(): resource_value = self._get_one_resource_value() client = KubernetesClient( os.path.join(settings.OMC_KUBE_CONFIG_DIR, resource_value, 'config')) else: client = KubernetesClient() self.context['common'] = {'client': client} except Exception as e: # some action no need to create load config, get config action e.g. raise Exception('invalid kubenetes config') if __name__ == '__main__': client = KubernetesClient() ret = client.list_service_for_all_namespaces(watch=False) yaml = YAML() with open('/Users/luganlin/.omc/config/kube/cd150/config') as f: content = yaml.load(f) print(ObjectUtils.get_node(content, "clusters[0].cluster.server")) # print(client.read_namespaced_pod("postgres-svc-5685d4bc7-l6j4m", 'default')) # print(client.read_namespaced_pod_template("postgres-svc-5685d4bc7-l6j4m", 'default')) # print(client.read_namspaced_event("postgres-svc-5685d4bc7-l6j4m", 'default')) console.log(ret) # for i in ret.items: # print("%s\t%s\t%s" % (i.status.pod_ip, i.metadata.namespace, i.metadata.name))
ssl_dir = self._get_cert_dir( os.path.join(the_kube_config_dir, 'config')) # download ssl files console.log("downloading ssl certificate to %s" % the_kube_config_dir) certificate_download_cmd = 'scp -r %s:%s %s' % (k8s_resource, ssl_dir, the_kube_config_dir) self.run_cmd(certificate_download_cmd) kube_config_file = os.path.join(the_kube_config_dir, 'config') file_utils.inplace_replace(kube_config_file, ssl_dir, os.path.join(the_kube_config_dir, 'ssl')) def _get_cert_dir(self, config_file): import yaml with open(config_file) as f: result = yaml.load(f, yaml.FullLoader) path = (ObjectUtils.get_node( result, 'clusters[0].cluster.certificate-authority')) return os.path.dirname(path) if __name__ == '__main__': import yaml with open('/Users/luganlin/.omc/config/kube/cd219/config') as f: result = yaml.load(f, yaml.FullLoader) path = (ObjectUtils.get_node( result, 'clusters[0].cluster.certificate-authority')) console.log(os.path.dirname(path)) console.log(result)
def get_namespace(self, resource_type: str, resource_name: str): list_namespaces = getattr(self, "list_%s_for_all_namespaces" % resource_type) all_namespaces = list_namespaces() for one in all_namespaces.get('items'): if ObjectUtils.get_node(one, 'metadata.name') == resource_name: return ObjectUtils.get_node(one, 'metadata.namespace')
def gen_strategic_merge_patch(self, origin, key_array, value, action, path): ''' 'spec.template.spec.containers[0].env[1]', {'name': 'name1', 'value': 'value1'} ''' keys = key_array.copy() one_key = keys.pop(0) current_path = path.copy() # raw path, with array index current_path.append(one_key) the_key, is_array, index = self.parse_one_key(one_key) current_key_path = '.'.join( [*path, the_key]) # with old array index, without current index, for get object value current_flatten_path = self.flatten_key('.'.join([*path, the_key])) # no array index, only for api spec usage if not is_array: if not keys: # no key any more if action == 'set': return {the_key: value} elif action == 'delete': return {the_key: None} else: return {the_key: self.gen_strategic_merge_patch(origin, keys, value, action, current_path)} else: the_value = value if current_flatten_path in self.api_spec: # for array, we have stratgic merge rule current_value = ObjectUtils.get_node(origin, current_key_path) merge_key = self.api_spec[current_flatten_path]['x-kubernetes-patch-merge-key'] patch_strategy = self.api_spec[current_flatten_path]['x-kubernetes-patch-strategy'] results = {} ''' "$setElementOrder/containers": [ { "name": "idm" } ], ''' if keys: # has children results['$setElementOrder/%s' % the_key] = [{merge_key: one.get(merge_key)} for one in current_value] results[the_key] = [ { merge_key: current_value[index].get(merge_key), **self.gen_strategic_merge_patch(origin, keys, the_value, action, current_path) } ] if not keys: results['$setElementOrder/%s' % the_key] = [{merge_key: one.get(merge_key)} for one in current_value] if action == 'set': one_item = [] if isinstance(value, dict): value = {**value, merge_key: current_value[index].get(merge_key)} one_item.insert(index, value) results[the_key] = one_item elif action == 'delete': one_item = [] # one_item.insert(index, value) one_item.append({"$patch": 'delete', **value}) results[the_key] = one_item return results else: # if no merge rule, merge normally current_value = ObjectUtils.get_node(origin, current_key_path) current_value = current_value if current_value else [] current_value.insert(index, the_value)