def json(self): 'get configuration by json format' 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) console.log(json.dumps(result, default=dateconverter, indent=4))
def _run(self): ssh_host = self._get_one_resource_value() cmd = 'ssh %s' % ssh_host if '--dry-run' in self._get_resource_values(): console.log(cmd) else: self.run_cmd(cmd)
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 cmd(path): FORMAT = "[%(filename)s:%(lineno)s - %(funcName)s ] %(message)s" logging.basicConfig(format=FORMAT) logger = logging.getLogger(__name__) argv = path.split('/') resource_type = argv[0] console.log('################## resource type:' + resource_type + '##################') try: mod = __import__(".".join(['omc', 'resources', resource_type, resource_type]), fromlist=[resource_type.capitalize()]) clazz = getattr(mod, resource_type.capitalize()) context = { 'all': ['web', *argv], 'index': 1 } data = clazz(context)._exec() response = app.response_class( response=json.dumps(data), mimetype='application/json' ) return response except Exception as inst: traceback.print_exc() logger.error(inst)
def sync(self, k8s_resource, kube_config_dir): the_kube_config_dir = os.path.join(kube_config_dir, k8s_resource) if os.path.exists(the_kube_config_dir): shutil.rmtree(the_kube_config_dir) file_utils.make_directory(the_kube_config_dir) # download config file console.log("downloading config file to %s" % the_kube_config_dir) config_download_cmd = 'scp %s:/root/.kube/config %s' % ( k8s_resource, the_kube_config_dir) self.run_cmd(config_download_cmd) 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 tunnel(self): """ setup ssh tunnel to from local port to remote host:port using <ssh host> as a bridge """ tunnel_template = "ssh -nNT -L %(local_port)s:%(remote_host)s:%(remote_port)s %(bridge)s" bridge = self._get_one_resource_value() parser = argparse.ArgumentParser() parser.add_argument('--local-port', nargs='?', help='local port') parser.add_argument('--remote-port', nargs='?', help='remote port') parser.add_argument('--remote-host', nargs='?', help='remote host') parser.add_argument('--dry-run', action='store_true') args = parser.parse_args(self._get_action_params()) cmd = tunnel_template % { 'bridge': bridge, 'local_port': args.local_port, 'remote_port': args.remote_port, 'remote_host': args.remote_host, } if args.dry_run: console.log(cmd) else: self.run_cmd(cmd)
def yaml(self): 'get configuration in yaml format' 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) stream = StringIO() yaml = YAML() yaml.dump(result, stream) console.log(stream.getvalue())
def run_cmd(self, cmd, cwd=None, env=None, block=True, capture_output=False, verbose=True, *args, **kwargs): the_env = {} the_env.update(os.environ) if env is not None: the_env.update(env) try: cwd = cwd if cwd is None else cwd.replace("\\", "/") if verbose: console.log("cmd: %s, cwd: %s" % (cmd, cwd)) if block: if capture_output: # capture output result = subprocess.run(cmd, cwd=cwd, shell=True, check=True, env=the_env, capture_output=True, *args, **kwargs) return result else: # to output result = subprocess.run(cmd, cwd=cwd, shell=True, check=True, env=the_env, capture_output=False, *args, **kwargs) return result else: result = subprocess.Popen(cmd, cwd=cwd, shell=True, env=the_env, *args, **kwargs) return result except Exception as e: raise e
def list(self): 'display one or more resources' resource_name = self._get_one_resource_value() namespace = 'all' if not resource_name else self.client.get_namespace( self._get_kube_api_resource_type(), resource_name) # ret = self._list_resource_for_all_namespaces() # console.log(ret) result = self.client.get(self._get_kube_resource_type(), resource_name, namespace) console.log(result)
def describe(self): 'Show details of a specific resource or group of resources' resource_name = self._get_one_resource_value() namespace = 'all' if resource_name: namespace = self.client.get_namespace( self._get_kube_api_resource_type(), resource_name) console.log( self.client.describe(self._get_kube_resource_type(), resource_name, namespace))
def upload(self, parser): """ upload file or folder to remote host with scp """ ssh_host = self._get_one_resource_value() args = parser.parse_args(self._get_action_params()) cmd = "scp %s %s %s:%s" % ('-r' if args.recursive else '', args.local, ssh_host, args.remote) if args.dry_run: console.log(cmd) else: self.run_cmd(cmd)
def exec(self, parser): """ execute command in remote host with ssh """ # parser = argparse.ArgumentParser() # parser.add_argument('--dry-run', action='store_true') parser.add_argument('cmd', nargs='*') args = parser.parse_args(self._get_action_params()) ssh_host = self._get_one_resource_value() cmd = "ssh %s -C '%s'" % (ssh_host, " ".join(args.cmd)) if args.dry_run: console.log(cmd) else: self.run_cmd(cmd)
def add(self, parser): """ add ssh configuration """ # parser = argparse.ArgumentParser() # parser.add_argument('--dry-run', action='store_true') args = parser.parse_args(self._get_action_params()) ssh_host = self._get_one_resource_value() self._add_ssh_host(ssh_host) cmd = "ssh-copy-id %s" % ssh_host if args.dry_run: console.log(cmd) else: self.run_cmd(cmd)
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 pause(self): resource_content = self._get_resource() namespace = self._get_namespace() config_key = 'spec.template.spec.containers[0]' config_value = json.loads( '{"command": ["/bin/sh"], "args": ["-c", "while true; do echo hello; sleep 10;done"]}' ) 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(resource_content, config_key.split('.'), config_value, 'set', []) new_result = patch_func(self._get_one_resource_value(), namespace, patch_object) console.log(new_result)
def download(self, parser): """ download file or folders from remote host to local with scp """ # parser = argparse.ArgumentParser() # parser.add_argument('-r', '--recursive', action='store_true') # parser.add_argument('--local', nargs='?', help='local files') # parser.add_argument('--remote', nargs='?', help='remote files') # parser.add_argument('--dry-run', action='store_true') ssh_host = self._get_one_resource_value() args = parser.parse_args(self._get_action_params()) cmd = "scp %s %s:%s %s" % ('-r' if args.recursive else '', ssh_host, args.remote, args.local) if args.dry_run: console.log(cmd) else: self.run_cmd(cmd)
def set(self): if 'completion' in self._get_params(): jmx = self._get_one_resource_value('jmx') bean = self._get_one_resource_value() bean = bean.replace(" ", "\\ ") short_cmd = "open %s && bean %s && info" % (jmx, bean) result = self.run_cmd(JmxTermUtils.build_command(short_cmd), capture_output=True, verbose=False) output = result.stdout.decode('utf-8').splitlines() for one_attr in (self._list_writable_resources( self._parse_info(output))): console.log(one_attr['attribute'] + ":" + one_attr['raw_data']) else: attr_name = ' '.join(self._get_params()) jmx = self._get_one_resource_value('jmx') bean = self._get_one_resource_value() bean = bean.replace(" ", "\\ ") cmd = "open %s && bean %s && set %s" % (jmx, bean, attr_name) self.run_cmd(JmxTermUtils.build_command(cmd))
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 print_completion(self, descriptions, short_mode=False): if type(descriptions) == list: for one in descriptions: if type(one) == tuple or type(one) == list: if not short_mode: console.log(":".join(one)) else: console.log(one[0]) else: console.log(one)
def _add_ssh_host(self, ssh_host): if ssh_host is None: raise Exception("hostname shouldn't be empty") ssh_config = {} hostconfig = SshService.get_instance().get(ssh_host) if hostconfig is None: for one_config, required in SshService.get_instance().config_keys: required = False result = self._prompt("Please input %s: " % one_config, required) if result: ssh_config[one_config] = result else: console.log('the host %s has been added already!' % ssh_host) return ssh_config_item = SshService.get_instance().format( ssh_host, ssh_config) console.log('ssh config:') console.log(ssh_config_item) confirmed = self._prompt( "are you sure you want add ssh host as above? (y/n)", isBool=True, required=True, default=True) if not confirmed: return connected = SshService.get_instance().test(ssh_host, ssh_config) if not connected: confirmed = self._prompt( "the connection is refused, are you sure to add the ssh host anyway? (y/n)", isBool=True, required=True, default=False) if not confirmed: return SshService.get_instance().add(ssh_host, ssh_config)
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))
def usage(): console.log('''omc resource action params ''')
def list(self): ret = self._list_resource_for_all_namespaces() console.log(ret)
def _run(self): if '--refresh' in self.context['all']: self._clean_completin_cache() console.log(self._get_resource_type_completion().get_raw_content())
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 print(self): console.log(self.configs)
content = stream.getvalue() make_directory(cache_folder) with open(os.path.join(cache_folder, resource_name + '.yaml'), 'w') as f: f.write(content) def _restore(self): 'restore configuration saved in file cache' 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()) make_directory(cache_folder) config_file = os.path.join(cache_folder, resource_name + '.yaml') if os.path.exists(config_file): self.client.apply(config_file) else: raise Exception("no config file found") if __name__ == '__main__': resource = pkg_resources.resource_filename('omc_kube.deployment', '_deployment_completion.json') console.log(resource)
def pprint(obj): console.log(json.dumps(obj, indent=2))
init_object = {first: ObjectUtils.build(others, value, [])} return init_object @staticmethod def format(obj): return json.dumps(obj, indent=2) if __name__ == '__main__': # obj = json.loads('{"a":"a", "b": [{"e": "sdfsdf"}, "d"]}') # set_obj_value(obj, 'b[0].e', 'test') # delete_obj_key(obj, 'b[0].e') # print(obj) # print(get_obj_value(obj, 'b[0].e')) # # paths = [] # get_all_dict_Keys(obj, paths) # print(paths) # # #result = build_object('a.b.c', 'value') # #print(result) # first,other = (extract_first_attr('a[1].b')) # second,other2 = extract_first_attr(other) # print(extract_first_attr(other2)) # the_object = (build_object('a[0].c.d', 'b')) # print(get_obj_value(the_object, 'a[0].c.d')) the_object = (ObjectUtils.build('a[0]', {'a': 'b'})) console.log(the_object) # print(json.loads('b'))