diff --git a/README.md b/README.md index e0992fa5..69f43559 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ ##Overview -The haproxy module provides the ability to install, configure, and manage HAProxy. +The haproxy module provides the ability to install, configure, and manage HAProxy. ##Module Description @@ -121,6 +121,28 @@ haproxy::listen { 'puppet00': }, } ``` +###Configuring multi-network daemon listener + +One might have more advanced needs for the listen block, then use the `$bind` parameter: + +```puppet +haproxy::listen { 'puppet00': + mode => 'tcp', + options => { + 'option' => [ + 'tcplog', + 'ssl-hello-chk', + ], + 'balance' => 'roundrobin', + }, + bind => { + '10.0.0.1:443' => ['ssl', 'crt', 'puppetlabs.com'], + '168.12.12.12:80' => [], + '192.168.122.42:80' => [] + }, +} +``` +Note: `$ports` or `$ipaddress` and `$bind` are mutually exclusive ###Configuring HAProxy load-balanced member nodes @@ -285,7 +307,10 @@ This type sets up a frontend service configuration block in haproxy.cfg. The HAP **Parameters** #####`bind_options` -Lists an array of options to be specified after the bind declaration in the bind's configuration block. +Lists an array of options to be specified after the bind declaration in the bind's configuration block. **Deprecated**: This parameter is being deprecated in favor of $bind + +#####`bind` +A hash of ipaddress:port, with the haproxy bind options the address will have in the listening service's configuration block. #####`ipaddress` Specifies the IP address the proxy binds to. No value, '\*', and '0.0.0.0' mean that the proxy listens to all valid addresses on the system. @@ -333,7 +358,10 @@ Using storeconfigs, you can export the `haproxy::balancermember` resources on al **Parameters:** #####`bind_options` -Sets the options to be specified after the bind declaration in the listening service's configuration block. Displays as an array. +Sets the options to be specified after the bind declaration in the listening service's configuration block. Displays as an array. **Deprecated**: This parameter is being deprecated in favor of $bind + +#####`bind` +A hash of ipaddress:port, with the haproxy bind options the address will have in the listening service's configuration block. #####`collect_exported` Enables exported resources from `haproxy::balancermember` to be collected, serving as a form of autodiscovery. Displays as a Boolean and defaults to 'true'. diff --git a/manifests/frontend.pp b/manifests/frontend.pp index 6bd55e71..95ed214a 100644 --- a/manifests/frontend.pp +++ b/manifests/frontend.pp @@ -21,17 +21,22 @@ # comma-separated string or an array of strings which may be ports or # hyphenated port ranges. # +# [*bind*] +# Set of ip addresses, port and bind options +# $bind = { '10.0.0.1:80' => ['ssl', 'crt', '/path/to/my/crt.pem'] } +# # [*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. +# 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 frontend service. Valid values are undef, # 'tcp', 'http', and 'health'. # # [*bind_options*] -# An array of options to be specified after the bind declaration in the -# bind's configuration block. +# (Deprecated) An array of options to be specified after the bind declaration +# in the listening serivce's configuration block. # # [*options*] # A hash of options that are inserted into the frontend service @@ -61,18 +66,32 @@ # Gary Larizza # define haproxy::frontend ( - $ports, + $ports = undef, $ipaddress = [$::ipaddress], + $bind = undef, $mode = undef, - $bind_options = undef, $collect_exported = true, $options = { 'option' => [ 'tcplog', ], - } + }, + # Deprecated + $bind_options = '', ) { + if $ports and $bind { + fail('The use of $ports and $bind is mutually exclusive, please choose either one') + } + if $ipaddress and $bind { + fail('The use of $ipaddress and $bind is mutually exclusive, please choose either one') + } + if $bind_options { + warning('The $bind_options parameter is deprecated; please use $bind instead') + } + if $bind { + validate_hash($bind) + } # Template uses: $name, $ipaddress, $ports, $options concat::fragment { "${name}_frontend_block": order => "15-${name}-00", diff --git a/manifests/listen.pp b/manifests/listen.pp index 71f2a802..5580f80a 100644 --- a/manifests/listen.pp +++ b/manifests/listen.pp @@ -27,8 +27,13 @@ # 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. +# 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. +# +# [*bind*] +# Set of ip addresses, port and bind options +# $bind = { '10.0.0.1:80' => ['ssl', 'crt', '/path/to/my/crt.pem'] } # # [*mode*] # The mode of operation for the listening service. Valid values are undef, @@ -39,8 +44,8 @@ # configuration block. # # [*bind_options*] -# An array of options to be specified after the bind declaration in the -# listening serivce's configuration block. +# (Deprecated) An array of options to be specified after the bind declaration +# in the listening serivce's configuration block. # # [*collect_exported*] # Boolean, default 'true'. True means 'collect exported @@balancermember resources' @@ -71,20 +76,35 @@ # Gary Larizza # define haproxy::listen ( - $ports, - $ipaddress = [$::ipaddress], - $mode = undef, - $collect_exported = true, - $options = { + $ports = undef, + $ipaddress = [$::ipaddress], + $bind = undef, + $mode = undef, + $collect_exported = true, + $options = { 'option' => [ 'tcplog', 'ssl-hello-chk' ], 'balance' => 'roundrobin' }, - $bind_options = '' + # Deprecated + $bind_options = '', ) { + if $ports and $bind { + fail('The use of $ports and $bind is mutually exclusive, please choose either one') + } + if $ipaddress and $bind { + fail('The use of $ipaddress and $bind is mutually exclusive, please choose either one') + } + if $bind_options { + warning('The $bind_options parameter is deprecated; please use $bind instead') + } + if $bind { + validate_hash($bind) + } + if defined(Haproxy::Backend[$name]) { fail("An haproxy::backend resource was discovered with the same name (${name}) which is not supported") } diff --git a/spec/defines/frontend_spec.rb b/spec/defines/frontend_spec.rb index d932d60e..2e3e398d 100644 --- a/spec/defines/frontend_spec.rb +++ b/spec/defines/frontend_spec.rb @@ -111,6 +111,19 @@ end end # C9949 + context "when a ports parameter and a bind parameter are passed" do + let(:params) do + { + :name => 'apache', + :bind => {'192.168.0.1:80' => ['ssl']}, + :ports => '80' + } + end + + it 'should raise error' do + expect { subject }.to raise_error Puppet::Error, /mutually exclusive/ + end + end context "when multiple IPs are provided" do let(:params) do { diff --git a/spec/defines/listen_spec.rb b/spec/defines/listen_spec.rb index 37f26567..c12687b5 100644 --- a/spec/defines/listen_spec.rb +++ b/spec/defines/listen_spec.rb @@ -127,6 +127,34 @@ 'content' => "\nlisten apache\n bind *:80 \n balance roundrobin\n option tcplog\n option ssl-hello-chk\n" ) } end + context "when a bind parameter hash is passed" do + let(:params) do + { + :name => 'apache', + :ipaddress => '', + :bind => {'10.0.0.1:333' => ['ssl', 'crt', 'public.puppetlabs.com'], '192.168.122.1:8082' => []}, + } + end + + it { should contain_concat__fragment('apache_listen_block').with( + 'order' => '20-apache-00', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => "\nlisten apache\n bind 10.0.0.1:333 ssl crt public.puppetlabs.com\n bind 192.168.122.1:8082 \n balance roundrobin\n option tcplog\n option ssl-hello-chk\n" + ) } + end + context "when a ports parameter and a bind parameter are passed" do + let(:params) do + { + :name => 'apache', + :bind => {'192.168.0.1:80' => ['ssl']}, + :ports => '80' + } + end + + it 'should raise error' do + expect { subject }.to raise_error Puppet::Error, /mutually exclusive/ + end + end # C9977 context "when an invalid hostname is passed" do let(:params) do diff --git a/templates/fragments/_bind.erb b/templates/fragments/_bind.erb index 6adac704..afb071ae 100644 --- a/templates/fragments/_bind.erb +++ b/templates/fragments/_bind.erb @@ -1,16 +1,34 @@ <% require 'ipaddr' -%> -<% Array(@ipaddress).uniq.each do |virtual_ip| (@ports.is_a?(Array) ? @ports : Array(@ports.split(","))).each do |port| -%> - <%- - begin - IPAddr.new(virtual_ip) - valid_ip = true - rescue ArgumentError => e - valid_ip = false - end - if ! valid_ip and ! virtual_ip.match(/^[A-Za-z][A-Za-z0-9\.-]+$/) and virtual_ip != "*" - scope.function_fail(["Invalid IP address or hostname [#{virtual_ip}]"]) - end - -%> - <%- scope.function_fail(["Port [#{port}] is outside of range 1-65535"]) if port.to_i < 1 or port.to_i > 65535 -%> - bind <%= virtual_ip %>:<%= port %> <%= Array(@bind_options).join(" ") %> -<% end end -%> +<% if @bind + @bind.keys.uniq.sort.each do |virtual_ip| + if ip_port = virtual_ip.match(/^([A-Za-z0-9\.-]+):([0-9]+)$/) + ip = ip_port[1] + port = ip_port[2] + elsif virtual_ip.match(/^([A-Za-z0-9\.-]+)$/) + ip = virtual_ip + end + begin + IPAddr.new(ip) + valid_ip = true + rescue ArgumentError => e + valid_ip = false + end + if ! valid_ip and ! ip.match(/^[A-Za-z][A-Za-z0-9\.-]+$/) and ip != "*" + scope.function_fail(["Invalid IP address or hostname [#{ip}]"]) + end + scope.function_fail(["Port #{port} for IP #{ip} is outside of range 1-65535"]) if port and (port.to_i < 1 or port.to_i > 65535) -%> + bind <%= ip -%>:<%= port -%> <%= Array(@bind[virtual_ip]).join(" ") %> +<%- end else + Array(@ipaddress).uniq.each do |virtual_ip| (@ports.is_a?(Array) ? @ports : Array(@ports.split(","))).each do |port| + begin + IPAddr.new(virtual_ip) + valid_ip = true + rescue ArgumentError => e + valid_ip = false + end + if ! valid_ip and ! virtual_ip.match(/^[A-Za-z][A-Za-z0-9\.-]+$/) and virtual_ip != "*" + scope.function_fail(["Invalid IP address or hostname [#{virtual_ip}]"]) + end + scope.function_fail(["Port [#{port}] is outside of range 1-65535"]) if port.to_i < 1 or port.to_i > 65535 -%> + bind <%= virtual_ip -%>:<%= port -%> <%= Array(@bind_options).join(" ") %> +<%- end end end -%>