diff options
author | Lars Wirzenius <liw@liw.fi> | 2017-10-16 22:15:42 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2017-10-16 22:15:42 +0300 |
commit | c1bb4e1ba7f7f057b139519b03726dd8b3055755 (patch) | |
tree | e9816e518c3e64b19c03367e87c5f11a6794a20d | |
parent | 5340eaeb454b454b12caeb28be29a6d282c9f4f2 (diff) | |
parent | 15156dfb3e1fc4a4670fe4f6b8151d27e45e56a5 (diff) | |
download | ick2-c1bb4e1ba7f7f057b139519b03726dd8b3055755.tar.gz |
Merge branch 'liw/icktool'
-rw-r--r-- | ick2/controllerapi.py | 11 | ||||
-rwxr-xr-x | icktool | 163 |
2 files changed, 168 insertions, 6 deletions
diff --git a/ick2/controllerapi.py b/ick2/controllerapi.py index 6d25a7d..1cf1aef 100644 --- a/ick2/controllerapi.py +++ b/ick2/controllerapi.py @@ -83,7 +83,7 @@ class APIbase: # pragma: no cover def GET(self, callback): def wrapper(content_type, body, **kwargs): ick2.log.log( - 'xxx', msg_text='GET called', kwargs=kwargs, + 'trace', msg_text='GET called', kwargs=kwargs, content_type=content_type, body=body) try: if 'raw_uri_path' in kwargs: @@ -98,6 +98,9 @@ class APIbase: # pragma: no cover def POST(self, callback): def wrapper(content_type, body, **kwargs): + ick2.log.log( + 'trace', msg_text='POST called', kwargs=kwargs, + content_type=content_type, body=body) body = callback(body) ick2.log.log('trace', msg_text='returned body', body=repr(body)) return created(body) @@ -105,6 +108,9 @@ class APIbase: # pragma: no cover def PUT(self, callback): def wrapper(content_type, body, **kwargs): + ick2.log.log( + 'trace', msg_text='PUT called', kwargs=kwargs, + content_type=content_type, body=body) if 'raw_uri_path' in kwargs: del kwargs['raw_uri_path'] body = callback(body, **kwargs) @@ -114,6 +120,9 @@ class APIbase: # pragma: no cover def DELETE(self, callback): def wrapper(content_type, body, **kwargs): + ick2.log.log( + 'trace', msg_text='DELETE called', kwargs=kwargs, + content_type=content_type, body=body) try: if 'raw_uri_path' in kwargs: del kwargs['raw_uri_path'] @@ -26,11 +26,22 @@ import requests import ick2 +def scopes(base): + patterns = [ + 'uapi_{}_get', + 'uapi_{}_post', + 'uapi_{}_id_get', + 'uapi_{}_id_put', + 'uapi_{}_id_delete', + ] + return [x.format(base) for x in patterns] + + class Icktool(cliapp.Application): _default_scopes = [ 'uapi_version_get', - ] + ] + scopes('projects') + scopes('workers') def add_settings(self): self.settings.string( @@ -67,13 +78,71 @@ class Icktool(cliapp.Application): if not self.settings['verify-tls']: logging.captureWarnings(True) + def cmd_scopes(self, args): + for scope in self.settings['scope']: + sys.stdout.write('{}\n'.format(scope)) + def cmd_token(self, args): token = self._new_token() sys.stdout.write(token) def cmd_version(self, args): api = self._new_api() - self._prettyson(api.get('/version')) + code, text = api.get('/version') + if code != 200: + sys.stderr.write('HTTP status {}\n'.format(code)) + sys.stderr.write(text) + sys.exit(1) + obj = json.loads(text) + self._prettyson(obj) + + def cmd_list_projects(self, args): + rc = self._new_rc('/projects', 'project') + self._prettyson(rc.list()) + + def cmd_create_project(self, args): + rc = self._new_rc('/projects', 'project') + obj = self._read_object() + rc.create(obj) + + def cmd_update_project(self, args): + rc = self._new_rc('/projects', 'project') + obj = self._read_object() + rc.update(obj) + + def cmd_show_project(self, args): + rc = self._new_rc('/projects', 'project') + name = args[0] + self._prettyson(rc.show(name)) + + def cmd_delete_project(self, args): + rc = self._new_rc('/projects', 'project') + name = args[0] + rc.delete(name) + + def cmd_list_workers(self, args): + rc = self._new_rc('/workers', 'worker') + self._prettyson(rc.list()) + + def cmd_create_worker(self, args): + rc = self._new_rc('/workers', 'worker') + obj = self._read_object() + rc.create(obj) + + def cmd_update_worker(self, args): + rc = self._new_rc('/workers', 'worker') + obj = self._read_object() + rc.update(obj) + + def cmd_show_worker(self, args): + rc = self._new_rc('/workers', 'worker') + name = args[0] + self._prettyson(rc.show(name)) + + def cmd_delete_worker(self, args): + rc = self._new_rc('/workers', 'worker') + name = args[0] + rc.delete(name) def _new_token(self): scopes = self.settings['scope'] @@ -94,10 +163,17 @@ class Icktool(cliapp.Application): api.set_verify(self.settings['verify-tls']) return api + def _new_rc(self, path, field_name): + api = self._new_api() + return ResourceCommands(path, api, field_name) + def _prettyson(self, obj): json.dump(obj, sys.stdout, indent=4) sys.stdout.write('\n') + def _read_object(self): + return json.load(sys.stdin) + class API: @@ -119,12 +195,89 @@ class API: assert self._url is not None assert self._token is not None - version_url = '{}/version'.format(self._url) + full_url = '{}/{}'.format(self._url, path) + headers = { + 'Authorization': 'Bearer {}'.format(self._token), + } + r = requests.get(full_url, headers=headers, verify=self._verify) + return r.status_code, r.text + + def post(self, path, obj): + assert self._url is not None + assert self._token is not None + + full_url = '{}{}'.format(self._url, path) + headers = { + 'Authorization': 'Bearer {}'.format(self._token), + } + r = requests.post( + full_url, json=obj, headers=headers, verify=self._verify) + return r.status_code, r.text + + def put(self, path, obj): + assert self._url is not None + assert self._token is not None + + full_url = '{}{}'.format(self._url, path) + headers = { + 'Authorization': 'Bearer {}'.format(self._token), + } + r = requests.put( + full_url, json=obj, headers=headers, verify=self._verify) + return r.status_code, r.text + + def delete(self, path): + assert self._url is not None + assert self._token is not None + + full_url = '{}{}'.format(self._url, path) headers = { 'Authorization': 'Bearer {}'.format(self._token), } - r = requests.get(version_url, headers=headers, verify=self._verify) - return r.json() + r = requests.delete( + full_url, headers=headers, verify=self._verify) + return r.status_code, r.text + + +class ResourceCommands: + + def __init__(self, path, api, name_field): + self._path = path + self._api = api + self._name = name_field + + def list(self): + code, text = self._api.get(self._path) + self._report(code, 200, text) + return json.loads(text) + + def create(self, obj): + code, text = self._api.post(self._path, obj) + self._report(code, 201, text) + + def update(self, obj): + code, text = self._api.put(self._id_path(obj[self._name]), obj) + self._report(code, 200, text) + + def show(self, name): + code, text = self._api.get(self._id_path(name)) + self._report(code, 200, text) + return json.loads(text) + + def delete(self, name): + code, text = self._api.delete(self._id_path(name)) + self._report(code, 200, text) + + def _id_path(self, name): + return '{}/{}'.format(self._path, name) + + def _report(self, code, expected, text): + if code != expected: + sys.stderr.write('HTTP status {}\n'.format(code)) + sys.stderr.write(text) + if not text.endswith('\n'): + sys.stderr.write('\n') + sys.exit(1) class TokenGenerator: |