Skip to content

Commit

Permalink
Add sensu_cluster_member type
Browse files Browse the repository at this point in the history
  • Loading branch information
treydock committed Aug 5, 2018
1 parent c330c51 commit 6578dd0
Show file tree
Hide file tree
Showing 12 changed files with 602 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ matrix:
env: BEAKER_set="centos-7" BEAKER_sensu_full=yes
bundler_args:
script: bundle exec rake beaker
- rvm: 2.4.2
sudo: required
services: docker
env: BEAKER_set="centos-7-cluster" BEAKER_sensu_cluster=yes
bundler_args:
script: bundle exec rake beaker
- rvm: 2.4.2
sudo: required
services: docker
Expand Down
26 changes: 26 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,32 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
backend.vm.provision :shell, :inline => "facter --custom-dir=/vagrant/lib/facter sensu_version"
end

config.vm.define "sensu-backend-peer", primary: true, autostart: true do |backend|
backend.vm.box = "centos/7"
backend.vm.hostname = 'sensu-backend-peer.example.com'
backend.vm.network :private_network, ip: ENV['ALTERNATE_IP'] || '192.168.52.11'
backend.vm.network :forwarded_port, guest: 2380, host: 2380, auto_correct: true
backend.vm.network :forwarded_port, guest: 3000, host: 3000, auto_correct: true
backend.vm.network :forwarded_port, guest: 8080, host: 8080, auto_correct: true
backend.vm.network :forwarded_port, guest: 8081, host: 8081, auto_correct: true
backend.vm.provision :shell, :path => "tests/provision_basic_el.sh"
backend.vm.provision :shell, :inline => "puppet apply /vagrant/tests/sensu-backend.pp"
backend.vm.provision :shell, :inline => "facter --custom-dir=/vagrant/lib/facter sensu_version"
end

config.vm.define "sensu-backend-peer2", primary: true, autostart: true do |backend|
backend.vm.box = "centos/7"
backend.vm.hostname = 'sensu-backend-peer2.example.com'
backend.vm.network :private_network, ip: ENV['ALTERNATE_IP'] || '192.168.52.12'
backend.vm.network :forwarded_port, guest: 2380, host: 2380, auto_correct: true
backend.vm.network :forwarded_port, guest: 3000, host: 3000, auto_correct: true
backend.vm.network :forwarded_port, guest: 8080, host: 8080, auto_correct: true
backend.vm.network :forwarded_port, guest: 8081, host: 8081, auto_correct: true
backend.vm.provision :shell, :path => "tests/provision_basic_el.sh"
backend.vm.provision :shell, :inline => "puppet apply /vagrant/tests/sensu-backend.pp"
backend.vm.provision :shell, :inline => "facter --custom-dir=/vagrant/lib/facter sensu_version"
end

config.vm.define "el7-agent", autostart: true do |agent|
agent.vm.box = "centos/7"
agent.vm.hostname = 'el7-agent.example.com'
Expand Down
98 changes: 98 additions & 0 deletions lib/puppet/provider/sensu_cluster_member/sensuctl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'sensuctl'))

Puppet::Type.type(:sensu_cluster_member).provide(:sensuctl, :parent => Puppet::Provider::Sensuctl) do
desc "Provider sensu_cluster_member using sensuctl"

mk_resource_methods

def self.instances
cluster_members = []

output = sensuctl('cluster', 'member-list', '--format', 'json')
Puppet.debug("sensu cluster members: #{output}")
begin
data = JSON.parse(output)
rescue JSON::ParserError => e
Puppet.debug('Unable to parse output from sensuctl cluster member-list')
data = {'members' => []}
end

data['members'].each do |d|
cluster_member = {}
cluster_member[:ensure] = :present
cluster_member[:name] = d['name']
# Skip member if no name, occurs if new member not yet started
next if cluster_member[:name].nil?
if d['ID'].is_a? Integer
cluster_member[:id] = d['ID'].to_s(16)
else
cluster_member[:id] = d['ID']
end
cluster_member[:peer_urls] = d['peerURLs']
cluster_members << new(cluster_member)
end
cluster_members
end

def self.prefetch(resources)
cluster_members = instances
resources.keys.each do |name|
if provider = cluster_members.find { |e| e.name == name }
resources[name].provider = provider
end
end
end

def exists?
@property_hash[:ensure] == :present
end

def initialize(value = {})
super(value)
@property_flush = {}
end

type_properties.each do |prop|
define_method "#{prop}=".to_sym do |value|
@property_flush[prop] = value
end
end

