influxdb2 plugins
This commit is contained in:
147
roles/cobald/library/influx_dashboard.py
Executable file
147
roles/cobald/library/influx_dashboard.py
Executable file
@@ -0,0 +1,147 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: influx2_dashboard
|
||||||
|
short_description: create dashboard in influxdb2
|
||||||
|
description: create dashboard in influxdb2
|
||||||
|
notes:
|
||||||
|
- just works with influxdb version 2
|
||||||
|
- does not create dashboard description
|
||||||
|
- does not update dashboards
|
||||||
|
- just creates a dashboard if it does not exist.
|
||||||
|
|
||||||
|
options:
|
||||||
|
base:
|
||||||
|
description: URL for path, e.g. `https://localhost:8086`
|
||||||
|
type: str
|
||||||
|
required: True
|
||||||
|
org:
|
||||||
|
description: influxdb2 organisation
|
||||||
|
type: str
|
||||||
|
required: True
|
||||||
|
token:
|
||||||
|
description: influxdb2 authentication token
|
||||||
|
type: str
|
||||||
|
required: True
|
||||||
|
data:
|
||||||
|
description: exported dashboard json file
|
||||||
|
type: json
|
||||||
|
required: True
|
||||||
|
force:
|
||||||
|
description: force creation even if dashboard already exists
|
||||||
|
(adds a new one)
|
||||||
|
type: bool
|
||||||
|
required: False
|
||||||
|
default: False
|
||||||
|
author:
|
||||||
|
- Thorsten M. (@thoto)
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
- name: "fetch auth token"
|
||||||
|
raw: influx auth list --user my-user --hide-headers | cut -f 3
|
||||||
|
register: influx_token_fetch
|
||||||
|
delegate_to: ed-influxdb-2
|
||||||
|
|
||||||
|
- name: "create dashboard"
|
||||||
|
influx_dashboard:
|
||||||
|
base: "http://localhost:8086"
|
||||||
|
org: "my-org"
|
||||||
|
token: "{{influx_token_fetch.stdout_lines[0]}}"
|
||||||
|
data: "{{lookup('file', 'influxdb-dashboard-cobald.json')}}"
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def parse_dashboard_template(data):
|
||||||
|
j = json.loads(data)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'name': j["content"]["data"]["attributes"]["name"],
|
||||||
|
'cells': {i["relationships"]["view"]["data"]["id"]: i["attributes"]
|
||||||
|
for i in j["content"]["included"] if i["type"] == "cell"},
|
||||||
|
'views': {i["id"]: i["attributes"]
|
||||||
|
for i in j["content"]["included"] if i["type"] == "view"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_auth(base, org_name, token):
|
||||||
|
h = {"Authorization": "Token {token}".format(token=token)}
|
||||||
|
|
||||||
|
rm = requests.get("{base}/api/v2/me".format(base=base), headers=h)
|
||||||
|
rm.raise_for_status()
|
||||||
|
# me_name = rm.json()["name"]
|
||||||
|
me = rm.json()["id"]
|
||||||
|
|
||||||
|
ro = requests.get("{base}/api/v2/orgs".format(base=base), headers=h,
|
||||||
|
json={"userID": me})
|
||||||
|
ro.raise_for_status()
|
||||||
|
org_id = [o["id"] for o in ro.json()["orgs"] if o["name"] == org_name]
|
||||||
|
|
||||||
|
return {"org_id": org_id[0], "org_name": org_name, "uid": me, "h": h}
|
||||||
|
|
||||||
|
|
||||||
|
def check(base, auth, dashboard):
|
||||||
|
h = auth["h"]
|
||||||
|
rd = requests.get("{base}/api/v2/dashboards".format(base=base), headers=h)
|
||||||
|
rd.raise_for_status()
|
||||||
|
x = [i for i in rd.json()["dashboards"]
|
||||||
|
if i["name"] == dashboard["name"] and i["orgID"] == auth["org_id"]]
|
||||||
|
return len(x) == 0, x
|
||||||
|
|
||||||
|
|
||||||
|
def create(base, auth, dashboard):
|
||||||
|
h = auth["h"]
|
||||||
|
|
||||||
|
# create dashboard
|
||||||
|
rd = requests.post("{base}/api/v2/dashboards".format(base=base), headers=h,
|
||||||
|
json={"orgID": auth["org_id"],
|
||||||
|
"name": dashboard["name"]})
|
||||||
|
rd.raise_for_status()
|
||||||
|
dash_id = rd.json()["id"]
|
||||||
|
|
||||||
|
for k, v in dashboard["cells"].items():
|
||||||
|
# create cells in dashboard
|
||||||
|
rc = requests.post(
|
||||||
|
"{base}/api/v2/dashboards/{dash_id}/cells".format(
|
||||||
|
base=base, dash_id=dash_id),
|
||||||
|
headers=h, json=v)
|
||||||
|
rc.raise_for_status()
|
||||||
|
cell_id = rc.json()["id"]
|
||||||
|
|
||||||
|
# create view of cell in dashboard
|
||||||
|
rv = requests.patch(
|
||||||
|
"{base}/api/v2/dashboards/{dash_id}/cells/{cell_id}/view".format(
|
||||||
|
base=base, dash_id=dash_id, cell_id=cell_id),
|
||||||
|
headers=h, json=dashboard["views"][k])
|
||||||
|
rv.raise_for_status()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = dict(changed=False, message="")
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=dict(
|
||||||
|
base=dict(type="str", required=True),
|
||||||
|
org=dict(type="str", required=True),
|
||||||
|
token=dict(type="str", required=True),
|
||||||
|
data=dict(type="json", required=True),
|
||||||
|
force=dict(type="bool", default=False),
|
||||||
|
),
|
||||||
|
supports_check_mode=True
|
||||||
|
)
|
||||||
|
dashboard = parse_dashboard_template(module.params["data"])
|
||||||
|
auth = get_auth(module.params["base"], module.params["org"],
|
||||||
|
module.params["token"])
|
||||||
|
changed, x = check(module.params["base"], auth, dashboard)
|
||||||
|
|
||||||
|
result['changed'] = changed
|
||||||
|
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
if changed or module.params["force"]:
|
||||||
|
create(module.params["base"], auth, dashboard)
|
||||||
|
module.exit_json(**result)
|
200
roles/cobald/library/influx_token.py
Executable file
200
roles/cobald/library/influx_token.py
Executable file
@@ -0,0 +1,200 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import requests
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: influx2_dashboard
|
||||||
|
short_description: create dashboard in influxdb2
|
||||||
|
description: create dashboard in influxdb2
|
||||||
|
notes:
|
||||||
|
- just works with influxdb version 2
|
||||||
|
- does not create dashboard description
|
||||||
|
- does not update dashboards
|
||||||
|
- just creates a dashboard if it does not exist.
|
||||||
|
|
||||||
|
options:
|
||||||
|
base:
|
||||||
|
description: URL for path, e.g. `https://localhost:8086`
|
||||||
|
type: str
|
||||||
|
required: True
|
||||||
|
org:
|
||||||
|
description: influxdb2 organisation
|
||||||
|
type: str
|
||||||
|
required: True
|
||||||
|
token:
|
||||||
|
description: influxdb2 authentication token
|
||||||
|
type: str
|
||||||
|
required: True
|
||||||
|
data:
|
||||||
|
description: exported dashboard json file
|
||||||
|
type: json
|
||||||
|
required: True
|
||||||
|
force:
|
||||||
|
description: force creation even if dashboard already exists
|
||||||
|
(adds a new one)
|
||||||
|
type: bool
|
||||||
|
required: False
|
||||||
|
default: False
|
||||||
|
author:
|
||||||
|
- Thorsten M. (@thoto)
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
- name: "fetch auth token"
|
||||||
|
raw: influx auth list --user my-user --hide-headers | cut -f 3
|
||||||
|
register: influx_token_fetch
|
||||||
|
delegate_to: ed-influxdb-2
|
||||||
|
|
||||||
|
- name: "create dashboard"
|
||||||
|
influx_dashboard:
|
||||||
|
base: "http://localhost:8086"
|
||||||
|
org: "my-org"
|
||||||
|
token: "{{influx_token_fetch.stdout_lines[0]}}"
|
||||||
|
data: "{{lookup('file', 'influxdb-dashboard-cobald.json')}}"
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def get_org_id(base, org_name, h):
|
||||||
|
ro = requests.get("{base}/api/v2/orgs".format(base=base), headers=h,
|
||||||
|
json={"org": org_name})
|
||||||
|
ro.raise_for_status()
|
||||||
|
org_id = [o["id"] for o in ro.json()["orgs"] if o["name"] == org_name]
|
||||||
|
return org_id[0]
|
||||||
|
|
||||||
|
|
||||||
|
def marker(key):
|
||||||
|
return "__ANSIBLE_TOKEN_{key}__".format(key=key)
|
||||||
|
|
||||||
|
|
||||||
|
def _filter_perms(perms):
|
||||||
|
for r in perms:
|
||||||
|
r["resource"] = {k: v for k, v in r["resource"].items() if v}
|
||||||
|
return perms
|
||||||
|
|
||||||
|
|
||||||
|
class Token:
|
||||||
|
def __init__(self, base, h, data):
|
||||||
|
self.base = base
|
||||||
|
self.h = h
|
||||||
|
self.marker = marker(data["key"])
|
||||||
|
|
||||||
|
self.org_id = data["org_id"]
|
||||||
|
self.perms = _filter_perms(data["perms"])
|
||||||
|
self.description = data["description"]+" "+self.marker
|
||||||
|
|
||||||
|
self.result_token = None
|
||||||
|
self.f = None
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
ra = requests.get("{base}/api/v2/authorizations".format(
|
||||||
|
base=self.base),
|
||||||
|
params={"orgID": self.org_id},
|
||||||
|
headers=self.h)
|
||||||
|
ra.raise_for_status()
|
||||||
|
x = [i for i in ra.json()["authorizations"]
|
||||||
|
if self.marker in i["description"]
|
||||||
|
and i["orgID"] == self.org_id]
|
||||||
|
|
||||||
|
update = None
|
||||||
|
for i in x: # FIXME: one loop
|
||||||
|
if self._match_perms(self.perms, i["permissions"]):
|
||||||
|
if self.description == i["description"]:
|
||||||
|
self.result_token = i
|
||||||
|
return False # everything matches -> no change needed
|
||||||
|
else:
|
||||||
|
self.result_token = i
|
||||||
|
update = {"auth_id": i["id"],
|
||||||
|
"description": self.description}
|
||||||
|
# TODO: may remove token because permissions do not match?
|
||||||
|
if update:
|
||||||
|
self.f = lambda: self._update(**update)
|
||||||
|
else:
|
||||||
|
self.result_token = None
|
||||||
|
self.f = lambda: self._create({
|
||||||
|
"orgID": self.org_id, # "permissions": self.perms,
|
||||||
|
"description": self.description,
|
||||||
|
"permissions": self.perms
|
||||||
|
})
|
||||||
|
return True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not self.f:
|
||||||
|
self.check()
|
||||||
|
ra = self.f()
|
||||||
|
|
||||||
|
def _match_perms(self, pa, pb):
|
||||||
|
a = pa.copy()
|
||||||
|
b = pb.copy()
|
||||||
|
for i in a:
|
||||||
|
try:
|
||||||
|
b.remove(i)
|
||||||
|
except ValueError:
|
||||||
|
return False # permission i not present in b
|
||||||
|
|
||||||
|
if b: # not empty
|
||||||
|
return False # some permissions in b not in a
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _update(self, auth_id, description):
|
||||||
|
ra = requests.patch(
|
||||||
|
"{base}/api/v2/authorizations/{auth_id}".format(
|
||||||
|
base=self.base, auth_id=auth_id),
|
||||||
|
headers=self.h, json={"description": description})
|
||||||
|
ra.raise_for_status()
|
||||||
|
return ra
|
||||||
|
|
||||||
|
def _create(self, data):
|
||||||
|
ra = requests.post("{base}/api/v2/authorizations".format(
|
||||||
|
base=self.base),
|
||||||
|
headers=self.h, json=data)
|
||||||
|
ra.raise_for_status()
|
||||||
|
self.result_token = ra.json()
|
||||||
|
return ra
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = dict(changed=False, message="")
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=dict(
|
||||||
|
base=dict(type="str", required=True),
|
||||||
|
org=dict(type="str", required=True),
|
||||||
|
auth_token=dict(type="str", required=True),
|
||||||
|
key=dict(type="str", required=True),
|
||||||
|
description=dict(type="str", default=""),
|
||||||
|
permissions=dict(type="list", elements='dict', options=dict(
|
||||||
|
action=dict(type='str', choices=['read', 'write'],
|
||||||
|
required=True),
|
||||||
|
resource=dict(type='dict', options=dict(
|
||||||
|
id=dict(type='str'),
|
||||||
|
name=dict(type='str'),
|
||||||
|
org=dict(type='str'),
|
||||||
|
orgID=dict(type='str'),
|
||||||
|
type=dict(type='str', required=True),
|
||||||
|
), required=True),
|
||||||
|
), required=True),
|
||||||
|
force=dict(type="bool", default=False),
|
||||||
|
),
|
||||||
|
supports_check_mode=True
|
||||||
|
)
|
||||||
|
h = {"Authorization": "Token {token}".format(
|
||||||
|
token=module.params["auth_token"])}
|
||||||
|
t = Token(module.params["base"], h, {
|
||||||
|
"org_id": get_org_id(module.params["base"], module.params["org"], h),
|
||||||
|
"key": module.params["key"],
|
||||||
|
# "perms": [{"action": "write", "resource": { "type": "buckets"}}],
|
||||||
|
"perms": module.params["permissions"],
|
||||||
|
"description": module.params["description"]})
|
||||||
|
|
||||||
|
changed = t.check()
|
||||||
|
if t.result_token:
|
||||||
|
result['token'] = t.result_token["token"]
|
||||||
|
result['changed'] = changed
|
||||||
|
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
if changed or module.params["force"]:
|
||||||
|
t.run()
|
||||||
|
result['token'] = t.result_token["token"]
|
||||||
|
module.exit_json(**result)
|
Reference in New Issue
Block a user