diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..12ed4ff --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,6 @@ +FROM puppet/pdk:latest + +# [Optional] Uncomment this section to install additional packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..f1a55dc --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,23 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/puppet +{ + "name": "Puppet Development Kit (Community)", + "dockerFile": "Dockerfile", + + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.shell.linux": "/bin/bash" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "puppet.puppet-vscode", + "rebornix.Ruby" + ] + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "pdk --version", +} diff --git a/.fixtures.yml b/.fixtures.yml index 6d286b9..c88d609 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,3 +1,6 @@ fixtures: + forge_modules: + stdlib: + repo: "puppetlabs/stdlib" symlinks: forge_server: "#{source_dir}" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9032a01 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.rb eol=lf +*.erb eol=lf +*.pp eol=lf +*.sh eol=lf +*.epp eol=lf diff --git a/.gitignore b/.gitignore index d474f89..988dcbb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,28 @@ -*.lock -.gems/ -.bundle/ -.librarian/ -.tmp/ -spec/fixtures/ -*.swp -.vagrant/ -.kitchen/ -.kitchen.local.yml -pkg/ -reports/ -/.project +.git/ +.*.sw[op] +.metadata +.yardoc +.yardwarns +*.iml +/.bundle/ +/.idea/ +/.vagrant/ +/coverage/ +/bin/ +/doc/ +/Gemfile.local +/Gemfile.lock +/junit/ +/log/ +/pkg/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/ +/tmp/ +/vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml +/spec/fixtures/litmus_inventory.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..6d5e786 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,53 @@ +--- +stages: + - syntax + - unit + +default: + cache: + paths: + - vendor/bundle + + before_script: &before_script + - bundle -v + - rm Gemfile.lock || true + - "# Update system gems if requested. This is useful to temporarily workaround troubles in the test runner" + - "# Set `rubygems_version` in the .sync.yml to set a value" + - "# Ignore exit code of SIGPIPE'd yes to not fail with shell's pipefail set" + - '[ -z "$RUBYGEMS_VERSION" ] || (yes || true) | gem update --system $RUBYGEMS_VERSION' + - gem --version + - bundle -v + - bundle install --without system_tests --path vendor/bundle --jobs $(nproc) + +validate lint check rubocop-Ruby 2.5.7-Puppet ~> 6: + stage: syntax + image: ruby:2.5.7 + script: + - bundle exec rake validate lint check rubocop + variables: + PUPPET_GEM_VERSION: '~> 6' + +parallel_spec-Ruby 2.5.7-Puppet ~> 6: + stage: unit + image: ruby:2.5.7 + script: + - bundle exec rake parallel_spec + variables: + PUPPET_GEM_VERSION: '~> 6' + +validate lint check rubocop-Ruby 2.7.2-Puppet ~> 7: + stage: syntax + image: ruby:2.7.2 + script: + - bundle exec rake validate lint check rubocop + variables: + PUPPET_GEM_VERSION: '~> 7' + +parallel_spec-Ruby 2.7.2-Puppet ~> 7: + stage: unit + image: ruby:2.7.2 + script: + - bundle exec rake parallel_spec + variables: + PUPPET_GEM_VERSION: '~> 7' + diff --git a/.pdkignore b/.pdkignore new file mode 100644 index 0000000..c538bea --- /dev/null +++ b/.pdkignore @@ -0,0 +1,47 @@ +.git/ +.*.sw[op] +.metadata +.yardoc +.yardwarns +*.iml +/.bundle/ +/.idea/ +/.vagrant/ +/coverage/ +/bin/ +/doc/ +/Gemfile.local +/Gemfile.lock +/junit/ +/log/ +/pkg/ +/spec/fixtures/manifests/ +/spec/fixtures/modules/ +/tmp/ +/vendor/ +/convert_report.txt +/update_report.txt +.DS_Store +.project +.envrc +/inventory.yaml +/spec/fixtures/litmus_inventory.yaml +/appveyor.yml +/.editorconfig +/.fixtures.yml +/Gemfile +/.gitattributes +/.gitignore +/.gitlab-ci.yml +/.pdkignore +/.puppet-lint.rc +/Rakefile +/rakelib/ +/.rspec +/.rubocop.yml +/.travis.yml +/.yardopts +/spec/ +/.vscode/ +/.sync.yml +/.devcontainer/ diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 0000000..cc96ece --- /dev/null +++ b/.puppet-lint.rc @@ -0,0 +1 @@ +--relative diff --git a/.rspec b/.rspec index 928109b..16f9cdb 100644 --- a/.rspec +++ b/.rspec @@ -1,3 +1,2 @@ ---format RspecJunitFormatter ---out reports/rspec.xml ---format documentation \ No newline at end of file +--color +--format documentation diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..8f782e7 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,519 @@ +--- +require: +- rubocop-performance +- rubocop-rspec +AllCops: + DisplayCopNames: true + TargetRubyVersion: '2.4' + Include: + - "**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - "**/Gemfile" + - "**/Rakefile" + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* + - "**/Puppetfile" + - "**/Vagrantfile" + - "**/Guardfile" +Layout/LineLength: + Description: People have wide screens, use them. + Max: 200 +RSpec/BeforeAfterAll: + Description: Beware of using after(:all) as it may cause state to leak between tests. + A necessary evil in acceptance testing. + Exclude: + - spec/acceptance/**/*.rb +RSpec/HookArgument: + Description: Prefer explicit :each argument, matching existing module's style + EnforcedStyle: each +RSpec/DescribeSymbol: + Exclude: + - spec/unit/facter/**/*.rb +Style/BlockDelimiters: + Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to + be consistent then. + EnforcedStyle: braces_for_chaining +Style/ClassAndModuleChildren: + Description: Compact style reduces the required amount of indentation. + EnforcedStyle: compact +Style/EmptyElse: + Description: Enforce against empty else clauses, but allow `nil` for clarity. + EnforcedStyle: empty +Style/FormatString: + Description: Following the main puppet project's style, prefer the % format format. + EnforcedStyle: percent +Style/FormatStringToken: + Description: Following the main puppet project's style, prefer the simpler template + tokens over annotated ones. + EnforcedStyle: template +Style/Lambda: + Description: Prefer the keyword for easier discoverability. + EnforcedStyle: literal +Style/RegexpLiteral: + Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 + EnforcedStyle: percent_r +Style/TernaryParentheses: + Description: Checks for use of parentheses around ternary conditions. Enforce parentheses + on complex expressions for better readability, but seriously consider breaking + it up. + EnforcedStyle: require_parentheses_when_complex +Style/TrailingCommaInArguments: + Description: Prefer always trailing comma on multiline argument lists. This makes + diffs, and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/TrailingCommaInArrayLiteral: + Description: Prefer always trailing comma on multiline literals. This makes diffs, + and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/SymbolArray: + Description: Using percent style obscures symbolic intent of array's contents. + EnforcedStyle: brackets +RSpec/MessageSpies: + EnforcedStyle: receive +Style/Documentation: + Exclude: + - lib/puppet/parser/functions/**/* + - spec/**/* +Style/WordArray: + EnforcedStyle: brackets +Performance/AncestorsInclude: + Enabled: true +Performance/BigDecimalWithNumericArgument: + Enabled: true +Performance/BlockGivenWithExplicitBlock: + Enabled: true +Performance/CaseWhenSplat: + Enabled: true +Performance/ConstantRegexp: + Enabled: true +Performance/MethodObjectAsBlock: + Enabled: true +Performance/RedundantSortBlock: + Enabled: true +Performance/RedundantStringChars: + Enabled: true +Performance/ReverseFirst: + Enabled: true +Performance/SortReverse: + Enabled: true +Performance/Squeeze: + Enabled: true +Performance/StringInclude: + Enabled: true +Performance/Sum: + Enabled: true +Style/CollectionMethods: + Enabled: true +Style/MethodCalledOnDoEndBlock: + Enabled: true +Style/StringMethods: + Enabled: true +Bundler/InsecureProtocolSource: + Enabled: false +Gemspec/DuplicatedAssignment: + Enabled: false +Gemspec/OrderedDependencies: + Enabled: false +Gemspec/RequiredRubyVersion: + Enabled: false +Gemspec/RubyVersionGlobalsUsage: + Enabled: false +Layout/ArgumentAlignment: + Enabled: false +Layout/BeginEndAlignment: + Enabled: false +Layout/ClosingHeredocIndentation: + Enabled: false +Layout/EmptyComment: + Enabled: false +Layout/EmptyLineAfterGuardClause: + Enabled: false +Layout/EmptyLinesAroundArguments: + Enabled: false +Layout/EmptyLinesAroundAttributeAccessor: + Enabled: false +Layout/EndOfLine: + Enabled: false +Layout/FirstArgumentIndentation: + Enabled: false +Layout/HashAlignment: + Enabled: false +Layout/HeredocIndentation: + Enabled: false +Layout/LeadingEmptyLines: + Enabled: false +Layout/SpaceAroundMethodCallOperator: + Enabled: false +Layout/SpaceInsideArrayLiteralBrackets: + Enabled: false +Layout/SpaceInsideReferenceBrackets: + Enabled: false +Lint/BigDecimalNew: + Enabled: false +Lint/BooleanSymbol: + Enabled: false +Lint/ConstantDefinitionInBlock: + Enabled: false +Lint/DeprecatedOpenSSLConstant: + Enabled: false +Lint/DisjunctiveAssignmentInConstructor: + Enabled: false +Lint/DuplicateElsifCondition: + Enabled: false +Lint/DuplicateRequire: + Enabled: false +Lint/DuplicateRescueException: + Enabled: false +Lint/EmptyConditionalBody: + Enabled: false +Lint/EmptyFile: + Enabled: false +Lint/ErbNewArguments: + Enabled: false +Lint/FloatComparison: + Enabled: false +Lint/HashCompareByIdentity: + Enabled: false +Lint/IdentityComparison: + Enabled: false +Lint/InterpolationCheck: + Enabled: false +Lint/MissingCopEnableDirective: + Enabled: false +Lint/MixedRegexpCaptureTypes: + Enabled: false +Lint/NestedPercentLiteral: + Enabled: false +Lint/NonDeterministicRequireOrder: + Enabled: false +Lint/OrderedMagicComments: + Enabled: false +Lint/OutOfRangeRegexpRef: + Enabled: false +Lint/RaiseException: + Enabled: false +Lint/RedundantCopEnableDirective: + Enabled: false +Lint/RedundantRequireStatement: + Enabled: false +Lint/RedundantSafeNavigation: + Enabled: false +Lint/RedundantWithIndex: + Enabled: false +Lint/RedundantWithObject: + Enabled: false +Lint/RegexpAsCondition: + Enabled: false +Lint/ReturnInVoidContext: + Enabled: false +Lint/SafeNavigationConsistency: + Enabled: false +Lint/SafeNavigationWithEmpty: + Enabled: false +Lint/SelfAssignment: + Enabled: false +Lint/SendWithMixinArgument: + Enabled: false +Lint/ShadowedArgument: + Enabled: false +Lint/StructNewOverride: + Enabled: false +Lint/ToJSON: + Enabled: false +Lint/TopLevelReturnWithArgument: + Enabled: false +Lint/TrailingCommaInAttributeDeclaration: + Enabled: false +Lint/UnreachableLoop: + Enabled: false +Lint/UriEscapeUnescape: + Enabled: false +Lint/UriRegexp: + Enabled: false +Lint/UselessMethodDefinition: + Enabled: false +Lint/UselessTimes: + Enabled: false +Metrics/AbcSize: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/BlockNesting: + Enabled: false +Metrics/ClassLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Metrics/ParameterLists: + Enabled: false +Metrics/PerceivedComplexity: + Enabled: false +Migration/DepartmentName: + Enabled: false +Naming/AccessorMethodName: + Enabled: false +Naming/BlockParameterName: + Enabled: false +Naming/HeredocDelimiterCase: + Enabled: false +Naming/HeredocDelimiterNaming: + Enabled: false +Naming/MemoizedInstanceVariableName: + Enabled: false +Naming/MethodParameterName: + Enabled: false +Naming/RescuedExceptionsVariableName: + Enabled: false +Naming/VariableNumber: + Enabled: false +Performance/BindCall: + Enabled: false +Performance/DeletePrefix: + Enabled: false +Performance/DeleteSuffix: + Enabled: false +Performance/InefficientHashSearch: + Enabled: false +Performance/UnfreezeString: + Enabled: false +Performance/UriDefaultParser: + Enabled: false +RSpec/Be: + Enabled: false +RSpec/Capybara/CurrentPathExpectation: + Enabled: false +RSpec/Capybara/FeatureMethods: + Enabled: false +RSpec/Capybara/VisibilityMatcher: + Enabled: false +RSpec/ContextMethod: + Enabled: false +RSpec/ContextWording: + Enabled: false +RSpec/DescribeClass: + Enabled: false +RSpec/EmptyHook: + Enabled: false +RSpec/EmptyLineAfterExample: + Enabled: false +RSpec/EmptyLineAfterExampleGroup: + Enabled: false +RSpec/EmptyLineAfterHook: + Enabled: false +RSpec/ExampleLength: + Enabled: false +RSpec/ExampleWithoutDescription: + Enabled: false +RSpec/ExpectChange: + Enabled: false +RSpec/ExpectInHook: + Enabled: false +RSpec/FactoryBot/AttributeDefinedStatically: + Enabled: false +RSpec/FactoryBot/CreateList: + Enabled: false +RSpec/FactoryBot/FactoryClassName: + Enabled: false +RSpec/HooksBeforeExamples: + Enabled: false +RSpec/ImplicitBlockExpectation: + Enabled: false +RSpec/ImplicitSubject: + Enabled: false +RSpec/LeakyConstantDeclaration: + Enabled: false +RSpec/LetBeforeExamples: + Enabled: false +RSpec/MissingExampleGroupArgument: + Enabled: false +RSpec/MultipleExpectations: + Enabled: false +RSpec/MultipleMemoizedHelpers: + Enabled: false +RSpec/MultipleSubjects: + Enabled: false +RSpec/NestedGroups: + Enabled: false +RSpec/PredicateMatcher: + Enabled: false +RSpec/ReceiveCounts: + Enabled: false +RSpec/ReceiveNever: + Enabled: false +RSpec/RepeatedExampleGroupBody: + Enabled: false +RSpec/RepeatedExampleGroupDescription: + Enabled: false +RSpec/RepeatedIncludeExample: + Enabled: false +RSpec/ReturnFromStub: + Enabled: false +RSpec/SharedExamples: + Enabled: false +RSpec/StubbedMock: + Enabled: false +RSpec/UnspecifiedException: + Enabled: false +RSpec/VariableDefinition: + Enabled: false +RSpec/VoidExpect: + Enabled: false +RSpec/Yield: + Enabled: false +Security/Open: + Enabled: false +Style/AccessModifierDeclarations: + Enabled: false +Style/AccessorGrouping: + Enabled: false +Style/AsciiComments: + Enabled: false +Style/BisectedAttrAccessor: + Enabled: false +Style/CaseLikeIf: + Enabled: false +Style/ClassEqualityComparison: + Enabled: false +Style/ColonMethodDefinition: + Enabled: false +Style/CombinableLoops: + Enabled: false +Style/CommentedKeyword: + Enabled: false +Style/Dir: + Enabled: false +Style/DoubleCopDisableDirective: + Enabled: false +Style/EmptyBlockParameter: + Enabled: false +Style/EmptyLambdaParameter: + Enabled: false +Style/Encoding: + Enabled: false +Style/EvalWithLocation: + Enabled: false +Style/ExpandPathArguments: + Enabled: false +Style/ExplicitBlockArgument: + Enabled: false +Style/ExponentialNotation: + Enabled: false +Style/FloatDivision: + Enabled: false +Style/FrozenStringLiteralComment: + Enabled: false +Style/GlobalStdStream: + Enabled: false +Style/HashAsLastArrayItem: + Enabled: false +Style/HashLikeCase: + Enabled: false +Style/HashTransformKeys: + Enabled: false +Style/HashTransformValues: + Enabled: false +Style/IfUnlessModifier: + Enabled: false +Style/KeywordParametersOrder: + Enabled: false +Style/MinMax: + Enabled: false +Style/MixinUsage: + Enabled: false +Style/MultilineWhenThen: + Enabled: false +Style/NegatedUnless: + Enabled: false +Style/NumericPredicate: + Enabled: false +Style/OptionalBooleanParameter: + Enabled: false +Style/OrAssignment: + Enabled: false +Style/RandomWithOffset: + Enabled: false +Style/RedundantAssignment: + Enabled: false +Style/RedundantCondition: + Enabled: false +Style/RedundantConditional: + Enabled: false +Style/RedundantFetchBlock: + Enabled: false +Style/RedundantFileExtensionInRequire: + Enabled: false +Style/RedundantRegexpCharacterClass: + Enabled: false +Style/RedundantRegexpEscape: + Enabled: false +Style/RedundantSelfAssignment: + Enabled: false +Style/RedundantSort: + Enabled: false +Style/RescueStandardError: + Enabled: false +Style/SingleArgumentDig: + Enabled: false +Style/SlicingWithRange: + Enabled: false +Style/SoleNestedConditional: + Enabled: false +Style/StderrPuts: + Enabled: false +Style/StringConcatenation: + Enabled: false +Style/Strip: + Enabled: false +Style/SymbolProc: + Enabled: false +Style/TrailingBodyOnClass: + Enabled: false +Style/TrailingBodyOnMethodDefinition: + Enabled: false +Style/TrailingBodyOnModule: + Enabled: false +Style/TrailingCommaInHashLiteral: + Enabled: false +Style/TrailingMethodEndStatement: + Enabled: false +Style/UnpackFirst: + Enabled: false +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Performance/CollectionLiteralInLoop: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NilLambda: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/SwapValues: + Enabled: false diff --git a/.ruby-version b/.ruby-version index 399088b..ecd7ee5 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1.6 +2.5.8 diff --git a/.sync.yml b/.sync.yml new file mode 100644 index 0000000..8c2c98e --- /dev/null +++ b/.sync.yml @@ -0,0 +1,8 @@ +# This file can be used to customize the files managed by PDK. +# +# See https://github.com/puppetlabs/pdk-templates/blob/main/README.md +# for more information. +# +# See https://github.com/puppetlabs/pdk-templates/blob/main/config_defaults.yml +# for the default values. +--- {} diff --git a/.travis.yml b/.travis.yml index 04844d1..444e17a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,45 @@ -sudo: false +--- +os: linux +dist: xenial language: ruby -bundler_args: --without kitchen +cache: bundler +before_install: + - bundle -v + - rm -f Gemfile.lock + - "# Update system gems if requested. This is useful to temporarily workaround troubles in the test runner" + - "# See https://github.com/puppetlabs/pdk-templates/commit/705154d5c437796b821691b707156e1b056d244f for an example of how this was used" + - "# Ignore exit code of SIGPIPE'd yes to not fail with shell's pipefail set" + - '[ -z "$RUBYGEMS_VERSION" ] || (yes || true) | gem update --system $RUBYGEMS_VERSION' + - gem --version + - bundle -v script: - - bundle exec rake lint - - bundle exec rake validate - - bundle exec rake spec -matrix: + - 'bundle exec rake $CHECK' +bundler_args: --without system_tests +rvm: + - 2.5.7 +stages: + - static + - spec + - acceptance + - + if: tag =~ ^v\d + name: deploy +jobs: + fast_finish: true include: - - rvm: 2.4.10 - env: PUPPET_VERSION="~> 5.0" - - rvm: 2.5.1 - env: PUPPET_VERSION="~> 6.0" -deploy: - provider: puppetforge - on: - tags: true - branch: master - condition: "$DEPLOY = true" - user: - secure: "STo4ZjU5uJNB68QAHzVCKi2PKSMZ/SCP8+RPZOJBh7s1YMkAINu0cbvKTvPEqgjlZ45KVJc8Nh8AzdVS6khzBxEwU/60C9ms15mBE+f+AOBPKgV55pKk4UxCCAlodWW9alBeuBylxpuKqO5o4xnOQtXdkse3u6IBduXO/zWyjso=" - password: - secure: "ihUcTHgymF+D4AkzFDcrNpJOR388BkY/2p6cKa85ottnEZCnIalcQXOAYQ54vpB3ME6bwE5C/chPf3opfcXMwbblnkEbuScTlRZ7ZdHO3xyso3Om71j2S2EiLdZRHpmei06/kCvAHlpCesue788R2eaf+Olm/c7807Jod/aHjJQ=" + - + env: CHECK="validate lint check rubocop" + stage: static + - + env: PUPPET_GEM_VERSION="~> 6.0" CHECK=parallel_spec + rvm: 2.5.7 + stage: spec + - + env: DEPLOY_TO_FORGE=yes + stage: deploy +branches: + only: + - main + - /^v\d/ +notifications: + email: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..2f1e4f7 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "puppet.puppet-vscode", + "rebornix.Ruby" + ] +} diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..29c933b --- /dev/null +++ b/.yardopts @@ -0,0 +1 @@ +--markup markdown diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9ee7369 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## Release 0.5.1 + +**Features** + +**Bugfixes** + +**Known Issues** diff --git a/Gemfile b/Gemfile index 16bc383..a167b88 100644 --- a/Gemfile +++ b/Gemfile @@ -1,28 +1,62 @@ -source 'https://rubygems.org' +source ENV['GEM_SOURCE'] || 'https://rubygems.org' -puppetversion = ENV.key?('PUPPET_VERSION') ? ENV['PUPPET_VERSION'] : '>=3.7.3' +def location_for(place_or_version, fake_version = nil) + git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?} + file_url_regex = %r{\Afile:\/\/(?.*)} -group :rspec, :kitchen do - gem 'librarian-puppet' - gem 'puppet', puppetversion - gem 'rspec_junit_formatter' - gem 'puppet-blacksmith' + if place_or_version && (git_url = place_or_version.match(git_url_regex)) + [fake_version, { git: git_url[:url], branch: git_url[:branch], require: false }].compact + elsif place_or_version && (file_url = place_or_version.match(file_url_regex)) + ['>= 0', { path: File.expand_path(file_url[:path]), require: false }] + else + [place_or_version, { require: false }] + end end -group :rspec do - gem 'puppetlabs_spec_helper', '~> 1.1' - gem 'puppet-lint', '< 1.1.0' - gem 'facter', '~> 2.5' - gem 'rspec-puppet', :git => 'https://github.com/rodjek/rspec-puppet.git' - gem 'rspec-puppet-facts', :require => false - gem 'puppet-syntax' - gem 'metadata-json-lint', '~> 1.1.0' +ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments +minor_version = ruby_version_segments[0..1].join('.') + +group :development do + gem "json", '= 2.0.4', require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.3.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 2.8.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "puppet-module-posix-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] + gem "puppet-module-posix-dev-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] + gem "puppet-module-win-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "puppet-module-win-dev-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] +end +group :system_tests do + gem "puppet-module-posix-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby] + gem "puppet-module-win-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:mswin, :mingw, :x64_mingw] +end + +puppet_version = ENV['PUPPET_GEM_VERSION'] +facter_version = ENV['FACTER_GEM_VERSION'] +hiera_version = ENV['HIERA_GEM_VERSION'] + +gems = {} + +gems['puppet'] = location_for(puppet_version) + +# If facter or hiera versions have been specified via the environment +# variables + +gems['facter'] = location_for(facter_version) if facter_version +gems['hiera'] = location_for(hiera_version) if hiera_version + +gems.each do |gem_name, gem_params| + gem gem_name, *gem_params end -group :kitchen do - gem 'test-kitchen', '~> 1.16.0' - gem 'kitchen-docker' - gem 'kitchen-puppet', :git => 'https://github.com/neillturner/kitchen-puppet.git', :tag => '3.1.1' - gem 'kitchen-vagrant' - gem 'vagrant-wrapper' +# Evaluate Gemfile.local and ~/.gemfile if they exist +extra_gemfiles = [ + "#{__FILE__}.local", + File.join(Dir.home, '.gemfile'), +] + +extra_gemfiles.each do |gemfile| + if File.file?(gemfile) && File.readable?(gemfile) + eval(File.read(gemfile), binding) + end end +# vim: syntax=ruby diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 0000000..58a9633 --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,278 @@ +# Reference + + + +## Table of Contents + +### Classes + +* [`forge_server`](#forge_server): == Class: forge_server A Puppet module to manage the Puppet Forge Server service === Authors Johan Lyheden === +* [`forge_server::config`](#forge_serverconfig): == Class: forge_server::config Manages configuration files +* [`forge_server::files`](#forge_serverfiles): == Class: forge_server::files Directories needed by puppet-forge-server +* [`forge_server::package`](#forge_serverpackage): == Class: forge_server::package Installs puppet-forge-server +* [`forge_server::service`](#forge_serverservice): == Class: forge_server::service Manages the puppet-forge-server daemon +* [`forge_server::user`](#forge_serveruser): == Class: forge_server::user Manages the forge user + +### Defined types + +* [`forge_server::mkdir`](#forge_servermkdir): == Define: forge_server::mkdir Helper define to create parent folders + +## Classes + +### `forge_server` + +== Class: forge_server + +A Puppet module to manage the Puppet Forge Server service + +=== Authors + +Johan Lyheden + +=== Copyright + +Copyright 2014 North Development AB + +#### Examples + +##### + +```puppet + +class { '::forge_server': + scl => 'ruby193' +} +``` + +#### Parameters + +The following parameters are available in the `forge_server` class: + +* [`package`](#package) +* [`scl`](#scl) +* [`scl_install_timeout`](#scl_install_timeout) +* [`scl_install_retries`](#scl_install_retries) +* [`service_enable`](#service_enable) +* [`service_ensure`](#service_ensure) +* [`service_refresh`](#service_refresh) +* [`pidfile`](#pidfile) +* [`port`](#port) +* [`bind_host`](#bind_host) +* [`daemonize`](#daemonize) +* [`module_directory`](#module_directory) +* [`http_proxy`](#http_proxy) +* [`proxy`](#proxy) +* [`cache_basedir`](#cache_basedir) +* [`log_dir`](#log_dir) +* [`debug`](#debug) +* [`forge_server_script`](#forge_server_script) +* [`user`](#user) +* [`user_homedir`](#user_homedir) +* [`provider`](#provider) + +##### `package` + +Data type: `String[1]` + +Optional override of package name + +Default value: `'puppet-forge-server'` + +##### `scl` + +Data type: `Optional` + +Name of ruby scl environment, leave undef to use system ruby + +Default value: ``undef`` + +##### `scl_install_timeout` + +Data type: `Integer` + +If using ruby scl, the timeout in seconds to allow the gem installation to run + +Default value: `300` + +##### `scl_install_retries` + +Data type: `Integer` + +If using ruby scl, the number of retries allowed if gem installation fails + +Default value: `1` + +##### `service_enable` + +Data type: `Boolean` + +Boolean if service should be enabled on boot + +Default value: ``true`` + +##### `service_ensure` + +Data type: `Enum['running', 'stopped']` + +Service ensure state + +Default value: `'running'` + +##### `service_refresh` + +Data type: `Boolean` + +Boolean if config changes and package changes should trigger service restart + +Default value: ``true`` + +##### `pidfile` + +Data type: `Stdlib::UnixPath` + +Path to pidfile + +Default value: `'/var/run/puppet-forge-server/forge-server.pid'` + +##### `port` + +Data type: `Integer` + +Port to bind to + +Default value: `8080` + +##### `bind_host` + +Data type: `Stdlib::Host` + +IP or host to bind to + +Default value: `'127.0.0.1'` + +##### `daemonize` + +Data type: `Boolean` + +Boolean if should be daemonized + +Default value: ``true`` + +##### `module_directory` + +Data type: `Variant[Array[Stdlib::Unixpath], Stdlib::Unixpath]` + +Directory of modules to serve, can be an array of directories + +Default value: `'/var/lib/puppet-forge-server/modules'` + +##### `http_proxy` + +Data type: `Optional` + +Use proxyserver for http(s) connections + +Default value: ``undef`` + +##### `proxy` + +Data type: `Optional` + +Proxy requests to this upstream forge url + +Default value: ``undef`` + +##### `cache_basedir` + +Data type: `Stdlib::Unixpath` + +Path where to store proxied / cached modules + +Default value: `'/var/lib/puppet-forge-server/cache'` + +##### `log_dir` + +Data type: `Stdlib::Unixpath` + +Path to log directory + +Default value: `'/var/log/puppet-forge-server'` + +##### `debug` + +Data type: `Boolean` + +Boolean to toggle debug + +Default value: ``false`` + +##### `forge_server_script` + +Data type: `String[1]` + +Name of the script which runs the forge server, depending on ruby version installed + +Default value: `'puppet-forge-server.ruby2.1'` + +##### `user` + +Data type: `String[1]` + +Name of the system user for forge-server + +Default value: `'forge'` + +##### `user_homedir` + +Data type: `Stdlib::Unixpath` + +Path to the system users home dir + +Default value: `'/home/forge'` + +##### `provider` + +Data type: `Enum['gem', 'puppet_gem']` + +Whether to use system ruby or puppet ruby + +Default value: `'gem'` + +### `forge_server::config` + +== Class: forge_server::config + +Manages configuration files + +### `forge_server::files` + +== Class: forge_server::files + +Directories needed by puppet-forge-server + +### `forge_server::package` + +== Class: forge_server::package + +Installs puppet-forge-server + +### `forge_server::service` + +== Class: forge_server::service + +Manages the puppet-forge-server daemon + +### `forge_server::user` + +== Class: forge_server::user + +Manages the forge user + +## Defined types + +### `forge_server::mkdir` + +== Define: forge_server::mkdir + +Helper define to create parent folders + diff --git a/Rakefile b/Rakefile index f34a3f6..2906c15 100644 --- a/Rakefile +++ b/Rakefile @@ -1,53 +1,88 @@ -require 'rubygems' +# frozen_string_literal: true + +require 'bundler' +require 'puppet_litmus/rake_tasks' if Bundler.rubygems.find_name('puppet_litmus').any? require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' require 'puppet-syntax/tasks/puppet-syntax' -require 'puppet_blacksmith/rake_tasks' -require 'bundler' -require 'rake/clean' - -exclude_paths = [ - "pkg/**/*", - "vendor/**/*", - "spec/**/*", - "test/**/*" -] - -CLEAN.include('spec/fixtures/') -CLOBBER.include('.tmp', '.librarian', 'Puppetfile.lock', 'spec/fixtures/modules') - -PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" -PuppetLint.configuration.send("disable_80chars") -PuppetLint.configuration.send("disable_autoloader_layout") -PuppetLint.configuration.send("disable_quoted_booleans") -PuppetLint.configuration.ignore_paths = exclude_paths -PuppetSyntax.exclude_paths = exclude_paths - -task :librarian_spec_prep do - sh "librarian-puppet install --path spec/fixtures/modules" +require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? +require 'github_changelog_generator/task' if Bundler.rubygems.find_name('github_changelog_generator').any? +require 'puppet-strings/tasks' if Bundler.rubygems.find_name('puppet-strings').any? + +def changelog_user + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = nil || JSON.load(File.read('metadata.json'))['author'] + raise "unable to find the changelog_user in .sync.yml, or the author in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator user:#{returnVal}" + returnVal end -task :spec_prep => :librarian_spec_prep -task :validate => :syntax -task :default => [:spec, :lint] +def changelog_project + return unless Rake.application.top_level_tasks.include? "changelog" + + returnVal = nil + returnVal ||= begin + metadata_source = JSON.load(File.read('metadata.json'))['source'] + metadata_source_match = metadata_source && metadata_source.match(%r{.*\/([^\/]*?)(?:\.git)?\Z}) + + metadata_source_match && metadata_source_match[1] + end -desc "Run integration tests" -task :integration do - sh "kitchen test all --destroy=always -c" + raise "unable to find the changelog_project in .sync.yml or calculate it from the source in metadata.json" if returnVal.nil? + + puts "GitHubChangelogGenerator project:#{returnVal}" + returnVal +end + +def changelog_future_release + return unless Rake.application.top_level_tasks.include? "changelog" + returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version'] + raise "unable to find the future_release (version) in metadata.json" if returnVal.nil? + puts "GitHubChangelogGenerator future_release:#{returnVal}" + returnVal end -desc "Set patch version in metadata.json based on env var TRAVIS_BUILD_NUMBER" -task :set_travis_version do - require 'json' - travis_build_number = ENV['TRAVIS_BUILD_NUMBER'] - metadata_json = File.read('metadata.json') - data_hash = JSON.parse(metadata_json) - version = data_hash["version"] - new_version = "#{version.split(".")[0,2].join(".")}.#{travis_build_number}" - data_hash["version"] = new_version - File.open('metadata.json', 'w') do |f| - f.write(JSON.pretty_generate(data_hash)) +PuppetLint.configuration.send('disable_relative') + +if Bundler.rubygems.find_name('github_changelog_generator').any? + GitHubChangelogGenerator::RakeTask.new :changelog do |config| + raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil? + config.user = "#{changelog_user}" + config.project = "#{changelog_project}" + config.future_release = "#{changelog_future_release}" + config.exclude_labels = ['maintenance'] + config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)." + config.add_pr_wo_labels = true + config.issues = false + config.merge_prefix = "### UNCATEGORIZED PRS; LABEL THEM ON GITHUB" + config.configure_sections = { + "Changed" => { + "prefix" => "### Changed", + "labels" => ["backwards-incompatible"], + }, + "Added" => { + "prefix" => "### Added", + "labels" => ["enhancement", "feature"], + }, + "Fixed" => { + "prefix" => "### Fixed", + "labels" => ["bug", "documentation", "bugfix"], + }, + } + end +else + desc 'Generate a Changelog from GitHub' + task :changelog do + raise < 1.15' + condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0')" +EOM end - puts "Travis build number: #{travis_build_number}" - puts "New version: #{new_version}" end + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..a70c01e --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,49 @@ +--- +version: 1.1.x.{build} +skip_branch_with_pr: true +branches: + only: + - main + - release +skip_commits: + message: /^\(?doc\)?.*/ +clone_depth: 10 +init: + - SET + - 'mkdir C:\ProgramData\PuppetLabs\code && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\facter && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\hiera && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\puppet\var && exit 0' +environment: + matrix: + - + RUBY_VERSION: 25-x64 + CHECK: validate lint check rubocop + - + PUPPET_GEM_VERSION: ~> 6.0 + RUBY_VERSION: 25 + CHECK: parallel_spec + - + PUPPET_GEM_VERSION: ~> 6.0 + RUBY_VERSION: 25-x64 + CHECK: parallel_spec +matrix: + fast_finish: true +install: + - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% + - bundle install --jobs 4 --retry 2 --without system_tests + - type Gemfile.lock +build: off +test_script: + - bundle exec puppet -V + - ruby -v + - gem -v + - bundle -v + - bundle exec rake %CHECK% +notifications: + - provider: Email + to: + - nobody@nowhere.com + on_build_success: false + on_build_failure: false + on_build_status_changed: false diff --git a/data/common.yaml b/data/common.yaml new file mode 100644 index 0000000..2fbf0ff --- /dev/null +++ b/data/common.yaml @@ -0,0 +1 @@ +--- {} diff --git a/tests/init.pp b/examples/init.pp similarity index 100% rename from tests/init.pp rename to examples/init.pp diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000..545fff3 --- /dev/null +++ b/hiera.yaml @@ -0,0 +1,21 @@ +--- +version: 5 + +defaults: # Used for any hierarchy level that omits these keys. + datadir: data # This path is relative to hiera.yaml's directory. + data_hash: yaml_data # Use the built-in YAML backend. + +hierarchy: + - name: "osfamily/major release" + paths: + # Used to distinguish between Debian and Ubuntu + - "os/%{facts.os.name}/%{facts.os.release.major}.yaml" + - "os/%{facts.os.family}/%{facts.os.release.major}.yaml" + # Used for Solaris + - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml" + - name: "osfamily" + paths: + - "os/%{facts.os.name}.yaml" + - "os/%{facts.os.family}.yaml" + - name: 'common' + path: 'common.yaml' diff --git a/manifests/config.pp b/manifests/config.pp index da55ac0..c5c38c6 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -5,64 +5,64 @@ class forge_server::config { # Scope config variables for templates - $user = $::forge_server::user - $pidfile = $::forge_server::pidfile - $pid_dir = dirname($::forge_server::pidfile) - $port = $::forge_server::port - $bind_host = $::forge_server::bind_host - $daemonize = $::forge_server::daemonize - $module_directory = $::forge_server::module_directory - $http_proxy = $::forge_server::http_proxy - $proxy = $::forge_server::proxy - $cache_basedir = $::forge_server::cache_basedir - $log_dir = $::forge_server::log_dir - $debug = $::forge_server::debug - $scl = $::forge_server::scl - $provider = $::forge_server::provider - $forge_server_script = $::forge_server::forge_server_script + $user = $forge_server::user + $pidfile = $forge_server::pidfile + $pid_dir = dirname($forge_server::pidfile) + $port = $forge_server::port + $bind_host = $forge_server::bind_host + $daemonize = $forge_server::daemonize + $module_directory = $forge_server::module_directory + $http_proxy = $forge_server::http_proxy + $proxy = $forge_server::proxy + $cache_basedir = $forge_server::cache_basedir + $log_dir = $forge_server::log_dir + $debug = $forge_server::debug + $scl = $forge_server::scl + $provider = $forge_server::provider + $forge_server_script = $forge_server::forge_server_script file { '/etc/default/puppet-forge-server': - ensure => present, + ensure => file, owner => 'root', group => 'root', mode => '0644', - content => template("${module_name}/${::osfamily}/puppet-forge-server.default.erb") + content => template("${module_name}/${facts['os']['family']}/puppet-forge-server.default.erb") } # On a systemd server create config file for tmpfiles.d - case $::operatingsystem { + case $facts['os']['name'] { 'RedHat', 'CentOS', 'Fedora', 'Scientific', 'OracleLinux', 'SLC': { - if versioncmp($::operatingsystemmajrelease, '7') >= 0 { + if versioncmp($facts['os']['release']['major'], '7') >= 0 { $unit_file_path = '/etc/systemd/system/puppet-forge-server.service' $unit_file_template = "${module_name}/puppet-forge-server.service.erb" } } 'SLES': { - if versioncmp($::operatingsystemmajrelease, '12') >= 0 { + if versioncmp($facts['os']['release']['major'], '12') >= 0 { $unit_file_path = '/usr/lib/systemd/system/puppet-forge-server.service' - $unit_file_template = "${module_name}/${::osfamily}/puppet-forge-server.service.erb" + $unit_file_template = "${module_name}/${facts['os']['family']}/puppet-forge-server.service.erb" } } 'Ubuntu': { - if versioncmp($::operatingsystemmajrelease, '15') >= 0 { + if versioncmp($facts['os']['release']['major'], '15') >= 0 { $unit_file_path = '/etc/systemd/system/puppet-forge-server.service' - $unit_file_template = "${module_name}/${::osfamily}/puppet-forge-server.service.erb" + $unit_file_template = "${module_name}/${facts['os']['family']}/puppet-forge-server.service.erb" } } default: { } } - if $::service_provider == 'systemd' { + if $facts['service_provider'] == 'systemd' { file { '/usr/lib/tmpfiles.d/puppet-forge-server.conf': - ensure => present, + ensure => file, owner => 'root', group => 'root', mode => '0644', content => template("${module_name}/puppet-forge-server.tmpfilesd.erb") } file { $unit_file_path: - ensure => present, + ensure => file, owner => 'root', group => 'root', mode => '0640', @@ -76,11 +76,11 @@ } } else { file { '/etc/init.d/puppet-forge-server': - ensure => present, + ensure => file, owner => 'root', group => 'root', mode => '0755', - content => template("${module_name}/${::osfamily}/puppet-forge-server.initd.erb") + content => template("${module_name}/${facts['os']['family']}/puppet-forge-server.initd.erb") } } } diff --git a/manifests/files.pp b/manifests/files.pp index f4b7a2c..8dc89f0 100644 --- a/manifests/files.pp +++ b/manifests/files.pp @@ -4,43 +4,43 @@ # class forge_server::files { - $pid_dir = dirname($::forge_server::pidfile) + $pid_dir = dirname($forge_server::pidfile) - ::forge_server::mkdir { $::forge_server::module_directory: } - ::forge_server::mkdir { $::forge_server::log_dir: } - ::forge_server::mkdir { $::forge_server::cache_basedir: } - ::forge_server::mkdir { $pid_dir: } + forge_server::mkdir { $forge_server::module_directory: } + forge_server::mkdir { $forge_server::log_dir: } + forge_server::mkdir { $forge_server::cache_basedir: } + forge_server::mkdir { $pid_dir: } file { $pid_dir: ensure => directory, - owner => $::forge_server::user, - group => $::forge_server::user, + owner => $forge_server::user, + group => $forge_server::user, mode => '0755', - require => ::Forge_server::Mkdir[$pid_dir] + require => Forge_server::Mkdir[$pid_dir] } - file { $::forge_server::log_dir: + file { $forge_server::log_dir: ensure => directory, - owner => $::forge_server::user, - group => $::forge_server::user, + owner => $forge_server::user, + group => $forge_server::user, mode => '0700', - require => ::Forge_server::Mkdir[$::forge_server::log_dir] + require => Forge_server::Mkdir[$forge_server::log_dir] } - file { $::forge_server::module_directory: + file { $forge_server::module_directory: ensure => directory, - owner => $::forge_server::user, - group => $::forge_server::user, + owner => $forge_server::user, + group => $forge_server::user, mode => '0755', - require => ::Forge_server::Mkdir[$::forge_server::module_directory] + require => Forge_server::Mkdir[$forge_server::module_directory] } - file { $::forge_server::cache_basedir: + file { $forge_server::cache_basedir: ensure => directory, - owner => $::forge_server::user, - group => $::forge_server::user, + owner => $forge_server::user, + group => $forge_server::user, mode => '0755', - require => ::Forge_server::Mkdir[$::forge_server::cache_basedir] + require => Forge_server::Mkdir[$forge_server::cache_basedir] } } diff --git a/manifests/init.pp b/manifests/init.pp index c61fcda..e697f71 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,64 +1,52 @@ # == Class: forge_server # +# @summary # A Puppet module to manage the Puppet Forge Server service # -# === Parameters -# -# [*package*] +# @param package # Optional override of package name -# -# [*scl*] +# @param scl # Name of ruby scl environment, leave undef to use system ruby -# -# [*scl_install_timeout*] +# @param scl_install_timeout # If using ruby scl, the timeout in seconds to allow the gem installation to run -# -# [*scl_install_retries*] +# @param scl_install_retries # If using ruby scl, the number of retries allowed if gem installation fails -# -# [*service_enable*] +# @param service_enable # Boolean if service should be enabled on boot -# -# [*service_ensure*] +# @param service_ensure # Service ensure state -# -# [*service_refresh*] +# @param service_refresh # Boolean if config changes and package changes should trigger service restart -# -# [*pidfile*] +# @param pidfile # Path to pidfile -# -# [*port*] +# @param port # Port to bind to -# -# [*bind_host*] +# @param bind_host # IP or host to bind to -# -# [*daemonize*] +# @param daemonize # Boolean if should be daemonized -# -# [*module_directory*] +# @param module_directory # Directory of modules to serve, can be an array of directories -# -# [*http_proxy*] +# @param http_proxy # Use proxyserver for http(s) connections -# -# [*proxy*] +# @param proxy # Proxy requests to this upstream forge url -# -# [*cache_basedir*] +# @param cache_basedir # Path where to store proxied / cached modules -# -# [*log_dir*] +# @param log_dir # Path to log directory -# -# [*debug*] +# @param debug # Boolean to toggle debug -# -# [*forge_server_script*] +# @param forge_server_script # Name of the script which runs the forge server, depending on ruby version installed +# @param user +# Name of the system user for forge-server +# @param user_homedir +# Path to the system users home dir +# @param provider +# Whether to use system ruby or puppet ruby # -# === Examples +# @example # # class { '::forge_server': # scl => 'ruby193' @@ -73,53 +61,46 @@ # Copyright 2014 North Development AB # class forge_server ( - $package = $::forge_server::params::package, - $scl = undef, - $scl_install_timeout = $::forge_server::params::scl_install_timeout, - $scl_install_retries = $::forge_server::params::scl_install_retries, - $service_enable = true, - $service_ensure = 'running', - $service_refresh = true, - $pidfile = $::forge_server::params::pidfile, - $port = $::forge_server::params::port, - $bind_host = $::forge_server::params::bind_host, - $daemonize = true, - $module_directory = $::forge_server::params::module_directory, - $http_proxy = $::forge_server::params::http_proxy, - $proxy = $::forge_server::params::proxy, - $cache_basedir = $::forge_server::params::cache_basedir, - $log_dir = $::forge_server::params::log_dir, - $debug = false, - $provider = 'gem', - $forge_server_script = $::forge_server::params::forge_server_script, -) inherits forge_server::params { + String[1] $package = 'puppet-forge-server', + String[1] $user = 'forge', + Stdlib::Unixpath $user_homedir = '/home/forge', + Stdlib::UnixPath $pidfile = '/var/run/puppet-forge-server/forge-server.pid', + Integer $port = 8080, + Stdlib::Host $bind_host = '127.0.0.1', + Variant[Array[Stdlib::Unixpath], Stdlib::Unixpath] $module_directory = '/var/lib/puppet-forge-server/modules', + Optional $proxy = undef, + Stdlib::Unixpath $cache_basedir = '/var/lib/puppet-forge-server/cache', + Stdlib::Unixpath $log_dir = '/var/log/puppet-forge-server', + Enum['gem', 'puppet_gem'] $provider = 'gem', + Optional $http_proxy = undef, + Optional $scl = undef, + Integer $scl_install_timeout = 300, + Integer $scl_install_retries = 1, + String[1] $forge_server_script = 'puppet-forge-server.ruby2.1', + Boolean $service_enable = true, + Enum['running', 'stopped'] $service_ensure = 'running', + Boolean $service_refresh = true, + Boolean $daemonize = true, + Boolean $debug = false, +) { if $scl { - if $::osfamily == 'RedHat' { - validate_integer($scl_install_timeout) - validate_integer($scl_install_retries) - } else { - fail("SCL is not a valid configuration option for ${::osfamily} systems") + if $facts['os']['family'] != 'RedHat' { + fail("SCL is not a valid configuration option for ${facts['os']['family']} systems") } } - validate_absolute_path($module_directory) - validate_absolute_path($cache_basedir) - validate_absolute_path($log_dir) - # contain class and ordering - anchor { '::forge_server::begin': } -> - class { '::forge_server::user': } -> - class { '::forge_server::package': } -> - class { '::forge_server::config': } -> - class { '::forge_server::files': } -> - class { '::forge_server::service': } -> - anchor { '::forge_server::end': } + class { 'forge_server::user': } + -> class { 'forge_server::package': } + -> class { 'forge_server::config': } + -> class { 'forge_server::files': } + -> class { 'forge_server::service': } # optional refresh if $service_refresh { - Class['::forge_server::package'] ~> Class['::forge_server::service'] - Class['::forge_server::config'] ~> Class['::forge_server::service'] + Class['forge_server::package'] ~> Class['forge_server::service'] + Class['forge_server::config'] ~> Class['forge_server::service'] } } diff --git a/manifests/mkdir.pp b/manifests/mkdir.pp index c111490..252d6e3 100644 --- a/manifests/mkdir.pp +++ b/manifests/mkdir.pp @@ -4,10 +4,10 @@ # define forge_server::mkdir () { - if !defined(Exec["forge_server_mkdir_p_${name}"]) { - exec { "forge_server_mkdir_p_${name}": - command => "mkdir -p ${name}", - creates => $name, + if !defined(Exec["forge_server_mkdir_p_${title}"]) { + exec { "forge_server_mkdir_p_${title}": + command => "mkdir -p ${title}", + creates => $title, path => ['/bin', '/usr/bin'] } } diff --git a/manifests/package.pp b/manifests/package.pp index b91867c..ab3293f 100644 --- a/manifests/package.pp +++ b/manifests/package.pp @@ -4,18 +4,18 @@ # class forge_server::package { - if $::forge_server::scl { + if $forge_server::scl { exec { 'scl_install_forge_server': - command => "scl enable ${::forge_server::scl} 'gem install --bindir /usr/bin --no-rdoc --no-ri ${::forge_server::package}'", + command => "scl enable ${forge_server::scl} 'gem install --bindir /usr/bin --no-rdoc --no-ri ${forge_server::package}'", path => ['/bin','/usr/bin'], - unless => "scl enable ${::forge_server::scl} 'gem list'| grep -qs ${::forge_server::package}", - timeout => $::forge_server::scl_install_timeout, - tries => $::forge_server::scl_install_retries + unless => "scl enable ${forge_server::scl} 'gem list'| grep -qs ${forge_server::package}", + timeout => $forge_server::scl_install_timeout, + tries => $forge_server::scl_install_retries } } else { package { $forge_server::package: ensure => present, - provider => $::forge_server::provider + provider => $forge_server::provider } } diff --git a/manifests/params.pp b/manifests/params.pp deleted file mode 100644 index 089e428..0000000 --- a/manifests/params.pp +++ /dev/null @@ -1,21 +0,0 @@ -# == Class: forge_server::params -# -# Default settings -# -class forge_server::params { - $package = 'puppet-forge-server' - $user = 'forge' - $user_homedir = '/home/forge' - $pidfile = '/var/run/puppet-forge-server/forge-server.pid' - $port = 8080 - $bind_host = '127.0.0.1' - $module_directory = '/var/lib/puppet-forge-server/modules' - $proxy = undef - $cache_basedir = '/var/lib/puppet-forge-server/cache' - $log_dir = '/var/log/puppet-forge-server' - $provider = 'gem' - $http_proxy = undef - $scl_install_timeout = 300 - $scl_install_retries = 1 - $forge_server_script = 'puppet-forge-server.ruby2.1' -} diff --git a/manifests/service.pp b/manifests/service.pp index 6d70cc1..d4d0249 100644 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -5,8 +5,8 @@ class forge_server::service { service { 'puppet-forge-server': - ensure => $::forge_server::service_ensure, - enable => $::forge_server::service_enable + ensure => $forge_server::service_ensure, + enable => $forge_server::service_enable } } diff --git a/manifests/user.pp b/manifests/user.pp index af3f541..b148014 100644 --- a/manifests/user.pp +++ b/manifests/user.pp @@ -3,19 +3,19 @@ # Manages the forge user # class forge_server::user { - user { $::forge_server::user: + user { $forge_server::user: ensure => present, - gid => $::forge_server::user + gid => $forge_server::user } # have to create a home dir or else systemd unit file will not start - file { $::forge_server::user_homedir: + file { $forge_server::user_homedir: ensure => directory, - owner => $::forge_server::user, - group => $::forge_server::user, + owner => $forge_server::user, + group => $forge_server::user, } - group { $::forge_server::user: + group { $forge_server::user: ensure => present } } diff --git a/metadata.json b/metadata.json index cafbc44..a28fedc 100644 --- a/metadata.json +++ b/metadata.json @@ -1,27 +1,46 @@ { "name": "parshipelite-forge_server", - "version": "0.5.1", + "version": "0.5.3", "author": "Parship Group", "summary": "A Puppet module to manage puppet-forge-server", "license": "Apache-2.0", "source": "https://github.com/parship/puppet-forge_server.git", - "project_page": "https://github.com/unibet/puppet-forge_server", - "issues_url": "https://github.com/unibet/puppet-forge_server/issues", + "project_page": "https://github.com/parship/puppet-forge_server", + "issues_url": "https://github.com/parship/puppet-forge_server/issues", "dependencies": [ - {"name":"puppetlabs-stdlib","version_requirement":">= 4.10.0"} + { + "name": "puppetlabs-stdlib", + "version_requirement": ">= 4.10.0 < 9.0.0" + } ], "operatingsystem_support": [ { - "operatingsystem": "RedHat", - "operatingsystemrelease": [ "6.0", "7.0" ] + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "7.0" + ] }, { - "operatingsystem": "Ubuntu", - "operatingsystemrelease": [ "18.04", "16.04", "14.04", "12.04" ] + "operatingsystem": "Ubuntu", + "operatingsystemrelease": [ + "18.04", + "16.04" + ] }, { - "operatingsystem": "SLES", - "operatingsystemrelease": [ "12" ] + "operatingsystem": "SLES", + "operatingsystemrelease": [ + "12" + ] + } + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">= 6.21.0 < 8.0.0" } - ] + ], + "pdk-version": "2.2.0", + "template-url": "pdk-default#2.2.0", + "template-ref": "tags/2.2.0-0-g2381db6" } diff --git a/pdk.yaml b/pdk.yaml new file mode 100644 index 0000000..4bef4bd --- /dev/null +++ b/pdk.yaml @@ -0,0 +1,2 @@ +--- +ignore: [] diff --git a/spec/classes/forge_server_spec.rb b/spec/classes/forge_server_spec.rb new file mode 100644 index 0000000..b434e8b --- /dev/null +++ b/spec/classes/forge_server_spec.rb @@ -0,0 +1,127 @@ +require 'spec_helper' +describe 'forge_server' do + on_supported_os.each do |os, facts| + context "with defaults for all parameters (on #{os})" do + let(:facts) do + facts + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_package('puppet-forge-server') } + it { is_expected.not_to contain_exec('scl_install_forge_server') } + it { is_expected.not_to contain_file('/etc/init.d/puppet-forge-server').with_content(%r{export LD_LIBRARY_PATH=.*\nexport GEM_PATH=.*\nexport PATH=.*\n}) } + end + context "with single module path and proxy (on #{os})" do + let(:params) do + { + module_directory: '/dir1', + proxy: 'proxy1' + } + end + let(:facts) do + facts + end + + it { is_expected.to compile.with_all_deps } + + case facts[:osfamily] + when 'RedHat' + it { is_expected.to contain_file('/etc/default/puppet-forge-server').with_content(%r{PARAMS=\"${PARAMS} --module-dir /dir1\"}) } + it { is_expected.to contain_file('/etc/default/puppet-forge-server').with_content(%r{PARAMS=\"${PARAMS} --proxy proxy1\"}) } + when 'Debian' + it { is_expected.to contain_file('/etc/default/puppet-forge-server').with_content(%r{PARAMS="\${PARAMS} --module-dir /dir1"}) } + it { is_expected.to contain_file('/etc/default/puppet-forge-server').with_content(%r{PARAMS="\${PARAMS} --proxy proxy1"}) } + end + end + + context "with multiple module paths and proxies (on #{os})" do + let(:params) do + { + module_directory: ['/dir1', '/dir2'], + proxy: ['proxy1', 'proxy2'] + } + end + let(:facts) do + facts + end + + it { is_expected.to compile.with_all_deps } + + case facts[:osfamily] + when 'RedHat' + it { + is_expected.to contain_file('/etc/default/puppet-forge-server') + .with_content(%r{PARAMS="\${PARAMS} --module-dir \\"/dir1\\""\nPARAMS="\${PARAMS} --module-dir \\"/dir2\\""\n}) + .with_content(%r{PARAMS="\${PARAMS} --proxy proxy1"\nPARAMS="\${PARAMS} --proxy proxy2"\n}) + } + when 'Debian' + it { + is_expected.to contain_file('/etc/default/puppet-forge-server') + .with_content(%r{PARAMS="\${PARAMS} --module-dir /dir1"\nPARAMS="\${PARAMS} --module-dir /dir2"\n}) + .with_content(%r{PARAMS="\${PARAMS} --proxy proxy1"\nPARAMS="\${PARAMS} --proxy proxy2"\n}) + } + end + end + + context "with service_refresh => false (on #{os})" do + let(:params) do + { + service_refresh: false + } + end + let(:facts) do + facts + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.not_to contain_class('::forge_server::package').that_notifies('Class[::forge_server::service]') } + it { is_expected.not_to contain_class('::forge_server::config').that_notifies('Class[::forge_server::service]') } + end + + context "with scl => ruby193 (on #{os})" do + let(:params) do + { + scl: 'ruby193' + } + end + let(:facts) do + facts + end + + case facts[:osfamily] + when 'RedHat' + it { is_expected.to compile.with_all_deps } + it { is_expected.not_to contain_package('puppet-forge-server') } + it { is_expected.to contain_exec('scl_install_forge_server').with(command: "scl enable ruby193 'gem install --bindir /usr/bin --no-rdoc --no-ri puppet-forge-server'") } + if facts[:release] == 6 + it { is_expected.to contain_file('/etc/init.d/puppet-forge-server').with_content(%r{export LD_LIBRARY_PATH=.*\nexport GEM_PATH=.*\nexport PATH=.*\n}) } + end + else + it { is_expected.not_to compile } + end + end + + # rubocop:disable EmptyExampleGroup + context "with scl, scl_install_timeout and scl_install_retries (on #{os})" do + let(:params) do + { + scl: 'ruby193', + scl_install_timeout: 60_000, + scl_install_retries: 10 + } + end + let(:facts) do + facts + end + + case facts[:osfamily] + when 'RedHat' + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_exec('scl_install_forge_server').with_timeout(60_000).with_tries(10) } + else + it { is_expected.not_to compile } + end + end + # rubocop:enable EmptyExampleGroup + end +end diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb deleted file mode 100644 index ddab45b..0000000 --- a/spec/classes/init_spec.rb +++ /dev/null @@ -1,157 +0,0 @@ -require 'spec_helper' -describe 'forge_server' do - - on_supported_os.each do |os, facts| - puts "stdout-debug OS: '#{os}' -- operatingsystemmajrelease: '#{facts[:operatingsystemmajrelease]}'" - context "with defaults for all parameters (on #{os})" do - let(:facts) do - facts - end - - it { should compile.with_all_deps } - it { - should contain_package('puppet-forge-server') - } - it { - should_not contain_exec('scl_install_forge_server') - } - it { - should_not contain_file('/etc/init.d/puppet-forge-server').with_content(/export LD_LIBRARY_PATH=.*\nexport GEM_PATH=.*\nexport PATH=.*\n/) - } - end - - - context "with single module path and proxy (on #{os})" do - let(:params) { { - :module_directory => '/dir1', - :proxy => 'proxy1' - } } - - let(:facts) do - facts - end - - it { should compile.with_all_deps } - - case facts[:osfamily] - when 'RedHat' - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --module-dir \\"\/dir1\\""\n\n/) - } - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --proxy proxy1"\n\n/) - } - when 'Debian' - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --module-dir \/dir1"\n\n/) - } - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --proxy proxy1"\n\n/) - } - end - end - - - context "with multiple module paths and proxies (on #{os})" do - let(:params) { { - :module_directory => ['/dir1', '/dir2'], - :proxy => ['proxy1', 'proxy2'] - } } - - let(:facts) do - facts - end - - it { should compile.with_all_deps } - - case facts[:osfamily] - when 'RedHat' - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --module-dir \\"\/dir1\\""\nPARAMS="\${PARAMS} --module-dir \\"\/dir2\\""\n/) - } - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --proxy proxy1"\nPARAMS="\${PARAMS} --proxy proxy2"\n/) - } - when 'Debian' - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --module-dir \/dir1"\nPARAMS="\${PARAMS} --module-dir \/dir2"\n/) - } - it { - should contain_file('/etc/default/puppet-forge-server').with_content(/PARAMS="\${PARAMS} --proxy proxy1"\nPARAMS="\${PARAMS} --proxy proxy2"\n/) - } - end - end - - - context "with service_refresh => false (on #{os})" do - let(:params) { { - :service_refresh => false - } } - - let(:facts) do - facts - end - - it { should compile.with_all_deps } - it { - should_not contain_class('::forge_server::package').that_notifies('Class[::forge_server::service]') - } - it { - should_not contain_class('::forge_server::config').that_notifies('Class[::forge_server::service]') - } - end - - - context "with scl => ruby193 (on #{os})" do - let(:params) { { - :scl => 'ruby193' - } } - - let(:facts) do - facts - end - - case facts[:osfamily] - when 'RedHat' - it { should compile.with_all_deps } - it { - should_not contain_package('puppet-forge-server') - } - it { - should contain_exec('scl_install_forge_server').with( - :command => "scl enable ruby193 'gem install --bindir /usr/bin --no-rdoc --no-ri puppet-forge-server'" - ) - } - if facts[:release] == 6 - it { - should contain_file('/etc/init.d/puppet-forge-server').with_content(/export LD_LIBRARY_PATH=.*\nexport GEM_PATH=.*\nexport PATH=.*\n/) - } - end - when 'Debian' - it { should_not compile } - end - end - - - context "with scl => ruby193, scl_install_timeout => 60000, scl_install_retries => 10 (on #{os})" do - let(:params) { { - :scl => 'ruby193', - :scl_install_timeout => 60000, - :scl_install_retries => 10 - } } - - let(:facts) do - facts - end - - case facts[:osfamily] - when 'RedHat' - it { should compile.with_all_deps } - it { should contain_exec('scl_install_forge_server').with_timeout(60000) } - it { should contain_exec('scl_install_forge_server').with_tries(10) } - when 'Debian' - it { should_not compile } - end - end - end -end diff --git a/spec/default_facts.yml b/spec/default_facts.yml new file mode 100644 index 0000000..f777abf --- /dev/null +++ b/spec/default_facts.yml @@ -0,0 +1,8 @@ +# Use default_module_facts.yml for module specific facts. +# +# Facts specified here will override the values provided by rspec-puppet-facts. +--- +ipaddress: "172.16.254.254" +ipaddress6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA" +is_pe: false +macaddress: "AA:AA:AA:AA:AA:AA" diff --git a/spec/default_module_facts.yml b/spec/default_module_facts.yml new file mode 100644 index 0000000..a5c9b4b --- /dev/null +++ b/spec/default_module_facts.yml @@ -0,0 +1,2 @@ +--- +service_provider: 'systemd' diff --git a/spec/defines/mkdir_spec.rb b/spec/defines/mkdir_spec.rb new file mode 100644 index 0000000..3fcdd3f --- /dev/null +++ b/spec/defines/mkdir_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'forge_server::mkdir' do + let(:title) { '/namevar' } + let(:params) do + {} + end + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + + it { is_expected.to compile } + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1ffdf17..9b1fa6f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,73 @@ +# frozen_string_literal: true + +RSpec.configure do |c| + c.mock_with :rspec +end + require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' + +require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) + include RspecPuppetFacts + +default_facts = { + puppetversion: Puppet.version, + facterversion: Facter.version, +} + +default_fact_files = [ + File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')), + File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')), +] + +default_fact_files.each do |f| + next unless File.exist?(f) && File.readable?(f) && File.size?(f) + + begin + default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) + rescue => e + RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" + end +end + +# read default_facts and merge them over what is provided by facterdb +default_facts.each do |fact, value| + add_custom_fact fact, value +end + +RSpec.configure do |c| + c.default_facts = default_facts + c.before :each do + # set to strictest setting for testing + # by default Puppet runs at warning level + Puppet.settings[:strict] = :warning + Puppet.settings[:strict_variables] = true + end + c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] + c.after(:suite) do + end + + # Filter backtrace noise + backtrace_exclusion_patterns = [ + %r{spec_helper}, + %r{gems}, + ] + + if c.respond_to?(:backtrace_exclusion_patterns) + c.backtrace_exclusion_patterns = backtrace_exclusion_patterns + elsif c.respond_to?(:backtrace_clean_patterns) + c.backtrace_clean_patterns = backtrace_exclusion_patterns + end +end + +# Ensures that a module is defined +# @param module_name Name of the module +def ensure_module_defined(module_name) + module_name.split('::').reduce(Object) do |last_module, next_module| + last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false) + last_module.const_get(next_module, false) + end +end + +# 'spec_overrides' from sync.yml will appear below this line diff --git a/test/integration/default/puppet/manifests/site.pp b/test/integration/default/puppet/manifests/site.pp deleted file mode 100644 index b49bf7a..0000000 --- a/test/integration/default/puppet/manifests/site.pp +++ /dev/null @@ -1,5 +0,0 @@ -package { ['scl-utils', 'scl-utils-build', 'centos-release-SCL']: } -> -package { ['ruby193', 'ruby193-ruby-devel']: } -> -class { '::forge_server': - scl => 'ruby193' -} diff --git a/test/integration/default/serverspec/default_spec.rb b/test/integration/default/serverspec/default_spec.rb deleted file mode 100644 index d652a2b..0000000 --- a/test/integration/default/serverspec/default_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'serverspec' -require 'yaml' - -set :backend, :exec - -describe "Puppet" do - it "should run without errors" do - last_run = YAML.load_file('/var/lib/puppet/state/last_run_summary.yaml') - expect(last_run['resources']['failed']).to eq(0) - expect(last_run['resources']['failed_to_restart']).to eq(0) - expect(last_run['events']['failure']).to eq(0) - end -end - -describe service('puppet-forge-server') do - it { should be_running } - it { should be_enabled.with_level(3) } -end - -describe port(8080) do - it { should be_listening } -end - -describe command('puppet module install --module_repository=http://localhost:8080 puppetlabs-stdlib') do - its(:exit_status) { should eq 0 } -end