diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f1f88cc..887d571 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,282 +1,252 @@ # Contribution guidelines ## Table of contents * [Contributing](#contributing) * [Writing proper commits - short version](#writing-proper-commits-short-version) * [Writing proper commits - long version](#writing-proper-commits-long-version) * [Dependencies](#dependencies) * [Note for OS X users](#note-for-os-x-users) * [The test matrix](#the-test-matrix) * [Syntax and style](#syntax-and-style) * [Running the unit tests](#running-the-unit-tests) * [Unit tests in docker](#unit-tests-in-docker) * [Integration tests](#integration-tests) This module has grown over time based on a range of contributions from people using it. If you follow these contributing guidelines your patch will likely make it into a release a little more quickly. ## Contributing Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. [Contributor Code of Conduct](https://voxpupuli.org/coc/). * Fork the repo. * Create a separate branch for your change. * We only take pull requests with passing tests, and documentation. [travis-ci](http://travis-ci.org) runs the tests for us. You can also execute them locally. This is explained [in a later section](#the-test-matrix). * Checkout [our docs](https://voxpupuli.org/docs/reviewing_pr/) we use to review a module and the [official styleguide](https://puppet.com/docs/puppet/6.0/style_guide.html). They provide some guidance for new code that might help you before you submit a pull request. * Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, please add a test. * Squash your commits down into logical components. Make sure to rebase against our current master. * Push the branch to your fork and submit a pull request. Please be prepared to repeat some of these steps as our contributors review your code. Also consider sending in your profile code that calls this component module as an acceptance test or provide it via an issue. This helps reviewers a lot to test your use case and prevents future regressions! ## Writing proper commits - short version * Make commits of logical units. * Check for unnecessary whitespace with "git diff --check" before committing. * Commit using Unix line endings (check the settings around "crlf" in git-config(1)). * Do not check in commented out code or unneeded files. * The first line of the commit message should be a short description (50 characters is the soft limit, excluding ticket number(s)), and should skip the full stop. * Associate the issue in the message. The first line should include the issue number in the form "(#XXXX) Rest of message". * The body should provide a meaningful commit message, which: *uses the imperative, present tense: `change`, not `changed` or `changes`. * includes motivation for the change, and contrasts its implementation with the previous behavior. * Make sure that you have tests for the bug you are fixing, or feature you are adding. * Make sure the test suites passes after your commit: * When introducing a new feature, make sure it is properly documented in the README.md ## Writing proper commits - long version 1. Make separate commits for logically separate changes. Please break your commits down into logically consistent units which include new or changed tests relevant to the rest of the change. The goal of doing this is to make the diff easier to read for whoever is reviewing your code. In general, the easier your diff is to read, the more likely someone will be happy to review it and get it into the code base. If you are going to refactor a piece of code, please do so as a separate commit from your feature or bug fix changes. We also really appreciate changes that include tests to make sure the bug is not re-introduced, and that the feature is not accidentally broken. Describe the technical detail of the change(s). If your description starts to get too long, that is a good sign that you probably need to split up your commit into more finely grained pieces. Commits which plainly describe the things which help reviewers check the patch and future developers understand the code are much more likely to be merged in with a minimum of bike-shedding or requested changes. Ideally, the commit message would include information, and be in a form suitable for inclusion in the release notes for the version of Puppet that includes them. Please also check that you are not introducing any trailing whitespace or other "whitespace errors". You can do this by running "git diff --check" on your changes before you commit. 2. Sending your patches To submit your changes via a GitHub pull request, we _highly_ recommend that you have them on a topic branch, instead of directly on `master`. It makes things much easier to keep track of, especially if you decide to work on another thing before your first change is merged in. GitHub has some pretty good [general documentation](http://help.github.com/) on using their site. They also have documentation on [creating pull requests](http://help.github.com/send-pull-requests/). In general, after pushing your topic branch up to your repository on GitHub, you can switch to the branch in the GitHub UI and click "Pull Request" towards the top of the page in order to open a pull request. 3. Update the related GitHub issue. If there is a GitHub issue associated with the change you submitted, then you should update the ticket to include the location of your branch, along with any other commentary you may wish to make. ## Dependencies The testing and development tools have a bunch of dependencies, all managed by [bundler](http://bundler.io/) according to the [Puppet support matrix](http://docs.puppetlabs.com/guides/platforms.html#ruby-versions). By default the tests use a baseline version of Puppet. If you have Ruby 2.x or want a specific version of Puppet, you must set an environment variable such as: ```sh export PUPPET_VERSION="~> 5.5.6" ``` You can install all needed gems for spec tests into the modules directory by running: ```sh bundle install --path .vendor/ --without development system_tests release --jobs "$(nproc)" ``` If you also want to run acceptance tests: ```sh bundle install --path .vendor/ --with system_tests --without development release --jobs "$(nproc)" ``` Our all in one solution if you don't know if you need to install or update gems: ```sh bundle install --path .vendor/ --with system_tests --without development release --jobs "$(nproc)"; bundle update; bundle clean ``` As an alternative to the `--jobs "$(nproc)` parameter, you can set an environment variable: ```sh BUNDLE_JOBS="$(nproc)" ``` ### Note for OS X users `nproc` isn't a valid command under OS x. As an alternative, you can do: ```sh --jobs "$(sysctl -n hw.ncpu)" ``` ## The test matrix ### Syntax and style The test suite will run [Puppet Lint](http://puppet-lint.com/) and [Puppet Syntax](https://github.com/gds-operations/puppet-syntax) to check various syntax and style things. You can run these locally with: ```sh bundle exec rake lint bundle exec rake validate ``` It will also run some [Rubocop](http://batsov.com/rubocop/) tests against it. You can run those locally ahead of time with: ```sh bundle exec rake rubocop ``` ### Running the unit tests The unit test suite covers most of the code, as mentioned above please add tests if you're adding new functionality. If you've not used [rspec-puppet](http://rspec-puppet.com/) before then feel free to ask about how best to test your new feature. To run the linter, the syntax checker and the unit tests: ```sh bundle exec rake test ``` To run your all the unit tests ```sh bundle exec rake spec ``` To run a specific spec test set the `SPEC` variable: ```sh bundle exec rake spec SPEC=spec/foo_spec.rb ``` #### Unit tests in docker Some people don't want to run the dependencies locally or don't want to install ruby. We ship a Dockerfile that enables you to run all unit tests and linting. You only need to run: ```sh docker build . ``` Please ensure that a docker daemon is running and that your user has the permission to talk to it. You can specify a remote docker host by setting the `DOCKER_HOST` environment variable. it will copy the content of the module into the docker image. So it will not work if a Gemfile.lock exists. ### Integration tests The unit tests just check the code runs, not that it does exactly what we want on a real machine. For that we're using [beaker](https://github.com/puppetlabs/beaker). This fires up a new virtual machine (using vagrant) and runs a series of simple tests against it after applying the module. You can run this with: ```sh -bundle exec rake beaker -``` - -This will run the tests on the module's default nodeset. You can override the -nodeset used, e.g., - -```sh -BEAKER_set=centos-7-x64 bundle exec rake beaker -``` - -There are default rake tasks for the various acceptance test modules, e.g., - -```sh -bundle exec rake beaker:centos-7-x64 -bundle exec rake beaker:ssh:centos-7-x64 -``` - -If you don't want to have to recreate the virtual machine every time you can -use `BEAKER_destroy=no` and `BEAKER_provision=no`. On the first run you will at -least need `BEAKER_provision` set to yes (the default). The Vagrantfile for the -created virtual machines will be in `.vagrant/beaker_vagrant_files`. - -Beaker also supports docker containers. We also use that in our automated CI -pipeline at [travis-ci](http://travis-ci.org). To use that instead of Vagrant: - -```sh -PUPPET_INSTALL_TYPE=agent BEAKER_IS_PE=no BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=debian10-64{hypervisor=docker} BEAKER_destroy=yes bundle exec rake beaker +BEAKER_setfile=debian10-x64 bundle exec rake beaker ``` You can replace the string `debian10` with any common operating system. The following strings are known to work: * ubuntu1604 * ubuntu1804 * ubuntu2004 * debian9 * debian10 * centos7 * centos8 -The easiest way to debug in a docker container is to open a shell: - -```sh -docker exec -it -u root ${container_id_or_name} bash -``` +For more information and tips & tricks, see [voxpupuli-acceptance's documentation](https://github.com/voxpupuli/voxpupuli-acceptance#running-tests). The source of this file is in our [modulesync_config](https://github.com/voxpupuli/modulesync_config/blob/master/moduleroot/.github/CONTRIBUTING.md.erb) repository. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4f47e8..97ddc62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,75 +1,75 @@ name: CI on: pull_request jobs: setup_matrix: name: 'Setup Test Matrix' runs-on: ubuntu-latest + timeout-minutes: 40 outputs: beaker_setfiles: ${{ steps.get-outputs.outputs.beaker_setfiles }} puppet_major_versions: ${{ steps.get-outputs.outputs.puppet_major_versions }} puppet_unit_test_matrix: ${{ steps.get-outputs.outputs.puppet_unit_test_matrix }} env: - BUNDLE_WITHOUT: development:test:release + BUNDLE_WITHOUT: development:release steps: - uses: actions/checkout@v2 - name: Setup ruby uses: ruby/setup-ruby@v1 with: ruby-version: '2.7' bundler-cache: true - name: Run rake validate run: bundle exec rake validate + - name: Run rake rubocop + run: bundle exec rake rubocop - name: Setup Test Matrix id: get-outputs run: bundle exec metadata2gha --use-fqdn --pidfile-workaround false unit: needs: setup_matrix runs-on: ubuntu-latest + timeout-minutes: 40 strategy: fail-fast: false matrix: include: ${{fromJson(needs.setup_matrix.outputs.puppet_unit_test_matrix)}} env: BUNDLE_WITHOUT: development:system_tests:release PUPPET_VERSION: "~> ${{ matrix.puppet }}.0" name: Puppet ${{ matrix.puppet }} (Ruby ${{ matrix.ruby }}) steps: - uses: actions/checkout@v2 - name: Setup ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run tests run: bundle exec rake acceptance: needs: setup_matrix runs-on: ubuntu-latest env: BUNDLE_WITHOUT: development:test:release strategy: fail-fast: false matrix: setfile: ${{fromJson(needs.setup_matrix.outputs.beaker_setfiles)}} puppet: ${{fromJson(needs.setup_matrix.outputs.puppet_major_versions)}} name: ${{ matrix.puppet.name }} - ${{ matrix.setfile.name }} steps: - - name: Enable IPv6 on docker - run: | - echo '{"ipv6":true,"fixed-cidr-v6":"2001:db8:1::/64"}' | sudo tee /etc/docker/daemon.json - sudo service docker restart - uses: actions/checkout@v2 - name: Setup ruby uses: ruby/setup-ruby@v1 with: ruby-version: '2.7' bundler-cache: true - name: Run tests run: bundle exec rake beaker env: BEAKER_PUPPET_COLLECTION: ${{ matrix.puppet.collection }} BEAKER_setfile: ${{ matrix.setfile.value }} diff --git a/.msync.yml b/.msync.yml index a0770a8..57ff503 100644 --- a/.msync.yml +++ b/.msync.yml @@ -1,2 +1,2 @@ --- -modulesync_config_version: '4.0.0' +modulesync_config_version: '4.1.0' diff --git a/Dockerfile b/Dockerfile index 6fd6342..a51c641 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,21 @@ -FROM ruby:2.5.3 +FROM ruby:2.7 WORKDIR /opt/puppet # https://github.com/puppetlabs/puppet/blob/06ad255754a38f22fb3a22c7c4f1e2ce453d01cb/lib/puppet/provider/service/runit.rb#L39 RUN mkdir -p /etc/sv ARG PUPPET_VERSION="~> 6.0" ARG PARALLEL_TEST_PROCESSORS=4 # Cache gems COPY Gemfile . RUN bundle install --without system_tests development release --path=${BUNDLE_PATH:-vendor/bundle} COPY . . RUN bundle install RUN bundle exec rake release_checks # Container should not saved RUN exit 1 diff --git a/Gemfile b/Gemfile index 0d0a9fb..f4855f6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,33 +1,33 @@ source ENV['GEM_SOURCE'] || "https://rubygems.org" group :test do gem 'voxpupuli-test', '~> 2.1', :require => false gem 'coveralls', :require => false gem 'simplecov-console', :require => false end group :development do gem 'guard-rake', :require => false gem 'overcommit', '>= 0.39.1', :require => false end group :system_tests do gem 'puppet_metadata', '~> 0.3.0', :require => false gem 'voxpupuli-acceptance', :require => false end group :release do - gem 'github_changelog_generator', :require => false, :git => 'https://github.com/voxpupuli/github-changelog-generator', :branch => 'voxpupuli_essential_fixes' - gem 'puppet-blacksmith', :require => false - gem 'voxpupuli-release', :require => false - gem 'puppet-strings', '>= 2.2', :require => false + gem 'github_changelog_generator', '>= 1.16.1', :require => false + gem 'puppet-blacksmith', :require => false + gem 'voxpupuli-release', :require => false + gem 'puppet-strings', '>= 2.2', :require => false end gem 'puppetlabs_spec_helper', '~> 2.0', :require => false gem 'rake', :require => false gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] puppetversion = ENV['PUPPET_VERSION'] || '~> 6.0' gem 'puppet', puppetversion, :require => false, :groups => [:test] # vim: syntax=ruby diff --git a/spec/defines/resource_server_spec.rb b/spec/defines/resource_server_spec.rb index b2734c8..4e104fa 100644 --- a/spec/defines/resource_server_spec.rb +++ b/spec/defines/resource_server_spec.rb @@ -1,1648 +1,1650 @@ require 'spec_helper' describe 'nginx::resource::server' do on_supported_os.each do |os, facts| context "on #{os} with Facter #{facts[:facterversion]} and Puppet #{facts[:puppetversion]}" do let(:facts) do facts end let :title do 'www.rspec.example.com' end let :default_params do { www_root: '/', ipv6_enable: true, listen_unix_socket_enable: true, fastcgi_index: 'index.php' } end let :pre_condition do [ 'include ::nginx' ] end describe 'os-independent items' do describe 'basic assumptions' do let(:params) { default_params } it { is_expected.to contain_class('nginx') } it do is_expected.to contain_concat("/etc/nginx/sites-available/#{title}.conf").with('owner' => 'root', 'group' => 'root', 'mode' => '0644') end it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{access_log\s+/var/log/nginx/www\.rspec\.example\.com\.access\.log;}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{error_log\s+/var/log/nginx/www\.rspec\.example\.com\.error\.log}) } it { is_expected.to contain_concat__fragment("#{title}-footer") } it { is_expected.to contain_nginx__resource__location("#{title}-default") } it { is_expected.not_to contain_file('/etc/nginx/fastcgi.conf') } it do is_expected.to contain_file("#{title}.conf symlink").with('ensure' => 'link', 'path' => "/etc/nginx/sites-enabled/#{title}.conf", 'target' => "/etc/nginx/sites-available/#{title}.conf") end end describe 'with $confd_only enabled' do let(:pre_condition) { 'class { "nginx": confd_only => true }' } let(:params) { default_params } it { is_expected.to contain_class('nginx') } it do is_expected.to contain_concat("/etc/nginx/conf.d/#{title}.conf").with('owner' => 'root', 'group' => 'root', 'mode' => '0644') is_expected.not_to contain_file('/etc/nginx/sites-enabled') is_expected.not_to contain_file('/etc/nginx/sites-available') end end describe 'with both $rewrite_www_to_non_www and $rewrite_non_www_to_www enabled' do let(:params) do default_params.merge(rewrite_non_www_to_www: true, rewrite_www_to_non_www: true) end it do is_expected.to compile.and_raise_error( %r{You must not set both \$rewrite_www_to_non_www and \$rewrite_non_www_to_www to true} ) end end describe 'server_header template content' do [ { title: 'should not contain www to non-www rewrite', attr: 'rewrite_www_to_non_www', value: false, notmatch: %r{ ^ \s+server_name\s+www\.rspec\.example\.com;\n \s+return\s+301\s+http://rspec\.example\.com\$request_uri; }x }, { title: 'should contain www to non-www rewrite', attr: 'rewrite_www_to_non_www', value: true, match: %r{ ^ \s+server_name\s+www\.rspec\.example\.com;\n \s+return\s+301\s+http://rspec\.example\.com\$request_uri; }x }, { title: 'should set the IPv4 listen IP', attr: 'listen_ip', value: '127.0.0.1', match: %r{\s+listen\s+127.0.0.1:80;} }, { title: 'should set the IPv4 listen port', attr: 'listen_port', value: 45, match: %r{\s+listen\s+\*:45;} }, { title: 'should set the IPv4 listen options', attr: 'listen_options', value: 'spdy default', match: %r{\s+listen\s+\*:80 spdy default;} }, { title: 'should enable IPv6', attr: 'ipv6_enable', value: true, match: %r{\s+listen\s+\[::\]:80 default ipv6only=on;} }, { title: 'should not enable IPv6', attr: 'ipv6_enable', value: false, notmatch: %r{\slisten \[::\]:80 default ipv6only=on;} }, { title: 'should set the IPv6 listen IP', attr: 'ipv6_listen_ip', value: '2001:0db8:85a3:0000:0000:8a2e:0370:7334', match: %r{\s+listen\s+\[2001:0db8:85a3:0000:0000:8a2e:0370:7334\]:80 default ipv6only=on;} }, { title: 'should set the IPv6 listen port', attr: 'ipv6_listen_port', value: 45, match: %r{\s+listen\s+\[::\]:45 default ipv6only=on;} }, { title: 'should set the IPv6 listen options', attr: 'ipv6_listen_options', value: 'spdy', match: %r{\s+listen\s+\[::\]:80 spdy;} }, { title: 'should enable listening on unix socket', attr: 'listen_unix_socket_enable', value: true, match: %r{\s+listen\s+unix:/var/run/nginx\.sock;} }, { title: 'should not enable listening on unix socket', attr: 'listen_unix_socket_enable', value: false, notmatch: %r{\s+listen\s+unix:/var/run/nginx\.sock;} }, { title: 'should set the listen unix socket', attr: 'listen_unix_socket', value: '/var/run/puppet_nginx.sock', match: %r{\s+listen\s+unix:/var/run/puppet_nginx\.sock;} }, { title: 'should set the listen unix socket options', attr: 'listen_unix_socket_options', value: 'spdy', match: %r{\s+listen\s+unix:/var/run/nginx\.sock spdy;} }, { title: 'should set servername(s)', attr: 'server_name', value: ['www.foo.com', 'foo.com'], match: %r{\s+server_name\s+www.foo.com foo.com;} }, { title: 'should rewrite www servername to non-www', attr: 'rewrite_www_to_non_www', value: true, match: %r{\s+server_name\s+rspec.example.com;} }, { title: 'should not rewrite www servername to non-www', attr: 'rewrite_www_to_non_www', value: false, match: %r{\s+server_name\s+www.rspec.example.com;} }, { title: 'should not set absolute_redirect', attr: 'absolute_redirect', value: :undef, notmatch: %r{absolute_redirect} }, { title: 'should set absolute_redirect off', attr: 'absolute_redirect', value: 'off', match: ' absolute_redirect off;' }, { title: 'should set auth_basic', attr: 'auth_basic', value: 'value', match: %r{\s+auth_basic\s+"value";} }, { title: 'should set auth_basic_user_file', attr: 'auth_basic_user_file', value: 'value', match: %r{\s+auth_basic_user_file\s+value;} }, { title: 'should set auth_request', attr: 'auth_request', value: 'value', match: %r{\s+auth_request\s+value;} }, { title: 'should set the client_body_timeout', attr: 'client_body_timeout', value: 'value', match: %r{^\s+client_body_timeout\s+value;} }, { title: 'should set the client_header_timeout', attr: 'client_header_timeout', value: 'value', match: %r{^\s+client_header_timeout\s+value;} }, { title: 'should set the gzip_types', attr: 'gzip_types', value: 'value', match: %r{^\s+gzip_types\s+value;} }, { title: 'should not set the gzip_static', attr: 'gzip_static', value: :undef, notmatch: 'gzip_static' }, { title: 'should set the gzip_static', attr: 'gzip_static', value: 'on', match: %r{^\s+gzip_static\s+on;} }, { title: 'should contain raw_prepend directives', attr: 'raw_prepend', value: [ 'if (a) {', ' b;', '}' ], match: %r{^\s+if \(a\) \{\n\s++b;\n\s+\}} }, { title: 'should contain ordered prepended directives', attr: 'server_cfg_prepend', value: { 'test1' => ['test value 1a', 'test value 1b'], 'test2' => 'test value 2', 'allow' => 'test value 3' }, match: [ ' allow test value 3;', ' test1 test value 1a;', ' test1 test value 1b;', ' test2 test value 2;' ] }, { title: 'should set root', attr: 'use_default_location', value: false, match: ' root /;' }, { title: 'should not set root', attr: 'use_default_location', value: true, notmatch: %r{ root /;} }, { title: 'should force https (SSL) redirect', attr: 'ssl_redirect', value: true, match: %r{ return 301 https://\$host\$request_uri;} }, { title: 'should not force https (SSL) redirect', attr: 'ssl_redirect', value: false, notmatch: %r{\s*return\s+301} }, { title: 'should set access_log', attr: 'access_log', value: '/path/to/access.log', match: ' access_log /path/to/access.log;' }, { title: 'should set multiple access_log directives', attr: 'access_log', value: ['/path/to/log/1', 'syslog:server=localhost'], match: [ ' access_log /path/to/log/1;', ' access_log syslog:server=localhost;' ] }, { title: 'should set access_log off', attr: 'access_log', value: 'off', match: ' access_log off;' }, { title: 'should set access_log to syslog', attr: 'access_log', value: 'syslog:server=localhost', match: ' access_log syslog:server=localhost;' }, { title: 'should set format_log custom_format', attr: 'format_log', value: 'custom', match: ' access_log /var/log/nginx/www.rspec.example.com.access.log custom;' }, { title: 'should not include access_log in server when set to absent', attr: 'access_log', value: 'absent', notmatch: 'access_log' }, { title: 'should set error_log', attr: 'error_log', value: '/path/to/error.log', match: ' error_log /path/to/error.log;' }, { title: 'should allow multiple error_log directives', attr: 'error_log', value: ['/path/to/error.log', 'syslog:server=localhost'], match: [ ' error_log /path/to/error.log;', ' error_log syslog:server=localhost;' ] }, { title: 'should not include error_log in server when set to absent', attr: 'error_log', value: 'absent', notmatch: 'error_log' }, { title: 'should set error_pages', attr: 'error_pages', value: { '503' => '/foo.html' }, match: ' error_page 503 /foo.html;' }, { title: 'should set index_file(s)', attr: 'index_files', value: %w[name1 name2], match: %r{\s*index\s+name1\s+name2;} }, { title: 'should not set index_file(s)', attr: 'index_files', value: [], notmatch: %r{\s+index\s+} }, { title: 'should set autoindex', attr: 'autoindex', value: 'on', match: ' autoindex on;' }, { title: 'should set autoindex_exact_size', attr: 'autoindex_exact_size', value: 'on', match: ' autoindex_exact_size on;' }, { title: 'should set reset_timedout_connection', attr: 'reset_timedout_connection', value: 'on', match: %r{^\s+reset_timedout_connection\s+on;} } ].each do |param| context "when #{param[:attr]} is #{param[:value]}" do let(:params) { default_params.merge(param[:attr].to_sym => param[:value]) } it { is_expected.to contain_concat__fragment("#{title}-header") } it param[:title] do matches = Array(param[:match]) if matches.all? { |m| m.is_a? Regexp } matches.each { |item| is_expected.to contain_concat__fragment("#{title}-header").with_content(item) } else lines = catalogue.resource('concat::fragment', "#{title}-header").send(:parameters)[:content].split("\n") expect(lines & Array(param[:match])).to eq(Array(param[:match])) end Array(param[:notmatch]).each do |item| is_expected.to contain_concat__fragment("#{title}-header").without_content(item) end end end end context 'with a naked domain title over http' do let(:title) { 'rspec.example.com' } [ { title: 'should not contain non-www to www rewrite', attr: 'rewrite_non_www_to_www', value: false, notmatch: %r{ ^ \s+server_name\s+rspec\.example\.com;\n \s+return\s+301\s+http://www\.rspec\.example\.com\$request_uri; }x }, { title: 'should contain non-www to www rewrite', attr: 'rewrite_non_www_to_www', value: true, match: %r{ ^ \s+server_name\s+rspec\.example\.com;\n \s+return\s+301\s+http://www\.rspec\.example\.com\$request_uri; }x }, { title: 'should rewrite non-www servername to www', attr: 'rewrite_non_www_to_www', value: true, match: %r{\s+server_name\s+www.rspec.example.com;} }, { title: 'should not rewrite non-www servername to www', attr: 'rewrite_non_www_to_www', value: false, notmatch: %r{\s+server_name\s+www.rspec.example.com;} } ].each do |param| context "when #{param[:attr]} is #{param[:value]}" do let(:params) { default_params.merge(param[:attr].to_sym => param[:value]) } it { is_expected.to contain_concat__fragment("#{title}-header") } it param[:title] do matches = Array(param[:match]) if matches.all? { |m| m.is_a? Regexp } matches.each { |item| is_expected.to contain_concat__fragment("#{title}-header").with_content(item) } else lines = catalogue.resource('concat::fragment', "#{title}-header").send(:parameters)[:content].split("\n") expect(lines & Array(param[:match])).to eq(Array(param[:match])) end Array(param[:notmatch]).each do |item| is_expected.to contain_concat__fragment("#{title}-header").without_content(item) end end end end end context 'with a naked domain title over https' do let(:title) { 'rspec.example.com' } [ { title: 'should not contain non-www to www rewrite', attr: 'rewrite_non_www_to_www', value: false, notmatch: %r{ ^ \s+server_name\s+rspec\.example\.com;\n \s+return\s+301\s+https://www\.rspec\.example\.com\$request_uri; }x }, { title: 'should contain non-www to www rewrite', attr: 'rewrite_non_www_to_www', value: true, match: %r{ ^ \s+server_name\s+rspec\.example\.com;\n \s+return\s+301\s+https://www\.rspec\.example\.com\$request_uri; }x }, { title: 'should rewrite non-www servername to www', attr: 'rewrite_non_www_to_www', value: true, match: %r{\s+server_name\s+www.rspec.example.com;} }, { title: 'should not rewrite non-www servername to www', attr: 'rewrite_non_www_to_www', value: false, notmatch: %r{\s+server_name\s+www.rspec.example.com;} } ].each do |param| context "when #{param[:attr]} is #{param[:value]}" do let(:params) { default_params.merge(param[:attr].to_sym => param[:value], ssl: true, ssl_cert: '/tmp/dummy.crt', ssl_key: '/tmp/dummy.key', listen_port: 443) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header") } it param[:title] do matches = Array(param[:match]) if matches.all? { |m| m.is_a? Regexp } matches.each { |item| is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(item) } else lines = catalogue.resource('concat::fragment', "#{title}-ssl-header").send(:parameters)[:content].split("\n") expect(lines & Array(param[:match])).to eq(Array(param[:match])) end Array(param[:notmatch]).each do |item| is_expected.to contain_concat__fragment("#{title}-ssl-header").without_content(item) end end end end end end describe 'server_footer template content' do [ { title: 'should not contain www to non-www rewrite', attr: 'rewrite_www_to_non_www', value: false, notmatch: %r{ ^ \s+server_name\s+www\.rspec\.example\.com;\n \s+return\s+301\s+https://rspec\.example\.com\$request_uri; }x }, { title: 'should contain include directives', attr: 'include_files', value: ['/file1', '/file2'], match: [ %r{^\s+include\s+/file1;}, %r{^\s+include\s+/file2;} ] }, { title: 'should contain ordered appended directives', attr: 'server_cfg_append', value: { 'test1' => 'test value 1', 'test2' => ['test value 2a', 'test value 2b'], 'allow' => 'test value 3' }, match: [ ' allow test value 3;', ' test1 test value 1;', ' test2 test value 2a;', ' test2 test value 2b;' ] }, { title: 'should contain raw_append directives', attr: 'raw_append', value: [ 'if (a) {', ' b;', '}' ], match: %r{^\s+if \(a\) \{\n\s++b;\n\s+\}} } ].each do |param| context "when #{param[:attr]} is #{param[:value]}" do let(:params) { default_params.merge(param[:attr].to_sym => param[:value]) } it { is_expected.to contain_concat__fragment("#{title}-footer") } it param[:title] do matches = Array(param[:match]) if matches.all? { |m| m.is_a? Regexp } matches.each { |item| is_expected.to contain_concat__fragment("#{title}-footer").with_content(item) } else lines = catalogue.resource('concat::fragment', "#{title}-footer").send(:parameters)[:content].split("\n") expect(lines & Array(param[:match])).to eq(Array(param[:match])) end Array(param[:notmatch]).each do |item| is_expected.to contain_concat__fragment("#{title}-footer").without_content(item) end end end end end context 'with a naked domain title' do [ { title: 'should not contain non-www to www rewrite', attr: 'rewrite_non_www_to_www', value: false, notmatch: %r{ ^ \s+server_name\s+rspec\.example\.com;\n \s+return\s+301\s+https://www\.rspec\.example\.com\$request_uri; }x } ].each do |param| context "when #{param[:attr]} is #{param[:value]}" do let(:params) { default_params.merge(param[:attr].to_sym => param[:value]) } it { is_expected.to contain_concat__fragment("#{title}-footer") } it param[:title] do matches = Array(param[:match]) if matches.all? { |m| m.is_a? Regexp } matches.each { |item| is_expected.to contain_concat__fragment("#{title}-footer").with_content(item) } else lines = catalogue.resource('concat::fragment', "#{title}-footer").send(:parameters)[:content].split("\n") expect(lines & Array(param[:match])).to eq(Array(param[:match])) end Array(param[:notmatch]).each do |item| is_expected.to contain_concat__fragment("#{title}-footer").without_content(item) end end end end end describe 'server_ssl_header template content' do context 'with ssl' do let :params do default_params.merge( ssl: true, ssl_key: '/tmp/dummy.key', ssl_cert: '/tmp/dummy.crt' ) end context 'without a value for the nginx_version fact do' do let :facts do facts[:nginx_version] ? facts.delete(:nginx_version) : facts end it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ ssl on;}) } end context 'with fact nginx_version=1.14.1' do let(:facts) { facts.merge(nginx_version: '1.14.1') } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ ssl on;}) } end context 'with fact nginx_version=1.15.1' do let(:facts) { facts.merge(nginx_version: '1.15.1') } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").without_content(%r{ ssl on;}) } end context 'with ssl cert and key definitions' do let(:pre_condition) do <<-PUPPET file { ['/tmp/dummy.key', '/tmp/dummy.crt']: } include nginx PUPPET end it { is_expected.to contain_file('/tmp/dummy.key').with_path('/tmp/dummy.key') } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").that_requires(['File[/tmp/dummy.key]', 'File[/tmp/dummy.crt]']) } end end [ { title: 'should not contain www to non-www rewrite', attr: 'rewrite_www_to_non_www', value: false, notmatch: %r{ ^ \s+server_name\s+www\.rspec\.example\.com;\n \s+return\s+301\s+https://rspec\.example\.com\$request_uri; }x }, { title: 'should contain www to non-www rewrite', attr: 'rewrite_www_to_non_www', value: true, match: %r{ ^ \s+server_name\s+www\.rspec\.example\.com;\n \s+return\s+301\s+https://rspec\.example\.com\$request_uri; }x }, { title: 'should set the IPv4 listen IP', attr: 'listen_ip', value: '127.0.0.1', match: %r{\s+listen\s+127.0.0.1:443 ssl;} }, { title: 'should set the IPv4 SSL listen port', attr: 'ssl_port', value: 45, match: %r{\s+listen\s+\*:45 ssl;} }, { title: 'should set SPDY', attr: 'spdy', value: 'on', match: %r{\s+listen\s+\*:443 ssl spdy;} }, { title: 'should not set SPDY', attr: 'spdy', value: 'off', match: %r{\s+listen\s+\*:443 ssl;} }, { title: 'should set HTTP2', attr: 'http2', value: 'on', match: %r{\s+listen\s+\*:443 ssl http2;} }, { title: 'should not set HTTP2', attr: 'http2', value: 'off', match: %r{\s+listen\s+\*:443 ssl;} }, { title: 'should set the IPv4 listen options', attr: 'listen_options', value: 'default', match: %r{\s+listen\s+\*:443 ssl default;} }, { title: 'should enable IPv6', attr: 'ipv6_enable', value: true, match: %r{\s+listen\s+\[::\]:443 ssl default ipv6only=on;} }, { title: 'should disable IPv6', attr: 'ipv6_enable', value: false, notmatch: %r{ listen \[::\]:443 ssl default ipv6only=on;} }, { title: 'should set the IPv6 listen IP', attr: 'ipv6_listen_ip', value: '2001:0db8:85a3:0000:0000:8a2e:0370:7334', match: %r{\s+listen\s+\[2001:0db8:85a3:0000:0000:8a2e:0370:7334\]:443 ssl default ipv6only=on;} }, { title: 'should set the IPv6 listen port', attr: 'ssl_port', value: 45, match: %r{\s+listen\s+\[::\]:45 ssl default ipv6only=on;} }, { title: 'should set the IPv6 listen options', attr: 'ipv6_listen_options', value: 'spdy default', match: %r{\s+listen\s+\[::\]:443 ssl spdy default;} }, { title: 'should set servername(s)', attr: 'server_name', value: ['www.foo.com', 'foo.com'], match: %r{\s+server_name\s+www.foo.com foo.com;} }, { title: 'should rewrite www servername to non-www', attr: 'rewrite_www_to_non_www', value: true, match: %r{\s+server_name\s+rspec.example.com;} }, { title: 'should not rewrite www servername to non-www', attr: 'rewrite_www_to_non_www', value: false, match: %r{\s+server_name\s+www.rspec.example.com;} }, { title: 'should set the SSL buffer size', attr: 'ssl_buffer_size', value: '4k', match: ' ssl_buffer_size 4k;' }, { title: 'should set the SSL client certificate file', attr: 'ssl_client_cert', value: '/tmp/client_certificate', match: %r{\s+ssl_client_certificate\s+/tmp/client_certificate;} }, { title: 'should set the SSL CRL file', attr: 'ssl_crl', value: '/tmp/crl', match: %r{\s+ssl_crl\s+/tmp/crl;} }, { title: 'should set the SSL DH parameters file', attr: 'ssl_dhparam', value: '/tmp/dhparam', match: %r{\s+ssl_dhparam\s+/tmp/dhparam;} }, { title: 'should set ssl_ecdh_curve', attr: 'ssl_ecdh_curve', value: 'secp521r1', match: %r{\s+ssl_ecdh_curve\s+secp521r1;} }, { title: 'should set the SSL stapling file', attr: 'ssl_stapling_file', value: '/tmp/stapling_file', match: %r{\s+ssl_stapling_file\s+/tmp/stapling_file;} }, { title: 'should set the SSL trusted certificate file', attr: 'ssl_trusted_cert', value: '/tmp/trusted_certificate', match: %r{\s+ssl_trusted_certificate\s+/tmp/trusted_certificate;} }, { title: 'should set ssl_verify_depth', attr: 'ssl_verify_depth', value: 2, match: %r{^\s+ssl_verify_depth\s+2;} }, { title: 'should set the SSL cache', attr: 'ssl_cache', value: 'shared:SSL:1m', match: %r{\s+ssl_session_cache\s+shared:SSL:1m;} }, { title: 'should set the SSL timeout', attr: 'ssl_session_timeout', value: '30m', match: ' ssl_session_timeout 30m;' }, { title: 'should set the SSL protocols', attr: 'ssl_protocols', value: 'TLSv1', match: %r{\s+ssl_protocols\s+TLSv1;} }, { title: 'should set the SSL ciphers', attr: 'ssl_ciphers', value: 'HIGH', match: %r{\s+ssl_ciphers\s+HIGH;} }, { title: 'should set ssl_prefer_server_ciphers on', attr: 'ssl_prefer_server_ciphers', value: 'on', match: %r{\s+ssl_prefer_server_ciphers\s+on;} }, { title: 'should set ssl_prefer_server_ciphers off', attr: 'ssl_prefer_server_ciphers', value: 'off', match: %r{\s+ssl_prefer_server_ciphers\s+off;} }, { title: 'should not set absolute_redirect', attr: 'absolute_redirect', value: :undef, notmatch: %r{absolute_redirect} }, { title: 'should set absolute_redirect off', attr: 'absolute_redirect', value: 'off', match: ' absolute_redirect off;' }, { title: 'should set auth_basic', attr: 'auth_basic', value: 'value', match: %r{\s+auth_basic\s+"value";} }, { title: 'should set auth_basic_user_file', attr: 'auth_basic_user_file', value: 'value', match: %r{\s+auth_basic_user_file\s+"value";} }, { title: 'should set auth_request', attr: 'auth_request', value: 'value', match: %r{\s+auth_request\s+value;} }, { title: 'should set the client_body_timeout', attr: 'client_body_timeout', value: 'value', match: %r{^\s+client_body_timeout\s+value;} }, { title: 'should set the client_header_timeout', attr: 'client_header_timeout', value: 'value', match: %r{^\s+client_header_timeout\s+value;} }, { title: 'should set the gzip_types', attr: 'gzip_types', value: 'value', match: %r{^\s+gzip_types\s+value;} }, { title: 'should set access_log', attr: 'access_log', value: '/path/to/access.log', match: ' access_log /path/to/access.log;' }, { title: 'should set multiple access_log directives', attr: 'access_log', value: ['/path/to/log/1', 'syslog:server=localhost'], match: [ ' access_log /path/to/log/1;', ' access_log syslog:server=localhost;' ] }, { title: 'should set access_log off', attr: 'access_log', value: 'off', match: ' access_log off;' }, { title: 'should not include access_log in server when set to absent', attr: 'access_log', value: 'absent', notmatch: 'access_log' }, { title: 'should set access_log to syslog', attr: 'access_log', value: 'syslog:server=localhost', match: ' access_log syslog:server=localhost;' }, { title: 'should set format_log custom_format', attr: 'format_log', value: 'custom', match: ' access_log /var/log/nginx/ssl-www.rspec.example.com.access.log custom;' }, { title: 'should set error_log', attr: 'error_log', value: '/path/to/error.log', match: ' error_log /path/to/error.log;' }, { title: 'should allow multiple error_log directives', attr: 'error_log', value: ['/path/to/error.log', 'syslog:server=localhost'], match: [ ' error_log /path/to/error.log;', ' error_log syslog:server=localhost;' ] }, { title: 'should not include error_log in server when set to absent', attr: 'error_log', value: 'absent', notmatch: 'error_log' }, { title: 'should set error_pages', attr: 'error_pages', value: { '503' => '/foo.html' }, match: ' error_page 503 /foo.html;' }, { title: 'should contain raw_prepend directives', attr: 'raw_prepend', value: [ 'if (a) {', ' b;', '}' ], match: %r{^\s+if \(a\) \{\n\s++b;\n\s+\}} }, { title: 'should contain ordered prepend directives', attr: 'server_cfg_prepend', value: { 'test1' => 'test value 1', 'test2' => ['test value 2a', 'test value 2b'], 'allow' => 'test value 3' }, match: [ ' allow test value 3;', ' test1 test value 1;', ' test2 test value 2a;', ' test2 test value 2b;' ] }, { title: 'should contain ordered ssl prepend directives', attr: 'server_cfg_ssl_prepend', value: { 'test1' => 'test value 1', 'test2' => ['test value 2a', 'test value 2b'], 'allow' => 'test value 3' }, match: [ ' allow test value 3;', ' test1 test value 1;', ' test2 test value 2a;', ' test2 test value 2b;' ] }, { title: 'should set root', attr: 'use_default_location', value: false, match: ' root /;' }, { title: 'should not set root', attr: 'use_default_location', value: true, notmatch: %r{ root /;} }, { title: 'should set index_file(s)', attr: 'index_files', value: %w[name1 name2], match: %r{\s*index\s+name1\s+name2;} }, { title: 'should not set index_file(s)', attr: 'index_files', value: [], notmatch: %r{\s+index\s+} }, { title: 'should set autoindex', attr: 'autoindex', value: 'on', match: ' autoindex on;' }, { title: 'should set autoindex_exact_size', attr: 'autoindex_exact_size', value: 'on', match: ' autoindex_exact_size on;' } ].each do |param| context "when #{param[:attr]} is #{param[:value]}" do let :params do default_params.merge(param[:attr].to_sym => param[:value], :ssl => true, :ssl_key => 'dummy.key', :ssl_cert => 'dummy.crt') end it { is_expected.to contain_concat__fragment("#{title}-ssl-header") } it param[:title] do matches = Array(param[:match]) if matches.all? { |m| m.is_a? Regexp } matches.each { |item| is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(item) } else lines = catalogue.resource('concat::fragment', "#{title}-ssl-header").send(:parameters)[:content].split("\n") expect(lines & Array(param[:match])).to eq(Array(param[:match])) end Array(param[:notmatch]).each do |item| is_expected.to contain_concat__fragment("#{title}-ssl-header").without_content(item) end end end end end describe 'server_ssl_footer template content' do [ { title: 'should not contain www to non-www rewrite', attr: 'rewrite_www_to_non_www', value: false, notmatch: %r{ ^ \s+server_name\s+www\.rspec\.example\.com;\n \s+return\s+301\s+https://rspec\.example\.com\$request_uri; }x }, { title: 'should contain include directives', attr: 'include_files', value: ['/file1', '/file2'], match: [ %r{^\s+include\s+/file1;}, %r{^\s+include\s+/file2;} ] }, { title: 'should contain ordered appended directives', attr: 'server_cfg_append', value: { 'test1' => 'test value 1', 'test2' => 'test value 2', 'allow' => 'test value 3' }, match: [ ' allow test value 3;', ' test1 test value 1;', ' test2 test value 2;' ] }, { title: 'should contain raw_append directives', attr: 'raw_append', value: [ 'if (a) {', ' b;', '}' ], match: %r{^\s+if \(a\) \{\n\s++b;\n\s+\}} }, { title: 'should contain ordered ssl appended directives', attr: 'server_cfg_ssl_append', value: { 'test1' => 'test value 1', 'test2' => ['test value 2a', 'test value 2b'], 'allow' => 'test value 3' }, match: [ ' allow test value 3;', ' test1 test value 1;', ' test2 test value 2a;', ' test2 test value 2b;' ] } ].each do |param| context "when #{param[:attr]} is #{param[:value]}" do let :params do default_params.merge(param[:attr].to_sym => param[:value], :ssl => true, :ssl_key => 'dummy.key', :ssl_cert => 'dummy.crt') end it { is_expected.to contain_concat__fragment("#{title}-ssl-footer") } it param[:title] do matches = Array(param[:match]) if matches.all? { |m| m.is_a? Regexp } matches.each { |item| is_expected.to contain_concat__fragment("#{title}-ssl-footer").with_content(item) } else lines = catalogue.resource('concat::fragment', "#{title}-ssl-footer").send(:parameters)[:content].split("\n") expect(lines & Array(param[:match])).to eq(Array(param[:match])) end Array(param[:notmatch]).each do |item| is_expected.to contain_concat__fragment("#{title}-ssl-footer").without_content(item) end end end end end context 'attribute resources' do context 'with SSL enabled, www rewrite to naked domain with multiple server_names' do let(:title) { 'foo.com' } let(:params) do { ssl: true, ssl_cert: 'cert', ssl_key: 'key', server_name: %w[www.foo.com bar.foo.com foo.com], use_default_location: false, rewrite_www_to_non_www: true } end it "sets the server_name of the rewrite server stanza to every server_name with 'www.' stripped" do is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{^\s+server_name\s+foo.com\s+bar.foo.com\s+foo.com;}) end end context 'with SSL disabled, www rewrite to naked domain with multiple server_names' do let(:title) { 'foo.com' } let(:params) do { server_name: %w[www.foo.com bar.foo.com foo.com], use_default_location: false, rewrite_www_to_non_www: true } end it "sets the server_name of the rewrite server stanza to every server_name with 'www.' stripped" do is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{^\s+server_name\s+foo.com\s+bar.foo.com\s+foo.com;}) end end context 'ssl_redirect' do let(:params) { { ssl_redirect: true } } it { is_expected.to contain_concat__fragment("#{title}-header").without_content(%r{^\s*index\s+}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{ return 301 https://\$host\$request_uri;}) } end context 'ssl_redirect with alternate port' do let(:params) { { ssl_redirect: true, ssl_port: 8888 } } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{ return 301 https://\$host:8888\$request_uri;}) } end context 'ssl_redirect with standard port set explicitly' do let(:params) { { ssl_redirect: true, ssl_port: 443 } } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{ return 301 https://\$host\$request_uri;}) } end context 'ssl_redirect with overridden port' do let(:params) { { ssl_redirect: true, ssl_redirect_port: 8878 } } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{ return 301 https://\$host:8878\$request_uri;}) } end context 'ssl_redirect with ssl_port set and overridden redirect port' do let(:params) do { ssl_redirect: true, ssl_redirect_port: 9787, ssl_port: 9783 } end it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{ return 301 https://\$host:9787\$request_uri;}) } end context 'ssl_redirect should set ssl_only when ssl => true' do let(:params) do { ssl_redirect: true, ssl: true, ssl_key: 'dummy.key', ssl_cert: 'dummy.crt' } end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_ssl_only(true) } end context 'ssl_redirect should not include default location when ssl => false' do let(:params) do { ssl_redirect: true, ssl: false } end it { is_expected.not_to contain_nginx__resource__location("#{title}-default") } end context 'SSL cert and key are both set to fully qualified paths' do let(:params) { { ssl: true, ssl_cert: '/tmp/foo.crt', ssl_key: '/tmp/foo.key:' } } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate\s+/tmp/foo.crt}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate_key\s+/tmp/foo.key}) } end context 'SSL cert and key are both set to false' do let(:params) { { ssl: true, ssl_cert: false, ssl_key: false } } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").without_content(%r{ssl_certificate}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").without_content(%r{ssl_certificate_key}) } end context 'SSL cert and key are both an array' do - let(:params) { { - ssl: true, - ssl_cert: ['/tmp/foo1.crt', '/tmp/foo2.crt'], - ssl_key: ['/tmp/foo1.key', '/tmp/foo2.key'], - } } + let(:params) do + { + ssl: true, + ssl_cert: ['/tmp/foo1.crt', '/tmp/foo2.crt'], + ssl_key: ['/tmp/foo1.key', '/tmp/foo2.key'], + } + end it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate\s+/tmp/foo1.crt}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate_key\s+/tmp/foo1.key}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate\s+/tmp/foo2.crt}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate_key\s+/tmp/foo2.key}) } end context 'when use_default_location => true' do let :params do default_params.merge(use_default_location: true) end it { is_expected.to contain_nginx__resource__location("#{title}-default") } end context 'when use_default_location => false' do let :params do default_params.merge(use_default_location: false) end it { is_expected.not_to contain_nginx__resource__location("#{title}-default") } end context 'when location_cfg_prepend => { key => value }' do let :params do default_params.merge(location_cfg_prepend: { 'key' => 'value' }) end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_location_cfg_prepend('key' => 'value') } end context "when location_raw_prepend => [ 'foo;' ]" do let :params do default_params.merge(location_raw_prepend: ['foo;']) end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_raw_prepend(['foo;']) } end context "when location_raw_append => [ 'foo;' ]" do let :params do default_params.merge(location_raw_append: ['foo;']) end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_raw_append(['foo;']) } end context 'when location_cfg_append => { key => value }' do let :params do default_params.merge(location_cfg_append: { 'key' => 'value' }) end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_location_cfg_append('key' => 'value') } end context 'when fastcgi => "localhost:9000"' do let :params do default_params.merge(fastcgi: 'localhost:9000') end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_fastcgi_params('/etc/nginx/fastcgi.conf') } it { is_expected.to contain_file('/etc/nginx/fastcgi.conf').with_mode('0644') } end context 'when fastcgi_params is non-default' do let :params do default_params.merge(fastcgi: 'localhost:9000', fastcgi_params: '/etc/nginx/mycustomparams') end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_fastcgi_params('/etc/nginx/mycustomparams') } it { is_expected.not_to contain_file('/etc/nginx/mycustomparams') } end context 'when fastcgi_params is not defined' do let :params do default_params.merge(fastcgi: 'localhost:9000', fastcgi_params: nil) end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_fastcgi_params('nil') } it { is_expected.not_to contain_file('/etc/nginx/fastcgi.conf') } end context 'when fastcgi_index => "index.php"' do let :params do default_params.merge(fastcgi_index: 'index.php') end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_fastcgi_index('index.php') } end context 'when fastcgi_param => {key => value}' do let :params do default_params.merge(fastcgi_param: { 'key' => 'value' }) end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_fastcgi_param('key' => 'value') } end context 'when uwsgi => "uwsgi_upstream"' do let :params do default_params.merge(uwsgi: 'uwsgi_upstream') end it { is_expected.to contain_file('/etc/nginx/uwsgi_params').with_mode('0644') } end context 'when uwsgi_params is non-default' do let :params do default_params.merge(uwsgi: 'uwsgi_upstream', uwsgi_params: '/etc/nginx/bogusparams') end it { is_expected.not_to contain_file('/etc/nginx/bogusparams') } end context 'when listen_port == ssl_port but ssl = false' do let :params do default_params.merge(listen_port: 80, ssl_port: 80, ssl: false) end # TODO: implement test after this can be tested # msg = %r{nginx: ssl must be true if listen_port is the same as ssl_port} it 'Testing for warnings not yet implemented in classes' end context 'when listen_port != ssl_port' do let :params do default_params.merge(listen_port: 80, ssl_port: 443) end it { is_expected.to contain_concat__fragment("#{title}-header") } it { is_expected.to contain_concat__fragment("#{title}-footer") } end context 'when ensure => absent' do let :params do default_params.merge(ensure: 'absent', ssl: true, ssl_key: 'dummy.key', ssl_cert: 'dummy.cert') end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_ensure('absent') } it { is_expected.to contain_file("#{title}.conf symlink").with_ensure('absent') } it { is_expected.to contain_concat("/etc/nginx/sites-available/#{title}.conf").with_ensure('absent') } end context 'when ssl => true and ssl_port == listen_port' do let :params do default_params.merge(ssl: true, listen_port: 80, ssl_port: 80, ssl_key: 'dummy.key', ssl_cert: 'dummy.cert') end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_ssl_only(true) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{access_log\s+/var/log/nginx/ssl-www\.rspec\.example\.com\.access\.log;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{error_log\s+/var/log/nginx/ssl-www\.rspec\.example\.com\.error\.log}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate\s+dummy.cert;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_certificate_key\s+dummy.key;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-footer") } end context 'when ssl_client_cert is set' do let :params do default_params.merge(ssl: true, listen_port: 80, ssl_port: 80, ssl_key: 'dummy.key', ssl_cert: 'dummy.cert', ssl_client_cert: 'client.cert', ssl_verify_client: 'optional') end it { is_expected.to contain_nginx__resource__location("#{title}-default").with_ssl_only(true) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{access_log\s+/var/log/nginx/ssl-www\.rspec\.example\.com\.access\.log;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{error_log\s+/var/log/nginx/ssl-www\.rspec\.example\.com\.error\.log}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{ssl_verify_client\s+optional;}) } end context 'when passenger_cgi_param is set' do let :params do default_params.merge(passenger_cgi_param: { 'test1' => 'test value 1', 'test2' => 'test value 2', 'test3' => 'test value 3' }) end it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_set_cgi_param test1 test value 1;}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_set_cgi_param test2 test value 2;}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_set_cgi_param test3 test value 3;}) } end context 'when passenger_cgi_param is set and ssl => true' do let :params do default_params.merge(passenger_cgi_param: { 'test1' => 'test value 1', 'test2' => 'test value 2', 'test3' => 'test value 3' }, ssl: true, ssl_key: 'dummy.key', ssl_cert: 'dummy.cert') end it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_set_cgi_param test1 test value 1;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_set_cgi_param test2 test value 2;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_set_cgi_param test3 test value 3;}) } end context 'when passenger_set_header is set' do let :params do default_params.merge(passenger_set_header: { 'test1' => 'test value 1', 'test2' => 'test value 2', 'test3' => 'test value 3' }) end it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_set_header test1 test value 1;}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_set_header test2 test value 2;}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_set_header test3 test value 3;}) } end context 'when passenger_set_header is set and ssl => true' do let :params do default_params.merge(passenger_set_header: { 'test1' => 'test value 1', 'test2' => 'test value 2', 'test3' => 'test value 3' }, ssl: true, ssl_key: 'dummy.key', ssl_cert: 'dummy.cert') end it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_set_header test1 test value 1;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_set_header test2 test value 2;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_set_header test3 test value 3;}) } end context 'when passenger_env_var is set' do let :params do default_params.merge(passenger_env_var: { 'test1' => 'test value 1', 'test2' => 'test value 2', 'test3' => 'test value 3' }) end it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_env_var test1 test value 1;}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_env_var test2 test value 2;}) } it { is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{passenger_env_var test3 test value 3;}) } end context 'when passenger_env_var is set and ssl => true' do let :params do default_params.merge(passenger_env_var: { 'test1' => 'test value 1', 'test2' => 'test value 2', 'test3' => 'test value 3' }, ssl: true, ssl_key: 'dummy.key', ssl_cert: 'dummy.cert') end it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_env_var test1 test value 1;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_env_var test2 test value 2;}) } it { is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{passenger_env_var test3 test value 3;}) } end context 'when passenger_pre_start is a string' do let :params do default_params.merge(passenger_pre_start: 'http://example.com:80/test/me') end it { is_expected.to contain_concat__fragment("#{title}-footer").with_content(%r{passenger_pre_start http://example.com:80/test/me;}) } end context 'when passenger_pre_start is an array' do let :params do default_params.merge(passenger_pre_start: ['http://example.com:80/test/me', 'http://example.com:3009/foo/bar']) end it { is_expected.to contain_concat__fragment("#{title}-footer").with_content(%r{passenger_pre_start http://example.com:80/test/me;}) } it { is_expected.to contain_concat__fragment("#{title}-footer").with_content(%r{passenger_pre_start http://example.com:3009/foo/bar;}) } end context 'when server name is sanitized' do let(:title) { 'www rspec-server com' } let(:params) { default_params } it { is_expected.to contain_concat('/etc/nginx/sites-available/www_rspec-server_com.conf') } end context 'when add_header is set' do let :params do default_params.merge(add_header: { 'header3' => { '' => '\'test value 3\' tv3' }, 'header2' => { 'test value 2' => 'tv2' }, 'header1' => 'test value 1' }) end it 'has correctly ordered entries in the config' do is_expected.to contain_concat__fragment("#{title}-header").with_content(%r{\s+add_header\s+"header1" "test value 1";\n\s+add_header\s+"header2" "test value 2" tv2;\n\s+add_header\s+"header3" 'test value 3' tv3;\n}) end end context 'when add_header is set and ssl => true' do let :params do default_params.merge(add_header: { 'header3' => { '' => '\'test value 3\' tv3' }, 'header2' => { 'test value 2' => 'tv2' }, 'header1' => 'test value 1' }, ssl: true, ssl_key: 'dummy.key', ssl_cert: 'dummy.cert') end it 'has correctly ordered entries in the config' do is_expected.to contain_concat__fragment("#{title}-ssl-header").with_content(%r{\s+add_header\s+"header1" "test value 1";\n\s+add_header\s+"header2" "test value 2" tv2;\n\s+add_header\s+"header3" 'test value 3' tv3;\n}) end end end describe 'with locations' do context 'simple location' do let(:params) do { use_default_location: false, locations: { 'one' => { 'location_custom_cfg' => {}, 'location' => '/one', 'expires' => '@12h34m' } } } end it { is_expected.to contain_nginx__resource__location('one') } it { is_expected.to contain_nginx__resource__location('one').with_location('/one') } it { is_expected.to contain_nginx__resource__location('one').with_expires('@12h34m') } end context 'multiple locations' do let(:params) do { use_default_location: false, locations: { 'one' => { 'location_custom_cfg' => {}, 'location' => '/one', 'expires' => '@12h34m' }, 'two' => { 'location_custom_cfg' => {}, 'location' => '= /two', 'expires' => '@23h45m' } } } end it { is_expected.to contain_nginx__resource__location('one') } it { is_expected.to contain_nginx__resource__location('one').with_location('/one') } it { is_expected.to contain_nginx__resource__location('one').with_expires('@12h34m') } it { is_expected.to contain_nginx__resource__location('two') } it { is_expected.to contain_nginx__resource__location('two').with_location('= /two') } it { is_expected.to contain_nginx__resource__location('two').with_expires('@23h45m') } end context 'with locations default' do let(:params) do { www_root: '/toplevel', locations_defaults: { 'www_root' => '/overwrite', 'expires' => '@12h34m' }, locations: { 'one' => { 'location_custom_cfg' => {}, 'location' => '/one' }, 'two' => { 'location_custom_cfg' => {}, 'location' => '= /two' } } } end it { is_expected.to contain_nginx__resource__location('one') } it { is_expected.to contain_nginx__resource__location('one').with_location('/one') } it { is_expected.to contain_nginx__resource__location('one').with_www_root('/overwrite') } it { is_expected.to contain_nginx__resource__location('one').with_expires('@12h34m') } it { is_expected.to contain_nginx__resource__location('two') } it { is_expected.to contain_nginx__resource__location('two').with_location('= /two') } it { is_expected.to contain_nginx__resource__location('two').with_www_root('/overwrite') } it { is_expected.to contain_nginx__resource__location('two').with_expires('@12h34m') } end end end end end end