def create
peer_urls = resource[:peer_urls].join(',')
begin
output = sensuctl('cluster', 'member-add', resource[:name], peer_urls)
output.each_line do |line|
Puppet.info("Cluster member-add #{resource[:name]}: #{line}")
end
rescue Exception => e
raise Puppet::Error, "sensuctl cluster member-add #{resource[:name]} #{peer_urls} failed\nError message: #{e.message}"
end
@property_hash[:ensure] = :present
end

def flush
if @property_flush[:peer_urls]
peer_urls = @property_flush[:peer_urls].join(',')
begin
output = sensuctl('cluster', 'member-update', @property_hash[:id], peer_urls)
output.each_line do |line|
Puppet.info("Cluster member-update #{resource[:name]}: #{line}")
end
rescue Exception => e
raise Puppet::Error, "sensuctl cluster member-update #{resource[:name]} #{peer_urls} failed\nError message: #{e.message}"
end
end
@property_hash = resource.to_hash
end

def destroy
begin
sensuctl('cluster', 'member-remove', @property_hash[:id])
rescue Exception => e
raise Puppet::Error, "sensuctl cluster member-remove #{@property_hash[:id]} failed\nError message: #{e.message}"
end
@property_hash.clear
end
end

46 changes: 46 additions & 0 deletions lib/puppet/type/sensu_cluster_member.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require_relative '../../puppet_x/sensu/type'
require_relative '../../puppet_x/sensu/array_property'
require_relative '../../puppet_x/sensu/hash_property'
require_relative '../../puppet_x/sensu/integer_property'

Puppet::Type.newtype(:sensu_cluster_member) do
desc <<-DESC
Manages Sensu cluster members
@example Add a cluster member
sensu_cluster_member { 'backend2':
ensure => 'present',
peer_urls => ['http://192.168.52.12:2380'],
}
DESC

extend PuppetX::Sensu::Type
add_autorequires()

ensurable

newparam(:name, :namevar => true) do
desc "The name of the cluster member."
end

newproperty(:peer_urls, :array_matching => :all, :parent => PuppetX::Sensu::ArrayProperty) do
desc "Array of cluster peer URLs"
end

newparam(:id) do
desc "Cluster member ID - read-only"
validate do |value|
fail "id is read-only"
end
end

validate do
required_properties = [
:peer_urls,
]
required_properties.each do |property|
if self[:ensure] == :present && self[property].nil?
fail "You must provide a #{property}"
end
end
end
end
2 changes: 1 addition & 1 deletion spec/acceptance/00_backend_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'spec_helper_acceptance'

describe 'sensu::backend class' do
describe 'sensu::backend class', unless: RSpec.configuration.sensu_cluster do
node = only_host_with_role(hosts, 'sensu_backend')
context 'default' do
it 'should work without errors' do
Expand Down
2 changes: 1 addition & 1 deletion spec/acceptance/01_agent_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'spec_helper_acceptance'

describe 'sensu::agent class' do
describe 'sensu::agent class', unless: RSpec.configuration.sensu_cluster do
node = only_host_with_role(hosts, 'sensu_agent')
context 'default' do
it 'should work without errors' do
Expand Down
100 changes: 100 additions & 0 deletions spec/acceptance/02_backend_cluster_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
require 'spec_helper_acceptance'

describe 'sensu::backend cluster class', if: RSpec.configuration.sensu_cluster do
node1 = hosts_with_name(hosts, 'sensu_backend1')[0]
node2 = hosts_with_name(hosts, 'sensu_backend2')[0]
node3 = hosts_with_name(hosts, 'sensu_backend3')[0]
context 'new cluster' do
it 'should work without errors' do
node1_pp = <<-EOS
class { '::sensu::backend':
config_hash => {
'listen-client-urls' => 'http://0.0.0.0:2379',
'listen-peer-urls' => 'http://0.0.0.0:2380',
'initial-cluster' => 'backend1=http://#{fact_on(node1, 'ipaddress')}:2380,backend2=http://#{fact_on(node2, 'ipaddress')}:2380',
'initial-advertise-peer-urls' => 'http://#{fact_on(node1, 'ipaddress')}:2380',
'initial-cluster-state' => 'new',
'name' => 'backend1',
},
}
EOS
node2_pp = <<-EOS
class { '::sensu::backend':
config_hash => {
'listen-client-urls' => 'http://0.0.0.0:2379',
'listen-peer-urls' => 'http://0.0.0.0:2380',
'initial-cluster' => 'backend1=http://#{fact_on(node1, 'ipaddress')}:2380,backend2=http://#{fact_on(node2, 'ipaddress')}:2380',
'initial-advertise-peer-urls' => 'http://#{fact_on(node2, 'ipaddress')}:2380',
'initial-cluster-state' => 'new',
'name' => 'backend2',
},
}
EOS

