From 4d56cf4e81bc0a93d286b12bd5b259c04eafcfb9 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Fri, 20 Apr 2018 19:53:20 +0300 Subject: Refactor: icktool --- icktool | 315 ++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 179 insertions(+), 136 deletions(-) (limited to 'icktool') diff --git a/icktool b/icktool index 7be5bc1..2e2acfc 100755 --- a/icktool +++ b/icktool @@ -114,155 +114,34 @@ class Icktool(cliapp.Application): self.output.write('{}\n'.format(token)) def cmd_version(self, args): - api = self._new_api() - token = self._new_token(api) - api.set_token(token) - version = api.get_version() - self._prettyson(version) + cmd = self._command(VersionCommand) + cmd.execute(args) def cmd_status(self, args): - table = Table() - table.set_columns('project', 'status', 'build_status', 'log_id') - - api = self._new_api() - token = self._new_token(api) - api.set_token(token) - - projects = api.show('/projects') - builds = api.show('/builds') - - for project in projects['projects']: - project_name = project['project'] - project_status = api.show( - '/projects/{}/status'.format(project_name)) - - row = { - 'project': project_name, - 'status': project_status['status'], - 'build_status': 'n/a', - 'log_id': 'n/a' - } - - build = self._latest_build(project_name, builds) - if build: - row['build_status'] = build['status'] - row['log_id'] = build['log'] - - table.append_row(**row) - - self.output.write(table.format()) - - def _latest_build(self, project_name, builds): - builds = self._find_builds(project_name, builds) - if builds: - return builds[-1] - return None - - def _find_builds(self, project_name, builds): - return [b for b in builds['builds'] if b['project'] == project_name] - - def _find_build(self, builds, build_id): - for build in builds: - if build['build_id'] == build_id: - return build - return None + cmd = self._command(StatusCommand) + cmd.execute(args) def cmd_build_graph(self, args): - api = self._new_api() - token = self._new_token(api) - api.set_token(token) - - project_name = args[0] - if len(args) > 1: - build_id = args[1] - else: - build_id = 'latest' - - builds = api.show('/builds') - builds = self._find_builds(project_name, builds) - if not builds: - sys.exit('No such build %s' % build_id) - - if build_id == 'latest': - build = builds[-1] - else: - build = self._find_build(builds, build_id) - - actions = build['actions'] - current = build['current_action'] - status = build['status'] - - f = self.output - f.write('digraph "build_graph" {\n') - for i, action in enumerate(actions): - self._describe_node(f, i, current, action) - f.write('}\n') - - def _describe_node(self, f, i, current, action): - styles = { - 'done': ('rectangle', '#ffffff'), - 'building': ('ellipse', '#00ff00'), - 'blocked': ('ellipse', '#bbbbbb'), - } - - if current is None: - shape, color = styles['done'] - elif i < current: - shape, color = styles['done'] - elif i == current: - shape, color = styles['building'] - elif i > current: - shape, color = styles['blocked'] - - tmpl = 'a{} [label="{}" shape={} style=filled fillcolor="{}"]\n' - f.write(tmpl.format(i, self._describe_action(action), shape, color)) - - def _describe_action(self, action): - for key in ['action', 'archive']: - if key in action: - return '{}: {}'.format(key, action[key]) - for key in ['debootstrap', 'shell', 'python']: - if key in action: - return key - return str(action) + cmd = self._command(BuildGraphCommand) + cmd.execute(args) def cmd_make_it_so(self, argv): - obj = self._read_object() - - api = self._new_api() - token = self._new_token(api) - api.set_token(token) - - self._create_resources(api, '/projects', obj.get('projects', [])) - self._create_resources(api, '/pipelines', obj.get('pipelines', [])) - - def _read_object(self): - return yaml.load(sys.stdin) - - def _create_resources(self, api, path, objs): - for obj in objs: - api.create(path, obj) + cmd = self._command(MakeItSoCommand) + cmd.execute(args) def cmd_trigger(self, args): - project = args[0] - api = self._new_api() - token = self._new_token(api) - api.set_token(token) - self._prettyson(api.trigger(project)) + cmd = self._command(TriggerCommand) + cmd.execute(args) def cmd_show(self, args): + cmd = self._command(ShowCommand) + cmd.execute(args) + + def _command(self, klass): api = self._new_api() token = self._new_token(api) api.set_token(token) - if not args: - args = [ - 'projects', - 'pipelines', - ] - - for kind in args: - objs = api.show('/' + kind) - self._prettyson(objs) + return klass(api, self.output) def _new_api(self): api = ick2.ControllerClient() @@ -352,4 +231,168 @@ class Table: return max(len(str(row[column_name])) for row in self._rows) +def _latest_build(project_name, builds): + builds = _find_builds(project_name, builds) + if builds: + return builds[-1] + return None + +def _find_builds(project_name, builds): + return [b for b in builds['builds'] if b['project'] == project_name] + +def _find_build(builds, build_id): + for build in builds: + if build['build_id'] == build_id: + return build + return None + + +class Command: + + def __init__(self, api, output): + self.api = api + self.output = output + + def _prettyson(self, obj): + json.dump(obj, self.output, indent=4, sort_keys=True) + self.output.write('\n') + + def execute(self, args): + raise NotImplementedError() + + +class VersionCommand(Command): + + def execute(self, args): + version = self.api.get_version() + self._prettyson(version) + + +class StatusCommand(Command): + + def execute(self, args): + table = Table() + table.set_columns('project', 'status', 'build_status', 'log_id') + + projects = self.api.show('/projects') + builds = self.api.show('/builds') + + for project in projects['projects']: + project_name = project['project'] + project_status = self.api.show( + '/projects/{}/status'.format(project_name)) + + row = { + 'project': project_name, + 'status': project_status['status'], + 'build_status': 'n/a', + 'log_id': 'n/a' + } + + build = _latest_build(project_name, builds) + if build: + row['build_status'] = build['status'] + row['log_id'] = build['log'] + + table.append_row(**row) + + self.output.write(table.format()) + + + +class BuildGraphCommand(Command): + + def execute(self, args): + project_name = args[0] + if len(args) > 1: + build_id = args[1] + else: + build_id = 'latest' + + builds = self.api.show('/builds') + builds = _find_builds(project_name, builds) + if not builds: + sys.exit('No such build %s' % build_id) + + if build_id == 'latest': + build = builds[-1] + else: + build = _find_build(builds, build_id) + + actions = build['actions'] + current = build['current_action'] + status = build['status'] + + f = self.output + f.write('digraph "build_graph" {\n') + for i, action in enumerate(actions): + self._describe_node(f, i, current, action) + f.write('}\n') + + def _describe_node(self, f, i, current, action): + styles = { + 'done': ('rectangle', '#ffffff'), + 'building': ('ellipse', '#00ff00'), + 'blocked': ('ellipse', '#bbbbbb'), + } + + if current is None: + shape, color = styles['done'] + elif i < current: + shape, color = styles['done'] + elif i == current: + shape, color = styles['building'] + elif i > current: + shape, color = styles['blocked'] + + tmpl = 'a{} [label="{}" shape={} style=filled fillcolor="{}"]\n' + f.write(tmpl.format(i, self._describe_action(action), shape, color)) + + def _describe_action(self, action): + for key in ['action', 'archive']: + if key in action: + return '{}: {}'.format(key, action[key]) + for key in ['debootstrap', 'shell', 'python']: + if key in action: + return key + return str(action) + + +class MakeItSoCommand(Command): + + def execute(self, args): + obj = self._read_object() + + self._create_resources('/projects', obj.get('projects', [])) + self._create_resources('/pipelines', obj.get('pipelines', [])) + + def _read_object(self): + return yaml.load(sys.stdin) + + def _create_resources(self, path, objs): + for obj in objs: + self.api.create(path, obj) + + +class TriggerCommand(Command): + + def execute(self, args): + project = args[0] + self._prettyson(self.api.trigger(project)) + + +class ShowCommand(Command): + + def execute(self, args): + if not args: + args = [ + 'projects', + 'pipelines', + ] + + for kind in args: + objs = self.api.show('/' + kind) + self._prettyson(objs) + + Icktool(version=ick2.__version__).run() -- cgit v1.2.1