Add support for rancher 1.6 API
- New ansible module to handle rancher API
- Setting up of the cattle db and log related options
to achieve lower space usage.
As of this moment it does what was intended:
- it setups new values for db and log related options
- it can be used for any other setting options
Change-Id: I25048469df0cb035cc6eac39740210cdfa175ada
Issue-ID: OOM-1681
Signed-off-by: Petr Ospalý <p.ospaly@partner.samsung.com>
diff --git a/ansible/library/rancher1_api.py b/ansible/library/rancher1_api.py
new file mode 100644
index 0000000..ce3df1b
--- /dev/null
+++ b/ansible/library/rancher1_api.py
@@ -0,0 +1,242 @@
+#!/usr/bin/python
+
+from ansible.module_utils.basic import AnsibleModule
+
+import requests
+import json
+import functools
+
+DOCUMENTATION = """
+---
+module: rancher1_api
+short_description: Client library for rancher API
+description:
+ - This module modifies a rancher 1.6 using it's API (v1).
+ - WIP, as of now it can only change a current value to a new one.
+
+options:
+ rancher:
+ description:
+ - The domain name or the IP address and the port of the rancher
+ where API is exposed.
+ - For example: http://10.0.0.1:8080
+ required: true
+ aliases:
+ - server
+ - rancher_url
+ - rancher_api
+ - api
+ - url
+ category:
+ description:
+ - The path in JSON API without the last element.
+ required: false
+ default: settings
+ aliases:
+ - rancher_category
+ - api_category
+ option:
+ description:
+ - The name of the settings option.
+ required: true
+ aliases:
+ - name
+ - key
+ - settings
+ value:
+ description:
+ - A new value to replace the current one.
+ required: true
+ timeout:
+ description:
+ - How long in seconds to wait for a response before raising error
+ required: false
+ default: 10.0
+"""
+
+
+def _decorate_rancher_api_request(request_method):
+
+ @functools.wraps(request_method)
+ def wrap_request(*args, **kwargs):
+
+ response = request_method(*args, **kwargs)
+
+ if response.status_code != requests.codes.ok:
+ response.raise_for_status()
+
+ try:
+ json_data = response.json()
+ except Exception:
+ json_data = None
+
+ return json_data
+
+ return wrap_request
+
+
+@_decorate_rancher_api_request
+def get_rancher_api_value(url, headers=None, timeout=10.0,
+ username=None, password=None):
+
+ if username and password:
+ return requests.get(url, headers=headers,
+ timeout=timeout,
+ allow_redirects=False,
+ auth=(username, password))
+ else:
+ return requests.get(url, headers=headers,
+ timeout=timeout,
+ allow_redirects=False)
+
+
+@_decorate_rancher_api_request
+def set_rancher_api_value(url, payload, headers=None, timeout=10.0,
+ username=None, password=None):
+
+ if username and password:
+ return requests.put(url, headers=headers,
+ timeout=timeout,
+ allow_redirects=False,
+ data=json.dumps(payload),
+ auth=(username, password))
+ else:
+ return requests.put(url, headers=headers,
+ timeout=timeout,
+ allow_redirects=False,
+ data=json.dumps(payload))
+
+
+def create_rancher_api_payload(json_data, new_value):
+
+ payload = {}
+
+ try:
+ api_id = json_data['id']
+ api_activeValue = json_data['activeValue']
+ api_name = json_data['name']
+ api_source = json_data['source']
+ except Exception:
+ raise ValueError
+
+ payload.update({"activeValue": api_activeValue,
+ "id": api_id,
+ "name": api_name,
+ "source": api_source,
+ "value": new_value})
+
+ if api_activeValue != new_value:
+ differs = True
+ else:
+ differs = False
+
+ return differs, payload
+
+
+def is_valid_rancher_api_option(json_data):
+
+ try:
+ api_activeValue = json_data['activeValue']
+ api_source = json_data['source']
+ except Exception:
+ return False
+
+ if api_activeValue is None and api_source is None:
+ return False
+
+ return True
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ rancher=dict(type='str', required=True,
+ aliases=['server',
+ 'rancher_api',
+ 'rancher_url',
+ 'api',
+ 'url']),
+ category=dict(type='str', default='settings',
+ aliases=['rancher_category', 'api_category']),
+ option=dict(type='str', required=True,
+ aliases=['name', 'key', 'settings']),
+ value=dict(type='str', required=True),
+ timeout=dict(type='float', default=10.0),
+ ),
+ supports_check_mode=True
+ )
+
+ rancher_url = module.params['rancher'].strip('/')
+ rancher_option = module.params['option'].strip('/')
+ rancher_category = module.params['category']
+ rancher_value = module.params['value']
+ rancher_timeout = module.params['timeout']
+ # cattle_access_key = ''
+ # cattle_secret_key = ''
+
+ # Assemble API url
+ request_url = rancher_url + '/v1/' + rancher_category + '/' \
+ + rancher_option
+
+ http_headers = {'Content-Type': 'application/json',
+ 'Accept': 'application/json'}
+
+ # API get current value
+ try:
+ json_response = get_rancher_api_value(request_url,
+ headers=http_headers,
+ timeout=rancher_timeout)
+ except requests.HTTPError as e:
+ module.fail_json(msg=str(e))
+ except requests.Timeout as e:
+ module.fail_json(msg=str(e))
+
+ if not json_response:
+ module.fail_json(msg='ERROR: BAD RESPONSE (GET) - no json value \
+ in the response')
+
+ if is_valid_rancher_api_option(json_response):
+ valid = True
+ try:
+ differs, payload = create_rancher_api_payload(json_response,
+ rancher_value)
+ except ValueError:
+ module.fail_json(msg='ERROR: INVALID JSON - missing json values \
+ in the response')
+ else:
+ valid = False
+
+ if valid and differs and module.check_mode:
+ # ansible dry-run mode
+ changed = True
+ elif valid and differs:
+ # API set new value
+ try:
+ json_response = set_rancher_api_value(request_url,
+ payload,
+ headers=http_headers,
+ timeout=rancher_timeout)
+ except requests.HTTPError as e:
+ module.fail_json(msg=str(e))
+ except requests.Timeout as e:
+ module.fail_json(msg=str(e))
+
+ if not json_response:
+ module.fail_json(msg='ERROR: BAD RESPONSE (PUT) - no json value \
+ in the response')
+ else:
+ changed = True
+ else:
+ changed = False
+
+ if changed:
+ msg = "Option '%s' is now set to the new value: %s" \
+ % (rancher_option, rancher_value)
+ else:
+ msg = "Option '%s' is unchanged." % (rancher_option)
+
+ module.exit_json(changed=changed, msg=msg)
+
+
+if __name__ == '__main__':
+ main()