summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2017-10-16 22:15:42 +0300
committerLars Wirzenius <liw@liw.fi>2017-10-16 22:15:42 +0300
commitc1bb4e1ba7f7f057b139519b03726dd8b3055755 (patch)
treee9816e518c3e64b19c03367e87c5f11a6794a20d
parent5340eaeb454b454b12caeb28be29a6d282c9f4f2 (diff)
parent15156dfb3e1fc4a4670fe4f6b8151d27e45e56a5 (diff)
downloadick2-c1bb4e1ba7f7f057b139519b03726dd8b3055755.tar.gz
Merge branch 'liw/icktool'
-rw-r--r--ick2/controllerapi.py11
-rwxr-xr-xicktool163
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']
diff --git a/icktool b/icktool
index 1842570..999bd50 100755
--- a/icktool
+++ b/icktool
@@ -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: