summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2018-04-07 15:24:40 +0300
committerLars Wirzenius <liw@liw.fi>2018-04-07 16:54:03 +0300
commitd52f5cbef49edff9ceb1b5092ed7e60553ce185a (patch)
tree7623145a540e4cae506ff7c0845b052d8ef5a07f
parentdaafee995775a5b79ef7bc23d819c39d30362061 (diff)
downloadick2-d52f5cbef49edff9ceb1b5092ed7e60553ce185a.tar.gz
Add: new icktool2 command
-rw-r--r--ick2/client.py10
-rwxr-xr-xicktool2210
2 files changed, 219 insertions, 1 deletions
diff --git a/ick2/client.py b/ick2/client.py
index cda3649..ec2a113 100644
--- a/ick2/client.py
+++ b/ick2/client.py
@@ -154,7 +154,7 @@ class ControllerClient:
return self._api.get_dict(url)
def get_artifact_store_url(self):
- version = self.version()
+ version = self.get_version()
url = version.get('artifact_store')
logging.info('Artifact store URL: %r', url)
return url
@@ -206,6 +206,14 @@ class ControllerClient:
body = json.dumps(work)
self._api.post(url, headers=headers, body=body)
+ def show(self, path): # pragma: no cover
+ url = self.url(path)
+ return self._api.get_dict(url)
+
+ def create(self, path, obj): # pragma: no cover
+ url = self.url(path)
+ return self._api.post(url, body=obj)
+
class AuthClient:
diff --git a/icktool2 b/icktool2
new file mode 100755
index 0000000..df5ccdd
--- /dev/null
+++ b/icktool2
@@ -0,0 +1,210 @@
+#!/usr/bin/python3
+# Copyright 2017-2018 Lars Wirzenius
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+import configparser
+import json
+import logging
+import sys
+import time
+
+import apifw
+import cliapp
+import Crypto.PublicKey.RSA
+import requests
+import yaml
+
+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]
+
+
+def scopes_for_types(typelist):
+ result = []
+ for type_name in typelist:
+ result.extend(scopes(type_name))
+ return result
+
+
+types = [
+ 'projects',
+ 'pipelines',
+ 'workers',
+ 'work',
+ 'builds',
+ 'logs',
+]
+
+
+class Icktool(cliapp.Application):
+
+ _default_scopes = [
+ 'uapi_version_get',
+ 'uapi_work_post',
+ 'uapi_projects_id_pipelines_id_get',
+ 'uapi_projects_id_pipelines_id_put',
+ 'uapi_blobs_id_get',
+ 'uapi_blobs_id_put',
+ ] + scopes_for_types(types)
+
+ def add_settings(self):
+ self.settings.string(
+ ['controller', 'c'],
+ 'use URL as the controller base URL',
+ metavar='URL',
+ )
+
+ self.settings.string(
+ ['auth-url'],
+ 'use URL as the authentication URL',
+ metavar='URL',
+ )
+
+ self.settings.string(
+ ['secrets'],
+ 'use URL as the controller base URL',
+ metavar='URL',
+ )
+
+ self.settings.boolean(
+ ['verify-tls'],
+ 'verify API provider TLS certificate '
+ '(default is verify, use --no-verify-tls)',
+ default=True,
+ )
+
+ self.settings.string(
+ ['token'],
+ 'use TOKEN instead of generating a new one',
+ metavar='TOKEN',
+ )
+
+ self.settings.string_list(
+ ['scope'],
+ 'add SCOPE to the list of scope in requested token',
+ metavar='SCOPE',
+ default=self._default_scopes,
+ )
+
+ def setup(self):
+ if not self.settings['verify-tls']:
+ logging.captureWarnings(True)
+
+ def cmd_scopes(self, args):
+ for scope in self.settings['scope']:
+ self.output.write('{}\n'.format(scope))
+
+ def cmd_token(self, args):
+ token = self._new_token()
+ self.output.write('{}\n'.format(token))
+
+ def cmd_version(self, args):
+ token = self._new_token()
+ api = self._new_api()
+ api.set_token(token)
+ version = api.get_version()
+ self._prettyson(version)
+
+ def cmd_make_it_so(self, argv):
+ obj = self._read_object()
+
+ token = self._new_token()
+ api = self._new_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)
+
+ def cmd_show(self, args):
+ token = self._new_token()
+ api = self._new_api()
+ api.set_token(token)
+ if not args:
+ args = [
+ 'projects',
+ 'pipelines',
+ ]
+
+ for kind in args:
+ objs = api.show('/' + kind)
+ self._prettyson(objs)
+
+ def _new_api(self):
+ api = ick2.ControllerClient()
+ api.set_verify_tls(self.settings['verify-tls'])
+ api.set_controller_url(self.settings['controller'])
+ return api
+
+ def _new_auth(self):
+ url = self.settings['auth-url']
+ client_id, client_secret = self._get_client_creds(url)
+
+ ac = ick2.AuthClient()
+ ac.set_auth_url(url)
+ ac.set_client_creds(client_id, client_secret)
+ return ac
+
+ def _new_token(self):
+ if self.settings['token']:
+ return self.settings['token']
+ ac = self._new_auth()
+ scopes = ' '.join(self.settings['scope'])
+ return ac.get_token(scopes)
+
+ def _get_client_creds(self, url):
+ cp = configparser.ConfigParser()
+ cp.read(self.settings['secrets'])
+ client_id = cp.get(url, 'client_id')
+ client_secret = cp.get(url, 'client_secret')
+ return client_id, client_secret
+
+ def _prettyson(self, obj):
+ json.dump(obj, self.output, indent=4, sort_keys=True)
+ self.output.write('\n')
+
+
+class Command:
+
+ def __init__(self, api):
+ self._api = api
+
+ def execute(self):
+ raise NotImplementedError()
+
+
+class VersionCommand(Command):
+
+ def execute(self):
+ self._api.get_version()
+
+
+Icktool(version=ick2.__version__).run()