diff --git a/Modulefile b/Modulefile index 8754662fe..448383f4e 100644 --- a/Modulefile +++ b/Modulefile @@ -7,6 +7,6 @@ summary 'Puppet NGINX management module' description 'This module can be used for basic NGINX Management' project_page 'http://github.com/jfryman/puppet-nginx' -dependency 'puppetlabs/stdlib', '>= 0.1.6' -dependency 'puppetlabs/apt', '>= 1.0.0' -dependency 'puppetlabs/concat', '>= 1.0.0' +dependency 'puppetlabs/stdlib', '>= 3.0.0' +dependency 'puppetlabs/apt', '>= 1.0.0' +dependency 'puppetlabs/concat', '>= 1.1.0' diff --git a/Puppetfile b/Puppetfile index 7a314f2e9..560d1cc68 100644 --- a/Puppetfile +++ b/Puppetfile @@ -1,5 +1,5 @@ forge 'http://forge.puppetlabs.com' -mod 'puppetlabs/stdlib', '>=0.1.6' -mod 'puppetlabs/apt', '>=1.0.0' -mod 'puppetlabs/concat', '>=1.0.0' +mod 'puppetlabs/stdlib', '>= 3.0.0' +mod 'puppetlabs/apt', '>= 1.0.0' +mod 'puppetlabs/concat', '>= 1.1.0' diff --git a/Puppetfile.lock b/Puppetfile.lock index aac666e40..ab6079e6f 100644 --- a/Puppetfile.lock +++ b/Puppetfile.lock @@ -3,11 +3,11 @@ FORGE specs: puppetlabs/apt (1.2.0) puppetlabs/stdlib (>= 2.2.1) - puppetlabs/concat (1.0.0) + puppetlabs/concat (1.1.0) puppetlabs/stdlib (4.1.0) DEPENDENCIES puppetlabs/apt (>= 1.0.0) - puppetlabs/concat (>= 1.0.0) - puppetlabs/stdlib (>= 0.1.6) + puppetlabs/concat (>= 1.1.0) + puppetlabs/stdlib (>= 3.0.0) diff --git a/manifests/resource/upstream.pp b/manifests/resource/upstream.pp index a3c49fe25..be5e31956 100644 --- a/manifests/resource/upstream.pp +++ b/manifests/resource/upstream.pp @@ -4,6 +4,7 @@ # # Parameters: # [*members*] - Array of member URIs for NGINX to connect to. Must follow valid NGINX syntax. +# If omitted, individual members should be defined with nginx::resource::upstream::member # [*ensure*] - Enables or disables the specified location (present|absent) # [*upstream_cfg_prepend*] - It expects a hash with custom directives to put before anything else inside upstream # [*upstream_fail_timeout*] - Set the fail_timeout for the upstream. Default is 10 seconds - As that is what Nginx does normally. @@ -38,31 +39,58 @@ # upstream_cfg_prepend => $my_config, # } define nginx::resource::upstream ( - $members, + $members = undef, $ensure = 'present', $upstream_cfg_prepend = undef, $upstream_fail_timeout = '10s', ) { - validate_array($members) + if $members != undef { + validate_array($members) + } validate_re($ensure, '^(present|absent)$', "${ensure} is not supported for ensure. Allowed values are 'present' and 'absent'.") if ($upstream_cfg_prepend != undef) { validate_hash($upstream_cfg_prepend) } - File { + Concat { owner => 'root', group => 'root', mode => '0644', } - file { "${nginx::config::conf_dir}/conf.d/${name}-upstream.conf": + concat { "${nginx::config::conf_dir}/conf.d/${name}-upstream.conf": ensure => $ensure ? { 'absent' => absent, - default => 'file', + 'file' => present, + default => present, }, - content => template('nginx/conf.d/upstream.erb'), notify => Class['nginx::service'], } + + # Uses: $name, $upstream_cfg_prepend + concat::fragment { "${name}_upstream_header": + target => "${nginx::config::conf_dir}/conf.d/${name}-upstream.conf", + order => 10, + content => template('nginx/conf.d/upstream_header.erb'), + } + + if $members != undef { + # Uses: $members, $upstream_fail_timeout + concat::fragment { "${name}_upstream_members": + target => "${nginx::config::conf_dir}/conf.d/${name}-upstream.conf", + order => 50, + content => template('nginx/conf.d/upstream_members.erb'), + } + } else { + # Collect exported members: + Nginx::Resource::Upstream::Member <<| upstream == $name |>> + } + + concat::fragment { "${name}_upstream_footer": + target => "${nginx::config::conf_dir}/conf.d/${name}-upstream.conf", + order => 90, + content => "}\n", + } } diff --git a/manifests/resource/upstream/member.pp b/manifests/resource/upstream/member.pp new file mode 100644 index 000000000..135779fe2 --- /dev/null +++ b/manifests/resource/upstream/member.pp @@ -0,0 +1,48 @@ +# Define: nginx::resources::upstream::member +# +# Creates an upstream member inside the upstream block. Export this resource +# in all upstream member servers and collect them on the NGINX server. +# +# +# Requirements: +# Requires storeconfigs on the Puppet Master to export and collect resources +# +# +# Parameters: +# [*upstream*] - The name of the upstream resource +# [*server*] - Hostname or IP of the upstream member server +# [*port*] - Port of the listening service on the upstream member +# [*upstream_fail_timeout*] - Set the fail_timeout for the upstream. Default is 10 seconds +# +# +# Examples: +# +# Exporting the resource on a upstream member server: +# +# @@nginx::resource::upstream::member { $::fqdn: +# upstream => 'proxypass', +# server => $::ipaddress, +# port => '3000', +# } +# +# +# Collecting the resource on the NGINX server: +# +# nginx::resource::upstream { 'proxypass': +# ensure => present, +# } +# +define nginx::resource::upstream::member ( + $upstream, + $server, + $port = '80', + $upstream_fail_timeout = '10s', +) { + + # Uses: $server, $port, $upstream_fail_timeout + concat::fragment { "${upstream}_upstream_member_${name}": + target => "${nginx::config::conf_dir}/conf.d/${upstream}-upstream.conf", + order => 40, + content => template('nginx/conf.d/upstream_member.erb'), + } +} diff --git a/spec/defines/resource_upstream_spec.rb b/spec/defines/resource_upstream_spec.rb index 415c5d648..63ff75655 100644 --- a/spec/defines/resource_upstream_spec.rb +++ b/spec/defines/resource_upstream_spec.rb @@ -10,12 +10,7 @@ :members => ['test'], } end - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'debian', - } - end + let :pre_condition do [ 'include ::nginx::params', @@ -23,34 +18,71 @@ ] end + let :default_facts do + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + :concat_basedir => '/var/lib/puppet/concat' + } + end + + let :pre_condition do + [ + 'include ::nginx::params', + 'include ::nginx::config', + ] + end + describe 'os-independent items' do + let :facts do default_facts end describe 'basic assumptions' do let :params do default_params end - it { should contain_file("/etc/nginx/conf.d/#{title}-upstream.conf").with( + it { should contain_class("nginx::params") } + it { should contain_class('concat::setup') } + it { should contain_file("/etc/nginx/conf.d/#{title}-upstream.conf") } + it { should contain_concat__fragment("#{title}_upstream_header").with_content(/upstream #{title}/) } + + it { + should contain_concat__fragment("#{title}_upstream_header").with( { - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'ensure' => 'file', - 'content' => /upstream #{title}/, + 'target' => "/etc/nginx/conf.d/#{title}-upstream.conf", + 'order' => 10, } )} + + it { + should contain_concat__fragment("#{title}_upstream_members").with( + { + 'target' => "/etc/nginx/conf.d/#{title}-upstream.conf", + 'order' => 50, + } + )} + + it { + should contain_concat__fragment("#{title}_upstream_footer").with( + { + 'target' => "/etc/nginx/conf.d/#{title}-upstream.conf", + 'order' => 90, + }).with_content("}\n") + } end describe "upstream.conf template content" do + let :facts do default_facts end [ { - :title => 'should contain ordered prepended directives', - :attr => 'upstream_cfg_prepend', + :title => 'should contain ordered prepended directives', + :attr => 'upstream_cfg_prepend', + :fragment => 'header', :value => { 'test3' => 'test value 3', + 'test6' => {'subkey1' => ['subvalue1', 'subvalue2']}, 'test1' => 'test value 1', 'test2' => 'test value 2', - 'test4' => ['test value 1', 'test value 2'], 'test5' => {'subkey1' => 'subvalue1'}, - 'test6' => {'subkey1' => ['subvalue1', 'subvalue2']}, + 'test4' => ['test value 1', 'test value 2'], }, :match => [ ' test1 test value 1;', @@ -64,14 +96,11 @@ ], }, { - :title => 'should set server', - :attr => 'members', - :value => [ - 'test3', - 'test1', - 'test2', - ], - :match => [ + :title => 'should set server', + :attr => 'members', + :fragment => 'members', + :value => %W( test3 test1 test2 ), + :match => [ ' server test3 fail_timeout=10s;', ' server test1 fail_timeout=10s;', ' server test2 fail_timeout=10s;', @@ -82,10 +111,12 @@ let :params do default_params.merge({ param[:attr].to_sym => param[:value] }) end it { should contain_file("/etc/nginx/conf.d/#{title}-upstream.conf").with_mode('0644') } + it { should contain_concat__fragment("#{title}_upstream_#{param[:fragment]}") } it param[:title] do - verify_contents(subject, "/etc/nginx/conf.d/#{title}-upstream.conf", Array(param[:match])) + lines = subject.resource('concat::fragment', "#{title}_upstream_#{param[:fragment]}").send(:parameters)[:content].split("\n") + (lines & Array(param[:match])).should == Array(param[:match]) Array(param[:notmatch]).each do |item| - should contain_file("/etc/nginx/conf.d/#{title}-upstream.conf").without_content(item) + should contain_concat__fragment("#{title}_upstream_#{param[:fragment]}").without_content(item) end end end diff --git a/templates/conf.d/upstream.erb b/templates/conf.d/upstream_header.erb similarity index 79% rename from templates/conf.d/upstream.erb rename to templates/conf.d/upstream_header.erb index a96121ab2..6b7f44883 100644 --- a/templates/conf.d/upstream.erb +++ b/templates/conf.d/upstream_header.erb @@ -10,6 +10,3 @@ upstream <%= @name %> { <% end -%> <% end -%> <% end -%><% end -%> - <% @members.each do |i| %> - server <%= i %> fail_timeout=<%= @upstream_fail_timeout %>;<% end %> -} diff --git a/templates/conf.d/upstream_member.erb b/templates/conf.d/upstream_member.erb new file mode 100644 index 000000000..081177b7e --- /dev/null +++ b/templates/conf.d/upstream_member.erb @@ -0,0 +1 @@ + server <%= @server %>:<%= @port %> fail_timeout=<%= @upstream_fail_timeout %>; diff --git a/templates/conf.d/upstream_members.erb b/templates/conf.d/upstream_members.erb new file mode 100644 index 000000000..d7a2ddaf1 --- /dev/null +++ b/templates/conf.d/upstream_members.erb @@ -0,0 +1,2 @@ + <% @members.each do |i| %> + server <%= i %> fail_timeout=<%= @upstream_fail_timeout %>;<% end %>