diff options
author | Gary Larizza <gary@puppetlabs.com> | 2012-05-07 14:26:21 -0700 |
---|---|---|
committer | Gary Larizza <gary@puppetlabs.com> | 2012-05-07 14:26:21 -0700 |
commit | c4799e59b9d9891e6c296c554a11814f14a5abfc (patch) | |
tree | 1ba82aa54bf523abb30ee03255114ba58fef1d20 |
Initial Commit
-rw-r--r-- | Modulefile | 12 | ||||
-rw-r--r-- | README | 14 | ||||
-rw-r--r-- | manifests/balancermember.pp | 86 | ||||
-rw-r--r-- | manifests/config.pp | 75 | ||||
-rw-r--r-- | manifests/data.pp | 29 | ||||
-rw-r--r-- | manifests/init.pp | 110 | ||||
-rw-r--r-- | spec/spec_helper.rb | 17 | ||||
-rw-r--r-- | templates/haproxy-base.cfg.erb | 21 | ||||
-rw-r--r-- | templates/haproxy_balancermember.erb | 1 | ||||
-rw-r--r-- | templates/haproxy_config_block.erb | 11 | ||||
-rw-r--r-- | tests/init.pp | 50 |
11 files changed, 426 insertions, 0 deletions
diff --git a/Modulefile b/Modulefile new file mode 100644 index 0000000..c8e5647 --- /dev/null +++ b/Modulefile @@ -0,0 +1,12 @@ +name 'puppet-haproxy' +version '0.0.1' +source 'git://github.com/glarizza/puppet-haproxy' +author 'Puppet Labs' +license 'Apache License, Version 2.0' +summary 'Haproxy Module' +description 'An Haproxy module for Redhat family OSes using Storeconfigs' +project_page 'http://github.com/glarizza/puppet-haproxy' + +## Add dependencies, if any: +# dependency 'username/name', '>= 1.2.0' +dependency 'ripienaar/concat', '>= 0.1.0' @@ -0,0 +1,14 @@ +haproxy + +This haproxy uses storeconfigs to collect and realize balancer member servers +on a load balancer server. Currently Redhat family OSes are supported, but +support for other OS Families shouldn't be too difficult to merge in. Pull +requests accepted! + +License +------- +Apache 2.0 + +Contact +------- +Gary Larizza <gary@puppetlabs.com> diff --git a/manifests/balancermember.pp b/manifests/balancermember.pp new file mode 100644 index 0000000..50e90c0 --- /dev/null +++ b/manifests/balancermember.pp @@ -0,0 +1,86 @@ +# == Define Resource Type: haproxy::balancermember +# +# This type will setup a balancer member inside a listening service +# configuration block in /etc/haproxy/haproxy.cfg on the load balancer. +# currently it only has the ability to specify the instance name, +# ip address, port, and whether or not it is a backup. More features +# can be added as needed. The best way to implement this is to export +# this resource for all haproxy balancer member servers, and then collect +# them on the main haproxy load balancer. +# +# === Requirement/Dependencies: +# +# Currently requires the ripienaar/concat module on the Puppet Forge and +# uses storeconfigs on the Puppet Master to export/collect resources +# from all balancer members. +# +# === Parameters +# +# [*name*] +# The title of the resource is arbitrary and only utilized in the concat +# fragment name. +# +# [*listening_service*] +# The haproxy service's instance name (or, the title of the +# haproxy::config resource). This must match up with a declared +# haproxy::config resource. +# +# [*balancer_port*] +# A unique port for which the balancer member will accept connections +# from the load balancer. Note that cookie values aren't yet supported, +# but shouldn't be difficult to add to the configuration. +# +# [*order*] +# The order, or numerical weight, of the fragment created by this defined +# resource type. This is necessary to ensure the fragment is associated +# with the correct listening service instance. +# +# [*server_name*] +# The name of the balancer member server as known to haproxy in the +# listening service's configuration block. This defaults to the +# hostname +# +# [*balancer_ip*] +# The ip address used to contact the balancer member server +# +# [*balancermember_options*] +# An array of options to be specified after the server declaration +# in the listening service's configuration block. +# +# +# === Examples +# +# Exporting the resource for a balancer member: +# +# @@haproxy::balancermember { 'haproxy': +# listening_service => 'puppet00', +# balancer_port => '8140', +# order => '21', +# server_name => $::hostname, +# balancer_ip => $::ipaddress, +# balancermember_options => 'check', +# } +# +# +# Collecting the resource on a load balancer +# +# Haproxy::Balancermember <<| listening_service == 'puppet00' |>> +# +# === Authors +# +# Gary Larizza <gary@puppetlabs.com> +# +define haproxy::balancermember ( + $listening_service, + $balancer_port, + $order = '20', + $server_name = $::hostname, + $balancer_ip = $::ipaddress, + $balancermember_options = '' +) { + concat::fragment { "${listening_service}_balancermember_${name}": + order => $order, + target => '/etc/haproxy/haproxy.cfg', + content => template('haproxy/haproxy_balancermember.erb'), + } +} diff --git a/manifests/config.pp b/manifests/config.pp new file mode 100644 index 0000000..55b40d7 --- /dev/null +++ b/manifests/config.pp @@ -0,0 +1,75 @@ +# == Define Resource Type: haproxy::config +# +# This type will setup a listening service configuration block inside +# the haproxy.cfg file on an haproxy load balancer. Each listening service +# configuration needs one or more load balancer member server (that can be +# declared with the haproxy::balancermember defined resource type). Using +# storeconfigs, you can export the haproxy::balancermember resources on all +# load balancer member servers, and then collect them on a single haproxy +# load balancer server. +# +# === Requirement/Dependencies: +# +# Currently requires the ripienaar/concat module on the Puppet Forge and +# uses storeconfigs on the Puppet Master to export/collect resources +# from all balancer members. +# +# === Parameters +# +# [*name*] +# The namevar of the defined resource type is the listening service's name. +# This name goes right after the 'listen' statement in haproxy.cfg +# +# [*virtual_ip_port*] +# A unique port, or a port range for which the proxy will accept connections +# for the ip address specified in the virtual_ip parameter. +# +# [*order*] +# The order, or numerical weight, of the fragment created by this defined +# resource type. This is necessary to ensure the fragment is associated +# with the correct listening service instance. +# +# [*virtual_ip*] +# The ip address the proxy binds to. Empty addresses, '*', and '0.0.0.0' +# mean that the proxy listens to all valid addresses on the system. +# +# [*mode*] +# The mode of operation for the listening service. Valid values are 'tcp', +# HTTP', and 'health'. +# +# [*haproxy_config_options*] +# A hash of options that are inserted into the listening service +# configuration block. +# +# +# === Examples +# +# Exporting the resource for a balancer member: +# +# haproxy::config { 'puppet00': +# order => '20', +# virtual_ip => $::ipaddress, +# virtual_ip_port => '18140', +# mode => 'tcp', +# haproxy_config_options => {'option' => 'tcplog', 'option' => 'ssl-hello-chk', 'balance' => 'roundrobin'}, +# } +# +# === Authors +# +# Gary Larizza <gary@puppetlabs.com> +# +define haproxy::config ( + $virtual_ip_port, + $order = '20', + $virtual_ip = $::ipaddress, + $mode = 'tcp', + $haproxy_config_options = {'option' => 'tcplog', 'option' => 'ssl-hello-chk', 'balance' => 'roundrobin'}, +) { + concat::fragment { "${name}_config_block": + order => $order, + target => '/etc/haproxy/haproxy.cfg', + content => template('haproxy/haproxy_config_block.erb'), + } + + Haproxy::Balancermember <<| listening_service == $name |>> +} diff --git a/manifests/data.pp b/manifests/data.pp new file mode 100644 index 0000000..aa49285 --- /dev/null +++ b/manifests/data.pp @@ -0,0 +1,29 @@ +# == Class: haproxy::data +# +# This is a container class holding default parameters for for haproxy class. +# currently, only the Redhat family is supported, but this can be easily +# extended by changing package names and configuration file paths. +# +class haproxy::data { + case $osfamily { + Redhat: { + $haproxy_global_options = { 'log' => "${::ipaddress} local0", + 'chroot' => '/var/lib/haproxy', + 'pidfile' => '/var/run/haproxy.pid', + 'maxconn' => '4000', + 'user' => 'haproxy', + 'group' => 'haproxy', + 'daemon' => '', + 'stats' => 'socket /var/lib/haproxy/stats' + } + $haproxy_defaults_options = { 'log' => 'global', + 'stats' => 'enable', + 'option' => 'redispatch', + 'retries' => '3', + 'timeout' => ['http-request 10s', 'queue 1m', 'connect 10s', 'client 1m', 'server 1m', 'check 10s'], + 'maxconn' => '8000' + } + } + default: { fail("The $::operatingsystem operating system is not supported with the haproxy module") } + } +} diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 0000000..6dde629 --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,110 @@ +# == Class: puppet-haproxy +# +# A Puppet module, using storeconfigs, to model an haproxy configuration. +# Currently VERY limited - assumes Redhat/CentOS setup. Pull requests accepted! +# +# === Requirement/Dependencies: +# +# Currently requires the ripienaar/concat module on the Puppet Forge and +# uses storeconfigs on the Puppet Master to export/collect resources +# from all balancer members. +# +# === Parameters +# +# [*enable*] +# Chooses whether haproxy should be installed or ensured absent. +# Currently ONLY accepts valid boolean true/false values. +# +# [*haproxy_global_options*] +# A hash of all the haproxy global options. If you want to specify more +# than one option (i.e. multiple timeout or stats options), pass those +# options as an array and you will get a line for each of them in the +# resultant haproxy.cfg file. +# +# [*haproxy_defaults_options*] +# A hash of all the haproxy defaults options. If you want to specify more +# than one option (i.e. multiple timeout or stats options), pass those +# options as an array and you will get a line for each of them in the +# resultant haproxy.cfg file. +# +# +# === Examples +# +# class { 'haproxy': +# enable => true, +# haproxy_global_options => { 'log' => "${::ipaddress} local0", +# 'chroot' => '/var/lib/haproxy', +# 'pidfile' => '/var/run/haproxy.pid', +# 'maxconn' => '4000', +# 'user' => 'haproxy', +# 'group' => 'haproxy', +# 'daemon' => '', +# 'stats' => 'socket /var/lib/haproxy/stats' +# }, +# haproxy_defaults_options => { 'log' => 'global', +# 'stats' => 'enable', +# 'option' => 'redispatch', +# 'retries' => '3', +# 'timeout' => ['http-request 10s', 'queue 1m', 'connect 10s', 'client 1m', 'server 1m', 'check 10s'], +# 'maxconn' => '8000' +# }, +# +# } +# +# === Authors +# +# Gary Larizza <gary@puppetlabs.com> +# +class haproxy ( + $enable = true, + $haproxy_global_options = $haproxy::data::haproxy_global_options, + $haproxy_defaults_options = $haproxy::data::haproxy_defaults_options +) inherits haproxy::data { + include concat::setup + + package { 'haproxy': + ensure => $enable ? { + true => present, + false => absent, + }, + name => 'haproxy', + } + + if $enable { + concat { '/etc/haproxy/haproxy.cfg': + owner => '0', + group => '0', + mode => '0644', + require => Package['haproxy'], + notify => Service['haproxy'], + } + + # Simple Header + concat::fragment { '00-header': + target => '/etc/haproxy/haproxy.cfg', + order => '01', + content => "# This file managed by Puppet\n", + } + + # Most of the variables are used inside the haproxy-base.cfg.erb template + concat::fragment { 'haproxy-base': + target => '/etc/haproxy/haproxy.cfg', + order => '10', + content => template('haproxy/haproxy-base.cfg.erb'), + } + } + + service { 'haproxy': + ensure => $enable ? { + true => running, + false => stopped, + }, + enable => $enable ? { + true => true, + false => false, + }, + name => 'haproxy', + hasstatus => true, + require => Concat['/etc/haproxy/haproxy.cfg'], + } +} diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..5fda588 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,17 @@ +dir = File.expand_path(File.dirname(__FILE__)) +$LOAD_PATH.unshift File.join(dir, 'lib') + +require 'mocha' +require 'puppet' +require 'rspec' +require 'spec/autorun' + +Spec::Runner.configure do |config| + config.mock_with :mocha +end + +# We need this because the RAL uses 'should' as a method. This +# allows us the same behaviour but with a different method name. +class Object + alias :must :should +end diff --git a/templates/haproxy-base.cfg.erb b/templates/haproxy-base.cfg.erb new file mode 100644 index 0000000..3e21436 --- /dev/null +++ b/templates/haproxy-base.cfg.erb @@ -0,0 +1,21 @@ +global +<% haproxy_global_options.sort.each do |key,val| -%> +<% if val.is_a?(Array) -%> +<% val.each do |item| -%> + <%= key %> <%= item %> +<% end -%> +<% else -%> + <%= key %> <%= val %> +<% end -%> +<% end -%> + +defaults +<% haproxy_defaults_options.sort.each do |key,val| -%> +<% if val.is_a?(Array) -%> +<% val.each do |item| -%> + <%= key %> <%= item %> +<% end -%> +<% else -%> + <%= key %> <%= val %> +<% end -%> +<% end -%>
\ No newline at end of file diff --git a/templates/haproxy_balancermember.erb b/templates/haproxy_balancermember.erb new file mode 100644 index 0000000..b739e11 --- /dev/null +++ b/templates/haproxy_balancermember.erb @@ -0,0 +1 @@ + server <%= server_name %> <%= balancer_ip %>:<%= balancer_port %> <% balancermember_options.each do |item| %> <%= item %> <% end %> diff --git a/templates/haproxy_config_block.erb b/templates/haproxy_config_block.erb new file mode 100644 index 0000000..8737dfc --- /dev/null +++ b/templates/haproxy_config_block.erb @@ -0,0 +1,11 @@ + +listen <%= name %> <%= virtual_ip %>:<%= virtual_ip_port %> +<% haproxy_config_options.sort.each do |key, val| -%> +<% if val.is_a?(Array) -%> +<% val.each do |item| -%> + <%= key %> <%= item %> +<% end -%> +<% else -%> + <%= key %> <%= val %> +<% end -%> +<% end -%> diff --git a/tests/init.pp b/tests/init.pp new file mode 100644 index 0000000..32c32c7 --- /dev/null +++ b/tests/init.pp @@ -0,0 +1,50 @@ +# Declare haproxy base class with configuration options +class { 'haproxy': + enable => true, + haproxy_global_options => { 'log' => "${::ipaddress} local0", + 'chroot' => '/var/lib/haproxy', + 'pidfile' => '/var/run/haproxy.pid', + 'maxconn' => '4000', + 'user' => 'haproxy', + 'group' => 'haproxy', + 'daemon' => '', + 'stats' => 'socket /var/lib/haproxy/stats' + }, + haproxy_defaults_options => { 'log' => 'global', + 'stats' => 'enable', + 'option' => 'redispatch', + 'retries' => '3', + 'timeout' => ['http-request 10s', 'queue 1m', 'connect 10s', 'client 1m', 'server 1m', 'check 10s'], + 'maxconn' => '8000' + }, + +} + +# Export a balancermember server, note that the listening_service parameter +# will/must correlate with an haproxy::config defined resource type. +@@haproxy::balancermember { $fqdn: + order => '21', + listening_service => 'puppet00', + server_name => $::hostname, + balancer_ip => $::ipaddress, + balancer_port => '8140', + balancermember_options => 'check' +} + +# Declare a couple of Listening Services for haproxy.cfg +# Note that the balancermember server resources are being collected in +# the haproxy::config defined resource type with the following line: +# Haproxy::Balancermember <<| listening_service == $name |>> +haproxy::config { 'puppet00': + order => '20', + virtual_ip => $::ipaddress, + virtual_ip_port => '18140', + haproxy_config_options => { 'option' => ['tcplog', 'ssl-hello-chk'], 'balance' => 'roundrobin' }, +} +haproxy::config { 'stats': + order => '30', + virtual_ip => '', + virtual_ip_port => '9090', + haproxy_config_options => { 'mode' => 'http', 'stats' => ['uri /', 'auth puppet:puppet'] }, +} + |