def run(self, args): ident = args.ident.split('-') if len(ident) != 2: raise SystemExit("Invalid message identity: %s" % args.ident) res = {"sys": 'system_message', "usr": '******'}.get(ident[0]) if res is None: raise SystemExit("Invalid message type: %s" % args.ident[0]) # NOTE: system_message does not support detail get. msg = self.api.get_by(['id'], res, ident[1]) shellish.vtmlprint('<b>Created: %s</b>' % msg['created']) shellish.vtmlprint('<b>Subject: %s</b>' % msg['title']) if 'message' in msg: output = shellish.htmlrender(msg['message']) for x in str(output).split('\n'): print( textwrap.fill(x.strip(), break_long_words=False, replace_whitespace=False, break_on_hyphens=False)) if ident[0] == 'usr': if not msg['is_read']: self.api.put(res, ident[1], {"is_read": True}) elif not msg['confirmed']: self.api.post('system_message_confirm', {"message": msg['resource_uri']})
def on_data(reader, writer): while True: data = yield from reader.readline() if not data: break log = json.loads(data.decode()) addr = writer.get_extra_info('peername')[0] ts = datetime.datetime.utcnow() log['timestamp'] = ts.isoformat() log['host_addr'] = addr if verbose: shellish.vtmlprint('<b>LOG:<b>', log) asyncio.ensure_future(relaylog(log, ts))
def run(self, args): """ Validate the args work with our worker by instantiating it here. if it checks out and doesn't exit via a `--help` or other type of SystemExit then we start the coordinator and save the arguments used just for the worker to be proxied to the worker processes. """ try: worker = setup.find_worker(args.worker_spec) except (ValueError, AttributeError, ImportError, TypeError) as e: shellish.vtmlprint("<b><red>Find Worker Error:</red> %s" % e) raise SystemExit(1) worker_cmd = setup.worker_coerce(worker)() worker_argv = ' '.join(map(shlex.quote, args.worker_args)) worker_args = vars(worker_cmd.parse_args(worker_argv)) worker_settings = {} if args.log_handler != 'off': worker_settings['logging'] = { "kind": args.log_handler, "level": args.log_level, "fmt": args.log_format, "verbose": args.verbose, "syslog_addr": args.syslog_addr, } setup.setup_logging(**worker_settings['logging']) worker_settings['event_loop'] = { "policy": args.event_loop, "debug": args.event_loop_debug } if not args.disable_diag: diag_settings = { "addr": args.diag_addr, "port": args.diag_port, } else: diag_settings = {} loop = setup.get_event_loop(**worker_settings['event_loop']) worker_restart = not args.disable_worker_restart coord = coordinator.Coordinator(args.worker_spec, worker_count=args.workers, worker_settings=worker_settings, worker_args=worker_args, worker_restart=worker_restart, diag_settings=diag_settings, loop=loop) loop.run_until_complete(coord.start()) try: loop.run_until_complete(coord.wait_stopped()) except KeyboardInterrupt: pass loop.close()
def start(self): self.app = web.Application(loop=self.loop) tpl_loader = jinja2.FileSystemLoader(self.ui_dir) env = aiohttp_jinja2.setup(self.app, loader=tpl_loader) env.globals.update({ "sorted": sorted }) self.app.router.add_route('GET', '/', self.index_redir) self.app.router.add_route('GET', '/health', self.health) self.app.router.add_route('GET', '/ui/{path}', self.tpl_handler) self.app.router.add_static('/ui/static', os.path.join(self.ui_dir, 'static')) self.handler = self.app.make_handler() listen = self.args.diag_addr, self.args.diag_port self.server = yield from self.loop.create_server(self.handler, *listen) shellish.vtmlprint('<b>Running diag web server</b>: ' '<blue><u>http://%s:%s</u></blue>' % listen, plain=self.plain_output)
def run(self, args): fw_field = 'actual_firmware__version' no_updates = True for x in self.api.get('routers', group_by=fw_field + ',product__name', count='id'): if x[fw_field] is None: continue # unsupported/dev fw avail = self.available_firmware(product_name=x['product__name'], version=x[fw_field]) name = '%s v%s (%s devices)' % (x['product__name'], x[fw_field], x['id_count']) if avail: no_updates = False shellish.vtmlprint("<b>Updates available for: %s</b>" % name) for xx in avail: print("\tv%s (Release Date: %s)" % (xx['version'], xx['release_date'].date())) if not no_updates: raise SystemExit(1)
def run(self, args): with args.package as f: url = self.api.uri + self.api.urn session = self.api.adapter.session del session.headers['content-type'] resp = session.post('%s/%s/' % (url, versions_res), files={ "archive": f }).json() if not resp['success']: raise SystemExit(resp['message']) appid = resp['data']['id'] print("Checking upload: ", end='', flush=True) for i in range(10): app = self.api.get_by('id', versions_res, appid) if app['state'] != 'uploading': break time.sleep(0.200) else: raise SystemExit("Timeout waiting for upload to complete") if app['state'] == 'error': shellish.vtmlprint("<red>ERROR</red>") self.api.delete(versions_res, app['id']) raise SystemExit(app['state_details']) elif app['state'] == 'ready': shellish.vtmlprint("<green>READY</green>") else: shellish.vtmlprint("<yellow>%s</yellow>" % app['state'].upper()) if app['state_details']: print(app.get('state_details'))
def run(self, args): while True: username = args.username or input('Username: '******'Email: ') password = args.password if not password: password = getpass.getpass('Password (or empty to send email): ') if password: password2 = getpass.getpass('Confirm Password: '******'Full Name: ')) role = args.role or input('Role: ') role_id = self.api.get_by_id_or_name('roles', role)['id'] user_data = { "username": username, "email": email, "first_name": name[0], "last_name": name[1], "password": password, } if args.account: a = self.api.get_by_id_or_name('accounts', args.account) user_data['account'] = a['resource_uri'] user = self.api.post('users', user_data, expand='profile') self.api.put('profiles', user['profile']['id'], { "require_password_change": not password }) self.api.post('authorizations', { "account": user['profile']['account'], "cascade": True, "role": '/api/v1/roles/%s/' % role_id, "user": user['resource_uri'] })
def post(self, data): payload = self.default_payload.copy() payload.update(data) with (yield from self.lock): while True: resp = yield from self.session.post(self.webhook, data=json.dumps(payload)) if resp.status != 200: content = yield from resp.json() if resp.status == 429: # rate limited retry = content['retry_after'] shellish.vtmlprint('<red>Slack Rate Limit Reached: ' 'Retry in %f seconds.</red>' % retry, plain=cronredux.PLAIN_OUTPUT) yield from asyncio.sleep(retry) continue else: shellish.vtmlprint('<b><red>Slack Post Failed:</red> ' '(%d) - %s</b>' % (resp.status, content), plain=cronredux.PLAIN_OUTPUT) yield from resp.release() break
def run(self, args): filters = {} if args.firmware: filters['version'] = args.firmware if args.product: filters['product__name'] = args.product firmwares = self.api.get('firmwares', expand='dtd', limit=1, **filters) if not firmwares: raise SystemExit("No firmware DTD matches this specification.") if firmwares.meta['total_count'] > 1: shellish.vtmlprint( '<red><b>WARNING:</b></red> More than one ' 'firmware DTD found for this specification.', file=sys.stderr) dtd = firmwares[0]['dtd']['value'] with args.output_file as f: dtd = self.walk_dtd(dtd, args.path) if args.shallow: if 'nodes' in dtd: dtd['nodes'] = list(dtd['nodes']) if args.format == 'json': print(json.dumps(dtd, indent=4, sort_keys=True), file=f) else: shellish.treeprint(dtd, file=f)
def postrun(self, args, result=None, exc=None): if exc is not None: return print() if self.accept: shellish.vtmlprint('I, %s %s (%s), do hereby accept the ECM ' 'terms of service: <u><b> X </b></u>' % (self.api.ident['user']['first_name'], self.api.ident['user']['last_name'], self.api.ident['user']['username'])) else: accept = input('Type "accept" to comply with the TOS: ') if accept != 'accept': raise SystemExit("Aborted") tos_uri = self.tos['resource_uri'] try: self.api.post('system_message_confirm', {"message": tos_uri}) except SystemExit as e: try: if 'already exists' in e.__context__.response['message']: raise SystemExit("TOS was already accepted.") except AttributeError: pass raise e
def error(self, title, message='', raw='', footer=None): shellish.vtmlprint("<b><red>ERROR: %s</red></b>" % title, plain=cronredux.PLAIN_OUTPUT) if message or raw: for line in (message + raw).splitlines(): shellish.vtmlprint(" <red>%s</red>" % line, plain=cronredux.PLAIN_OUTPUT) if footer: shellish.vtmlprint(" <dim>%s</dim>" % footer, plain=cronredux.PLAIN_OUTPUT)
def warning(self, title, message='', raw='', footer=None): shellish.vtmlprint("<b>WARN: %s</b>" % title, plain=cronredux.PLAIN_OUTPUT) if message or raw: for line in (message + raw).splitlines(): shellish.vtmlprint(" %s" % line, plain=cronredux.PLAIN_OUTPUT) if footer: shellish.vtmlprint("<dim>%s</dim>" % footer, plain=cronredux.PLAIN_OUTPUT)
def info(self, title, message='', raw='', footer=None): shellish.vtmlprint("<b><blue>INFO: %s</blue></b>" % title, plain=cronredux.PLAIN_OUTPUT) if message or raw: for line in (message + raw).splitlines(): shellish.vtmlprint(" <blue>%s</blue>" % line, plain=cronredux.PLAIN_OUTPUT) if footer: shellish.vtmlprint(" <dim>%s</dim>" % footer, plain=cronredux.PLAIN_OUTPUT)
async def relaylog(log, ts): data = json.dumps(log) url = '%s/%s-%s/%s' % (es_url, es_index, ts.strftime('%Y-%m-%d'), es_type) try: with aiohttp.Timeout(60): async with es_session.post(url, data=data) as r: if r.status != 201: shellish.vtmlprint('<b><red>ES POST ERROR:</red> %s</b>' % (await r.text())) elif verbose: shellish.vtmlprint('<b>ES INDEX:</b>', await r.text()) except asyncio.TimeoutError: shellish.vtmlprint('<b><red>ES POST TIMEOUT</red></b>')
async def relaylog(log, ts): data = json.dumps(log) url = '%s/%s-%s/%s' % (es_url, es_index, ts.strftime('%Y-%m-%d'), es_type) try: with aiohttp.Timeout(60): async with es_session.post(url, data=data) as r: if r.status != 201: shellish.vtmlprint( '<b><red>ES POST ERROR:</red> %s</b>' % (await r.text())) elif verbose: shellish.vtmlprint('<b>ES INDEX:</b>', await r.text()) except asyncio.TimeoutError: shellish.vtmlprint('<b><red>ES POST TIMEOUT</red></b>')
def run(self, args): self.args = args tasks = [] if args.plain: cronredux.PLAIN_OUTPUT = True if args.verbose: shellish.vtmlprint("<b>Processing crontab file:</b> <red>%s</red>" % args.crontab, plain=cronredux.PLAIN_OUTPUT) with args.crontab as f: for spec, command in cronparser.parsef(f): if args.verbose: shellish.vtmlprint("<b>Adding task:</b> <blue>%s</blue> %s" % (spec, command), plain=cronredux.PLAIN_OUTPUT) tasks.append(scheduler.Task(crontab.CronTab(spec), command)) if args.slack_webhook: notifier = notification.SlackNotifier( args.slack_webhook, channel=args.slack_channel, username=args.slack_username, icon_emoji=args.slack_icon_emoji) else: notifier = notification.PrintNotifier() loop = asyncio.get_event_loop() sched = scheduler.Scheduler(tasks, args, notifier, loop) diag = web.DiagService(tasks, args, loop, sched=sched, plain=cronredux.PLAIN_OUTPUT) try: loop.run_until_complete(notifier.setup(loop)) loop.run_until_complete(diag.start()) loop.create_task(sched.run()) loop.run_forever() except KeyboardInterrupt: pass finally: if args.verbose: shellish.vtmlprint("<b>Shutting Down</b>", plain=cronredux.PLAIN_OUTPUT) loop.run_until_complete(diag.cleanup()) loop.close()
def run(self, args): group = self.api.get_by_id_or_name('groups', args.ident, expand='configuration') cur_patch = group['configuration'] if args.replace: with args.replace as f: patch = json.load(f) patch_validate(patch) elif args.merge: with args.merge as f: overlay = json.load(f) patch_validate(overlay) patch = self.merge(cur_patch, overlay) elif args.set: path, value = args.set.split('=', 1) path = path.strip().split('.') value = json.loads(value) updates = copy.deepcopy(cur_patch[0]) offt = updates for x in path[:-1]: if x in offt: offt = offt[x] else: offt[x] = {} offt[path[-1]] = value patch = [updates, cur_patch[1]] patch_validate(patch) if args.json_diff: oldjson = json.dumps(cur_patch, indent=4, sort_keys=True) newjson = json.dumps(patch, indent=4, sort_keys=True) printed = False for line in difflib.unified_diff(oldjson.splitlines(True), newjson.splitlines(True), fromfile='current config', tofile='proposed config', n=10): if line.startswith('---') or line.startswith('+++'): line = '<b>%s</b>' % line elif line.startswith('@@'): line = '<cyan>%s</cyan>' % line elif line[0] == '-': line = '<red>%s</red>' % line elif line[0] == '+': line = '<green>%s</green>' % line shellish.vtmlprint(line, end='') printed = True if printed: print() else: old_adds = dict(base.totuples(cur_patch[0])) new_adds = dict(base.totuples(patch[0])) old_add_keys = set(old_adds) new_add_keys = set(new_adds) for x in old_add_keys - new_add_keys: shellish.vtmlprint('<red>Unsetting:</red> %s=%s' % ( x, old_adds[x])) for x in new_add_keys - old_add_keys: shellish.vtmlprint('<green>Adding:</green> %s=%s' % ( x, new_adds[x])) for x in new_add_keys & old_add_keys: if old_adds[x] != new_adds[x]: shellish.vtmlprint('<yellow>Changing:</yellow> %s (%s' '<b> -> </b>%s)' % (x, old_adds[x], new_adds[x])) old_removes = set(map(tuple, cur_patch[1])) new_removes = set(map(tuple, patch[1])) for x in old_removes - new_removes: shellish.vtmlprint('<red>Unsetting removal:</red> %s' % ( '.'.join(map(str, x)))) for x in new_removes - old_removes: shellish.vtmlprint('<green>Adding removal:</green> %s' % ( '.'.join(map(str, x)))) self.confirm('Confirm update of config of: %s' % group['name']) self.api.put('groups', group['id'], {"configuration": patch})
def verror(self, *args, **kwargs): msg = ' '.join(map(str, args)) shellish.vtmlprint(msg, file=sys.stderr, **kwargs)