From 92db4a5cb817b07a39857eac0f319f6587397203 Mon Sep 17 00:00:00 2001 From: Christos Date: Tue, 19 Jul 2016 11:35:19 +0300 Subject: [PATCH 1/2] Include organization name when requesting a new API token This is due to the recent changes regarding user context Updated tunnel API endpoints Also, some clean up and PEP8 --- src/mistclient/__init__.py | 49 ++++++++++++------------------ src/mistcommand/helpers/login.py | 38 +++++++++++------------ src/mistcommand/helpers/tunnels.py | 20 ++++++------ 3 files changed, 46 insertions(+), 61 deletions(-) diff --git a/src/mistclient/__init__.py b/src/mistclient/__init__.py index d158fb1..0b0d75b 100644 --- a/src/mistclient/__init__.py +++ b/src/mistclient/__init__.py @@ -13,7 +13,7 @@ class MistClient(object): """ def __init__(self, mist_uri="https://mist.io", email=None, password=None, - api_token=None, verify=True): + org_name=None, api_token=None, verify=True): """ Initialize the mist.client. In case email and password are given, it will try to authenticate with mist.io and keep the api_token that is @@ -33,6 +33,7 @@ def __init__(self, mist_uri="https://mist.io", email=None, password=None, self.uri = mist_uri + "api/v1" self.email = email self.password = password + self.org_name = org_name self.api_token = api_token self.user_details = None self.verify = verify @@ -68,7 +69,8 @@ def __authenticate(self): auth_uri = self.uri.split('/api/v1')[0] + '/auth' payload = { 'email': self.email, - 'password': self.password + 'password': self.password, + 'org_id': self.org_name } data = json.dumps(payload) req = self.request(auth_uri, data=data) @@ -141,7 +143,8 @@ def post_logs(self, entries=[]): def clouds(self, id=None, name=None, provider=None, search=None): """ - Property-like function to call the _list_clouds function in order to populate self._clouds dict + Property-like function to call the _list_clouds function in + order to populate self._clouds dict :returns: A list of Cloud instances. """ @@ -170,8 +173,8 @@ def update_clouds(self): """ Update added clouds' info and re-populate the self._clouds dict. - This one is used whenever a new cloud is added, renamed etc etc or whenever you want to update the list - of added clouds. + This one is used whenever a new cloud is added, renamed etc etc or + whenever you want to update the list of added clouds. :returns: A list of Cloud instances. """ @@ -209,8 +212,6 @@ def add_cloud(self, title, provider, **kwargs): payload = self._add_cloud_docker(**kwargs) elif provider == "libvirt": payload = self._add_cloud_libvirt(**kwargs) - # elif provider == "hpcloud": - # payload = self._add_cloud_hp(**kwargs) elif provider == "openstack": payload = self._add_cloud_openstack(**kwargs) elif provider == "hostvirtual": @@ -343,15 +344,6 @@ def _add_cloud_libvirt(self, **kwargs): } return payload - # def _add_cloud_hp(self, **kwargs): - # payload = { - # 'username': kwargs.get('username', ''), - # 'password': kwargs.get('password', ''), - # 'tenant_name': kwargs.get('tenant_name', ''), - # 'region': kwargs.get('region', '') - # } - # return payload - def _add_cloud_openstack(self, **kwargs): payload = { 'username': kwargs.get('username', ''), @@ -384,7 +376,8 @@ def _add_cloud_packet(self, **kwargs): def _list_keys(self): """ - Retrieves a list of all added Keys and populates the self._keys dict with Key instances + Retrieves a list of all added Keys and populates the + self._keys dict with Key instances :returns: A list of Keys instances """ @@ -399,7 +392,8 @@ def _list_keys(self): def keys(self, id=None, search=None): """ - Property-like function to call the _list_keys function in order to populate self._keys dict + Property-like function to call the _list_keys function in + order to populate self._keys dict :returns: A list of Key instances """ @@ -419,9 +413,8 @@ def keys(self, id=None, search=None): def update_keys(self): """ Update added keys' info and re-populate the self._keys dict. - - This one is used whenever a new key is added, renamed etc etc or whenever you want to update the list - of added keys. + This one is used whenever a new key is added, renamed etc etc or + whenever you want to update the list of added keys. :returns: A list of Key instances. """ @@ -435,7 +428,8 @@ def _generate_and_add_key(self, key_name): def generate_key(self): """ - Ask mist.io to randomly generate a private ssh-key to be used with the creation of a new Key + Ask mist.io to randomly generate a private ssh-key to be + used with the creation of a new Key :returns: A string of a randomly generated ssh private key """ @@ -686,22 +680,17 @@ def edit_tunnel(self, tunnel_id, name, cidrs, description): 'description': description } - req = self.request(self.uri + '/tunnel/' + tunnel_id, + req = self.request(self.uri + '/tunnels/' + tunnel_id, data=json.dumps(payload)) response = req.put() return response.json() def delete_tunnel(self, tunnel_id): - req = self.request(self.uri + '/tunnel/' + tunnel_id) + req = self.request(self.uri + '/tunnels/' + tunnel_id) response = req.delete() return response - def tunnel_script(self, tunnel_id): - req = self.request(self.uri + '/tunnel/' + tunnel_id + '/script') - response = req.get() - return response.text - def tunnel_command(self, tunnel_id): - req = self.request(self.uri + '/tunnel/' + tunnel_id + '/command') + req = self.request(self.uri + '/tunnels/' + tunnel_id + '/command') response = req.get() return response.text diff --git a/src/mistcommand/helpers/login.py b/src/mistcommand/helpers/login.py index fad0f6e..4ca1b73 100644 --- a/src/mistcommand/helpers/login.py +++ b/src/mistcommand/helpers/login.py @@ -6,18 +6,6 @@ from prettytable import PrettyTable -# def init_client(mist_uri, email, password, api_token): -# try: -# client = MistClient(mist_uri=mist_uri, email=email, password=password, -# api_token=api_token) -# # Ensures that GET requests are authenticated -# client.clouds() -# return client -# except Exception as e: -# print e -# sys.exit(1) - - def parse_config(): home_path = os.getenv("HOME") config_path = os.path.join(home_path, ".mist") @@ -32,6 +20,7 @@ def parse_config(): config.add_section("mist.credentials") config.set("mist.credentials", "email", None) config.set("mist.credentials", "password", None) + config.set("mist.credentials", "org_name", None) config.set("mist.credentials", "api_token", None) # Read configuration file @@ -43,22 +32,24 @@ def parse_config(): mist_uri = config.get("mist.io", "mist_uri") email = config.get("mist.credentials", "email") or prompt_email() password = config.get("mist.credentials", "password") or prompt_password() - _api_token = config.get("mist.credentials", "api_token") or None + org_name = config.get("mist.credentials", "org_name") or prompt_org() + api_token = config.get("mist.credentials", "api_token") or None # initiate a new MistClient to verify the existing token or request a new client = MistClient(mist_uri='https://mist.io', email=email, - password=password, api_token=_api_token) - api_token = client.api_token - if _api_token != api_token: + password=password, org_name=org_name, + api_token=api_token) + if api_token != client.api_token: renew = False - if _api_token is not None: + if api_token is not None: renew = True print 'API token no longer valid. Renewing ...' - prompt_save_config(mist_uri, email, password, api_token, config_path, renew) - + prompt_save_config(mist_uri, email, password, org_name, + client.api_token, config_path, renew) return client -def prompt_save_config(mist_uri, email, password, api_token, config_path, renew): +def prompt_save_config(mist_uri, email, password, org_name, api_token, + config_path, renew): answered = None if renew: answered = True @@ -80,8 +71,9 @@ def prompt_save_config(mist_uri, email, password, api_token, config_path, renew) [mist.credentials] email=%s password=%s +org_name=%s api_token=%s -""" % (mist_uri, email, password, api_token) +""" % (mist_uri, email, password, org_name, api_token) if answer: with open(config_path, "w") as f: @@ -100,6 +92,10 @@ def prompt_password(): return getpass.getpass("Password: ") +def prompt_org(): + return raw_input("Organization: ") + + def authenticate(): client = parse_config() return client diff --git a/src/mistcommand/helpers/tunnels.py b/src/mistcommand/helpers/tunnels.py index d9770e7..5a1e66f 100644 --- a/src/mistcommand/helpers/tunnels.py +++ b/src/mistcommand/helpers/tunnels.py @@ -16,11 +16,11 @@ def tunnel_action(args): print 'Now, copy-paste and run the configuration script on your VPN ' \ 'client in order to complete the VPN tunnel\'s establishment\n' print '='*50 + '\n' - get_conf(client, tunnel['_id']) + get_conf(client, tunnel['id']) print '='*50 + '\n' print 'Or, you can simply run the following `curl` command directly ' \ 'in your VPN client\'s shell:\n' - get_cmd(client, tunnel['_id']) + get_cmd(client, tunnel['id']) elif args.action == 'edit-tunnel': edit_tunnel(client, args) print 'Tunnel %s was edited successfully' % args.tunnel @@ -42,12 +42,12 @@ def list_tunnels(client, pretty): x = PrettyTable(['Name', 'ID', 'CIDRs', 'Description']) for tunnel in tunnels: description = tunnel.get('description', '-') - x.add_row([tunnel['name'], tunnel['_id'], tunnel['cidrs'], description]) + x.add_row([tunnel['name'], tunnel['id'], tunnel['cidrs'], description]) print x else: for tunnel in tunnels: description = tunnel.get('description', '-') - print '%-40s %-40s %-40s %-40s' % (tunnel['name'], tunnel['_id'], + print '%-40s %-40s %-40s %-40s' % (tunnel['name'], tunnel['id'], tunnel['cidrs'], description) @@ -92,12 +92,12 @@ def get_conf(client, tunnel_id): print 'Could not find any VPN Tunnels' sys.exit(0) for tunnel in tunnels: - if tunnel['_id'] == tunnel_id: - script = tunnel['script'] - break - else: - print 'The ID provided does not correspond to any VPN Tunnel' - sys.exit(0) + if tunnel['id'] == tunnel_id: + script = tunnel['script'] + break + else: + print 'The ID provided does not correspond to any VPN Tunnel' + sys.exit(0) print script From d45c2dcd73c31c468437ad72f9e139b381acf8be Mon Sep 17 00:00:00 2001 From: Christos Date: Tue, 19 Jul 2016 11:37:06 +0300 Subject: [PATCH 2/2] Update mist user-info command --- src/mistclient/helpers.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/mistclient/helpers.py b/src/mistclient/helpers.py index d034155..952e061 100644 --- a/src/mistclient/helpers.py +++ b/src/mistclient/helpers.py @@ -4,7 +4,6 @@ import time from HTMLParser import HTMLParser as _HTMLParser -from HTMLParser import HTMLParseError try: import requests @@ -97,28 +96,31 @@ def handle_data(self, data): if str(data).startswith(' var '): _data = data.lstrip(' var ').split('=') key, value = _data[0], json.loads(_data[1]) - if not isinstance(value, basestring) and \ - not isinstance(value, list) and \ - not isinstance(value, dict): + if not (isinstance(value, basestring) or + isinstance(value, list) or + isinstance(value, dict)): pass else: self.user_info[key] = value def user_details(self): user = {} - for key in ['FIRST_NAME', 'LAST_NAME', 'EMAIL', - 'NUMBER_OF_SERVERS', 'COMPANY_NAME']: - if key in self.user_info.keys(): - user[key] = self.user_info[key] + orgs = [] + for key in ['FIRST_NAME', 'LAST_NAME', 'EMAIL']: + user[key] = self.user_info[key] + for org in self.user_info['ORGS']: + orgs.append(org['name']) + user['ORGANIZATIONS'] = ', '.join(orgs) return user def plan_details(self): current = self.user_info['CURRENT_PLAN'] plan = {} - for key in ['title', 'started', 'expiration', 'machine_limit']: - if key in ['started', 'expiration']: - current[key] = time.ctime(current[key]) - plan[key.upper()] = current[key] + if current: + for key in ['title', 'started', 'expiration', 'machine_limit']: + if key in ['started', 'expiration']: + current[key] = time.ctime(current[key]) + plan[key.upper()] = current[key] return plan