diff --git a/lib/puppet/provider/grafana_datasource/grafana.rb b/lib/puppet/provider/grafana_datasource/grafana.rb index d94a8b1..35e66c7 100644 --- a/lib/puppet/provider/grafana_datasource/grafana.rb +++ b/lib/puppet/provider/grafana_datasource/grafana.rb @@ -1,267 +1,267 @@ # frozen_string_literal: true # Copyright 2015 Mirantis, Inc. # require 'json' require File.expand_path(File.join(File.dirname(__FILE__), '..', 'grafana')) Puppet::Type.type(:grafana_datasource).provide(:grafana, parent: Puppet::Provider::Grafana) do desc 'Support for Grafana datasources' defaultfor kernel: 'Linux' def organization resource[:organization] end def grafana_api_path resource[:grafana_api_path] end def fetch_organizations response = send_request('GET', format('%s/orgs', resource[:grafana_api_path])) raise format('Fail to retrieve organizations (HTTP response: %s/%s)', response.code, response.body) if response.code != '200' begin fetch_organizations = JSON.parse(response.body) fetch_organizations.map { |x| x['id'] }.map do |id| response = send_request 'GET', format('%s/orgs/%s', resource[:grafana_api_path], id) raise format('Failed to retrieve organization %d (HTTP response: %s/%s)', id, response.code, response.body) if response.code != '200' fetch_organization = JSON.parse(response.body) { id: fetch_organization['id'], name: fetch_organization['name'] } end rescue JSON::ParserError raise format('Failed to parse response: %s', response.body) end end def fetch_organization @fetch_organization ||= if resource[:organization].is_a?(Numeric) || resource[:organization].match(%r{^[0-9]*$}) fetch_organizations.find { |x| x[:id] == resource[:organization] } else fetch_organizations.find { |x| x[:name] == resource[:organization] } end @fetch_organization end def datasources response = send_request('GET', format('%s/datasources', resource[:grafana_api_path])) raise format('Fail to retrieve datasources (HTTP response: %s/%s)', response.code, response.body) if response.code != '200' begin datasources = JSON.parse(response.body) datasources.map { |x| x['id'] }.map do |id| response = send_request 'GET', format('%s/datasources/%s', resource[:grafana_api_path], id) raise format('Failed to retrieve datasource %d (HTTP response: %s/%s)', id, response.code, response.body) if response.code != '200' datasource = JSON.parse(response.body) { id: datasource['id'], name: datasource['name'], url: datasource['url'], type: datasource['type'], user: datasource['user'], password: datasource['password'], database: datasource['database'], access_mode: datasource['access'], - is_default: datasource['isDefault'] ? true : false, - with_credentials: datasource['withCredentials'] ? true : false, - basic_auth: datasource['basicAuth'] ? true : false, + is_default: datasource['isDefault'] ? :true : :false, + with_credentials: datasource['withCredentials'] ? :true : :false, + basic_auth: datasource['basicAuth'] ? :true : :false, basic_auth_user: datasource['basicAuthUser'], basic_auth_password: datasource['basicAuthPassword'], json_data: datasource['jsonData'], secure_json_data: datasource['secureJsonData'] } end rescue JSON::ParserError raise format('Failed to parse response: %s', response.body) end end def datasource @datasource ||= datasources.find { |x| x[:name] == resource[:name] } @datasource end attr_writer :datasource def type datasource[:type] end def type=(value) resource[:type] = value save_datasource end def url datasource[:url] end def url=(value) resource[:url] = value save_datasource end def access_mode datasource[:access_mode] end def access_mode=(value) resource[:access_mode] = value save_datasource end def database datasource[:database] end def database=(value) resource[:database] = value save_datasource end def user datasource[:user] end def user=(value) resource[:user] = value save_datasource end def password datasource[:password] end def password=(value) resource[:password] = value save_datasource end - # rubocop:disable Naming/PredicateName + # rubocop:disable Style/PredicateName def is_default datasource[:is_default] end def is_default=(value) resource[:is_default] = value save_datasource end - # rubocop:enable Naming/PredicateName + # rubocop:enable Style/PredicateName def basic_auth datasource[:basic_auth] end def basic_auth=(value) resource[:basic_auth] = value save_datasource end def basic_auth_user datasource[:basic_auth_user] end def basic_auth_user=(value) resource[:basic_auth_user] = value save_datasource end def basic_auth_password datasource[:basic_auth_password] end def basic_auth_password=(value) resource[:basic_auth_password] = value save_datasource end def with_credentials datasource[:with_credentials] end def with_credentials=(value) resource[:with_credentials] = value save_datasource end def json_data datasource[:json_data] end def json_data=(value) resource[:json_data] = value save_datasource end def secure_json_data datasource[:secure_json_data] end def secure_json_data=(value) resource[:secure_json_data] = value save_datasource end def save_datasource # change organizations response = send_request 'POST', format('%s/user/using/%s', resource[:grafana_api_path], fetch_organization[:id]) raise format('Failed to switch to org %s (HTTP response: %s/%s)', fetch_organization[:id], response.code, response.body) unless response.code == '200' data = { name: resource[:name], type: resource[:type], url: resource[:url], access: resource[:access_mode], database: resource[:database], user: resource[:user], password: resource[:password], - isDefault: (resource[:is_default] == true), - basicAuth: (resource[:basic_auth] == true), + isDefault: (resource[:is_default] == :true), + basicAuth: (resource[:basic_auth] == :true), basicAuthUser: resource[:basic_auth_user], basicAuthPassword: resource[:basic_auth_password], - withCredentials: (resource[:with_credentials] == true), + withCredentials: (resource[:with_credentials] == :true), jsonData: resource[:json_data], secureJsonData: resource[:secure_json_data] } if datasource.nil? response = send_request('POST', format('%s/datasources', resource[:grafana_api_path]), data) else data[:id] = datasource[:id] response = send_request 'PUT', format('%s/datasources/%s', resource[:grafana_api_path], datasource[:id]), data end raise format('Failed to create save %s (HTTP response: %s/%s)', resource[:name], response.code, response.body) if response.code != '200' self.datasource = nil end def delete_datasource response = send_request 'DELETE', format('%s/datasources/%s', resource[:grafana_api_path], datasource[:id]) raise format('Failed to delete datasource %s (HTTP response: %s/%s', resource[:name], response.code, response.body) if response.code != '200' self.datasource = nil end def create save_datasource end def destroy delete_datasource end def exists? datasource end end diff --git a/lib/puppet/provider/grafana_notification/grafana.rb b/lib/puppet/provider/grafana_notification/grafana.rb index 4714951..1ca6664 100644 --- a/lib/puppet/provider/grafana_notification/grafana.rb +++ b/lib/puppet/provider/grafana_notification/grafana.rb @@ -1,140 +1,140 @@ # frozen_string_literal: true # Copyright 2015 Mirantis, Inc. # require 'json' require File.expand_path(File.join(File.dirname(__FILE__), '..', 'grafana')) Puppet::Type.type(:grafana_notification).provide(:grafana, parent: Puppet::Provider::Grafana) do desc 'Support for Grafana notifications' defaultfor kernel: 'Linux' def grafana_api_path resource[:grafana_api_path] end def notifications response = send_request('GET', format('%s/alert-notifications', resource[:grafana_api_path])) raise format('Fail to retrieve notifications (HTTP response: %s/%s)', response.code, response.body) if response.code != '200' begin notifications = JSON.parse(response.body) notifications.map { |x| x['id'] }.map do |id| response = send_request 'GET', format('%s/alert-notifications/%s', resource[:grafana_api_path], id) raise format('Failed to retrieve notification %d (HTTP response: %s/%s)', id, response.code, response.body) if response.code != '200' notification = JSON.parse(response.body) { id: notification['id'], name: notification['name'], type: notification['type'], - is_default: notification['isDefault'] ? true : false, - send_reminder: notification['sendReminder'] ? true : false, + is_default: notification['isDefault'] ? :true : :false, + send_reminder: notification['sendReminder'] ? :true : :false, frequency: notification['frequency'], settings: notification['settings'] } end rescue JSON::ParserError raise format('Failed to parse response: %s', response.body) end end def notification @notification ||= notifications.find { |x| x[:name] == resource[:name] } @notification end attr_writer :notification def type notification[:type] end def type=(value) resource[:type] = value save_notification end - # rubocop:disable Naming/PredicateName + # rubocop:disable Style/PredicateName def is_default notification[:is_default] end def is_default=(value) resource[:is_default] = value save_notification end def send_reminder notification[:send_reminder] end def send_reminder=(value) resource[:send_reminder] = value save_notification end - # rubocop:enable Naming/PredicateName + # rubocop:enable Style/PredicateName def frequency notification[:frequency] end def frequency=(value) resource[:frequency] = value save_notification end def settings notification[:settings] end def settings=(value) resource[:settings] = value save_notification end def save_notification data = { name: resource[:name], type: resource[:type], - isDefault: (resource[:is_default] == true), - sendReminder: (resource[:send_reminder] == true), + isDefault: (resource[:is_default] == :true), + sendReminder: (resource[:send_reminder] == :true), frequency: resource[:frequency], settings: resource[:settings] } if notification.nil? response = send_request('POST', format('%s/alert-notifications', resource[:grafana_api_path]), data) else data[:id] = notification[:id] response = send_request 'PUT', format('%s/alert-notifications/%s', resource[:grafana_api_path], notification[:id]), data end raise format('Failed to create save %s (HTTP response: %s/%s)', resource[:name], response.code, response.body) if response.code != '200' self.notification = nil end def delete_notification response = send_request 'DELETE', format('%s/alert-notifications/%s', resource[:grafana_api_path], notification[:id]) raise format('Failed to delete notification %s (HTTP response: %s/%s', resource[:name], response.code, response.body) if response.code != '200' self.notification = nil end def create save_notification end def destroy delete_notification end def exists? notification end end diff --git a/lib/puppet/provider/grafana_user/grafana.rb b/lib/puppet/provider/grafana_user/grafana.rb index 5892d5e..56d9d4d 100644 --- a/lib/puppet/provider/grafana_user/grafana.rb +++ b/lib/puppet/provider/grafana_user/grafana.rb @@ -1,159 +1,159 @@ # frozen_string_literal: true require 'json' 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' defaultfor kernel: 'Linux' def users response = send_request('GET', format('%s/users', resource[:grafana_api_path])) raise format('Fail to retrieve users (HTTP response: %s/%s)', response.code, response.body) if response.code != '200' begin users = JSON.parse(response.body) users.map { |x| x['id'] }.map do |id| response = send_request('GET', format('%s/users/%s', resource[:grafana_api_path], id)) raise format('Fail to retrieve user %d (HTTP response: %s/%s)', id, response.code, response.body) if response.code != '200' user = JSON.parse(response.body) { id: id, name: user['login'], full_name: user['name'], email: user['email'], theme: user['theme'], password: nil, - is_admin: user['isGrafanaAdmin'] ? true : false + is_admin: user['isGrafanaAdmin'] ? :true : :false } end rescue JSON::ParserError raise format('Fail to parse response: %s', response.body) end end def user @user ||= users.find { |x| x[:name] == resource[:name] } @user end attr_writer :user def name user[:name] end def name=(value) resource[:name] = value save_user end def full_name user[:full_name] end def full_name=(value) resource[:full_name] = value save_user end def email user[:email] end def email=(value) resource[:email] = value save_user end def theme user[:theme] end def theme=(value) resource[:theme] = value save_user end def password nil end def password=(value) resource[:password] = value save_user end - # rubocop:disable Naming/PredicateName + # rubocop:disable Style/PredicateName def is_admin user[:is_admin] end def is_admin=(value) resource[:is_admin] = value save_user end - # rubocop:enable Naming/PredicateName + # rubocop:enable Style/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) + 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) response = send_request('PUT', format('%s/users/%s', resource[:grafana_api_path], user[:id]), data) end raise format('Failed to create user %s (HTTP response: %s/%s)', resource[:name], response.code, response.body) if response.code != '200' self.user = nil end def check_password uri = URI.parse format('%s://%s:%d%s/dashboards/home', grafana_scheme, grafana_host, grafana_port, resource[:grafana_api_path]) request = Net::HTTP::Get.new(uri.to_s) request.content_type = 'application/json' request.basic_auth resource[:name], resource[:password] response = Net::HTTP.start(grafana_host, grafana_port, use_ssl: grafana_scheme == 'https', verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http| http.request(request) end response.code == '200' end def delete_user response = send_request('DELETE', format('%s/admin/users/%s', resource[:grafana_api_path], user[:id])) raise format('Failed to delete user %s (HTTP response: %s/%s', resource[:name], response.code, response.body) if response.code != '200' self.user = nil end def create save_user end def destroy delete_user end def exists? user end end diff --git a/lib/puppet/type/grafana_datasource.rb b/lib/puppet/type/grafana_datasource.rb index 6a76b33..d60b81e 100644 --- a/lib/puppet/type/grafana_datasource.rb +++ b/lib/puppet/type/grafana_datasource.rb @@ -1,130 +1,130 @@ # frozen_string_literal: true # Copyright 2015 Mirantis, Inc. # Puppet::Type.newtype(:grafana_datasource) do @doc = 'Manage datasources in Grafana' ensurable newparam(:name, namevar: true) do desc 'The name of the datasource.' end newparam(:grafana_api_path) do desc 'The absolute path to the API endpoint' defaultto '/api' validate do |value| raise ArgumentError, format('%s is not a valid API path', value) unless value =~ %r{^/.*/?api$} end end newparam(:grafana_url) do desc 'The URL of the Grafana server' defaultto '' validate do |value| raise ArgumentError, format('%s is not a valid URL', value) unless value =~ %r{^https?://} end end newparam(:grafana_user) do desc 'The username for the Grafana server' end newparam(:grafana_password) do desc 'The password for the Grafana server' end newproperty(:url) do desc 'The URL/Endpoint of the datasource' end newproperty(:type) do desc 'The datasource type' end newparam(:organization) do desc 'The organization name to create the datasource on' defaultto 1 end newproperty(:user) do desc 'The username for the datasource (optional)' end newproperty(:password) do desc 'The password for the datasource (optional)' sensitive true end newproperty(:database) do desc 'The name of the database (optional)' end newproperty(:access_mode) do desc 'Whether the datasource is accessed directly or not by the clients' newvalues(:direct, :proxy) defaultto :direct end newproperty(:is_default) do desc 'Whether the datasource is the default one' - newvalues(true, false) - defaultto false + newvalues(:true, :false) + defaultto :false end newproperty(:basic_auth) do desc 'Whether basic auth is enabled or not' - newvalues(true, false) - defaultto false + newvalues(:true, :false) + defaultto :false end newproperty(:basic_auth_user) do desc 'The username for basic auth if enabled' defaultto '' end newproperty(:basic_auth_password) do desc 'The password for basic auth if enabled' defaultto '' end newproperty(:with_credentials) do desc 'Whether credentials such as cookies or auth headers should be sent with cross-site requests' - newvalues(true, false) - defaultto false + newvalues(:true, :false) + defaultto :false end newproperty(:json_data) do desc 'Additional JSON data to configure the datasource (optional)' validate do |value| raise ArgumentError, 'json_data should be a Hash!' unless value.nil? || value.is_a?(Hash) end end newproperty(:secure_json_data) do desc 'Additional secure JSON data to configure the datasource (optional)' sensitive true validate do |value| raise ArgumentError, 'secure_json_data should be a Hash!' unless value.nil? || value.is_a?(Hash) end end def set_sensitive_parameters(sensitive_parameters) # rubocop:disable Naming/AccessorMethodName parameter(:password).sensitive = true if parameter(:password) parameter(:basic_auth_password).sensitive = true if parameter(:basic_auth_password) super(sensitive_parameters) end autorequire(:service) do 'grafana-server' end autorequire(:grafana_conn_validator) do 'grafana' end end diff --git a/lib/puppet/type/grafana_notification.rb b/lib/puppet/type/grafana_notification.rb index f50a927..4b701c5 100644 --- a/lib/puppet/type/grafana_notification.rb +++ b/lib/puppet/type/grafana_notification.rb @@ -1,75 +1,75 @@ # frozen_string_literal: true # Copyright 2015 Mirantis, Inc. # Puppet::Type.newtype(:grafana_notification) do @doc = 'Manage notification in Grafana' ensurable newparam(:name, namevar: true) do desc 'The name of the notification.' end newparam(:grafana_api_path) do desc 'The absolute path to the API endpoint' defaultto '/api' validate do |value| raise ArgumentError, format('%s is not a valid API path', value) unless value =~ %r{^/.*/?api$} end end newparam(:grafana_url) do desc 'The URL of the Grafana server' defaultto '' validate do |value| raise ArgumentError, format('%s is not a valid URL', value) unless value =~ %r{^https?://} end end newparam(:grafana_user) do desc 'The username for the Grafana server' end newparam(:grafana_password) do desc 'The password for the Grafana server' end newproperty(:type) do desc 'The notification type' end newproperty(:is_default) do desc 'Whether the notification is the default one' - newvalues(true, false) - defaultto false + newvalues(:true, :false) + defaultto :false end newproperty(:send_reminder) do desc 'Whether automatic message resending is enabled or not' - newvalues(true, false) - defaultto false + newvalues(:true, :false) + defaultto :false end newproperty(:frequency) do desc 'The notification reminder frequency' end newproperty(:settings) do desc 'Additional JSON data to configure the notification' validate do |value| raise ArgumentError, 'settings should be a Hash!' unless value.nil? || value.is_a?(Hash) end end autorequire(:service) do 'grafana-server' end autorequire(:grafana_conn_validator) do 'grafana' end end diff --git a/lib/puppet/type/grafana_user.rb b/lib/puppet/type/grafana_user.rb index 47b6d7c..b39cee3 100644 --- a/lib/puppet/type/grafana_user.rb +++ b/lib/puppet/type/grafana_user.rb @@ -1,75 +1,75 @@ # frozen_string_literal: true Puppet::Type.newtype(:grafana_user) do @doc = 'Manage users in Grafana' ensurable newparam(:name, namevar: true) do desc 'The username of the user.' end newparam(:grafana_api_path) do desc 'The absolute path to the API endpoint' defaultto '/api' validate do |value| raise ArgumentError, format('%s is not a valid API path', value) unless value =~ %r{^/.*/?api$} end end newparam(:grafana_url) do desc 'The URL of the Grafana server' defaultto '' validate do |value| raise ArgumentError, format('%s is not a valid URL', value) unless value =~ %r{^https?://} end end newparam(:grafana_user) do desc 'The username for the Grafana server' end newparam(:grafana_password) do desc 'The password for the Grafana server' end newparam(:full_name) do desc 'The full name of the user.' end newproperty(:password) do desc 'The password for the user' def insync?(_is) # rubocop:disable Naming/MethodParameterName provider.check_password end end newproperty(:email) do desc 'The email for the user' end newproperty(:theme) do desc 'The theme for the user' end newproperty(:is_admin) do desc 'Whether the user is a grafana admin' - newvalues(true, false) - defaultto false + newvalues(:true, :false) + defaultto :false end - def set_sensitive_parameters(sensitive_parameters) # rubocop:disable Naming/AccessorMethodName + def set_sensitive_parameters(sensitive_parameters) # rubocop:disable Style/AccessorMethodName parameter(:password).sensitive = true if parameter(:password) super(sensitive_parameters) end autorequire(:service) do 'grafana-server' end autorequire(:grafana_conn_validator) do 'grafana' end end diff --git a/spec/classes/grafana_spec.rb b/spec/classes/grafana_spec.rb index 934bee0..5444636 100644 --- a/spec/classes/grafana_spec.rb +++ b/spec/classes/grafana_spec.rb @@ -1,467 +1,467 @@ # frozen_string_literal: true require 'spec_helper' describe 'grafana' do on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) do facts end context 'with default values' do it { is_expected.to compile.with_all_deps } it { is_expected.to contain_class('grafana') } it { is_expected.to contain_class('grafana::install').that_comes_before('Class[grafana::config]') } it { is_expected.to contain_class('grafana::config').that_notifies('Class[grafana::service]') } it { is_expected.to contain_class('grafana::service') } end # rubocop:disable RSpec/EmptyExampleGroup context 'with parameter install_method is set to package' do let(:params) do { install_method: 'package', version: '5.4.2' } end case facts[:osfamily] when 'Debian' download_location = '/tmp/grafana.deb' describe 'use archive to fetch the package to a temporary location' do it do expect(subject).to contain_archive('/tmp/grafana.deb').with_source( 'https://dl.grafana.com/oss/release/grafana_5.4.2_amd64.deb' ) end it { is_expected.to contain_archive('/tmp/grafana.deb').that_comes_before('Package[grafana]') } end describe 'install dependencies first' do it { is_expected.to contain_package('libfontconfig1').with_ensure('present').that_comes_before('Package[grafana]') } end describe 'install the package' do it { is_expected.to contain_package('grafana').with_provider('dpkg') } it { is_expected.to contain_package('grafana').with_source(download_location) } end when 'RedHat' describe 'install dependencies first' do it { is_expected.to contain_package('fontconfig').with_ensure('present').that_comes_before('Package[grafana]') } end describe 'install the package' do it { is_expected.to contain_package('grafana').with_provider('rpm') } end end end context 'with some plugins passed in' do let(:params) do { plugins: { 'grafana-wizzle' => { 'ensure' => 'present' }, 'grafana-woozle' => { 'ensure' => 'absent' }, 'grafana-plugin' => { 'ensure' => 'present', 'repo' => 'https://nexus.company.com/grafana/plugins' }, 'grafana-plugin-url' => { 'ensure' => 'present', 'plugin_url' => 'https://grafana.com/api/plugins/grafana-simple-json-datasource/versions/latest/download' } } } end it { is_expected.to contain_grafana_plugin('grafana-wizzle').with(ensure: 'present') } it { is_expected.to contain_grafana_plugin('grafana-woozle').with(ensure: 'absent').that_notifies('Class[grafana::service]') } describe 'install plugin with plugin repo' do it { is_expected.to contain_grafana_plugin('grafana-plugin').with(ensure: 'present', repo: 'https://nexus.company.com/grafana/plugins') } end describe 'install plugin with plugin url' do it { is_expected.to contain_grafana_plugin('grafana-plugin-url').with(ensure: 'present', plugin_url: 'https://grafana.com/api/plugins/grafana-simple-json-datasource/versions/latest/download') } end end context 'with parameter install_method is set to repo' do let(:params) do { install_method: 'repo' } end case facts[:osfamily] when 'Debian' describe 'install apt repo dependencies first' do it { is_expected.to contain_class('apt') } it { is_expected.to contain_apt__source('grafana').with(release: 'stable', repos: 'main', location: 'https://packages.grafana.com/oss/deb') } it { is_expected.to contain_apt__source('grafana').that_comes_before('Package[grafana]') } end describe 'install dependencies first' do it { is_expected.to contain_package('libfontconfig1').with_ensure('present').that_comes_before('Package[grafana]') } end describe 'install the package' do it { is_expected.to contain_package('grafana').with_ensure('installed') } end when 'RedHat' describe 'yum repo dependencies first' do it { is_expected.to contain_yumrepo('grafana-stable').with(baseurl: 'https://packages.grafana.com/oss/rpm', gpgkey: 'https://packages.grafana.com/gpg.key', enabled: 1) } it { is_expected.to contain_yumrepo('grafana-stable').that_comes_before('Package[grafana]') } end describe 'install dependencies first' do it { is_expected.to contain_package('fontconfig').with_ensure('present').that_comes_before('Package[grafana]') } end describe 'install the package' do it { is_expected.to contain_package('grafana').with_ensure('installed') } end end end context 'with parameter install_method is set to repo and manage_package_repo is set to false' do let(:params) do { install_method: 'repo', manage_package_repo: false, version: 'present' } end case facts[:osfamily] when 'Debian' describe 'install dependencies first' do it { is_expected.to contain_package('libfontconfig1').with_ensure('present').that_comes_before('Package[grafana]') } end describe 'install the package' do it { is_expected.to contain_package('grafana').with_ensure('present') } end when 'RedHat' describe 'install dependencies first' do it { is_expected.to contain_package('fontconfig').with_ensure('present').that_comes_before('Package[grafana]') } end describe 'install the package' do it { is_expected.to contain_package('grafana').with_ensure('present') } end when 'Archlinux' describe 'install the package' do it { is_expected.to contain_package('grafana').with_ensure('present') } end end end context 'with parameter install_method is set to archive' do let(:params) do { install_method: 'archive', version: '5.4.2' } end install_dir = '/usr/share/grafana' service_config = '/usr/share/grafana/conf/custom.ini' archive_source = 'https://dl.grafana.com/oss/release/grafana-5.4.2.linux-amd64.tar.gz' describe 'extract archive to install_dir' do it { is_expected.to contain_archive('/tmp/grafana.tar.gz').with_ensure('present') } it { is_expected.to contain_archive('/tmp/grafana.tar.gz').with_source(archive_source) } it { is_expected.to contain_archive('/tmp/grafana.tar.gz').with_extract_path(install_dir) } end describe 'create grafana user' do it { is_expected.to contain_user('grafana').with_ensure('present').with_home(install_dir) } it { is_expected.to contain_user('grafana').that_comes_before('File[/usr/share/grafana]') } end case facts[:osfamily] when 'Archlinux', 'Debian', 'RedHat' describe 'create data_dir' do it { is_expected.to contain_file('/var/lib/grafana').with_ensure('directory') } end - when 'FreBSD' + when 'FreeBSD' describe 'create data_dir' do it { is_expected.to contain_file('/var/db/grafana').with_ensure('directory') } end end describe 'manage install_dir' do it { is_expected.to contain_file(install_dir).with_ensure('directory') } it { is_expected.to contain_file(install_dir).with_group('grafana').with_owner('grafana') } end describe 'configure grafana' do it { is_expected.to contain_file(service_config).with_ensure('file') } end describe 'run grafana as service' do it { is_expected.to contain_service('grafana').with_ensure('running').with_provider('base') } it { is_expected.to contain_service('grafana').with_hasrestart(false).with_hasstatus(false) } end context 'when user already defined' do let(:pre_condition) do 'user{"grafana": ensure => present, }' end describe 'do NOT create grafana user' do it { is_expected.not_to contain_user('grafana').with_ensure('present').with_home(install_dir) } end end context 'when service already defined' do let(:pre_condition) do 'service{"grafana": ensure => running, name => "grafana-server", hasrestart => true, hasstatus => true, }' end describe 'do NOT run service' do it { is_expected.not_to contain_service('grafana').with_hasrestart(false).with_hasstatus(false) } end end end context 'invalid parameters' do context 'cfg' do describe 'should not raise an error when cfg parameter is a hash' do let(:params) do { cfg: {} } end it { is_expected.to contain_package('grafana') } end end end context 'configuration file' do describe 'should not contain any configuration when cfg param is empty' do it { is_expected.to contain_file('grafana.ini').with_content("# This file is managed by Puppet, any changes will be overwritten\n\n") } end describe 'should correctly transform cfg param entries to Grafana configuration' do let(:params) do { cfg: { 'app_mode' => 'production', 'section' => { 'string' => 'production', 'number' => 8080, 'boolean' => false, 'empty' => '' } }, ldap_cfg: { 'servers' => [ { 'host' => 'server1', 'use_ssl' => true, 'search_filter' => '(sAMAccountName=%s)', 'search_base_dns' => ['dc=domain1,dc=com'] } ], 'servers.attributes' => { 'name' => 'givenName', 'surname' => 'sn', 'username' => 'sAMAccountName', 'member_of' => 'memberOf', 'email' => 'email' } } } end expected = "# This file is managed by Puppet, any changes will be overwritten\n\n"\ "app_mode = production\n\n"\ "[section]\n"\ "boolean = false\n"\ "empty = \n"\ "number = 8080\n"\ "string = production\n" it { is_expected.to contain_file('grafana.ini').with_content(expected) } ldap_expected = "\n[[servers]]\n"\ "host = \"server1\"\n"\ "search_base_dns = [\"dc=domain1,dc=com\"]\n"\ "search_filter = \"(sAMAccountName=%s)\"\n"\ "use_ssl = true\n"\ "\n"\ "[servers.attributes]\n"\ "email = \"email\"\n"\ "member_of = \"memberOf\"\n"\ "name = \"givenName\"\n"\ "surname = \"sn\"\n"\ "username = \"sAMAccountName\"\n"\ "\n" it { is_expected.to contain_file('/etc/grafana/ldap.toml').with_content(ldap_expected) } end end context 'multiple ldap configuration' do describe 'should correctly transform ldap config param into Grafana ldap.toml' do let(:params) do { cfg: {}, ldap_cfg: [ { 'servers' => [ { 'host' => 'server1a server1b', 'use_ssl' => true, 'search_filter' => '(sAMAccountName=%s)', 'search_base_dns' => ['dc=domain1,dc=com'] } ], 'servers.attributes' => { 'name' => 'givenName', 'surname' => 'sn', 'username' => 'sAMAccountName', 'member_of' => 'memberOf', 'email' => 'email' } }, { 'servers' => [ { 'host' => 'server2a server2b', 'use_ssl' => true, 'search_filter' => '(sAMAccountName=%s)', 'search_base_dns' => ['dc=domain2,dc=com'] } ], 'servers.attributes' => { 'name' => 'givenName', 'surname' => 'sn', 'username' => 'sAMAccountName', 'member_of' => 'memberOf', 'email' => 'email' } } ] } end ldap_expected = "\n[[servers]]\n"\ "host = \"server1a server1b\"\n"\ "search_base_dns = [\"dc=domain1,dc=com\"]\n"\ "search_filter = \"(sAMAccountName=%s)\"\n"\ "use_ssl = true\n"\ "\n"\ "[servers.attributes]\n"\ "email = \"email\"\n"\ "member_of = \"memberOf\"\n"\ "name = \"givenName\"\n"\ "surname = \"sn\"\n"\ "username = \"sAMAccountName\"\n"\ "\n"\ "\n[[servers]]\n"\ "host = \"server2a server2b\"\n"\ "search_base_dns = [\"dc=domain2,dc=com\"]\n"\ "search_filter = \"(sAMAccountName=%s)\"\n"\ "use_ssl = true\n"\ "\n"\ "[servers.attributes]\n"\ "email = \"email\"\n"\ "member_of = \"memberOf\"\n"\ "name = \"givenName\"\n"\ "surname = \"sn\"\n"\ "username = \"sAMAccountName\"\n"\ "\n" it { is_expected.to contain_file('/etc/grafana/ldap.toml').with_content(ldap_expected) } end end context 'provisioning_dashboards defined' do let(:params) do { version: '6.0.0', provisioning_dashboards: { apiVersion: 1, providers: [ { name: 'default', orgId: 1, folder: '', type: 'file', disableDeletion: true, options: { path: '/var/lib/grafana/dashboards', puppetsource: 'puppet:///modules/my_custom_module/dashboards' } } ] } } end it do expect(subject).to contain_file('/var/lib/grafana/dashboards').with( ensure: 'directory', owner: 'grafana', group: 'grafana', mode: '0750', recurse: true, purge: true, source: 'puppet:///modules/my_custom_module/dashboards' ) end context 'without puppetsource defined' do let(:params) do { version: '6.0.0', provisioning_dashboards: { apiVersion: 1, providers: [ { name: 'default', orgId: 1, folder: '', type: 'file', disableDeletion: true, options: { path: '/var/lib/grafana/dashboards' } } ] } } end it { is_expected.not_to contain_file('/var/lib/grafana/dashboards') } end end context 'sysconfig environment variables' do let(:params) do { install_method: 'repo', sysconfig: { http_proxy: 'http://proxy.example.com/' } } end case facts[:osfamily] when 'Debian' describe 'Add the environment variable to the config file' do it { is_expected.to contain_augeas('sysconfig/grafana-server').with_context('/files/etc/default/grafana-server') } it { is_expected.to contain_augeas('sysconfig/grafana-server').with_changes(['set http_proxy http://proxy.example.com/']) } end when 'RedHat' describe 'Add the environment variable to the config file' do it { is_expected.to contain_augeas('sysconfig/grafana-server').with_context('/files/etc/sysconfig/grafana-server') } it { is_expected.to contain_augeas('sysconfig/grafana-server').with_changes(['set http_proxy http://proxy.example.com/']) } end end end # rubocop:enable RSpec/EmptyExampleGroup end end end diff --git a/spec/unit/puppet/type/grafana_datasource_type_spec.rb b/spec/unit/puppet/type/grafana_datasource_type_spec.rb index ea1b4f7..33a78f2 100644 --- a/spec/unit/puppet/type/grafana_datasource_type_spec.rb +++ b/spec/unit/puppet/type/grafana_datasource_type_spec.rb @@ -1,96 +1,96 @@ # frozen_string_literal: true # Copyright 2015 Mirantis, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'spec_helper' describe Puppet::Type.type(:grafana_datasource) do let(:gdatasource) do described_class.new( name: 'foo', grafana_url: 'http://example.com', url: 'http://es.example.com', type: 'elasticsearch', organization: 'test_org', access_mode: 'proxy', is_default: true, basic_auth: true, basic_auth_user: 'user', basic_auth_password: 'password', with_credentials: true, database: 'test_db', user: 'db_user', password: 'db_password', json_data: { esVersion: 5, timeField: '@timestamp', timeInterval: '1m' }, secure_json_data: { password: '5ecretPassw0rd' } ) end context 'when setting parameters' do it "fails if grafana_url isn't HTTP-based" do expect do described_class.new name: 'foo', grafana_url: 'example.com', content: '{}', ensure: :present end.to raise_error(Puppet::Error, %r{not a valid URL}) end it "fails if json_data isn't valid" do expect do described_class.new name: 'foo', grafana_url: 'http://example.com', json_data: 'invalid', ensure: :present end.to raise_error(Puppet::Error, %r{json_data should be a Hash}) end it "fails if secure_json_data isn't valid" do expect do described_class.new name: 'foo', grafana_url: 'http://example.com', secure_json_data: 'invalid', ensure: :present end.to raise_error(Puppet::Error, %r{json_data should be a Hash}) end it 'accepts valid parameters' do expect(gdatasource[:name]).to eq('foo') expect(gdatasource[:grafana_url]).to eq('http://example.com') expect(gdatasource[:url]).to eq('http://es.example.com') expect(gdatasource[:type]).to eq('elasticsearch') expect(gdatasource[:organization]).to eq('test_org') expect(gdatasource[:access_mode]).to eq(:proxy) - expect(gdatasource[:is_default]).to eq(:true) # rubocop:disable Lint/BooleanSymbol - expect(gdatasource[:basic_auth]).to eq(:true) # rubocop:disable Lint/BooleanSymbol + expect(gdatasource[:is_default]).to eq(:true) + expect(gdatasource[:basic_auth]).to eq(:true) expect(gdatasource[:basic_auth_user]).to eq('user') expect(gdatasource[:basic_auth_password]).to eq('password') - expect(gdatasource[:with_credentials]).to eq(:true) # rubocop:disable Lint/BooleanSymbol + expect(gdatasource[:with_credentials]).to eq(:true) expect(gdatasource[:database]).to eq('test_db') expect(gdatasource[:user]).to eq('db_user') expect(gdatasource[:password]).to eq('db_password') expect(gdatasource[:json_data]).to eq(esVersion: 5, timeField: '@timestamp', timeInterval: '1m') expect(gdatasource[:secure_json_data]).to eq(password: '5ecretPassw0rd') end it 'autorequires the grafana-server for proper ordering' do catalog = Puppet::Resource::Catalog.new service = Puppet::Type.type(:service).new(name: 'grafana-server') catalog.add_resource service catalog.add_resource gdatasource relationship = gdatasource.autorequire.find do |rel| (rel.source.to_s == 'Service[grafana-server]') && (rel.target.to_s == gdatasource.to_s) end expect(relationship).to be_a Puppet::Relationship end it 'does not autorequire the service it is not managed' do catalog = Puppet::Resource::Catalog.new catalog.add_resource gdatasource expect(gdatasource.autorequire).to be_empty end end end diff --git a/spec/unit/puppet/type/grafana_notification_type_spec.rb b/spec/unit/puppet/type/grafana_notification_type_spec.rb index ac5826f..7f51f9e 100644 --- a/spec/unit/puppet/type/grafana_notification_type_spec.rb +++ b/spec/unit/puppet/type/grafana_notification_type_spec.rb @@ -1,72 +1,72 @@ # frozen_string_literal: true # Copyright 2015 Mirantis, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'spec_helper' describe Puppet::Type.type(:grafana_notification) do let(:gnotification) do described_class.new( name: 'foo', grafana_url: 'http://example.com', type: 'email', is_default: true, send_reminder: true, frequency: '20m', settings: { adresses: 'test@example.com' } ) end context 'when setting parameters' do it "fails if grafana_url isn't HTTP-based" do expect do described_class.new name: 'foo', grafana_url: 'example.com', content: '{}' end.to raise_error(Puppet::Error, %r{not a valid URL}) end it "fails if settings isn't valid" do expect do described_class.new name: 'foo', grafana_url: 'http://example.com', settings: 'invalid' end.to raise_error(Puppet::Error, %r{settings should be a Hash}) end it 'accepts valid parameters' do expect(gnotification[:name]).to eq('foo') expect(gnotification[:grafana_url]).to eq('http://example.com') expect(gnotification[:type]).to eq('email') - expect(gnotification[:is_default]).to eq(:true) # rubocop:disable Lint/BooleanSymbol - expect(gnotification[:send_reminder]).to eq(:true) # rubocop:disable Lint/BooleanSymbol + expect(gnotification[:is_default]).to eq(:true) + expect(gnotification[:send_reminder]).to eq(:true) expect(gnotification[:frequency]).to eq('20m') expect(gnotification[:settings]).to eq(adresses: 'test@example.com') end it 'autorequires the grafana-server for proper ordering' do catalog = Puppet::Resource::Catalog.new service = Puppet::Type.type(:service).new(name: 'grafana-server') catalog.add_resource service catalog.add_resource gnotification relationship = gnotification.autorequire.find do |rel| (rel.source.to_s == 'Service[grafana-server]') && (rel.target.to_s == gnotification.to_s) end expect(relationship).to be_a Puppet::Relationship end it 'does not autorequire the service it is not managed' do catalog = Puppet::Resource::Catalog.new catalog.add_resource gnotification expect(gnotification.autorequire).to be_empty end end end