From 00c8ba34ffe8f2e0d7dfd6fb6c3eddd6600557a0 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 24 May 2016 10:19:36 -0400 Subject: Squashed 'puppet/modules/haproxy/' content from commit af322a7 git-subtree-dir: puppet/modules/haproxy git-subtree-split: af322a73c013f80a958ab7d5d31d0c75cf6d0523 --- .fixtures.yml | 5 ++ .gemfile | 5 ++ .travis.yml | 23 ++++++ CHANGELOG | 5 ++ Modulefile | 12 +++ README.md | 87 ++++++++++++++++++++ Rakefile | 1 + manifests/balancermember.pp | 95 ++++++++++++++++++++++ manifests/init.pp | 149 +++++++++++++++++++++++++++++++++++ manifests/listen.pp | 95 ++++++++++++++++++++++ manifests/params.pp | 65 +++++++++++++++ spec/classes/haproxy_spec.rb | 138 ++++++++++++++++++++++++++++++++ spec/defines/balancermember_spec.rb | 82 +++++++++++++++++++ spec/defines/listen_spec.rb | 53 +++++++++++++ spec/spec.opts | 6 ++ spec/spec_helper.rb | 1 + templates/haproxy-base.cfg.erb | 21 +++++ templates/haproxy_balancermember.erb | 3 + templates/haproxy_listen_block.erb | 10 +++ tests/init.pp | 69 ++++++++++++++++ 20 files changed, 925 insertions(+) create mode 100644 .fixtures.yml create mode 100644 .gemfile create mode 100644 .travis.yml create mode 100644 CHANGELOG create mode 100644 Modulefile create mode 100644 README.md create mode 100644 Rakefile create mode 100644 manifests/balancermember.pp create mode 100644 manifests/init.pp create mode 100644 manifests/listen.pp create mode 100644 manifests/params.pp create mode 100644 spec/classes/haproxy_spec.rb create mode 100644 spec/defines/balancermember_spec.rb create mode 100644 spec/defines/listen_spec.rb create mode 100644 spec/spec.opts create mode 100644 spec/spec_helper.rb create mode 100644 templates/haproxy-base.cfg.erb create mode 100644 templates/haproxy_balancermember.erb create mode 100644 templates/haproxy_listen_block.erb create mode 100644 tests/init.pp diff --git a/.fixtures.yml b/.fixtures.yml new file mode 100644 index 00000000..8d6f22d6 --- /dev/null +++ b/.fixtures.yml @@ -0,0 +1,5 @@ +fixtures: + repositories: + concat: "git://github.com/ripienaar/puppet-concat.git" + symlinks: + haproxy: "#{source_dir}" diff --git a/.gemfile b/.gemfile new file mode 100644 index 00000000..9aad840c --- /dev/null +++ b/.gemfile @@ -0,0 +1,5 @@ +source :rubygems + +puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 2.7'] +gem 'puppet', puppetversion +gem 'puppetlabs_spec_helper', '>= 0.1.0' diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..fdbc95dc --- /dev/null +++ b/.travis.yml @@ -0,0 +1,23 @@ +language: ruby +rvm: + - 1.8.7 + - 1.9.3 +script: "rake spec" +branches: + only: + - master +env: + - PUPPET_VERSION=2.6.17 + - PUPPET_VERSION=2.7.19 + #- PUPPET_VERSION=3.0.1 # Breaks due to rodjek/rspec-puppet#58 +notifications: + email: false +gemfile: .gemfile +matrix: + exclude: + - rvm: 1.9.3 + gemfile: .gemfile + env: PUPPET_VERSION=2.6.17 + - rvm: 1.8.7 + gemfile: .gemfile + env: PUPPET_VERSION=3.0.1 diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 00000000..0b6d670f --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,5 @@ +2012-10-12 - Version 0.2.0 +- Initial public release +- Backwards incompatible changes all around +- No longer needs ordering passed for more than one listener +- Accepts multiple listen ips/ports/server_names diff --git a/Modulefile b/Modulefile new file mode 100644 index 00000000..e729739b --- /dev/null +++ b/Modulefile @@ -0,0 +1,12 @@ +name 'puppetlabs-haproxy' +version '0.2.0' +source 'git://github.com/puppetlabs/puppetlabs-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/puppetlabs/puppetlabs-haproxy' + +## Add dependencies, if any: +# dependency 'username/name', '>= 1.2.0' +dependency 'ripienaar/concat', '>= 0.1.0' diff --git a/README.md b/README.md new file mode 100644 index 00000000..d209e9ab --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +PuppetLabs Module for haproxy +============================= + +HAProxy is an HA proxying daemon for load-balancing to clustered services. It +can proxy TCP directly, or other kinds of traffic such as HTTP. + +Dependencies +------------ + +Tested and built on Debian, Ubuntu and CentOS + +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. + +Basic Usage +----------- + +This haproxy uses storeconfigs to collect and realize balancer member servers +on a load balancer server. + +*To install and configure HAProxy server listening on port 8140* + +```puppet +node 'haproxy-server' { + class { 'haproxy': } + haproxy::listen { 'puppet00': + ipaddress => $::ipaddress, + ports => '8140', + } +} +``` + +*To add backend loadbalance members* + +```puppet +node 'webserver01' { + @@haproxy::balancermember { $fqdn: + listening_service => 'puppet00', + server_names => $::hostname, + ipaddresses => $::ipaddress, + ports => '8140', + options => 'check' + } +} +``` + +Configuring haproxy options +--------------------------- + +The base `haproxy` class can accept two parameters which will configure basic +behaviour of the haproxy server daemon: + +- `global_options` to configure the `global` section in `haproxy.cfg` +- `defaults_options` to configure the `defaults` section in `haproxy.cfg` + +Configuring haproxy daemon listener +----------------------------------- + +One `haproxy::listen` defined resource should be defined for each HAProxy loadbalanced set of backend servers. The title of the `haproxy::listen` resource is the key to which balancer members will be proxied to. The `ipaddress` field should be the public ip address which the loadbalancer will be contacted on. The `ports` attribute can accept an array or comma-separated list of ports which should be proxied to the `haproxy::balancermemeber` nodes. + +Configuring haproxy loadbalanced member nodes +--------------------------------------------- + +The `haproxy::balacemember` defined resource should be exported from each node +which is serving loadbalanced traffic. the `listening_service` attribute will +associate it with `haproxy::listen` directives on the haproxy node. +`ipaddresses` and `ports` will be assigned to the member to be contacted on. If an array of `ipaddresses` and `server_names` are provided then they will be added to the config in lock-step. + + +Copyright and License +--------------------- + +Copyright (C) 2012 [Puppet Labs](https://www.puppetlabs.com/) Inc + +Puppet Labs can be contacted at: info@puppetlabs.com + +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. diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..cd3d3799 --- /dev/null +++ b/Rakefile @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/rake_tasks' diff --git a/manifests/balancermember.pp b/manifests/balancermember.pp new file mode 100644 index 00000000..a0e27539 --- /dev/null +++ b/manifests/balancermember.pp @@ -0,0 +1,95 @@ +# == 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::listen resource). This must match up with a declared +# haproxy::listen resource. +# +# [*ports*] +# An array or commas-separated list of ports 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. If you use an array in server_names and ipaddresses, the +# same port is used for all balancermembers. +# +# [*server_names*] +# The name of the balancer member server as known to haproxy in the +# listening service's configuration block. This defaults to the +# hostname. Can be an array of the same length as ipaddresses, +# in which case a balancermember is created for each pair of +# server_names and ipaddresses (in lockstep). +# +# [*ipaddresses*] +# The ip address used to contact the balancer member server. +# Can be an array, see documentation to server_names. +# +# [*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', +# ports => '8140', +# server_names => $::hostname, +# ipaddresses => $::ipaddress, +# options => 'check', +# } +# +# +# Collecting the resource on a load balancer +# +# Haproxy::Balancermember <<| listening_service == 'puppet00' |>> +# +# Creating the resource for multiple balancer members at once +# (for single-pass installation of haproxy without requiring a first +# pass to export the resources if you know the members in advance): +# +# haproxy::balancermember { 'haproxy': +# listening_service => 'puppet00', +# ports => '8140', +# server_names => ['server01', 'server02'], +# ipaddresses => ['192.168.56.200', '192.168.56.201'], +# options => 'check', +# } +# +# (this resource can be declared anywhere) +# +define haproxy::balancermember ( + $listening_service, + $ports, + $server_names = $::hostname, + $ipaddresses = $::ipaddress, + $options = '' +) { + # Template uses $ipaddresses, $server_name, $ports, $option + concat::fragment { "${listening_service}_balancermember_${name}": + order => "20-${listening_service}-${name}", + target => '/etc/haproxy/haproxy.cfg', + content => template('haproxy/haproxy_balancermember.erb'), + } +} diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 00000000..b91591a3 --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,149 @@ +# == Class: haproxy +# +# A Puppet module, using storeconfigs, to model an haproxy configuration. +# Currently VERY limited - 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. +# +# [*version*] +# Allows you to specify what version of the package to install. +# Default is simply 'present' +# +# [*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. +# +# [*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, +# 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' +# }, +# 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' +# }, +# } +# +class haproxy ( + $manage_service = true, + $enable = true, + $version = 'present', + $global_options = $haproxy::params::global_options, + $defaults_options = $haproxy::params::defaults_options +) inherits haproxy::params { + include concat::setup + + package { 'haproxy': + ensure => $enable ? { + true => $version, + false => absent, + }, + name => 'haproxy', + } + + if $enable { + concat { '/etc/haproxy/haproxy.cfg': + owner => '0', + group => '0', + mode => '0644', + require => Package['haproxy'], + notify => $manage_service ? { + true => Service['haproxy'], + false => undef, + }, + } + + # Simple Header + concat::fragment { '00-header': + target => '/etc/haproxy/haproxy.cfg', + order => '01', + content => "# This file managed by Puppet\n", + } + + # Template uses $global_options, $defaults_options + concat::fragment { 'haproxy-base': + target => '/etc/haproxy/haproxy.cfg', + order => '10', + content => template('haproxy/haproxy-base.cfg.erb'), + } + + if ($::osfamily == 'Debian') { + file { '/etc/default/haproxy': + content => 'ENABLED=1', + require => Package['haproxy'], + before => $manage_service ? { + true => Service['haproxy'], + false => undef, + }, + } + } + + file { $global_options['chroot']: + ensure => directory, + owner => $global_options['user'], + group => $global_options['group'], + mode => '0550', + require => Package['haproxy'] + } + + } + + if $manage_service { + service { 'haproxy': + ensure => $enable ? { + true => running, + false => stopped, + }, + enable => $enable ? { + true => true, + false => false, + }, + name => 'haproxy', + hasrestart => true, + hasstatus => true, + require => [ + Concat['/etc/haproxy/haproxy.cfg'], + File[$global_options['chroot']], + ], + } + } +} diff --git a/manifests/listen.pp b/manifests/listen.pp new file mode 100644 index 00000000..00636e3d --- /dev/null +++ b/manifests/listen.pp @@ -0,0 +1,95 @@ +# == Define Resource Type: haproxy::listen +# +# 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 +# +# [*ports*] +# Ports on which the proxy will listen for connections on the ip address +# specified in the virtual_ip parameter. Accepts either a single +# comma-separated string or an array of strings which may be ports or +# hyphenated port ranges. +# +# [*ipaddress*] +# 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'. +# +# [*options*] +# A hash of options that are inserted into the listening service +# configuration block. +# +# [*collect_exported*] +# Boolean, default 'true'. True means 'collect exported @@balancermember resources' +# (for the case when every balancermember node exports itself), false means +# 'rely on the existing declared balancermember resources' (for the case when you +# know the full set of balancermembers in advance and use haproxy::balancermember +# with array arguments, which allows you to deploy everything in 1 run) +# +# +# === Examples +# +# Exporting the resource for a balancer member: +# +# haproxy::listen { 'puppet00': +# ipaddress => $::ipaddress, +# ports => '18140', +# mode => 'tcp', +# options => { +# 'option' => [ +# 'tcplog', +# 'ssl-hello-chk' +# ], +# 'balance' => 'roundrobin' +# }, +# } +# +# === Authors +# +# Gary Larizza +# +define haproxy::listen ( + $ports, + $ipaddress = [$::ipaddress], + $mode = 'tcp', + $collect_exported = true, + $options = { + 'option' => [ + 'tcplog', + 'ssl-hello-chk' + ], + 'balance' => 'roundrobin' + } +) { + # Template uses: $name, $ipaddress, $ports, $options + concat::fragment { "${name}_listen_block": + order => "20-${name}-00", + target => '/etc/haproxy/haproxy.cfg', + content => template('haproxy/haproxy_listen_block.erb'), + } + + if $collect_exported { + Haproxy::Balancermember <<| listening_service == $name |>> + } + # else: the resources have been created and they introduced their + # concat fragments. We don't have to do anything about them. +} diff --git a/manifests/params.pp b/manifests/params.pp new file mode 100644 index 00000000..53442ddc --- /dev/null +++ b/manifests/params.pp @@ -0,0 +1,65 @@ +# == Class: haproxy::params +# +# 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::params { + case $osfamily { + Redhat: { + $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' + } + $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' + } + } + Debian: { + $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' + } + $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 $::osfamily operating system is not supported with the haproxy module") } + } +} diff --git a/spec/classes/haproxy_spec.rb b/spec/classes/haproxy_spec.rb new file mode 100644 index 00000000..4b5902ce --- /dev/null +++ b/spec/classes/haproxy_spec.rb @@ -0,0 +1,138 @@ +require 'spec_helper' + +describe 'haproxy', :type => :class do + let(:default_facts) do + { + :concat_basedir => '/dne', + :ipaddress => '10.10.10.10' + } + end + context 'on supported platforms' do + describe 'for OS-agnostic configuration' do + ['Debian', 'RedHat'].each do |osfamily| + context "on #{osfamily} family operatingsystems" do + let(:facts) do + { :osfamily => osfamily }.merge default_facts + end + let(:params) do + {'enable' => true} + end + it { should include_class('concat::setup') } + it 'should install the haproxy package' do + subject.should contain_package('haproxy').with( + 'ensure' => 'present' + ) + end + it 'should install the haproxy service' do + subject.should contain_service('haproxy').with( + 'ensure' => 'running', + 'enable' => 'true', + 'hasrestart' => 'true', + 'hasstatus' => 'true', + 'require' => [ + 'Concat[/etc/haproxy/haproxy.cfg]', + 'File[/var/lib/haproxy]' + ] + ) + end + it 'should set up /etc/haproxy/haproxy.cfg as a concat resource' do + subject.should contain_concat('/etc/haproxy/haproxy.cfg').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644' + ) + end + it 'should manage the chroot directory' do + subject.should contain_file('/var/lib/haproxy').with( + 'ensure' => 'directory' + ) + end + it 'should contain a header concat fragment' do + subject.should contain_concat__fragment('00-header').with( + 'target' => '/etc/haproxy/haproxy.cfg', + 'order' => '01', + 'content' => "# This file managed by Puppet\n" + ) + end + it 'should contain a haproxy-base concat fragment' do + subject.should contain_concat__fragment('haproxy-base').with( + 'target' => '/etc/haproxy/haproxy.cfg', + 'order' => '10' + ) + end + describe 'Base concat fragment contents' do + let(:contents) { param_value(subject, 'concat::fragment', 'haproxy-base', 'content').split("\n") } + it 'should contain global and defaults sections' do + contents.should include('global') + contents.should include('defaults') + end + it 'should log to an ip address for local0' do + contents.should be_any { |match| match =~ / log \d+(\.\d+){3} local0/ } + end + it 'should specify the default chroot' do + contents.should include(' chroot /var/lib/haproxy') + end + it 'should specify the correct user' do + contents.should include(' user haproxy') + end + it 'should specify the correct group' do + contents.should include(' group haproxy') + end + it 'should specify the correct pidfile' do + contents.should include(' pidfile /var/run/haproxy.pid') + end + end + end + context "on #{osfamily} family operatingsystems without managing the service" do + let(:facts) do + { :osfamily => osfamily }.merge default_facts + end + let(:params) do + { + 'enable' => true, + 'manage_service' => false, + } + end + it { should include_class('concat::setup') } + it 'should install the haproxy package' do + subject.should contain_package('haproxy').with( + 'ensure' => 'present' + ) + end + it 'should install the haproxy service' do + subject.should_not contain_service('haproxy') + end + end + end + end + describe 'for OS-specific configuration' do + context 'only on Debian family operatingsystems' do + let(:facts) do + { :osfamily => 'Debian' }.merge default_facts + end + it 'should manage haproxy service defaults' do + subject.should contain_file('/etc/default/haproxy').with( + 'before' => 'Service[haproxy]', + 'require' => 'Package[haproxy]' + ) + verify_contents(subject, '/etc/default/haproxy', ['ENABLED=1']) + end + end + context 'only on RedHat family operatingsystems' do + let(:facts) do + { :osfamily => 'RedHat' }.merge default_facts + end + end + end + end + context 'on unsupported operatingsystems' do + let(:facts) do + { :osfamily => 'RainbowUnicorn' }.merge default_facts + end + it do + expect { + should contain_service('haproxy') + }.to raise_error(Puppet::Error, /operating system is not supported with the haproxy module/) + end + end +end diff --git a/spec/defines/balancermember_spec.rb b/spec/defines/balancermember_spec.rb new file mode 100644 index 00000000..74bc7a8b --- /dev/null +++ b/spec/defines/balancermember_spec.rb @@ -0,0 +1,82 @@ +require 'spec_helper' + +describe 'haproxy::balancermember' do + let(:title) { 'tyler' } + let(:facts) do + { + :ipaddress => '1.1.1.1', + :hostname => 'dero' + } + end + + context 'with a single balancermember option' do + let(:params) do + { + :name => 'tyler', + :listening_service => 'croy', + :ports => '18140', + :options => 'check' + } + end + + it { should contain_concat__fragment('croy_balancermember_tyler').with( + 'order' => '20-croy-tyler', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => " server dero 1.1.1.1:18140 check\n\n" + ) } + end + + context 'with multiple balancermember options' do + let(:params) do + { + :name => 'tyler', + :listening_service => 'croy', + :ports => '18140', + :options => ['check', 'close'] + } + end + + it { should contain_concat__fragment('croy_balancermember_tyler').with( + 'order' => '20-croy-tyler', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => " server dero 1.1.1.1:18140 check close\n\n" + ) } + end + + context 'with multiple servers' do + let(:params) do + { + :name => 'tyler', + :listening_service => 'croy', + :ports => '18140', + :server_names => ['server01', 'server02'], + :ipaddresses => ['192.168.56.200', '192.168.56.201'], + :options => ['check'] + } + end + + it { should contain_concat__fragment('croy_balancermember_tyler').with( + 'order' => '20-croy-tyler', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => " server server01 192.168.56.200:18140 check\n server server02 192.168.56.201:18140 check\n\n" + ) } + end + context 'with multiple servers and multiple ports' do + let(:params) do + { + :name => 'tyler', + :listening_service => 'croy', + :ports => ['18140','18150'], + :server_names => ['server01', 'server02'], + :ipaddresses => ['192.168.56.200', '192.168.56.201'], + :options => ['check'] + } + end + + it { should contain_concat__fragment('croy_balancermember_tyler').with( + 'order' => '20-croy-tyler', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => " server server01 192.168.56.200:18140,192.168.56.200:18150 check\n server server02 192.168.56.201:18140,192.168.56.201:18150 check\n\n" + ) } + end +end diff --git a/spec/defines/listen_spec.rb b/spec/defines/listen_spec.rb new file mode 100644 index 00000000..31dd4c85 --- /dev/null +++ b/spec/defines/listen_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe 'haproxy::listen' do + let(:title) { 'tyler' } + let(:facts) {{ :ipaddress => '1.1.1.1' }} + context "when only one port is provided" do + let(:params) do + { + :name => 'croy', + :ports => '18140' + } + end + + it { should contain_concat__fragment('croy_listen_block').with( + 'order' => '20-croy-00', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => "listen croy\n\n bind 1.1.1.1:18140\n\n balance roundrobin\n option tcplog\n option ssl-hello-chk\n" + ) } + end + context "when an array of ports is provided" do + let(:params) do + { + :name => 'apache', + :ipaddress => '23.23.23.23', + :ports => [ + '80', + '443', + ] + } + end + + it { should contain_concat__fragment('apache_listen_block').with( + 'order' => '20-apache-00', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => "listen apache\n\n bind 23.23.23.23:80\n\n bind 23.23.23.23:443\n\n balance roundrobin\n option tcplog\n option ssl-hello-chk\n" + ) } + end + context "when a comma-separated list of ports is provided" do + let(:params) do + { + :name => 'apache', + :ipaddress => '23.23.23.23', + :ports => '80,443' + } + end + + it { should contain_concat__fragment('apache_listen_block').with( + 'order' => '20-apache-00', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => "listen apache\n\n bind 23.23.23.23:80\n\n bind 23.23.23.23:443\n\n balance roundrobin\n option tcplog\n option ssl-hello-chk\n" + ) } + end +end diff --git a/spec/spec.opts b/spec/spec.opts new file mode 100644 index 00000000..91cd6427 --- /dev/null +++ b/spec/spec.opts @@ -0,0 +1,6 @@ +--format +s +--colour +--loadby +mtime +--backtrace diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 00000000..2c6f5664 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/templates/haproxy-base.cfg.erb b/templates/haproxy-base.cfg.erb new file mode 100644 index 00000000..f25d5c34 --- /dev/null +++ b/templates/haproxy-base.cfg.erb @@ -0,0 +1,21 @@ +global +<% @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 +<% @defaults_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/templates/haproxy_balancermember.erb b/templates/haproxy_balancermember.erb new file mode 100644 index 00000000..1d03f565 --- /dev/null +++ b/templates/haproxy_balancermember.erb @@ -0,0 +1,3 @@ +<% Array(ipaddresses).zip(Array(server_names)).each do |ipaddress,host| -%> + server <%= host %> <%= ipaddress %>:<%= Array(ports).collect {|x|x.split(',')}.flatten.join(",#{ipaddress}:") %> <%= Array(options).join(" ") %> +<% end %> diff --git a/templates/haproxy_listen_block.erb b/templates/haproxy_listen_block.erb new file mode 100644 index 00000000..129313f1 --- /dev/null +++ b/templates/haproxy_listen_block.erb @@ -0,0 +1,10 @@ +listen <%= name %> + mode <%= mode %> +<% Array(ipaddress).uniq.each do |virtual_ip| (ports.is_a?(Array) ? ports : Array(ports.split(","))).each do |port| %> + bind <%= virtual_ip %>:<%= port %> +<% end end %> +<% options.sort.each do |key, val| -%> +<% Array(val).each do |item| -%> + <%= key %> <%= item %> +<% end -%> +<% end -%> diff --git a/tests/init.pp b/tests/init.pp new file mode 100644 index 00000000..77590ac8 --- /dev/null +++ b/tests/init.pp @@ -0,0 +1,69 @@ +# Declare haproxy base class with configuration options +class { 'haproxy': + enable => true, + 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', + }, + 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::listen 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::listen { 'puppet00': + order => '20', + ipaddress => $::ipaddress, + ports => '18140', + options => { + 'option' => [ + 'tcplog', + 'ssl-hello-chk', + ], + 'balance' => 'roundrobin', + }, +} +haproxy::listen { 'stats': + order => '30', + ipaddress => '', + ports => '9090', + options => { + 'mode' => 'http', + 'stats' => [ + 'uri /', + 'auth puppet:puppet' + ], + }, +} -- cgit v1.2.3