apply_manifest_on(node1, node1_pp, :catch_failures => true)
#on node1, 'curl http://127.0.0.1:8080/info', :accept_all_exit_codes => true
apply_manifest_on(node2, node2_pp, :catch_failures => true)
# first node has to have agent started back up
#on node1, 'systemctl status sensu-agent -l', :accept_all_exit_codes => true
#on node1, 'curl http://127.0.0.1:8080/info', :accept_all_exit_codes => true
apply_manifest_on(node1, node1_pp, :catch_failures => true)
apply_manifest_on(node1, node1_pp, :catch_changes => true)
apply_manifest_on(node2, node2_pp, :catch_changes => true)
end

describe service('sensu-backend'), :node => node1 do
it { should be_enabled }
it { should be_running }
end
describe service('sensu-backend'), :node => node2 do
it { should be_enabled }
it { should be_running }
end
it 'should have cluster members' do
on node1, 'sensuctl cluster member-list --format json' do
data = JSON.parse(stdout)
expect(data['members'].size).to eq(2)
end
end
end

context 'Add sensu backend cluster member' do
it 'should add member' do
pp = <<-EOS
sensu_cluster_member { 'backend3':
peer_urls => ['http://#{fact_on(node3, 'ipaddress')}:2380'],
}
EOS
node3_pp = <<-EOS
class { '::sensu::backend':
config_hash => {
'listen-client-urls' => 'http://0.0.0.0:2379',
'listen-peer-urls' => 'http://0.0.0.0:2380',
'initial-cluster' => 'backend1=http://#{fact_on(node1, 'ipaddress')}:2380,backend2=http://#{fact_on(node2, 'ipaddress')}:2380,backend3=http://#{fact_on(node3, 'ipaddress')}:2380',
'initial-advertise-peer-urls' => 'http://#{fact_on(node3, 'ipaddress')}:2380',
'initial-cluster-state' => 'existing',
'name' => 'backend3',
},
}
EOS

apply_manifest_on(node1, pp, :catch_failures => true)
apply_manifest_on(node3, node3_pp, :catch_failures => true)
apply_manifest_on(node1, pp, :catch_changes => true)
apply_manifest_on(node3, node3_pp, :catch_changes => true)
end

describe service('sensu-backend'), :node => node3 do
it { should be_enabled }
it { should be_running }
end

it 'should have new cluster member' do
on node1, 'sensuctl cluster member-list --format json' do
data = JSON.parse(stdout)
member = data['members'].select { |m| m['name'] == 'backend3' }[0]
expect(member['peerURLs']).to eq(["http://#{fact_on(node3, 'ipaddress')}:2380"])
end
end
end
end
47 changes: 47 additions & 0 deletions spec/acceptance/nodesets/centos-7-cluster.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
HOSTS:
sensu_backend1:
roles:
- agent
- sensu_agent
- sensu_backend
- default
platform: el-7-x86_64
hypervisor: docker
image: centos:7
docker_preserve_image: true
docker_cmd:
- '/usr/sbin/init'
docker_image_commands:
- 'yum install -y wget'
docker_container_name: 'sensu-backend1-el7'
sensu_backend2:
roles:
- agent
platform: el-7-x86_64
hypervisor: docker
image: centos:7
docker_preserve_image: true
docker_cmd:
- '/usr/sbin/init'
docker_image_commands:
- 'yum install -y wget'
docker_container_name: 'sensu-backend2-el7'
sensu_backend3:
roles:
- agent
platform: el-7-x86_64
hypervisor: docker
image: centos:7
docker_preserve_image: true
docker_cmd:
- '/usr/sbin/init'
docker_image_commands:
- 'yum install -y wget'
docker_container_name: 'sensu-backend3-el7'
CONFIG:
log_level: debug
type: foss
ssh:
password: root
auth_methods: ["password"]

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"header": {
"cluster_id": 17565986561799419732,
"member_id": 10267398221920748210,
"raft_term": 42
},
"members": [
{
"ID": 8407831832234002477,
"name": "backend3",
"peerURLs": [
"http://172.17.0.4:2380"
],
"clientURLs": [
"http://0.0.0.0:2379"
]
},
{
"ID": 10267398221920748210,
"name": "backend1",
"peerURLs": [
"http://172.17.0.2:2380"
],
"clientURLs": [
"http://0.0.0.0:2379"
]
},
{
"ID": 16764669051924799718,
"name": "backend2",
"peerURLs": [
"http://172.17.0.3:2380"
],
"clientURLs": [
"http://0.0.0.0:2379"
]
}
]
}

Loading

0 comments on commit 6578dd0

Please sign in to comment.