summaryrefslogtreecommitdiff
diff options
authorBrad Marshall <brad.marshall@canonical.com>2017-11-21 16:38:36 +1000
committerBrad Marshall <brad.marshall@canonical.com>2017-11-21 16:38:36 +1000
commit12f9a02e92cf18809f5b531898f2fdc151a3fa70 (patch)
treeb7f20f5eb7be59772a80c3c096856e31a75766d1
parent2bf4bbf7c439f4c1c6cc2fa39003b1a08f068973 (diff)
[brad-marshall, r=tcuthbert] Merge branch 'action-user-mgmt' of git+ssh://git.launchpad.net/~brad-marshall/grafana-charm
-rw-r--r--README.md35
-rw-r--r--actions.yaml50
-rwxr-xr-xactions/change-user-role78
-rwxr-xr-xactions/create-api-key4
-rwxr-xr-xactions/create-user129
-rwxr-xr-xactions/delete-user68
-rwxr-xr-xactions/import-dashboard23
-rwxr-xr-xactions/set-user-password78
8 files changed, 449 insertions, 16 deletions
diff --git a/README.md b/README.md
index a298909..e282e84 100644
--- a/README.md
+++ b/README.md
@@ -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)