2 changes: 1 addition & 1 deletion .msync.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
modulesync_config_version: '1.9.2'
modulesync_config_version: '1.9.3'
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ matrix:
- rvm: 2.5.1
bundler_args: --without development release
dist: trusty
env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_setfile=ubuntu1604-64{hypervisor=docker} CHECK=beaker
env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=ubuntu1604-64{hypervisor=docker} CHECK=beaker
services: docker
sudo: required
- rvm: 2.5.1
bundler_args: --without development release
dist: trusty
env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_setfile=centos7-64{hypervisor=docker} CHECK=beaker
env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=centos7-64{hypervisor=docker} CHECK=beaker
services: docker
sudo: required
branches:
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
Each new release typically also includes the latest modulesync defaults.
These should not affect the functionality of the module.

## [v4.5.0](https://github.com/voxpupuli/puppet-grafana/tree/v4.5.0) (2018-07-15)

[Full Changelog](https://github.com/voxpupuli/puppet-grafana/compare/v4.4.1...v4.5.0)

**Implemented enhancements:**

- Use provisioning backend for dashboards, providers [\#103](https://github.com/voxpupuli/puppet-grafana/issues/103)
- Feature: Add grafana provisioning to this module. [\#120](https://github.com/voxpupuli/puppet-grafana/pull/120) ([drshawnkwang](https://github.com/drshawnkwang))

## [v4.4.1](https://github.com/voxpupuli/puppet-grafana/tree/v4.4.1) (2018-07-04)

[Full Changelog](https://github.com/voxpupuli/puppet-grafana/compare/v4.4.0...v4.4.1)
Expand Down
7 changes: 5 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def location_for(place, fake_version = nil)
end

group :test do
gem 'puppetlabs_spec_helper', '~> 2.6.0', :require => false
gem 'puppetlabs_spec_helper', '~> 2.6', :require => false
gem 'rspec-puppet', '~> 2.5', :require => false
gem 'rspec-puppet-facts', :require => false
gem 'rspec-puppet-utils', :require => false
Expand Down Expand Up @@ -56,13 +56,16 @@ group :system_tests do
gem 'beaker-hostgenerator', '>= 1.1.10', :require => false
gem 'beaker-puppet_install_helper', :require => false
gem 'beaker-module_install_helper', :require => false
gem 'rbnacl', '~> 4', :require => false if RUBY_VERSION >= '2.2.6'
gem 'rbnacl-libsodium', :require => false if RUBY_VERSION >= '2.2.6'
gem 'bcrypt_pbkdf', :require => false
end

group :release do
gem 'github_changelog_generator', :require => false, :git => 'https://github.com/skywinder/github-changelog-generator' if RUBY_VERSION >= '2.2.2'
gem 'puppet-blacksmith', :require => false
gem 'voxpupuli-release', :require => false, :git => 'https://github.com/voxpupuli/voxpupuli-release-gem'
gem 'puppet-strings', '~> 1.0', :require => false
gem 'puppet-strings', '>= 1.0', :require => false
end


Expand Down
141 changes: 141 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,33 @@ The download location of a package to be used with the 'package' install method.
Defaults to the URL of the latest version of Grafana available at the time of
module release.

##### `provisioning_datasources`

A Hash which is converted to YAML for grafana to provision data
sources. See [provisioning
grafana](http://docs.grafana.org/administration/provisioning/) for
details and example config file. Requires grafana > v5.0.0.

This is very useful with Hiera as you can provide a yaml
hash/dictionary which will effectively 'passthrough' to grafana. See
**Advanced Usage** for examples.

##### `provisioning_dashboards`

A Hash which is converted to YAML for grafana to provision
dashboards. See [provisioning
grafana](http://docs.grafana.org/administration/provisioning/) for
details and example config file. Requires grafana > v5.0.0.

This is very useful with Hiera as you can provide a yaml
hash/dictionary which will effectively 'passthrough' to grafana. See
**Advanced Usage** for examples.

N.B. A option named `puppetsource` may be given in the `options` hash
which is not part of grafana's syntax. This option will be extracted
from the hash, and used to "source" a directory of dashboards. See
**Advanced Usage** for details.

##### `rpm_iteration`

Used when installing Grafana from package ('package' or 'repo' install methods)
Expand Down Expand Up @@ -607,6 +634,120 @@ grafana_user { 'username':
```
`grafana_api_path` is only required if using sub-paths for the API

#### Provisioning Grafana

[Grafana documentation on
provisioning](http://docs.grafana.org/administration/provisioning/).

This module will provision grafana by placing yaml files into
`/etc/grafana/provisioning/datasources` and
`/etc/grafana/provisioning/dashboards`.

##### Example datasource

A puppet hash example for Prometheus. The module will place the hash
as a yaml file into `/etc/gafana/provisioning/datasources/puppetprovisioned.yaml`.

```puppet
class { 'grafana':
provisioning_datasources => {
apiVersion => 1,
datasources => [
{
name => 'Prometheus',
type => 'prometheus',
access => 'proxy',
url => 'http://localhost:9090/prometheus',
isDefault => true,
},
],
}
}
```

Here is the same configuration example as a hiera hash.

```yaml
grafana::provisioning_datasources:
apiVersion: 1
datasources:
- name: 'Prometheus'
type: 'prometheus'
access: 'proxy'
url: 'http://localhost:9090/prometheus'
isDefault: true
```
##### Example dashboard
An example puppet hash for provisioning dashboards. The module will
place the hash as a yaml file into
`/etc/grafana/provisioning/dashboards/puppetprovisioned.yaml`. More details follow the examples.

```puppet
class { 'grafana':
provisioning_dashboards => {
apiVersion => 1,
providers => [
{
name => 'default',
orgId => 1,
fiolder => '',
type => 'file',
disableDeletion => true,
options => {
path => '/var/lib/grafana/dashboards',
puppetsource => 'puppet:///modules/my_custom_module/dashboards',
},
},
],
}
}
```

Here is the same configuraiton example as a hiera hash.

```yaml
grafana::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'
```

In both examples above a non-grafana option named `puppetsource` has
been used. When this module finds that the provisioning_dashboards hash
contains keys `path` and `puppetsource` in the `options` subhash, it
will do the following.
* It will create the path found in `options['path']`. Note: puppet
will only create the final directory of the path unless the
parameter `create_subdirs_provisioning` is set to true: this defaults
to false.
* It will use `puppetsource` as the file resource's 'source' for the
directory.
* It removes the `puppetsource` key from the `options` subhash, so the
subsequent yaml file for gafana does not contain this key. (The
`path` key will remain.)

This feature allows you to define a custom module, and place any
dashboards you want provisioned in the its `files/` directory. In the
example above you would put dashboards into
`my_custom_module/files/dashboards` and puppet-grafana will create
`/var/lib/grafana/dashboards` and provision it with the contents of
`my_custom_module/files/dashboards`.

Puppet's file resource may also be given a `file://` URI which may
point to a locally available directory on the filesystem, typically
the filesystem of the puppetserver/master. Thus you may specify a
local directory with grafana dashboards you wish to provision into
grafana.

## Limitations

This module has been tested on Ubuntu 14.04, using each of the 'archive', 'docker'
Expand Down
37 changes: 37 additions & 0 deletions lib/puppet/functions/grafana/deep_find_and_remove.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# == Function: deep_find_and_remove
#
# This function takes a hash as input, along with a string
# (key). Additionally, the optional removekey (defaults to
# 'puppetsource') is a parameter.
#
# The purpose of this function is to extract the 'options' subhash
# from the array of hashes given to provision dashboards. This options
# subhash may contain a path and source which puppet will use for
# provisioning: creating the path and applying the files from the
# source.
#
# Additionally, if the key 'puppetsource' exists in the sub-hash, it
# will be deleted from the structure. Thus the output of this function
# may be used in yaml format for grafana's provisioning
# configuration file for dashboards.
Puppet::Functions.create_function(:'grafana::deep_find_and_remove') do
dispatch :deep_find_and_remove do
param 'String', :key
param 'Hash', :object
optional_param 'String', :removekey
return_type 'Array'
end

def deep_find_and_remove(key, object, removekey = 'puppetsource')
foundpaths = []
if object.respond_to?(:key?) && object.key?(key)
foundpaths << object[key].dup
object[key].delete(removekey)
end
if object.is_a? Enumerable
foundpaths << object.map { |*a| deep_find_and_remove(key, a.last) }
end
foundpaths.flatten.compact
foundpaths
end
end
39 changes: 39 additions & 0 deletions lib/puppet/functions/grafana/get_sub_paths.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# == Function get_sub_paths
#
# This function receives an input path as an input parameter, and
# returns an array of the subpaths in the input, excluding the input
# path itself. The function will attempt to ignore any extra slashes
# in the path given.
#
# This function will only work on UNIX paths with forward slashes (/).
#
# Examples:
# input = '/var/lib/grafana/dashboards'
# output = [ '/var', '/var/lib', '/var/lib/grafana'/ ]
#
# input = '/opt'
# output = []
#
# input = '/first/second/'
# output = [ '/first' ]
Puppet::Functions.create_function(:'grafana::get_sub_paths') do
dispatch :get_sub_paths do
param 'String', :inputpath
return_type 'Array'
end

def get_sub_paths(inputpath)
ip = inputpath.gsub(%r{/+}, '/')
allsubs = []
parts = ip.split('/')
parts.each_with_index do |value, index|
next if index.zero? || index == (parts.length - 1)
allsubs << if index == 1
'/' + value
else
allsubs[index - 2] + '/' + value
end
end
allsubs
end
end
65 changes: 65 additions & 0 deletions manifests/config.pp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
'docker': {
if $::grafana::container_cfg {
$cfg = $::grafana::cfg
$myprovision = false

file { $::grafana::cfg_location:
ensure => file,
Expand All @@ -18,6 +19,7 @@
}
'package','repo': {
$cfg = $::grafana::cfg
$myprovision = true

file { $::grafana::cfg_location:
ensure => file,
Expand Down Expand Up @@ -47,6 +49,7 @@
}
'archive': {
$cfg = $::grafana::cfg
$myprovision = true

file { "${::grafana::install_dir}/conf/custom.ini":
ensure => file,
Expand Down Expand Up @@ -76,4 +79,66 @@
group => 'grafana',
}
}

# If grafana version is > 5.0.0, and the install method is package,
# repo, or archive, then use the provisioning feature. Dashboards
# and datasources are placed in
# /etc/grafana/provisioning/[dashboards|datasources].
# --dashboards--
if ((versioncmp($grafana::version, '5.0.0') >= 0) and ($myprovision)) {
$pdashboards = $grafana::provisioning_dashboards
if (length($pdashboards) >= 1 ) {
$dashboardpaths = flatten(grafana::deep_find_and_remove('options', $pdashboards))
# template uses:
# - pdashboards
file { '/etc/grafana/provisioning/dashboards/puppetprovisioned.yaml':
ensure => file,
owner => 'grafana',
group => 'grafana',
mode => '0640',
content => epp('grafana/pdashboards.yaml.epp'),
notify => Service[$grafana::service_name],
}
# Loop over all providers, extract the paths and create
# directories for each path of dashboards.
$dashboardpaths.each | Integer $index, Hash $options | {
if has_key($options, 'path') {
# get sub paths of 'path' and create subdirs if necessary
$subpaths = grafana::get_sub_paths($options['path'])
if ($grafana::create_subdirs_provisioning and (length($subpaths) >= 1)) {
file { $subpaths :
ensure => directory,
before => File[$options['path']],
}
}

file { $options['path'] :
ensure => directory,
owner => 'grafana',
group => 'grafana',
mode => '0750',
recurse => true,
purge => true,
source => $options['puppetsource'],
}
}
}
}

# --datasources--
$pdatasources = $grafana::provisioning_datasources
if (length($pdatasources) >= 1) {
# template uses:
# - pdatasources
file { '/etc/grafana/provisioning/datasources/puppetprovisioned.yaml':
ensure => file,
owner => 'grafana',
group => 'grafana',
mode => '0640',
content => epp('grafana/pdatasources.yaml.epp'),
notify => Service[$grafana::service_name],
}
}

}
}
Loading