diff options
| author | Brad Marshall <brad.marshall@canonical.com> | 2017-11-21 16:38:36 +1000 |
|---|---|---|
| committer | Brad Marshall <brad.marshall@canonical.com> | 2017-11-21 16:38:36 +1000 |
| commit | 12f9a02e92cf18809f5b531898f2fdc151a3fa70 (patch) | |
| tree | b7f20f5eb7be59772a80c3c096856e31a75766d1 | |
| parent | 2bf4bbf7c439f4c1c6cc2fa39003b1a08f068973 (diff) | |
[brad-marshall, r=tcuthbert] Merge branch 'action-user-mgmt' of git+ssh://git.launchpad.net/~brad-marshall/grafana-charm
| -rw-r--r-- | README.md | 35 | ||||
| -rw-r--r-- | actions.yaml | 50 | ||||
| -rwxr-xr-x | actions/change-user-role | 78 | ||||
| -rwxr-xr-x | actions/create-api-key | 4 | ||||
| -rwxr-xr-x | actions/create-user | 129 | ||||
| -rwxr-xr-x | actions/delete-user | 68 | ||||
| -rwxr-xr-x | actions/import-dashboard | 23 | ||||
| -rwxr-xr-x | actions/set-user-password | 78 |
8 files changed, 449 insertions, 16 deletions
@@ -10,10 +10,10 @@ This charm provides the latest stable version of Grafana. Above will automatically configure prometheus as grafana datasource If admin password is not set using configuration option it is autogenerated. + To retrieve autogenerated password run: $ juju run-action --wait grafana/0 get-admin-password - #Actions This charm supports importing dashboards, simply run: @@ -33,10 +33,41 @@ There is also an action to create an API key, run: where the keyrole is one of Viewer, Editor, Read Only Editor or Admin. -You can also retrieve the admin password, via: +##User Management Actions + +Currently user management is only implemented to manipulate users in the default +organisation. + +You can retrieve the admin password, via: $ juju run-action --wait grafana/0 get-admin-password +You can create a user: + + $ juju run-action -w grafana/0 create-user name="John Citizen" \ + email="john@example.com" login="john" password="redacted" \ + role="Viewer" + +where the role is one of Viewer, Editor, Read Only Editor or Admin. +This will create the user in the default organisation. + +To reset a user's password: + + $ juju run-action --wait grafana/0 set-user-password \ + login=john new-password=citizen2 + +This again assumes the user is in the default organisation, if it +isn't it won't find the user. + +If you need to change the user's role, run: + + $ juju run-action --wait grafana/0 change-user-role login="john" \ + new-role="Admin" + +To delete a user, you simply run: + + $ juju run-action --wait grafana/0 delete-user login=john + #Development Explicitly set `JUJU_REPOSITORY`: diff --git a/actions.yaml b/actions.yaml index de14f9b..81b8a67 100644 --- a/actions.yaml +++ b/actions.yaml @@ -19,3 +19,53 @@ create-api-key: description: Role for key, one of Viewer, Editor, Read Only Editor or Admin required: [keyname, keyrole] additionalProperties: false +create-user: + description: Create an user + params: + name: + type: string + description: Name of user to be created + email: + type: string + description: Email of user to be created + login: + type: string + description: Login of user to be created + password: + type: string + description: Password of user to be created + role: + type: string + description: role of user to be created, one of Viewer, Editor, Read Only Editor or Admin + required: [name, email, login, password, role] + additionalProperties: false +set-user-password: + description: Set the password for a user + params: + login: + type: string + description: Login of user to change password for + new-password: + type: string + description: New password to use + required: [login, new-password] + additionalProperties: false +delete-user: + description: Delete the user + params: + login: + type: string + description: Login of user to delete + required: [login] + additionalProperties: false +change-user-role: + description: Set the role of the user + params: + login: + type: string + description: Login of user to change role for + new-role: + type: string + description: New role to use, one of Viewer, Editor, Read Only Editor or Admin + required: [login, new-role] + additionalProperties: false diff --git a/actions/change-user-role b/actions/change-user-role new file mode 100755 index 0000000..ca469ce --- /dev/null +++ b/actions/change-user-role @@ -0,0 +1,78 @@ +#!/usr/bin/python3 +# Creates a user in grafana + +import requests +import json +import sys +from charmhelpers.core.hookenv import ( + config, + action_fail, + action_set, + action_get, + log, +) + +from grafana_utils import get_admin_password + +action = "change-user-role" + +admin_passwd = get_admin_password() + +if admin_passwd is None: + action_fail('Unable to retrieve password.') + sys.exit(0) + +port = config('port') +grafana = "http://localhost:%s" % (port) +api_auth = ('admin', admin_passwd) + +login = action_get('login') + +api_lookup_user_url = "/api/users/lookup?loginOrEmail=%s" % login + +grafana_api_user_lookup_url = grafana + api_lookup_user_url + +if requests.utils.urlparse(grafana_api_user_lookup_url).scheme: + r_user = requests.get( + grafana_api_user_lookup_url, + auth=api_auth + ) +else: + action_fail("Grafana url %s failed to parse" % (grafana_api_user_lookup_url)) + sys.exit(0) + +if r_user.status_code == 200: + user_data = json.loads(r_user.text) + user_id = user_data['id'] + + # http://docs.grafana.org/http_api/org/#updates-the-given-user + api_change_role_url = "/api/org/users/%s" % user_id + # Needs the following json posted to it: + # { "role": "Viewer", } + + new_role = action_get('new-role') + user_data = {'role': new_role} + + headers = {'Content-Type': 'application/json'} + + grafana_api_change_role_url = grafana + api_change_role_url + + if requests.utils.urlparse(grafana_api_change_role_url).scheme: + r_passwd = requests.patch( + grafana_api_change_role_url, + auth=api_auth, + headers=headers, + data=json.dumps(user_data) + ) + else: + action_fail("Grafana url %s failed to parse" % (grafana_api_change_role_url)) + sys.exit(0) + + if r_passwd.status_code == 200: + action_set({"changed-role": login}) + else: + action_fail("User %s failed to set password" % (login)) + log("Failed to set password") + sys.exit(0) +else: + action_fail("Can't find user %s" % (login)) diff --git a/actions/create-api-key b/actions/create-api-key index 44427a4..433cbd3 100755 --- a/actions/create-api-key +++ b/actions/create-api-key @@ -4,6 +4,7 @@ import requests import json from charmhelpers.core.hookenv import ( + config, action_fail, action_set, action_get, @@ -20,7 +21,8 @@ if passwd is None: roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin'] -grafana = "http://localhost:3000" +port = config('port') +grafana = "http://localhost:%s" % (port) api_auth = ('admin', passwd) key_name = action_get('keyname') key_role = action_get('keyrole') diff --git a/actions/create-user b/actions/create-user new file mode 100755 index 0000000..2ec26bc --- /dev/null +++ b/actions/create-user @@ -0,0 +1,129 @@ +#!/usr/bin/python3 +# Creates a user in grafana + +import requests +import json +import sys +from charmhelpers.core.hookenv import ( + config, + action_fail, + action_set, + action_get, + log, +) + +from grafana_utils import get_admin_password + +action = "create-user" + +admin_passwd = get_admin_password() + +if admin_passwd is None: + action_fail('Unable to retrieve password.') + sys.exit(0) + +port = config('port') +grafana = "http://localhost:%s" % (port) +api_auth = ('admin', admin_passwd) + +# http://docs.grafana.org/http_api/admin/#global-users +api_create_user_url = "/api/admin/users" +# Needs the following json posted to it: +# { +# "name":"User", +# "email":"user@graf.com", +# "login":"user", +# "password":"userpassword" +# } + +name = action_get('name') +email = action_get('email') +login = action_get('login') +user_password = action_get('password') +user_role = action_get('role') + +valid_roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin'] +if user_role not in valid_roles: + action_fail("Role %s isn't valid, needs to be one of %s" % (user_role, valid_roles)) + sys.exit(0) + +user_data = { + 'name': name, + 'email': email, + 'login': login, + 'password': user_password +} + +headers = {'Content-Type': 'application/json'} + +grafana_api_create_user_url = grafana + api_create_user_url + +if requests.utils.urlparse(grafana_api_create_user_url).scheme: + r_create = requests.post( + grafana_api_create_user_url, + auth=api_auth, + headers=headers, + data=json.dumps(user_data) + ) +else: + action_fail("Grafana url %s failed to parse!" % (grafana_api_create_user_url)) + sys.exit(0) + +if r_create.status_code == 200: + action_set({"created": login}) +else: + action_fail("User %s failed to create" % (login)) + sys.exit(0) + +# http://docs.grafana.org/http_api/org/#get-organisation-by-id +api_org_url = "/api/orgs/1" + +# http://docs.grafana.org/http_api/org/#add-a-new-user-to-the-actual-organisation +api_org_user_url = "/api/org/users" +# { +# "role": "Admin", +# "loginOrEmail": "admin" +# } + +grafana_api_org_url = grafana + api_org_url + +if requests.utils.urlparse(grafana_api_org_url).scheme: + r_org = requests.get( + grafana_api_org_url, + auth=api_auth + ) +else: + action_fail("Grafana url %s failed to parse" % (grafana_api_org_url)) + sys.exit(0) + +if r_org.status_code == 200: + org_data = r_org.json + org_id = org_data['id'] + org_name = org_data['name'] + org_user_data = '''{ +"role": %s, +"loginOrEmail": %s +}''' % (user_role, login) + + grafana_api_org_user_url = grafana + api_org_user_url + + if requests.utils.urlparse(grafana_api_org_user_url).scheme: + r_userorg = requests.post( + grafana_api_org_user_url, + auth=api_auth, + headers=headers, + data=json.dumps(org_user_data) + ) + else: + action_fail("Grafana url %s failed to parse" % (grafana_api_org_user_url)) + sys.exit(0) + + if r_userorg.status_code == 200: + action_set({"organisation_name": org_name}) + action_set({"organisation_role": user_role}) + else: + action_fail("Failed to add user to organisation") + sys.exit(0) +else: + action_fail("Failed to retrieve organisation details") + sys.exit(0) diff --git a/actions/delete-user b/actions/delete-user new file mode 100755 index 0000000..33d4126 --- /dev/null +++ b/actions/delete-user @@ -0,0 +1,68 @@ +#!/usr/bin/python3 +# Deletes a user in grafana + +import requests +import json +import sys +from charmhelpers.core.hookenv import ( + config, + action_fail, + action_set, + action_get, + log, +) + +from grafana_utils import get_admin_password + +action = "delete-user" + +admin_passwd = get_admin_password() + +if admin_passwd is None: + action_fail('Unable to retrieve password.') + sys.exit(0) + +port = config('port') +grafana = "http://localhost:%s" % (port) +api_auth = ('admin', admin_passwd) + +login = action_get('login') + +api_lookup_user_url = "/api/users/lookup?loginOrEmail=%s" % login + +grafana_api_lookup_user_url = grafana + api_lookup_user_url + +if requests.utils.urlparse(grafana_api_lookup_user_url).scheme: + r_user = requests.get( + grafana_api_lookup_user_url, + auth=api_auth + ) +else: + action_fail("Grafana url %s failed to parse" % (grafana_api_lookup_user_url)) + sys.exit(0) + +if r_user.status_code == 200: + user_data = json.loads(r_user.text) + user_id = user_data['id'] + + # http://docs.grafana.org/http_api/admin/#delete-global-user + api_delete_user_url = "/api/admin/users/%s" % user_id + + grafana_api_delete_user_url = grafana + api_delete_user_url + + if requests.utils.urlparse(grafana_api_delete_user_url).scheme: + r_delete = requests.delete( + grafana_api_delete_user_url, + auth=api_auth + ) + else: + action_fail("Grafana url %s failed to parse" % (grafana_api_delete_user_url)) + sys.exit(0) + + if r_delete.status_code == 200: + action_set({"delete-user": login}) + else: + action_fail("User %s failed to delete" % (login)) + sys.exit(0) +else: + action_fail("Can't find user %s" % (login)) diff --git a/actions/import-dashboard b/actions/import-dashboard index 2f0854f..d9e3477 100755 --- a/actions/import-dashboard +++ b/actions/import-dashboard @@ -5,30 +5,27 @@ import requests import json import base64 import traceback +import sys from charmhelpers.core.hookenv import ( + config, action_fail, action_set, action_get, - config, log, ) -from charmhelpers.core import unitdata +from grafana_utils import get_admin_password action = "import-dashboard" -kv = unitdata.kv() -if kv.get('grafana.admin_password'): - # print('Admin password: {}'.format(kv.get('grafana.admin_password'))) - passwd = kv.get('grafana.admin_password') -elif config('admin_password'): - passwd = config('admin_password') - # print('Admin password: {}'.format(config('admin_password'))) -else: - action_fail('ERROR! Unable to retrieve password.') - exit(0) +passwd = get_admin_password() + +if passwd is None: + action_fail('Unable to retrieve password.') + sys.exit(0) -grafana = "http://localhost:3000" +port = config('port') +grafana = "http://localhost:%s" % (port) api_auth = ('admin', passwd) api_dash_import_url = "/api/dashboards/import" try: diff --git a/actions/set-user-password b/actions/set-user-password new file mode 100755 index 0000000..7c06937 --- /dev/null +++ b/actions/set-user-password @@ -0,0 +1,78 @@ +#!/usr/bin/python3 +# Creates a user in grafana + +import requests +import json +import sys +from charmhelpers.core.hookenv import ( + config, + action_fail, + action_set, + action_get, + log, +) + +from grafana_utils import get_admin_password + +action = "set-user-password" + +admin_passwd = get_admin_password() + +if admin_passwd is None: + action_fail('Unable to retrieve password.') + sys.exit(0) + +port = config('port') +grafana = "http://localhost:%s" % (port) +api_auth = ('admin', admin_passwd) + +login = action_get('login') + +api_lookup_user_url = "/api/users/lookup?loginOrEmail=%s" % login + +grafana_api_lookup_user_url = grafana + api_lookup_user_url + +if requests.utils.urlparse(grafana_api_lookup_user_url).scheme: + r_user = requests.get( + grafana_api_lookup_user_url, + auth=api_auth + ) +else: + action_fail("Grafana url %s failed to parse" % (grafana_api_lookup_user_url)) + sys.exit(0) + +if r_user.status_code == 200: + user_data = json.loads(r_user.text) + user_id = user_data['id'] + + # http://docs.grafana.org/http_api/admin/#password-for-user + api_change_pass_url = "/api/admin/users/%s/password" % user_id + + # Needs the following json posted to it: + # {"password":"userpassword"} + new_password = action_get('new-password') + user_data = {'password': new_password} + + headers = {'Content-Type': 'application/json'} + + grafana_api_change_pass_url = grafana + api_change_pass_url + + if requests.utils.urlparse(grafana_api_change_pass_url).scheme: + r_passwd = requests.put( + grafana_api_change_pass_url, + auth=api_auth, + headers=headers, + data=json.dumps(user_data) + ) + else: + action_fail("Grafana url %s failed to parse" % (grafana_api_change_pass_url)) + sys.exit(0) + + if r_passwd.status_code == 200: + action_set({"changed-password": login}) + else: + action_fail("User %s failed to set password" % (login)) + sys.exit(0) +else: + action_fail("Can't find user %s" % (login)) + sys.exit(0) |
