-
Notifications
You must be signed in to change notification settings - Fork 289
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(#597) Add sensu::contact type (Enterprise Only)
Without this patch the Puppet module doesn't provide an affordance for [contact routing](https://sensuapp.org/docs/0.29/enterprise/contact-routing.html) This patch addresses the problem by adding a new defined type, sensu::contact backed by a custom type and provider for sensu_contact. Example usage: sensu::contact { 'support': config => { 'email' => { 'to' => 'support@example.com' } }, } sensu::contact { 'ops': config => { 'email' => { 'to' => 'ops@example.com' } }, } sensu::check { 'check_ntp': command => 'PATH=$PATH:/usr/lib64/nagios/plugins check_ntp_time -H pool.ntp.org -w 30 -c 60', handlers => 'email', contacts => ['ops', 'support'], } Resolves #597
- Loading branch information
1 parent
bd97d83
commit 89e7918
Showing
11 changed files
with
363 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
require 'json' if Puppet.features.json? | ||
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', | ||
'puppet_x', 'sensu', 'provider_create.rb')) | ||
|
||
Puppet::Type.type(:sensu_contact).provide(:json) do | ||
confine :feature => :json | ||
include PuppetX::Sensu::ProviderCreate | ||
|
||
def conf | ||
begin | ||
@conf ||= JSON.parse(File.read(config_file)) | ||
rescue | ||
@conf ||= {} | ||
end | ||
end | ||
|
||
def flush | ||
File.open(config_file, 'w') do |f| | ||
f.puts JSON.pretty_generate(conf) | ||
end | ||
end | ||
|
||
def pre_create | ||
conf['contacts'] = {} | ||
conf['contacts'][resource[:name]] = {} | ||
self.config = resource[:config] | ||
end | ||
|
||
def config_file | ||
"#{resource[:base_path]}/#{resource[:name]}.json" | ||
end | ||
|
||
def destroy | ||
@conf = nil | ||
end | ||
|
||
def exists? | ||
conf.has_key?('contacts') and conf['contacts'].has_key?(resource[:name]) | ||
end | ||
|
||
def config | ||
conf['contacts'][resource[:name]] | ||
end | ||
|
||
def config=(value) | ||
conf['contacts'][resource[:name]] = value | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
Puppet::Type.newtype(:sensu_contact) do | ||
@doc = "" | ||
|
||
def initialize(*args) | ||
super *args | ||
|
||
if c = catalog | ||
self[:notify] = [ | ||
'Service[sensu-server]', | ||
'Service[sensu-enterprise]', | ||
].select { |ref| c.resource(ref) } | ||
end | ||
end | ||
|
||
ensurable do | ||
newvalue(:present) do | ||
provider.create | ||
end | ||
|
||
newvalue(:absent) do | ||
provider.destroy | ||
end | ||
|
||
defaultto :present | ||
end | ||
|
||
newparam(:name) do | ||
isnamevar | ||
# Valid names documented at | ||
# https://sensuapp.org/docs/0.29/enterprise/contact-routing.html#contact-names | ||
newvalues(/^[\w\.-]+$/) | ||
desc 'The name of the contact, e.g. "support"' | ||
end | ||
|
||
newproperty(:config) do | ||
desc 'Configuration hash for the contact.' | ||
|
||
def is_to_s(hash = @is) | ||
hash.keys.sort.map {|key| "#{key} => #{hash[key]}"}.join(", ") | ||
end | ||
|
||
def should_to_s(hash = @should[0]) | ||
hash.keys.sort.map {|key| "#{key} => #{hash[key]}"}.join(", ") | ||
end | ||
|
||
def insync?(is) | ||
is_to_s(is) == should_to_s | ||
end | ||
|
||
defaultto {} | ||
end | ||
|
||
newparam(:base_path) do | ||
desc 'The base path to the contact config file' | ||
defaultto '/etc/sensu/conf.d/contacts/' | ||
end | ||
|
||
autorequire(:package) do | ||
['sensu'] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# = Define: sensu::routing | ||
# | ||
# Manage [Contact | ||
# Routing](https://sensuapp.org/docs/0.26/enterprise/contact-routing.html) | ||
# configuration with Sensu Enterprise. | ||
# | ||
# Note: If the `sensu::purge_config` class parameter is `true`, unmanaged | ||
# sensu::contact resources located in /etc/sensu/conf.d/contacts will be purged. | ||
# | ||
# == Parameters | ||
# | ||
# [*ensure*] | ||
# String. Whether the check should be present or not | ||
# Default: present | ||
# Valid values: present, absent | ||
# | ||
# [*base_path*] | ||
# String. Where to place the contact JSON configuration file. Defaults to | ||
# `undef` which defers to the behavior of the underlying sensu_contact type. | ||
# Default: undef | ||
# | ||
# [*config*] | ||
# Hash. The configuration data for the contact. This is an arbitrary hash to | ||
# accommodate the various communication channels. For example, `{ "email": { | ||
# "to": "support@example.com" } }`. | ||
# Default: {} | ||
define sensu::contact( | ||
$ensure = 'present', | ||
$base_path = undef, | ||
$config = {}, | ||
) { | ||
validate_re($ensure, ['^present$', '^absent$'] ) | ||
validate_hash($config) | ||
|
||
$file_ensure = $ensure ? { | ||
'absent' => 'absent', | ||
default => 'file' | ||
} | ||
|
||
# handler configuration may contain "secrets" | ||
file { "/etc/sensu/conf.d/contacts/${name}.json": | ||
ensure => $file_ensure, | ||
owner => 'sensu', | ||
group => 'sensu', | ||
mode => '0440', | ||
before => Sensu_contact[$name], | ||
} | ||
|
||
sensu_contact { $name: | ||
ensure => $ensure, | ||
config => $config, | ||
base_path => $base_path, | ||
require => File['/etc/sensu/conf.d/contacts'], | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
require 'spec_helper' | ||
|
||
describe 'sensu::contact', :type => :define do | ||
let(:facts) { { 'Class[sensu::service::server]' => true } } | ||
let(:params) { { } } | ||
|
||
let(:pre_condition) do | ||
<<-'ENDofPUPPETcode' | ||
include ::sensu | ||
ENDofPUPPETcode | ||
end | ||
let(:title) { 'support' } | ||
|
||
context 'default (ensure => present)' do | ||
it 'manages the config file ownership and permissions' do | ||
expect(subject).to contain_file('/etc/sensu/conf.d/contacts/support.json').with( | ||
ensure: 'file', | ||
owner: 'sensu', | ||
group: 'sensu', | ||
mode: '0440', | ||
) | ||
end | ||
it 'defaults to an empty config hash' do | ||
expect(subject).to contain_sensu_contact('support').with(ensure: 'present', config: {}) | ||
end | ||
end | ||
|
||
describe 'ensure => absent' do | ||
let(:params) { { ensure: 'absent' } } | ||
it { is_expected.to contain_sensu_contact(title).with_ensure('absent') } | ||
it do | ||
is_expected.to contain_file("/etc/sensu/conf.d/contacts/#{title}.json"). | ||
with_ensure('absent') | ||
end | ||
end | ||
|
||
describe 'config param' do | ||
let(:params) { { config: { 'email' => { 'to' => 'support@example.com' } } } } | ||
|
||
it 'passes the config hash to sensu_contact' do | ||
is_expected.to contain_sensu_contact(title).with_config(params[:config]) | ||
end | ||
end | ||
|
||
describe 'base_path param' do | ||
context 'when specified' do | ||
let(:params) { { base_path: '/tmp/foo' } } | ||
|
||
it 'passes the base_path string to sensu_contact' do | ||
is_expected.to contain_sensu_contact(title).with_base_path('/tmp/foo') | ||
end | ||
end | ||
context 'when not specified' do | ||
it 'defers to sensu_contact by passing undef' do | ||
is_expected.to contain_sensu_contact(title).without_base_path | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
require 'spec_helper' | ||
|
||
describe Puppet::Type.type(:sensu_contact) do | ||
let(:resource_hash_base) do | ||
{ | ||
:title => 'support', | ||
:catalog => Puppet::Resource::Catalog.new | ||
} | ||
end | ||
# This is overridden on a context by context basis | ||
let(:resource_hash_override) { {} } | ||
let(:resource_hash) { resource_hash_base.merge(resource_hash_override) } | ||
|
||
describe 'name parameter' do | ||
subject { described_class.new(resource_hash)[:name] } | ||
describe 'valid name "support"' do | ||
it { is_expected.to eq 'support' } | ||
end | ||
describe 'invalid name "invalid%name"' do | ||
let(:resource_hash_override) { {name: 'invalid%name'} } | ||
it do | ||
expect { subject }.to raise_error Puppet::ResourceError, /Parameter name failed/ | ||
end | ||
end | ||
end | ||
|
||
describe 'notifications' do | ||
context 'when managing sensu-enterprise (#495)' do | ||
let(:service_resource) do | ||
Puppet::Type.type(:service).new(name: 'sensu-enterprise') | ||
end | ||
let(:resource_hash) do | ||
c = Puppet::Resource::Catalog.new | ||
c.add_resource(service_resource) | ||
{ | ||
:title => 'mymutator', | ||
:catalog => c | ||
} | ||
end | ||
|
||
it 'notifies Service[sensu-enterprise]' do | ||
notify_list = described_class.new(resource_hash)[:notify] | ||
# compare the resource reference strings, the object identities differ. | ||
expect(notify_list.map(&:ref)).to eq [service_resource.ref] | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.