def init(): """Return top level command handler.""" cell_formatter = cli.make_formatter('cell') @click.group(name='cell') @click.option('--api-service-principal', required=False, envvar='TREADMILL_API_SERVICE_PRINCIPAL', callback=cli.handle_context_opt, help='API service principal for SPNEGO auth (default HTTP)', expose_value=False) def cell_grp(): """List & display Treadmill cells.""" @cell_grp.command(name='list') @cli.handle_exceptions(restclient.CLI_REST_EXCEPTIONS) def _list(): """List the configured cells.""" restapi = context.GLOBAL.admin_api() cli.out(cell_formatter(restclient.get(restapi, '/cell/').json())) @cell_grp.command() @click.argument('name') @cli.handle_exceptions(restclient.CLI_REST_EXCEPTIONS) def configure(name): """Display the details of a cell.""" restapi = context.GLOBAL.admin_api() cli.out( cell_formatter(restclient.get(restapi, '/cell/%s' % name).json())) del _list del configure return cell_grp
def init(): """Manage IAM policies.""" formatter = cli.make_formatter('aws_policy') @click.group() def policy(): """Manage IAM policies.""" pass @policy.command() @click.option('--version-id', help='Version ID of policy') @click.argument('policy', type=IamPolicy()) @cli.admin.ON_EXCEPTIONS def configure(policy, version_id): """configure/get IAM policy.""" iam_conn = awscontext.GLOBAL.iam response = iam_conn.get_policy(PolicyArn=policy) if not version_id: version_id = response['Policy']['DefaultVersionId'] version = iam_conn.get_policy_version(PolicyArn=policy, VersionId=version_id) response['Policy']['PolicyVersion'] = version['PolicyVersion'] cli.out(formatter(response['Policy'])) del configure return policy
def init(): """AWS subnet CLI group""" formatter = cli.make_formatter('aws_subnet') @click.group() def subnet(): """Manage subnet configuration""" pass @subnet.command(name='list') @cli.admin.ON_EXCEPTIONS def _list(): """List subnets""" ec2_conn = awscontext.GLOBAL.ec2 subnets = ec2client.list_subnets(ec2_conn) cli.out(formatter(subnets)) @subnet.command() @click.argument('subnet', required=False, type=aws_cli.SUBNET) @cli.admin.ON_EXCEPTIONS @treadmill_aws.cli.admin.aws.ON_AWS_EXCEPTIONS def configure(subnet): """Configure subnet""" ec2_conn = awscontext.GLOBAL.ec2 if not subnet: subnet = {'ids': [metadata.subnet_id()]} subnet_obj = ec2client.get_subnet(ec2_conn, **subnet) cli.out(formatter(subnet_obj)) del _list del configure return subnet
def init(): """AWS security group CLI group""" formatter = cli.make_formatter('aws_secgroup') @click.group() def secgroup(): """Manage security group configuration.""" pass @secgroup.command(name='list') @cli.admin.ON_EXCEPTIONS def _list(): """List security groups""" ec2_conn = awscontext.GLOBAL.ec2 secgroups = ec2client.list_secgroups(ec2_conn) cli.out(formatter(secgroups)) @secgroup.command() @click.argument('secgrp', required=False, type=aws_cli.SECGROUP) @cli.admin.ON_EXCEPTIONS @treadmill_aws.cli.admin.aws.ON_AWS_EXCEPTIONS def configure(secgrp): """Configure security group.""" ec2_conn = awscontext.GLOBAL.ec2 if not secgrp: secgrp = {'ids': [metadata.secgroup_id()]} grp_obj = ec2client.get_secgroup(ec2_conn, **secgrp) cli.out(formatter(grp_obj)) del _list del configure return secgroup
def endpoints(): """Show endpoints and their status.""" zkclient = context.GLOBAL.zk.conn discovery_state = zkclient.get_children(z.DISCOVERY_STATE) state = collections.defaultdict(dict) for hostname in discovery_state: state[hostname] = zkutils.get(zkclient, z.path.discovery_state(hostname)) discovery = zkclient.get_children(z.DISCOVERY) all_endpoints = [] for hostname in discovery: endpoints = [] for entry in zkutils.get(zkclient, z.path.discovery(hostname)): app, endpoint, proto, port = entry.split(':') port = int(port) endpoint_state = state[hostname].get(port) hostport = '{}:{}'.format(hostname, port) endpoints.append( (app, proto, endpoint, hostport, endpoint_state)) all_endpoints.append(endpoints) merged = heapq.merge(*all_endpoints) formatter = cli.make_formatter('endpoint') cli.out( formatter([{ 'name': name, 'endpoint': endpoint, 'proto': proto, 'hostport': hostport, 'state': state, } for name, proto, endpoint, hostport, state in merged]))
def ldap_tenant_group(parent): """Configures tenant CLI group""" formatter = cli.make_formatter(cli.TenantPrettyFormatter) @parent.group() def tenant(): """Manage tenants""" pass @tenant.command() @click.option('-s', '--system', help='System eon id', type=int, multiple=True, default=[]) @click.argument('tenant') @cli.admin.ON_EXCEPTIONS def configure(system, tenant): """Create, get or modify tenant configuration""" admin_tnt = admin.Tenant(context.GLOBAL.ldap.conn) attrs = {} if system: attrs['systems'] = system if attrs: try: admin_tnt.create(tenant, attrs) except ldap3.LDAPEntryAlreadyExistsResult: admin_tnt.update(tenant, attrs) try: tenant_obj = admin_tnt.get(tenant) tenant_obj['allocations'] = admin_tnt.allocations(tenant) cli.out(formatter(tenant_obj)) except ldap3.LDAPNoSuchObjectResult: click.echo('Tenant does not exist: %s' % tenant, err=True) @tenant.command(name='list') @cli.admin.ON_EXCEPTIONS def _list(): """List configured tenants""" admin_tnt = admin.Tenant(context.GLOBAL.ldap.conn) cli.out(formatter(admin_tnt.list({}))) @tenant.command() @click.argument('tenant') @cli.admin.ON_EXCEPTIONS def delete(tenant): """Delete a tenant""" admin_tnt = admin.Tenant(context.GLOBAL.ldap.conn) try: admin_tnt.delete(tenant) except ldap3.LDAPNoSuchObjectResult: click.echo('Tenant does not exist: %s' % tenant, err=True) del delete del _list del configure
def schema_group(parent): """Schema CLI group.""" formatter = cli.make_formatter(cli.LdapSchemaPrettyFormatter) @parent.command() @click.option('-l', '--load', help='Schema (YAML) file.', type=click.File('rb')) @cli.admin.ON_EXCEPTIONS def schema(load): """View or update LDAP schema.""" if load: schema = yaml.load(load.read()) context.GLOBAL.ldap.conn.update_schema(schema) schema_obj = context.GLOBAL.ldap.conn.schema() def dict_to_namevalue_list(item): """Translates name: value dict into [{name: $name, ...}]""" return [ pair[1].update({'name': pair[0]}) or pair[1] for pair in sorted(item.iteritems()) ] schema_obj['attributeTypes'] = dict_to_namevalue_list( schema_obj['attributeTypes']) schema_obj['objectClasses'] = dict_to_namevalue_list( schema_obj['objectClasses']) cli.out(formatter(schema_obj)) del schema
def put(path, payload): """REST PUT request.""" request = yaml.load(payload.read()) response = restclient.put(ctx['api'], path, payload=request) formatter = cli.make_formatter(None) cli.out(formatter(response.json()))
def explain_group(parent): """Scheduler explain CLI group.""" queue_formatter = cli.make_formatter('alloc-queue') placement_formatter = cli.make_formatter('placement') @parent.group() def explain(): """Explain scheduler internals. """ @explain.command() @click.option('--instance', help='Application instance') @click.option('--partition', help='Cell partition', default='_default') @cli.admin.ON_EXCEPTIONS def queue(instance, partition): """Explain the application queue""" cell_master = make_readonly_master() frame = reports.explain_queue(cell_master.cell, partition, pattern=instance) _print(frame, queue_formatter) @explain.command() @click.argument('instance') @click.option('--mode', help='Tree traversal method', type=click.Choice(reports.WALKS.keys()), default='default') @cli.admin.ON_EXCEPTIONS def placement(instance, mode): """Explain application placement""" cell_master = make_readonly_master() if instance not in cell_master.cell.apps: cli.bad_exit('Instance not found.') app = cell_master.cell.apps[instance] if app.server: cli.bad_exit('Instace already placed on %s' % app.server) frame = reports.explain_placement(cell_master.cell, app, mode) _print(frame, placement_formatter) del queue del placement
def put(path, payload): """REST PUT request.""" with io.open(payload, 'rb') as fd: request = yaml.load(stream=fd) response = restclient.put(ctx['api'], path, payload=request) formatter = cli.make_formatter(None) cli.out(formatter(response.json()))
def post(path, payload): """REST POST request.""" with open(payload, 'rb') as fd: request = yaml.load(fd.read()) response = restclient.post(ctx['api'], path, payload=request) formatter = cli.make_formatter(None) cli.out(formatter(response.json()))
def init(): """Configures HAProxy servers""" formatter = cli.make_formatter('haproxy') @click.group() def haproxy(): """Manage HAProxies""" pass @haproxy.command() @click.option('-c', '--cell', help='Treadmll cell') @click.argument('haproxy') @cli.admin.ON_EXCEPTIONS def configure(cell, haproxy): """Create, get or modify HAProxy servers""" admin_haproxy = admin.HAProxy(context.GLOBAL.ldap.conn) attrs = {} if cell: attrs['cell'] = cell if attrs: try: admin_haproxy.create(haproxy, attrs) except ldap_exceptions.LDAPEntryAlreadyExistsResult: admin_haproxy.update(haproxy, attrs) try: cli.out(formatter(admin_haproxy.get(haproxy))) except ldap_exceptions.LDAPNoSuchObjectResult: click.echo('HAProxy does not exist: {}'.format(haproxy), err=True) @haproxy.command(name='list') @cli.admin.ON_EXCEPTIONS def _list(): """List partitions""" admin_haproxy = admin.HAProxy(context.GLOBAL.ldap.conn) haproxies = admin_haproxy.list({}) cli.out(formatter(haproxies)) @haproxy.command() @click.argument('haproxy') @cli.admin.ON_EXCEPTIONS def delete(haproxy): """Delete a partition""" admin_haproxy = admin.HAProxy(context.GLOBAL.ldap.conn) try: admin_haproxy.delete(haproxy) except ldap_exceptions.LDAPNoSuchObjectResult: click.echo('HAProxy does not exist: {}'.format(haproxy), err=True) del configure del _list del delete return haproxy
def init(): """Configures app CLI group""" # Disable too many branches. # # pylint: disable=R0912 formatter = cli.make_formatter('app') @click.group() def app(): """Manage applications""" pass @app.command() @click.option('-m', '--manifest', help='Application manifest.', type=click.Path(exists=True, readable=True)) @click.argument('app') @cli.admin.ON_EXCEPTIONS def configure(app, manifest): """Create, get or modify an app configuration""" admin_app = admin.Application(context.GLOBAL.ldap.conn) if manifest: with io.open(manifest, 'rb') as fd: data = yaml.load(stream=fd) try: admin_app.create(app, data) except ldap_exceptions.LDAPEntryAlreadyExistsResult: admin_app.replace(app, data) try: cli.out(formatter(admin_app.get(app))) except ldap_exceptions.LDAPNoSuchObjectResult: click.echo('App does not exist: %s' % app, err=True) @app.command(name='list') @cli.admin.ON_EXCEPTIONS def _list(): """List configured applicaitons""" admin_app = admin.Application(context.GLOBAL.ldap.conn) cli.out(formatter(admin_app.list({}))) @app.command() @click.argument('app') @cli.admin.ON_EXCEPTIONS def delete(app): """Delete applicaiton""" admin_app = admin.Application(context.GLOBAL.ldap.conn) try: admin_app.delete(app) except ldap_exceptions.LDAPNoSuchObjectResult: click.echo('App does not exist: %s' % app, err=True) del delete del _list del configure return app
def app_group(parent): """Configures app CLI group.""" # Disable too many branches. # # pylint: disable=R0912 formatter = cli.make_formatter(cli.AppPrettyFormatter) @parent.group() def app(): """Manage treadmill applications.""" pass @app.command() @click.option('-m', '--manifest', help='Application manifest.', type=click.File('rb')) @click.argument('app') @cli.admin.ON_EXCEPTIONS def configure(app, manifest): """Get or modify app configuration.""" admin_app = admin.Application(context.GLOBAL.ldap.conn) if manifest: data = yaml.load(manifest.read()) try: admin_app.create(app, data) except ldap3.LDAPEntryAlreadyExistsResult: admin_app.replace(app, data) try: cli.out(formatter(admin_app.get(app))) except ldap3.LDAPNoSuchObjectResult: click.echo('App does not exist: %s' % app, err=True) @app.command(name='list') @cli.admin.ON_EXCEPTIONS def _list(): """List configured applicaitons.""" admin_app = admin.Application(context.GLOBAL.ldap.conn) cli.out(formatter(admin_app.list({}))) @app.command() @click.argument('app') @cli.admin.ON_EXCEPTIONS def delete(app): """Delete applicaiton.""" admin_app = admin.Application(context.GLOBAL.ldap.conn) try: admin_app.delete(app) except ldap3.LDAPNoSuchObjectResult: click.echo('App does not exist: %s' % app, err=True) del delete del _list del configure
def _iam_grp(parent): """Configure IAM command group.""" formatter = cli.make_formatter('aws_user') @parent.group() def iam(): """Manage IAM user configuration""" pass @iam.command(name='configure') @click.option('--policy-doc', required=False, help='IAM Role policy document.') @click.option('--create', is_flag=True, default=False, help='Create IAM user/role.') @click.argument('username', required=True, callback=aws_cli.sanitize_user_name) @cli.admin.ON_EXCEPTIONS def configure_iam(policy_doc, create, username): """Create IAM user. """ iam_conn = awscontext.GLOBAL.iam try: user = usermanager.get_iam_user(iam_conn=iam_conn, user_name=username) except exc.NotFoundError: if not create: raise if create or policy_doc: policy = _default_policy() if policy_doc: with io.open(policy_doc) as f: policy = json.loads(f.read()) user = usermanager.create_iam_user( iam_conn=iam_conn, user_name=username, policy=policy ) cli.out(formatter(user)) @iam.command(name='delete') @click.argument('username') @cli.admin.ON_EXCEPTIONS def delete_iam(username): """Delete IAM user.""" ipa_client = awscontext.GLOBAL.ipaclient iam_conn = awscontext.GLOBAL.iam usermanager.delete_iam_user(iam_conn=iam_conn, user_name=username) del configure_iam del delete_iam
def init(): """Return top level command handler.""" server_formatter = cli.make_formatter('server') ctx = {} @click.group(name='server') @click.option('--api-service-principal', required=False, envvar='TREADMILL_API_SERVICE_PRINCIPAL', callback=cli.handle_context_opt, help='API service principal for SPNEGO auth (default HTTP)', expose_value=False) @click.option('--api', required=False, help='API url to use.', envvar='TREADMILL_ADMINAPI') def server_grp(api): """List & display Treadmill servers.""" if api: ctx['api'] = api @server_grp.command(name='list') @click.option('--cell', required=True, envvar='TREADMILL_CELL', help='Filter servers by cell') @click.option('--partition', required=False, help='Filter servers by partition') @cli.handle_exceptions(restclient.CLI_REST_EXCEPTIONS) def _list(cell, partition): """List all servers.""" query = {'cell': cell} if partition is not None: query['partition'] = partition url = '/server/?{}'.format(urllib_parse.urlencode(query)) restapi = context.GLOBAL.admin_api(ctx.get('api')) cli.out(server_formatter(restclient.get(restapi, url).json())) @server_grp.command() @click.argument('name') @cli.handle_exceptions(restclient.CLI_REST_EXCEPTIONS) def configure(name): """Display details of the server.""" restapi = context.GLOBAL.admin_api(ctx.get('api')) cli.out( server_formatter( restclient.get(restapi, '/server/{}'.format(name)).json())) del _list del configure return server_grp
def bucket_group(parent): """Bucket CLI group""" formatter = cli.make_formatter('bucket') @parent.group() def bucket(): """Manage Treadmill bucket configuration. """ @bucket.command() @click.option('-f', '--features', help='Bucket features, - to reset', multiple=True, default=[]) @click.argument('bucket') @cli.admin.ON_EXCEPTIONS def configure(features, bucket): """Create, get or modify bucket configuration""" features = cli.combine(features) if features: # This is special case - reset features to empty. if features == ['-']: features = None masterapi.update_bucket_features(context.GLOBAL.zk.conn, bucket, features) data = masterapi.get_bucket(context.GLOBAL.zk.conn, bucket) data['name'] = bucket cli.out(formatter(data)) @bucket.command() @cli.admin.ON_EXCEPTIONS def list(): # pylint: disable=W0622 """Delete bucket""" buckets = [] for name in masterapi.cell_buckets(context.GLOBAL.zk.conn): bucket = masterapi.get_bucket(context.GLOBAL.zk.conn, name) bucket['name'] = name buckets.append(bucket) cli.out(formatter(buckets)) @bucket.command() @click.argument('bucket') @cli.admin.ON_EXCEPTIONS def delete(bucket): """Delete bucket""" masterapi.delete_bucket(context.GLOBAL.zk.conn, bucket) del configure del list del delete
def _display_tenant(restapi, tenant): """Display allocations for the given tenant.""" tenant_url = '/tenant/{}'.format(tenant) alloc_url = '/allocation/{}'.format(tenant) tenant_obj = restclient.get(restapi, tenant_url).json() allocations_obj = restclient.get(restapi, alloc_url).json() tenant_obj['allocations'] = allocations_obj tenant_formatter = cli.make_formatter('tenant') cli.out(tenant_formatter(tenant_obj))
def init(): """EC2 spot CLI group""" formatter = cli.make_formatter('aws_spot') @click.group() def spot(): """Manage spot configuration""" pass @spot.command(name='list') @treadmill_aws.cli.admin.aws.ON_AWS_EXCEPTIONS def _list(): """List spot instance requestss""" ec2_conn = awscontext.GLOBAL.ec2 sirs = [vars(o) for o in ec2client.list_spot_requests(ec2_conn)] if not sirs: print("No spot request was found") return cli.out(formatter(sirs)) @spot.command() @click.argument('sir_id') @treadmill_aws.cli.admin.aws.ON_AWS_EXCEPTIONS def delete(sir_id): """Delete spot instance request""" ipa_client = awscontext.GLOBAL.ipaclient ec2_conn = awscontext.GLOBAL.ec2 for item in ec2client.list_spot_requests(ec2_conn): if item.id == sir_id: sir = item break else: print("SIR %s was not found" % sir_id) return instances = ec2_conn.describe_instances(InstanceIds=[sir.instance_id]) hostname = jmespath.search( "Reservations[].Instances[].[Tags[?Key=='Name'].Value][][]", instances)[0] print("Terminating", hostname) hostmanager.delete_hosts(ipa_client=ipa_client, ec2_conn=ec2_conn, hostnames=[hostname]) print("Cancelling", sir.id) ec2_conn.cancel_spot_instance_requests(SpotInstanceRequestIds=[sir.id]) del _list del delete return spot
def monitor_group(parent): """App monitor CLI group""" formatter = cli.make_formatter('app-monitor') @parent.group() def monitor(): """Manage app monitors configuration""" pass @monitor.command() @click.option('-n', '--count', type=int) @click.argument('app') @cli.admin.ON_EXCEPTIONS def configure(app, count): """Create, get or modify an app monitor configuration""" zkclient = context.GLOBAL.zk.conn if count is not None: data = masterapi.update_appmonitor(zkclient, app, count) else: data = masterapi.get_appmonitor(zkclient, app) cli.out(formatter(data)) @monitor.command() @click.argument('app') @cli.admin.ON_EXCEPTIONS def delete(app): """Deletes app monitor""" masterapi.delete_appmonitor(context.GLOBAL.zk.conn, app) @monitor.command(name='list') def _list(): """List all configured monitors""" zkclient = context.GLOBAL.zk.conn suspended_monitors = masterapi.get_suspended_appmonitors(zkclient) monitors = [ masterapi.get_appmonitor( zkclient, app, suspended_monitors=suspended_monitors, ) for app in masterapi.appmonitors(zkclient) ] cli.out(formatter(monitors)) del delete del configure del _list
def init(): """Admin Cell CLI module""" formatter = cli.make_formatter('aws_cell_data') @click.command(name='configure-data') @click.option('--docker-registries', help='Docker registries', type=cli.LIST) @click.option('--image', help='Default AMI image.') # TODO: support XXXG as input. @click.option('--disk-size', help='Default image disk size.') @click.option('--size', help='Default instance size.') @click.option('--hostgroups', help='Nodes hostgroups.', type=cli.LIST) # TODO: should be list. @click.option('--secgroup', help='Nodes security group.') @click.option('--realm', help='Nodes kerberos realm.') @click.option('--instance-profile', help='Instance profile.') @click.option('--subnets', help='List of subnets.', type=cli.LIST) @click.option('--s3-registry-region', help='S3 registry bucket region.') @click.option('--s3-registry-bucket', help='S3 registry bucket name.') def configure_data_cmd(docker_registries, image, disk_size, size, hostgroups, secgroup, realm, instance_profile, subnets, s3_registry_region, s3_registry_bucket): """Configure cell data.""" admin_cell = admin.Cell(context.GLOBAL.ldap.conn) cell = admin_cell.get(context.GLOBAL.cell) data = cell.get('data', {}) modified = _set(data, 'docker_registries', docker_registries) modified = _set(data, 'image', image) or modified modified = _set(data, 'disk_size', disk_size) or modified modified = _set(data, 'size', size) or modified modified = _set(data, 'hostgroups', hostgroups) or modified modified = _set(data, 'secgroup', secgroup) or modified modified = _set(data, 'realm', realm) or modified modified = _set(data, 'instance_profile', instance_profile) or modified modified = _set(data, 'subnets', subnets) or modified modified = _set(data, 's3_registry_region', s3_registry_region) or modified modified = _set(data, 's3_registry_bucket', s3_registry_bucket) or modified if modified: admin_cell.update(context.GLOBAL.cell, {'data': data}) cli.out(formatter(data)) return configure_data_cmd
def get(rec_dn, cls, attrs): """List all defined DNs.""" if not attrs: attrs = [] try: # TODO: it is porbably possible to derive class from DN. klass = getattr(admin, cls) attrs.extend([elem[0] for elem in klass.schema()]) except AttributeError: cli.bad_exit('Invalid admin type: %s', cls) return entry = context.GLOBAL.ldap.conn.get(rec_dn, '(objectClass=*)', list(set(attrs))) formatter = cli.make_formatter(None) cli.out(formatter(entry))
def init(): # pylint: disable=R0912 """Configures application monitor""" formatter = cli.make_formatter('aws_image') ctx = {} @click.group() @click.option('--api', help='API url to use.', metavar='URL', envvar='TREADMILL_RESTAPI') def image_group(api): """Manage Treadmill app monitor configuration""" ctx['api'] = api @image_group.command() @click.argument('name') @_ON_EXCEPTIONS def configure(name): """Configure AWS image.""" restapi = context.GLOBAL.cell_api(ctx['api']) url = _REST_PATH + name image_entry = restclient.get(restapi, url) cli.out(formatter(image_entry.json())) @image_group.command(name='list') @_ON_EXCEPTIONS def _list(): """List AWS images.""" restapi = context.GLOBAL.cell_api(ctx['api']) url = _REST_PATH response = restclient.get(restapi, url) cli.out(formatter(response.json())) @image_group.command() @click.argument('name', nargs=1, required=True) @_ON_EXCEPTIONS def delete(name): """Delete AWS image""" restapi = context.GLOBAL.cell_api(ctx['api']) url = _REST_PATH + name restclient.delete(restapi, url) del delete del _list del configure return image_group
def init(): """Schema CLI group""" formatter = cli.make_formatter('ldap-schema') @click.command(name='schema') @click.option('-u', '--update', help='Refresh LDAP schema.', is_flag=True, default=False) @cli.admin.ON_EXCEPTIONS def _schema(update): """View or update LDAP schema""" if update: context.GLOBAL.ldap.user = '******' utf8_reader = codecs.getreader('utf8') schema_rsrc = utf8_reader( pkg_resources.resource_stream('treadmill', '/etc/ldap/schema.yml')) schema = yaml.load(stream=schema_rsrc) context.GLOBAL.admin.conn.update_schema(schema) schema_obj = context.GLOBAL.admin.conn.schema() def dict_to_namevalue_list(item): """Translates name: value dict into [{name: $name, ...}] """ result = [] for pair in sorted(six.iteritems(item)): entry = pair[1].copy() entry.update({'name': pair[0]}) result.append(entry) return result schema_obj['attributeTypes'] = dict_to_namevalue_list( schema_obj['attributeTypes']) schema_obj['objectClasses'] = dict_to_namevalue_list( schema_obj['objectClasses']) cli.out(formatter(schema_obj)) return _schema
def command(*args, **kwargs): """Constructs a command handler.""" try: if 'rsrc' in kwargs: kwargs['rsrc'] = yaml.load(kwargs['rsrc'].read()) formatter = cli.make_formatter(None) cli.out(formatter(func(*args, **kwargs))) except jsonschema.exceptions.ValidationError as input_err: click.echo(input_err, err=True) except jsonschema.exceptions.RefResolutionError as res_error: click.echo(res_error, err=True) except authz.AuthorizationError as auth_err: click.echo('Not authorized.', err=True) click.echo(auth_err, err=True) except TypeError as type_err: click.echo(type_err, err=True)
def _display_tenant(tenant): """Display allocations for the given tenant.""" tenant_obj = _check_tenant_exists(tenant) admin_tenant = context.GLOBAL.admin.tenant() allocs = admin_tenant.allocations(tenant) cell_allocs = admin_tenant.reservations(tenant) name2alloc = {alloc['_id']: defaultdict(list, alloc) for alloc in allocs} for alloc in cell_allocs: name = '/'.join(alloc['_id'].split('/')[:2]) name2alloc[name]['reservations'].append(alloc) allocations_obj = list(name2alloc.values()) tenant_obj['allocations'] = allocations_obj tenant_formatter = cli.make_formatter('tenant') cli.out(tenant_formatter(tenant_obj))
def monitor_group(parent): """App monitor CLI group.""" formatter = cli.make_formatter(cli.AppMonitorPrettyFormatter()) @parent.group() def monitor(): """Manage app monitors configuration.""" pass @monitor.command() @click.option('-n', '--count', type=int) @click.argument('app') @cli.admin.ON_EXCEPTIONS def configure(app, count): """Configures app monitor.""" zkclient = context.GLOBAL.zk.conn if count is not None: master.update_appmonitor(zkclient, app, count) cli.out(formatter(master.get_appmonitor(zkclient, app))) @monitor.command() @click.argument('app') @cli.admin.ON_EXCEPTIONS def delete(app): """Deletes app monitor.""" master.delete_appmonitor(context.GLOBAL.zk.conn, app) @monitor.command(name='list') def _list(): """List all configured monitors.""" zkclient = context.GLOBAL.zk.conn monitors = [ master.get_appmonitor(zkclient, app) for app in master.appmonitors(zkclient) ] cli.out(formatter(monitors)) del delete del configure del _list
def identity_group_group(parent): """App monitor CLI group""" formatter = cli.make_formatter('identity-group') @parent.group(name='identity-group') def identity_group(): """Manage identity group configuration. """ @identity_group.command() @click.option('-n', '--count', type=int) @click.argument('group') @cli.admin.ON_EXCEPTIONS def configure(group, count): """Create, get or modify identity group configuration""" zkclient = context.GLOBAL.zk.conn if count is not None: masterapi.update_identity_group(zkclient, group, count) cli.out(formatter(masterapi.get_identity_group(zkclient, group))) @identity_group.command() @click.argument('group') @cli.admin.ON_EXCEPTIONS def delete(group): """Deletes identity group""" masterapi.delete_identity_group(context.GLOBAL.zk.conn, group) @identity_group.command(name='list') def _list(): """List all configured identity groups""" zkclient = context.GLOBAL.zk.conn groups = [ masterapi.get_identity_group(zkclient, group) for group in masterapi.identity_groups(zkclient) ] cli.out(formatter(groups)) del delete del configure del _list
def schema_group(parent): """Schema CLI group""" formatter = cli.make_formatter(cli.LdapSchemaPrettyFormatter) @parent.command() @click.option('-u', '--update', help='Refresh LDAP schema.', is_flag=True, default=False) @cli.admin.ON_EXCEPTIONS def schema(update): """View or update LDAP schema""" if update: context.GLOBAL.ldap.user = '******' schema_rsrc = pkg_resources.resource_stream( 'treadmill', '/etc/ldap/schema.yml') schema = yaml.load(schema_rsrc.read()) context.GLOBAL.ldap.conn.update_schema(schema) schema_obj = context.GLOBAL.ldap.conn.schema() def dict_to_namevalue_list(item): """Translates name: value dict into [{name: $name, ...}]""" return [ pair[1].update({'name': pair[0]}) or pair[1] for pair in sorted(item.items()) ] schema_obj['attributeTypes'] = dict_to_namevalue_list( schema_obj['attributeTypes']) schema_obj['objectClasses'] = dict_to_namevalue_list( schema_obj['objectClasses']) cli.out(formatter(schema_obj)) del schema
def init(): """Return top level command handler.""" cell_formatter = cli.make_formatter('cell') ctx = {} @click.group(name='cell') @click.option('--api', required=False, help='API url to use.', envvar='TREADMILL_RESTAPI') def cell_grp(api): """List & display Treadmill cells.""" if api: ctx['api'] = api @cell_grp.command(name='list') @cli.handle_exceptions(restclient.CLI_REST_EXCEPTIONS) def _list(): """List the configured cells.""" restapi = context.GLOBAL.admin_api(ctx.get('api')) cli.out(cell_formatter(restclient.get(restapi, '/cell/').json())) @cell_grp.command() @click.argument('name') @cli.handle_exceptions(restclient.CLI_REST_EXCEPTIONS) def configure(name): """Display the details of a cell.""" restapi = context.GLOBAL.admin_api(ctx.get('api')) cli.out( cell_formatter(restclient.get(restapi, '/cell/%s' % name).json())) del _list del configure return cell_grp