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/.fixtures.yml b/.fixtures.yml index 67f196a..4a53781 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,6 +1,3 @@ fixtures: repositories: - "augeasproviders_core": - repo: "git://github.com/hercules-team/augeasproviders_core.git" - symlinks: - augeasproviders_puppet: "#{source_dir}" + "augeasproviders_core": "https://github.com/voxpupuli/puppet-augeasproviders_core.git" diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..6aaa603 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,254 @@ +# 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_GEM_VERSION="~> 6.1.0" +``` + +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_PUPPET_COLLECTION=puppet7 BEAKER_setfile=debian11-64 bundle exec rake beaker +``` + +You can replace the string `debian11` with any common operating system. +The following strings are known to work: + +* ubuntu2004 +* ubuntu2204 +* debian11 +* centos7 +* centos8 +* centos9 +* almalinux8 +* almalinux9 +* fedora36 + +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/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..318d583 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +--- +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +name: CI + +on: + pull_request: {} + push: + branches: + - main + - master + +concurrency: + group: ${{ github.ref_name }} + cancel-in-progress: true + +jobs: + puppet: + name: Puppet + uses: voxpupuli/gha-puppet/.github/workflows/basic.yml@v2 + with: + additional_packages: 'libaugeas-dev augeas-tools' + rubocop: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..55324aa --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,22 @@ +--- +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +name: Release + +on: + push: + tags: + - '*' + +jobs: + release: + name: Release + uses: voxpupuli/gha-puppet/.github/workflows/release.yml@v2 + with: + allowed_owner: 'voxpupuli' + secrets: + # Configure secrets here: + # https://docs.github.com/en/actions/security-guides/encrypted-secrets + username: ${{ secrets.PUPPET_FORGE_USERNAME }} + api_key: ${{ secrets.PUPPET_FORGE_API_KEY }} diff --git a/.gitignore b/.gitignore index 94145ab..84fd904 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,23 @@ -pkg -coverage -.bundle/ -.librarian/ -.tmp/ -modules/ -_site/ -spec/fixtures/manifests -spec/fixtures/modules -yardoc/ -.yardoc/ +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -## Ruby -.rvmrc* -.rbenv* -.ruby-* - -## MAC OS -.DS_Store - -## TEXTMATE -*.tmproj -tmtags - -## EMACS -*~ -\#* -.\#* - -## VIM -*.swp -tags +/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..f46ee02 --- /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: '7.3.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/.pmtignore b/.pmtignore new file mode 100644 index 0000000..10b9830 --- /dev/null +++ b/.pmtignore @@ -0,0 +1,38 @@ +# 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/ +/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 +/HISTORY.md 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 new file mode 100644 index 0000000..f634583 --- /dev/null +++ b/.rspec @@ -0,0 +1,5 @@ +# 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 new file mode 100644 index 0000000..fded90c --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,7 @@ +--- +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +inherit_from: .rubocop_todo.yml +inherit_gem: + voxpupuli-test: rubocop.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..4c0452a --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,34 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2023-08-17 21:29:56 UTC using RuboCop version 1.50.2. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'lib/puppet/provider/puppet_auth/augeas.rb' + +# Offense count: 2 +# This cop supports unsafe autocorrection (--autocorrect-all). +RSpec/BeEq: + Exclude: + - 'spec/unit/puppet/provider/puppet_auth/augeas_spec.rb' + +# Offense count: 2 +# Configuration parameters: AssignmentOnly. +RSpec/InstanceVariable: + Exclude: + - 'spec/unit/puppet/provider/puppet_auth/augeas_spec.rb' + +# Offense count: 2 +# Configuration parameters: AllowedChars. +# AllowedChars: © +Style/AsciiComments: + Exclude: + - 'lib/puppet/provider/puppet_auth/augeas.rb' + - 'lib/puppet/type/puppet_auth.rb' diff --git a/.sync.yml b/.sync.yml index 8480ccc..20846fc 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,3 +1,15 @@ --- -.travis.yml: - forge_password: "YVzquxfEQFySEKM63ipGUkaTZM+ue0LsDHsvUm66uYSsUpjeJEAuFWqRRljhAleJLWUqbXUvXJYr/kilOvDJvsHZXZb9MPA9/gfw08qWYcOgBVWrYTm/KF8N43mZuxbIzw1ZtNyoxuyNrLaqMfnps29e6G+zZIoOluFREsOqtMM=" +.github/workflows/ci.yml: + additional_packages: libaugeas-dev augeas-tools + rubocop: false +Gemfile: + optional: + ':test': + - gem: ruby-augeas +spec/spec_helper.rb: + spec_overrides: + - "require 'augeas_spec'" + - "# augeasproviders: setting $LOAD_PATH to work around broken type autoloading" + - "$LOAD_PATH.unshift(File.join(__dir__, 'fixtures/modules/augeasproviders_core/lib'))" +spec/spec_helper_acceptance.rb: + unmanaged: false diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0b7a5d9..0000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -language: ruby -sudo: required -rvm: - - 2.4.4 -notifications: - email: - - raphael.pinson@camptocamp.com -env: -# base env - # Test latest Puppet 5 version - - PUPPET=5.5 RUBY_AUGEAS=0.5 FORGE_PUBLISH=true - # Test latest Puppet version - - PUPPET=6 RUBY_AUGEAS=0.5 - - -matrix: - fast_finish: true - -install: - - "travis_retry ./.travis.sh" -script: - - AUGEAS_LENS_LIB=lib/augeas/lenses:augeas/lenses bundle exec rake - # Do not include the augeas/ directory in the deployed module - - rm -rf augeas/ -deploy: - provider: puppetforge - user: herculesteam - password: - secure: "YVzquxfEQFySEKM63ipGUkaTZM+ue0LsDHsvUm66uYSsUpjeJEAuFWqRRljhAleJLWUqbXUvXJYr/kilOvDJvsHZXZb9MPA9/gfw08qWYcOgBVWrYTm/KF8N43mZuxbIzw1ZtNyoxuyNrLaqMfnps29e6G+zZIoOluFREsOqtMM=" - on: - tags: true - # all_branches is required to use tags - all_branches: true - # Only publish if our main Ruby target builds - rvm: 2.4.4 - condition: "$FORGE_PUBLISH = true" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8dd82d6 --- /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_GEM_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 7c75c8b..b61ba2a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,50 +1,33 @@ -source 'https://rubygems.org' +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -if ENV.key?('PUPPET') - puppetversion = "~> #{ENV['PUPPET']}" -else - puppetversion = ['>= 2.7'] +source ENV['GEM_SOURCE'] || 'https://rubygems.org' + +group :test do + gem 'voxpupuli-test', '~> 7.0', :require => false + gem 'coveralls', :require => false + gem 'simplecov-console', :require => false + gem 'puppet_metadata', '~> 3.5', :require => false + gem 'ruby-augeas', :require => false +end + +group :development do + gem 'guard-rake', :require => false + gem 'overcommit', '>= 0.39.1', :require => false end -gem 'puppet', puppetversion - -if ENV.key?('RUBY_AUGEAS') - if ENV['RUBY_AUGEAS'] == '0.3.0' - # pre-0.4.1 versions aren't available on rubygems - rbaugversion = {:git => 'git://github.com/domcleal/ruby-augeas.git', :branch => '0.3.0-gem'} - else - rbaugversion = "~> #{ENV['RUBY_AUGEAS']}" - end -else - rbaugversion = ['~> 0.3'] + +group :system_tests do + gem 'voxpupuli-acceptance', '~> 3.0', :require => false end -gem 'ruby-augeas', rbaugversion - -group :development, :unit_tests do - gem 'rake', ' < 11.0', :require => false if RUBY_VERSION =~ /^1\.8/ - gem 'rspec', '< 3.2', :require => false if RUBY_VERSION =~ /^1\.8/ - gem 'json', '< 2.0', :require => false if RUBY_VERSION =~ /^1\.[89]/ - gem 'json_pure', '< 2.0', :require => false if RUBY_VERSION =~ /^1\.[89]/ - gem 'rspec-puppet', :require => false - gem 'puppetlabs_spec_helper', :require => false - gem 'metadata-json-lint', :require => false - gem 'puppet-lint', :require => false - gem 'puppet-lint-unquoted_string-check', :require => false - gem 'puppet-lint-empty_string-check', :require => false - gem 'puppet-lint-spaceship_operator_without_tag-check', :require => false - gem 'puppet-lint-variable_contains_upcase', :require => false - gem 'puppet-lint-absolute_classname-check', :require => false - gem 'puppet-lint-undef_in_function-check', :require => false - gem 'puppet-lint-leading_zero-check', :require => false - gem 'puppet-lint-trailing_comma-check', :require => false - gem 'puppet-lint-file_ensure-check', :require => false - gem 'puppet-lint-version_comparison-check', :require => false - gem 'rspec-puppet-facts', :require => false - - gem 'coveralls', :require => false unless RUBY_VERSION =~ /^1\.8/ - gem 'simplecov', '~> 0.7.0', :require => false - gem 'yard', :require => false - gem 'redcarpet', '~> 2.0', :require => false - - # mime-types-data requires Ruby version >= 2.0 - gem 'mime-types', '2.6.2' if RUBY_VERSION =~ /^1\.9/ + +group :release do + gem 'voxpupuli-release', '~> 3.0', :require => false end + +gem 'rake', :require => false +gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] + +puppetversion = ENV['PUPPET_GEM_VERSION'] || '~> 7.24' +gem 'puppet', puppetversion, :require => false, :groups => [:test] + +# vim: syntax=ruby diff --git a/Rakefile b/Rakefile index 8490143..569a16d 100644 --- a/Rakefile +++ b/Rakefile @@ -1,30 +1,44 @@ -require 'rubygems' -require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-syntax/tasks/puppet-syntax' -require 'puppet-lint/tasks/puppet-lint' -require 'yard' +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -exclude_paths = [ - "pkg/**/*", - "vendor/**/*", - "spec/**/*", -] - -task :default => [:spec, :yard, :syntax, :lint] +# 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 -desc "Run acceptance tests" -RSpec::Core::RakeTask.new(:acceptance) do |t| - t.pattern = 'spec/acceptance' +# load optional tasks for acceptance +# only available if gem group releases is installed +begin + require 'voxpupuli/acceptance/rake' +rescue LoadError end -YARD::Rake::YardocTask.new do |t| - t.options = [] +# load optional tasks for releases +# only available if gem group releases is installed +begin + require 'voxpupuli/release/rake_tasks' +rescue LoadError + # voxpupuli-release not present +else + GCGConfig.user = 'voxpupuli' + GCGConfig.project = 'puppet-augeasproviders_puppet' end -# Disable puppet-lint checks -PuppetLint.configuration.send("disable_80chars") -PuppetLint.configuration.send("disable_class_inherits_from_params_class") +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 -# Ignore files outside this module -PuppetLint.configuration.ignore_paths = exclude_paths -PuppetSyntax.exclude_paths = exclude_paths +# vim: syntax=ruby diff --git a/lib/puppet/provider/puppet_auth/augeas.rb b/lib/puppet/provider/puppet_auth/augeas.rb index e3c80fd..428f159 100644 --- a/lib/puppet/provider/puppet_auth/augeas.rb +++ b/lib/puppet/provider/puppet_auth/augeas.rb @@ -1,25 +1,27 @@ -# coding: utf-8 +# frozen_string_literal: true + # Alternative Augeas-based providers for Puppet # # Copyright (c) 2012 Raphaël Pinson # Licensed under the Apache License, Version 2.0 -raise("Missing augeasproviders_core dependency") if Puppet::Type.type(:augeasprovider).nil? -Puppet::Type.type(:puppet_auth).provide(:augeas, :parent => Puppet::Type.type(:augeasprovider).provider(:default)) do +raise('Missing augeasproviders_core dependency') if Puppet::Type.type(:augeasprovider).nil? + +Puppet::Type.type(:puppet_auth).provide(:augeas, parent: Puppet::Type.type(:augeasprovider).provider(:default)) do desc "Uses Augeas API to update a rule in Puppet's auth.conf." INS_ALIASES = { - "first allow" => "path[allow][1]", - "last allow" => "path[allow][last()]", - "first deny" => "path[count(allow)=0][1]", - "last deny" => "path[count(allow)=0][last()]", - } + 'first allow' => 'path[allow][1]', + 'last allow' => 'path[allow][last()]', + 'first deny' => 'path[count(allow)=0][1]', + 'last deny' => 'path[count(allow)=0][last()]', + }.freeze default_file { File.join(Puppet[:confdir], 'auth.conf') } lens { 'Puppet_Auth.lns' } - confine :feature => :augeas + confine feature: :augeas resource_path do |resource| path = resource[:path] @@ -29,7 +31,7 @@ def self.instances resources = [] augopen do |aug| - settings = aug.match("$target/path") + settings = aug.match('$target/path') settings.each do |node| # Set $resource for getters @@ -42,12 +44,12 @@ def self.instances allow = attr_aug_reader_allow(aug) allow_ip = attr_aug_reader_allow_ip(aug) authenticated = attr_aug_reader_authenticated(aug) - name = (path_regex == :false) ? "Auth rule for #{path}" : "Auth rule matching #{path}" - entry = {:ensure => :present, :name => name, - :path => path, :path_regex => path_regex, - :environments => environments, :methods => methods, - :allow => allow, :allow_ip => allow_ip, - :authenticated => authenticated} + name = path_regex == :false ? "Auth rule for #{path}" : "Auth rule matching #{path}" + entry = { ensure: :present, name: name, + path: path, path_regex: path_regex, + environments: environments, methods: methods, + allow: allow, allow_ip: allow_ip, + authenticated: authenticated } resources << new(entry) if entry[:path] end end @@ -65,21 +67,17 @@ def create allow_ip = resource[:allow_ip] authenticated = resource[:authenticated] augopen! do |aug| - if before or after + if before || after expr = before || after - if INS_ALIASES.has_key?(expr) - expr = INS_ALIASES[expr] - end - aug.insert("$target/#{expr}", "path", before ? true : false) + expr = INS_ALIASES[expr] if INS_ALIASES.key?(expr) + aug.insert("$target/#{expr}", 'path', before ? true : false) aug.set("$target/path[.='']", apath) end aug.set(resource_path, apath) # Refresh $resource setvars(aug) - if apath_regex == :true - aug.set('$resource/operator', "~") - end + aug.set('$resource/operator', '~') if apath_regex == :true attr_aug_writer_environments(aug, environments) attr_aug_writer_methods(aug, methods) attr_aug_writer_allow(aug, allow) @@ -89,33 +87,28 @@ def create end attr_aug_accessor(:environments, - :label => 'environment', - :type => :array, - :sublabel => :seq, - :purge_ident => true - ) + label: 'environment', + type: :array, + sublabel: :seq, + purge_ident: true) attr_aug_accessor(:methods, - :label => 'method', - :type => :array, - :sublabel => :seq, - :purge_ident => true - ) + label: 'method', + type: :array, + sublabel: :seq, + purge_ident: true) attr_aug_accessor(:allow, - :type => :array, - :sublabel => :seq, - :purge_ident => true - ) + type: :array, + sublabel: :seq, + purge_ident: true) attr_aug_accessor(:allow_ip, - :type => :array, - :sublabel => :seq, - :purge_ident => true - ) + type: :array, + sublabel: :seq, + purge_ident: true) attr_aug_accessor(:authenticated, - :label => 'auth', - :purge_ident => true - ) + label: 'auth', + purge_ident: true) end diff --git a/lib/puppet/type/puppet_auth.rb b/lib/puppet/type/puppet_auth.rb index db9d1ab..f7a041e 100644 --- a/lib/puppet/type/puppet_auth.rb +++ b/lib/puppet/type/puppet_auth.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Manages settings in Puppet's auth.conf file # # Copyright (c) 2012 Raphaël Pinson @@ -10,26 +12,26 @@ def munge_boolean(value) case value - when true, "true", :true + when true, 'true', :true :true - when false, "false", :false + when false, 'false', :false :false else - fail("munge_boolean only takes booleans") + raise('munge_boolean only takes booleans') end end newparam(:name) do - desc "The name of the resource." + desc 'The name of the resource.' isnamevar end newparam(:path) do - desc "The path for the auth rule." + desc 'The path for the auth rule.' end - newparam(:path_regex, :boolean => true) do - desc "Whether the path is specified as a regex." + newparam(:path_regex, boolean: true) do + desc 'Whether the path is specified as a regex.' newvalues(:true, :false) @@ -60,11 +62,11 @@ def munge_boolean(value) - `last deny`, mapping to path[count(allow)=0][last()]`" end - newproperty(:environments, :array_matching => :all) do - desc "The list of environments the rule applies to." + newproperty(:environments, array_matching: :all) do + desc 'The list of environments the rule applies to.' end - newproperty(:methods, :array_matching => :all) do + newproperty(:methods, array_matching: :all) do desc "The list of methods the rule applies to. Possible values are: - find; @@ -73,17 +75,17 @@ def munge_boolean(value) - destroy." end - newproperty(:allow, :array_matching => :all) do + newproperty(:allow, array_matching: :all) do desc "The list of hosts allowed for this rule, specified by hostname or cername. Regexes are allowed, as well as the special value `*`." validate do |val| - raise ArgumentError, "The allow parameter cannot be undef" if val == :undef + raise ArgumentError, 'The allow parameter cannot be undef' if val == :undef end end - newproperty(:allow_ip, :array_matching => :all) do + newproperty(:allow_ip, array_matching: :all) do desc "The list of IPs allowed for this rule. Requires Puppet 3.0.0 or greater." end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b5aa0c4..d34b248 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,51 +1,26 @@ -require 'pathname' -dir = Pathname.new(__FILE__).parent -$LOAD_PATH.unshift(dir, File.join(dir, 'fixtures/modules/augeasproviders_core/spec/lib'), File.join(dir, '..', 'lib')) +# frozen_string_literal: true -require 'rubygems' +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ -require 'simplecov' -unless RUBY_VERSION =~ /^1\.8/ - require 'coveralls' - SimpleCov.formatter = Coveralls::SimpleCov::Formatter -end -SimpleCov.start do - add_group "Puppet Types", "/lib/puppet/type/" - add_group "Puppet Providers", "/lib/puppet/provider/" +# 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__)) + +require 'voxpupuli/test/spec_helper' - add_filter "/spec/fixtures/" - add_filter "/spec/unit/" - add_filter "/spec/support/" +add_mocked_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 -require 'puppetlabs_spec_helper/module_spec_helper' require 'augeas_spec' -Puppet[:modulepath] = File.join(dir, 'fixtures', 'modules') - -# There's no real need to make this version dependent, but it helps find -# regressions in Puppet -# -# 1. Workaround for issue #16277 where default settings aren't initialised from -# a spec and so the libdir is never initialised (3.0.x) -# 2. Workaround for 2.7.20 that now only loads types for the current node -# environment (#13858) so Puppet[:modulepath] seems to get ignored -# 3. Workaround for 3.5 where context hasn't been configured yet, -# ticket https://tickets.puppetlabs.com/browse/MODULES-823 -# -ver = Gem::Version.new(Puppet.version.split('-').first) -if ver >= Gem::Version.new("2.7.20") - puts "augeasproviders: setting $LOAD_PATH to work around broken type autoloading" - Puppet.initialize_settings - $LOAD_PATH.unshift( - dir, - File.join(dir, 'fixtures/modules/augeasproviders_core/spec/lib'), - File.join(dir, 'fixtures/modules/augeasproviders_core/lib') - ) - - - $LOAD_PATH.unshift(File.join(dir, '..', 'lib')) -end +# augeasproviders: setting $LOAD_PATH to work around broken type autoloading -# Load all shared contexts and shared examples -Dir["#{dir}/support/**/*.rb"].sort.each {|f| require f} +$LOAD_PATH.unshift(File.join(__dir__, 'fixtures/modules/augeasproviders_core/lib')) +Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f } diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb new file mode 100644 index 0000000..2681792 --- /dev/null +++ b/spec/spec_helper_acceptance.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Managed by modulesync - DO NOT EDIT +# https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ + +require 'voxpupuli/acceptance/spec_helper_acceptance' + +configure_beaker(modules: :metadata) + +Dir['./spec/support/acceptance/**/*.rb'].sort.each { |f| require f } diff --git a/spec/unit/puppet/provider/puppet_auth/augeas_spec.rb b/spec/unit/puppet/provider/puppet_auth/augeas_spec.rb index 417ea4a..223832f 100644 --- a/spec/unit/puppet/provider/puppet_auth/augeas_spec.rb +++ b/spec/unit/puppet/provider/puppet_auth/augeas_spec.rb @@ -1,4 +1,4 @@ -#!/usr/bin/env rspec +# frozen_string_literal: true require 'spec_helper' @@ -8,167 +8,167 @@ def valid_lens? Puppet::Util::Package.versioncmp(Puppet::Type.type(:puppet_auth).provider(:augeas).aug_version, '0.10.0') > 0 end -describe provider_class, :if => valid_lens? do - before :each do - FileTest.stubs(:exist?).returns false - FileTest.stubs(:exist?).with('/etc/puppet/auth.conf').returns true +describe provider_class, if: valid_lens? do + before do + allow(FileTest).to receive(:exist?).and_return(false) + allow(FileTest).to receive(:exist?).with('/etc/puppet/auth.conf').and_return(true) end - context "with empty file" do - let(:tmptarget) { aug_fixture("empty") } + context 'with empty file' do + let(:tmptarget) { aug_fixture('empty') } let(:target) { tmptarget.path } - it "should create simple new entry" do + it 'creates simple new entry' do apply!(Puppet::Type.type(:puppet_auth).new( - :name => "/facts rule", - :path => "/facts", - :authenticated => "any", - :target => target, - :provider => "augeas", - :ensure => "present" - )) - - aug_open(target, "Puppet_Auth.lns") do |aug| - expect(aug.match("path").size).to eq(1) - expect(aug.get("path")).to eq("/facts") - expect(aug.match("path/operator").size).to eq(0) - expect(aug.get("path/auth")).to eq("any") + name: '/facts rule', + path: '/facts', + authenticated: 'any', + target: target, + provider: 'augeas', + ensure: 'present' + )) + + aug_open(target, 'Puppet_Auth.lns') do |aug| + expect(aug.match('path').size).to eq(1) + expect(aug.get('path')).to eq('/facts') + expect(aug.match('path/operator').size).to eq(0) + expect(aug.get('path/auth')).to eq('any') end end end - context "with full file" do - let(:tmptarget) { aug_fixture("full") } + context 'with full file' do + let(:tmptarget) { aug_fixture('full') } let(:target) { tmptarget.path } - it "should list instances" do - provider_class.stubs(:target).returns(target) - inst = provider_class.instances.map { |p| + it 'lists instances' do + allow(provider_class).to receive(:target).and_return(target) + inst = provider_class.instances.map do |p| { - :name => p.get(:name), - :ensure => p.get(:ensure), - :path => p.get(:path), - :path_regex => p.get(:path_regex), - :environments => p.get(:environments), - :methods => p.get(:methods), - :allow => p.get(:allow), - :allow_ip => p.get(:allow_ip), - :authenticated => p.get(:authenticated), + name: p.get(:name), + ensure: p.get(:ensure), + path: p.get(:path), + path_regex: p.get(:path_regex), + environments: p.get(:environments), + methods: p.get(:methods), + allow: p.get(:allow), + allow_ip: p.get(:allow_ip), + authenticated: p.get(:authenticated), } - } + end expect(inst.size).to eq(9) - expect(inst[0]).to eq({:path_regex=>:true, :methods=>["find"], :environments=>[], :authenticated=>:absent, :allow=>["$1"], :allow_ip=>[], :ensure=>:present, :name=>"Auth rule matching ^/catalog/([^/]+)$", :path=>"^/catalog/([^/]+)$"}) - expect(inst[2]).to eq({:path_regex=>:false, :methods=>["find"], :environments=>[], :authenticated=>:absent, :allow=>["*"], :allow_ip=>[], :ensure=>:present, :name=>"Auth rule for /certificate_revocation_list/ca", :path=>"/certificate_revocation_list/ca"}) - expect(inst[7]).to eq({:path_regex=>:false, :methods=>["find", "save"], :environments=>[], :authenticated=>"any", :allow=>["*"], :allow_ip=>[], :ensure=>:present, :name=>"Auth rule for /certificate_request", :path=>"/certificate_request"}) + expect(inst[0]).to eq({ path_regex: :true, methods: ['find'], environments: [], authenticated: :absent, allow: ['$1'], allow_ip: [], ensure: :present, name: 'Auth rule matching ^/catalog/([^/]+)$', path: '^/catalog/([^/]+)$' }) + expect(inst[2]).to eq({ path_regex: :false, methods: ['find'], environments: [], authenticated: :absent, allow: ['*'], allow_ip: [], ensure: :present, name: 'Auth rule for /certificate_revocation_list/ca', path: '/certificate_revocation_list/ca' }) + expect(inst[7]).to eq({ path_regex: :false, methods: %w[find save], environments: [], authenticated: 'any', allow: ['*'], allow_ip: [], ensure: :present, name: 'Auth rule for /certificate_request', path: '/certificate_request' }) end - describe "when creating settings" do - it "should create a simple new entry" do + describe 'when creating settings' do + it 'creates a simple new entry' do apply!(Puppet::Type.type(:puppet_auth).new( - :name => "/facts before first deny", - :path => "/facts", - :environments => ["staging", "stable"], - :methods => "find", - :authenticated => "any", - :ins_before => "first deny", - :target => target, - :provider => "augeas", - :ensure => "present" - )) - - aug_open(target, "Puppet_Auth.lns") do |aug| - expect(aug.get("path[last()-1]")).to eq("/facts") - expect(aug.get("path[.='/facts']/environment/1")).to eq("staging") + name: '/facts before first deny', + path: '/facts', + environments: %w[staging stable], + methods: 'find', + authenticated: 'any', + ins_before: 'first deny', + target: target, + provider: 'augeas', + ensure: 'present' + )) + + aug_open(target, 'Puppet_Auth.lns') do |aug| + expect(aug.get('path[last()-1]')).to eq('/facts') + expect(aug.get("path[.='/facts']/environment/1")).to eq('staging') expect(aug.match("path[.='/facts']/method/*").size).to eq(1) - expect(aug.get("path[.='/facts']/method/1")).to eq("find") + expect(aug.get("path[.='/facts']/method/1")).to eq('find') end end - it "should create an entry with a regex path" do + it 'creates an entry with a regex path' do apply!(Puppet::Type.type(:puppet_auth).new( - :name => "Matching ^/foo/([^/]+)$", - :path => "^/foo/([^/]+)$", - :path_regex => "true", - :authenticated => "any", - :target => target, - :provider => "augeas", - :ensure => "present" - )) - - aug_open(target, "Puppet_Auth.lns") do |aug| + name: 'Matching ^/foo/([^/]+)$', + path: '^/foo/([^/]+)$', + path_regex: 'true', + authenticated: 'any', + target: target, + provider: 'augeas', + ensure: 'present' + )) + + aug_open(target, 'Puppet_Auth.lns') do |aug| expect(aug.get("path[.='^/foo/([^/]+)$']/operator")).to eq('~') end end end - describe "when modifying settings" do - it "should modify the properties" do + describe 'when modifying settings' do + it 'modifies the properties' do apply!(Puppet::Type.type(:puppet_auth).new( - :name => "Apply /certificate/ to staging", - :path => "/certificate/", - :environments => "staging", - :authenticated => "on", - :allow => ["localhost.localdomain", "example.com"], - :allow_ip => "192.168.0.1/32", - :target => target, - :provider => "augeas", - :ensure => "present" - )) - - aug_open(target, "Puppet_Auth.lns") do |aug| - expect(aug.get("path[.='/certificate/']/environment/1")).to eq("staging") - expect(aug.get("path[.='/certificate/']/auth")).to eq("on") - expect(aug.get("path[.='/certificate/']/allow/1")).to eq("localhost.localdomain") - expect(aug.get("path[.='/certificate/']/allow/2")).to eq("example.com") - expect(aug.get("path[.='/certificate/']/allow_ip/1")).to eq("192.168.0.1/32") + name: 'Apply /certificate/ to staging', + path: '/certificate/', + environments: 'staging', + authenticated: 'on', + allow: ['localhost.localdomain', 'example.com'], + allow_ip: '192.168.0.1/32', + target: target, + provider: 'augeas', + ensure: 'present' + )) + + aug_open(target, 'Puppet_Auth.lns') do |aug| + expect(aug.get("path[.='/certificate/']/environment/1")).to eq('staging') + expect(aug.get("path[.='/certificate/']/auth")).to eq('on') + expect(aug.get("path[.='/certificate/']/allow/1")).to eq('localhost.localdomain') + expect(aug.get("path[.='/certificate/']/allow/2")).to eq('example.com') + expect(aug.get("path[.='/certificate/']/allow_ip/1")).to eq('192.168.0.1/32') end end - it "should remove the save method" do + it 'removes the save method' do apply!(Puppet::Type.type(:puppet_auth).new( - :name => "Remove save method from /certificate_request", - :path => "/certificate_request", - :methods => "find", - :target => target, - :provider => "augeas", - :ensure => "present" - )) - - aug_open(target, "Puppet_Auth.lns") do |aug| + name: 'Remove save method from /certificate_request', + path: '/certificate_request', + methods: 'find', + target: target, + provider: 'augeas', + ensure: 'present' + )) + + aug_open(target, 'Puppet_Auth.lns') do |aug| expect(aug.match("path[.='/certificate_request']/method").size).to eq(1) - expect(aug.get("path[.='/certificate_request']/method/1")).to eq("find") + expect(aug.get("path[.='/certificate_request']/method/1")).to eq('find') end end - it "should remove the entry" do + it 'removes the entry' do apply!(Puppet::Type.type(:puppet_auth).new( - :name => "Remove save method from /certificate_request", - :path => "/certificate_request", - :target => target, - :provider => "augeas", - :ensure => "absent" - )) - - aug_open(target, "Puppet_Auth.lns") do |aug| + name: 'Remove save method from /certificate_request', + path: '/certificate_request', + target: target, + provider: 'augeas', + ensure: 'absent' + )) + + aug_open(target, 'Puppet_Auth.lns') do |aug| expect(aug.match("path[.='/certificate_request']").size).to eq(0) end end end end - context "with broken file" do - let(:tmptarget) { aug_fixture("broken") } + context 'with broken file' do + let(:tmptarget) { aug_fixture('broken') } let(:target) { tmptarget.path } - it "should fail to load" do + it 'fails to load' do txn = apply(Puppet::Type.type(:puppet_auth).new( - :name => "Test broken", - :path => "/facts", - :target => target, - :provider => "augeas", - :ensure => "present" - )) + name: 'Test broken', + path: '/facts', + target: target, + provider: 'augeas', + ensure: 'present' + )) expect(txn.any_failed?).not_to eq(nil) expect(@logs.first.level).to eq(:err)