diff --git a/lib/puppet/provider/grafana_user/grafana.rb b/lib/puppet/provider/grafana_user/grafana.rb index 56d9d4d2..61d99b4b 100644 --- a/lib/puppet/provider/grafana_user/grafana.rb +++ b/lib/puppet/provider/grafana_user/grafana.rb @@ -5,9 +5,12 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'grafana')) Puppet::Type.type(:grafana_user).provide(:grafana, parent: Puppet::Provider::Grafana) do - desc 'Support for Grafana users' + desc 'Manages local Grafana users' - defaultfor kernel: 'Linux' + def initialize(value = {}) + super(value) + @property_flush = {} + end def users response = send_request('GET', format('%s/users', resource[:grafana_api_path])) @@ -48,8 +51,7 @@ def name end def name=(value) - resource[:name] = value - save_user + @property_flush[:login] = value end def full_name @@ -57,8 +59,7 @@ def full_name end def full_name=(value) - resource[:full_name] = value - save_user + @property_flush[:name] = value end def email @@ -66,8 +67,7 @@ def email end def email=(value) - resource[:email] = value - save_user + @property_flush[:email] = value end def theme @@ -75,8 +75,7 @@ def theme end def theme=(value) - resource[:theme] = value - save_user + @property_flush[:theme] = value end def password @@ -84,43 +83,50 @@ def password end def password=(value) - resource[:password] = value - save_user + @property_flush[:password] = value end - # rubocop:disable Style/PredicateName + # rubocop:disable Naming/PredicateName def is_admin user[:is_admin] end def is_admin=(value) - resource[:is_admin] = value - save_user + @property_flush[:is_admin] = value end - # rubocop:enable Style/PredicateName + # rubocop:enable Naming/PredicateName - def save_user - data = { - login: resource[:name], - name: resource[:full_name], - email: resource[:email], - password: resource[:password], - theme: resource[:theme], - isGrafanaAdmin: (resource[:is_admin] == :true) - } - - if user.nil? - response = send_request('POST', format('%s/admin/users', resource[:grafana_api_path]), data) - else - data[:id] = user[:id] - send_request 'PUT', format('%s/admin/users/%s/password', resource[:grafana_api_path], user[:id]), password: data.delete(:password) - send_request 'PUT', format('%s/admin/users/%s/permissions', resource[:grafana_api_path], user[:id]), isGrafanaAdmin: data.delete(:isGrafanaAdmin) + def flush + if @property_flush[:ensure] == :absent + delete_user + return + end + + password = @property_flush.delete(:password) + is_admin = @property_flush.delete(:is_admin) + + unless @property_flush.empty? + debug('Updating user properties') + + # If we don't include the login name, and email is being updated, then login will be reset to match the email address! + data = @property_flush.merge({ login: resource[:name] }) response = send_request('PUT', format('%s/users/%s', resource[:grafana_api_path], user[:id]), data) + raise format('Failed to update properties for user %s (HTTP response: %s/%s', resource[:name], response.code, response.body) if response.code != '200' end - raise format('Failed to create user %s (HTTP response: %s/%s)', resource[:name], response.code, response.body) if response.code != '200' + if password + debug('Updating user password') + response = send_request 'PUT', format('%s/admin/users/%s/password', resource[:grafana_api_path], user[:id]), password: password + raise format('Failed to update password for user %s (HTTP response: %s/%s', resource[:name], response.code, response.body) if response.code != '200' + end - self.user = nil + update_admin_flag(is_admin) unless is_admin.nil? + end + + def update_admin_flag(is_admin) + debug("Setting isGrafanaAdmin to #{is_admin}") + response = send_request 'PUT', format('%s/admin/users/%s/permissions', resource[:grafana_api_path], user[:id]), isGrafanaAdmin: (is_admin == :true) + raise format('Failed to update isGrafanaAdmin for user %s (HTTP response: %s/%s', resource[:name], response.code, response.body) if response.code != '200' end def check_password @@ -146,11 +152,29 @@ def delete_user end def create - save_user + data = { + login: resource[:name], + name: resource[:full_name], + email: resource[:email], + theme: resource[:theme], + password: resource[:password] || random_password, + }.compact + + debug('Creating user') + + response = send_request('POST', format('%s/admin/users', resource[:grafana_api_path]), data) + raise format('Failed to create user %s (HTTP response: %s/%s)', resource[:name], response.code, response.body) if response.code != '200' + + update_admin_flag(resource[:is_admin]) unless resource[:is_admin].nil? + end + + def random_password + require 'securerandom' + SecureRandom.hex(64) end def destroy - delete_user + @property_flush[:ensure] = :absent end def exists? diff --git a/lib/puppet/type/grafana_user.rb b/lib/puppet/type/grafana_user.rb index ca5b9b21..28fcbb57 100644 --- a/lib/puppet/type/grafana_user.rb +++ b/lib/puppet/type/grafana_user.rb @@ -35,7 +35,7 @@ desc 'The password for the Grafana server' end - newparam(:full_name) do + newproperty(:full_name) do desc 'The full name of the user.' end @@ -57,7 +57,6 @@ def insync?(_is) newproperty(:is_admin) do desc 'Whether the user is a grafana admin' newvalues(:true, :false) - defaultto :false end def set_sensitive_parameters(sensitive_parameters) # rubocop:disable Naming/AccessorMethodName