From 43e82e4044a5018eb2e38fe513562edfc0be98c3 Mon Sep 17 00:00:00 2001 From: John H Date: Mon, 12 Sep 2016 13:04:58 -0400 Subject: [PATCH] Adding methods to python client. --- .../collins_client/collins_client/client.py | 178 +++++++++++++++++- support/python/collins_client/setup.py | 2 +- 2 files changed, 173 insertions(+), 7 deletions(-) diff --git a/support/python/collins_client/collins_client/client.py b/support/python/collins_client/collins_client/client.py index c538a840e..fe0d2ce6d 100644 --- a/support/python/collins_client/collins_client/client.py +++ b/support/python/collins_client/collins_client/client.py @@ -1,14 +1,18 @@ #!/usr/bin/env python -import grequests - import base64 +import logging import urllib import urllib2 + +import grequests try: import simplejson as json except ImportError: import json +log = logging.getLogger(__name__) + + class CollinsClient: """ This client will help you interface with Collins in a meaningful way @@ -100,11 +104,173 @@ def create_assets_log(self, tag, params={}): url = "/api/asset/%s/log" % (tag) response = self._query("put", url, params) + def ping(self): + + url = "/api/ping" + response = self._query("get", url, {}) + return response + + def create_assettype(self, name, label): + """ + Description Create a new asset type + Request PUT /api/assettype/:name + Permission controllers.AssetTypeApi.createAssetType + Parameters + Name Type Description + name String Must be alphanumeric (but can include underscores and dashes) and unique + label String Human readable label for the asset type. 2-32 characters. + Response Codes + Code Reason + 201 Asset type was successfully created + 409 Asset type with specified name already exists + """ + + url = "/api/assettype/{0}".format(name) + params = {'label': label} + response = self._query("put", url, params) + return response + + def update_assettype(self, name, label=None, newname=None): + """ + Description Update an asset type + Request POST /api/assettype/:tag + Permission controllers.AssetTypeApi.updateAssetType + Parameters + Name Type Description + name String New name of the asset type (i.e. SERVICE). All uppercase, 2-32 chars. + label String New label of the asset type. 2-32 chars. + Response Codes + Code Reason + 200 Asset type updated successfully + 404 The specified asset type was not found + """ + + url = "/api/assettype/{0}".format(name) + params = {} + if label: + params['label'] = label + if newname: + params['name'] = newname + + response = self._query("post", url, params) + return response + + def get_assettype(self, name): + """ + Description Get an asset type by name + Request GET /api/assettype/:name + Permission controllers.AssetTypeApi.getAssetType + Parameters + Name Type Description + name String Must be alphanumeric (but can include underscores and dashes) and unique + Response Codes + Code Reason + 200 Asset type was found + 404 Asset type could not be found + """ + + url = "/api/assettype/{0}".format(name) + response = self._query("get", url) + return response + + def delete_assettype(self, name): + """ Delete the specified asset type + :param name: Asset unique name + :return dict + + Request DELETE /api/assettype/:name + Permission controllers.AssetTypeApi.deleteAssetType + Parameters + Name Type Description + name String Must be alphanumeric (but can include underscores and dashes) and unique + Response Codes + Code Reason + 200 Asset type has been deleted + 404 Asset type not found + 409 System asset types cannot be deleted + 500 Asset type unable to be deleted (Assets of this type still exist?) + """ + + url = "/api/assettype/{0}".format(name) + response = self._query("delete", url) + return response + + def ensure_assettype(self, name, label): + """ Ensure assettype exists. + :param name: Asset type name + :param label: Asset type descriptive label + :return: dict + """ + try: + response = self.create_assettype(name, label) + except urllib2.HTTPError as e: + if e.code == 409: + response = {u'status': u'success:exists', + u'data': {u'SUCCESS': True}} + + return response + + def ensure_asset(self, tag, params={}): + """ Ensure asset exists + :param tag: Unique asset tag + :param params: dict + :return: dict + """ + try: + response = self.create_asset(tag, params) + except urllib2.HTTPError as e: + if e.code == 409: + response = dict(status=u'success:exists', + data={u'SUCCESS': True}) + else: + response = dict(status=u'failure:{0}'.format(e.code), + data={u'SUCCESS': False}) + + if not response['status'].startswith('success'): + log.warn(response['status']) + + return response + + def soft_update(self, tag, key, value): + + old_record = self.asset_info(tag) + + # everything from the API is a string + value = str(value) + + update = True + old = None + if 'ATTRIBS' in old_record['data'].keys(): + + # If no attributes have ever been stored, [u'0'] doesn't + # exist. + log.debug(len(old_record['data']['ATTRIBS'])) + + if len(old_record['data']['ATTRIBS']) > 0: + attribs = old_record['data']['ATTRIBS'][u'0'] + else: + attribs = {} + + if key.upper() in attribs.keys(): + old = attribs[key.upper()] + if old == value: + update = False + + # Never erase + if value == '' or value == 'None': + update = False + + if update: + log.debug('{0}: Will update {1} from {2} to {3}'.format(tag, key, old, value)) + self.update_asset(tag, {'attribute': '{0};{1}'.format(key, value)}) + else: + log.debug('{0}: No change to {1}, no update needed'.format(tag, key)) + def _query(self, method, url, params={}): """ """ handle = urllib2.build_opener(urllib2.HTTPHandler) - #Eventually making this a little more robust + # Eventually making this a little more robust if method in ['post', 'put']: request = urllib2.Request(self.host+url, data=urllib.urlencode(params, doseq=True)) else: @@ -115,8 +281,8 @@ def _query(self, method, url, params={}): authstring = base64.encodestring("%s:%s" % (self.username, self.passwd)).strip() request.add_header("Authorization", "Basic %s" % authstring) - #Python does not support case statements - #This will override the request method, defaulting to get + # Python does not support case statements + # This will override the request method, defaulting to get request.get_method = { "get" : lambda: "GET", "post" : lambda: "POST", @@ -124,7 +290,7 @@ def _query(self, method, url, params={}): "delete" : lambda: "DELETE" }.get(method, "get") - #TODO little more robust + # TODO little more robust response = handle.open(request).read() response = json.loads(response) return response diff --git a/support/python/collins_client/setup.py b/support/python/collins_client/setup.py index 5256464b1..35fabab7c 100644 --- a/support/python/collins_client/setup.py +++ b/support/python/collins_client/setup.py @@ -5,7 +5,7 @@ setup(name="collins_client", version="0.1.1", description="The python interface to the collins api.", - author="John Bunting, Nick Thuesen, Nick Sauro, Will Richard", + author="John Bunting, Nick Thuesen, Nick Sauro, Will Richard, John Hogenmiller", author_email="opensourcesoftware@tumblr.com", url="https://github.com/tumblr/collins/tree/master/support/python/collins_client", packages=find_packages(),