diff --git a/.gitignore b/.gitignore index 27247b1..650022e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,24 @@ -.*.sw? -pkg -spec/fixtures -!spec/fixtures/hiera.yaml -!spec/fixtures/hieradata/*.yaml -!spec/fixtures/manifests/site.pp -.rspec_system -.vagrant -.bundle -vendor -.idea -bin -Gemfile.lock -coverage -Modulefile -log -junuit -doc +.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 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..e369e3c --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,41 @@ +--- +stages: + - syntax + - unit + +cache: + paths: + - vendor/bundle + +before_script: + - bundle -v + - rm Gemfile.lock || true + - gem update --system + - gem --version + - bundle -v + - bundle install --without system_tests --path vendor/bundle --jobs $(nproc) + +parallel_spec-Ruby 2.1.9-Puppet ~> 4.0: + stage: unit + image: ruby:2.1.9 + script: + - bundle exec rake parallel_spec + variables: + PUPPET_GEM_VERSION: '~> 4.0' + +syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop-Ruby 2.4.4-Puppet ~> 5.5: + stage: syntax + image: ruby:2.4.4 + script: + - bundle exec rake syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop + variables: + PUPPET_GEM_VERSION: '~> 5.5' + +parallel_spec-Ruby 2.4.4-Puppet ~> 5.5: + stage: unit + image: ruby:2.4.4 + script: + - bundle exec rake parallel_spec + variables: + PUPPET_GEM_VERSION: '~> 5.5' + diff --git a/.pdkignore b/.pdkignore new file mode 100644 index 0000000..650022e --- /dev/null +++ b/.pdkignore @@ -0,0 +1,24 @@ +.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 diff --git a/.rspec b/.rspec index 8c18f1a..16f9cdb 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1,2 @@ ---format documentation --color +--format documentation diff --git a/.rubocop.yml b/.rubocop.yml index 3f1d222..f5a6c2a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,1156 +1,122 @@ +--- +require: rubocop-rspec AllCops: - DisabledByDefault: true - -#################### Lint ################################ - -Lint/AmbiguousOperator: - Description: >- - Checks for ambiguous operators in the first argument of a - method invocation without parentheses. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-as-args' - Enabled: true - -Lint/AmbiguousRegexpLiteral: - Description: >- - Checks for ambiguous regexp literals in the first argument of - a method invocation without parenthesis. - Enabled: true - -Lint/AssignmentInCondition: - Description: "Don't use assignment in conditions." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition' - Enabled: true - -Lint/BlockAlignment: - Description: 'Align block ends correctly.' - Enabled: true - -Lint/CircularArgumentReference: - Description: "Don't refer to the keyword argument in the default value." - Enabled: true - -Lint/ConditionPosition: - Description: >- - Checks for condition placed in a confusing position relative to - the keyword. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#same-line-condition' - Enabled: true - -Lint/Debugger: - Description: 'Check for debugger calls.' - Enabled: true - -Lint/DefEndAlignment: - Description: 'Align ends corresponding to defs correctly.' - Enabled: true - -Lint/DeprecatedClassMethods: - Description: 'Check for deprecated class method calls.' - Enabled: true - -Lint/DuplicateMethods: - Description: 'Check for duplicate methods calls.' - Enabled: true - -Lint/EachWithObjectArgument: - Description: 'Check for immutable argument given to each_with_object.' - Enabled: true - -Lint/ElseLayout: - Description: 'Check for odd code arrangement in an else block.' - Enabled: true - -Lint/EmptyEnsure: - Description: 'Checks for empty ensure block.' - Enabled: true - -Lint/EmptyInterpolation: - Description: 'Checks for empty string interpolation.' - Enabled: true - -Lint/EndAlignment: - Description: 'Align ends correctly.' - Enabled: true - -Lint/EndInMethod: - Description: 'END blocks should not be placed inside method definitions.' - Enabled: true - -Lint/EnsureReturn: - Description: 'Do not use return in an ensure block.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-return-ensure' - Enabled: true - -Lint/Eval: - Description: 'The use of eval represents a serious security risk.' - Enabled: true - -Lint/FormatParameterMismatch: - Description: 'The number of parameters to format/sprint must match the fields.' - Enabled: true - -Lint/HandleExceptions: - Description: "Don't suppress exception." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions' - Enabled: true - -Lint/InvalidCharacterLiteral: - Description: >- - Checks for invalid character literals with a non-escaped - whitespace character. - Enabled: true - -Lint/LiteralInCondition: - Description: 'Checks of literals used in conditions.' - Enabled: true - -Lint/LiteralInInterpolation: - Description: 'Checks for literals used in interpolation.' - Enabled: true - -Lint/Loop: - Description: >- - Use Kernel#loop with break rather than begin/end/until or - begin/end/while for post-loop tests. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#loop-with-break' - Enabled: true - -Lint/NestedMethodDefinition: - Description: 'Do not use nested method definitions.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-methods' - Enabled: true - -Lint/NonLocalExitFromIterator: - Description: 'Do not use return in iterator to cause non-local exit.' - Enabled: true - -Lint/ParenthesesAsGroupedExpression: - Description: >- - Checks for method calls with a space before the opening - parenthesis. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces' - Enabled: true - -Lint/RequireParentheses: - Description: >- - Use parentheses in the method call to avoid confusion - about precedence. - Enabled: true - -Lint/RescueException: - Description: 'Avoid rescuing the Exception class.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues' - Enabled: true - -Lint/ShadowingOuterLocalVariable: - Description: >- - Do not use the same name as outer local variable - for block arguments or block local variables. - Enabled: true - -Lint/StringConversionInInterpolation: - Description: 'Checks for Object#to_s usage in string interpolation.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-to-s' - Enabled: true - -Lint/UnderscorePrefixedVariableName: - Description: 'Do not use prefix `_` for a variable that is used.' - Enabled: true - -Lint/UnneededDisable: - Description: >- - Checks for rubocop:disable comments that can be removed. - Note: this cop is not disabled when disabling all cops. - It must be explicitly disabled. - Enabled: true - -Lint/UnusedBlockArgument: - Description: 'Checks for unused block arguments.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' - Enabled: true - -Lint/UnusedMethodArgument: - Description: 'Checks for unused method arguments.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' - Enabled: true - -Lint/UnreachableCode: - Description: 'Unreachable code.' - Enabled: true - -Lint/UselessAccessModifier: - Description: 'Checks for useless access modifiers.' - Enabled: true - -Lint/UselessAssignment: - Description: 'Checks for useless assignment to a local variable.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscore-unused-vars' - Enabled: true - -Lint/UselessComparison: - Description: 'Checks for comparison of something with itself.' - Enabled: true - -Lint/UselessElseWithoutRescue: - Description: 'Checks for useless `else` in `begin..end` without `rescue`.' - Enabled: true - -Lint/UselessSetterCall: - Description: 'Checks for useless setter call to a local variable.' - Enabled: true - -Lint/Void: - Description: 'Possible use of operator/literal/variable in void context.' - Enabled: true - -###################### Metrics #################################### - -Metrics/AbcSize: - Description: >- - A calculated magnitude based on number of assignments, - branches, and conditions. - Reference: 'http://c2.com/cgi/wiki?AbcMetric' - Enabled: false - Max: 20 - -Metrics/BlockNesting: - Description: 'Avoid excessive block nesting' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#three-is-the-number-thou-shalt-count' - Enabled: true - Max: 4 - -Metrics/ClassLength: - Description: 'Avoid classes longer than 250 lines of code.' - Enabled: true - Max: 250 - -Metrics/CyclomaticComplexity: - Description: >- - A complexity metric that is strongly correlated to the number - of test cases needed to validate a method. - Enabled: true - + DisplayCopNames: true + TargetRubyVersion: '2.1' + Include: + - "./**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - "**/Gemfile" + - "**/Rakefile" + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* + - "**/Puppetfile" + - "**/Vagrantfile" + - "**/Guardfile" Metrics/LineLength: - Description: 'Limit lines to 80 characters.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#80-character-limits' - Enabled: false - -Metrics/MethodLength: - Description: 'Avoid methods longer than 30 lines of code.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods' - Enabled: true - Max: 30 - -Metrics/ModuleLength: - Description: 'Avoid modules longer than 250 lines of code.' - Enabled: true - Max: 250 - -Metrics/ParameterLists: - Description: 'Avoid parameter lists longer than three or four parameters.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#too-many-params' - Enabled: true - -Metrics/PerceivedComplexity: - Description: >- - A complexity metric geared towards measuring complexity for a - human reader. - Enabled: false - -##################### Performance ############################# - -Performance/Count: - Description: >- - Use `count` instead of `select...size`, `reject...size`, - `select...count`, `reject...count`, `select...length`, - and `reject...length`. - Enabled: true - -Performance/Detect: - Description: >- - Use `detect` instead of `select.first`, `find_all.first`, - `select.last`, and `find_all.last`. - Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerabledetect-vs-enumerableselectfirst-code' - Enabled: true - -Performance/FlatMap: - Description: >- - Use `Enumerable#flat_map` - instead of `Enumerable#map...Array#flatten(1)` - or `Enumberable#collect..Array#flatten(1)` - Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code' - Enabled: true - EnabledForFlattenWithoutParams: false - # If enabled, this cop will warn about usages of - # `flatten` being called without any parameters. - # This can be dangerous since `flat_map` will only flatten 1 level, and - # `flatten` without any parameters can flatten multiple levels. - -Performance/ReverseEach: - Description: 'Use `reverse_each` instead of `reverse.each`.' - Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablereverseeach-vs-enumerablereverse_each-code' - Enabled: true - -Performance/Sample: - Description: >- - Use `sample` instead of `shuffle.first`, - `shuffle.last`, and `shuffle[Fixnum]`. - Reference: 'https://github.com/JuanitoFatas/fast-ruby#arrayshufflefirst-vs-arraysample-code' - Enabled: true - -Performance/Size: - Description: >- - Use `size` instead of `count` for counting - the number of elements in `Array` and `Hash`. - Reference: 'https://github.com/JuanitoFatas/fast-ruby#arraycount-vs-arraysize-code' - Enabled: true - -Performance/StringReplacement: - Description: >- - Use `tr` instead of `gsub` when you are replacing the same - number of characters. Use `delete` instead of `gsub` when - you are deleting characters. - Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringgsub-vs-stringtr-code' - Enabled: true - -##################### Rails ################################## - -Rails/ActionFilter: - Description: 'Enforces consistent use of action filter methods.' - Enabled: false - -Rails/Date: - Description: >- - Checks the correct usage of date aware methods, - such as Date.today, Date.current etc. - Enabled: false - -Rails/Delegate: - Description: 'Prefer delegate method for delegations.' - Enabled: false - -Rails/FindBy: - Description: 'Prefer find_by over where.first.' - Enabled: false - -Rails/FindEach: - Description: 'Prefer all.find_each over all.find.' - Enabled: false - -Rails/HasAndBelongsToMany: - Description: 'Prefer has_many :through to has_and_belongs_to_many.' - Enabled: false - -Rails/Output: - Description: 'Checks for calls to puts, print, etc.' - Enabled: false - -Rails/ReadWriteAttribute: - Description: >- - Checks for read_attribute(:attr) and - write_attribute(:attr, val). - Enabled: false - -Rails/ScopeArgs: - Description: 'Checks the arguments of ActiveRecord scopes.' - Enabled: false - -Rails/TimeZone: - Description: 'Checks the correct usage of time zone aware methods.' - StyleGuide: 'https://github.com/bbatsov/rails-style-guide#time' - Reference: 'http://danilenko.org/2012/7/6/rails_timezones' - Enabled: false - -Rails/Validation: - Description: 'Use validates :attribute, hash of validations.' - Enabled: false - -################## Style ################################# - -Style/AccessModifierIndentation: - Description: Check indentation of private/protected visibility modifiers. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-public-private-protected' - Enabled: false - -Style/AccessorMethodName: - Description: Check the naming of accessor methods for get_/set_. - Enabled: false - -Style/Alias: - Description: 'Use alias_method instead of alias.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#alias-method' - Enabled: false - -Style/AlignArray: - Description: >- - Align the elements of an array literal if they span more than - one line. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#align-multiline-arrays' - Enabled: false - -Style/AlignHash: - Description: >- - Align the elements of a hash literal if they span more than - one line. - Enabled: false - -Style/AlignParameters: - Description: >- - Align the parameters of a method call if they span more - than one line. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-double-indent' - Enabled: false - -Style/AndOr: - Description: 'Use &&/|| instead of and/or.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-and-or-or' - Enabled: false - -Style/ArrayJoin: - Description: 'Use Array#join instead of Array#*.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#array-join' - Enabled: false - -Style/AsciiComments: - Description: 'Use only ascii symbols in comments.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-comments' - Enabled: false - -Style/AsciiIdentifiers: - Description: 'Use only ascii symbols in identifiers.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#english-identifiers' - Enabled: false - -Style/Attr: - Description: 'Checks for uses of Module#attr.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr' - Enabled: false - -Style/BeginBlock: - Description: 'Avoid the use of BEGIN blocks.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-BEGIN-blocks' - Enabled: false - -Style/BarePercentLiterals: - Description: 'Checks if usage of %() or %Q() matches configuration.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q-shorthand' - Enabled: false - -Style/BlockComments: - Description: 'Do not use block comments.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-block-comments' - Enabled: false - -Style/BlockEndNewline: - Description: 'Put end statement of multiline block on its own line.' - Enabled: false - + Description: People have wide screens, use them. + Max: 200 +GetText/DecorateString: + Description: We don't want to decorate test output. + Exclude: + - spec/* +RSpec/BeforeAfterAll: + Description: Beware of using after(:all) as it may cause state to leak between tests. + A necessary evil in acceptance testing. + Exclude: + - spec/acceptance/**/*.rb +RSpec/HookArgument: + Description: Prefer explicit :each argument, matching existing module's style + EnforcedStyle: each Style/BlockDelimiters: - Description: >- - Avoid using {...} for multi-line blocks (multiline chaining is - always ugly). - Prefer {...} over do...end for single-line blocks. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks' - Enabled: false - -Style/BracesAroundHashParameters: - Description: 'Enforce braces style around hash parameters.' - Enabled: false - -Style/CaseEquality: - Description: 'Avoid explicit use of the case equality operator(===).' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-case-equality' - Enabled: false - -Style/CaseIndentation: - Description: 'Indentation of when in a case/when/[else/]end.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#indent-when-to-case' - Enabled: false - -Style/CharacterLiteral: - Description: 'Checks for uses of character literals.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-character-literals' - Enabled: false - -Style/ClassAndModuleCamelCase: - Description: 'Use CamelCase for classes and modules.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#camelcase-classes' - Enabled: false - + Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to + be consistent then. + EnforcedStyle: braces_for_chaining Style/ClassAndModuleChildren: - Description: 'Checks style of children classes and modules.' - Enabled: false - -Style/ClassCheck: - Description: 'Enforces consistent use of `Object#is_a?` or `Object#kind_of?`.' - Enabled: false - -Style/ClassMethods: - Description: 'Use self when defining module/class methods.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#def-self-class-methods' - Enabled: false - -Style/ClassVars: - Description: 'Avoid the use of class variables.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-class-vars' - Enabled: false - -Style/ClosingParenthesisIndentation: - Description: 'Checks the indentation of hanging closing parentheses.' - Enabled: false - -Style/ColonMethodCall: - Description: 'Do not use :: for method call.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#double-colons' - Enabled: false - -Style/CommandLiteral: - Description: 'Use `` or %x around command literals.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-x' - Enabled: false - -Style/CommentAnnotation: - Description: 'Checks formatting of annotation comments.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#annotate-keywords' - Enabled: false - -Style/CommentIndentation: - Description: 'Indentation of comments.' - Enabled: false - -Style/ConstantName: - Description: 'Constants should use SCREAMING_SNAKE_CASE.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#screaming-snake-case' - Enabled: false - -Style/DefWithParentheses: - Description: 'Use def with parentheses when there are arguments.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens' - Enabled: false - -Style/DeprecatedHashMethods: - Description: 'Checks for use of deprecated Hash methods.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-key' - Enabled: false - -Style/Documentation: - Description: 'Document classes and non-namespace modules.' - Enabled: false - -Style/DotPosition: - Description: 'Checks the position of the dot in multi-line method calls.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains' - Enabled: false - -Style/DoubleNegation: - Description: 'Checks for uses of double negation (!!).' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-bang-bang' - Enabled: false - -Style/EachWithObject: - Description: 'Prefer `each_with_object` over `inject` or `reduce`.' - Enabled: false - -Style/ElseAlignment: - Description: 'Align elses and elsifs correctly.' - Enabled: false - + Description: Compact style reduces the required amount of indentation. + EnforcedStyle: compact Style/EmptyElse: - Description: 'Avoid empty else-clauses.' - Enabled: false - -Style/EmptyLineBetweenDefs: - Description: 'Use empty lines between defs.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#empty-lines-between-methods' - Enabled: false - -Style/EmptyLines: - Description: "Don't use several empty lines in a row." - Enabled: false - -Style/EmptyLinesAroundAccessModifier: - Description: "Keep blank lines around access modifiers." - Enabled: false - -Style/EmptyLinesAroundBlockBody: - Description: "Keeps track of empty lines around block bodies." - Enabled: false - -Style/EmptyLinesAroundClassBody: - Description: "Keeps track of empty lines around class bodies." - Enabled: false - -Style/EmptyLinesAroundModuleBody: - Description: "Keeps track of empty lines around module bodies." - Enabled: false - -Style/EmptyLinesAroundMethodBody: - Description: "Keeps track of empty lines around method bodies." - Enabled: false - -Style/EmptyLiteral: - Description: 'Prefer literals to Array.new/Hash.new/String.new.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#literal-array-hash' - Enabled: false - -Style/EndBlock: - Description: 'Avoid the use of END blocks.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-END-blocks' - Enabled: false - -Style/EndOfLine: - Description: 'Use Unix-style line endings.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#crlf' - Enabled: false - -Style/EvenOdd: - Description: 'Favor the use of Fixnum#even? && Fixnum#odd?' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' - Enabled: false - -Style/ExtraSpacing: - Description: 'Do not use unnecessary spacing.' - Enabled: false - -Style/FileName: - Description: 'Use snake_case for source file names.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files' - Enabled: false - -Style/InitialIndentation: - Description: >- - Checks the indentation of the first non-blank non-comment line in a file. - Enabled: false - -Style/FirstParameterIndentation: - Description: 'Checks the indentation of the first parameter in a method call.' - Enabled: false - -Style/FlipFlop: - Description: 'Checks for flip flops' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-flip-flops' - Enabled: false - -Style/For: - Description: 'Checks use of for or each in multiline loops.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-for-loops' - Enabled: false - + Description: Enforce against empty else clauses, but allow `nil` for clarity. + EnforcedStyle: empty Style/FormatString: - Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#sprintf' - Enabled: false - -Style/GlobalVars: - Description: 'Do not introduce global variables.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#instance-vars' - Reference: 'http://www.zenspider.com/Languages/Ruby/QuickRef.html' - Enabled: false - -Style/GuardClause: - Description: 'Check for conditionals that can be replaced with guard clauses' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals' - Enabled: false - -Style/HashSyntax: - Description: >- - Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax - { :a => 1, :b => 2 }. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-literals' - Enabled: false - -Style/IfUnlessModifier: - Description: >- - Favor modifier if/unless usage when you have a - single-line body. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier' - Enabled: false - -Style/IfWithSemicolon: - Description: 'Do not use if x; .... Use the ternary operator instead.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs' - Enabled: false - -Style/IndentationConsistency: - Description: 'Keep indentation straight.' - Enabled: false - -Style/IndentationWidth: - Description: 'Use 2 spaces for indentation.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation' - Enabled: false - -Style/IndentArray: - Description: >- - Checks the indentation of the first element in an array - literal. - Enabled: false - -Style/IndentHash: - Description: 'Checks the indentation of the first key in a hash literal.' - Enabled: false - -Style/InfiniteLoop: - Description: 'Use Kernel#loop for infinite loops.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#infinite-loop' - Enabled: false - + 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: 'Use the new lambda literal syntax for single-line blocks.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#lambda-multi-line' - Enabled: false - -Style/LambdaCall: - Description: 'Use lambda.call(...) instead of lambda.(...).' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc-call' - Enabled: false - -Style/LeadingCommentSpace: - Description: 'Comments should start with a space.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-space' - Enabled: false - -Style/LineEndConcatenation: - Description: >- - Use \ instead of + or << to concatenate two string literals at - line end. - Enabled: false - -Style/MethodCallParentheses: - Description: 'Do not use parentheses for method calls with no arguments.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens' - Enabled: false - -Style/MethodDefParentheses: - Description: >- - Checks if the method definitions have or don't have - parentheses. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens' - Enabled: false - -Style/MethodName: - Description: 'Use the configured style when naming methods.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars' - Enabled: false - -Style/ModuleFunction: - Description: 'Checks for usage of `extend self` in modules.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#module-function' - Enabled: false - -Style/MultilineBlockChain: - Description: 'Avoid multi-line chains of blocks.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks' - Enabled: false - -Style/MultilineBlockLayout: - Description: 'Ensures newlines after multiline block do statements.' - Enabled: false - -Style/MultilineIfThen: - Description: 'Do not use then for multi-line if/unless.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-then' - Enabled: false - -Style/MultilineOperationIndentation: - Description: >- - Checks indentation of binary operations that span more than - one line. - Enabled: false - -Style/MultilineTernaryOperator: - Description: >- - Avoid multi-line ?: (the ternary operator); - use if/unless instead. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-ternary' - Enabled: false - -Style/NegatedIf: - Description: >- - Favor unless over if for negative conditions - (or control flow or). - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#unless-for-negatives' - Enabled: false - -Style/NegatedWhile: - Description: 'Favor until over while for negative conditions.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#until-for-negatives' - Enabled: false - -Style/NestedTernaryOperator: - Description: 'Use one expression per branch in a ternary operator.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-ternary' - Enabled: false - -Style/Next: - Description: 'Use `next` to skip iteration instead of a condition at the end.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals' - Enabled: false - -Style/NilComparison: - Description: 'Prefer x.nil? to x == nil.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods' - Enabled: false - -Style/NonNilCheck: - Description: 'Checks for redundant nil checks.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-non-nil-checks' - Enabled: false - -Style/Not: - Description: 'Use ! instead of not.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bang-not-not' - Enabled: false - -Style/NumericLiterals: - Description: >- - Add underscores to large numeric literals to improve their - readability. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#underscores-in-numerics' - Enabled: false - -Style/OneLineConditional: - Description: >- - Favor the ternary operator(?:) over - if/then/else/end constructs. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#ternary-operator' - Enabled: false - -Style/OpMethod: - Description: 'When defining binary operators, name the argument other.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg' - Enabled: false - -Style/OptionalArguments: - Description: >- - Checks for optional arguments that do not appear at the end - of the argument list - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#optional-arguments' - Enabled: false - -Style/ParallelAssignment: - Description: >- - Check for simple usages of parallel assignment. - It will only warn when the number of variables - matches on both sides of the assignment. - This also provides performance benefits - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parallel-assignment' - Enabled: false - -Style/ParenthesesAroundCondition: - Description: >- - Don't use parentheses around the condition of an - if/unless/while. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-parens-if' - Enabled: false - -Style/PercentLiteralDelimiters: - Description: 'Use `%`-literal delimiters consistently' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-literal-braces' - Enabled: false - -Style/PercentQLiterals: - Description: 'Checks if uses of %Q/%q match the configured preference.' - Enabled: false - -Style/PerlBackrefs: - Description: 'Avoid Perl-style regex back references.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers' - Enabled: false - -Style/PredicateName: - Description: 'Check the names of predicate methods.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark' - Enabled: false - -Style/Proc: - Description: 'Use proc instead of Proc.new.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#proc' - Enabled: false - -Style/RaiseArgs: - Description: 'Checks the arguments passed to raise/fail.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#exception-class-messages' - Enabled: false - -Style/RedundantBegin: - Description: "Don't use begin blocks when they are not needed." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#begin-implicit' - Enabled: false - -Style/RedundantException: - Description: "Checks for an obsolete RuntimeException argument in raise/fail." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-runtimeerror' - Enabled: false - -Style/RedundantReturn: - Description: "Don't use return where it's not required." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-explicit-return' - Enabled: false - -Style/RedundantSelf: - Description: "Don't use self where it's not needed." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-self-unless-required' - Enabled: false - + Description: Prefer the keyword for easier discoverability. + EnforcedStyle: literal Style/RegexpLiteral: - Description: 'Use / or %r around regular expressions.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-r' - Enabled: false - -Style/RescueEnsureAlignment: - Description: 'Align rescues and ensures correctly.' - Enabled: false - -Style/RescueModifier: - Description: 'Avoid using rescue in its modifier form.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-rescue-modifiers' - Enabled: false - -Style/SelfAssignment: - Description: >- - Checks for places where self-assignment shorthand should have - been used. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#self-assignment' - Enabled: false - -Style/Semicolon: - Description: "Don't use semicolons to terminate expressions." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon' - Enabled: false - -Style/SignalException: - Description: 'Checks for proper usage of fail and raise.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#fail-method' - Enabled: false - -Style/SingleLineBlockParams: - Description: 'Enforces the names of some block params.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#reduce-blocks' - Enabled: false - -Style/SingleLineMethods: - Description: 'Avoid single-line methods.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-single-line-methods' - Enabled: false - -Style/SpaceBeforeFirstArg: - Description: >- - Checks that exactly one space is used between a method name - and the first argument for method calls without parentheses. + Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 + EnforcedStyle: percent_r +Style/TernaryParentheses: + Description: Checks for use of parentheses around ternary conditions. Enforce parentheses + on complex expressions for better readability, but seriously consider breaking + it up. + EnforcedStyle: require_parentheses_when_complex +Style/TrailingCommaInArguments: + Description: Prefer always trailing comma on multiline argument lists. This makes + diffs, and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/TrailingCommaInLiteral: + Description: Prefer always trailing comma on multiline literals. This makes diffs, + and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/SymbolArray: + Description: Using percent style obscures symbolic intent of array's contents. + EnforcedStyle: brackets +RSpec/MessageSpies: + EnforcedStyle: receive +Style/Documentation: + Exclude: + - lib/puppet/parser/functions/**/* + - spec/**/* +Style/WordArray: + EnforcedStyle: brackets +Style/CollectionMethods: Enabled: true - -Style/SpaceAfterColon: - Description: 'Use spaces after colons.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' - Enabled: false - -Style/SpaceAfterComma: - Description: 'Use spaces after commas.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' - Enabled: false - -Style/SpaceAroundKeyword: - Description: 'Use spaces around keywords.' - Enabled: false - -Style/SpaceAfterMethodName: - Description: >- - Do not put a space between a method name and the opening - parenthesis in a method definition. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces' - Enabled: false - -Style/SpaceAfterNot: - Description: Tracks redundant space after the ! operator. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-bang' - Enabled: false - -Style/SpaceAfterSemicolon: - Description: 'Use spaces after semicolons.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' - Enabled: false - -Style/SpaceBeforeBlockBraces: - Description: >- - Checks that the left block brace has or doesn't have space - before it. - Enabled: false - -Style/SpaceBeforeComma: - Description: 'No spaces before commas.' +Style/MethodCalledOnDoEndBlock: + Enabled: true +Style/StringMethods: + Enabled: true +Layout/EndOfLine: Enabled: false - -Style/SpaceBeforeComment: - Description: >- - Checks for missing space between code and a comment on the - same line. +Layout/IndentHeredoc: Enabled: false - -Style/SpaceBeforeSemicolon: - Description: 'No spaces before semicolons.' +Metrics/AbcSize: Enabled: false - -Style/SpaceInsideBlockBraces: - Description: >- - Checks that block braces have or don't have surrounding space. - For blocks taking parameters, checks that the left brace has - or doesn't have trailing space. +Metrics/BlockLength: Enabled: false - -Style/SpaceAroundBlockParameters: - Description: 'Checks the spacing inside and after block parameters pipes.' +Metrics/ClassLength: Enabled: false - -Style/SpaceAroundEqualsInParameterDefault: - Description: >- - Checks that the equals signs in parameter default assignments - have or don't have surrounding space depending on - configuration. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-around-equals' +Metrics/CyclomaticComplexity: Enabled: false - -Style/SpaceAroundOperators: - Description: 'Use a single space around operators.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' +Metrics/MethodLength: Enabled: false - -Style/SpaceInsideBrackets: - Description: 'No spaces after [ or before ].' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces' +Metrics/ModuleLength: Enabled: false - -Style/SpaceInsideHashLiteralBraces: - Description: "Use spaces inside hash literal braces - or don't." - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-operators' +Metrics/ParameterLists: Enabled: false - -Style/SpaceInsideParens: - Description: 'No spaces after ( or before ).' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces' +Metrics/PerceivedComplexity: Enabled: false - -Style/SpaceInsideRangeLiteral: - Description: 'No spaces inside range literals.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-space-inside-range-literals' +RSpec/DescribeClass: Enabled: false - -Style/SpaceInsideStringInterpolation: - Description: 'Checks for padding/surrounding spaces inside string interpolation.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#string-interpolation' +RSpec/ExampleLength: Enabled: false - -Style/SpecialGlobalVars: - Description: 'Avoid Perl-style global variables.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms' +RSpec/MessageExpectation: Enabled: false - -Style/StringLiterals: - Description: 'Checks if uses of quotes match the configured preference.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-string-literals' +RSpec/MultipleExpectations: Enabled: false - -Style/StringLiteralsInInterpolation: - Description: >- - Checks if uses of quotes inside expressions in interpolated - strings match the configured preference. +RSpec/NestedGroups: Enabled: false - -Style/StructInheritance: - Description: 'Checks for inheritance from Struct.new.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-extend-struct-new' +Style/AsciiComments: Enabled: false - -Style/SymbolLiteral: - Description: 'Use plain symbols instead of string symbols when possible.' +Style/IfUnlessModifier: Enabled: false - Style/SymbolProc: - Description: 'Use symbols as procs instead of blocks when possible.' - Enabled: false - -Style/Tab: - Description: 'No hard tabs.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#spaces-indentation' - Enabled: false - -Style/TrailingBlankLines: - Description: 'Checks trailing blank lines and final newline.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#newline-eof' - Enabled: false - -Style/TrailingCommaInArguments: - Description: 'Checks for trailing comma in parameter lists.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-params-comma' - Enabled: false - -Style/TrailingCommaInLiteral: - Description: 'Checks for trailing comma in literals.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas' - Enabled: false - -Style/TrailingWhitespace: - Description: 'Avoid trailing whitespace.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace' - Enabled: false - -Style/TrivialAccessors: - Description: 'Prefer attr_* methods to trivial readers/writers.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family' - Enabled: false - -Style/UnlessElse: - Description: >- - Do not use unless with else. Rewrite these with the positive - case first. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-else-with-unless' - Enabled: false - -Style/UnneededCapitalW: - Description: 'Checks for %W when interpolation is not needed.' - Enabled: false - -Style/UnneededPercentQ: - Description: 'Checks for %q/%Q when single quotes or double quotes would do.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q' - Enabled: false - -Style/TrailingUnderscoreVariable: - Description: >- - Checks for the usage of unneeded trailing underscores at the - end of parallel variable assignment. - Enabled: false - -Style/VariableInterpolation: - Description: >- - Don't interpolate global, instance and class variables - directly in strings. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#curlies-interpolate' - Enabled: false - -Style/VariableName: - Description: 'Use the configured style when naming variables.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars' - Enabled: false - -Style/WhenThen: - Description: 'Use when x then ... for one-line cases.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#one-line-cases' - Enabled: false - -Style/WhileUntilDo: - Description: 'Checks for redundant do after while or until.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-multiline-while-do' - Enabled: false - -Style/WhileUntilModifier: - Description: >- - Favor modifier while/until usage when you have a - single-line body. - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#while-as-a-modifier' - Enabled: false - -Style/WordArray: - Description: 'Use %w or %W for arrays of words.' - StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-w' Enabled: false diff --git a/.travis.yml b/.travis.yml index 3307730..c948f3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,47 @@ --- +sudo: false +dist: trusty language: ruby -bundler_args: --without development system_tests -before_install: rm Gemfile.lock || true - -# drop support for ruby 1.9.3 due to json_pure -# dropped support for 2.0.0 since deprication warning causes Travis CI failures - +cache: bundler +before_install: + - bundle -v + - rm -f Gemfile.lock + - gem update --system + - gem --version + - bundle -v +script: + - 'bundle exec rake $CHECK' +bundler_args: --without system_tests rvm: - - 2.1.5 - - 2.1.9 - -script: bundle exec rake test - -# drop support for very old 3.x series of Puppet + - 2.5.0 env: - matrix: - - PUPPET_GEM_VERSION="~> 3.8" - - PUPPET_GEM_VERSION="~> 4.8.0" # PE 201x.y.z - - PUPPET_GEM_VERSION="~> 4.10.4" # Latest 2017-07-20 - -addons: - code_climate: - repo_token: 1d699cad8d8d5a2ebbe437105276e862e3acd77fbd635a7225c50476b36e8c5a + global: + - BEAKER_PUPPET_COLLECTION=puppet6 PUPPET_GEM_VERSION="~> 6.0" +matrix: + fast_finish: true + include: + - + env: CHECK="syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop" + - + env: CHECK=parallel_spec + - + env: PUPPET_GEM_VERSION="~> 5.0" CHECK=parallel_spec + rvm: 2.4.4 + - + env: PUPPET_GEM_VERSION="~> 4.0" CHECK=parallel_spec + rvm: 2.1.9 +branches: + only: + - master + - /^v\d/ +notifications: + email: false +deploy: + provider: puppetforge + user: puppet + password: + secure: "" + on: + tags: true + all_branches: true + condition: "$DEPLOY_TO_FORGE = yes" 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 b/CHANGELOG index ab9e320..2b34505 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +2018-11-23 Release 1.0.0 +- Rename class to follow Rubocop standards +- PDK 1.7.1 compatibility + 2017-10-23 Release 0.2.1 - Use exit? for puppet/file_system diff --git a/Gemfile b/Gemfile index 97366e0..731dc74 100644 --- a/Gemfile +++ b/Gemfile @@ -1,40 +1,72 @@ -source "https://rubygems.org" - -group :test do - gem "rake" - gem "listen","2.1.0" - gem "puppet", ENV["PUPPET_VERSION"] || "~> 4.10.0" - gem "rspec-puppet", :git => "https://github.com/rodjek/rspec-puppet.git" - gem "rspec-puppet-utils", :git => "https://github.com/Accuity/rspec-puppet-utils.git" - gem "hiera-puppet-helper", :git => "https://github.com/bobtfish/hiera-puppet-helper.git" - gem "puppetlabs_spec_helper" - gem "puppet-syntax" - gem "puppet-lint" - gem "metadata-json-lint" +# frozen_string_literal: true + +source ENV['GEM_SOURCE'] || 'https://rubygems.org' + +def location_for(place_or_version, fake_version = nil) + git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?} + file_url_regex = %r{\Afile:\/\/(?.*)} + + 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 +ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments +minor_version = ruby_version_segments[0..1].join('.') + group :development do - gem "travis" - gem "travis-lint" - gem "vagrant-wrapper" - gem "puppet-blacksmith" - gem "guard-rake" + gem "puppet-module-posix-default-r#{minor_version}", require: false, platforms: [:ruby] + gem "puppet-module-posix-dev-r#{minor_version}", require: false, platforms: [:ruby] + gem "puppet-module-win-default-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "puppet-module-win-dev-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem 'fast_gettext', '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') + gem 'fast_gettext', require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') + gem 'json', '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') + gem 'json', '<= 2.0.4', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.4.4') + gem 'json_pure', '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') end -group :system_tests do - if RUBY_VERSION < "2.2.5" - # lock beaker version - gem "beaker", "~> 2.0" - gem "beaker-rspec", "~> 5.6" - # lock nokogirii - gem "nokogiri", "1.8.1" - else - gem "beaker" - gem "beaker-rspec" - gem "nokogiri" - 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 + +if Gem.win_platform? && puppet_version =~ %r{^(file:///|git://)} + # If we're using a Puppet gem on Windows which handles its own win32-xxx gem + # dependencies (>= 3.5.0), set the maximum versions (see PUP-6445). + gems['win32-dir'] = ['<= 0.4.9', require: false] + gems['win32-eventlog'] = ['<= 0.6.5', require: false] + gems['win32-process'] = ['<= 0.7.5', require: false] + gems['win32-security'] = ['<= 0.2.5', require: false] + gems['win32-service'] = ['0.8.8', require: false] end -# codeclimate -gem "simplecov", :require => false -gem "codeclimate-test-reporter", :require => false +gems.each do |gem_name, gem_params| + gem gem_name, *gem_params +end + +# 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/Guardfile b/Guardfile index fd50602..a503758 100644 --- a/Guardfile +++ b/Guardfile @@ -1,5 +1,7 @@ +# frozen_string_literal: true + notification :off -guard 'rake', :task => 'test' do +guard 'rake', task: 'test' do watch(%r{^manifests\/(.+)\.pp$}) end diff --git a/Rakefile b/Rakefile index 970368d..a577e7b 100644 --- a/Rakefile +++ b/Rakefile @@ -1,54 +1,76 @@ +# frozen_string_literal: true + require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet/vendor/semantic/lib/semantic' -require 'puppet-lint/tasks/puppet-lint' require 'puppet-syntax/tasks/puppet-syntax' +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? -# Fixes conflicts with Puppet Labs vendored semantic gem and metadata-rake-lint -require 'puppet/version' -require 'puppet/vendor/semantic/lib/semantic' unless Puppet.version.to_f <3.6 - -# These gems aren't always present, for instance -# on Travis with --without development -begin - require 'puppet_blacksmith/rake_tasks' -rescue LoadError +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 -Rake::Task[:lint].clear - -PuppetLint.configuration.relative = true -PuppetLint.configuration.send("disable_80chars") -PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" -PuppetLint.configuration.fail_on_warnings = true - -# Forsake support for Puppet 2.6.2 for the benefit of cleaner code. -# http://puppet-lint.com/checks/class_parameter_defaults/ -PuppetLint.configuration.send('disable_class_parameter_defaults') -# http://puppet-lint.com/checks/class_inherits_from_params_class/ -PuppetLint.configuration.send('disable_class_inherits_from_params_class') - -exclude_paths = [ - "bundle/**/*", - "pkg/**/*", - "vendor/**/*", - "spec/**/*", -] -PuppetLint.configuration.ignore_paths = exclude_paths -PuppetSyntax.exclude_paths = exclude_paths - -desc "Run acceptance tests" -RSpec::Core::RakeTask.new(:acceptance) do |t| - t.pattern = 'spec/acceptance' +def changelog_project + return unless Rake.application.top_level_tasks.include? 'changelog' + returnVal = nil || JSON.load(File.read('metadata.json'))['name'] + raise 'unable to find the changelog_project in .sync.yml or the name in metadata.json' if returnVal.nil? + puts "GitHubChangelogGenerator project:#{returnVal}" + returnVal end -task :metadata do - sh "metadata-json-lint metadata.json" +def changelog_future_release + return unless Rake.application.top_level_tasks.include? 'changelog' + returnVal = 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 "Run syntax, lint, and spec tests." -task :test => [ - :syntax, - :lint, - :spec, - :metadata_lint, -] +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') && ENV['CHANGELOG_GITHUB_TOKEN'].nil? + config.user = changelog_user.to_s + config.project = changelog_project.to_s + config.future_release = changelog_future_release.to_s + 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; GO LABEL THEM' + config.configure_sections = { + 'Changed' => { + 'prefix' => '### Changed', + 'labels' => ['backwards-incompatible'] + }, + 'Added' => { + 'prefix' => '### Added', + 'labels' => ['feature', 'enhancement'] + }, + 'Fixed' => { + 'prefix' => '### Fixed', + 'labels' => ['bugfix'] + } + } + end +else + desc 'Generate a Changelog from GitHub' + task :changelog do + raise <= Gem::Version.new('2.2.2')" +EOM + end +end diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..bb60864 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,60 @@ +--- +version: 1.1.x.{build} +skip_commits: + message: /^\(?doc\)?.*/ +clone_depth: 10 +init: + - SET + - 'mkdir C:\ProgramData\PuppetLabs\code && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\facter && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\hiera && exit 0' + - 'mkdir C:\ProgramData\PuppetLabs\puppet\var && exit 0' +environment: + matrix: + - + RUBY_VERSION: 24-x64 + CHECK: syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop + - + PUPPET_GEM_VERSION: ~> 4.0 + RUBY_VERSION: 21 + CHECK: parallel_spec + - + PUPPET_GEM_VERSION: ~> 4.0 + RUBY_VERSION: 21-x64 + CHECK: parallel_spec + - + PUPPET_GEM_VERSION: ~> 5.0 + RUBY_VERSION: 24 + CHECK: parallel_spec + - + PUPPET_GEM_VERSION: ~> 5.0 + RUBY_VERSION: 24-x64 + CHECK: parallel_spec + - + 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/lib/facter/util/facter_cacheable.rb b/lib/facter/util/facter_cacheable.rb old mode 100644 new mode 100755 index e60ae36..a9de004 --- a/lib/facter/util/facter_cacheable.rb +++ b/lib/facter/util/facter_cacheable.rb @@ -1,4 +1,6 @@ #!/usr/bin/ruby +# frozen_string_literal: true + # # Provide a caching API for facter facts. # @@ -12,12 +14,14 @@ # See LICENSE for licensing. # # +require 'English' require 'facter' require 'time' require 'yaml' -module Facter::Util::Facter_cacheable - @doc=< e - Facter.debug("#{e.backtrace[0]}: #{$!}.") - cache = nil - cache_time = Time.at(0) - end + if File.exist?(cache_file) + begin + cache = YAML.load_file(cache_file) + # returns [{}] structures if valid for Cached Facts + cache = cache[0] if cache.is_a? Array + cache = nil unless cache.is_a? Hash + cache_time = File.mtime(cache_file) + rescue StandardError => e + Facter.debug("#{e.backtrace[0]}: #{$ERROR_INFO}.") + cache = nil + cache_time = Time.at(0) + end end - if ! cache || (Time.now - cache_time) > ttl - cache = nil + if !cache || (Time.now - cache_time) > ttl + cache = nil end cache end @@ -60,59 +64,67 @@ def cached?(key, ttl = 3600, source = nil) # @return [object] Cached value (hash, string, array, number, etc) # @api public def cache(key, value, source = nil) - if key && value - mycache = get_cache(key, source) - cache_file = mycache[:file] - cache_dir = mycache[:dir] - begin - # Changed to recursively create directories for facts. - if !cache_dir.nil? && !File::exist?(cache_dir) - recursive = cache_dir.split('/') - directory = '' - recursive.each do |sub_directory| - directory += sub_directory + '/' - Dir.mkdir(directory) unless (File::directory?(directory)) - end - # Dir.mkdir(cache_dir) - end - # don't use the Rubyist standard pattern so we can test with rspec - out = File.open(cache_file, 'w') - YAML.dump({(key.to_s) => value}, out) - out.close() - rescue Exception => e - Facter.debug("#{e.backtrace[0]}: #{$!}.") - end - end + if key.nil? || value.nil? + raise ArgumentError, 'Missing key or value to store' + end + mycache = find_cache(key, source) + make_cache_path(mycache[:dir]) unless mycache[:dir].nil? + # don't use the Rubyist standard pattern so we can test with rspec + begin + out = File.open(mycache[:file], 'w') + YAML.dump({ key.to_s => value }, out) + out.close + rescue StandardError => e + Facter.debug("Unable to write to cache #{mycache[:file]}: #{e.backtrace[0]}: #{$ERROR_INFO}.") + end + end + + # make a cache + # @param file String The file + # @param dir String The location for the file + # @api private + def make_cache_path(cache_dir) + # Changed to recursively create directories for facts. + if !cache_dir.nil? && !File.exist?(cache_dir) + recursive = cache_dir.split('/') + directory = '' + recursive.each do |sub_directory| + directory += sub_directory + '/' + Dir.mkdir(directory) unless File.directory?(directory) + end + # Dir.mkdir(cache_dir) + end + rescue StandardError => e + Facter.debug("Unable to create path #{cache_dir} for a cache file #{e.backtrace[0]}: #{$ERROR_INFO}.") end # find a source # @param key [symbol] The identifier to use # @return file [string, string] The cachefile location # @api private - def get_cache(key, source) - if ! key - raise ArgumentError, 'No key was provided to check' - end - if ! source - cache_dir = '/etc/facter/facts.d' - if Puppet.features.external_facts? - for dir in Facter.search_external_path - # the plugin facts directory in /var/lib is cleaned each run - # Exclude default pluginsync directory for PE 2016.2 - if ((File.exist?(dir)) and (dir != '/opt/puppetlabs/puppet/cache/facts.d')) - #dir != '/var/lib/puppet/facts.d' and - cache_dir = dir - break - end - end - end - keystring = key.to_s - cache_file = "#{cache_dir}/#{keystring}.yaml" - else - cache_dir = File.dirname(source) - cache_file = source - end - {:file => cache_file, :dir => cache_dir } + def find_cache(key, source) + unless key + raise ArgumentError, 'No key was provided to check' + end + if !source + cache_dir = '/etc/facter/facts.d' + if Puppet.features.external_facts? + Facter.search_external_path.each do |dir| + # the plugin facts directory in /var/lib is cleaned each run + # Exclude default pluginsync directory for PE 2016.2 + next unless File.exist?(dir) && (dir != '/opt/puppetlabs/puppet/cache/facts.d') + # dir != '/var/lib/puppet/facts.d' and + cache_dir = dir + break + end + end + keystring = key.to_s + cache_file = "#{cache_dir}/#{keystring}.yaml" + else + cache_dir = File.dirname(source) + cache_file = source + end + { file: cache_file, dir: cache_dir } end end end diff --git a/lib/puppet/feature/facter_cacheable.rb b/lib/puppet/feature/facter_cacheable.rb old mode 100644 new mode 100755 index d4bc802..7817371 --- a/lib/puppet/feature/facter_cacheable.rb +++ b/lib/puppet/feature/facter_cacheable.rb @@ -1,4 +1,6 @@ #!/usr/bin/ruby +# frozen_string_literal: true + # # Puppet feature for the facter_cachable utility # @@ -14,14 +16,14 @@ Puppet.features.add(:facter_cacheable) do require 'time' require 'yaml' - if (Puppet::Util::Package.versioncmp(Puppet.version, "5.0.0") > 0) or Puppet.features.external_facts? + if Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0').positive? || Puppet.features.external_facts? # use external location - for dir in Facter.search_external_path + Facter.search_external_path.each do |dir| Puppet::FileSystem.exist?(dir) end else # use default - if !Puppet::Util::Platform.windows? + unless Puppet::Util::Platform.windows? Puppet::FileSystem.exist?('/var/lib/puppet/facts.d') end end diff --git a/metadata.json b/metadata.json index 33304fb..c52a571 100644 --- a/metadata.json +++ b/metadata.json @@ -1,65 +1,76 @@ { "name": "waveclaw-facter_cacheable", - "version": "0.2.2", + "version": "1.0.0", "author": "JD Powell ", "summary": "Provide a Cache for Facter facts", "license": "Apache-2.0", "source": "https://github.com/waveclaw/puppet-facter_cacheable", "project_page": "https://github.com/waveclaw/puppet-facter_cacheable", "issues_url": "https://github.com/waveclaw/puppet-facter_cacheable/issues", + "dependencies": [ + + ], "operatingsystem_support": [ - { - "operatingsystem":"AIX", - "operatingsystemrelease":[ - "5.3", - "6.1", - "7.1" - ] - }, - { - "operatingsystem":"Solaris", - "operatingsystemrelease":[ - "5.10", - "5.11" - ] - }, - { - "operatingsystem":"SLES", - "operatingsystemrelease":[ - "12.1", - "12.2", - "12.3" - ] - }, - { - "operatingsystem":"openSUSE", - "operatingsystemrelease":[ - "42.1", - "42.2", - "42.3" - ] - }, - { - "operatingsystem":"RedHat", - "operatingsystemrelease":[ - "6.0", - "7.0" - ] - }, - { - "operatingsystem":"CentOS", - "operatingsystemrelease":[ - "6.0", - "7.0" - ] - }, - { - "operatingsystem":"Scientific", - "operatingsystemrelease":[ - "6.0", - "7.0" - ] - } + { + "operatingsystem": "AIX", + "operatingsystemrelease": [ + "5.3", + "6.1", + "7.1" + ] + }, + { + "operatingsystem": "Solaris", + "operatingsystemrelease": [ + "5.10", + "5.11" + ] + }, + { + "operatingsystem": "SLES", + "operatingsystemrelease": [ + "12.1", + "12.2", + "12.3" + ] + }, + { + "operatingsystem": "openSUSE", + "operatingsystemrelease": [ + "42.1", + "42.2", + "42.3" + ] + }, + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "6.0", + "7.0" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "6.0", + "7.0" + ] + }, + { + "operatingsystem": "Scientific", + "operatingsystemrelease": [ + "6.0", + "7.0" + ] + } + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">= 4.7.0 < 7.0.0" + } ], - "dependencies": [ ] + "pdk-version": "1.7.1", + "template-url": "file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git", + "template-ref": "1.7.1-0-g810b982" } diff --git a/spec/acceptance/class_spec.rb b/spec/acceptance/class_spec.rb index b0f97f8..54017e0 100644 --- a/spec/acceptance/class_spec.rb +++ b/spec/acceptance/class_spec.rb @@ -1,17 +1,18 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'facter_cacheable class' do - context 'default parameters' do # Using puppet_apply as a helper - it 'should work idempotently with no errors' do + it 'works idempotently with no errors' do pp = <<-EOS class { 'facter_cacheable': } EOS # 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 describe package('facter_cacheable') do diff --git a/spec/classes/coverage_spec.rb b/spec/classes/coverage_spec.rb index 12513b8..0548dd4 100644 --- a/spec/classes/coverage_spec.rb +++ b/spec/classes/coverage_spec.rb @@ -1 +1,3 @@ +# frozen_string_literal: true + at_exit { RSpec::Puppet::Coverage.report! } diff --git a/spec/classes/facter_cacheable_spec.rb b/spec/classes/facter_cacheable_spec.rb index 72aad63..24d0a22 100644 --- a/spec/classes/facter_cacheable_spec.rb +++ b/spec/classes/facter_cacheable_spec.rb @@ -1,13 +1,18 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'facter_cacheable' do context 'on supported operating systems' do ['Debian', 'RedHat', 'AIX', 'Solaris', 'SuSE'].each do |osfamily| describe "without any parameters on #{osfamily}" do - let(:params) {{ }} - let(:facts) {{ - :osfamily => osfamily, - }} + let(:params) { {} } + let(:facts) do + { + osfamily: osfamily, + } + end + it { is_expected.to compile.with_all_deps } it { is_expected.to contain_class('facter_cacheable') } end @@ -16,12 +21,15 @@ context 'unsupported operating system' do describe 'facter_cacheable class without any parameters on Windows' do - let(:facts) {{ - :osfamily => 'Microsoft', - :operatingsystem => 'Windows', - }} - let(:params) {{ }} - it { expect { is_expected.to contain_class('facter_cacheable') }.to raise_error(Puppet::Error, /Windows is not supported/) } + let(:facts) do + { + osfamily: 'Microsoft', + operatingsystem: 'Windows', + } + end + let(:params) { {} } + + it { expect { is_expected.to contain_class('facter_cacheable') }.to raise_error(Puppet::Error, %r{Windows is not supported}) } end end end diff --git a/spec/default_facts.yml b/spec/default_facts.yml new file mode 100644 index 0000000..e10d991 --- /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. +--- +concat_basedir: "" +ipaddress: "172.16.254.254" +is_pe: false +macaddress: "AA:AA:AA:AA:AA:AA" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1a40dd2..a286a84 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,46 @@ +# frozen_string_literal: true + require 'puppetlabs_spec_helper/module_spec_helper' +require 'rspec-puppet-facts' + +begin + require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) +rescue LoadError => loaderror + warn "Could not require spec_helper_local: #{loaderror.message}" +end + +include RspecPuppetFacts + +default_facts = { + puppetversion: Puppet.version, + facterversion: Facter.version, +} + +default_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')) +default_module_facts_path = File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')) + +if File.exist?(default_facts_path) && File.readable?(default_facts_path) + default_facts.merge!(YAML.safe_load(File.read(default_facts_path))) +end + +if File.exist?(default_module_facts_path) && File.readable?(default_module_facts_path) + default_facts.merge!(YAML.safe_load(File.read(default_module_facts_path))) +end RSpec.configure do |c| - c.formatter = 'documentation' - c.mock_with :rspec + 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 + end end + +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) + last_module.const_get(next_module) + end +end + +# 'spec_overrides' from sync.yml will appear below this line diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 425c7a7..5065f26 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'beaker-rspec/spec_helper' require 'beaker-rspec/helpers/serverspec' @@ -22,9 +24,9 @@ # Configure all nodes in nodeset c.before :suite do # Install module and dependencies - puppet_module_install(:source => proj_root, :module_name => 'facter_cacheable') - #hosts.each do |host| + puppet_module_install(source: proj_root, module_name: 'facter_cacheable') + # hosts.each do |host| # on host, puppet('module', 'install', 'puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] } - #end + # end end end diff --git a/spec/spec_helper_local.rb b/spec/spec_helper_local.rb new file mode 100644 index 0000000..ca291e8 --- /dev/null +++ b/spec/spec_helper_local.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'simplecov' + +SimpleCov.start do + add_filter '/spec/' + # Exclude bundled Gems in typical locations + add_filter '/.vendor/' + add_filter '/.bundle/' +end + +RSpec.configure do |c| + c.mock_with :rspec +end diff --git a/spec/unit/facter_cacheable_spec.rb b/spec/unit/facter_cacheable_spec.rb old mode 100644 new mode 100755 index 17a6a89..84920a3 --- a/spec/unit/facter_cacheable_spec.rb +++ b/spec/unit/facter_cacheable_spec.rb @@ -1,4 +1,6 @@ #!/usr/bin/ruby -S rspec +# frozen_string_literal: false + # # Test the facter_cachable utility # @@ -15,186 +17,211 @@ require 'facter/util/facter_cacheable' data = { - :single => "--- \n string_value: tested", - :list_like => "--- \n list_value: \n - thing1\n - thing2", - :hash_like => - "--- \n hash_value: \n alpha: one\n beta: two\n tres: three", + single: "--- \n string_value: tested", + list_like: "--- \n list_value: \n - thing1\n - thing2", + hash_like: "--- \n hash_value: \n alpha: one\n beta: two\n tres: three", } # reformat each of the keys using the local YAML format convention # this is needed do to spacing changes between Ruby 1.9, 2.0 and 2.1. -data.keys.each { |testcase| - data[testcase] = YAML.dump(YAML.load(data[testcase])) -} +data.keys.each do |testcase| + data[testcase] = YAML.dump(YAML.safe_load(data[testcase])) +end # YAML.load* does not return symbols as hash keys! expected = { - :single => { "string_value" => 'tested' }, - :list_like => { "list_value" => [ 'thing1', 'thing2' ] }, - :hash_like => { "hash_value" => { - 'alpha' => 'one', 'beta' => 'two', 'tres' => 'three' } } + single: { 'string_value' => 'tested' }, + list_like: { 'list_value' => ['thing1', 'thing2'] }, + hash_like: { 'hash_value' => { + 'alpha' => 'one', 'beta' => 'two', 'tres' => 'three' + } }, } - -describe "Facter::Util::Facter_cacheable.cached?", :type => :function do - -context "when the cache is hot" do -data.keys.each { |testcase| - cache = "/tmp/#{testcase.to_s}.yaml" - rawdata = StringIO.new(data[testcase]) - it "for #{testcase.to_s} values should return the cached value" do - expect(Puppet.features).to receive(:external_facts?) { true } - expect(Facter).to receive(:search_external_path) { ['/tmp'] } - expect(File).to receive(:exist?).with('/tmp') { true } # get_cache - expect(File).to receive(:exist?).with(cache) { true } - expect(YAML).to receive(:load_file).with(cache) { - YAML.load_stream(rawdata) - } - expect(File).to receive(:mtime).with(cache) { Time.now } - expect(Facter::Util::Facter_cacheable.cached?(testcase)).to eq( - expected[testcase]) - end - } - end - - context "when the cache is cold" do - data.keys.each { |testcase| - cache = "/tmp/#{testcase.to_s}.yaml" +describe 'Facter::Util::FacterCacheable' do + describe 'Facter::Util::FacterCacheable.cached?', type: :function do + context 'when the cache is hot' do + data.keys.each do |testcase| + cache = "/tmp/#{testcase}.yaml" rawdata = StringIO.new(data[testcase]) - it "for #{testcase.to_s} values should return nothing" do - expect(Puppet.features).to receive(:external_facts?) { true } - expect(Facter).to receive(:search_external_path) { ['/tmp'] } - expect(File).to receive(:exist?).with('/tmp') { true } # get_cache - expect(File).to receive(:exist?).with(cache) { true } + it "for #{testcase} values should return the cached value" do + expect(Puppet.features).to receive(:external_facts?).and_return(true) + expect(Facter).to receive(:search_external_path).and_return(['/tmp']) + expect(File).to receive(:exist?).with('/tmp').and_return(true) # find_cache + expect(File).to receive(:exist?).with(cache).and_return(true) expect(YAML).to receive(:load_file).with(cache) { YAML.load_stream(rawdata) } - expect(File).to receive(:mtime).with(cache) { Time.at(0) } - expect(Facter::Util::Facter_cacheable.cached?(testcase)).to eq(nil) + expect(File).to receive(:mtime).with(cache).and_return(Time.now) + expect(Facter::Util::FacterCacheable.cached?(testcase)).to eq( + expected[testcase], + ) end - } - end - - context "when the cache is missing" do - data.keys.each { |testcase| - cache = "/tmp/#{testcase.to_s}.yaml" + end + end + context 'when the cache is cold' do + data.keys.each do |testcase| + cache = "/tmp/#{testcase}.yaml" rawdata = StringIO.new(data[testcase]) - it "for #{testcase.to_s} values should return nothing" do - expect(Puppet.features).to receive(:external_facts?) { true } - expect(Facter).to receive(:search_external_path) { ['/tmp'] } - expect(File).to receive(:exist?).with('/tmp') { true } # get_cache - expect(File).to receive(:exist?).with(cache) { false } - expect(YAML).to_not receive(:load_file).with(cache) - expect(File).to_not receive(:mtime).with(cache) - expect(Facter::Util::Facter_cacheable.cached?(testcase)).to eq(nil) + it "for #{testcase} values should return nothing" do + expect(Puppet.features).to receive(:external_facts?).and_return(true) + expect(Facter).to receive(:search_external_path).and_return(['/tmp']) + expect(File).to receive(:exist?).with('/tmp').and_return(true) # find_cache + expect(File).to receive(:exist?).with(cache).and_return(true) + expect(YAML).to receive(:load_file).with(cache) { + YAML.load_stream(rawdata) + } + expect(File).to receive(:mtime).with(cache).and_return(Time.at(0)) + expect(Facter::Util::FacterCacheable.cached?(testcase)).to eq(nil) end - } - end - - context "for garbage values" do - cache = "/tmp/garbage.yaml" - rawdata = StringIO.new('random non-yaml garbage') - it "should return nothing" do - expect(Puppet.features).to receive(:external_facts?) { true } - expect(Facter).to receive(:search_external_path) { ['/tmp'] } - expect(File).to receive(:exist?).with('/tmp') { true } # get_cache - expect(File).to receive(:exist?).with(cache) { true } - expect(YAML).to receive(:load_file).with(cache) { + end + end + context 'when the cache is missing' do + data.keys.each do |testcase| + cache = "/tmp/#{testcase}.yaml" + it "for #{testcase} values should return nothing" do + expect(Puppet.features).to receive(:external_facts?).and_return(true) + expect(Facter).to receive(:search_external_path).and_return(['/tmp']) + expect(File).to receive(:exist?).with('/tmp').and_return(true) # find_cache + expect(File).to receive(:exist?).with(cache).and_return(false) + expect(YAML).not_to receive(:load_file).with(cache) + expect(File).not_to receive(:mtime).with(cache) + expect(Facter::Util::FacterCacheable.cached?(testcase)).to eq(nil) + end + end + end + context 'for garbage values' do + cache = '/tmp/garbage.yaml' + rawdata = StringIO.new('random non-yaml garbage') + it 'returns nothing' do + expect(Puppet.features).to receive(:external_facts?).and_return(true) + expect(Facter).to receive(:search_external_path).and_return(['/tmp']) + expect(File).to receive(:exist?).with('/tmp').and_return(true) # find_cache + expect(File).to receive(:exist?).with(cache).and_return(true) + expect(YAML).to receive(:load_file).with(cache) { YAML.load_stream(rawdata) - } - expect(File).to receive(:mtime).with(cache) { Time.now } - expect(Facter::Util::Facter_cacheable.cached?('garbage')).to eq(nil) + } + expect(File).to receive(:mtime).with(cache).and_return(Time.now) + expect(Facter::Util::FacterCacheable.cached?('garbage')).to eq(nil) + end end end -end - -describe "Facter::Util::Facter_cacheable.cache", :type => :fact do - data.keys.each { |testcase| - result = StringIO.new('') - key = (expected[testcase].keys)[0] - value = expected[testcase][key] - cache = "/tmp/#{key}.yaml" - it "should store a #{testcase.to_s} value in YAML" do - expect(Facter::Util::Facter_cacheable).to receive(:get_cache) { - {:dir => '/tmp', :file => cache } - } - expect(File).to receive(:open).with(cache, 'w') { result } - # WTF? called 785 times? - #expect(YAML).to receive(:dump).with({ key => value }, result) { - # YAML.dump({ key => value }, result) - #} - Facter::Util::Facter_cacheable.cache(key, value) - expect(result.string).to eq(data[testcase]) - end - } - context "for garbage input values" do - it "should sliently output nothing" do - result = StringIO.new('') - cache = "/tmp/.yaml" - expect(Facter::Util::Facter_cacheable - ).to_not receive(:get_cache).and_call_original - expect(File).to_not receive(:open).with(cache, 'w') { result } - Facter::Util::Facter_cacheable.cache(nil, nil) - expect(result.string).to eq('') + describe 'Facter::Util::FacterCacheable.cache', type: :fact do + context 'raises an error' do + it 'for missing arguments' do + expect { + Facter::Util::FacterCacheable.cache(nil, nil) + }.to raise_error(ArgumentError, %r{Missing key or value to store}) + end + it 'for failed cache writes' do + expect(Facter::Util::FacterCacheable).to receive(:find_cache).with( + 'thing', '/dev/null' + ).and_return(file: 'thing', dir: '/dev/null') + expect(Facter::Util::FacterCacheable).to receive(:make_cache_path).with('/dev/null') + expect(File).to receive(:open).with('thing', 'w') { throw IOError } + expect(Facter).to receive(:debug) + Facter::Util::FacterCacheable.cache('thing', 'value', '/dev/null') + end + end + context "if getting a cache's location fails" do + it 'skips trying to make that location' do + key = '' + value = '' + result = StringIO.new('') + cache = '/tmp/.yaml' + expect(Facter::Util::FacterCacheable).to receive(:find_cache).and_return( + dir: nil, file: cache, + ) + expect(Facter::Util::FacterCacheable).not_to receive(:make_cache_path) + expect(File).to receive(:open).with(cache, 'w').and_return(result) + result.rewind + expect(YAML).to receive(:dump).with({ key => value }, result).and_call_original + Facter::Util::FacterCacheable.cache(key, value) + expect(result.string).to eq("---\n'': ''\n") + end + end + data.keys.each do |testcase| + context "for #{testcase}" do + result = StringIO.new('') + key = expected[testcase].keys[0] + value = expected[testcase][key] + cache = "/tmp/#{key}.yaml" + filespec = { dir: '/tmp', file: cache } + it "stores a #{testcase} value in YAML" do + expect(Facter::Util::FacterCacheable).to receive(:find_cache).with(key, cache).and_return(filespec) + expect(Facter::Util::FacterCacheable).to receive(:make_cache_path).with(filespec[:dir]) + expect(File).to receive(:open).with(cache, 'w').and_return(result) + expect(YAML).to receive(:dump).with({ key => value }, result).and_call_original + Facter::Util::FacterCacheable.cache(key, value, cache) + expect(result.string).to eq(data[testcase]) + end + end end end # - # this tests use of an internal helper function instead of overall logic + # this tests an internal helper function instead of overall logic # - context "if getting a cache's location fails" do - it "should skip trying to make that location" do - result = StringIO.new('') - cache = "/tmp/.yaml" - expect(Facter::Util::Facter_cacheable).to receive(:get_cache) { - { :dir => nil, :file => cache } } - expect(File).to_not receive(:exist?).with(nil) - expect(Dir).to_not receive(:mkdir) - expect(File).to receive(:open).with(cache, 'w') { result } - Facter::Util::Facter_cacheable.cache('', '') - expect(result.string).to eq("---\n'': ''\n") + describe 'Facter::Util::FacterCacheable.make_cache_path', type: :fact do + it 'does nothing for empty arguments' do + expect(File).not_to receive(:exist?).with(nil) + Facter::Util::FacterCacheable.make_cache_path(nil) + end + it 'does nothing if there is an Error' do + expect(File).to receive(:exist?).with('/tmp/nothing') { throw IOError } + expect(Facter).to receive(:debug) + Facter::Util::FacterCacheable.make_cache_path('/tmp/nothing') + end + it 'checks for chached directories' do + expect(File).to receive(:exist?).with('/tmp/nothing').and_return(true) + expect(Dir).not_to receive(:mkdir) + Facter::Util::FacterCacheable.make_cache_path('/tmp/nothing') + end + it 'recursively makes a deep path' do + expect(File).to receive(:exist?).with('/this/is/deep/nothing').and_return(false) + ['/this/', '/this/is/', '/this/is/deep/', '/this/is/deep/nothing/'].each do |dir| + expect(Dir).to receive(:mkdir).with(dir) + end + Facter::Util::FacterCacheable.make_cache_path('/this/is/deep/nothing') end end -end -# -# this tests an internal helper function instead of overall logic -# -describe "Facter::Util::Facter_cacheable.get_cache", :type => :fact do - it "should return a dir for a key and directory" do - result = Facter::Util::Facter_cacheable.get_cache('foo', '/foo/bar') - expect(result).to eq({:file => '/foo/bar', :dir => '/foo' }) - end - it "should return current dir for a key with a directory" do - result = Facter::Util::Facter_cacheable.get_cache('foo', 'bar') - expect(result).to eq({:file => 'bar', :dir => '.' }) - end - it "should return the default path path for no source" do - default_path = '/etc/facter/facts.d' - expect(Puppet.features).to receive(:external_facts?) { false } - result = Facter::Util::Facter_cacheable.get_cache('foo', nil) - expect(result).to eq( - {:file => "#{default_path}/foo.yaml", :dir => default_path }) - end - it "should return a dir for a key and no directory" do - expect(Puppet.features).to receive(:external_facts?) { true } - expect(Facter).to receive(:search_external_path) { ['/tmp'] } - result = Facter::Util::Facter_cacheable.get_cache('foo', nil) - expect(result).to eq({:file => '/tmp/foo.yaml', :dir => '/tmp'}) - end - it "should check all paths when there are many" do - expect(Puppet.features).to receive(:external_facts?) { true } - expect(Facter).to receive(:search_external_path) { ['/a', 'b', '/tmp' ] } - expect(File).to receive(:exist?).with('/a') { false } - expect(File).to receive(:exist?).with('b') { false } - expect(File).to receive(:exist?).with('/tmp') { true } - result = Facter::Util::Facter_cacheable.get_cache('foo', nil) - expect(result).to eq({:file => '/tmp/foo.yaml', :dir => '/tmp'}) - end - it "should return an error for no key" do - expect { - Facter::Util::Facter_cacheable.get_cache(nil, nil) - }.to raise_error(ArgumentError, /No key/) - expect { - Facter::Util::Facter_cacheable.get_cache(nil, 'foo') - }.to raise_error(ArgumentError, /No key/) + describe 'Facter::Util::FacterCacheable.find_cache', type: :fact do + it 'returns a dir for a key and directory' do + result = Facter::Util::FacterCacheable.find_cache('foo', '/foo/bar') + expect(result).to eq(file: '/foo/bar', dir: '/foo') + end + it 'returns current dir for a key with a directory' do + result = Facter::Util::FacterCacheable.find_cache('foo', 'bar') + expect(result).to eq(file: 'bar', dir: '.') + end + it 'returns the default path path for no source' do + default_path = '/etc/facter/facts.d' + expect(Puppet.features).to receive(:external_facts?).and_return(false) + result = Facter::Util::FacterCacheable.find_cache('foo', nil) + expect(result).to eq( + file: "#{default_path}/foo.yaml", dir: default_path, + ) + end + it 'returns a dir for a key and no directory' do + expect(Puppet.features).to receive(:external_facts?).and_return(true) + expect(Facter).to receive(:search_external_path).and_return(['/tmp']) + result = Facter::Util::FacterCacheable.find_cache('foo', nil) + expect(result).to eq(file: '/tmp/foo.yaml', dir: '/tmp') + end + it 'checks all paths when there are many' do + expect(Puppet.features).to receive(:external_facts?).and_return(true) + expect(Facter).to receive(:search_external_path).and_return(['/a', 'b', '/tmp']) + expect(File).to receive(:exist?).with('/a').and_return(false) + expect(File).to receive(:exist?).with('b').and_return(false) + expect(File).to receive(:exist?).with('/tmp').and_return(true) + result = Facter::Util::FacterCacheable.find_cache('foo', nil) + expect(result).to eq(file: '/tmp/foo.yaml', dir: '/tmp') + end + it 'returns an error for no key' do + expect { + Facter::Util::FacterCacheable.find_cache(nil, nil) + }.to raise_error(ArgumentError, %r{No key}) + expect { + Facter::Util::FacterCacheable.find_cache(nil, 'foo') + }.to raise_error(ArgumentError, %r{No key}) + end end end