diff --git a/.fixtures.yml b/.fixtures.yml index 0cd1147..d62fb8b 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,10 +1,4 @@ fixtures: repositories: - stdlib: - repo: https://github.com/puppetlabs/puppetlabs-stdlib.git - ref: 4.1.0 - debconf: - repo: https://github.com/smoeding/puppet-debconf.git - ref: v1.0.0 - symlinks: - timezone: "#{source_dir}" + stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib" + debconf: "https://github.com/smoeding/puppet-debconf" diff --git a/.gitignore b/.gitignore index 5b9ccf1..e9b3cf4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,20 @@ -*.swp -.bundle/ -.vagrant -/coverage/ -Gemfile.lock -log/ pkg/ -spec/fixtures +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/.pmtignore b/.pmtignore index fb58957..4e6d54b 100644 --- a/.pmtignore +++ b/.pmtignore @@ -1,20 +1,21 @@ docs/ 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/ +Dockerfile diff --git a/.rspec b/.rspec index 6278ec5..8c18f1a 100644 --- a/.rspec +++ b/.rspec @@ -1,3 +1,2 @@ --format documentation --color ---tty diff --git a/.rspec_parallel b/.rspec_parallel new file mode 100644 index 0000000..e4d136b --- /dev/null +++ b/.rspec_parallel @@ -0,0 +1 @@ +--format progress diff --git a/.rubocop.yml b/.rubocop.yml index 0b9de9e..c2ebc88 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,517 +1,546 @@ require: rubocop-rspec AllCops: - TargetRubyVersion: 2.2 +# Puppet Server 5 defaults to jruby 1.7 so TargetRubyVersion must stay at 1.9 until we drop support for puppet 5 + TargetRubyVersion: 1.9 Include: - ./**/*.rb Exclude: - files/**/* - vendor/**/* - - Gemfile - - Rakefile - .vendor/**/* - pkg/**/* - spec/fixtures/**/* - Gemfile - Rakefile -Layout/ConditionPosition: - Enabled: true + - Guardfile + - Vagrantfile +Lint/ConditionPosition: + Enabled: True Lint/ElseLayout: - Enabled: true + Enabled: True Lint/UnreachableCode: - Enabled: true + Enabled: True Lint/UselessComparison: - Enabled: true + Enabled: True Lint/EnsureReturn: - Enabled: true + Enabled: True Lint/HandleExceptions: - Enabled: true + Enabled: True + +Lint/LiteralInCondition: + Enabled: True Lint/ShadowingOuterLocalVariable: - Enabled: true + Enabled: True Lint/LiteralInInterpolation: - Enabled: true + Enabled: True Style/HashSyntax: - Enabled: false + Enabled: True Style/RedundantReturn: - Enabled: true + Enabled: True + +Layout/EndOfLine: + Enabled: False Lint/AmbiguousOperator: - Enabled: true + Enabled: True Lint/AssignmentInCondition: - Enabled: true + Enabled: True Layout/SpaceBeforeComment: - Enabled: true + Enabled: True Style/AndOr: - Enabled: true + Enabled: True Style/RedundantSelf: - Enabled: true + Enabled: True + +Metrics/BlockLength: + Enabled: False # Method length is not necessarily an indicator of code quality Metrics/MethodLength: - Enabled: false + Enabled: False # Module length is not necessarily an indicator of code quality Metrics/ModuleLength: - Enabled: false + Enabled: False Style/WhileUntilModifier: - Enabled: true + Enabled: True Lint/AmbiguousRegexpLiteral: - Enabled: true + Enabled: True Security/Eval: - Enabled: true + Enabled: True -Layout/BlockAlignment: - Enabled: true +Lint/BlockAlignment: + Enabled: True -Layout/DefEndAlignment: - Enabled: true +Lint/DefEndAlignment: + Enabled: True -Layout/EndAlignment: - Enabled: true +Lint/EndAlignment: + Enabled: True Lint/DeprecatedClassMethods: - Enabled: true + Enabled: True Lint/Loop: - Enabled: true + Enabled: True Lint/ParenthesesAsGroupedExpression: - Enabled: true + Enabled: True Lint/RescueException: - Enabled: true + Enabled: True Lint/StringConversionInInterpolation: - Enabled: true + Enabled: True Lint/UnusedBlockArgument: - Enabled: true + Enabled: True Lint/UnusedMethodArgument: - Enabled: true + Enabled: True Lint/UselessAccessModifier: - Enabled: true + Enabled: True Lint/UselessAssignment: - Enabled: true + Enabled: True Lint/Void: - Enabled: true + Enabled: True Layout/AccessModifierIndentation: - Enabled: true + Enabled: True -Naming/AccessorMethodName: - Enabled: true +Style/AccessorMethodName: + Enabled: True Style/Alias: - Enabled: true + Enabled: True Layout/AlignArray: - Enabled: true + Enabled: True Layout/AlignHash: - Enabled: true + Enabled: True Layout/AlignParameters: - Enabled: true + Enabled: True Metrics/BlockNesting: - Enabled: true + Enabled: True Style/AsciiComments: - Enabled: true + Enabled: True Style/Attr: - Enabled: true + Enabled: True Style/BracesAroundHashParameters: - Enabled: true + Enabled: True Style/CaseEquality: - Enabled: true + Enabled: True Layout/CaseIndentation: - Enabled: true + Enabled: True Style/CharacterLiteral: - Enabled: true + Enabled: True -Naming/ClassAndModuleCamelCase: - Enabled: true +Style/ClassAndModuleCamelCase: + Enabled: True Style/ClassAndModuleChildren: - Enabled: false + Enabled: False Style/ClassCheck: - Enabled: true + Enabled: True # Class length is not necessarily an indicator of code quality Metrics/ClassLength: - Enabled: false + Enabled: False Style/ClassMethods: - Enabled: true + Enabled: True Style/ClassVars: - Enabled: true + Enabled: True Style/WhenThen: - Enabled: true + Enabled: True Style/WordArray: - Enabled: true + Enabled: True Style/UnneededPercentQ: - Enabled: true + Enabled: True Layout/Tab: - Enabled: true + Enabled: True Layout/SpaceBeforeSemicolon: - Enabled: true + Enabled: True Layout/TrailingBlankLines: - Enabled: true + Enabled: True Layout/SpaceInsideBlockBraces: - Enabled: true + Enabled: True + +Layout/SpaceInsideBrackets: + Enabled: True Layout/SpaceInsideHashLiteralBraces: - Enabled: true + Enabled: True Layout/SpaceInsideParens: - Enabled: true + Enabled: True Layout/LeadingCommentSpace: - Enabled: true + Enabled: True Layout/SpaceBeforeFirstArg: - Enabled: true + Enabled: True Layout/SpaceAfterColon: - Enabled: true + Enabled: True Layout/SpaceAfterComma: - Enabled: true + Enabled: True Layout/SpaceAfterMethodName: - Enabled: true + Enabled: True Layout/SpaceAfterNot: - Enabled: true + Enabled: True Layout/SpaceAfterSemicolon: - Enabled: true + Enabled: True Layout/SpaceAroundEqualsInParameterDefault: - Enabled: true + Enabled: True Layout/SpaceAroundOperators: - Enabled: true + Enabled: True Layout/SpaceBeforeBlockBraces: - Enabled: true + Enabled: True Layout/SpaceBeforeComma: - Enabled: true + Enabled: True Style/CollectionMethods: - Enabled: true + Enabled: True Layout/CommentIndentation: - Enabled: true + Enabled: True Style/ColonMethodCall: - Enabled: true + Enabled: True Style/CommentAnnotation: - Enabled: true + Enabled: True # 'Complexity' is very relative Metrics/CyclomaticComplexity: - Enabled: false + Enabled: False -Naming/ConstantName: - Enabled: true +Style/ConstantName: + Enabled: True Style/Documentation: - Enabled: false + Enabled: False Style/DefWithParentheses: - Enabled: true + Enabled: True Style/PreferredHashMethods: - Enabled: true + Enabled: True Layout/DotPosition: EnforcedStyle: trailing Style/DoubleNegation: - Enabled: true + Enabled: True Style/EachWithObject: - Enabled: true + Enabled: True Layout/EmptyLineBetweenDefs: - Enabled: true + Enabled: True Layout/IndentArray: - Enabled: true + Enabled: True Layout/IndentHash: - Enabled: true + Enabled: True Layout/IndentationConsistency: - Enabled: true + Enabled: True Layout/IndentationWidth: - Enabled: true + Enabled: True Layout/EmptyLines: - Enabled: true + Enabled: True Layout/EmptyLinesAroundAccessModifier: - Enabled: true + Enabled: True Style/EmptyLiteral: - Enabled: true + Enabled: True # Configuration parameters: AllowURI, URISchemes. Metrics/LineLength: - Enabled: false + Enabled: False Style/MethodCallWithoutArgsParentheses: - Enabled: true + Enabled: True Style/MethodDefParentheses: - Enabled: true + Enabled: True Style/LineEndConcatenation: - Enabled: true + Enabled: True Layout/TrailingWhitespace: - Enabled: true + Enabled: True Style/StringLiterals: - Enabled: true + Enabled: True Style/TrailingCommaInArguments: - Enabled: true + Enabled: True -Style/TrailingCommaInArrayLiteral: - Enabled: true - -Style/TrailingCommaInHashLiteral: - Enabled: true +Style/TrailingCommaInLiteral: + Enabled: True Style/GlobalVars: - Enabled: true + Enabled: True Style/GuardClause: - Enabled: true + Enabled: True Style/IfUnlessModifier: - Enabled: true + Enabled: True Style/MultilineIfThen: - Enabled: true + Enabled: True Style/NegatedIf: - Enabled: true + Enabled: True Style/NegatedWhile: - Enabled: true + Enabled: True Style/Next: - Enabled: true + Enabled: True Style/SingleLineBlockParams: - Enabled: true + Enabled: True Style/SingleLineMethods: - Enabled: true + Enabled: True Style/SpecialGlobalVars: - Enabled: true + Enabled: True Style/TrivialAccessors: - Enabled: true + Enabled: True Style/UnlessElse: - Enabled: true + Enabled: True Style/VariableInterpolation: - Enabled: true + Enabled: True -Naming/VariableName: - Enabled: true +Style/VariableName: + Enabled: True Style/WhileUntilDo: - Enabled: true + Enabled: True Style/EvenOdd: - Enabled: true + Enabled: True -Naming/FileName: - Enabled: true +Style/FileName: + Enabled: True Style/For: - Enabled: true + Enabled: True Style/Lambda: - Enabled: true + Enabled: True -Naming/MethodName: - Enabled: true +Style/MethodName: + Enabled: True Style/MultilineTernaryOperator: - Enabled: true + Enabled: True Style/NestedTernaryOperator: - Enabled: true + Enabled: True Style/NilComparison: - Enabled: true + Enabled: True Style/FormatString: - Enabled: true + Enabled: True Style/MultilineBlockChain: - Enabled: true + Enabled: True Style/Semicolon: - Enabled: true + Enabled: True Style/SignalException: - Enabled: true + Enabled: True Style/NonNilCheck: - Enabled: true + Enabled: True Style/Not: - Enabled: true + Enabled: True Style/NumericLiterals: - Enabled: true + Enabled: True Style/OneLineConditional: - Enabled: true + Enabled: True -Naming/BinaryOperatorParameterName: - Enabled: true +Style/OpMethod: + Enabled: True Style/ParenthesesAroundCondition: - Enabled: true + Enabled: True Style/PercentLiteralDelimiters: - Enabled: true + Enabled: True Style/PerlBackrefs: - Enabled: true + Enabled: True -Naming/PredicateName: - Enabled: true +Style/PredicateName: + Enabled: True Style/RedundantException: - Enabled: true + Enabled: True Style/SelfAssignment: - Enabled: true + Enabled: True Style/Proc: - Enabled: true + Enabled: True Style/RaiseArgs: - Enabled: true + Enabled: True Style/RedundantBegin: - Enabled: true + Enabled: True Style/RescueModifier: - Enabled: true + Enabled: True # based on https://github.com/voxpupuli/modulesync_config/issues/168 Style/RegexpLiteral: EnforcedStyle: percent_r - Enabled: true + Enabled: True Lint/UnderscorePrefixedVariableName: - Enabled: true + Enabled: True Metrics/ParameterLists: - Enabled: false + Enabled: False Lint/RequireParentheses: - Enabled: true - -Layout/SpaceBeforeFirstArg: - Enabled: true + Enabled: True Style/ModuleFunction: - Enabled: true + Enabled: True Lint/Debugger: - Enabled: true + Enabled: True Style/IfWithSemicolon: - Enabled: true + Enabled: True Style/Encoding: - Enabled: true + Enabled: True Style/BlockDelimiters: - Enabled: true - -Style/FormatStringToken: - Enabled: false + Enabled: True Layout/MultilineBlockLayout: - Enabled: true + Enabled: True # 'Complexity' is very relative Metrics/AbcSize: Enabled: False -Metrics/BlockLength: - Enabled: False - # 'Complexity' is very relative Metrics/PerceivedComplexity: Enabled: False Lint/UselessAssignment: - Enabled: true + Enabled: True Layout/ClosingParenthesisIndentation: - Enabled: false + Enabled: True # RSpec +RSpec/BeforeAfterAll: + Exclude: + - spec/acceptance/**/* + # We don't use rspec in this way RSpec/DescribeClass: Enabled: False # Example length is not necessarily an indicator of code quality RSpec/ExampleLength: Enabled: False -RSpec/NestedGroups: - Max: 4 -RSpec/MultipleExpectations: - Max: 2 + +RSpec/NamedSubject: + Enabled: False + +# disabled for now since they cause a lot of issues +# these issues aren't easy to fix +RSpec/RepeatedDescription: + Enabled: False + +RSpec/NestedGroups: + Enabled: False + +# this is broken on ruby1.9 +Layout/IndentHeredoc: + Enabled: False + +# disable Yaml safe_load. This is needed to support ruby2.0.0 development envs +Security/YAMLLoad: + Enabled: false + +# This affects hiera interpolation, as well as some configs that we push. +Style/FormatStringToken: + Enabled: false + +# This is useful, but sometimes a little too picky about where unit tests files +# are located. +RSpec/FilePath: + Enabled: false diff --git a/.travis.yml b/.travis.yml index d5c0ce1..3a0fded 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,42 +1,93 @@ -sudo: false +--- +dist: bionic language: ruby cache: bundler -bundler_args: "--without system_tests development" before_install: -- bundle -v -- rm Gemfile.lock || true -- gem update --system -- gem update bundler -- gem --version -- bundle -v + - yes | gem update --system + - bundle --version script: -- bundle exec rake $CHECK + - 'bundle exec rake $CHECK' matrix: fast_finish: true include: - - rvm: 2.3.1 - env: PUPPET_VERSION="~> 4.0" STRICT_VARIABLES="yes" CHECK=test - - rvm: 2.3.1 - env: PUPPET_VERSION="~> 4.0" STRICT_VARIABLES="yes" CHECK=rubocop - - rvm: 2.3.1 - env: PUPPET_VERSION="~> 4.0" STRICT_VARIABLES="yes" CHECK=build FORGEDEPLOY=true - - rvm: 2.3.1 - env: PUPPET_VERSION="~> 5.0" STRICT_VARIABLES="yes" CHECK=test - - rvm: 2.3.1 - env: PUPPET_VERSION="~> 5.0" STRICT_VARIABLES="yes" CHECK=rubocop - - rvm: 2.5.3 - env: PUPPET_VERSION="~> 6.1" STRICT_VARIABLES="yes" CHECK=test - - rvm: 2.5.3 - env: PUPPET_VERSION="~> 6.1" STRICT_VARIABLES="yes" CHECK=rubocop + - rvm: 2.4.4 + bundler_args: --without system_tests development release + env: PUPPET_VERSION="~> 5.0" CHECK=test + - rvm: 2.5.3 + bundler_args: --without system_tests development release + env: PUPPET_VERSION="~> 6.0" CHECK=test_with_coveralls + - rvm: 2.5.3 + bundler_args: --without system_tests development release + env: PUPPET_VERSION="~> 6.0" CHECK=rubocop + - rvm: 2.4.4 + bundler_args: --without system_tests development release + env: PUPPET_VERSION="~> 5.0" CHECK=build DEPLOY_TO_FORGE=yes + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=ubuntu1804-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=ubuntu1804-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=ubuntu1604-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=ubuntu1604-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=centos8-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=centos8-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=centos7-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=centos7-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=centos6-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=centos6-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=debian9-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=debian9-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet5 BEAKER_debug=true BEAKER_setfile=debian8-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker + - rvm: 2.5.3 + bundler_args: --without development release + env: PUPPET_INSTALL_TYPE=agent BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_debug=true BEAKER_setfile=debian8-64 BEAKER_HYPERVISOR=docker CHECK=beaker + services: docker notifications: email: false deploy: provider: puppetforge user: saz password: secure: VlSGdU3hHTPHYe+++BOrnVcZE8rFHEYtByHoymvbf++dZaGv1RgCYVGr2Vn33gaT/h4hho8rgRyep5F6sHJaDPZUprJ5WU3I/TnbQrm13C521Z2+PP5jhEjG9rMHze4+4vDVKdO8K9x0zErGDwHaf6+QF5lQH6ewIykLWXl0DRA= on: tags: true + # all_branches is required to use tags all_branches: true - rvm: 2.3.1 - condition: "$FORGEDEPLOY = true" + # Only publish the build marked with "DEPLOY_TO_FORGE" + condition: "$DEPLOY_TO_FORGE = yes" diff --git a/Gemfile b/Gemfile index 577f487..4860141 100644 --- a/Gemfile +++ b/Gemfile @@ -1,63 +1,76 @@ -source ENV['GEM_SOURCE'] || 'https://rubygems.org' +source ENV['GEM_SOURCE'] || "https://rubygems.org" def location_for(place, fake_version = nil) if place =~ /^(git[:@][^#]*)#(.*)/ - [fake_version, { git: $1, branch: $2, require: false }].compact + [fake_version, { :git => $1, :branch => $2, :require => false }].compact elsif place =~ /^file:\/\/(.*)/ - ['>= 0', { path: File.expand_path($1), require: false }] + ['>= 0', { :path => File.expand_path($1), :require => false }] else - [place, { require: false }] + [place, { :require => false }] end end group :test do - gem 'puppetlabs_spec_helper', '>= 2.11.0', require: false - gem 'rspec-puppet', require: false - gem 'rspec-puppet-facts', require: false - gem 'rspec-puppet-utils', require: false - gem 'puppet-lint-absolute_classname-check', require: false - gem 'puppet-lint-leading_zero-check', require: false - gem 'puppet-lint-trailing_comma-check', require: false - gem 'puppet-lint-version_comparison-check', require: false - gem 'puppet-lint-classes_and_types_beginning_with_digits-check', require: false - gem 'puppet-lint-unquoted_string-check', require: false - gem 'puppet-lint-variable_contains_upcase', require: false - gem 'metadata-json-lint', require: false - gem 'puppet-blacksmith', require: false - gem 'voxpupuli-release', require: false, git: 'https://github.com/voxpupuli/voxpupuli-release-gem.git' - gem 'puppet-strings', '~> 1.0', require: false - gem 'rubocop', '~> 0.49.1', require: false - gem 'rubocop-rspec', require: false - gem 'rspec-its', require: false + gem 'puppetlabs_spec_helper', '>= 2.11.0', :require => false + gem 'rspec-puppet-facts', :require => false + gem 'rspec-puppet-utils', :require => false + gem 'puppet-lint-leading_zero-check', :require => false + gem 'puppet-lint-trailing_comma-check', :require => false + gem 'puppet-lint-version_comparison-check', :require => false + gem 'puppet-lint-classes_and_types_beginning_with_digits-check', :require => false + gem 'puppet-lint-unquoted_string-check', :require => false + gem 'puppet-lint-variable_contains_upcase', :require => false + gem 'puppet-lint-absolute_classname-check', '>= 2.0.0', :require => false + gem 'puppet-lint-topscope-variable-check', :require => false + gem 'puppet-lint-legacy_facts-check', :require => false + gem 'puppet-lint-anchor-check', :require => false + gem 'metadata-json-lint', :require => false + gem 'rubocop', '~> 0.49.1', :require => false + gem 'rubocop-rspec', :require => false + gem 'coveralls', :require => false + gem 'simplecov-console', :require => false + gem 'parallel_tests', :require => false end group :development do - gem 'travis', require: false - gem 'travis-lint', require: false - gem 'guard-rake', require: false + gem 'travis', :require => false + gem 'travis-lint', :require => false + gem 'guard-rake', :require => false end group :system_tests do - if (beaker_version = ENV['BEAKER_VERSION']) + if beaker_version = ENV['BEAKER_VERSION'] gem 'beaker', *location_for(beaker_version) + else + gem 'beaker', '>= 4.2.0', :require => false end - if (beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION']) + if beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION'] gem 'beaker-rspec', *location_for(beaker_rspec_version) else - gem 'beaker-rspec', require: false + gem 'beaker-rspec', :require => false end - gem 'beaker-puppet_install_helper', require: false + gem 'beaker-hostgenerator', '>= 1.1.22', :require => false + gem 'beaker-docker', :require => false + gem 'beaker-puppet', :require => false + gem 'beaker-puppet_install_helper', :require => false + gem 'beaker-module_install_helper', :require => false +end + +group :release do + gem 'puppet-blacksmith', :require => false + gem 'voxpupuli-release', :require => false + gem 'puppet-strings', '>= 2.2', :require => false end -if (facterversion = ENV['FACTER_GEM_VERSION']) - gem 'facter', facterversion.to_s, require: false, groups: [:test] +if facterversion = ENV['FACTER_GEM_VERSION'] + gem 'facter', facterversion.to_s, :require => false, :groups => [:test] else - gem 'facter', require: false, groups: [:test] + gem 'facter', :require => false, :groups => [:test] end -ENV['PUPPET_VERSION'].nil? ? puppetversion = '~> 4.0' : puppetversion = ENV['PUPPET_VERSION'].to_s -gem 'puppet', puppetversion, require: false, groups: [:test] +ENV['PUPPET_VERSION'].nil? ? puppetversion = '~> 6.0' : puppetversion = ENV['PUPPET_VERSION'].to_s +gem 'puppet', puppetversion, :require => false, :groups => [:test] # vim: syntax=ruby diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 0000000..f5ca26d --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,133 @@ +# Reference + + +## Table of Contents + +**Classes** + +* [`timezone`](#timezone): This module manages timezone settings + +## Classes + +### timezone + +This module manages timezone settings + +#### Examples + +##### + +```puppet +class { 'timezone': + timezone => 'Europe/Berlin', +} +``` + +#### Parameters + +The following parameters are available in the `timezone` class. + +##### `timezone` + +Data type: `String` + +The name of the timezone. + +Default value: 'Etc/UTC' + +##### `ensure` + +Data type: `Enum['present','absent']` + +Ensure if present or absent. + +Default value: 'present' + +##### `autoupgrade` + +Data type: `Boolean` + +Upgrade package automatically, if there is a newer version. + +Default value: `false` + +##### `package` + +Data type: `Optional[String]` + +Name of the package. +Only set this, if your platform is not supported or you know, what you're doing. + +Default value: `undef` + +##### `config_file` + +Main configuration file. +Only set this, if your platform is not supported or you know, what you're doing. + +##### `zoneinfo_dir` + +Data type: `String` + +Source directory of zoneinfo files. +Only set this, if your platform is not supported or you know, what you're doing. +Default: auto-set, platform specific + +Default value: '/usr/share/zoneinfo/' + +##### `hwutc` + +Data type: `Optional[Boolean]` + +Is the hardware clock set to UTC? (true or false) + +Default value: `undef` + +##### `notify_services` + +Data type: `Optional[Array[String]]` + +List of services to notify + +Default value: `undef` + +##### `localtime_file` + +Data type: `String` + + + +Default value: '/etc/localtime' + +##### `timezone_file` + +Data type: `Optional[String]` + + + +Default value: `undef` + +##### `timezone_file_template` + +Data type: `Optional[String]` + + + +Default value: 'timezone/clock.erb' + +##### `timezone_file_supports_comment` + +Data type: `Optional[Boolean]` + + + +Default value: `undef` + +##### `timezone_update` + +Data type: `Optional[String]` + + + +Default value: `undef` + diff --git a/Rakefile b/Rakefile index 5c10c3f..c4fdaf4 100644 --- a/Rakefile +++ b/Rakefile @@ -1,42 +1,58 @@ require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet_blacksmith/rake_tasks' -require 'voxpupuli/release/rake_tasks' -if RUBY_VERSION >= '2.2.0' - require 'rubocop/rake_task' - - RuboCop::RakeTask.new(:rubocop) do |task| - # These make the rubocop experience maybe slightly less terrible - task.options = ['-D', '-S', '-E'] - end +# load optional tasks for releases +# only available if gem group releases is installed +begin + require 'voxpupuli/release/rake_tasks' +rescue LoadError end -PuppetLint.configuration.fail_on_warnings = true -PuppetLint.configuration.send('relative') -PuppetLint.configuration.send('disable_140chars') -PuppetLint.configuration.send('disable_class_inherits_from_params_class') -PuppetLint.configuration.send('disable_documentation') -PuppetLint.configuration.send('disable_single_quote_string_with_variables') - -exclude_paths = %w( - pkg/**/* - vendor/**/* - .vendor/**/* - spec/**/* -) -PuppetLint.configuration.ignore_paths = exclude_paths -PuppetSyntax.exclude_paths = exclude_paths +PuppetLint.configuration.log_format = '%{path}:%{line}:%{check}:%{KIND}:%{message}' + +desc 'Auto-correct puppet-lint offenses' +task 'lint:auto_correct' do + Rake::Task[:lint_fix].invoke +end desc 'Run acceptance tests' RSpec::Core::RakeTask.new(:acceptance) do |t| t.pattern = 'spec/acceptance' end -desc 'Run tests metadata_lint, lint, syntax, spec' -task test: [ - :metadata_lint, - :lint, - :syntax, - :spec, -] +desc 'Run tests' +task test: [:release_checks] + +namespace :check do + desc 'Check for trailing whitespace' + task :trailing_whitespace do + Dir.glob('**/*.md', File::FNM_DOTMATCH).sort.each do |filename| + next if filename =~ %r{^((modules|acceptance|\.?vendor|spec/fixtures|pkg)/|REFERENCE.md)} + File.foreach(filename).each_with_index do |line, index| + if line =~ %r{\s\n$} + puts "#{filename} has trailing whitespace on line #{index + 1}" + exit 1 + end + end + end + end +end +Rake::Task[:release_checks].enhance ['check:trailing_whitespace'] + +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 + # vim: syntax=ruby diff --git a/data/os/Archlinux.yaml b/data/family/Archlinux.yaml similarity index 98% rename from data/os/Archlinux.yaml rename to data/family/Archlinux.yaml index 074cf91..1d034f6 100644 --- a/data/os/Archlinux.yaml +++ b/data/family/Archlinux.yaml @@ -1,6 +1,5 @@ ---- timezone::package: tzdata timezone::zoneinfo_dir: /usr/share/zoneinfo timezone::localtime_file: /etc/localtime timezone::timezone_update: 'timedatectl set-timezone %s' timezone::timezone_update_check_cmd: 'timedatectl status | grep "Timezone:\|Time zone:" | grep -q %s' diff --git a/data/os/Debian.yaml b/data/family/Debian.yaml similarity index 98% rename from data/os/Debian.yaml rename to data/family/Debian.yaml index e48e2cc..22918b7 100644 --- a/data/os/Debian.yaml +++ b/data/family/Debian.yaml @@ -1,9 +1,8 @@ ---- timezone::package: tzdata timezone::zoneinfo_dir: /usr/share/zoneinfo timezone::localtime_file: /etc/localtime timezone::timezone_file: /etc/timezone timezone::timezone_file_template: timezone/timezone.erb timezone::timezone_file_supports_comment: false timezone::timezone_update: dpkg-reconfigure -f noninteractive tzdata timezone::use_debconf: true diff --git a/data/os/FreeBSD.yaml b/data/family/FreeBSD.yaml similarity index 95% rename from data/os/FreeBSD.yaml rename to data/family/FreeBSD.yaml index a376524..ca23047 100644 --- a/data/os/FreeBSD.yaml +++ b/data/family/FreeBSD.yaml @@ -1,3 +1,2 @@ ---- timezone::zoneinfo_dir: /usr/share/zoneinfo timezone::localtime_file: /etc/localtime diff --git a/data/os/Gentoo.yaml b/data/family/Gentoo.yaml similarity index 98% rename from data/os/Gentoo.yaml rename to data/family/Gentoo.yaml index fd6be1b..e8a13dd 100644 --- a/data/os/Gentoo.yaml +++ b/data/family/Gentoo.yaml @@ -1,8 +1,7 @@ ---- timezone::package: sys-libs/timezone-data timezone::zoneinfo_dir: /usr/share/zoneinfo timezone::localtime_file: /etc/localtime timezone::timezone_file: /etc/timezone timezone::timezone_file_template: timezone/timezone.erb timezone::timezone_file_supports_comment: false timezone::timezone_update: emerge --config timezone-data diff --git a/data/os/Linux.yaml b/data/family/Linux.yaml similarity index 98% rename from data/os/Linux.yaml rename to data/family/Linux.yaml index 9d096e6..79597ce 100644 --- a/data/os/Linux.yaml +++ b/data/family/Linux.yaml @@ -1,6 +1,5 @@ ---- timezone::package: tzdata timezone::zoneinfo_dir: /usr/share/zoneinfo timezone::localtime_file: /etc/localtime timezone::timezone_file_template: timezone/clock.erb timezone::timezone_file_supports_comment: false diff --git a/data/os/RedHat.yaml b/data/family/RedHat.yaml similarity index 98% rename from data/os/RedHat.yaml rename to data/family/RedHat.yaml index 9d096e6..79597ce 100644 --- a/data/os/RedHat.yaml +++ b/data/family/RedHat.yaml @@ -1,6 +1,5 @@ ---- timezone::package: tzdata timezone::zoneinfo_dir: /usr/share/zoneinfo timezone::localtime_file: /etc/localtime timezone::timezone_file_template: timezone/clock.erb timezone::timezone_file_supports_comment: false diff --git a/data/os/RedHat/6.yaml b/data/family/RedHat/6.yaml similarity index 92% rename from data/os/RedHat/6.yaml rename to data/family/RedHat/6.yaml index 6b7764b..ccccefc 100644 --- a/data/os/RedHat/6.yaml +++ b/data/family/RedHat/6.yaml @@ -1,2 +1 @@ ---- timezone::timezone_file: /etc/sysconfig/clock diff --git a/data/os/RedHat/7.yaml b/data/family/RedHat/7.yaml similarity index 98% copy from data/os/RedHat/7.yaml copy to data/family/RedHat/7.yaml index e4a45bf..5524ed3 100644 --- a/data/os/RedHat/7.yaml +++ b/data/family/RedHat/7.yaml @@ -1,6 +1,5 @@ ---- timezone::timezone_update: 'timedatectl set-timezone %s' timezone::timezone_update_check_cmd: 'timedatectl status | grep "Timezone:\|Time zone:" | grep -q %s' timezone::check_hwclock_enabled_cmd: 'grep LOCAL /etc/adjtime' timezone::check_hwclock_disabled_cmd: 'grep UTC /etc/adjtime' timezone::hwclock_cmd: 'timedatectl set-local-rtc %s' diff --git a/data/os/RedHat/7.yaml b/data/family/RedHat/8.yaml similarity index 98% rename from data/os/RedHat/7.yaml rename to data/family/RedHat/8.yaml index e4a45bf..5524ed3 100644 --- a/data/os/RedHat/7.yaml +++ b/data/family/RedHat/8.yaml @@ -1,6 +1,5 @@ ---- timezone::timezone_update: 'timedatectl set-timezone %s' timezone::timezone_update_check_cmd: 'timedatectl status | grep "Timezone:\|Time zone:" | grep -q %s' timezone::check_hwclock_enabled_cmd: 'grep LOCAL /etc/adjtime' timezone::check_hwclock_disabled_cmd: 'grep UTC /etc/adjtime' timezone::hwclock_cmd: 'timedatectl set-local-rtc %s' diff --git a/data/os/Suse.yaml b/data/family/Suse.yaml similarity index 97% rename from data/os/Suse.yaml rename to data/family/Suse.yaml index a905b2d..68c3e06 100644 --- a/data/os/Suse.yaml +++ b/data/family/Suse.yaml @@ -1,5 +1,4 @@ ---- timezone::package: timezone timezone::zoneinfo_dir: /usr/share/zoneinfo timezone::localtime_file: /etc/localtime timezone::timezone_update: 'zic -l %s' diff --git a/data/os/Suse/11.yaml b/data/family/Suse/11.yaml similarity index 96% rename from data/os/Suse/11.yaml rename to data/family/Suse/11.yaml index 1634e47..be5eb96 100644 --- a/data/os/Suse/11.yaml +++ b/data/family/Suse/11.yaml @@ -1,3 +1,2 @@ ---- timezone::timezone_file: /etc/sysconfig/clock timezone::timezone_file_template: timezone/clock_sles11.erb diff --git a/data/os/Suse/12.yaml b/data/family/Suse/12.yaml similarity index 97% rename from data/os/Suse/12.yaml rename to data/family/Suse/12.yaml index 24f9b3f..49b5b34 100644 --- a/data/os/Suse/12.yaml +++ b/data/family/Suse/12.yaml @@ -1,3 +1,2 @@ ---- timezone::timezone_update: 'timedatectl set-timezone %s' timezone::timezone_update_check_cmd: 'timedatectl status | grep "Timezone:\|Time zone:" | grep -q %s' diff --git a/data/os/Suse/15.yaml b/data/family/Suse/15.yaml similarity index 97% rename from data/os/Suse/15.yaml rename to data/family/Suse/15.yaml index 24f9b3f..49b5b34 100644 --- a/data/os/Suse/15.yaml +++ b/data/family/Suse/15.yaml @@ -1,3 +1,2 @@ ---- timezone::timezone_update: 'timedatectl set-timezone %s' timezone::timezone_update_check_cmd: 'timedatectl status | grep "Timezone:\|Time zone:" | grep -q %s' diff --git a/hiera.yaml b/hiera.yaml index 4776331..aa50c09 100644 --- a/hiera.yaml +++ b/hiera.yaml @@ -1,15 +1,14 @@ --- version: 5 + defaults: datadir: 'data' - data_hash: 'yaml_data' + data_hash: yaml_data hierarchy: - - name: 'Operating system major version' - path: 'os/%{facts.os.family}/%{facts.os.release.major}.yaml' - - - name: 'Operating system family' - path: 'os/%{facts.os.family}.yaml' - - - name: 'common' - path: 'common.yaml' + - name: 'OS Major Release Overrides' + path: "family/%{facts.os.family}/%{facts.os.release.major}.yaml" + - name: 'Operating System Family' + path: "family/%{facts.os.family}.yaml" + - name: 'Defaults' + path: 'defaults.yaml' diff --git a/manifests/init.pp b/manifests/init.pp index 3429d3d..23508d9 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,154 +1,155 @@ -# This module manages timezone settings +# +# @summary This module manages timezone settings # # @param timezone # The name of the timezone. # # @param ensure # Ensure if present or absent. # # @param autoupgrade # Upgrade package automatically, if there is a newer version. # # @param package # Name of the package. # Only set this, if your platform is not supported or you know, what you're doing. # # @param config_file # Main configuration file. # Only set this, if your platform is not supported or you know, what you're doing. # # @param zoneinfo_dir # Source directory of zoneinfo files. # Only set this, if your platform is not supported or you know, what you're doing. # Default: auto-set, platform specific # # @param hwutc # Is the hardware clock set to UTC? (true or false) # # @param notify_services # List of services to notify # # @example # class { 'timezone': # timezone => 'Europe/Berlin', # } # class timezone ( String $timezone = 'Etc/UTC', Enum['present','absent'] $ensure = 'present', Optional[Boolean] $hwutc = undef, Boolean $autoupgrade = false, Optional[Array[String]] $notify_services = undef, Optional[String] $package = undef, String $zoneinfo_dir = '/usr/share/zoneinfo/', String $localtime_file = '/etc/localtime', Optional[String] $timezone_file = undef, Optional[String] $timezone_file_template = 'timezone/clock.erb', Optional[Boolean] $timezone_file_supports_comment = undef, Optional[String] $timezone_update = undef ) { case $ensure { /(present)/: { if $autoupgrade == true { $package_ensure = 'latest' } else { $package_ensure = 'present' } $localtime_ensure = 'link' $timezone_ensure = 'file' } /(absent)/: { # Leave package installed, as it is a system dependency $package_ensure = 'present' $localtime_ensure = 'absent' $timezone_ensure = 'absent' } default: { fail('ensure parameter must be present or absent') } } if $package { $use_debconf = lookup('timezone::use_debconf', Boolean, 'first', false) if $package_ensure == 'present' and $use_debconf { $_tz = split($timezone, '/') $area = $_tz[0] $zone = $_tz[1] debconf { 'tzdata/Areas': package => 'tzdata', item => 'tzdata/Areas', type => 'select', value => $area; "tzdata/Zones/${area}": package => 'tzdata', item => "tzdata/Zones/${area}", type => 'select', value => $zone; } -> Package[$package] } package { $package: ensure => $package_ensure, before => File[$localtime_file], } } file { $localtime_file: ensure => $localtime_ensure, target => "${zoneinfo_dir}/${timezone}", force => true, notify => $notify_services, } if $timezone_file { file { $timezone_file: ensure => $timezone_ensure, content => template($timezone_file_template), notify => $notify_services, } if $ensure == 'present' and $timezone_update { exec { 'update_timezone': command => sprintf($timezone_update, $timezone), subscribe => File[$timezone_file], refreshonly => true, path => '/usr/bin:/usr/sbin:/bin:/sbin', require => File[$localtime_file], } } } else { if $ensure == 'present' and $timezone_update { $unless_cmd = lookup('timezone::timezone_update_check_cmd', String, 'first') exec { 'update_timezone': command => sprintf($timezone_update, $timezone), unless => sprintf($unless_cmd, $timezone), path => '/usr/bin:/usr/sbin:/bin:/sbin', require => File[$localtime_file], } } } if $ensure == 'present' and $hwutc != undef { $hwclock_cmd = lookup('timezone::hwclock_cmd', Optional[String], 'first', undef) $hwclock_check_enabled_cmd = lookup('timezone::check_hwclock_enabled_cmd', Optional[String], 'first', undef) $hwclock_check_disabled_cmd = lookup('timezone::check_hwclock_disabled_cmd', Optional[String], 'first', undef) if $hwclock_cmd != '' and $hwclock_cmd != undef { if ! $hwutc { $hwclock_unless = $hwclock_check_enabled_cmd } else { $hwclock_unless = $hwclock_check_disabled_cmd } exec { 'set_hwclock': command => sprintf($hwclock_cmd, (! $hwutc)), unless => $hwclock_unless, path => '/usr/bin:/usr/sbin:/bin:/sbin', } } } } diff --git a/metadata.json b/metadata.json index d0dd6f1..906af1e 100644 --- a/metadata.json +++ b/metadata.json @@ -1,54 +1,70 @@ { + "name": "saz-timezone", + "version": "5.2.2", + "author": "saz", + "summary": "Manage timezone settings via Puppet", + "license": "Apache-2.0", + "source": "https://github.com/saz/puppet-timezone", + "project_page": "https://github.com/saz/puppet-timezone", + "issues_url": "https://github.com/saz/puppet-timezone/issues", + "description": "Manage timezone settings via Puppet", "operatingsystem_support": [ + { + "operatingsystem": "Ubuntu" + }, + { + "operatingsystem": "Debian" + }, { "operatingsystem": "RedHat" }, { "operatingsystem": "CentOS" }, { "operatingsystem": "OracleLinux" }, { "operatingsystem": "Scientific" }, { - "operatingsystem": "Debian" - }, - { - "operatingsystem": "Ubuntu" + "operatingsystem": "Gentoo" }, { - "operatingsystem": "Gentoo" + "operatingsystem": "Archlinux" }, { - "operatingsystem": "ArchLinux" + "operatingsystem": "FreeBSD", + "operatingsystemrelease": [ + "11", + "12" + ] }, { "operatingsystem": "SLES", "operatingsystemrelease": [ "11", "12", "15" ] } ], "requirements": [ { "name": "puppet", - "version_requirement": ">= 4.9.1 < 7.0.0" + "version_requirement": ">= 5.0.0 < 7.0.0" } ], - "name": "saz-timezone", - "version": "5.2.1", - "source": "git://github.com/saz/puppet-timezone", - "author": "saz", - "license": "Apache-2.0", - "summary": "Manage timezone settings via Puppet", - "description": "Manage timezone settings via Puppet", - "project_page": "https://github.com/saz/puppet-timezone", "dependencies": [ - { "name": "puppetlabs/stdlib", "version_requirement": ">=2.6.0 < 7.0.0" }, - { "name": "stm/debconf", "version_requirement": ">= 2.0.0 < 3.0.0" } + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 2.6.0 < 7.0.0" + }, + { + "name": "stm/debconf", + "version_requirement": ">= 2.0.0 < 3.0.0" + } + ], + "tags": [ ] } diff --git a/spec/acceptance/timezone_spec.rb b/spec/acceptance/timezone_spec.rb index b4f23e3..cced91d 100644 --- a/spec/acceptance/timezone_spec.rb +++ b/spec/acceptance/timezone_spec.rb @@ -1,15 +1,15 @@ require 'spec_helper_acceptance' describe 'timezone class' do describe 'running puppet code' do it 'works with no errors' do pp = <<-PUPPET class { '::timezone': } PUPPET # Run it twice and test for idempotency - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) end end end diff --git a/spec/classes/timezone_spec.rb b/spec/classes/timezone_spec.rb index 50a19fd..9818905 100644 --- a/spec/classes/timezone_spec.rb +++ b/spec/classes/timezone_spec.rb @@ -1,11 +1,219 @@ require 'spec_helper' -describe 'timezone' do - %w[Debian RedHat Gentoo FreeBSD].each do |osfamily| - describe "on supported osfamily: #{osfamily}" do - let(:title) { 'EST' } +describe 'timezone', type: :class do + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:params) { {} } + let(:facts) do + facts + end - include_examples osfamily + puts "Testing #{os} (#{facts[:os]['family']})" + + it { is_expected.to compile.with_all_deps } + + it { is_expected.to create_class('timezone') } + + case facts[:os]['family'] + when 'Debian' + + context 'when using default class parameters' do + it { is_expected.to contain_file('/etc/timezone') } + it { is_expected.to contain_file('/etc/timezone').with_ensure('file') } + it { is_expected.to contain_file('/etc/timezone').with_content(%r{Etc/UTC}) } + it { is_expected.to contain_exec('update_timezone').with_command(%r{^dpkg-reconfigure -f noninteractive tzdata$}) } + it { is_expected.to contain_package('tzdata').with(ensure: 'present', before: 'File[/etc/localtime]') } + it { is_expected.to contain_file('/etc/localtime').with(ensure: 'link', target: '/usr/share/zoneinfo/Etc/UTC') } + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) { { timezone: 'Europe/Berlin' } } + + it { is_expected.to contain_file('/etc/timezone').with_content(%r{^Europe/Berlin$}) } + it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) { { autoupgrade: true } } + + it { is_expected.to contain_package('tzdata').with_ensure('latest') } + end + + context 'when ensure => absent' do + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_package('tzdata').with_ensure('present') } + it { is_expected.to contain_file('/etc/timezone').with_ensure('absent') } + it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } + end # end Debian version + + when 'RedHat' + case facts[:os]['release']['major'] + when '6' + context 'redhat/centos 6' do + context 'when using default class parameters' do + it { is_expected.to contain_package('tzdata').with(ensure: 'present', before: 'File[/etc/localtime]') } + + it { is_expected.to contain_file('/etc/sysconfig/clock').with_ensure('file') } + it { is_expected.to contain_file('/etc/sysconfig/clock').with_content(%r{^ZONE="Etc/UTC"$}) } + it { is_expected.not_to contain_exec('update_timezone') } + + it { is_expected.to contain_file('/etc/localtime').with(ensure: 'link', target: '/usr/share/zoneinfo/Etc/UTC') } + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) { { timezone: 'Europe/Berlin' } } + + it { is_expected.to contain_file('/etc/sysconfig/clock').with_content(%r{^ZONE="Europe/Berlin"$}) } + it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) { { autoupgrade: true } } + + it { is_expected.to contain_package('tzdata').with_ensure('latest') } + end + + context 'when ensure => absent' do + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_package('tzdata').with_ensure('present') } + it { is_expected.to contain_file('/etc/sysconfig/clock').with_ensure('absent') } + it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } + end + end + when '7', '8' + context 'redhat/centos 7, 8' do + it { is_expected.not_to contain_file('/etc/sysconfig/clock') } + it { is_expected.to contain_file('/etc/localtime').with_ensure('link') } + it { is_expected.to contain_exec('update_timezone').with_command('timedatectl set-timezone Etc/UTC').with_unless('timedatectl status | grep "Timezone:\|Time zone:" | grep -q Etc/UTC') } + end + end # end RedHat version + + when 'Archlinux' + context 'archlinux' do + context 'when using default class parameters' do + it { is_expected.to contain_package('tzdata').with(ensure: 'present', before: 'File[/etc/localtime]') } + + it { is_expected.not_to contain_file('/etc/sysconfig/clock') } + it { is_expected.to contain_file('/etc/localtime').with_ensure('link') } + it { is_expected.to contain_exec('update_timezone').with_command('timedatectl set-timezone Etc/UTC').with_unless('timedatectl status | grep "Timezone:\|Time zone:" | grep -q Etc/UTC') } + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) { { timezone: 'Europe/Berlin' } } + + it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) { { autoupgrade: true } } + + it { is_expected.to contain_package('tzdata').with_ensure('latest') } + end + + context 'when ensure => absent' do + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_package('tzdata').with_ensure('present') } + it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } + end + end # end Archlinux version + + when 'Gentoo' + + context 'Gentoo' do + context 'when using default class parameters' do + it { is_expected.to contain_package('sys-libs/timezone-data').with(ensure: 'present', before: 'File[/etc/localtime]') } + + it { is_expected.to contain_file('/etc/timezone').with_ensure('file') } + it { is_expected.to contain_file('/etc/timezone').with_content(%r{^Etc/UTC$}) } + it { is_expected.to contain_exec('update_timezone').with_command(%r{^emerge --config timezone-data$}) } + it { is_expected.to contain_file('/etc/localtime').with(ensure: 'link', target: '/usr/share/zoneinfo/Etc/UTC') } + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) { { timezone: 'Europe/Berlin' } } + + it { is_expected.to contain_file('/etc/timezone').with_content(%r{^Europe/Berlin$}) } + it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) { { autoupgrade: true } } + + it { is_expected.to contain_package('sys-libs/timezone-data').with_ensure('latest') } + end + + context 'when ensure => absent' do + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_package('sys-libs/timezone-data').with_ensure('present') } + it { is_expected.to contain_file('/etc/timezone').with_ensure('absent') } + it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } + end + end # end Gentoo + + when 'FreeBSD' + context 'FreeBSD' do + context 'when using default class parameters' do + it { is_expected.to contain_file('/etc/localtime').with(ensure: 'link', target: '/usr/share/zoneinfo/Etc/UTC') } + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) { { timezone: 'Europe/Berlin' } } + + it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) { { autoupgrade: true } } + + it { is_expected.to compile.with_all_deps } + end + + context 'when ensure => absent' do + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } + end + end # end FreeBSD + + when 'Suse' + context 'Suse' do + context 'when using default class parameters' do + case facts[:os]['release']['major'] + when '11' + it { is_expected.to contain_file('/etc/sysconfig/clock').with_ensure('file') } + it { is_expected.to contain_exec('update_timezone').with_command('zic -l Etc/UTC').with(subscribe: 'File[/etc/sysconfig/clock]') } + else + it { is_expected.not_to contain_file('/etc/sysconfig/clock') } + it { is_expected.to contain_exec('update_timezone').with_command('timedatectl set-timezone Etc/UTC').with_unless('timedatectl status | grep "Timezone:\|Time zone:" | grep -q Etc/UTC') } + end + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) { { timezone: 'Europe/Berlin' } } + + it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) { { autoupgrade: true } } + + it { is_expected.to compile.with_all_deps } + end + + context 'when ensure => absent' do + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } + end + end # end Suse + + else + pending "There are no tests for #{os} (#{facts[:os]['family']})" + end # end OS Family end end end diff --git a/spec/fixtures/hiera/hiera.yaml b/spec/fixtures/hiera/hiera.yaml new file mode 100644 index 0000000..58f410e --- /dev/null +++ b/spec/fixtures/hiera/hiera.yaml @@ -0,0 +1,7 @@ +--- +:backends: + - yaml +:hierarchy: + - test +:yaml: + :datadir: 'spec/fixtures/hiera' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c8f3151..661a512 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,8 +1,66 @@ +# This file is based on Vox Pupuli's modulesync +# https://github.com/voxpupuli/modulesync +# https://github.com/voxpupuli/modulesync_config +RSpec.configure do |c| + c.mock_with :rspec +end + require 'puppetlabs_spec_helper/module_spec_helper' -require 'pathname' +require 'rspec-puppet-facts' +require 'bundler' +include RspecPuppetFacts + +if ENV['DEBUG'] + Puppet::Util::Log.level = :debug + Puppet::Util::Log.newdestination(:console) +end + +if File.exist?(File.join(__dir__, 'default_module_facts.yml')) + facts = YAML.load(File.read(File.join(__dir__, 'default_module_facts.yml'))) + if facts + facts.each do |name, value| + add_custom_fact name.to_sym, value + end + end +end + +if Dir.exist?(File.expand_path('../../lib', __FILE__)) + require 'coveralls' + require 'simplecov' + require 'simplecov-console' + SimpleCov.formatters = [ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::Console + ] + SimpleCov.start do + track_files 'lib/**/*.rb' + add_filter '/spec' + add_filter '/vendor' + add_filter '/.vendor' + add_filter Bundler.configured_bundle_path.path + end +end -dir = Pathname.new(__FILE__).parent -# Load all shared contexts and shared examples -Dir["#{dir}/support/**/*.rb"].sort.each { |f| require f } +RSpec.configure do |c| + c.hiera_config = 'spec/fixtures/hiera/hiera.yaml' + # getting the correct facter version is tricky. We use facterdb as a source to mock facts + # see https://github.com/camptocamp/facterdb + # people might provide a specific facter version. In that case we use it. + # Otherwise we need to match the correct facter version to the used puppet version. + # as of 2019-10-31, puppet 5 ships facter 3.11 and puppet 6 ships facter 3.14 + # https://puppet.com/docs/puppet/5.5/about_agent.html + # + # The environment variable `PUPPET_VERSION` is available in our travis environment, but we cannot rely on it + # if somebody runs the tests locally. For that case we should fallback the the puppet gem version. + c.default_facter_version = if ENV['FACTERDB_FACTS_VERSION'] + ENV['FACTERDB_FACTS_VERSION'] + else + puppet_version = ENV['PUPPET_VERSION'] ? ENV['PUPPET_VERSION'] : Gem.loaded_specs['puppet'].version.to_s + Gem::Dependency.new('', puppet_version).match?('', '5') ? '3.11.0' : '3.14.0' + end -at_exit { RSpec::Puppet::Coverage.report! } + # Coverage generation + c.after(:suite) do + RSpec::Puppet::Coverage.report! + end +end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 5d1cbb9..7610623 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,20 +1,17 @@ require 'beaker-rspec' +require 'beaker-puppet' +require 'beaker/puppet_install_helper' +require 'beaker/module_install_helper' -install_puppet_on hosts +run_puppet_install_helper unless ENV['BEAKER_provision'] == 'no' RSpec.configure do |c| - module_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) - module_name = module_root.split('-').last - # Readable test descriptions c.formatter = :documentation # Configure all nodes in nodeset c.before :suite do - # Install module and dependencies - puppet_module_install(:source => module_root, :module_name => module_name) - hosts.each do |host| - on host, puppet('module', 'install', 'puppetlabs-stdlib'), :acceptable_exit_codes => [0, 1] - end + install_module + install_module_dependencies end end diff --git a/spec/support/debian.rb b/spec/support/debian.rb deleted file mode 100644 index 0cb6c82..0000000 --- a/spec/support/debian.rb +++ /dev/null @@ -1,53 +0,0 @@ -shared_examples 'Debian' do - let(:facts) do - { - :os => { - :name => 'Debian', - :family => 'Debian', - :release => { :major => '8' } - } - } - end - - describe 'when using default class parameters' do - let(:params) { {} } - - it { is_expected.to create_class('timezone') } - it { is_expected.to contain_file('/etc/timezone') } - it { is_expected.to contain_file('/etc/timezone').with_ensure('file') } - it { is_expected.to contain_file('/etc/timezone').with_content(%r{Etc/UTC}) } - it { is_expected.to contain_exec('update_timezone').with_command(%r{^dpkg-reconfigure -f noninteractive tzdata$}) } - - it do - is_expected.to contain_package('tzdata').with(:ensure => 'present', - :before => 'File[/etc/localtime]') - end - it do - is_expected.to contain_file('/etc/localtime').with(:ensure => 'link', - :target => '/usr/share/zoneinfo/Etc/UTC') - end - - context 'when timezone => "Europe/Berlin"' do - let(:params) { { :timezone => 'Europe/Berlin' } } - - it { is_expected.to contain_file('/etc/timezone').with_content(%r{^Europe/Berlin$}) } - it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } - end - - context 'when autoupgrade => true' do - let(:params) { { :autoupgrade => true } } - - it { is_expected.to contain_package('tzdata').with_ensure('latest') } - end - - context 'when ensure => absent' do - let(:params) { { :ensure => 'absent' } } - - it { is_expected.to contain_package('tzdata').with_ensure('present') } - it { is_expected.to contain_file('/etc/timezone').with_ensure('absent') } - it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } - end - - include_examples 'validate parameters' - end -end diff --git a/spec/support/freebsd.rb b/spec/support/freebsd.rb deleted file mode 100644 index 006a1a8..0000000 --- a/spec/support/freebsd.rb +++ /dev/null @@ -1,41 +0,0 @@ -shared_examples 'FreeBSD' do - let(:facts) do - { - :os => { - :family => 'FreeBSD', - :release => { :major => '9' } - } - } - end - - describe 'when using default class parameters' do - let(:params) { {} } - - it { is_expected.to create_class('timezone') } - - it do - is_expected.to contain_file('/etc/localtime').with(:ensure => 'link', - :target => '/usr/share/zoneinfo/Etc/UTC') - end - - context 'when timezone => "Europe/Berlin"' do - let(:params) { { :timezone => 'Europe/Berlin' } } - - it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } - end - - context 'when autoupgrade => true' do - let(:params) { { :autoupgrade => true } } - - it { is_expected.to compile.with_all_deps } - end - - context 'when ensure => absent' do - let(:params) { { :ensure => 'absent' } } - - it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } - end - - include_examples 'validate parameters' - end -end diff --git a/spec/support/gentoo.rb b/spec/support/gentoo.rb deleted file mode 100644 index 7f7f7f1..0000000 --- a/spec/support/gentoo.rb +++ /dev/null @@ -1,55 +0,0 @@ -shared_examples 'Gentoo' do - let(:facts) do - { - :os => { - :family => 'Gentoo', - :release => { - :full => '4.8.0', - :major => '4' - } - } - } - end - - describe 'when using default class parameters' do - let(:params) { {} } - - it { is_expected.to create_class('timezone') } - - it do - is_expected.to contain_package('sys-libs/timezone-data').with(:ensure => 'present', - :before => 'File[/etc/localtime]') - end - - it { is_expected.to contain_file('/etc/timezone').with_ensure('file') } - it { is_expected.to contain_file('/etc/timezone').with_content(%r{^Etc/UTC$}) } - it { is_expected.to contain_exec('update_timezone').with_command(%r{^emerge --config timezone-data$}) } - it do - is_expected.to contain_file('/etc/localtime').with(:ensure => 'link', - :target => '/usr/share/zoneinfo/Etc/UTC') - end - - context 'when timezone => "Europe/Berlin"' do - let(:params) { { :timezone => 'Europe/Berlin' } } - - it { is_expected.to contain_file('/etc/timezone').with_content(%r{^Europe/Berlin$}) } - it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } - end - - context 'when autoupgrade => true' do - let(:params) { { :autoupgrade => true } } - - it { is_expected.to contain_package('sys-libs/timezone-data').with_ensure('latest') } - end - - context 'when ensure => absent' do - let(:params) { { :ensure => 'absent' } } - - it { is_expected.to contain_package('sys-libs/timezone-data').with_ensure('present') } - it { is_expected.to contain_file('/etc/timezone').with_ensure('absent') } - it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } - end - - include_examples 'validate parameters' - end -end diff --git a/spec/support/redhat.rb b/spec/support/redhat.rb deleted file mode 100644 index f2ab3af..0000000 --- a/spec/support/redhat.rb +++ /dev/null @@ -1,73 +0,0 @@ -shared_examples 'RedHat' do - describe 'when using default class parameters with osfamily => RedHat and major release => 6' do - let(:params) { {} } - let(:facts) do - { - :os => { - :name => 'CentOS', - :family => 'RedHat', - :release => { :major => '6' } - } - } - end - - it { is_expected.to create_class('timezone') } - - it do - is_expected.to contain_package('tzdata').with(:ensure => 'present', - :before => 'File[/etc/localtime]') - end - - it { is_expected.to contain_file('/etc/sysconfig/clock').with_ensure('file') } - it { is_expected.to contain_file('/etc/sysconfig/clock').with_content(%r{^ZONE="Etc/UTC"$}) } - it { is_expected.not_to contain_exec('update_timezone') } - - it do - is_expected.to contain_file('/etc/localtime').with(:ensure => 'link', - :target => '/usr/share/zoneinfo/Etc/UTC') - end - - context 'when timezone => "Europe/Berlin"' do - let(:params) { { :timezone => 'Europe/Berlin' } } - - it { is_expected.to contain_file('/etc/sysconfig/clock').with_content(%r{^ZONE="Europe/Berlin"$}) } - it { is_expected.to contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } - end - - context 'when autoupgrade => true' do - let(:params) { { :autoupgrade => true } } - - it { is_expected.to contain_package('tzdata').with_ensure('latest') } - end - - context 'when ensure => absent' do - let(:params) { { :ensure => 'absent' } } - - it { is_expected.to contain_package('tzdata').with_ensure('present') } - it { is_expected.to contain_file('/etc/sysconfig/clock').with_ensure('absent') } - it { is_expected.to contain_file('/etc/localtime').with_ensure('absent') } - end - - include_examples 'validate parameters' - end - - describe 'when using default class parameters with osfamily => RedHat and major release => 7' do - let(:params) { {} } - let(:facts) do - { - :os => { - :name => 'CentOS', - :family => 'RedHat', - :release => { :major => '7' } - } - } - end - - it { is_expected.to create_class('timezone') } - it { is_expected.not_to contain_file('/etc/sysconfig/clock') } - it { is_expected.to contain_file('/etc/localtime').with_ensure('link') } - it { is_expected.to contain_exec('update_timezone').with_command('timedatectl set-timezone Etc/UTC').with_unless('timedatectl status | grep "Timezone:\|Time zone:" | grep -q Etc/UTC') } - - include_examples 'validate parameters' - end -end diff --git a/spec/support/validate_params.rb b/spec/support/validate_params.rb deleted file mode 100644 index 0e12d8d..0000000 --- a/spec/support/validate_params.rb +++ /dev/null @@ -1,20 +0,0 @@ -shared_examples_for 'validate parameters' do - [ - 'autoupgrade' - ].each do |param| - context "with #{param} => 'foo'" do - let(:facts) do - { - :os => { - :name => 'Debian', - :family => 'Debian', - :release => { :major => 8, :full => 8 } - } - } - end - let(:params) { { param.to_sym => 'foo' } } - - it { expect { is_expected.to create_class('timezone') }.to raise_error(Puppet::Error, %r{expects a Boolean value}) } - end - end -end diff --git a/tests/init.pp b/tests/init.pp deleted file mode 100644 index 1884b2d..0000000 --- a/tests/init.pp +++ /dev/null @@ -1 +0,0 @@ -include ::timezone