diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ecb10a8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# editorconfig.org + +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +tab_width = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..048d2b5 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +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. [GitHub Actions](https://docs.github.com/en/actions) run 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 +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 + +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/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..593e7aa --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,26 @@ + + +## Affected Puppet, Ruby, OS and module versions/distributions + +- Puppet: +- Ruby: +- Distribution: +- Module version: + +## How to reproduce (e.g Puppet code you use) + +## What are you seeing + +## What behaviour did you expect instead + +## Output log + +## Any additional information you'd like to impart diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..342807b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ + +#### Pull Request (PR) description + + +#### This Pull Request (PR) fixes the following issues + diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..cacadf2 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,3 @@ +# Vox Pupuli Security Policy + +Our vulnerabilities reporting process is at https://voxpupuli.org/security/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c5dad05 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,66 @@ +--- +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +name: CI + +on: pull_request + +concurrency: + group: ${{ github.head_ref }} + cancel-in-progress: true + +jobs: + setup_matrix: + name: 'Setup Test Matrix' + runs-on: ubuntu-latest + timeout-minutes: 40 + outputs: + puppet_unit_test_matrix: ${{ steps.get-outputs.outputs.puppet_unit_test_matrix }} + github_action_test_matrix: ${{ steps.get-outputs.outputs.github_action_test_matrix }} + env: + BUNDLE_WITHOUT: development:system_tests:release + steps: + - uses: actions/checkout@v2 + - name: Setup ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.0' + bundler-cache: true + - name: Run static validations + run: bundle exec rake validate lint check + - 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 parallel_spec + + tests: + needs: + - unit + runs-on: ubuntu-latest + name: Test suite + steps: + - run: echo Test suite completed diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..664ba69 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,34 @@ +--- +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +name: Release + +on: + push: + tags: + - '*' + +env: + BUNDLE_WITHOUT: development:test:system_tests + +jobs: + deploy: + name: 'deploy to forge' + runs-on: ubuntu-latest + if: github.repository_owner == 'voxpupuli' + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '2.7' + bundler-cache: true + - name: Build and Deploy + env: + # Configure secrets here: + # https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets + BLACKSMITH_FORGE_USERNAME: '${{ secrets.PUPPET_FORGE_USERNAME }}' + BLACKSMITH_FORGE_API_KEY: '${{ secrets.PUPPET_FORGE_API_KEY }}' + run: bundle exec rake module:push diff --git a/.gitignore b/.gitignore index bb8970a..9b95224 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,23 @@ -.*.sw[op] -.metadata -.yardoc -.yardwarns -*.iml -/.bundle/ -/.idea/ -/.vagrant/ -/coverage/ -/bin/ -/doc/ -/Gemfile.local -/Gemfile.lock -/junit/ -/log/ -/log/ -/pkg/ -/spec/fixtures/manifests/ -/spec/fixtures/modules/ -/tmp/ -/vendor/ +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ +pkg/ +Gemfile.lock +Gemfile.local +vendor/ +.vendor/ +spec/fixtures/manifests/ +spec/fixtures/modules/ +.vagrant/ +.bundle/ +.ruby-version +coverage/ +log/ +.idea/ +.dependencies/ +.librarian/ +Puppetfile.lock +*.iml +.*.sw? +.yardoc/ +Guardfile diff --git a/.msync.yml b/.msync.yml new file mode 100644 index 0000000..a83abd9 --- /dev/null +++ b/.msync.yml @@ -0,0 +1,5 @@ +--- +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +modulesync_config_version: '5.1.0' diff --git a/.overcommit.yml b/.overcommit.yml new file mode 100644 index 0000000..d367ada --- /dev/null +++ b/.overcommit.yml @@ -0,0 +1,65 @@ +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ +# +# Hooks are only enabled if you take action. +# +# To enable the hooks run: +# +# ``` +# bundle exec overcommit --install +# # ensure .overcommit.yml does not harm to you and then +# bundle exec overcommit --sign +# ``` +# +# (it will manage the .git/hooks directory): +# +# Examples howto skip a test for a commit or push: +# +# ``` +# SKIP=RuboCop git commit +# SKIP=PuppetLint git commit +# SKIP=RakeTask git push +# ``` +# +# Don't invoke overcommit at all: +# +# ``` +# OVERCOMMIT_DISABLE=1 git commit +# ``` +# +# Read more about overcommit: https://github.com/brigade/overcommit +# +# To manage this config yourself in your module add +# +# ``` +# .overcommit.yml: +# unmanaged: true +# ``` +# +# to your modules .sync.yml config +--- +PreCommit: + RuboCop: + enabled: true + description: 'Runs rubocop on modified files only' + command: ['bundle', 'exec', 'rubocop'] + PuppetLint: + enabled: true + description: 'Runs puppet-lint on modified files only' + command: ['bundle', 'exec', 'puppet-lint'] + YamlSyntax: + enabled: true + JsonSyntax: + enabled: true + TrailingWhitespace: + enabled: true + +PrePush: + RakeTarget: + enabled: true + description: 'Run rake targets' + targets: + - 'validate' + - 'test' + - 'rubocop' + command: ['bundle', 'exec', 'rake'] diff --git a/.pdkignore b/.pdkignore deleted file mode 100644 index c444699..0000000 --- a/.pdkignore +++ /dev/null @@ -1,48 +0,0 @@ -# Defaults -.git/ -.*.sw[op] -.metadata -.yardoc -.yardwarns -*.iml -/.bundle/ -/.idea/ -/.vagrant/ -/coverage/ -/bin/ -/doc/ -/Gemfile.local -/Gemfile.lock -/junit/ -/log/ -/pkg/ -/spec/fixtures/manifests/ -/spec/fixtures/modules/ -/tmp/ -/vendor/ -/convert_report.txt -/update_report.txt -.DS_Store -.project -.envrc -/inventory.yaml -/appveyor.yml -/.fixtures.yml -/Gemfile -/.gitattributes -/.gitignore -/.gitlab-ci.yml -/.pdkignore -/Rakefile -/rakelib/ -/.rspec -/.rubocop.yml -/.travis.yml -/.yardopts -/spec/ -/.vscode/ - -# Custom -.pmtignore -Vagrantfile -Vagrantfile.d diff --git a/.pmtignore b/.pmtignore index fb58957..65f5051 100644 --- a/.pmtignore +++ b/.pmtignore @@ -1,20 +1,37 @@ +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + docs/ pkg/ +Gemfile Gemfile.lock Gemfile.local vendor/ .vendor/ -spec/fixtures/manifests/ -spec/fixtures/modules/ +spec/ +Rakefile .vagrant/ .bundle/ .ruby-version coverage/ log/ .idea/ .dependencies/ +.github/ .librarian/ Puppetfile.lock *.iml +.editorconfig +.fixtures.yml +.gitignore +.msync.yml +.overcommit.yml +.pmtignore +.rspec +.rspec_parallel +.rubocop.yml +.sync.yml .*.sw? .yardoc/ +.yardopts +Dockerfile diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 0000000..dd8272c --- /dev/null +++ b/.puppet-lint.rc @@ -0,0 +1,3 @@ +--fail-on-warnings +--no-parameter_documentation-check +--no-parameter_types-check diff --git a/.rspec b/.rspec index 16f9cdb..f634583 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1,5 @@ ---color +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + --format documentation +--color diff --git a/.rspec_parallel b/.rspec_parallel new file mode 100644 index 0000000..a9a84f8 --- /dev/null +++ b/.rspec_parallel @@ -0,0 +1,4 @@ +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +--format progress diff --git a/.rubocop.yml b/.rubocop.yml index 4827ee5..53ac189 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,108 +1,6 @@ --- -require: rubocop-rspec -AllCops: - TargetRubyVersion: '2.1' - Include: - - "./**/*.rb" - Exclude: - - bin/* - - ".vendor/**/*" - - Gemfile - - Rakefile - - pkg/**/* - - spec/fixtures/**/* - - vendor/**/* -Metrics/LineLength: - Description: People have wide screens, use them. - Max: 200 -RSpec/BeforeAfterAll: - Description: Beware of using after(:all) as it may cause state to leak between tests. - A necessary evil in acceptance testing. - Exclude: - - spec/acceptance/**/*.rb -RSpec/HookArgument: - Description: Prefer explicit :each argument, matching existing module's style - EnforcedStyle: each -Style/BlockDelimiters: - Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to - be consistent then. - EnforcedStyle: braces_for_chaining -Style/ClassAndModuleChildren: - Description: Compact style reduces the required amount of indentation. - EnforcedStyle: compact -Style/EmptyElse: - Description: Enforce against empty else clauses, but allow `nil` for clarity. - EnforcedStyle: empty -Style/FormatString: - Description: Following the main puppet project's style, prefer the % format format. - EnforcedStyle: percent -Style/FormatStringToken: - Description: Following the main puppet project's style, prefer the simpler template - tokens over annotated ones. - EnforcedStyle: template -Style/Lambda: - Description: Prefer the keyword for easier discoverability. - EnforcedStyle: literal -Style/RegexpLiteral: - Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 - EnforcedStyle: percent_r -Style/TernaryParentheses: - Description: Checks for use of parentheses around ternary conditions. Enforce parentheses - on complex expressions for better readability, but seriously consider breaking - it up. - EnforcedStyle: require_parentheses_when_complex -Style/TrailingCommaInArguments: - Description: Prefer always trailing comma on multiline argument lists. This makes - diffs, and re-ordering nicer. - EnforcedStyleForMultiline: comma -Style/TrailingCommaInLiteral: - Description: Prefer always trailing comma on multiline literals. This makes diffs, - and re-ordering nicer. - EnforcedStyleForMultiline: comma -Style/SymbolArray: - Description: Using percent style obscures symbolic intent of array's contents. - EnforcedStyle: brackets -Style/CollectionMethods: - Enabled: true -Style/MethodCalledOnDoEndBlock: - Enabled: true -Style/MixinUsage: - Exclude: - - spec/spec_helper.rb -Style/StringMethods: - Enabled: true -Metrics/AbcSize: - Enabled: false -Metrics/BlockLength: - Enabled: false -Metrics/ClassLength: - Enabled: false -Metrics/CyclomaticComplexity: - Enabled: false -Metrics/MethodLength: - Enabled: false -Metrics/ModuleLength: - Enabled: false -Metrics/ParameterLists: - Enabled: false -Metrics/PerceivedComplexity: - Enabled: false -RSpec/DescribeClass: - Enabled: false -RSpec/ExampleLength: - Enabled: false -RSpec/MessageExpectation: - Enabled: false -RSpec/MultipleExpectations: - Enabled: false -RSpec/NestedGroups: - Enabled: false -Style/AsciiComments: - Enabled: false -Style/IfUnlessModifier: - Enabled: false -Style/SymbolProc: - Enabled: false -Naming/FileName: - Exclude: - - Vagrantfile +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +inherit_gem: + voxpupuli-test: rubocop.yml diff --git a/.yardopts b/.yardopts deleted file mode 100644 index 3687f51..0000000 --- a/.yardopts +++ /dev/null @@ -1,2 +0,0 @@ ---markup markdown ---output-dir docs/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e3cf307 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +# MANAGED BY MODULESYNC +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +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 6b6af0b..b6dcf45 100644 --- a/Gemfile +++ b/Gemfile @@ -1,126 +1,34 @@ -source ENV['GEM_SOURCE'] || 'https://rubygems.org' +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -def location_for(place_or_version, fake_version = nil) - if place_or_version =~ %r{\A(git[:@][^#]*)#(.*)} - [fake_version, { git: Regexp.last_match(1), branch: Regexp.last_match(2), require: false }].compact - elsif place_or_version =~ %r{\Afile:\/\/(.*)} - ['>= 0', { path: File.expand_path(Regexp.last_match(1)), require: false }] - else - [place_or_version, { require: false }] - end -end +source ENV['GEM_SOURCE'] || "https://rubygems.org" -def gem_type(place_or_version) - if place_or_version =~ %r{\Agit[:@]} - :git - elsif !place_or_version.nil? && place_or_version.start_with?('file:') - :file - else - :gem - end +group :test do + gem 'voxpupuli-test', '~> 5.0', :require => false + gem 'coveralls', :require => false + gem 'simplecov-console', :require => false + gem 'puppet_metadata', '~> 1.0', :require => false end -ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments -minor_version = ruby_version_segments[0..1].join('.') - group :development do - gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') - gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') - gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') - gem "puppet-module-posix-default-r#{minor_version}", require: false, platforms: [:ruby] - gem "puppet-module-posix-dev-r#{minor_version}", require: false, platforms: [:ruby] - gem "puppet-module-win-default-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-module-win-dev-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] -end - -puppet_version = ENV['PUPPET_GEM_VERSION'] -puppet_type = gem_type(puppet_version) -facter_version = ENV['FACTER_GEM_VERSION'] -hiera_version = ENV['HIERA_GEM_VERSION'] - -def puppet_older_than?(version) - puppet_version = ENV['PUPPET_GEM_VERSION'] - !puppet_version.nil? && - Gem::Version.correct?(puppet_version) && - Gem::Requirement.new("< #{version}").satisfied_by?(Gem::Version.new(puppet_version.dup)) -end - -gems = {} - -gems['puppet'] = location_for(puppet_version) - -# If facter or hiera versions have been specified via the environment -# variables, use those versions. If not, and if the puppet version is < 3.5.0, -# use known good versions of both for puppet < 3.5.0. -if facter_version - gems['facter'] = location_for(facter_version) -elsif puppet_type == :gem && puppet_older_than?('3.5.0') - gems['facter'] = ['>= 1.6.11', '<= 1.7.5', require: false] + gem 'guard-rake', :require => false + gem 'overcommit', '>= 0.39.1', :require => false end -if hiera_version - gems['hiera'] = location_for(ENV['HIERA_GEM_VERSION']) -elsif puppet_type == :gem && puppet_older_than?('3.5.0') - gem['hiera'] = ['>= 1.0.0', '<= 1.3.0', require: false] +group :system_tests do + gem 'voxpupuli-acceptance', '~> 1.0', :require => false end -if Gem.win_platform? && (puppet_type != :gem || puppet_older_than?('3.5.0')) - # For Puppet gems < 3.5.0 (tested as far back as 3.0.0) on Windows - if puppet_type == :gem - gems['ffi'] = ['1.9.0', require: false] - gems['minitar'] = ['0.5.4', require: false] - gems['win32-eventlog'] = ['0.5.3', '<= 0.6.5', require: false] - gems['win32-process'] = ['0.6.5', '<= 0.7.5', require: false] - gems['win32-security'] = ['~> 0.1.2', '<= 0.2.5', require: false] - gems['win32-service'] = ['0.7.2', '<= 0.8.8', require: false] - else - gems['ffi'] = ['~> 1.9.0', require: false] - gems['minitar'] = ['~> 0.5.4', require: false] - gems['win32-eventlog'] = ['~> 0.5', '<= 0.6.5', require: false] - gems['win32-process'] = ['~> 0.6', '<= 0.7.5', require: false] - gems['win32-security'] = ['~> 0.1', '<= 0.2.5', require: false] - gems['win32-service'] = ['~> 0.7', '<= 0.8.8', require: false] - end - - gems['win32-dir'] = ['~> 0.3', '<= 0.4.9', require: false] - - if RUBY_VERSION.start_with?('1.') - gems['win32console'] = ['1.3.2', require: false] - # sys-admin was removed in Puppet 3.7.0 and doesn't compile under Ruby 2.x - gems['sys-admin'] = ['1.5.6', require: false] - end - - # Puppet < 3.7.0 requires these. - # Puppet >= 3.5.0 gem includes these as requirements. - # The following versions are tested to work with 3.0.0 <= puppet < 3.7.0. - gems['win32-api'] = ['1.4.8', require: false] - gems['win32-taskscheduler'] = ['0.2.2', require: false] - gems['windows-api'] = ['0.4.3', require: false] - gems['windows-pr'] = ['1.2.3', require: false] -elsif Gem.win_platform? - # If we're using a Puppet gem on Windows which handles its own win32-xxx gem - # dependencies (>= 3.5.0), set the maximum versions (see PUP-6445). - gems['win32-dir'] = ['<= 0.4.9', require: false] - gems['win32-eventlog'] = ['<= 0.6.5', require: false] - gems['win32-process'] = ['<= 0.7.5', require: false] - gems['win32-security'] = ['<= 0.2.5', require: false] - gems['win32-service'] = ['<= 0.8.8', require: false] +group :release do + gem 'github_changelog_generator', '>= 1.16.1', :require => false if RUBY_VERSION >= '2.5' + gem 'voxpupuli-release', '>= 1.2.0', :require => false + gem 'puppet-strings', '>= 2.2', :require => false end -gems.each do |gem_name, gem_params| - gem gem_name, *gem_params -end +gem 'rake', :require => false +gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] -# Evaluate Gemfile.local and ~/.gemfile if they exist -extra_gemfiles = [ - "#{__FILE__}.local", - File.join(Dir.home, '.gemfile'), -] +puppetversion = ENV['PUPPET_VERSION'] || '>= 6.0' +gem 'puppet', puppetversion, :require => false, :groups => [:test] -extra_gemfiles.each do |gemfile| - if File.file?(gemfile) && File.readable?(gemfile) - eval(File.read(gemfile), binding) - end -end # vim: syntax=ruby diff --git a/Rakefile b/Rakefile index 82350f6..f92f051 100644 --- a/Rakefile +++ b/Rakefile @@ -1,11 +1,72 @@ -require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-syntax/tasks/puppet-syntax' - -desc 'Run the test suite.' -task :test => [ - :rubocop, - :syntax, - :validate, - :lint, - :spec -] +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +# Attempt to load voxpupuli-test (which pulls in puppetlabs_spec_helper), +# otherwise attempt to load it directly. +begin + require 'voxpupuli/test/rake' +rescue LoadError + begin + require 'puppetlabs_spec_helper/rake_tasks' + rescue LoadError + end +end + +# load optional tasks for acceptance +# only available if gem group releases is installed +begin + require 'voxpupuli/acceptance/rake' +rescue LoadError +end + +# load optional tasks for releases +# only available if gem group releases is installed +begin + require 'voxpupuli/release/rake_tasks' +rescue LoadError +end + +desc "Run main 'test' task and report merged results to coveralls" +task test_with_coveralls: [:test] do + if Dir.exist?(File.expand_path('../lib', __FILE__)) + require 'coveralls/rake/task' + Coveralls::RakeTask.new + Rake::Task['coveralls:push'].invoke + else + puts 'Skipping reporting to coveralls. Module has no lib dir' + end +end + +desc 'Generate REFERENCE.md' +task :reference, [:debug, :backtrace] do |t, args| + patterns = '' + Rake::Task['strings:generate:reference'].invoke(patterns, args[:debug], args[:backtrace]) +end + +begin + require 'github_changelog_generator/task' + require 'puppet_blacksmith' + GitHubChangelogGenerator::RakeTask.new :changelog do |config| + metadata = Blacksmith::Modulefile.new + config.future_release = "v#{metadata.version}" if metadata.version =~ /^\d+\.\d+.\d+$/ + config.header = "# Changelog\n\nAll notable changes to this project will be documented in this file.\nEach new release typically also includes the latest modulesync defaults.\nThese should not affect the functionality of the module." + config.exclude_labels = %w{duplicate question invalid wontfix wont-fix modulesync skip-changelog} + config.user = 'voxpupuli' + config.project = metadata.metadata['name'] + end + + # Workaround for https://github.com/github-changelog-generator/github-changelog-generator/issues/715 + require 'rbconfig' + if RbConfig::CONFIG['host_os'] =~ /linux/ + task :changelog do + puts 'Fixing line endings...' + changelog_file = File.join(__dir__, 'CHANGELOG.md') + changelog_txt = File.read(changelog_file) + new_contents = changelog_txt.gsub(%r{\r\n}, "\n") + File.open(changelog_file, "w") {|file| file.puts new_contents } + end + end + +rescue LoadError +end +# vim: syntax=ruby diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 59982b4..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: 1.1.x.{build} -skip_commits: - message: /^\(?doc\)?.*/ -clone_depth: 10 -init: - - SET - - 'mkdir C:\ProgramData\PuppetLabs\code && exit 0' - - 'mkdir C:\ProgramData\PuppetLabs\facter && exit 0' - - 'mkdir C:\ProgramData\PuppetLabs\hiera && exit 0' - - 'mkdir C:\ProgramData\PuppetLabs\puppet\var && exit 0' -environment: - matrix: - - PUPPET_GEM_VERSION: ~> 4.0 - RUBY_VERSION: 21-x64 - - PUPPET_GEM_VERSION: ~> 4.0 - RUBY_VERSION: 23-x64 -matrix: - fast_finish: true -install: - - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - - bundle install --jobs 4 --retry 2 --without system_tests - - type Gemfile.lock -build: off -test_script: - - bundle exec puppet -V - - ruby -v - - gem -v - - bundle -v - - bundle exec rake spec -notifications: - - provider: Email - to: - - nobody@nowhere.com - on_build_success: false - on_build_failure: false - on_build_status_changed: false diff --git a/manifests/repo.pp b/manifests/repo.pp index 774291c..ed2e11f 100644 --- a/manifests/repo.pp +++ b/manifests/repo.pp @@ -1,144 +1,144 @@ # elastic_stack::repo # # @summary Set up the package repository for Elastic Stack components # # @example # include elastic_stack::repo # # @param oss Whether to use the purely open source (i.e., bundled without X-Pack) repository # @param prerelease Whether to use a repo for prerelease versions, like "6.0.0-rc2" # @param priority A numeric priority for the repo, passed to the package management system # @param proxy The URL of a HTTP proxy to use for package downloads (YUM only) # @param version The (major) version of the Elastic Stack for which to configure the repo # @param base_repo_url The base url for the repo path class elastic_stack::repo ( Boolean $oss = false, Boolean $prerelease = false, Optional[Integer] $priority = undef, String $proxy = 'absent', Integer $version = 7, Optional[String] $base_repo_url = undef, ) { if $prerelease { $version_suffix = '.x-prerelease' } else { $version_suffix = '.x' } if $oss { $version_prefix = 'oss-' } else { $version_prefix = '' } - if $version > 2 { + if $version > 2 { # lint:ignore:version_comparison $_repo_url = $base_repo_url ? { undef => 'https://artifacts.elastic.co/packages', default => $base_repo_url, } case $facts['os']['family'] { 'Debian': { $_repo_path = 'apt' } default: { $_repo_path = 'yum' } } } else { $_repo_url = $base_repo_url ? { undef => 'https://packages.elastic.co/elasticsearch', default => $base_repo_url, } case $facts['os']['family'] { 'Debian': { $_repo_path = 'debian' } default: { $_repo_path = 'centos' } } } $base_url = "${_repo_url}/${version_prefix}${version}${version_suffix}/${_repo_path}" $key_id='46095ACC8548582C1A2699A9D27D666CD88E42B4' $key_source='https://artifacts.elastic.co/GPG-KEY-elasticsearch' $description='Elastic package repository.' - case $::osfamily { + case $facts['os']['family'] { 'Debian': { include apt apt::source { 'elastic': ensure => 'present', comment => $description, location => $base_url, release => 'stable', repos => 'main', key => { 'id' => $key_id, 'source' => $key_source, }, include => { 'deb' => true, 'src' => false, }, pin => $priority, } } 'RedHat', 'Linux': { yumrepo { 'elastic': descr => $description, baseurl => $base_url, gpgcheck => 1, gpgkey => $key_source, enabled => 1, proxy => $proxy, priority => $priority, } ~> exec { 'elastic_yumrepo_yum_clean': command => 'yum clean metadata expire-cache --disablerepo="*" --enablerepo="elastic"', refreshonly => true, returns => [0, 1], - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], + path => ['/bin', '/usr/bin', '/usr/local/bin'], cwd => '/', } } 'Suse': { # Older versions of SLES do not ship with rpmkeys - if $::operatingsystem == 'SLES' and versioncmp($::operatingsystemmajrelease, '11') <= 0 { + if $facts['os']['name'] == 'SLES' and versioncmp($facts['os']['release']['major'], '11') <= 0 { $_import_cmd = "rpm --import ${key_source}" } else { $_import_cmd = "rpmkeys --import ${key_source}" } exec { 'elastic_suse_import_gpg': command => $_import_cmd, unless => "test $(rpm -qa gpg-pubkey | grep -i 'D88E42B4' | wc -l) -eq 1", notify => Zypprepo['elastic'], - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], + path => ['/bin', '/usr/bin', '/usr/local/bin'], cwd => '/', } zypprepo { 'elastic': baseurl => $base_url, enabled => 1, autorefresh => 1, name => 'elastic', gpgcheck => 1, gpgkey => $key_source, type => 'yum', priority => $priority, } ~> exec { 'elastic_zypper_refresh_elastic': command => 'zypper refresh elastic', refreshonly => true, - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], + path => ['/bin', '/usr/bin', '/usr/local/bin'], cwd => '/', } } default: { - fail("\"${module_name}\" provides no repository information for OSfamily \"${::osfamily}\"") + fail("\"${module_name}\" provides no repository information for OSfamily \"${facts['os']['family']}\"") } } } diff --git a/metadata.json b/metadata.json index ec7d793..2259e44 100644 --- a/metadata.json +++ b/metadata.json @@ -1,74 +1,66 @@ { "name": "elastic-elastic_stack", "version": "7.0.0", "author": "toby@jarpy.net", "summary": "Helpers for installing and configuring components of the Elastic Stack.", "license": "Apache-2.0", "source": "https://github.com/elastic/puppet-elastic-stack", "project_page": "https://github.com/elastic/puppet-elastic-stack", "issues_url": "https://github.com/elastic/puppet-elastic-stack/issues", "dependencies": [ { "name": "puppetlabs-stdlib", "version_requirement": ">= 4.13.1 < 7.0.0" }, { "name": "puppetlabs/apt", "version_requirement": ">= 2.0.0 < 8.0.0" }, { "name": "puppet/yum", "version_requirement": ">= 0.9.6 < 5.0.0" }, { "name": "puppetlabs/yumrepo_core", "version_requirement": ">= 1.0.0 < 2.0.0" } ], "operatingsystem_support": [ { "operatingsystem": "Debian", "operatingsystemrelease": [ - "7", - "8", - "9" ] }, { "operatingsystem": "OpenSuSE", "operatingsystemrelease": [ - "42.2" ] }, { "operatingsystem": "RedHat", "operatingsystemrelease": [ - "6.0", "7.0" ] }, { "operatingsystem": "SLES", "operatingsystemrelease": [ - "12.1", - "12.2" + "12" ] }, { "operatingsystem": "Ubuntu", "operatingsystemrelease": [ - "14.04", - "16.04" ] } ], "requirements": [ { "name": "puppet", - "version_requirement": ">= 4.10.0 < 7.0.0" + "version_requirement": ">= 6.1.0 < 8.0.0" } ], "pdk-version": "1.0.1", "template-url": "file:///opt/puppetlabs/pdk/share/cache/pdk-module-template.git", "template-ref": "heads/master-0-g5db7961" } diff --git a/spec/classes/repo_spec.rb b/spec/classes/repo_spec.rb index 409c4fd..c5a44ed 100644 --- a/spec/classes/repo_spec.rb +++ b/spec/classes/repo_spec.rb @@ -1,158 +1,160 @@ +# frozen_string_literal: true + require 'spec_helper' def url(format, version) case version when %r{^2} - repo_type = (format == 'yum') ? 'centos' : 'debian' + repo_type = format == 'yum' ? 'centos' : 'debian' "https://packages.elastic.co/elasticsearch/#{version}/#{repo_type}" else "https://artifacts.elastic.co/packages/#{version}/#{format}" end end def declare_apt(version: '7.x', **params) params[:location] ||= url('apt', version) contain_apt__source('elastic').with(params) end def declare_yum(version: '7.x', **params) params[:baseurl] ||= url('yum', version) contain_yumrepo('elastic').with(params) end def declare_zypper(version: '7.x', **params) params[:baseurl] ||= url('yum', version) contain_zypprepo('elastic').with(params) end describe 'elastic_stack::repo', type: 'class' do default_params = {} rpm_key_cmd = 'rpmkeys --import https://artifacts.elastic.co/GPG-KEY-elasticsearch' on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) { facts } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt } when 'RedHat' it { is_expected.to declare_yum } when 'Suse' it { is_expected.to declare_zypper } it { is_expected.to contain_exec('elastic_suse_import_gpg').with(command: rpm_key_cmd) } it { is_expected.to contain_exec('elastic_zypper_refresh_elastic').with(command: 'zypper refresh elastic') } end - context 'with "version => 2"' do + context 'with "version => 2"' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(version: 2) } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(version: '2.x') } when 'RedHat' it { is_expected.to declare_yum(version: '2.x') } when 'Suse' it { is_expected.to declare_zypper(version: '2.x') } end end - context 'with "version => 5"' do + context 'with "version => 5"' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(version: 5) } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(version: '5.x') } when 'RedHat' it { is_expected.to declare_yum(version: '5.x') } when 'Suse' it { is_expected.to declare_zypper(version: '5.x') } end end - context 'with "version => 6"' do + context 'with "version => 6"' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(version: 6) } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(version: '6.x') } when 'RedHat' it { is_expected.to declare_yum(version: '6.x') } when 'Suse' it { is_expected.to declare_zypper(version: '6.x') } end end - context 'with "priority => 99"' do + context 'with "priority => 99"' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(priority: 99) } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(pin: 99) } when 'RedHat' it { is_expected.to declare_yum(priority: 99) } when 'Suse' it { is_expected.to declare_zypper(priority: 99) } end end - context 'with "prerelease => true"' do + context 'with "prerelease => true"' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(prerelease: true) } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(version: '7.x-prerelease') } when 'RedHat' it { is_expected.to declare_yum(version: '7.x-prerelease') } when 'Suse' it { is_expected.to declare_zypper(version: '7.x-prerelease') } end end - context 'with "oss => true"' do + context 'with "oss => true"' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(oss: true) } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(version: 'oss-7.x') } when 'RedHat' it { is_expected.to declare_yum(version: 'oss-7.x') } when 'Suse' it { is_expected.to declare_zypper(version: 'oss-7.x') } end end - context 'with "oss and prerelease => true"' do + context 'with "oss and prerelease => true"' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(oss: true, prerelease: true) } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(version: 'oss-7.x-prerelease') } when 'RedHat' it { is_expected.to declare_yum(version: 'oss-7.x-prerelease') } when 'Suse' it { is_expected.to declare_zypper(version: 'oss-7.x-prerelease') } end end - context 'with base_repo_url parameter' do + context 'with base_repo_url parameter' do # rubocop:disable RSpec/EmptyExampleGroup let(:params) { default_params.merge(base_repo_url: 'https://mymirror.example.org/elastic-artifacts/packages') } case facts[:os]['family'] when 'Debian' it { is_expected.to declare_apt(location: 'https://mymirror.example.org/elastic-artifacts/packages/7.x/apt') } when 'RedHat' it { is_expected.to declare_yum(baseurl: 'https://mymirror.example.org/elastic-artifacts/packages/7.x/yum') } when 'Suse' it { is_expected.to declare_zypper(baseurl: 'https://mymirror.example.org/elastic-artifacts/packages/7.x/yum') } end end context 'with proxy parameter' do let(:params) { default_params.merge(proxy: 'http://proxy.com:8080') } it { is_expected.to declare_yum(proxy: 'http://proxy.com:8080') } if facts[:os]['family'] == 'RedHat' end end end end diff --git a/spec/default_facts.yml b/spec/default_facts.yml deleted file mode 100644 index 3248be5..0000000 --- a/spec/default_facts.yml +++ /dev/null @@ -1,8 +0,0 @@ -# Use default_module_facts.yml for module specific facts. -# -# Facts specified here will override the values provided by rspec-puppet-facts. ---- -concat_basedir: "/tmp" -ipaddress: "172.16.254.254" -is_pe: false -macaddress: "AA:AA:AA:AA:AA:AA" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 15266c2..4d617f3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,23 +1,17 @@ -require 'puppetlabs_spec_helper/module_spec_helper' -require 'rspec-puppet-facts' -include RspecPuppetFacts +# frozen_string_literal: true -default_facts = { - puppetversion: Puppet.version, - facterversion: Facter.version, -} +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -default_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')) -default_module_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')) +# puppetlabs_spec_helper will set up coverage if the env variable is set. +# We want to do this if lib exists and it hasn't been explicitly set. +ENV['COVERAGE'] ||= 'yes' if Dir.exist?(File.expand_path('../lib', __dir__)) -if File.exist?(default_facts_path) && File.readable?(default_facts_path) - default_facts.merge!(YAML.safe_load(File.read(default_facts_path))) -end - -if File.exist?(default_module_facts_path) && File.readable?(default_module_facts_path) - default_facts.merge!(YAML.safe_load(File.read(default_module_facts_path))) -end +require 'voxpupuli/test/spec_helper' -RSpec.configure do |c| - c.default_facts = default_facts +if File.exist?(File.join(__dir__, 'default_module_facts.yml')) + facts = YAML.safe_load(File.read(File.join(__dir__, 'default_module_facts.yml'))) + facts&.each do |name, value| + add_custom_fact name.to_sym, value + end end