From 2bcceeb27e3e1ce3f49f4a89764d433ec059d903 Mon Sep 17 00:00:00 2001 From: Marek Isalski Date: Sun, 1 Jul 2018 19:26:12 +0200 Subject: [PATCH] initial import --- .hgignore | 4 ++ modules/pillar/fulcrm.py | 101 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 .hgignore create mode 100644 modules/pillar/fulcrm.py diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..1dcb12c --- /dev/null +++ b/.hgignore @@ -0,0 +1,4 @@ +\.pyc$ +^sftp-config\.json$ +\.sublime-workspace$ +\.sublime-project$ diff --git a/modules/pillar/fulcrm.py b/modules/pillar/fulcrm.py new file mode 100644 index 0000000..b4024d7 --- /dev/null +++ b/modules/pillar/fulcrm.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- + +import requests +import requests.exceptions +import time + +import logging +log = logging.getLogger(__name__) + +def __init__(opts): + return True + +def __virtual__(): + return True + +class TastypieAuth( requests.auth.AuthBase ): + def __init__( self, api_username, api_key ): + self.api_username = api_username + self.api_key = api_key + + def __call__( self, r ): + r.headers[ 'Authorization' ] = "ApiKey %s:%s" % ( self.api_username, self.api_key ) + r.headers[ 'Content-Type' ] = "application/json" + r.headers[ 'Accept-Encoding' ] = "application/json" + return r + +class API( object ): + def __init__( self, api_username, api_key, base = "https://fulcrm.org/api/v2/" ): + self.api_username = api_username + self.api_key = api_key + self.base = base + self.auth = TastypieAuth( self.api_username, self.api_key ) + + def make_request( self, url, data, method, _countdown = 3 ): + if not url.startswith( self.base ): + url = self.base + url + + method = { 'POST': requests.post, + 'PATCH': requests.patch, + 'GET': requests.get, + 'DELETE': requests.delete + }.get( method, requests.get ) + + try: + if data: + request = method( url, data = json.dumps( data ), auth = self.auth ) + else: + request = method( url, auth = self.auth ) + except requests.exceptions.ConnectionError: + if _countdown > 0: + time.sleep( 5 ** ( 3 - _countdown ) ) + return self.make_request( url, data, method, _countdown - 1 ) + else: + raise + if request.ok: + try: + return request.json() + except: + return None + else: + raise IOError( request.text ) + + def get_many( self, url, no_d = False ): + next = None + if no_d: + if "?" in url: + url = url + "&count=10" + else: + url = url + "?count=10" + else: + if "?" in url: + url = url + "&expand=d&count=10" + else: + url = url + "?expand=d&count=10" + if not url.startswith( self.base ): + url = self.base + url + while True: + result = self.make_request( url, None, 'GET' ) + if result: + if 'results' in result: + for object in result[ 'results' ]: + yield object + if 'next' in result: + next = result.get( 'next', None ) + if next: + url = next + else: + return + else: + return + +def ext_pillar( minion_id, p, **kw ): + pillar = {} + api = API( api_username = kw.get( 'username' ), api_key = kw.get( 'api_key' ) ) + for t in api.get_many( 'thing/?name=' + minion_id ): + pillar.update( t.get( 'd', {} ) ) + for t in api.get_many( 'thing/?passport__system=dev.provisioning.faelix.net&passport__passport=' + minion_id ): + pillar.update( t.get( 'd', {} ) ) + for t in api.get_many( 'thing/?passport__system=salt.faelix.net&passport__passport=' + minion_id ): + pillar.update( t.get( 'd', {} ) ) + return { 'fulcrm_thing': pillar }