From bda68c794347cbf6b0eb2aa0a72a1694c4ef5e7b Mon Sep 17 00:00:00 2001 From: Steven Pritchard Date: Fri, 13 Dec 2024 16:14:15 -0600 Subject: [PATCH] Clean up for rubocop --- .github/workflows/pr_tests.yml | 11 +- .rubocop.yml | 699 ++++++++++++++++++ Gemfile | 11 +- lib/puppet/functions/simpkv/delete.rb | 17 +- lib/puppet/functions/simpkv/deletetree.rb | 17 +- lib/puppet/functions/simpkv/exists.rb | 17 +- lib/puppet/functions/simpkv/get.rb | 17 +- lib/puppet/functions/simpkv/list.rb | 23 +- lib/puppet/functions/simpkv/put.rb | 17 +- .../functions/simpkv/support/config/merge.rb | 14 +- .../simpkv/support/config/validate.rb | 38 +- .../functions/simpkv/support/key/validate.rb | 24 +- lib/puppet/functions/simpkv/support/load.rb | 31 +- lib/puppet_x/simpkv/file_plugin.rb | 126 ++-- lib/puppet_x/simpkv/ldap_plugin.rb | 295 ++++---- lib/puppet_x/simpkv/loader.rb | 12 +- lib/puppet_x/simpkv/plugin_template.rb | 42 +- lib/puppet_x/simpkv/simpkv.rb | 179 +++-- spec/acceptance/helpers.rb | 4 +- spec/acceptance/helpers/ldap_utils.rb | 150 ++-- spec/acceptance/helpers/manifest_utils.rb | 38 +- spec/acceptance/helpers/test_data.rb | 71 +- spec/acceptance/helpers/utils.rb | 55 +- spec/acceptance/shared_examples.rb | 4 +- .../shared_examples/pre_populate_keystores.rb | 18 +- .../shared_examples/simpkv_delete.rb | 51 +- .../shared_examples/simpkv_deletetree.rb | 89 ++- .../shared_examples/simpkv_exists.rb | 56 +- spec/acceptance/shared_examples/simpkv_get.rb | 28 +- .../acceptance/shared_examples/simpkv_list.rb | 28 +- .../shared_examples/simpkv_plugin.rb | 16 +- spec/acceptance/shared_examples/simpkv_put.rb | 48 +- .../default/00_file_plugin_setup_spec.rb | 9 +- .../default/10_configured_file_plugin_spec.rb | 9 +- .../20_auto_default_file_plugin_spec.rb | 18 +- .../suites/default/validate_file_entries.rb | 35 +- .../suites/ldap_plugin/00_ldap_server_spec.rb | 14 +- .../ldap_plugin/05_ldap_client_setup_spec.rb | 13 +- .../suites/ldap_plugin/10_ldapi_spec.rb | 44 +- .../suites/ldap_plugin/20_ldap_protos_spec.rb | 74 +- .../suites/ldap_plugin/30_errors_spec.rb | 52 +- .../ldap_plugin/ldap_test_configuration.rb | 71 +- .../ldap_plugin/validate_ldap_entries.rb | 43 +- .../10_multiple_plugins_spec.rb | 64 +- .../validate_multiple_plugins_entries.rb | 24 +- spec/data_helper.rb | 104 ++- spec/functions/simpkv/delete_spec.rb | 84 +-- spec/functions/simpkv/deletetree_spec.rb | 94 ++- spec/functions/simpkv/exists_spec.rb | 80 +- spec/functions/simpkv/get_spec.rb | 89 ++- spec/functions/simpkv/list_spec.rb | 142 ++-- spec/functions/simpkv/put_spec.rb | 108 ++- .../simpkv/support/config/merge_spec.rb | 82 +- .../simpkv/support/config/validate_spec.rb | 92 ++- .../simpkv/support/key/validate_spec.rb | 29 +- spec/functions/simpkv/support/load_spec.rb | 35 +- spec/spec_helper.rb | 15 +- spec/spec_helper_acceptance.rb | 39 +- .../lib/puppet_x/simpkv/failer_plugin.rb | 21 +- .../lib/puppet_x/simpkv/failer_plugin.rb | 21 +- spec/unit/puppet_x/simpkv/file_plugin_spec.rb | 442 ++++++----- spec/unit/puppet_x/simpkv/ldap_plugin_spec.rb | 566 +++++++------- spec/unit/puppet_x/simpkv/simpkv_spec.rb | 423 ++++++----- 63 files changed, 2878 insertions(+), 2304 deletions(-) create mode 100644 .rubocop.yml diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml index 21ca28c..bcc5fb0 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/pr_tests.yml @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: "Install Ruby ${{matrix.puppet.ruby_version}}" + - name: "Install Ruby 2.7" uses: ruby/setup-ruby@v1 # ruby/setup-ruby@ec106b438a1ff6ff109590de34ddc62c540232e0 with: ruby-version: 2.7 @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: "Install Ruby ${{matrix.puppet.ruby_version}}" + - name: "Install Ruby 2.7" uses: ruby/setup-ruby@v1 with: ruby-version: 2.7 @@ -56,13 +56,12 @@ jobs: - run: "bundle exec rake metadata_lint" ruby-style: - if: false # TODO Modules will need: rubocop in Gemfile, .rubocop.yml - name: 'Ruby Style (experimental)' + name: 'Ruby Style' runs-on: ubuntu-latest continue-on-error: true steps: - uses: actions/checkout@v3 - - name: "Install Ruby ${{matrix.puppet.ruby_version}}" + - name: "Install Ruby 2.7" uses: ruby/setup-ruby@v1 with: ruby-version: 2.7 @@ -89,7 +88,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: 'Install Ruby ${{matrix.puppet.ruby_version}}' + - name: 'Install Ruby 2.7' uses: ruby/setup-ruby@v1 with: ruby-version: 2.7 diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..65c8c0a --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,699 @@ +--- +require: + - rubocop-performance + - rubocop-rake + - rubocop-rspec +AllCops: + NewCops: enable + DisplayCopNames: true + TargetRubyVersion: "2.7" + Include: + - "**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - 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/GemFilename: + Enabled: false +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/Dialect: + Enabled: false +RSpec/ContainExactly: + 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/HooksBeforeExamples: + Enabled: false +RSpec/ImplicitBlockExpectation: + Enabled: false +RSpec/ImplicitSubject: + Enabled: false +RSpec/LeakyConstantDeclaration: + Enabled: false +RSpec/LetBeforeExamples: + Enabled: false +RSpec/MatchArray: + 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/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 +Gemspec/DeprecatedAttributeAssignment: + Enabled: false +Gemspec/DevelopmentDependencies: + Enabled: false +Gemspec/RequireMFA: + Enabled: false +Layout/LineContinuationLeadingSpace: + Enabled: false +Layout/LineContinuationSpacing: + Enabled: false +Layout/LineEndStringConcatenationIndentation: + Enabled: false +Layout/SpaceBeforeBrackets: + Enabled: false +Lint/AmbiguousAssignment: + Enabled: false +Lint/AmbiguousOperatorPrecedence: + Enabled: false +Lint/AmbiguousRange: + Enabled: false +Lint/ConstantOverwrittenInRescue: + Enabled: false +Lint/DeprecatedConstants: + Enabled: false +Lint/DuplicateBranch: + Enabled: false +Lint/DuplicateMagicComment: + Enabled: false +Lint/DuplicateMatchPattern: + Enabled: false +Lint/DuplicateRegexpCharacterClassElement: + Enabled: false +Lint/EmptyBlock: + Enabled: false +Lint/EmptyClass: + Enabled: false +Lint/EmptyInPattern: + Enabled: false +Lint/IncompatibleIoSelectWithFiberScheduler: + Enabled: false +Lint/LambdaWithoutLiteralBlock: + Enabled: false +Lint/NoReturnInBeginEndBlocks: + Enabled: false +Lint/NonAtomicFileOperation: + Enabled: false +Lint/NumberedParameterAssignment: + Enabled: false +Lint/OrAssignmentToConstant: + Enabled: false +Lint/RedundantDirGlobSort: + Enabled: false +Lint/RefinementImportMethods: + Enabled: false +Lint/RequireRangeParentheses: + Enabled: false +Lint/RequireRelativeSelfPath: + Enabled: false +Lint/SymbolConversion: + Enabled: false +Lint/ToEnumArguments: + Enabled: false +Lint/TripleQuotes: + Enabled: false +Lint/UnexpectedBlockArity: + Enabled: false +Lint/UnmodifiedReduceAccumulator: + Enabled: false +Lint/UselessRescue: + Enabled: false +Lint/UselessRuby2Keywords: + Enabled: false +Metrics/CollectionLiteralLength: + Enabled: false +Naming/BlockForwarding: + Enabled: false +Performance/CollectionLiteralInLoop: + Enabled: false +Performance/ConcurrentMonotonicTime: + Enabled: false +Performance/MapCompact: + Enabled: false +Performance/RedundantEqualityComparisonBlock: + Enabled: false +Performance/RedundantSplitRegexpArgument: + Enabled: false +Performance/StringIdentifierArgument: + Enabled: false +RSpec/BeEq: + Enabled: false +RSpec/BeNil: + Enabled: false +RSpec/ChangeByZero: + Enabled: false +RSpec/ClassCheck: + Enabled: false +RSpec/DuplicatedMetadata: + Enabled: false +RSpec/ExcessiveDocstringSpacing: + Enabled: false +RSpec/IdenticalEqualityAssertion: + Enabled: false +RSpec/NoExpectationExample: + Enabled: false +RSpec/PendingWithoutReason: + Enabled: false +RSpec/RedundantAround: + Enabled: false +RSpec/SkipBlockInsideExample: + Enabled: false +RSpec/SortMetadata: + Enabled: false +RSpec/SubjectDeclaration: + Enabled: false +RSpec/VerifiedDoubleReference: + Enabled: false +Security/CompoundHash: + Enabled: false +Security/IoMethods: + Enabled: false +Style/ArgumentsForwarding: + Enabled: false +Style/ArrayIntersect: + Enabled: false +Style/CollectionCompact: + Enabled: false +Style/ComparableClamp: + Enabled: false +Style/ConcatArrayLiterals: + Enabled: false +Style/DataInheritance: + Enabled: false +Style/DirEmpty: + Enabled: false +Style/DocumentDynamicEvalDefinition: + Enabled: false +Style/EmptyHeredoc: + Enabled: false +Style/EndlessMethod: + Enabled: false +Style/EnvHome: + Enabled: false +Style/FetchEnvVar: + Enabled: false +Style/FileEmpty: + Enabled: false +Style/FileRead: + Enabled: false +Style/FileWrite: + Enabled: false +Style/HashConversion: + Enabled: false +Style/HashExcept: + Enabled: false +Style/IfWithBooleanLiteralBranches: + Enabled: false +Style/InPatternThen: + Enabled: false +Style/MagicCommentFormat: + Enabled: false +Style/MapCompactWithConditionalBlock: + Enabled: false +Style/MapToHash: + Enabled: false +Style/MapToSet: + Enabled: false +Style/MinMaxComparison: + Enabled: false +Style/MultilineInPatternThen: + Enabled: false +Style/NegatedIfElseCondition: + Enabled: false +Style/NestedFileDirname: + Enabled: false +Style/NilLambda: + Enabled: false +Style/NumberedParameters: + Enabled: false +Style/NumberedParametersLimit: + Enabled: false +Style/ObjectThen: + Enabled: false +Style/OpenStructUse: + Enabled: false +Style/OperatorMethodCall: + Enabled: false +Style/QuotedSymbols: + Enabled: false +Style/RedundantArgument: + Enabled: false +Style/RedundantConstantBase: + Enabled: false +Style/RedundantDoubleSplatHashBraces: + Enabled: false +Style/RedundantEach: + Enabled: false +Style/RedundantHeredocDelimiterQuotes: + Enabled: false +Style/RedundantInitialize: + Enabled: false +Style/RedundantLineContinuation: + Enabled: false +Style/RedundantSelfAssignmentBranch: + Enabled: false +Style/RedundantStringEscape: + Enabled: false +Style/SelectByRegexp: + Enabled: false +Style/StringChars: + Enabled: false +Style/SwapValues: + Enabled: false diff --git a/Gemfile b/Gemfile index e74c3da..7c330d6 100644 --- a/Gemfile +++ b/Gemfile @@ -10,16 +10,23 @@ ENV['PDK_DISABLE_ANALYTICS'] ||= 'true' gem_sources.each { |gem_source| source gem_source } +group :syntax do + gem 'metadata-json-lint' + gem 'puppet-lint-trailing_comma-check', require: false + gem 'rubocop', '~> 1.68.0' + gem 'rubocop-performance', '~> 1.23.0' + gem 'rubocop-rake', '~> 0.6.0' + gem 'rubocop-rspec', '~> 3.2.0' +end + group :test do puppet_version = ENV.fetch('PUPPET_VERSION', ['>= 7', '< 9']) major_puppet_version = Array(puppet_version).first.scan(%r{(\d+)(?:\.|\Z)}).flatten.first.to_i gem 'hiera-puppet-helper' - gem 'metadata-json-lint' gem 'pathspec', '~> 0.2' if Gem::Requirement.create('< 2.6').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) gem('pdk', ENV.fetch('PDK_VERSION', ['>= 2.0', '< 4.0']), require: false) if major_puppet_version > 5 gem 'puppet', puppet_version gem 'puppetlabs_spec_helper' - gem 'puppet-lint-trailing_comma-check', require: false gem 'puppet-strings' gem 'rake' gem 'rspec' diff --git a/lib/puppet/functions/simpkv/delete.rb b/lib/puppet/functions/simpkv/delete.rb index 5c33c46..0702607 100644 --- a/lib/puppet/functions/simpkv/delete.rb +++ b/lib/puppet/functions/simpkv/delete.rb @@ -3,7 +3,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::delete') do - # @param key The key to remove. Must conform to the following: # # * Key must contain only the following characters: @@ -96,7 +95,7 @@ optional_param 'Hash', :options end - def delete(key, options={}) + def delete(key, options = {}) # key validation difficult to do via a type alias, so validate via function call_function('simpkv::support::key::validate', key) @@ -107,23 +106,21 @@ def delete(key, options={}) # and the list of backends for which plugins have been loaded begin catalog = closure_scope.find_global_scope.catalog - merged_options = call_function( 'simpkv::support::config::merge', options, + merged_options = call_function('simpkv::support::config::merge', options, catalog.simpkv.backends) rescue ArgumentError => e msg = "simpkv Configuration Error for simpkv::delete with key='#{key}': #{e.message}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end # use simpkv for delete operation backend_result = catalog.simpkv.delete(key, merged_options) success = backend_result[:result] unless success - err_msg = "simpkv Error for simpkv::delete with key='#{key}': #{backend_result[:err_msg]}" - if merged_options['softfail'] - Puppet.warning(err_msg) - else - raise(err_msg) - end + err_msg = "simpkv Error for simpkv::delete with key='#{key}': #{backend_result[:err_msg]}" + raise(err_msg) unless merged_options['softfail'] + Puppet.warning(err_msg) + end success diff --git a/lib/puppet/functions/simpkv/deletetree.rb b/lib/puppet/functions/simpkv/deletetree.rb index e245178..85473a1 100644 --- a/lib/puppet/functions/simpkv/deletetree.rb +++ b/lib/puppet/functions/simpkv/deletetree.rb @@ -3,7 +3,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::deletetree') do - # @param keydir The key folder to remove. Must conform to the following: # # * Key folder must contain only the following characters: @@ -96,7 +95,7 @@ optional_param 'Hash', :options end - def deletetree(keydir, options={}) + def deletetree(keydir, options = {}) # keydir validation difficult to do via a type alias, so validate via function call_function('simpkv::support::key::validate', keydir) @@ -107,23 +106,21 @@ def deletetree(keydir, options={}) # and the list of backends for which plugins have been loaded begin catalog = closure_scope.find_global_scope.catalog - merged_options = call_function( 'simpkv::support::config::merge', options, + merged_options = call_function('simpkv::support::config::merge', options, catalog.simpkv.backends) rescue ArgumentError => e msg = "simpkv Configuration Error for simpkv::deletetree with keydir='#{keydir}': #{e.message}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end # use simpkv for delete operation backend_result = catalog.simpkv.deletetree(keydir, merged_options) success = backend_result[:result] unless success - err_msg = "simpkv Error for simpkv::deletetree with keydir='#{keydir}': #{backend_result[:err_msg]}" - if merged_options['softfail'] - Puppet.warning(err_msg) - else - raise(err_msg) - end + err_msg = "simpkv Error for simpkv::deletetree with keydir='#{keydir}': #{backend_result[:err_msg]}" + raise(err_msg) unless merged_options['softfail'] + Puppet.warning(err_msg) + end success diff --git a/lib/puppet/functions/simpkv/exists.rb b/lib/puppet/functions/simpkv/exists.rb index 24786a4..52f735f 100644 --- a/lib/puppet/functions/simpkv/exists.rb +++ b/lib/puppet/functions/simpkv/exists.rb @@ -3,7 +3,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::exists') do - # @param key The key or key folder to check. Must conform to the following: # # * Key must contain only the following characters: @@ -102,7 +101,7 @@ optional_param 'Hash', :options end - def exists(key, options={}) + def exists(key, options = {}) # key validation difficult to do via a type alias, so validate via function call_function('simpkv::support::key::validate', key) @@ -113,23 +112,21 @@ def exists(key, options={}) # and the list of backends for which plugins have been loaded begin catalog = closure_scope.find_global_scope.catalog - merged_options = call_function( 'simpkv::support::config::merge', options, + merged_options = call_function('simpkv::support::config::merge', options, catalog.simpkv.backends) rescue ArgumentError => e msg = "simpkv Configuration Error for simpkv::exists with key='#{key}': #{e.message}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end # use simpkv for exists operation backend_result = catalog.simpkv.exists(key, merged_options) success = backend_result[:result] if success.nil? - err_msg = "simpkv Error for simpkv::exists with key='#{key}': #{backend_result[:err_msg]}" - if merged_options['softfail'] - Puppet.warning(err_msg) - else - raise(err_msg) - end + err_msg = "simpkv Error for simpkv::exists with key='#{key}': #{backend_result[:err_msg]}" + raise(err_msg) unless merged_options['softfail'] + Puppet.warning(err_msg) + end success diff --git a/lib/puppet/functions/simpkv/get.rb b/lib/puppet/functions/simpkv/get.rb index b7e2326..831fa8b 100644 --- a/lib/puppet/functions/simpkv/get.rb +++ b/lib/puppet/functions/simpkv/get.rb @@ -4,7 +4,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::get') do - # @param key The key to retrieve. Must conform to the following: # # * Key must contain only the following characters: @@ -113,7 +112,7 @@ optional_param 'Hash', :options end - def get(key, options={}) + def get(key, options = {}) # key validation difficult to do via a type alias, so validate via function call_function('simpkv::support::key::validate', key) @@ -124,11 +123,11 @@ def get(key, options={}) # and the list of backends for which plugins have been loaded begin catalog = closure_scope.find_global_scope.catalog - merged_options = call_function( 'simpkv::support::config::merge', options, + merged_options = call_function('simpkv::support::config::merge', options, catalog.simpkv.backends) rescue ArgumentError => e msg = "simpkv Configuration Error for simpkv::get with key='#{key}': #{e.message}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end # use simpkv for get operation @@ -136,12 +135,10 @@ def get(key, options={}) result = backend_result[:result] if result.nil? - err_msg = "simpkv Error for simpkv::get with key='#{key}': #{backend_result[:err_msg]}" - if merged_options['softfail'] - Puppet.warning(err_msg) - else - raise(err_msg) - end + err_msg = "simpkv Error for simpkv::get with key='#{key}': #{backend_result[:err_msg]}" + raise(err_msg) unless merged_options['softfail'] + Puppet.warning(err_msg) + else result = { 'value' => backend_result[:result][:value] } unless backend_result[:result][:metadata].empty? diff --git a/lib/puppet/functions/simpkv/list.rb b/lib/puppet/functions/simpkv/list.rb index 87b4794..fbe928f 100644 --- a/lib/puppet/functions/simpkv/list.rb +++ b/lib/puppet/functions/simpkv/list.rb @@ -6,7 +6,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::list') do - # @param keydir The key folder to list. Must conform to the following: # # * Key folder must contain only the following characters: @@ -115,7 +114,7 @@ optional_param 'Hash', :options end - def list(keydir, options={}) + def list(keydir, options = {}) # keydir validation difficult to do via a type alias, so validate via function call_function('simpkv::support::key::validate', keydir) @@ -126,11 +125,11 @@ def list(keydir, options={}) # and the list of backends for which plugins have been loaded begin catalog = closure_scope.find_global_scope.catalog - merged_options = call_function( 'simpkv::support::config::merge', options, + merged_options = call_function('simpkv::support::config::merge', options, catalog.simpkv.backends) rescue ArgumentError => e msg = "simpkv Configuration Error for simpkv::list with keydir='#{keydir}': #{e.message}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end # use simpkv for list operation @@ -138,17 +137,15 @@ def list(keydir, options={}) result = backend_result[:result] if result.nil? - err_msg = "simpkv Error for simpkv::list with keydir='#{keydir}': #{backend_result[:err_msg]}" - if merged_options['softfail'] - Puppet.warning(err_msg) - else - raise(err_msg) - end + err_msg = "simpkv Error for simpkv::list with keydir='#{keydir}': #{backend_result[:err_msg]}" + raise(err_msg) unless merged_options['softfail'] + Puppet.warning(err_msg) + else result = { 'keys' => {}, 'folders' => backend_result[:result][:folders] } - backend_result[:result][:keys].each do |key,info| - result['keys'][key] = { 'value' => info[:value] } - unless info[:metadata].empty? + backend_result[:result][:keys].each do |key, info| + result['keys'][key] = { 'value' => info[:value] } + unless info[:metadata].empty? result['keys'][key]['metadata'] = info[:metadata] end end diff --git a/lib/puppet/functions/simpkv/put.rb b/lib/puppet/functions/simpkv/put.rb index b5dafd3..0d4efe9 100644 --- a/lib/puppet/functions/simpkv/put.rb +++ b/lib/puppet/functions/simpkv/put.rb @@ -4,7 +4,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::put') do - # @param key The key to set. Must conform to the following: # # * Key must contain only the following characters: @@ -106,7 +105,7 @@ optional_param 'Hash', :options end - def put(key, value, metadata={}, options={}) + def put(key, value, metadata = {}, options = {}) # key validation difficult to do via a type alias, so validate via function call_function('simpkv::support::key::validate', key) @@ -117,23 +116,21 @@ def put(key, value, metadata={}, options={}) # and the list of backends for which plugins have been loaded begin catalog = closure_scope.find_global_scope.catalog - merged_options = call_function( 'simpkv::support::config::merge', options, + merged_options = call_function('simpkv::support::config::merge', options, catalog.simpkv.backends) rescue ArgumentError => e msg = "simpkv Configuration Error for simpkv::put with key='#{key}': #{e.message}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end # use simpkv for put operation backend_result = catalog.simpkv.put(key, value, metadata, merged_options) success = backend_result[:result] unless success - err_msg = "simpkv Error for simpkv::put with key='#{key}': #{backend_result[:err_msg]}" - if merged_options['softfail'] - Puppet.warning(err_msg) - else - raise(err_msg) - end + err_msg = "simpkv Error for simpkv::put with key='#{key}': #{backend_result[:err_msg]}" + raise(err_msg) unless merged_options['softfail'] + Puppet.warning(err_msg) + end success diff --git a/lib/puppet/functions/simpkv/support/config/merge.rb b/lib/puppet/functions/simpkv/support/config/merge.rb index f4bd762..2634440 100644 --- a/lib/puppet/functions/simpkv/support/config/merge.rb +++ b/lib/puppet/functions/simpkv/support/config/merge.rb @@ -29,7 +29,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::support::config::merge') do - # @param options Hash that specifies simpkv backend options to be merged with # `simpkv::options`. # @@ -51,7 +50,7 @@ def merge(options, backends) merged_options = merge_options(options) call_function('simpkv::support::config::validate', merged_options, backends) - return merged_options + merged_options end # merge options; set defaults for 'backend', 'environment', 'global' and @@ -65,13 +64,13 @@ def merge_options(options) # deep_merge will not work with frozen options, so make a deep copy # (options.dup is a shallow copy of contained Hashes) options_dup = Marshal.load(Marshal.dump(options)) - app_id = options.has_key?('app_id') ? options['app_id'] : 'default' + app_id = options.key?('app_id') ? options['app_id'] : 'default' merged_options = call_function('lookup', 'simpkv::options', { 'default_value' => {} }) merged_options.deep_merge!(options_dup) backend_names = [ 'default' ] - if merged_options.has_key?('backends') + if merged_options.key?('backends') # reverse sort by length of string so we get the longest match when using # a partial match backend_names = merged_options['backends'].keys.sort_by(&:length).reverse @@ -85,7 +84,7 @@ def merge_options(options) } end - unless merged_options.has_key?('backend') + unless merged_options.key?('backend') backend = 'default' if backend_names.include?(app_id) backend = app_id @@ -100,11 +99,11 @@ def merge_options(options) merged_options['backend'] = backend end - unless merged_options.has_key?('softfail') + unless merged_options.key?('softfail') merged_options['softfail'] = false end - unless merged_options.has_key?('global') + unless merged_options.key?('global') merged_options['global'] = false end @@ -113,4 +112,3 @@ def merge_options(options) merged_options end end - diff --git a/lib/puppet/functions/simpkv/support/config/validate.rb b/lib/puppet/functions/simpkv/support/config/validate.rb index 621f5f2..a3ce2ca 100644 --- a/lib/puppet/functions/simpkv/support/config/validate.rb +++ b/lib/puppet/functions/simpkv/support/config/validate.rb @@ -3,7 +3,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::support::config::validate') do - # @param options Hash that specifies simpkv backend options # # @param backends List of backends for which plugins have been successfully @@ -22,53 +21,52 @@ end def validate(options, backends) - unless options.has_key?('backend') + unless options.key?('backend') msg = "'backend' not specified in simpkv configuration: #{options}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end backend = options['backend'] - unless options.has_key?('backends') + unless options.key?('backends') msg = "'backends' not specified in simpkv configuration: #{options}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end unless options['backends'].is_a?(Hash) msg = "'backends' in simpkv configuration is not a Hash: #{options}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end - unless ( - options['backends'].has_key?(options['backend']) && - options['backends'][backend].is_a?(Hash) && - options['backends'][backend].has_key?('id') && - options['backends'][backend].has_key?('type') - ) + unless options['backends'].key?(options['backend']) && + options['backends'][backend].is_a?(Hash) && + options['backends'][backend].key?('id') && + options['backends'][backend].key?('type') + msg = "No simpkv backend '#{backend}' with 'id' and 'type' attributes has been configured: #{options}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end unless backends.include?(options['backends'][backend]['type']) msg = "simpkv backend plugin '#{options['backends'][backend]['type']}' not available. Valid plugins = #{backends}" - raise ArgumentError.new(msg) + raise ArgumentError, msg end # plugin instances are uniquely defined by the pair, not name. # Make sure all backend configurations for a pair have the same # configuration. backend_instances = {} - options['backends'].each do |name, config| + options['backends'].each_value do |config| instance_id = "#{config['type']}/#{config['id']}" - if backend_instances.has_key?(instance_id) + if backend_instances.key?(instance_id) unless backend_instances[instance_id] == config - msg = 'simpkv config contains different backend configs for ' + - "type=#{config['type']} id=#{config['id']}: #{options}" - raise ArgumentError.new(msg) + msg = 'simpkv config contains different backend configs for ' \ + "type=#{config['type']} id=#{config['id']}: #{options}" + raise ArgumentError, msg end else backend_instances[instance_id] = config end - end + end end end diff --git a/lib/puppet/functions/simpkv/support/key/validate.rb b/lib/puppet/functions/simpkv/support/key/validate.rb index bcae04d..fc5f6e6 100644 --- a/lib/puppet/functions/simpkv/support/key/validate.rb +++ b/lib/puppet/functions/simpkv/support/key/validate.rb @@ -15,7 +15,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::support::key::validate') do - # @param key simpkv key # # @return [Nil] @@ -37,24 +36,21 @@ end def validate(key) - ws_regex = /[[:space:]]/ - if (key =~ ws_regex) + ws_regex = %r{[[:space:]]} + if key&.match?(ws_regex) msg = "key '#{key}' contains disallowed whitespace" - raise ArgumentError.new(msg) + raise ArgumentError, msg end - char_regex = /^[a-z0-9._:\-\/]+$/m - unless (key =~ char_regex) + char_regex = %r{^[a-z0-9._:\-/]+$}m + unless key&.match?(char_regex) msg = "key '#{key}' contains unsupported characters. Allowed set=[a-z0-9._:-/]" - raise ArgumentError.new(msg) + raise ArgumentError, msg end - dot_regex = /\/\.\.?\// - if (key =~ dot_regex) - msg = "key '#{key}' contains disallowed '/./' or '/../' sequence" - raise ArgumentError.new(msg) - end + dot_regex = %r{/\.\.?/} + return unless key&.match?(dot_regex) + msg = "key '#{key}' contains disallowed '/./' or '/../' sequence" + raise ArgumentError, msg end - end - diff --git a/lib/puppet/functions/simpkv/support/load.rb b/lib/puppet/functions/simpkv/support/load.rb index 2a1c942..6eb5760 100644 --- a/lib/puppet/functions/simpkv/support/load.rb +++ b/lib/puppet/functions/simpkv/support/load.rb @@ -4,7 +4,6 @@ # @author https://github.com/simp/pupmod-simp-simpkv/graphs/contributors # Puppet::Functions.create_function(:'simpkv::support::load') do - # @return [Nil] # @raise LoadError if simpkv adapter software fails to load # @@ -13,25 +12,21 @@ def load catalog = closure_scope.find_global_scope.catalog - unless catalog.respond_to?(:simpkv) - # load and instantiate simpkv adapter and then add it as a - # 'simpkv' attribute to the catalog instance - lib_dir = File.dirname(File.dirname(File.dirname(File.dirname(File.dirname("#{__FILE__}"))))) - filename = File.join(lib_dir, 'puppet_x', 'simpkv', 'loader.rb') - if File.exist?(filename) - begin - catalog.instance_eval(File.read(filename), filename) - rescue SyntaxError => e - raise(LoadError, - "simpkv Internal Error: unable to load #{filename}: #{e.message}" - ) - end - else + return if catalog.respond_to?(:simpkv) + # load and instantiate simpkv adapter and then add it as a + # 'simpkv' attribute to the catalog instance + lib_dir = File.dirname(File.dirname(File.dirname(File.dirname(File.dirname(__FILE__.to_s))))) + filename = File.join(lib_dir, 'puppet_x', 'simpkv', 'loader.rb') + if File.exist?(filename) + begin + catalog.instance_eval(File.read(filename), filename) + rescue SyntaxError => e raise(LoadError, - "simpkv Internal Error: unable to load #{filename}: File not found" - ) + "simpkv Internal Error: unable to load #{filename}: #{e.message}") end + else + raise(LoadError, + "simpkv Internal Error: unable to load #{filename}: File not found") end end - end diff --git a/lib/puppet_x/simpkv/file_plugin.rb b/lib/puppet_x/simpkv/file_plugin.rb index dec7132..2b61eaf 100644 --- a/lib/puppet_x/simpkv/file_plugin.rb +++ b/lib/puppet_x/simpkv/file_plugin.rb @@ -4,8 +4,7 @@ # Each plugin **MUST** be an anonymous class accessible only through # a `plugin_class` local variable. # DO NOT CHANGE THE LINE BELOW!!!! -plugin_class = Class.new do - +Class.new do require 'etc' require 'fileutils' require 'timeout' @@ -52,24 +51,22 @@ def initialize(name) def configure(options) # backend config should already have been verified by simpkv adapter, but # just in case... - unless ( - options.is_a?(Hash) && - options.has_key?('backend') && - options.has_key?('backends') && - options['backends'].is_a?(Hash) && - options['backends'].has_key?(options['backend']) && - options['backends'][ options['backend'] ].has_key?('id') && - options['backends'][ options['backend'] ].has_key?('type') && - (options['backends'][ options['backend'] ]['type'] == 'file') - ) + unless options.is_a?(Hash) && + options.key?('backend') && + options.key?('backends') && + options['backends'].is_a?(Hash) && + options['backends'].key?(options['backend']) && + options['backends'][ options['backend'] ].key?('id') && + options['backends'][ options['backend'] ].key?('type') && + (options['backends'][ options['backend'] ]['type'] == 'file') + raise("Plugin misconfigured: #{options}") end - # set optional configuration backend = options['backend'] @root_path = ensure_root_path(options) - if options['backends'][backend].has_key?('lock_timeout_seconds') + if options['backends'][backend].key?('lock_timeout_seconds') @lock_timeout_seconds = options['backends'][backend]['lock_timeout_seconds'] else @lock_timeout_seconds = 5 @@ -83,8 +80,6 @@ def configure(options) Puppet.debug("#{@name} simpkv plugin for #{@root_path} configured") end - - # Deletes a `key` from the configured backend. # # @param key String key @@ -114,7 +109,7 @@ def delete(key) end end - { :result => success, :err_msg => err_msg } + { result: success, err_msg: err_msg } end # Deletes a whole folder from the configured backend. @@ -149,7 +144,7 @@ def deletetree(keydir) success = true end - { :result => success, :err_msg => err_msg } + { result: success, err_msg: err_msg } end # Returns whether key or key folder exists in the configured backend. @@ -166,7 +161,7 @@ def exists(key) key_file = File.join(@root_path, key) # this simple plugin doesn't have any error cases that would be reported # in :err_msg - { :result => File.exist?(key_file), :err_msg => nil } + { result: File.exist?(key_file), err_msg: nil } end # Retrieves the value stored at `key` from the configured backend. @@ -191,14 +186,13 @@ def get(key) # do **NOT** use a File.open block! file = File.open(key_file, 'r') - Timeout::timeout(@lock_timeout_seconds) do + Timeout.timeout(@lock_timeout_seconds) do file.flock(File::LOCK_EX) end value = file.read file.close # lock released with close file = nil - rescue Errno::ENOENT err_msg = "Key not found at '#{key_file}'" rescue Errno::EACCES @@ -210,10 +204,10 @@ def get(key) err_msg = "Key retrieval at '#{key_file}' failed: #{e.message}" ensure # make sure lock is released even on failure - file.close unless file.nil? + file&.close end end - { :result => value, :err_msg => err_msg } + { result: value, err_msg: err_msg } end # Returns a listing of all keys/info pairs and sub-folders in a folder @@ -239,12 +233,12 @@ def list(keydir) err_msg = nil dir = File.join(@root_path, keydir) if Dir.exist?(dir) - result = { :keys => {}, :folders => [] } - Dir.glob(File.join(dir,'*')).each do |entry| + result = { keys: {}, folders: [] } + Dir.glob(File.join(dir, '*')).each do |entry| if File.directory?(entry) result[:folders] << File.basename(entry) else - key = entry.gsub(@root_path + File::SEPARATOR,'') + key = entry.gsub(@root_path + File::SEPARATOR, '') key_result = get(key) unless key_result[:result].nil? result[:keys][File.basename(key)] = key_result[:result] @@ -253,16 +247,14 @@ def list(keydir) end result[:folders].sort! else - err_msg = "Key folder '#{keydir}' not found" + err_msg = "Key folder '#{keydir}' not found" end - { :result => result, :err_msg => err_msg } + { result: result, err_msg: err_msg } end # @return unique identifier assigned to this plugin instance - def name - @name - end + attr_reader :name # Sets the data at `key` to a `value` in the configured backend. # @@ -290,9 +282,9 @@ def put(key, value) # To ensure all threads are not sharing the same file descriptor # do **NOT** use a File.open block! # Also, don't use 'w' as it truncates file before the lock is obtained - file = File.open(key_file, File::RDWR|File::CREAT) + file = File.open(key_file, File::RDWR | File::CREAT) - Timeout::timeout(@lock_timeout_seconds) do + Timeout.timeout(@lock_timeout_seconds) do # only wrap timeout around flock, so we don't end up with partially # modified files file.flock(File::LOCK_EX) @@ -305,7 +297,7 @@ def put(key, value) file.close # lock released with close file = nil - if new_file || ( File.stat(key_file).uid == user_id ) + if new_file || (File.stat(key_file).uid == user_id) # we set the permissions here, instead of when the file was opened, # so that the user's umask is ignored # NOTE: Group writable setting is specifically to support `simp passgen` @@ -313,10 +305,9 @@ def put(key, value) # Do not want `simp passgen` to create a file/directory that # subsequent `puppet agent` runs as puppet:puppet will not be able # to manage. - File.chmod(0660, key_file) + File.chmod(0o660, key_file) end success = true - rescue Timeout::Error success = false err_msg = "Timed out waiting for lock of key file '#{key_file}'" @@ -328,10 +319,10 @@ def put(key, value) success = false err_msg = "Key write to '#{key_file}' failed: #{e.message}" ensure - file.close unless file.nil? + file&.close end - { :result => success, :err_msg => err_msg } + { result: success, err_msg: err_msg } end ###### Internal Methods ###### @@ -355,7 +346,7 @@ def ensure_folder_path(keydir) # Do not want `simp passgen` to create a file/directory that # subsequent `puppet agent` runs as puppet:puppet will not be able # to manage. - FileUtils.mkdir(path.to_s, :mode => 0770) + FileUtils.mkdir(path.to_s, mode: 0o770) end end end @@ -382,7 +373,7 @@ def ensure_root_path(options) default_root_path_var = File.join('/', 'var', 'simp', 'simpkv', @name) default_root_path_puppet_vardir = File.join(Puppet.settings[:vardir], 'simp', 'simpkv', @name) - if options['backends'][backend].has_key?('root_path') + if options['backends'][backend].key?('root_path') root_path = options['backends'][backend]['root_path'] elsif Dir.exist?(default_root_path_var) root_path = default_root_path_var @@ -400,8 +391,8 @@ def ensure_root_path(options) else begin FileUtils.mkdir_p(root_path) - rescue Exception => e - if options['backends'][backend].has_key?('root_path') + rescue Exception + if options['backends'][backend].key?('root_path') # someone made an explicit config error err_msg = "Unable to create configured root path '#{root_path}'.\n" err_msg += ">>> Ensure '#{group}' group can create '#{root_path}' to fix." @@ -410,10 +401,10 @@ def ensure_root_path(options) # try again using a fallback default that should work for 'puppet agent' runs begin FileUtils.mkdir_p(default_root_path_puppet_vardir) - Puppet.warning("simpkv plugin #{name}: Unable to create root path " + + Puppet.warning("simpkv plugin #{name}: Unable to create root path " \ "'#{root_path}'. Defaulting to '#{default_root_path_puppet_vardir}'") root_path = default_root_path_puppet_vardir - rescue Exception => e + rescue Exception # our fallback default didn't work... err_msg = "Unable to create default root path '#{root_path}'.\n" err_msg += ">>> Ensure '#{group}' group can create '#{root_path}' to fix." @@ -428,7 +419,7 @@ def ensure_root_path(options) # Do not want `simp passgen` to create a file/directory that subsequent # `puppet agent` runs as puppet:puppet will not be able to manage. begin - FileUtils.chmod(0770, root_path) + FileUtils.chmod(0o770, root_path) rescue Exception => e raise("Unable to set permissions on #{root_path}: #{e.message}") end @@ -468,33 +459,30 @@ def user # @param dir Directory to verify # @raise RuntimeError if process cannot read and write to the directory def verify_dir_access(dir) - begin - Dir.entries(dir) - - # We can read the directory, now make sure we can write to it - stat = File.stat(dir) - write_access = false - if (stat.uid == user_id) - # we own the dir, so go ahead and enforce desired permissions - FileUtils.chmod(0770, dir) - write_access = true - elsif (stat.gid == group_id) && ( (stat.mode & 00070) == 0070 ) - write_access = true - elsif (stat.mode & 00007) == 0007 - # Yuk! Should we warn? - write_access = true - end + Dir.entries(dir) + + # We can read the directory, now make sure we can write to it + stat = File.stat(dir) + write_access = false + if stat.uid == user_id + # we own the dir, so go ahead and enforce desired permissions + FileUtils.chmod(0o770, dir) + write_access = true + elsif (stat.gid == group_id) && stat.mode.allbits?(0o0070) + write_access = true + elsif stat.mode.allbits?(0o0007) + # Yuk! Should we warn? + write_access = true + end - unless write_access - err_msg = "Cannot modify '#{dir}' as #{user}:#{group}. \n" - err_msg += ">>> Enable '#{group}' group read AND write access on '#{dir}' to fix." - raise(err_msg) - end - rescue Errno::EACCES - err_msg = "Cannot access '#{dir}' as #{user}:#{group}. \n" + unless write_access + err_msg = "Cannot modify '#{dir}' as #{user}:#{group}. \n" err_msg += ">>> Enable '#{group}' group read AND write access on '#{dir}' to fix." raise(err_msg) end + rescue Errno::EACCES + err_msg = "Cannot access '#{dir}' as #{user}:#{group}. \n" + err_msg += ">>> Enable '#{group}' group read AND write access on '#{dir}' to fix." + raise(err_msg) end - end diff --git a/lib/puppet_x/simpkv/ldap_plugin.rb b/lib/puppet_x/simpkv/ldap_plugin.rb index 1c75e7f..85b37e2 100644 --- a/lib/puppet_x/simpkv/ldap_plugin.rb +++ b/lib/puppet_x/simpkv/ldap_plugin.rb @@ -3,7 +3,8 @@ # Each plugin **MUST** be an anonymous class accessible only through # a `plugin_class` local variable. # DO NOT CHANGE THE LINE BELOW!!!! -plugin_class = Class.new do +require 'English' +Class.new do require 'facter' require 'pathname' require 'set' @@ -35,7 +36,7 @@ def initialize(name) # - Relative to simpkv root tree # - Don't need the the 'ldap/' prefix the simpkv adapter adds to @name... # just want the configured id - @instance_path = File.join('instances', @name.gsub(%r{^ldap/},'')) + @instance_path = File.join('instances', @name.gsub(%r{^ldap/}, '')) # Maintain a list of folders that already exist to reduce the number of # unnecessary ldap add operations over the lifetime of this plugin instance @@ -114,16 +115,15 @@ def initialize(name) def configure(options) # backend config should already have been verified by simpkv adapter, but # just in case... - unless ( - options.is_a?(Hash) && - options.has_key?('backend') && - options.has_key?('backends') && - options['backends'].is_a?(Hash) && - options['backends'].has_key?(options['backend']) && - options['backends'][ options['backend'] ].has_key?('id') && - options['backends'][ options['backend'] ].has_key?('type') && - (options['backends'][ options['backend'] ]['type'] == 'ldap') - ) + unless options.is_a?(Hash) && + options.key?('backend') && + options.key?('backends') && + options['backends'].is_a?(Hash) && + options['backends'].key?(options['backend']) && + options['backends'][ options['backend'] ].key?('id') && + options['backends'][ options['backend'] ].key?('type') && + (options['backends'][ options['backend'] ]['type'] == 'ldap') + raise("Plugin misconfigured: #{options}") end @@ -144,9 +144,7 @@ def configure(options) end # @return unique identifier assigned to this plugin instance - def name - @name - end + attr_reader :name # Deletes a `key` from the configured backend. # @@ -160,13 +158,13 @@ def delete(key) Puppet.debug("#{@name} delete(#{key})") unless @configured return { - :result => false, - :err_msg => 'Internal error: delete called before configure' + result: false, + err_msg: 'Internal error: delete called before configure' } end - full_key_path = File.join(@instance_path, key) - cmd = %Q{#{@ldapdelete} "#{path_to_dn(full_key_path)}"} + full_key_path = File.join(@instance_path, key) + cmd = %(#{@ldapdelete} "#{path_to_dn(full_key_path)}") deleted = false err_msg = nil done = false @@ -181,7 +179,7 @@ def delete(key) deleted = true done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 err_msg = result[:stderr] done = true end @@ -192,7 +190,7 @@ def delete(key) retries -= 1 end - { :result => deleted, :err_msg => err_msg } + { result: deleted, err_msg: err_msg } end # Deletes a whole folder from the configured backend. @@ -207,13 +205,13 @@ def deletetree(keydir) Puppet.debug("#{@name} deletetree(#{keydir})") unless @configured return { - :result => false, - :err_msg => 'Internal error: deletetree called before configure' + result: false, + err_msg: 'Internal error: deletetree called before configure' } end - full_keydir_path = File.join(@instance_path, keydir) - cmd = %Q{#{@ldapdelete} -r "#{path_to_dn(full_keydir_path, false)}"} + full_keydir_path = File.join(@instance_path, keydir) + cmd = %(#{@ldapdelete} -r "#{path_to_dn(full_keydir_path, false)}") deleted = false err_msg = nil done = false @@ -228,7 +226,7 @@ def deletetree(keydir) deleted = true done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 err_msg = result[:stderr] done = true end @@ -241,11 +239,11 @@ def deletetree(keydir) if deleted existing_folders.delete(full_keydir_path) - parent_path = full_keydir_path + "/" + parent_path = full_keydir_path + '/' existing_folders.delete_if { |path| path.start_with?(parent_path) } end - { :result => deleted, :err_msg => err_msg } + { result: deleted, err_msg: err_msg } end # Returns whether key or key folder exists in the configured backend. @@ -262,23 +260,23 @@ def exists(key) Puppet.debug("#{@name} exists(#{key})") unless @configured return { - :result => nil, - :err_msg => 'Internal error: exists called before configure' + result: nil, + err_msg: 'Internal error: exists called before configure' } end # don't know if the key path is to a key or a folder so need to create a # search filter for both an RDN of ou= or an RDN simpkvKey=. - full_key_path = File.join(@instance_path, key) + full_key_path = File.join(@instance_path, key) dn = path_to_dn(File.dirname(full_key_path), false) leaf = File.basename(key) search_filter = "(|(ou=#{leaf})(simpkvKey=#{leaf}))" cmd = [ @ldapsearch, - '-b', %Q{"#{dn}"}, + '-b', %("#{dn}"), '-s one', - %Q{"#{search_filter}"}, - '1.1' # only print out the dn, no attributes + %("#{search_filter}"), + '1.1' # only print out the dn, no attributes ].join(' ') found = false @@ -292,13 +290,13 @@ def exists(key) # Parent DN exists, but search may or may not have returned a result # (i.e. search may have returned no matches). Have to parse console # output to see if a dn was returned. - found = true if result[:stdout].match(%r{^dn: (ou=#{leaf})|(simpkvKey=#{leaf}),#{dn}}) + found = true if result[:stdout].match?(%r{^dn: (ou=#{leaf})|(simpkvKey=#{leaf}),#{dn}}) done = true when ldap_code_no_such_object # Some part of the parent DN does not exist, so it does not exist! done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 found = nil err_msg = result[:stderr] done = true @@ -311,7 +309,7 @@ def exists(key) retries -= 1 end - { :result => found, :err_msg => err_msg } + { result: found, err_msg: err_msg } end # Retrieves the value stored at `key` from the configured backend. @@ -327,13 +325,13 @@ def get(key) Puppet.debug("#{@name} get(#{key})") unless @configured return { - :result => nil, - :err_msg => 'Internal error: get called before configure' + result: nil, + err_msg: 'Internal error: get called before configure' } end - full_key_path = File.join(@instance_path, key) - cmd = %Q{#{@ldapsearch} -b "#{path_to_dn(full_key_path)}"} + full_key_path = File.join(@instance_path, key) + cmd = %(#{@ldapsearch} -b "#{path_to_dn(full_key_path)}") value = nil err_msg = nil done = false @@ -342,16 +340,16 @@ def get(key) result = run_command(cmd) case result[:exitstatus] when 0 - match = result[:stdout].match(/^simpkvJsonValue: (.*?)$/) - if match - value = match[1] - else - err_msg = "Key retrieval did not return key/value entry:" - err_msg += "\n#{result[:stdout]}" - end - done = true + match = result[:stdout].match(%r{^simpkvJsonValue: (.*?)$}) + if match + value = match[1] + else + err_msg = 'Key retrieval did not return key/value entry:' + err_msg += "\n#{result[:stdout]}" + end + done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 err_msg = result[:stderr] done = true end @@ -362,7 +360,7 @@ def get(key) retries -= 1 end - { :result => value, :err_msg => err_msg } + { result: value, err_msg: err_msg } end # Returns a listing of all keys/info pairs and sub-folders in a folder @@ -387,16 +385,16 @@ def list(keydir) Puppet.debug("#{@name} list(#{keydir})") unless @configured return { - :result => nil, - :err_msg => 'Internal error: list called before configure' + result: nil, + err_msg: 'Internal error: list called before configure' } end - full_keydir_path = File.join(@instance_path, keydir) + full_keydir_path = File.join(@instance_path, keydir) cmd = [ @ldapsearch, - '-b', %Q{"#{path_to_dn(full_keydir_path, false)}"}, - '-s', 'one', + '-b', %("#{path_to_dn(full_keydir_path, false)}"), + '-s', 'one' ].join(' ') ldif_out = nil @@ -413,7 +411,7 @@ def list(keydir) err_msg = result[:stderr] done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 err_msg = result[:stderr] done = true end @@ -426,14 +424,14 @@ def list(keydir) list = nil unless ldif_out.nil? - if ldif_out.empty? - list = { :keys => {}, :folders => [] } - else - list = parse_list_ldif(ldif_out) - end + list = if ldif_out.empty? + { keys: {}, folders: [] } + else + parse_list_ldif(ldif_out) + end end - { :result => list, :err_msg => err_msg } + { result: list, err_msg: err_msg } end # Sets the data at `key` to a `value` in the configured backend. @@ -449,12 +447,12 @@ def put(key, value) Puppet.debug("#{@name} put(#{key},...)") unless @configured return { - :result => false, - :err_msg => 'Internal error: put called before configure' + result: false, + err_msg: 'Internal error: put called before configure' } end - full_key_path = File.join(@instance_path, key) + full_key_path = File.join(@instance_path, key) # We want to add the key/value entry if it does not exist, but only modify # the value if its current value does not match the desired value. @@ -471,7 +469,7 @@ def put(key, value) # each node. results = nil - ldap_results = ensure_folder_path( File.dirname(full_key_path) ) + ldap_results = ensure_folder_path(File.dirname(full_key_path)) if ldap_results[:success] # first try ldapadd for the key/value entry ldif = entry_add_ldif(full_key_path, value) @@ -480,16 +478,16 @@ def put(key, value) ldap_results = ldap_add(ldif, false) if ldap_results[:success] - results = { :result => true, :err_msg => nil } - elsif (ldap_results[:exitstatus] == ldap_code_already_exists) + results = { result: true, err_msg: nil } + elsif ldap_results[:exitstatus] == ldap_code_already_exists Puppet.debug("#{@name} #{full_key_path} already exists") # ldapmodify only if necessary results = update_value_if_changed(key, value) else - results = { :result => false, :err_msg => ldap_results[:err_msg] } + results = { result: false, err_msg: ldap_results[:err_msg] } end else - results = { :result => false, :err_msg => ldap_results[:err_msg] } + results = { result: false, err_msg: ldap_results[:err_msg] } end results @@ -514,7 +512,6 @@ def ensure_folder_path(folder_path) Puppet.debug("#{@name} ensure_folder_path(#{folder_path})") # Handle each folder separately instead of all at once, so we don't have to # use log scraping to understand what happened...log scraping is fragile! - ldif_file = nil folders_ensured = true results = nil Pathname.new(folder_path).descend do |folder| @@ -532,7 +529,7 @@ def ensure_folder_path(folder_path) end if folders_ensured - results = { :success => true, :exitstatus => 0, :err_msg => nil } + results = { success: true, exitstatus: 0, err_msg: nil } end results @@ -550,8 +547,8 @@ def ensure_folder_path(folder_path) def ensure_instance_tree [ File.join(@instance_path, 'globals'), - File.join(@instance_path, 'environments') - ].each do | folder| + File.join(@instance_path, 'environments'), + ].each do |folder| # Have already verified access to the base DN, so going to *assume* any # failures here are transient and will ignore them for now. If there is # a persistent problem, it will be caught in the first key storage @@ -613,7 +610,7 @@ def ldap_add(ldif, ignore_already_exists = false) # Maintainers: Comment out this line to see actual LDIF content when # debugging. Since may contain sensitive info, we don't want to allow this # output normally. - #Puppet.debug( "#{@name} add ldif:\n#{ldif}" ) + # Puppet.debug( "#{@name} add ldif:\n#{ldif}" ) ldif_file = Tempfile.new('ldap_add') ldif_file.puts(ldif) ldif_file.close @@ -641,7 +638,7 @@ def ldap_add(ldif, ignore_already_exists = false) end done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 err_msg = result[:stderr] exitstatus = result[:exitstatus] done = true @@ -654,10 +651,10 @@ def ldap_add(ldif, ignore_already_exists = false) retries -= 1 end - { :success => added, :exitstatus => exitstatus, :err_msg => err_msg } + { success: added, exitstatus: exitstatus, err_msg: err_msg } ensure - ldif_file.close if ldif_file - ldif_file.unlink if ldif_file + ldif_file&.close + ldif_file&.unlink end # LDAP return code for 'Already exists' @@ -691,12 +688,12 @@ def ldap_modify(ldif) # Maintainers: Comment out this line to see actual LDIF content when # debugging. Since may contain sensitive info, we don't want to allow this # output normally. - #Puppet.debug( "#{@name} modify ldif:\n#{ldif}" ) + # Puppet.debug( "#{@name} modify ldif:\n#{ldif}" ) ldif_file = Tempfile.new('ldap_modify') ldif_file.puts(ldif) ldif_file.close - cmd = "#{@ldapmodify} -f #{ldif_file.path}" + cmd = "#{@ldapmodify} -f #{ldif_file.path}" modified = false exitstatus = nil err_msg = nil @@ -715,7 +712,7 @@ def ldap_modify(ldif) err_msg = result[:stderr] done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 err_msg = result[:stderr] done = true end @@ -727,11 +724,10 @@ def ldap_modify(ldif) retries -= 1 end - { :success => modified, :exitstatus => exitstatus, :err_msg => err_msg } + { success: modified, exitstatus: exitstatus, err_msg: err_msg } ensure - ldif_file.close if ldif_file - ldif_file.unlink if ldif_file - + ldif_file&.close + ldif_file&.unlink end # @return DN corresponding to a path @@ -747,7 +743,7 @@ def path_to_dn(path, leaf_is_key = true) else attribute = leaf_is_key ? 'simpkvKey' : 'ou' dn = "#{attribute}=#{parts.pop}" - parts.reverse.each do |folder| + parts.reverse_each do |folder| dn += ",ou=#{folder}" end dn += ",#{@base_dn}" @@ -826,13 +822,13 @@ def parse_config(config) ldap_uri = config['ldap_uri'] raise("Plugin missing 'ldap_uri' configuration") if ldap_uri.nil? - # TODO this regex for URI or socket can be better! - unless ldap_uri.match(%r{^(ldapi|ldap|ldaps)://\S.}) + # TODO: this regex for URI or socket can be better! + unless ldap_uri.match?(%r{^(ldapi|ldap|ldaps)://\S.}) raise("Invalid 'ldap_uri' configuration: #{ldap_uri}") end if config.key?('base_dn') - # TODO Detect when non-escaped characters exist and fail? + # TODO: Detect when non-escaped characters exist and fail? opts[:base_dn] = config['base_dn'] else opts[:base_dn] = 'ou=simpkv,o=puppet,dc=simp' @@ -843,7 +839,7 @@ def parse_config(config) if config.key?('admin_dn') admin_dn = config['admin_dn'] else - #FIXME Should not use admin for whole tree + # FIXME: Should not use admin for whole tree admin_dn = 'cn=Directory_Manager' Puppet.debug("simpkv plugin #{name}: Using default simpkv admin DN #{admin_dn}") end @@ -859,16 +855,16 @@ def parse_config(config) if tls_enabled?(config) opts[:cmd_env], extra_opts = parse_tls_config(config) - opts[:base_opts] = %Q{#{extra_opts} -x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}} + opts[:base_opts] = %(#{extra_opts} -x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}) else opts[:cmd_env] = '' - if admin_pw_file - # unencrypted ldap or ldapi with simple authentication - opts[:base_opts] = %Q{-x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}} - else - # ldapi with EXTERNAL SASL - opts[:base_opts] = "-Y EXTERNAL -H #{ldap_uri}" - end + opts[:base_opts] = if admin_pw_file + # unencrypted ldap or ldapi with simple authentication + %(-x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}) + else + # ldapi with EXTERNAL SASL + "-Y EXTERNAL -H #{ldap_uri}" + end end if config.key?('retries') @@ -893,34 +889,34 @@ def parse_config(config) def parse_list_ldif(ldif_out) folders = [] keys = {} - ldif_out.split(/^dn: /).each do |ldif| + ldif_out.split(%r{^dn: }).each do |ldif| next if ldif.strip.empty? - if ldif.match(/objectClass: organizationalUnit/i) + if ldif.match?(%r{objectClass: organizationalUnit}i) rdn = ldif.split("\n").first.split(',').first - folder_match = rdn.match(/^ou=(\S+)$/) + folder_match = rdn.match(%r{^ou=(\S+)$}) if folder_match folders << folder_match[1] else Puppet.debug("Unexpected organizationalUnit entry:\n#{ldif}") end - elsif ldif.match(/objectClass: simpkvEntry/i) - key_match = ldif.match(/simpkvKey: (\S+)/i) + elsif ldif.match?(%r{objectClass: simpkvEntry}i) + key_match = ldif.match(%r{simpkvKey: (\S+)}i) if key_match key = key_match[1] - value_match = ldif.match(/simpkvJsonValue: (\{.+?\})\n/i) + value_match = ldif.match(%r{simpkvJsonValue: (\{.+?\})\n}i) if value_match keys[key] = value_match[1] else - Puppet.debug("simpkvEntry missing simpkvJsonValue:\n#{ldif}") + Puppet.debug("simpkvEntry missing simpkvJsonValue:\n#{ldif}") end else - Puppet.debug("simpkvEntry missing simpkvKey:\n#{ldif}") + Puppet.debug("simpkvEntry missing simpkvKey:\n#{ldif}") end else Puppet.debug("Found unexpected object in simpkv tree:\n#{ldif}") end end - { :keys => keys, :folders => folders } + { keys: keys, folders: folders } end # @return Pair of string modifiers for StartTLS/TLS via ldap* commands: @@ -934,7 +930,7 @@ def parse_tls_config(config) tls_cacert = config.fetch('tls_cacert', nil) if tls_cert.nil? || tls_key.nil? || tls_cacert.nil? - err_msg = "TLS configuration incomplete:" + err_msg = 'TLS configuration incomplete:' err_msg += ' tls_cert, tls_key, and tls_cacert must all be set' raise(err_msg) end @@ -942,16 +938,16 @@ def parse_tls_config(config) cmd_env = [ "LDAPTLS_CERT=#{tls_cert}", "LDAPTLS_KEY=#{tls_key}", - "LDAPTLS_CACERT=#{tls_cacert}" + "LDAPTLS_CACERT=#{tls_cacert}", ].join(' ') - if config['ldap_uri'].match(/^ldap:/) - # StartTLS - extra_opts = '-ZZ' - else - # TLS - extra_opts = '' - end + extra_opts = if config['ldap_uri'].match?(%r{^ldap:}) + # StartTLS + '-ZZ' + else + # TLS + '' + end [ cmd_env, extra_opts ] end @@ -976,16 +972,16 @@ def parse_tls_config(config) # * :stderr - Messages sent to stderr # def run_command(command) - Puppet.debug( "#{@name} executing: #{command}" ) + Puppet.debug("#{@name} executing: #{command}") out_pipe_r, out_pipe_w = IO.pipe err_pipe_r, err_pipe_w = IO.pipe - pid = spawn(command, :out => out_pipe_w, :err => err_pipe_w) + pid = spawn(command, out: out_pipe_w, err: err_pipe_w) out_pipe_w.close err_pipe_w.close Process.wait(pid) - exitstatus = $?.nil? ? nil : $?.exitstatus + exitstatus = $CHILD_STATUS&.exitstatus stdout = out_pipe_r.read out_pipe_r.close stderr = err_pipe_r.read @@ -994,10 +990,10 @@ def run_command(command) stderr = "#{command} failed:\n#{stderr}" if exitstatus != 0 { - :success => (exitstatus == 0), - :exitstatus => exitstatus, - :stdout => stdout, - :stderr => stderr + success: (exitstatus == 0), + exitstatus: exitstatus, + stdout: stdout, + stderr: stderr } end @@ -1034,11 +1030,11 @@ def set_base_ldap_commands(cmd_env, base_opts) ldapsearch, base_opts, - # TODO switch to ldif_wrap when we drop support for EL7 + # TODO: switch to ldif_wrap when we drop support for EL7 # - EL7 only supports ldif-wrap # - EL8 says it supports ldif_wrap (--help and man page), but actually # accepts ldif-wrap or ldif_wrap - '-o "ldif-wrap=no" -LLL' + '-o "ldif-wrap=no" -LLL', ].join(' ') @ldapadd = [ @@ -1064,17 +1060,16 @@ def set_base_ldap_commands(cmd_env, base_opts) # # @param config Hash backend-specific options def tls_enabled?(config) - tls_enabled = false ldap_uri = config['ldap_uri'] - if ldap_uri.start_with?('ldapi') - tls_enabled = false - elsif ldap_uri.match(/^ldaps:/) - tls_enabled = true - elsif config.key?('enable_tls') - tls_enabled = config['enable_tls'] - else - tls_enabled = false - end + tls_enabled = if ldap_uri.start_with?('ldapi') + false + elsif ldap_uri.match?(%r{^ldaps:}) + true + elsif config.key?('enable_tls') + config['enable_tls'] + else + false + end tls_enabled end @@ -1100,19 +1095,19 @@ def update_value_if_changed(key, value) Puppet.debug("#{@name} Attempting modify for #{full_key_path}") ldif = entry_modify_ldif(full_key_path, value) ldap_results = ldap_modify(ldif) - if ldap_results[:success] - results = { :result => true, :err_msg => nil } - else - results = { :result => false, :err_msg => ldap_results[:err_msg] } - end + results = if ldap_results[:success] + { result: true, err_msg: nil } + else + { result: false, err_msg: ldap_results[:err_msg] } + end else # no change needed Puppet.debug("#{@name} #{full_key_path} value already correct") - results = { :result => true, :err_msg => nil } + results = { result: true, err_msg: nil } end else err_msg = "Failed to retrieve current value for comparison: #{current_result[:err_msg]}" - results = { :result => false, :err_msg => err_msg } + results = { result: false, err_msg: err_msg } end results @@ -1123,9 +1118,9 @@ def update_value_if_changed(key, value) def verify_ldap_access cmd = [ @ldapsearch, - '-b', %Q{"#{@base_dn}"}, + '-b', %("#{@base_dn}"), '-s base', - '1.1' # only print out the dn, no attributes + '1.1' # only print out the dn, no attributes ].join(' ') found = false @@ -1139,7 +1134,7 @@ def verify_ldap_access found = true done = true when ldap_code_server_is_busy - if (retries == 0) + if retries == 0 err_msg = result[:stderr] done = true end @@ -1150,9 +1145,7 @@ def verify_ldap_access retries -= 1 end - unless found - raise("Plugin could not access #{@base_dn}: #{err_msg}") - end + return if found + raise("Plugin could not access #{@base_dn}: #{err_msg}") end end - diff --git a/lib/puppet_x/simpkv/loader.rb b/lib/puppet_x/simpkv/loader.rb index 710710b..92c1e00 100644 --- a/lib/puppet_x/simpkv/loader.rb +++ b/lib/puppet_x/simpkv/loader.rb @@ -18,15 +18,11 @@ # Get simpkv adapter # @return simpkv adapter object -def simpkv - @simpkv -end +attr_reader :simpkv # Set simpkv adapter # @param value simpkv wrapper object -def simpkv=(value) - @simpkv = value -end +attr_writer :simpkv # Load simpkv.rb. The code evaluated will set this local scope variable # 'simp_simpkv_adapter_class' to an anonymous Class object for the simpkv adapter @@ -34,9 +30,9 @@ def simpkv=(value) # NOTE: 'simp_simpkv_adapter_class' **MUST** be defined prior to the eval # in order to be in scope simp_simpkv_adapter_class = nil -self.instance_eval( +instance_eval( File.read(File.join(File.dirname(__FILE__), 'simpkv.rb')), - File.join(File.dirname(__FILE__), 'simpkv.rb') + File.join(File.dirname(__FILE__), 'simpkv.rb'), ) # Set simpkv attribute of the object loading this file to a new simpkv diff --git a/lib/puppet_x/simpkv/plugin_template.rb b/lib/puppet_x/simpkv/plugin_template.rb index a1d3f06..806342b 100644 --- a/lib/puppet_x/simpkv/plugin_template.rb +++ b/lib/puppet_x/simpkv/plugin_template.rb @@ -41,12 +41,10 @@ # should provide instructions on how to install those Gems. ############################################################################### - # Each plugin **MUST** be an anonymous class accessible only through # a `plugin_class` local variable. # DO NOT CHANGE THE LINE BELOW!!!! -plugin_class = Class.new do - +Class.new do # WARNING: # In typical Ruby code, using constants and class methods is quite normal. # Unfortunately, you cannot use constants or class methods in an anonymous @@ -119,8 +117,7 @@ def initialize(name) # @raise RuntimeError if any required configuration is missing from options # or this object can't set up any stateful objects it needs to do its work # (e.g., file directory, connection to a backend) - def configure(options) - + def configure(_options) # FIXME: insert validation and set up code here # Be sure to create 'globals' and 'environments' sub-folders off of the # root directory. @@ -129,9 +126,7 @@ def configure(options) end # @return unique identifier assigned to this plugin instance - def name - @name - end + attr_reader :name # The remaining methods in this API map one-for-one to those in # simpkv's Puppet function API. @@ -182,8 +177,7 @@ def name # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def delete(key) - + def delete(_key) # FIXME: insert code that connects to the backend and affects the delete # operation # @@ -192,7 +186,7 @@ def delete(key) # error message. # - { :result => false, :err_msg => 'FIXME: not implemented' } + { result: false, err_msg: 'FIXME: not implemented' } end # Deletes a whole folder from the configured backend. @@ -203,8 +197,7 @@ def delete(key) # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def deletetree(keydir) - + def deletetree(_keydir) # FIXME: insert code that connects to the backend and affects the deletetree # operation # @@ -214,7 +207,7 @@ def deletetree(keydir) # error message. # - { :result => false, :err_msg => 'FIXME: not implemented' } + { result: false, err_msg: 'FIXME: not implemented' } end # Returns whether key or key folder exists in the configured backend. @@ -227,8 +220,7 @@ def deletetree(keydir) # * :err_msg - String. Explanatory text when status could not be # determined; nil otherwise. # - def exists(key) - + def exists(_key) # FIXME: insert code that connects to the backend and affects the exists # operation # @@ -236,7 +228,7 @@ def exists(key) # error message. # - { :result => nil, :err_msg => 'FIXME: not implemented' } + { result: nil, err_msg: 'FIXME: not implemented' } end # Retrieves the value stored at `key` from the configured backend. @@ -248,8 +240,7 @@ def exists(key) # be retrieved # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def get(key) - + def get(_key) # FIXME: insert code that connects to the backend and affects the get # operation # @@ -258,7 +249,7 @@ def get(key) # error message. # - { :result => nil, :err_msg => 'FIXME: not implemented' } + { result: nil, err_msg: 'FIXME: not implemented' } end # Returns a listing of all keys/info pairs and sub-folders in a folder @@ -279,8 +270,7 @@ def get(key) # # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def list(keydir) - + def list(_keydir) # FIXME: insert code that connects to the backend and affects the list # operation # @@ -288,7 +278,7 @@ def list(keydir) # error message. # - { :result => nil, :err_msg => 'FIXME: not implemented' } + { result: nil, err_msg: 'FIXME: not implemented' } end # Sets the data at `key` to a `value` in the configured backend. @@ -300,8 +290,7 @@ def list(keydir) # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def put(key, value) - + def put(_key, _value) # FIXME: insert code that connects to the backend and affects the put # operation # @@ -310,7 +299,6 @@ def put(key, value) # error message. # - { :result => false, :err_msg => 'FIXME: not implemented' } + { result: false, err_msg: 'FIXME: not implemented' } end - end diff --git a/lib/puppet_x/simpkv/simpkv.rb b/lib/puppet_x/simpkv/simpkv.rb index a38f89c..81bfe26 100644 --- a/lib/puppet_x/simpkv/simpkv.rb +++ b/lib/puppet_x/simpkv/simpkv.rb @@ -13,7 +13,7 @@ # - Deserializes value data to be retrieved from common JSON format # - Delegates actions to appropriate plugin instance # -simp_simpkv_adapter_class = Class.new do +Class.new do require 'base64' require 'json' require 'pathname' @@ -22,15 +22,15 @@ def initialize Puppet.debug('Constructing simpkv adapter from anonymous class') - @plugin_info = {} # backend plugin classes; - # key = backend type derived from the plugin base - # filename (_plugin.rb) - # value = { :class => , - # :source => - # } + @plugin_info = {} # backend plugin classes; + # key = backend type derived from the plugin base + # filename (_plugin.rb) + # value = { :class => , + # :source => + # } @plugin_instances = {} # backend plugin instances; - # key = name assigned to the instance, / - # supports multiple backend plugin instances per backend + # key = name assigned to the instance, / + # supports multiple backend plugin instances per backend # Load in the simpkv backend plugins from all modules. # @@ -65,24 +65,22 @@ def initialize Puppet.debug("Loading simpkv plugin from #{filename}") begin plugin_class = nil - self.instance_eval(File.read(filename), filename) + instance_eval(File.read(filename), filename) plugin_type = File.basename(filename, '_plugin.rb') - if @plugin_info.has_key?(plugin_type) - msg = "Skipping load of simpkv plugin from #{filename}: " + - "plugin type '#{plugin_type}' already loaded from " + - @plugin_info[plugin_type][:source] + if @plugin_info.key?(plugin_type) + msg = "Skipping load of simpkv plugin from #{filename}: " \ + "plugin type '#{plugin_type}' already loaded from " + + @plugin_info[plugin_type][:source] + Puppet.warning(msg) + elsif plugin_class.nil? + msg = "Skipping load of simpkv plugin from #{filename}: " \ + 'Internal error: Plugin missing required plugin_class definition' Puppet.warning(msg) else - if plugin_class.nil? - msg = "Skipping load of simpkv plugin from #{filename}: " + - 'Internal error: Plugin missing required plugin_class definition' - Puppet.warning(msg) - else - @plugin_info[plugin_type] = { - :class => plugin_class, - :source => filename - } - end + @plugin_info[plugin_type] = { + class: plugin_class, + source: filename + } end rescue SyntaxError => e Puppet.warning("simpkv plugin from #{filename} failed to load: #{e.message}") @@ -95,7 +93,7 @@ def initialize # @return list of backend plugins (i.e. their types) that have successfully # loaded def backends - return plugin_info.keys.sort + plugin_info.keys.sort end # execute delete operation on the backend, after normalizing the key @@ -112,12 +110,12 @@ def delete(key, options) result = nil begin instance = plugin_instance(options) - result = instance.delete( normalize_key(key, options) ) + result = instance.delete(normalize_key(key, options)) rescue Exception => e bt = filter_backtrace(e.backtrace) prefix = instance.nil? ? 'simpkv' : "simpkv #{instance.name}" err_msg = "#{prefix} Error: #{e.message}\n#{bt.join("\n")}".strip - result = { :result => false, :err_msg => err_msg } + result = { result: false, err_msg: err_msg } end result @@ -138,12 +136,12 @@ def deletetree(keydir, options) result = nil begin instance = plugin_instance(options) - result = instance.deletetree( normalize_key(keydir, options) ) + result = instance.deletetree(normalize_key(keydir, options)) rescue Exception => e bt = filter_backtrace(e.backtrace) prefix = instance.nil? ? 'simpkv' : "simpkv #{instance.name}" err_msg = "#{prefix} Error: #{e.message}\n#{bt.join("\n")}".strip - result = { :result => false, :err_msg => err_msg } + result = { result: false, err_msg: err_msg } end result @@ -165,12 +163,12 @@ def exists(key, options) result = nil begin instance = plugin_instance(options) - result = instance.exists( normalize_key(key, options) ) + result = instance.exists(normalize_key(key, options)) rescue Exception => e bt = filter_backtrace(e.backtrace) prefix = instance.nil? ? 'simpkv' : "simpkv #{instance.name}" err_msg = "#{prefix} Error: #{e.message}\n#{bt.join("\n")}".strip - result = { :result => nil, :err_msg => err_msg } + result = { result: nil, err_msg: err_msg } end result @@ -193,10 +191,10 @@ def get(key, options) result = nil begin instance = plugin_instance(options) - raw_result = instance.get( normalize_key(key, options) ) + raw_result = instance.get(normalize_key(key, options)) if raw_result[:result] value = deserialize(raw_result[:result]) - result = { :result => value, :err_msg => nil } + result = { result: value, err_msg: nil } else result = raw_result end @@ -204,7 +202,7 @@ def get(key, options) bt = filter_backtrace(e.backtrace) prefix = instance.nil? ? 'simpkv' : "simpkv #{instance.name}" err_msg = "#{prefix} Error: #{e.message}\n#{bt.join("\n")}".strip - result = { :result => nil, :err_msg => err_msg } + result = { result: nil, err_msg: err_msg } end result @@ -235,11 +233,11 @@ def list(keydir, options) result = nil begin instance = plugin_instance(options) - raw_result = instance.list( normalize_key(keydir, options) ) + raw_result = instance.list(normalize_key(keydir, options)) if raw_result[:result] - result = { - :result => { :keys => {}, :folders => [] }, - :err_msg => nil + result = { + result: { keys: {}, folders: [] }, + err_msg: nil } raw_result[:result][:folders].each do |raw_folder| @@ -247,7 +245,7 @@ def list(keydir, options) result[:result][:folders] << folder end - raw_result[:result][:keys].each do |raw_key,raw_value| + raw_result[:result][:keys].each do |raw_key, raw_value| key = normalize_key(raw_key, options, :remove_prefix) result[:result][:keys][key] = deserialize(raw_value) end @@ -258,7 +256,7 @@ def list(keydir, options) bt = filter_backtrace(e.backtrace) prefix = instance.nil? ? 'simpkv' : "simpkv #{instance.name}" err_msg = "#{prefix} Error: #{e.message}\n#{bt.join("\n")}".strip - result = { :result => nil, :err_msg => err_msg } + result = { result: nil, err_msg: err_msg } end result @@ -285,7 +283,7 @@ def put(key, value, metadata, options) bt = filter_backtrace(e.backtrace) prefix = instance.nil? ? 'simpkv' : "simpkv #{instance.name}" err_msg = "#{prefix} Error: #{e.message}\n#{bt.join("\n")}".strip - result = { :result => false, :err_msg => err_msg } + result = { result: false, err_msg: err_msg } end result @@ -309,9 +307,9 @@ def filter_backtrace(backtrace) # The user will still know the manifest that couldn't be compiled, # because the compiler automatically adds a log line that reports the # manifest file and line number that failed compilation. - short_bt = backtrace.reverse.drop_while { |line| + short_bt = backtrace.reverse.drop_while do |line| !line.include?('/simpkv/lib/puppet/functions/simpkv/') - } + end short_bt.reverse end @@ -335,17 +333,17 @@ def global_prefix # def normalize_key(key, options, operation = :add_prefix) normalized_key = key.dup - if options.fetch('global', false) - prefix = global_prefix - else - prefix = environment_prefix(options['environment']) - end + prefix = if options.fetch('global', false) + global_prefix + else + environment_prefix(options['environment']) + end case operation when :add_prefix normalized_key = "#{prefix}/#{key}" when :remove_prefix - normalized_key = key.gsub(/^#{prefix}\//,'') + normalized_key = key.gsub(%r{^#{prefix}/}, '') else # do nothing end @@ -373,16 +371,15 @@ def normalize_key(key, options, operation = :add_prefix) # plugin constructor fails def plugin_instance(options) # backend config should already have been verified, but just in case... - unless ( - options.is_a?(Hash) && - options.has_key?('backend') && - options.has_key?('backends') && - options['backends'].is_a?(Hash) && - options['backends'].has_key?(options['backend']) && - options['backends'][ options['backend'] ].has_key?('id') && - options['backends'][ options['backend'] ].has_key?('type') && - plugin_info.has_key?(options['backends'][ options['backend'] ]['type']) - ) + unless options.is_a?(Hash) && + options.key?('backend') && + options.key?('backends') && + options['backends'].is_a?(Hash) && + options['backends'].key?(options['backend']) && + options['backends'][ options['backend'] ].key?('id') && + options['backends'][ options['backend'] ].key?('type') && + plugin_info.key?(options['backends'][ options['backend'] ]['type']) + raise("Malformed backend config in options=#{options}") end @@ -392,7 +389,7 @@ def plugin_instance(options) type = backend_config['type'] name = "#{type}/#{id}" - unless plugin_instances.has_key?(name) + unless plugin_instances.key?(name) begin plugin_instances[name] = plugin_info[type][:class].new(name) plugin_instances[name].configure(options) @@ -413,7 +410,7 @@ def plugin_instance(options) # key, or the optional 'encoding' key contains an unsupported encoding # scheme. # - #FIXME This should use Puppet's deserialization code so that + # FIXME This should use Puppet's deserialization code so that # all contained Binary strings in the value object are properly deserialized def deserialize(serialized_value) begin @@ -421,16 +418,16 @@ def deserialize(serialized_value) rescue JSON::ParserError => e raise("Failed to deserialize: JSON parse error: #{e}") end - unless encapsulation.has_key?('value') + unless encapsulation.key?('value') raise("Failed to deserialize: 'value' missing in '#{serialized_value}'") end result = {} - if encapsulation['value'].is_a?(String) - result[:value] = deserialize_string_value(encapsulation) - else - result[:value] = encapsulation['value'] - end + result[:value] = if encapsulation['value'].is_a?(String) + deserialize_string_value(encapsulation) + else + encapsulation['value'] + end result[:metadata] = encapsulation['metadata'] @@ -440,16 +437,14 @@ def deserialize(serialized_value) # @raise RuntimeError if the optional 'encoding' specifie dis not 'base64' def deserialize_string_value(encapsulation) value = encapsulation['value'] - if encapsulation.has_key?('encoding') + if encapsulation.key?('encoding') # right now, only support base64 encoding - if encapsulation['encoding'] == 'base64' - value = Base64.strict_decode64(encapsulation['value']) - if encapsulation.has_key?('original_encoding') - value.force_encoding(encapsulation['original_encoding']) - end - else - raise("Failed to deserialize: Unsupported encoding in '#{encapsulation}'") + raise("Failed to deserialize: Unsupported encoding in '#{encapsulation}'") unless encapsulation['encoding'] == 'base64' + value = Base64.strict_decode64(encapsulation['value']) + if encapsulation.key?('original_encoding') + value.force_encoding(encapsulation['original_encoding']) end + end value @@ -474,18 +469,17 @@ def deserialize_string_value(encapsulation) # Array value, binary Strings within the metadata Hash) will fail # serialization unless that binary data just happens to form valid UTF-8. # - #FIXME This should use Puppet's serialization code so that all contained Binary + # FIXME This should use Puppet's serialization code so that all contained Binary # strings are properly serialized def serialize(value, metadata) - encapsulation = nil - if value.is_a?(String) - encapsulation = serialize_string_value(value, metadata) - elsif value.respond_to?(:binary_buffer) - # This is a Puppet Binary type - encapsulation = serialize_binary_data(value.binary_buffer, metadata) - else - encapsulation = { 'value' => value, 'metadata' => metadata } - end + encapsulation = if value.is_a?(String) + serialize_string_value(value, metadata) + elsif value.respond_to?(:binary_buffer) + # This is a Puppet Binary type + serialize_binary_data(value.binary_buffer, metadata) + else + { 'value' => value, 'metadata' => metadata } + end # This will raise an error if the value or metadata contains # any element that cannot be serialized to JSON. Caller catches # error and reports failure. @@ -494,7 +488,7 @@ def serialize(value, metadata) def serialize_binary_data(value, metadata) encoded_value = Base64.strict_encode64(value) - encapsulation = { + { 'value' => encoded_value, 'encoding' => 'base64', 'original_encoding' => 'ASCII-8BIT', @@ -510,14 +504,11 @@ def serialize_string_value(value, metadata) # TODO Should we fail instead and tell the user to use a Binary type? normalized_value.force_encoding('ASCII-8BIT') end - - encapsulation = nil - if normalized_value.encoding == Encoding::ASCII_8BIT - encapsulation = serialize_binary_data(normalized_value, metadata) - else - encapsulation = { 'value' => normalized_value, 'metadata' => metadata } - end + encapsulation = if normalized_value.encoding == Encoding::ASCII_8BIT + serialize_binary_data(normalized_value, metadata) + else + { 'value' => normalized_value, 'metadata' => metadata } + end encapsulation end - end diff --git a/spec/acceptance/helpers.rb b/spec/acceptance/helpers.rb index 7ab878a..29bdf1d 100644 --- a/spec/acceptance/helpers.rb +++ b/spec/acceptance/helpers.rb @@ -1,2 +1,2 @@ -rb_files = File.expand_path( 'helpers/**/*.rb', __dir__) -Dir.glob( rb_files ).sort_by(&:to_s).each { |file| require file } +rb_files = File.expand_path('helpers/**/*.rb', __dir__) +Dir.glob(rb_files).sort_by(&:to_s).each { |file| require file } diff --git a/spec/acceptance/helpers/ldap_utils.rb b/spec/acceptance/helpers/ldap_utils.rb index f793154..6abbbc9 100644 --- a/spec/acceptance/helpers/ldap_utils.rb +++ b/spec/acceptance/helpers/ldap_utils.rb @@ -1,88 +1,82 @@ -module Acceptance - module Helpers - module LdapUtils - - # @return DN for a folder path - # - # @param folder Folder path - # @param base_dn Base DN - # - def build_folder_dn(folder, base_dn) - parts = folder.split('/') - dn = '' - parts.reverse.each { |subfolder| dn += "ou=#{subfolder}," } - dn += base_dn - dn - end - - # @return DN for a key path - # - # @param key_path Key path - # @param base_dn Base DN - # - def build_key_dn(key_path, base_dn) - key_name = File.basename(key_path) - key_folder = File.dirname(key_path) - "simpkvKey=#{key_name},#{build_folder_dn(key_folder, base_dn)}" - end +module Acceptance::Helpers::LdapUtils + # @return DN for a folder path + # + # @param folder Folder path + # @param base_dn Base DN + # + def build_folder_dn(folder, base_dn) + parts = folder.split('/') + dn = '' + parts.reverse_each { |subfolder| dn += "ou=#{subfolder}," } + dn += base_dn + dn + end - # @return Command with the LDAP server uri option and options and - # environment variables for authentication - # - # **ASSUMES** ldap_backend_config is valid! - # - # @param base_command Base command to be run (e.g., ldapsearch) - # @param ldap_backend_config ldap backend configuration - # - def build_ldap_command(base_command, ldap_backend_config) - ldap_uri = ldap_backend_config['ldap_uri'] - admin_dn = ldap_backend_config.fetch('admin_dn', nil) - admin_pw_file = ldap_backend_config.fetch('admin_pw_file', nil) + # @return DN for a key path + # + # @param key_path Key path + # @param base_dn Base DN + # + def build_key_dn(key_path, base_dn) + key_name = File.basename(key_path) + key_folder = File.dirname(key_path) + "simpkvKey=#{key_name},#{build_folder_dn(key_folder, base_dn)}" + end - opts = nil - enable_tls = nil - if ldap_uri.match(/^ldapi:/) - enable_tls = false - elsif ldap_uri.match(/^ldaps:/) - enable_tls = true - elsif ldap_backend_config.key?('enable_tls') - enable_tls = ldap_backend_config['enable_tls'] - else - enable_tls = false - end + # @return Command with the LDAP server uri option and options and + # environment variables for authentication + # + # **ASSUMES** ldap_backend_config is valid! + # + # @param base_command Base command to be run (e.g., ldapsearch) + # @param ldap_backend_config ldap backend configuration + # + def build_ldap_command(base_command, ldap_backend_config) + ldap_uri = ldap_backend_config['ldap_uri'] + admin_dn = ldap_backend_config.fetch('admin_dn', nil) + admin_pw_file = ldap_backend_config.fetch('admin_pw_file', nil) - if enable_tls - tls_cert = ldap_backend_config['tls_cert'] - tls_key = ldap_backend_config['tls_key'] - tls_cacert = ldap_backend_config['tls_cacert'] + opts = nil + enable_tls = if ldap_uri.match?(%r{^ldapi:}) + false + elsif ldap_uri.match?(%r{^ldaps:}) + true + elsif ldap_backend_config.key?('enable_tls') + ldap_backend_config['enable_tls'] + else + false + end - cmd_env = [ - "LDAPTLS_CERT=#{tls_cert}", - "LDAPTLS_KEY=#{tls_key}", - "LDAPTLS_CACERT=#{tls_cacert}" - ].join(' ') + if enable_tls + tls_cert = ldap_backend_config['tls_cert'] + tls_key = ldap_backend_config['tls_key'] + tls_cacert = ldap_backend_config['tls_cacert'] - if ldap_uri.match(/^ldap:/) - # StartTLS - opts = %Q{-ZZ -x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}} - else - # TLS - opts = %Q{-x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}} - end + cmd_env = [ + "LDAPTLS_CERT=#{tls_cert}", + "LDAPTLS_KEY=#{tls_key}", + "LDAPTLS_CACERT=#{tls_cacert}", + ].join(' ') - else - cmd_env = '' - if admin_pw_file - # unencrypted ldap or ldapi with simple authentication - opts = %Q{-x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}} - else - # ldapi with EXTERNAL SASL - opts = "-Y EXTERNAL -H #{ldap_uri}" - end - end + opts = if ldap_uri.match?(%r{^ldap:}) + # StartTLS + %(-ZZ -x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}) + else + # TLS + %(-x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}) + end - "#{cmd_env} #{base_command} #{opts}" - end + else + cmd_env = '' + opts = if admin_pw_file + # unencrypted ldap or ldapi with simple authentication + %(-x -D "#{admin_dn}" -y #{admin_pw_file} -H #{ldap_uri}) + else + # ldapi with EXTERNAL SASL + "-Y EXTERNAL -H #{ldap_uri}" + end end + + "#{cmd_env} #{base_command} #{opts}" end end diff --git a/spec/acceptance/helpers/manifest_utils.rb b/spec/acceptance/helpers/manifest_utils.rb index 119c6b6..531efe5 100644 --- a/spec/acceptance/helpers/manifest_utils.rb +++ b/spec/acceptance/helpers/manifest_utils.rb @@ -1,25 +1,19 @@ -module Acceptance - module Helpers - module ManifestUtils - - def print_test_config(hieradata, manifest) - puts '>'*80 - if hieradata.is_a?(Hash) - puts "Hieradata:\n#{hieradata.to_yaml}" - else - puts "Hieradata:\n#{hieradata}" - end - puts '-'*80 - puts "Manifest:\n#{manifest}" - puts '<'*80 - end - - def set_hiera_and_apply_on(host, hieradata, manifest, apply_opts = {}, verbose = true ) - print_test_config(hieradata, manifest) if verbose - set_hieradata_on(host, hieradata) - apply_manifest_on(host, manifest, apply_opts) - end - +module Acceptance::Helpers::ManifestUtils + def print_test_config(hieradata, manifest) + puts '>' * 80 + if hieradata.is_a?(Hash) + puts "Hieradata:\n#{hieradata.to_yaml}" + else + puts "Hieradata:\n#{hieradata}" end + puts '-' * 80 + puts "Manifest:\n#{manifest}" + puts '<' * 80 + end + + def set_hiera_and_apply_on(host, hieradata, manifest, apply_opts = {}, verbose = true) + print_test_config(hieradata, manifest) if verbose + set_hieradata_on(host, hieradata) + apply_manifest_on(host, manifest, apply_opts) end end diff --git a/spec/acceptance/helpers/test_data.rb b/spec/acceptance/helpers/test_data.rb index acb3c83..aefdf24 100644 --- a/spec/acceptance/helpers/test_data.rb +++ b/spec/acceptance/helpers/test_data.rb @@ -16,7 +16,6 @@ module Acceptance::Helpers; end # generation/transformation methods. module Acceptance::Helpers::TestData - # @return simpkv::options hieradata with aliases to backend configuration # derived from backend_configs # @@ -57,7 +56,7 @@ def generate_backend_hiera(backend_configs) backend_tag = "simpkv::backend::#{name}" hiera[backend_tag] = Marshal.load(Marshal.dump(config)) hiera[backend_tag]['id'] = name - backends[name]= "%{alias('#{backend_tag}')}" + backends[name] = "%{alias('#{backend_tag}')}" end hiera['simpkv::options'] = { @@ -98,7 +97,7 @@ def generate_initial_key_info(app_id1, app_id2, app_id3) appid3 = (app_id3 == 'default') ? '' : app_id3 data_yaml = ERB.new(File.read(data_template)).result(binding) - YAML.load(data_yaml) + YAML.safe_load(data_yaml) end # @return transformed copy of original_key_info in which the key values and/or @@ -113,9 +112,9 @@ def generate_initial_key_info(app_id1, app_id2, app_id3) # def modify_key_data(original_key_info) updated_key_info = Marshal.load(Marshal.dump(original_key_info)) - updated_key_info.each do |app_id, key_struct| - key_struct.each do |key_type, keys| - keys.each do |key, key_data| + updated_key_info.each_value do |key_struct| + key_struct.each_value do |keys| + keys.each_value do |key_data| # modify non-binary values if key_data.key?('value') if key_data['value'].is_a?(Array) || key_data['value'].is_a?(String) @@ -123,7 +122,7 @@ def modify_key_data(original_key_info) end if key_data['value'].is_a?(TrueClass) || key_data['value'].is_a?(FalseClass) - key_data['value'] = ! key_data['value'] + key_data['value'] = !key_data['value'] end if key_data['value'].is_a?(Hash) @@ -135,11 +134,11 @@ def modify_key_data(original_key_info) end end - #TODO modify binary values specified by a 'file' attribute + # TODO: modify binary values specified by a 'file' attribute # modify metadata if key_data.key?('metadata') - key_data.delete('metadata') + key_data.delete('metadata') else key_data['metadata'] = { 'version' => 2 } end @@ -158,13 +157,13 @@ def modify_key_data(original_key_info) # # @param suffix Suffix to be appended to each original folder name # - def rename_folders_in_folder_info(original_folder_info, suffix='new') + def rename_folders_in_folder_info(original_folder_info, suffix = 'new') new_info = {} - original_folder_info.each do |app_id,folder_struct| + original_folder_info.each do |app_id, folder_struct| new_info[app_id] = {} - folder_struct.each do |folder_type,folders| + folder_struct.each do |folder_type, folders| new_info[app_id][folder_type] = {} - folders.each do |folder,folder_data| + folders.each do |folder, folder_data| new_info[app_id][folder_type]["#{folder}#{suffix}"] = folder_data end end @@ -181,9 +180,9 @@ def rename_folders_in_folder_info(original_folder_info, suffix='new') # # @param suffix Suffix to be appended to each original folder name # - def rename_folders_in_name_info(original_foldername_info, suffix='new') + def rename_folders_in_name_info(original_foldername_info, suffix = 'new') new_info = Marshal.load(Marshal.dump(original_foldername_info)) - new_info.each do |app_id,folder_struct| + new_info.each_value do |folder_struct| folder_struct.each do |folder_type, folder_names| folder_struct[folder_type] = folder_names.map { |folder| "#{folder}#{suffix}" } end @@ -200,7 +199,7 @@ def rename_folders_in_name_info(original_foldername_info, suffix='new') # # @param suffix String to be appended to original key names # - def rename_keys_in_key_info(original_key_info, suffix='new') + def rename_keys_in_key_info(original_key_info, suffix = 'new') key_info = {} original_key_info.each do |app_id, key_struct| key_info[app_id] = {} @@ -229,7 +228,7 @@ def rename_keys_in_key_info(original_key_info, suffix='new') def root_foldername_info(key_info) foldername_info = {} full_foldername_info = to_foldername_info(key_info) - full_foldername_info.each do |app_id,folder_struct| + full_foldername_info.each do |app_id, folder_struct| folder_struct.each do |folder_type, folder_names| if folder_names.include?('/') foldername_info[app_id] = {} unless foldername_info.key?(app_id) @@ -255,7 +254,7 @@ def root_foldername_info(key_info) # def select_subfolders_subset(original_foldername_info) subset_info = {} - original_foldername_info.each do |app_id,folder_struct| + original_foldername_info.each do |app_id, folder_struct| folder_struct.each do |folder_type, folder_names| count = 0 selected = [] @@ -270,7 +269,7 @@ def select_subfolders_subset(original_foldername_info) end end - if !within_selected_folder && ( (count % 2) == 0) + if !within_selected_folder && count.even? selected << folder count += 1 end @@ -303,7 +302,7 @@ def select_subfolders_subset(original_foldername_info) def split_key_info_per_subfolder_deletes(original_key_info, delete_foldernames_info) retain_index = 0 remove_index = 1 - key_infos = [ Hash.new, Hash.new ] + key_infos = [ {}, {} ] original_key_info.each do |app_id, key_struct| key_struct.each do |key_type, keys| keys.each do |key, key_data| @@ -318,7 +317,7 @@ def split_key_info_per_subfolder_deletes(original_key_info, delete_foldernames_i end end - key_infos[type][app_id] = {} unless key_infos[type].key?(app_id) + key_infos[type][app_id] = {} unless key_infos[type].key?(app_id) key_infos[type][app_id][key_type] = {} unless key_infos[type][app_id].key?(key_type) key_infos[type][app_id][key_type][key] = key_data end @@ -342,13 +341,13 @@ def split_key_info_per_subfolder_deletes(original_key_info, delete_foldernames_i # the Simpkv_test::KeyInfo type alias or is empty, if input key info hash is # too sparse to support the split size specified. # - def split_key_info(original_key_info, split_size=2) - key_infos = Array.new(split_size) { Hash.new } + def split_key_info(original_key_info, split_size = 2) + key_infos = Array.new(split_size) { {} } original_key_info.each do |app_id, key_struct| - key_infos.each { |key_info| key_info[app_id] = Hash.new } + key_infos.each { |key_info| key_info[app_id] = {} } key_struct.each do |key_type, keys| - key_infos.each { |key_info| key_info[app_id][key_type] = Hash.new } + key_infos.each { |key_info| key_info[app_id][key_type] = {} } count = 0 keys.each do |key, key_data| @@ -365,7 +364,7 @@ def split_key_info(original_key_info, split_size=2) key_infos.each do |key_info| if key_info[app_id].empty? - key_info.delete(app_id) + key_info.delete(app_id) end end end @@ -386,7 +385,7 @@ def split_key_info(original_key_info, split_size=2) # @param exclude_root_folder Whether to exclude the root folder from the returned # listing # - def to_folder_info(key_info, exclude_root_folder=false) + def to_folder_info(key_info, exclude_root_folder = false) folder_info = {} key_info.each do |app_id, key_struct| folder_info[app_id] = {} @@ -413,11 +412,11 @@ def to_folder_info(key_info, exclude_root_folder=false) end end - folder_info.each do |app_id, folder_struct| - folder_struct.each do |folder_type, folders| - folders.delete_if do |folder, folder_data| + folder_info.each_value do |folder_struct| + folder_struct.each_value do |folders| + folders.delete_if do |_folder, folder_data| binary_data = false - folder_data['keys'].each do |key, key_data| + folder_data['keys'].each_value do |key_data| if key_data.key?('file') binary_data = true break @@ -445,12 +444,11 @@ def to_foldername_info(key_info) key_struct.each do |key_type, keys| foldername_info[app_id][key_type] = Set.new foldername_info[app_id][key_type] << '/' - keys.each do |key, key_data| + keys.each_key do |key| path = File.dirname(key) - unless path == '.' - Pathname.new(path).descend do |folder| - foldername_info[app_id][key_type] << folder.to_s - end + next if path == '.' + Pathname.new(path).descend do |folder| + foldername_info[app_id][key_type] << folder.to_s end end @@ -479,4 +477,3 @@ def to_keyname_info(key_info) keyname_info end end - diff --git a/spec/acceptance/helpers/utils.rb b/spec/acceptance/helpers/utils.rb index ac304ac..65aa857 100644 --- a/spec/acceptance/helpers/utils.rb +++ b/spec/acceptance/helpers/utils.rb @@ -5,7 +5,6 @@ module Acceptance; end module Acceptance::Helpers; end module Acceptance::Helpers::Utils - # @return Backend configuration Hash for the backend corresponding to app_id and # plugin_type # @@ -32,16 +31,16 @@ def backend_config_for_app_id(app_id, plugin_type, backend_hiera) backend_hiera['simpkv::options']['backends'][app_id] end elsif backend_hiera['simpkv::options']['backends'].key?('default') - if backend_hiera['simpkv::options']['backends']['default'].is_a?(String) - # Assume this is an alias for simpkv::backend::default - config = backend_hiera['simpkv::backend::default'] - else - config = backend_hiera['simpkv::options']['backends']['default'] - end + config = if backend_hiera['simpkv::options']['backends']['default'].is_a?(String) + # Assume this is an alias for simpkv::backend::default + backend_hiera['simpkv::backend::default'] + else + backend_hiera['simpkv::options']['backends']['default'] + end end - if config.empty? || ( !plugin_type.nil? && (config['type'] != plugin_type) ) - fail("No '#{plugin_type}' backend found for #{app_id}") + if config.empty? || (!plugin_type.nil? && (config['type'] != plugin_type)) + raise("No '#{plugin_type}' backend found for #{app_id}") end config @@ -55,28 +54,26 @@ def backend_config_for_app_id(app_id, plugin_type, backend_hiera) # @param key_data Hash with key data corresponding to Simpkv_test::KeyData # def key_data_string(key_data) - key_hash = {} - if key_data.key?('value') - key_hash['value'] = key_data['value'] - elsif key_data.key?('file') - simpkv_test_files = File.join(__dir__, '../../support/modules/simpkv_test/files') - value = IO.read( key_data['file'].gsub('simpkv_test', "#{simpkv_test_files}") ) - value.force_encoding('ASCII-8BIT') + key_hash = {} + if key_data.key?('value') + key_hash['value'] = key_data['value'] + elsif key_data.key?('file') + simpkv_test_files = File.join(__dir__, '../../support/modules/simpkv_test/files') + value = IO.read(key_data['file'].gsub('simpkv_test', simpkv_test_files.to_s)) + value.force_encoding('ASCII-8BIT') - encoded_value = Base64.strict_encode64(value) - key_hash['value'] = encoded_value - key_hash['encoding'] = 'base64' - key_hash['original_encoding'] = 'ASCII-8BIT' - end + encoded_value = Base64.strict_encode64(value) + key_hash['value'] = encoded_value + key_hash['encoding'] = 'base64' + key_hash['original_encoding'] = 'ASCII-8BIT' + end - if key_data.key?('metadata') - key_hash['metadata'] = key_data['metadata'] - else - key_hash['metadata'] = {} - end + key_hash['metadata'] = if key_data.key?('metadata') + key_data['metadata'] + else + {} + end - key_hash.to_json + key_hash.to_json end - end - diff --git a/spec/acceptance/shared_examples.rb b/spec/acceptance/shared_examples.rb index b689f67..892e442 100644 --- a/spec/acceptance/shared_examples.rb +++ b/spec/acceptance/shared_examples.rb @@ -1,2 +1,2 @@ -rb_files = File.expand_path( 'shared_examples/**/*.rb', __dir__) -Dir.glob( rb_files ).sort_by(&:to_s).each { |file| require file } +rb_files = File.expand_path('shared_examples/**/*.rb', __dir__) +Dir.glob(rb_files).sort_by(&:to_s).each { |file| require file } diff --git a/spec/acceptance/shared_examples/pre_populate_keystores.rb b/spec/acceptance/shared_examples/pre_populate_keystores.rb index 5ec8283..31e7e67 100644 --- a/spec/acceptance/shared_examples/pre_populate_keystores.rb +++ b/spec/acceptance/shared_examples/pre_populate_keystores.rb @@ -16,20 +16,20 @@ # shared_examples 'pre-populate keystores' do |host| context "ensure keystores are pre-populated with initial keys on #{host}" do - let(:hieradata) { - backend_hiera.merge( { - 'simpkv_test::store_keys::key_info' => initial_key_info - } ) - } + let(:hieradata) do + backend_hiera.merge({ + 'simpkv_test::store_keys::key_info' => initial_key_info + }) + end let(:manifest) { 'include simpkv_test::store_keys' } - it 'should remove all backend instance data' do - on(host, clear_data_cmd, :accept_all_exit_codes => true) + it 'removes all backend instance data' do + on(host, clear_data_cmd, accept_all_exit_codes: true) end - it 'should store keys' do - set_hiera_and_apply_on(host, hieradata, manifest, { :catch_failures => true }) + it 'stores keys' do + set_hiera_and_apply_on(host, hieradata, manifest, { catch_failures: true }) end end end diff --git a/spec/acceptance/shared_examples/simpkv_delete.rb b/spec/acceptance/shared_examples/simpkv_delete.rb index 59847b4..283e989 100644 --- a/spec/acceptance/shared_examples/simpkv_delete.rb +++ b/spec/acceptance/shared_examples/simpkv_delete.rb @@ -45,53 +45,52 @@ # # Hashes are subsets of initial_key_info # - let(:test_key_infos) { + let(:test_key_infos) do key_infos = split_key_info(initial_key_info, 2) - if key_infos[0].empty? or key_infos[1].empty? - raise("Unable to split the initial_key_info into two non-empty Hashes. Data provided is too sparse") + if key_infos[0].empty? || key_infos[1].empty? + raise('Unable to split the initial_key_info into two non-empty Hashes. Data provided is too sparse') end { - :remove => key_infos[0], - :retain => key_infos[1] + remove: key_infos[0], + retain: key_infos[1] } - } + end let(:remove_manifest) { 'include simpkv_test::remove_keys' } - let(:remove_hieradata) { - backend_hiera.merge( { - 'simpkv_test::remove_keys::keyname_info' => to_keyname_info(test_key_infos[:remove]) - } ) - } + let(:remove_hieradata) do + backend_hiera.merge({ + 'simpkv_test::remove_keys::keyname_info' => to_keyname_info(test_key_infos[:remove]) + }) + end let(:verify_manifest) { 'include simpkv_test::retrieve_and_verify_keys' } - let(:verify_hieradata) { - backend_hiera.merge( { - 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => test_key_infos[:retain], + let(:verify_hieradata) do + backend_hiera.merge({ + 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => test_key_infos[:retain], 'simpkv_test::retrieve_and_verify_keys::invalid_key_info' => test_key_infos[:remove] - } ) - } + }) + end - it 'should call simpkv::delete with valid keys without errors' do + it 'calls simpkv::delete with valid keys without errors' do set_hiera_and_apply_on(host, remove_hieradata, remove_manifest, - { :catch_failures => true }) + { catch_failures: true }) end - it 'should retain only untouched keys in backends' do - expect( validator.call(test_key_infos[:retain], true, backend_hiera, host) ).to be true - expect( validator.call(test_key_infos[:remove], false, backend_hiera, host) ).to be true + it 'retains only untouched keys in backends' do + expect(validator.call(test_key_infos[:retain], true, backend_hiera, host)).to be true + expect(validator.call(test_key_infos[:remove], false, backend_hiera, host)).to be true end - it 'should only be able to retrieve untouched keys via simpkv::get' do + it 'onlies be able to retrieve untouched keys via simpkv::get' do set_hiera_and_apply_on(host, verify_hieradata, verify_manifest, - { :catch_failures => true }) + { catch_failures: true }) end - it 'should call simpkv::delete with invalid keys without errors' do + it 'calls simpkv::delete with invalid keys without errors' do set_hiera_and_apply_on(host, remove_hieradata, remove_manifest, - { :catch_failures => true }) + { catch_failures: true }) end end end - diff --git a/spec/acceptance/shared_examples/simpkv_deletetree.rb b/spec/acceptance/shared_examples/simpkv_deletetree.rb index 602cc43..31d25ea 100644 --- a/spec/acceptance/shared_examples/simpkv_deletetree.rb +++ b/spec/acceptance/shared_examples/simpkv_deletetree.rb @@ -40,52 +40,52 @@ context "simpkv::deletetree operation on #{host}" do let(:initial_foldername_info) { to_foldername_info(initial_key_info) } - let(:subfolders_to_delete) { + let(:subfolders_to_delete) do subfolders = select_subfolders_subset(initial_foldername_info) if subfolders.empty? raise('No subfolders from initial_key_info selected for deletion: data too sparse') end subfolders - } + end - let(:test_key_infos_after_subfolder_delete) { + let(:test_key_infos_after_subfolder_delete) do key_infos = split_key_info_per_subfolder_deletes(initial_key_info, subfolders_to_delete) - { :retain => key_infos[0], :remove => key_infos[1] } - } + { retain: key_infos[0], remove: key_infos[1] } + end # Any root folder that originally had key data. - let(:root_folders) { + let(:root_folders) do foldername_info = root_foldername_info(initial_key_info) if foldername_info.empty? raise('All root folders found in initial_key_info are empty: No keys!') end foldername_info - } + end let(:remove_manifest) { 'include simpkv_test::remove_folders' } - let(:remove_subfolders_hieradata) { - backend_hiera.merge( { - 'simpkv_test::remove_folders::foldername_info' => subfolders_to_delete - } ) - } - - let(:remove_root_folders_hieradata) { - backend_hiera.merge( { - 'simpkv_test::remove_folders::foldername_info' => root_folders - } ) - } + let(:remove_subfolders_hieradata) do + backend_hiera.merge({ + 'simpkv_test::remove_folders::foldername_info' => subfolders_to_delete + }) + end + + let(:remove_root_folders_hieradata) do + backend_hiera.merge({ + 'simpkv_test::remove_folders::foldername_info' => root_folders + }) + end let(:verify_manifest) { 'include simpkv_test::retrieve_and_verify_folders' } - let(:verify_hieradata_after_subfolders_delete) { - backend_hiera.merge( { - 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => to_folder_info(test_key_infos_after_subfolder_delete[:retain]), + let(:verify_hieradata_after_subfolders_delete) do + backend_hiera.merge({ + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => to_folder_info(test_key_infos_after_subfolder_delete[:retain]), 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => to_folder_info(test_key_infos_after_subfolder_delete[:remove], true) - } ) - } + }) + end - let(:verify_empty_backend_folders_hieradata) { + let(:verify_empty_backend_folders_hieradata) do # Expected results after root directories have been removed: # - The root folder for the Puppet environment in each backend will no # longer exist, and so a listing of if will fail. @@ -96,50 +96,49 @@ env_folder_info = {} global_folder_info = {} empty_folders = { '/' => { 'keys' => {}, 'folders' => [] } } - initial_key_info.keys.each do |app_id| + initial_key_info.each_key do |app_id| env_folder_info[app_id] = { 'env' => Marshal.load(Marshal.dump(empty_folders)) } global_folder_info[app_id] = { 'global' => Marshal.load(Marshal.dump(empty_folders)) } end - backend_hiera.merge( { - 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => global_folder_info, + backend_hiera.merge({ + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => global_folder_info, 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => env_folder_info - } ) - } + }) + end - it 'should call simpkv::deletetree with valid sub-folders without errors' do + it 'calls simpkv::deletetree with valid sub-folders without errors' do set_hiera_and_apply_on(host, remove_subfolders_hieradata, remove_manifest, - { :catch_failures => true }) + { catch_failures: true }) end - it 'should retain only untouched keys/folders in backends' do + it 'retains only untouched keys/folders in backends' do set_hiera_and_apply_on(host, verify_hieradata_after_subfolders_delete, - verify_manifest, { :catch_failures => true }) + verify_manifest, { catch_failures: true }) end - it 'should call simpkv::deletetree with root folders without errors' do + it 'calls simpkv::deletetree with root folders without errors' do set_hiera_and_apply_on(host, remove_root_folders_hieradata, - remove_manifest, { :catch_failures => true }) + remove_manifest, { catch_failures: true }) end - it 'should retain no key data in the backends' do - # This makes sure there is no key data, but does not verify that the - # directory tree is absent. That verification is done by the next test - # example. - expect( validator.call(initial_key_info, false, backend_hiera, host) ).to be true + it 'retains no key data in the backends' do + # This makes sure there is no key data, but does not verify that the + # directory tree is absent. That verification is done by the next test + # example. + expect(validator.call(initial_key_info, false, backend_hiera, host)).to be true end - it 'should retrieve non-existent or empty root dir list results from the backends' do + it 'retrieves non-existent or empty root dir list results from the backends' do # non-existent: Puppet environment root dirs # empty: global root dirs set_hiera_and_apply_on(host, verify_empty_backend_folders_hieradata, - verify_manifest, { :catch_failures => true }) + verify_manifest, { catch_failures: true }) end - it 'should call simpkv::deletetree with invalid folders without errors' do + it 'calls simpkv::deletetree with invalid folders without errors' do set_hiera_and_apply_on(host, remove_subfolders_hieradata, - remove_manifest, { :catch_failures => true }) + remove_manifest, { catch_failures: true }) end end end - diff --git a/spec/acceptance/shared_examples/simpkv_exists.rb b/spec/acceptance/shared_examples/simpkv_exists.rb index 9c71b38..2eda986 100644 --- a/spec/acceptance/shared_examples/simpkv_exists.rb +++ b/spec/acceptance/shared_examples/simpkv_exists.rb @@ -20,65 +20,65 @@ context "simpkv::exists operation for keys on #{host}" do let(:initial_keyname_info) { to_keyname_info(initial_key_info) } - let(:hieradata_with_valid_keys) { - backend_hiera.merge( { - 'simpkv_test::verify_keys_exist::valid_keyname_info' => initial_keyname_info, + let(:hieradata_with_valid_keys) do + backend_hiera.merge({ + 'simpkv_test::verify_keys_exist::valid_keyname_info' => initial_keyname_info, 'simpkv_test::verify_keys_exist::invalid_keyname_info' => {} - } ) - } + }) + end # copy of initial_key_info for which all key names have been modified let(:new_key_info) { rename_keys_in_key_info(initial_key_info) } let(:new_keyname_info) { to_keyname_info(new_key_info) } - let(:hieradata_with_invalid_keys) { - backend_hiera.merge( { - 'simpkv_test::verify_keys_exist::valid_keyname_info' => {}, + let(:hieradata_with_invalid_keys) do + backend_hiera.merge({ + 'simpkv_test::verify_keys_exist::valid_keyname_info' => {}, 'simpkv_test::verify_keys_exist::invalid_keyname_info' => new_keyname_info - } ) - } + }) + end let(:manifest) { 'include simpkv_test::verify_keys_exist' } - it 'should call simpkv::exists for valid keys and return true' do + it 'calls simpkv::exists for valid keys and return true' do set_hiera_and_apply_on(host, hieradata_with_valid_keys, manifest, - { :catch_failures => true }) + { catch_failures: true }) end - it 'should call simpkv::exists for invalid keys and return false' do + it 'calls simpkv::exists for invalid keys and return false' do set_hiera_and_apply_on(host, hieradata_with_invalid_keys, manifest, - { :catch_failures => true }) + { catch_failures: true }) end end context "simpkv::exists operation for folders on #{host}" do let(:initial_foldername_info) { to_foldername_info(initial_key_info) } - let(:hieradata_with_valid_folders) { - backend_hiera.merge( { - 'simpkv_test::verify_folders_exist::valid_foldername_info' => initial_foldername_info, + let(:hieradata_with_valid_folders) do + backend_hiera.merge({ + 'simpkv_test::verify_folders_exist::valid_foldername_info' => initial_foldername_info, 'simpkv_test::verify_folders_exist::invalid_foldername_info' => {} - } ) - } + }) + end # copy of inital_foldername_info for which all folder names have been modified let(:new_foldername_info) { rename_folders_in_name_info(initial_foldername_info) } - let(:hieradata_with_invalid_folders) { - backend_hiera.merge( { - 'simpkv_test::verify_folders_exist::valid_foldername_info' => {}, + let(:hieradata_with_invalid_folders) do + backend_hiera.merge({ + 'simpkv_test::verify_folders_exist::valid_foldername_info' => {}, 'simpkv_test::verify_folders_exist::invalid_foldername_info' => new_foldername_info - } ) - } + }) + end let(:manifest) { 'include simpkv_test::verify_folders_exist' } - it 'should call simpkv::exists for valid folders and return true' do + it 'calls simpkv::exists for valid folders and return true' do set_hiera_and_apply_on(host, hieradata_with_valid_folders, manifest, - { :catch_failures => true }) + { catch_failures: true }) end - it 'should call simpkv::exists for invalid folders and return false' do + it 'calls simpkv::exists for invalid folders and return false' do set_hiera_and_apply_on(host, hieradata_with_invalid_folders, manifest, - { :catch_failures => true }) + { catch_failures: true }) end end end diff --git a/spec/acceptance/shared_examples/simpkv_get.rb b/spec/acceptance/shared_examples/simpkv_get.rb index 42eebfb..902df78 100644 --- a/spec/acceptance/shared_examples/simpkv_get.rb +++ b/spec/acceptance/shared_examples/simpkv_get.rb @@ -20,33 +20,33 @@ include_examples('pre-populate keystores', host) context "simpkv::get operation on #{host}" do - let(:hieradata_with_valid_keys) { - backend_hiera.merge( { - 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => initial_key_info, + let(:hieradata_with_valid_keys) do + backend_hiera.merge({ + 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => initial_key_info, 'simpkv_test::retrieve_and_verify_keys::invalid_key_info' => {} - } ) - } + }) + end # copy of initial_key_info for which all key names have been modified let(:new_key_info) { rename_keys_in_key_info(initial_key_info) } - let(:hieradata_with_invalid_keys) { - backend_hiera.merge( { - 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => {}, + let(:hieradata_with_invalid_keys) do + backend_hiera.merge({ + 'simpkv_test::retrieve_and_verify_keys::valid_key_info' => {}, 'simpkv_test::retrieve_and_verify_keys::invalid_key_info' => new_key_info - } ) - } + }) + end let(:manifest) { 'include simpkv_test::retrieve_and_verify_keys' } - it 'should call simpkv::get for valid keys without errors and verify retrieved info' do + it 'calls simpkv::get for valid keys without errors and verify retrieved info' do set_hieradata_on(host, hieradata_with_valid_keys) - apply_manifest_on(host, manifest, :catch_failures => true) + apply_manifest_on(host, manifest, catch_failures: true) end - it 'should call simpkv::get with softfail=true for invalid keys without errors and verify nothing is retrieved' do + it 'calls simpkv::get with softfail=true for invalid keys without errors and verify nothing is retrieved' do set_hieradata_on(host, hieradata_with_invalid_keys) - apply_manifest_on(host, manifest, :catch_failures => true) + apply_manifest_on(host, manifest, catch_failures: true) end end end diff --git a/spec/acceptance/shared_examples/simpkv_list.rb b/spec/acceptance/shared_examples/simpkv_list.rb index 2e1318a..3bbb666 100644 --- a/spec/acceptance/shared_examples/simpkv_list.rb +++ b/spec/acceptance/shared_examples/simpkv_list.rb @@ -21,32 +21,32 @@ context "simpkv::list operation on #{host}" do let(:initial_folder_info) { to_folder_info(initial_key_info) } - let(:hieradata_with_valid_folders) { - backend_hiera.merge( { - 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => initial_folder_info, + let(:hieradata_with_valid_folders) do + backend_hiera.merge({ + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => initial_folder_info, 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => {} - } ) - } + }) + end # copy of initial_folder_info for which all folder names have been modified let(:new_folder_info) { rename_folders_in_folder_info(initial_folder_info) } - let(:hieradata_with_invalid_folders) { - backend_hiera.merge( { - 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => {}, + let(:hieradata_with_invalid_folders) do + backend_hiera.merge({ + 'simpkv_test::retrieve_and_verify_folders::valid_folder_info' => {}, 'simpkv_test::retrieve_and_verify_folders::invalid_folder_info' => new_folder_info - } ) - } + }) + end let(:manifest) { 'include simpkv_test::retrieve_and_verify_folders' } - it 'should call simpkv::list for valid folders without errors and verify retrieved info' do + it 'calls simpkv::list for valid folders without errors and verify retrieved info' do set_hiera_and_apply_on(host, hieradata_with_valid_folders, manifest, - { :catch_failures => true }) + { catch_failures: true }) end - it 'should call simpkv::list with softfail=true for invalid folders without errors and verify nothing is retrieved' do + it 'calls simpkv::list with softfail=true for invalid folders without errors and verify nothing is retrieved' do set_hiera_and_apply_on(host, hieradata_with_invalid_folders, manifest, - { :catch_failures => true }) + { catch_failures: true }) end end end diff --git a/spec/acceptance/shared_examples/simpkv_plugin.rb b/spec/acceptance/shared_examples/simpkv_plugin.rb index b0fb56a..9266e44 100644 --- a/spec/acceptance/shared_examples/simpkv_plugin.rb +++ b/spec/acceptance/shared_examples/simpkv_plugin.rb @@ -88,7 +88,6 @@ # independent verification commands executed # shared_examples 'a simpkv plugin test' do |host| - # This is a very high level, test configuration sanity check, but will not # detect all misconfiguration errors (especially ones that result in # non-unique keys, e.g., when multiple app_ids unexpectedly end up in the @@ -97,15 +96,15 @@ # Included examples may have more specific validation, especially WRT to # whether initial_key_info has appropriate data for derived data used to # stimulate the key/folder removal tests. - it 'should have basic test configuration' do - expect( backend_hiera.key?('simpkv::options')).to be true - expect( backend_hiera['simpkv::options'].key?('backends')).to be true - expect( backend_hiera['simpkv::options']['backends'].key?('default')).to be true + it 'has basic test configuration' do + expect(backend_hiera.key?('simpkv::options')).to be true + expect(backend_hiera['simpkv::options'].key?('backends')).to be true + expect(backend_hiera['simpkv::options']['backends'].key?('default')).to be true - expect(initial_key_info).to_not be_empty - initial_key_info.keys.each do |app_id| + expect(initial_key_info).not_to be_empty + initial_key_info.each_key do |app_id| appid = app_id.empty? ? 'default' : app_id - expect( backend_hiera['simpkv::options']['backends'].keys.include?(appid) ).to be true + expect(backend_hiera['simpkv::options']['backends'].keys.include?(appid)).to be true end end @@ -125,4 +124,3 @@ include_examples('simpkv::delete tests', host) include_examples('simpkv::deletetree tests', host) end - diff --git a/spec/acceptance/shared_examples/simpkv_put.rb b/spec/acceptance/shared_examples/simpkv_put.rb index 3086b0a..f82b853 100644 --- a/spec/acceptance/shared_examples/simpkv_put.rb +++ b/spec/acceptance/shared_examples/simpkv_put.rb @@ -38,49 +38,49 @@ # shared_examples 'simpkv::put tests' do |host| context "ensure empty keystore(s) on #{host}" do - it 'should remove all backend instance data' do - on(host, clear_data_cmd, :accept_all_exit_codes => true) + it 'removes all backend instance data' do + on(host, clear_data_cmd, accept_all_exit_codes: true) end end context "simpkv::put operation on #{host}" do - let(:hieradata) { - backend_hiera.merge( { - 'simpkv_test::store_keys::key_info' => initial_key_info - } ) - } + let(:hieradata) do + backend_hiera.merge({ + 'simpkv_test::store_keys::key_info' => initial_key_info + }) + end let(:updated_key_info) { modify_key_data(initial_key_info) } - let(:updated_hieradata) { - backend_hiera.merge( { - 'simpkv_test::store_keys::key_info' => updated_key_info - } ) - } + let(:updated_hieradata) do + backend_hiera.merge({ + 'simpkv_test::store_keys::key_info' => updated_key_info + }) + end let(:manifest) { 'include simpkv_test::store_keys' } - it 'should call simpkv::put without errors' do - set_hiera_and_apply_on(host, hieradata, manifest, { :catch_failures => true }) + it 'calls simpkv::put without errors' do + set_hiera_and_apply_on(host, hieradata, manifest, { catch_failures: true }) end - it 'should store the keys in the configured backends' do - expect( validator.call(initial_key_info, true, backend_hiera, host) ).to be true + it 'stores the keys in the configured backends' do + expect(validator.call(initial_key_info, true, backend_hiera, host)).to be true end - it 'should call simpkv::put without errors when keys already exist with same value' do - apply_manifest_on(host, manifest, :catch_failures => true) + it 'calls simpkv::put without errors when keys already exist with same value' do + apply_manifest_on(host, manifest, catch_failures: true) end - it 'should retain the keys in the configured backends' do - expect( validator.call(initial_key_info, true, backend_hiera, host) ).to be true + it 'retains the keys in the configured backends' do + expect(validator.call(initial_key_info, true, backend_hiera, host)).to be true end - it 'should call simpkv::put without errors when keys already exist with different values' do - set_hiera_and_apply_on(host, updated_hieradata, manifest, { :catch_failures => true }) + it 'calls simpkv::put without errors when keys already exist with different values' do + set_hiera_and_apply_on(host, updated_hieradata, manifest, { catch_failures: true }) end - it 'should update the keys in the configured backends' do - expect( validator.call(updated_key_info, true, backend_hiera, host) ).to be true + it 'updates the keys in the configured backends' do + expect(validator.call(updated_key_info, true, backend_hiera, host)).to be true end end end diff --git a/spec/acceptance/suites/default/00_file_plugin_setup_spec.rb b/spec/acceptance/suites/default/00_file_plugin_setup_spec.rb index d9debf7..3868c58 100644 --- a/spec/acceptance/suites/default/00_file_plugin_setup_spec.rb +++ b/spec/acceptance/suites/default/00_file_plugin_setup_spec.rb @@ -4,15 +4,16 @@ describe 'simpkv file plugin setup' do # Ensure /var/simp/simpkv already exists - let(:manifest) { <<~EOM + let(:manifest) do + <<~EOM file {'/var/simp': ensure => directory } file {'/var/simp/simpkv': ensure => directory } EOM - } + end hosts.each do |host| - it "should create /var/simp/simpkv on #{host}" do - apply_manifest_on(host, manifest, :catch_failures => true) + it "creates /var/simp/simpkv on #{host}" do + apply_manifest_on(host, manifest, catch_failures: true) end end end diff --git a/spec/acceptance/suites/default/10_configured_file_plugin_spec.rb b/spec/acceptance/suites/default/10_configured_file_plugin_spec.rb index 5b82118..1dca8b2 100644 --- a/spec/acceptance/suites/default/10_configured_file_plugin_spec.rb +++ b/spec/acceptance/suites/default/10_configured_file_plugin_spec.rb @@ -13,7 +13,6 @@ # a local filesystem command is appropriate. let(:clear_data_cmd) { 'rm -rf /var/simp/simpkv/file' } - # The ids below are the backend/app_id names used in the test: # - One must be 'default' or simpkv::options validation will fail. # - 'a simpkv plugin test' shared_examples assumes there is a one-to-one @@ -33,7 +32,7 @@ # simpkv::options hieradata for 3 distinct backends, one of which must # be 'default' - let(:backend_hiera) { + let(:backend_hiera) do backend_configs = { id1 => { 'type' => 'file', @@ -50,16 +49,16 @@ } generate_backend_hiera(backend_configs) - } + end # Hash of initial key information for the 3 test backends/app_ids. # # 'a simpkv plugin test' uses this data to test key storage operations # and then transform the data into subsets that it uses to test key/folder # existence, folder lists, and key and folder delete operations. - let(:initial_key_info) { + let(:initial_key_info) do generate_initial_key_info(id1, id2, id3) - } + end hosts.each do |host| context "configured simpkv file plugin on #{host}" do diff --git a/spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb b/spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb index e6f0692..45b501c 100644 --- a/spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb +++ b/spec/acceptance/suites/default/20_auto_default_file_plugin_spec.rb @@ -12,34 +12,34 @@ let(:clean_data_cmd) { 'rm -rf /var/simp/simpkv/file' } # No backend configuration in hieradata - let(:hieradata) {{ }} + let(:hieradata) { {} } # Store a few keys so we can spot check that the keys are being stored # in the auto-default backend - let(:manifest) { + let(:manifest) do <<~EOS simpkv::put('key1', 'environment key value1') simpkv::put('global1', 'global key value 1', {'version' => 10}, {'global' => true}) EOS - } + end hosts.each do |host| context "without simpkv configuration on #{host}" do - it 'should start with no backend data' do + it 'starts with no backend data' do on(host, clean_data_cmd) end - it 'should call simpkv::put with no errors' do + it 'calls simpkv::put with no errors' do set_hiera_and_apply_on(host, hieradata, manifest, - {:catch_failures => true} ) + { catch_failures: true }) end - it 'should store keys in auto-default backend' do + it 'stores keys in auto-default backend' do [ '/var/simp/simpkv/file/auto_default/environments/production/key1', - '/var/simp/simpkv/file/auto_default/globals/global1' + '/var/simp/simpkv/file/auto_default/globals/global1', ].each do |file| - expect( file_exists_on(host, file) ).to be true + expect(file_exists_on(host, file)).to be true end end end diff --git a/spec/acceptance/suites/default/validate_file_entries.rb b/spec/acceptance/suites/default/validate_file_entries.rb index 8814f58..f059751 100644 --- a/spec/acceptance/suites/default/validate_file_entries.rb +++ b/spec/acceptance/suites/default/validate_file_entries.rb @@ -38,12 +38,11 @@ def validate_file_entries(key_info, keys_should_exist, backend_hiera, host) config = backend_config_for_app_id(app_id, 'file', backend_hiera) key_struct.each do |key_type, keys| keys.each do |key, key_data| - result = {} - if keys_should_exist - result = validate_file_key_entry_present(key, key_type, key_data, config, host) - else - result = validate_file_key_entry_absent(key, key_type, config, host) - end + result = if keys_should_exist + validate_file_key_entry_present(key, key_type, key_data, config, host) + else + validate_file_key_entry_absent(key, key_type, config, host) + end unless result[:success] errors << result[:err_msg] @@ -52,7 +51,7 @@ def validate_file_entries(key_info, keys_should_exist, backend_hiera, host) end end - if errors.size == 0 + if errors.empty? true else warn('Validation Failures:') @@ -85,26 +84,26 @@ def validate_file_entries(key_info, keys_should_exist, backend_hiera, host) # * :err_msg - error message upon failure or nil otherwise # def validate_file_key_entry_present(key, key_type, key_data, config, host) - result = { :success => true } + result = { success: true } key_path = filesystem_key_path(key, key_type, config) - cmd_result = on(host, "cat #{key_path}", :accept_all_exit_codes => true) + cmd_result = on(host, "cat #{key_path}", accept_all_exit_codes: true) if cmd_result.exit_code == 0 expected_key_string = key_data_string(key_data) if cmd_result.stdout.strip != expected_key_string result = { - :success => false, - :err_msg => [ + success: false, + err_msg: [ "Data for #{key} did not match expected:", " Expected: #{expected_key_string}", - " Actual: #{result.stdout}" + " Actual: #{result.stdout}", ].join("\n") } end else result = { - :success => false, - :err_msg => "Validation of #{key} presence failed: Could not find #{key_path}" + success: false, + err_msg: "Validation of #{key} presence failed: Could not find #{key_path}" } end @@ -128,14 +127,14 @@ def validate_file_key_entry_present(key, key_type, key_data, config, host) # * :err_msg - error message upon failure or nil otherwise # def validate_file_key_entry_absent(key, key_type, config, host) - result = { :success => true } + result = { success: true } key_path = filesystem_key_path(key, key_type, config) - cmd_result = on(host, "ls -l #{key_path}", :accept_all_exit_codes => true) + on(host, "ls -l #{key_path}", accept_all_exit_codes: true) if result.exit_code == 0 result = { - :success => false, - :err_msg => "Validation of #{key} absence failed: Found #{key_path}" + success: false, + err_msg: "Validation of #{key} absence failed: Found #{key_path}" } end diff --git a/spec/acceptance/suites/ldap_plugin/00_ldap_server_spec.rb b/spec/acceptance/suites/ldap_plugin/00_ldap_server_spec.rb index 27d7a72..0903987 100644 --- a/spec/acceptance/suites/ldap_plugin/00_ldap_server_spec.rb +++ b/spec/acceptance/suites/ldap_plugin/00_ldap_server_spec.rb @@ -34,7 +34,7 @@ let(:hieradata) do { - 'ds389::instances' => { + 'ds389::instances' => { 'simp_data_without_tls' => { 'base_dn' => ldap_instances['simp_data_without_tls'][:base_dn], 'root_dn' => ldap_instances['simp_data_without_tls'][:root_dn], @@ -44,7 +44,7 @@ 'bootstrap_ldif_content' => bootstrap_ldif }, - 'simp_data_with_tls' => { + 'simp_data_with_tls' => { 'base_dn' => ldap_instances['simp_data_with_tls'][:base_dn], 'root_dn' => ldap_instances['simp_data_with_tls'][:root_dn], 'root_dn_password' => ldap_instances['simp_data_with_tls'][:root_pw], @@ -62,7 +62,7 @@ end it 'disables firewall for LDAP access via custom ports' do - # FIXME ds389 module does NOT manage firewall rules. So, for hosts that + # FIXME: ds389 module does NOT manage firewall rules. So, for hosts that # have firewalld running by default, we need to make sure it is stopped # or add our own rules. This should be a non-issue when SIMP provides # a 389-DS instance for simpkv in the simp_ds389 module. @@ -79,15 +79,15 @@ end it "applies a simpkv custom schema to all 389-DS instances on #{host}" do - ldap_instances.each do |instance,config| + ldap_instances.each do |instance, config| src = File.join(__dir__, 'files', '70simpkv.ldif') dest = "/etc/dirsrv/slapd-#{instance}/schema/70simpkv.ldif" scp_to(host, src, dest) on(host, "chown dirsrv:dirsrv #{dest}") - #FIXME use dsconf schema reload instead - on(host, %Q{schema-reload.pl -Z #{instance} -D "#{config[:root_dn]}" -w "#{config[:root_pw]}" -P LDAPI}) + # FIXME: use dsconf schema reload instead + on(host, %(schema-reload.pl -Z #{instance} -D "#{config[:root_dn]}" -w "#{config[:root_pw]}" -P LDAPI)) on(host, "egrep 'ERR\s*-\s*schemareload' /var/log/dirsrv/slapd-#{instance}/errors", - :acceptable_exit_codes => [1]) + acceptable_exit_codes: [1]) end end end diff --git a/spec/acceptance/suites/ldap_plugin/05_ldap_client_setup_spec.rb b/spec/acceptance/suites/ldap_plugin/05_ldap_client_setup_spec.rb index 6a69e0d..f12a9bc 100644 --- a/spec/acceptance/suites/ldap_plugin/05_ldap_client_setup_spec.rb +++ b/spec/acceptance/suites/ldap_plugin/05_ldap_client_setup_spec.rb @@ -7,10 +7,11 @@ describe 'simpkv client setup' do include_context('ldap test configuration') - # FIXME Can't compile manifests with simpkv functions unless the files containing + # FIXME: Can't compile manifests with simpkv functions unless the files containing # the admin passwords already exist on each host context 'Ensure LDAP password files for clients exists prior to using simpkv functions' do - let(:manifest) { <<-EOM + let(:manifest) do + <<-EOM file { '/etc/simp': ensure => 'directory' } file { '#{ldap_instances['simp_data_without_tls'][:admin_pw_file]}': @@ -29,17 +30,17 @@ content => Sensitive('#{ldap_instances['simp_data_with_tls'][:admin_pw]}') } EOM - } + end hosts.each do |host| - it "should create admin pw files needed by ldap plugin on #{host}" do - apply_manifest_on(host, manifest, :catch_failures => true) + it "creates admin pw files needed by ldap plugin on #{host}" do + apply_manifest_on(host, manifest, catch_failures: true) end end end context 'Ensure openldap-clients package is installed on clients prior to using simpkv functions' do - it 'should install openlap-clients package' do + it 'installs openlap-clients package' do install_package_unless_present_on(hosts, 'openldap-clients') end end diff --git a/spec/acceptance/suites/ldap_plugin/10_ldapi_spec.rb b/spec/acceptance/suites/ldap_plugin/10_ldapi_spec.rb index f6d064f..9141ec5 100644 --- a/spec/acceptance/suites/ldap_plugin/10_ldapi_spec.rb +++ b/spec/acceptance/suites/ldap_plugin/10_ldapi_spec.rb @@ -11,71 +11,73 @@ let(:ldap_instance_name) { 'simp_data_with_tls' } let(:ldap_instance) { ldap_instances[ldap_instance_name] } let(:ldap_uri) { "ldapi://%2fvar%2frun%2fslapd-#{ldap_instance_name}.socket" } - let(:common_ldap_config) {{ - 'type' => 'ldap', - 'ldap_uri' => ldap_uri, - 'base_dn' => ldap_instance[:simpkv_base_dn], - }} + let(:common_ldap_config) do + { + 'type' => 'ldap', + 'ldap_uri' => ldap_uri, + 'base_dn' => ldap_instance[:simpkv_base_dn], + } + end # Command to run on the test host to clear out all stored key data. # - All stored in same 389-DS instance, so single clear command - let(:clear_data_cmd) { + let(:clear_data_cmd) do [ build_ldap_command('ldapdelete', common_ldap_config), '-r', - %Q{"ou=instances,#{ldap_instance[:simpkv_base_dn]}"} + %("ou=instances,#{ldap_instance[:simpkv_base_dn]}"), ].join(' ') - } + end # simpkv::options hieradata for 3 distinct backends # - 2 use LDAPI with EXTERNAL SASL authentication # - 1 uses LDAPI with simple authentication - let(:backend_hiera) { + let(:backend_hiera) do backend_configs = { id1 => common_ldap_config, id2 => common_ldap_config, id3 => common_ldap_config.merge({ - 'admin_dn' => ldap_instance[:admin_dn], + 'admin_dn' => ldap_instance[:admin_dn], 'admin_pw_file' => ldap_instance[:admin_pw_file] - }) + }) } # will set each 'id' to its corresponding backend name, which # results in a unique tree for that backend name beneath the # simpkv tree in the 389-DS instance generate_backend_hiera(backend_configs) - } + end hosts_with_role(hosts, 'ldap_server').each do |host| context "simpkv ldap plugin on #{host} using ldapi" do it_behaves_like 'a simpkv plugin test', host context 'LDAP-specific features' do - let(:manifest) { %Q{simpkv::put('mykey', "Value for mykey", {})} } - let(:get_ldap_attributes_cmd) { + let(:manifest) { %{simpkv::put('mykey', "Value for mykey", {})} } + let(:get_ldap_attributes_cmd) do dn = "simpkvKey=mykey,ou=production,ou=environments,ou=default,ou=instances,#{ldap_instance[:simpkv_base_dn]}" [ build_ldap_command('ldapsearch', common_ldap_config), '-o "ldif-wrap=no"', '-LLL', - %Q{-b "#{dn}"}, - '+' + %(-b "#{dn}"), + '+', ].join(' ') - } + end - it 'should not change LDAP modifyTimestamp when no changes are made' do + it 'does not change LDAP modifyTimestamp when no changes are made' do # store a key and retrieve its LDAP modifyTimestamp set_hiera_and_apply_on(host, backend_hiera, manifest) result1 = on(host, get_ldap_attributes_cmd) - timestamp1 = result1.stdout.split("\n").delete_if{ |line| !line.start_with?('modifyTimestamp:') }.first + timestamp1 = result1.stdout.split("\n").delete_if { |line| !line.start_with?('modifyTimestamp:') }.first # store a key with the same content and retrieve its LDAP modifyTimestamp set_hiera_and_apply_on(host, backend_hiera, manifest) result2 = on(host, get_ldap_attributes_cmd) - timestamp2 = result2.stdout.split("\n").delete_if{ |line| !line.start_with?('modifyTimestamp:') }.first + timestamp2 = result2.stdout.split("\n").delete_if { |line| !line.start_with?('modifyTimestamp:') }.first # key was not modified, so timestamp should be the same - expect( timestamp2 ).to eq(timestamp1) + expect(timestamp2).to eq(timestamp1) end end end diff --git a/spec/acceptance/suites/ldap_plugin/20_ldap_protos_spec.rb b/spec/acceptance/suites/ldap_plugin/20_ldap_protos_spec.rb index d9f7fe8..2dcb731 100644 --- a/spec/acceptance/suites/ldap_plugin/20_ldap_protos_spec.rb +++ b/spec/acceptance/suites/ldap_plugin/20_ldap_protos_spec.rb @@ -29,53 +29,59 @@ let(:tls_cert) { "#{certdir}/public/#{client_fqdn}.pub" } let(:tls_key) { "#{certdir}/private/#{client_fqdn}.pem" } let(:tls_cacert) { "#{certdir}/cacerts/cacerts.pem" } - let(:ldaps_config) {{ - 'type' => 'ldap', - 'ldap_uri' => ldaps_uri, - 'base_dn' => ldap_with_tls[:simpkv_base_dn], - 'admin_dn' => ldap_with_tls[:admin_dn], - 'admin_pw_file' => ldap_with_tls[:admin_pw_file], - 'tls_cert' => tls_cert, - 'tls_key' => tls_key, - 'tls_cacert' => tls_cacert, - }} + let(:ldaps_config) do + { + 'type' => 'ldap', + 'ldap_uri' => ldaps_uri, + 'base_dn' => ldap_with_tls[:simpkv_base_dn], + 'admin_dn' => ldap_with_tls[:admin_dn], + 'admin_pw_file' => ldap_with_tls[:admin_pw_file], + 'tls_cert' => tls_cert, + 'tls_key' => tls_key, + 'tls_cacert' => tls_cacert, + } + end - let(:ldap_starttls_config) {{ - 'type' => 'ldap', - 'ldap_uri' => ldap_starttls_uri, - 'base_dn' => ldap_with_tls[:simpkv_base_dn], - 'admin_dn' => ldap_with_tls[:admin_dn], - 'admin_pw_file' => ldap_with_tls[:admin_pw_file], - 'enable_tls' => true, - 'tls_cert' => tls_cert, - 'tls_key' => tls_key, - 'tls_cacert' => tls_cacert, - }} + let(:ldap_starttls_config) do + { + 'type' => 'ldap', + 'ldap_uri' => ldap_starttls_uri, + 'base_dn' => ldap_with_tls[:simpkv_base_dn], + 'admin_dn' => ldap_with_tls[:admin_dn], + 'admin_pw_file' => ldap_with_tls[:admin_pw_file], + 'enable_tls' => true, + 'tls_cert' => tls_cert, + 'tls_key' => tls_key, + 'tls_cacert' => tls_cacert, + } + end - let(:ldap_config) {{ - 'type' => 'ldap', - 'ldap_uri' => ldap_uri, - 'base_dn' => ldap_without_tls[:simpkv_base_dn], - 'admin_dn' => ldap_without_tls[:admin_dn], - 'admin_pw_file' => ldap_without_tls[:admin_pw_file] - }} + let(:ldap_config) do + { + 'type' => 'ldap', + 'ldap_uri' => ldap_uri, + 'base_dn' => ldap_without_tls[:simpkv_base_dn], + 'admin_dn' => ldap_without_tls[:admin_dn], + 'admin_pw_file' => ldap_without_tls[:admin_pw_file] + } + end # Command to run on the test host to clear out all stored key data. - let(:clear_data_cmd) { + let(:clear_data_cmd) do [ build_ldap_command('ldapdelete', ldaps_config), '-r', - %Q{"ou=instances,#{ldap_with_tls[:simpkv_base_dn]}"}, + %("ou=instances,#{ldap_with_tls[:simpkv_base_dn]}"), ' ; ', build_ldap_command('ldapdelete', ldap_config), '-r', - %Q{"ou=instances,#{ldap_without_tls[:simpkv_base_dn]}"}, + %("ou=instances,#{ldap_without_tls[:simpkv_base_dn]}"), ].join(' ') - } + end # simpkv::options hieradata for 3 distinct backends - let(:backend_hiera) { + let(:backend_hiera) do backend_configs = { id1 => ldaps_config, id2 => ldap_starttls_config, @@ -86,7 +92,7 @@ # results in unique trees for that backend name beneath the # simpkv tree in the 389-DS instances generate_backend_hiera(backend_configs) - } + end context "simpkv ldap_plugin on #{client} using ldap with & without TLS to #{server}" do it_behaves_like 'a simpkv plugin test', client diff --git a/spec/acceptance/suites/ldap_plugin/30_errors_spec.rb b/spec/acceptance/suites/ldap_plugin/30_errors_spec.rb index cedaede..0ce8470 100644 --- a/spec/acceptance/suites/ldap_plugin/30_errors_spec.rb +++ b/spec/acceptance/suites/ldap_plugin/30_errors_spec.rb @@ -19,7 +19,7 @@ let(:ldap_without_tls) { ldap_instances['simp_data_without_tls'] } # key will go to the default backend - let(:manifest) { %Q{simpkv::put('mykey', "Value for mykey", {})} } + let(:manifest) { %{simpkv::put('mykey', "Value for mykey", {})} } let(:new_pki_certs_dir) { '/etc/pki/simp-testing-new' } context 'TLS error test prep' do @@ -44,25 +44,25 @@ let(:server_fqdn) { fact_on(server, 'fqdn').strip } let(:valid_ldaps_uri) { "ldaps://#{server_fqdn}:#{ldap_with_tls[:secure_port]}" } let(:valid_ldap_uri) { "ldap://#{server_fqdn}:#{ldap_without_tls[:port]}" } - let(:failed_regex) { + let(:failed_regex) do # The full failure message tells the user the ldapsearch command that failed # and its error messages, so that the user doesn't have to apply the manifest # with --debug to figure out what is going on! %r{Unable to construct 'ldap/default': Plugin could not access ou=simpkv,o=puppet,dc=simp.*ldapsearch} - } + end hosts_with_role(hosts, 'client').each do |client| context "with LDAP client #{client}" do - # valid backend config for ldap - let(:valid_ldap_config) {{ - 'type' => 'ldap', - 'ldap_uri' => valid_ldap_uri, - 'base_dn' => ldap_without_tls[:simpkv_base_dn], - 'admin_dn' => ldap_without_tls[:admin_dn], - 'admin_pw_file' => ldap_without_tls[:admin_pw_file] - }} - + let(:valid_ldap_config) do + { + 'type' => 'ldap', + 'ldap_uri' => valid_ldap_uri, + 'base_dn' => ldap_without_tls[:simpkv_base_dn], + 'admin_dn' => ldap_without_tls[:admin_dn], + 'admin_pw_file' => ldap_without_tls[:admin_pw_file] + } + end context 'with LDAP configuration errors' do it 'fails to compile when LDAP URI has invalid host' do @@ -72,9 +72,9 @@ backend_hiera = generate_backend_hiera(backend_configs) result = set_hiera_and_apply_on(client, backend_hiera, manifest, - { :expect_failures => true } ) + { expect_failures: true }) - expect( result.stderr ).to match(failed_regex) + expect(result.stderr).to match(failed_regex) end it 'fails to compile when LDAP URI has invalid port' do @@ -85,10 +85,10 @@ backend_configs = { 'default' => invalid_config } backend_hiera = generate_backend_hiera(backend_configs) - result =set_hiera_and_apply_on(client, backend_hiera, manifest, - { :expect_failures => true } ) + result = set_hiera_and_apply_on(client, backend_hiera, manifest, + { expect_failures: true }) - expect( result.stderr ).to match(failed_regex) + expect(result.stderr).to match(failed_regex) end it 'fails to compile when base DN is invalid' do @@ -98,21 +98,21 @@ backend_hiera = generate_backend_hiera(backend_configs) result = set_hiera_and_apply_on(client, backend_hiera, manifest, - { :expect_failures => true } ) + { expect_failures: true }) - expect( result.stderr ).to match(failed_regex) + expect(result.stderr).to match(failed_regex) end it 'fails to compile when admin DN is invalid' do - bad_admin_dn = valid_ldap_config['admin_dn'] + ',dc=oops' + bad_admin_dn = valid_ldap_config['admin_dn'] + ',dc=oops' invalid_config = valid_ldap_config.merge({ 'admin_dn' => bad_admin_dn }) backend_configs = { 'default' => invalid_config } backend_hiera = generate_backend_hiera(backend_configs) result = set_hiera_and_apply_on(client, backend_hiera, manifest, - { :expect_failures => true } ) + { expect_failures: true }) - expect( result.stderr ).to match(failed_regex) + expect(result.stderr).to match(failed_regex) end it 'fails to compile when admin password is invalid' do @@ -126,9 +126,9 @@ backend_hiera = generate_backend_hiera(backend_configs) result = set_hiera_and_apply_on(client, backend_hiera, manifest, - { :expect_failures => true } ) + { expect_failures: true }) - expect( result.stderr ).to match(failed_regex) + expect(result.stderr).to match(failed_regex) end it 'fails to compile when TLS certs are invalid' do @@ -153,9 +153,9 @@ backend_hiera = generate_backend_hiera(backend_configs) result = set_hiera_and_apply_on(client, backend_hiera, manifest, - { :expect_failures => true } ) + { expect_failures: true }) - expect( result.stderr ).to match(failed_regex) + expect(result.stderr).to match(failed_regex) end end end diff --git a/spec/acceptance/suites/ldap_plugin/ldap_test_configuration.rb b/spec/acceptance/suites/ldap_plugin/ldap_test_configuration.rb index 495bec0..464bafd 100644 --- a/spec/acceptance/suites/ldap_plugin/ldap_test_configuration.rb +++ b/spec/acceptance/suites/ldap_plugin/ldap_test_configuration.rb @@ -14,7 +14,7 @@ shared_context 'ldap test configuration' do include Acceptance::Helpers::LdapUtils - # TODO Create a separate administrator bind DN and configure it appropriately + # TODO: Create a separate administrator bind DN and configure it appropriately # for LDAPI via an ACI # - This test configures the ldap_plugin to use the appropriate instance root # dn and password as its admin user, instead of a specific simpkv admin @@ -23,46 +23,46 @@ # mapping for the 'root' user. # let(:base_dn) { 'dc=simp' } - let(:root_dn) { 'cn=Directory_Manager' } - let(:simpkv_base_dn) { "ou=simpkv,o=puppet,#{base_dn}"} + let(:root_dn) { 'cn=Directory_Manager' } + let(:simpkv_base_dn) { "ou=simpkv,o=puppet,#{base_dn}" } let(:admin_dn) { root_dn } - let(:ldap_instances) { { - 'simp_data_without_tls' => { + let(:ldap_instances) do + { + 'simp_data_without_tls' => { + # ds389::instance config + base_dn: base_dn, + root_dn: root_dn, + root_pw: 'P@ssw0rdP@ssw0rd!N0TLS', + port: 387, + + # simpkv ldap_plugin config + simpkv_base_dn: simpkv_base_dn, + admin_dn: admin_dn, + admin_pw: 'P@ssw0rdP@ssw0rd!N0TLS', + admin_pw_file: '/etc/simp/simp_data_without_tls_pw.txt', + }, + + 'simp_data_with_tls' => { # ds389::instance config - :base_dn => base_dn, - :root_dn => root_dn, - :root_pw => 'P@ssw0rdP@ssw0rd!N0TLS', - :port => 387, + base_dn: base_dn, + root_dn: root_dn, + root_pw: 'P@ssw0rdP@ssw0rd!TLS', + port: 388, # for StartTLS + secure_port: 637, # simpkv ldap_plugin config - :simpkv_base_dn => simpkv_base_dn, - :admin_dn => admin_dn, - :admin_pw => 'P@ssw0rdP@ssw0rd!N0TLS', - :admin_pw_file => '/etc/simp/simp_data_without_tls_pw.txt', - }, - - 'simp_data_with_tls' => { - # ds389::instance config - :base_dn => base_dn, - :root_dn => root_dn, - :root_pw => 'P@ssw0rdP@ssw0rd!TLS', - :port => 388, # for StartTLS - :secure_port => 637, - - # simpkv ldap_plugin config - :simpkv_base_dn => simpkv_base_dn, - :admin_dn => admin_dn, - :admin_pw => 'P@ssw0rdP@ssw0rd!TLS', - :admin_pw_file => '/etc/simp/simp_data_with_tls_pw.txt', + simpkv_base_dn: simpkv_base_dn, + admin_dn: admin_dn, + admin_pw: 'P@ssw0rdP@ssw0rd!TLS', + admin_pw_file: '/etc/simp/simp_data_with_tls_pw.txt', } - - } } + } + end # PKI general let(:certdir) { '/etc/pki/simp-testing/pki' } - # Context for 'a simpkv plug test' shared_examples # Method object to validate key/folder entries in an LDAP instance @@ -86,15 +86,12 @@ let(:id2) { 'custom' } let(:id3) { 'custom_snowflake' } - - # Hash of initial key information for the 3 test backends/app_ids. + # Hash of initial key information for the 3 test backends/app_ids. # # 'a simpkv plugin test' uses this data to test key storage operations # and then transform the data into subsets that it uses to test key/folder # existence, folder lists, and key and folder delete operations. - let(:initial_key_info) { + let(:initial_key_info) do generate_initial_key_info(id1, id2, id3) - } - + end end - diff --git a/spec/acceptance/suites/ldap_plugin/validate_ldap_entries.rb b/spec/acceptance/suites/ldap_plugin/validate_ldap_entries.rb index 7722853..e2177cf 100644 --- a/spec/acceptance/suites/ldap_plugin/validate_ldap_entries.rb +++ b/spec/acceptance/suites/ldap_plugin/validate_ldap_entries.rb @@ -32,7 +32,7 @@ # cannot be found in backend_hiera # def validate_ldap_entries(key_info, keys_should_exist, backend_hiera, host) - #TODO: Make the iteration through keys and backend config selection part + # TODO: Make the iteration through keys and backend config selection part # of the test infrastructure instead of having this code replicated # in each plugin-provided validator # @@ -41,12 +41,11 @@ def validate_ldap_entries(key_info, keys_should_exist, backend_hiera, host) config = backend_config_for_app_id(app_id, 'ldap', backend_hiera) key_struct.each do |key_type, keys| keys.each do |key, key_data| - result = {} - if keys_should_exist - result = validate_ldap_key_entry_present(key, key_type, key_data, config, host) - else - result = validate_ldap_key_entry_absent(key, key_type, config, host) - end + result = if keys_should_exist + validate_ldap_key_entry_present(key, key_type, key_data, config, host) + else + validate_ldap_key_entry_absent(key, key_type, config, host) + end unless result[:success] errors << result[:err_msg] @@ -55,7 +54,7 @@ def validate_ldap_entries(key_info, keys_should_exist, backend_hiera, host) end end - if errors.size == 0 + if errors.empty? true else warn('Validation Failures:') @@ -87,26 +86,26 @@ def validate_ldap_entries(key_info, keys_should_exist, backend_hiera, host) # * :err_msg - error message upon failure or nil otherwise # def validate_ldap_key_entry_present(key, key_type, key_data, config, host) - result = { :success => true } + result = { success: true } full_path = ldap_key_path(key, key_type, config) dn = build_key_dn(full_path, config['base_dn']) cmd = build_ldapsearch_cmd(dn, config, false) - cmd_result = on(host, cmd, :accept_all_exit_codes => true) + cmd_result = on(host, cmd, accept_all_exit_codes: true) if cmd_result.stdout.match(%r{^dn: .*#{dn}}).nil? result = { - :success => false, - :err_msg => "Validation of #{key} presence failed: Could not find #{dn}" + success: false, + err_msg: "Validation of #{key} presence failed: Could not find #{dn}" } else expected_key_string = key_data_string(key_data) - if cmd_result.stdout.match(/simpkvJsonValue: #{Regexp.escape(expected_key_string)}/).nil? + if cmd_result.stdout.match(%r{simpkvJsonValue: #{Regexp.escape(expected_key_string)}}).nil? result = { - :success => false, - :err_msg => [ + success: false, + err_msg: [ "Data for #{key} did not match expected:", " Expected: simpkvJsonValue: #{expected_key_string}", - " Actual: #{result.stdout}" + " Actual: #{result.stdout}", ].join("\n") } end @@ -131,16 +130,16 @@ def validate_ldap_key_entry_present(key, key_type, key_data, config, host) # * :err_msg - error message upon failure or nil otherwise # def validate_ldap_key_entry_absent(key, key_type, config, host) - result = { :success => true } + result = { success: true } full_path = ldap_key_path(key, key_type, config) dn = build_key_dn(full_path, config['base_dn']) cmd = build_ldapsearch_cmd(dn, config, true) - cmd_result = on(host, cmd, :accept_all_exit_codes => true) + cmd_result = on(host, cmd, accept_all_exit_codes: true) unless cmd_result.exit_code == 32 # No such object result = { - :success => false, - :err_msg => "Validation of #{key} absence failed: Found #{dn}:\n#{result.stdout}" + success: false, + err_msg: "Validation of #{key} absence failed: Found #{dn}:\n#{result.stdout}" } end @@ -170,12 +169,12 @@ def build_ldapsearch_cmd(dn, config, existence_only) '-s base', "-b #{dn}", - # TODO switch to ldif_wrap when we drop support for EL7 + # TODO: switch to ldif_wrap when we drop support for EL7 # - EL7 only supports ldif-wrap # - EL8 says it supports ldif_wrap (--help and man page), but actually # accepts ldif-wrap or ldif_wrap '-o "ldif-wrap=no"', '-LLL', - existence_only ? '1.1' : '' + existence_only ? '1.1' : '', ].join(' ') end diff --git a/spec/acceptance/suites/multiple_plugins/10_multiple_plugins_spec.rb b/spec/acceptance/suites/multiple_plugins/10_multiple_plugins_spec.rb index e75e247..cec974e 100644 --- a/spec/acceptance/suites/multiple_plugins/10_multiple_plugins_spec.rb +++ b/spec/acceptance/suites/multiple_plugins/10_multiple_plugins_spec.rb @@ -20,61 +20,67 @@ # with one that handles both file and LDAP backends include_context('ldap test configuration') - let(:file_backend_config) {{ - 'type' => 'file', - 'root_path' => "/var/simp/simpkv/file/#{id1}" - }} + let(:file_backend_config) do + { + 'type' => 'file', + 'root_path' => "/var/simp/simpkv/file/#{id1}" + } + end let(:file_clear_data_cmd) { 'rm -rf /var/simp/simpkv/file' } let(:ldap1_name) { 'simp_data_with_tls' } let(:ldap1) { ldap_instances[ldap1_name] } let(:ldap1_uri) { "ldapi://%2fvar%2frun%2fslapd-#{ldap1_name}.socket" } - let(:ldap1_backend_config) {{ - 'type' => 'ldap', - 'ldap_uri' => ldap1_uri, - 'base_dn' => ldap1[:simpkv_base_dn], - 'admin_dn' => ldap1[:admin_dn], - 'admin_pw_file' => ldap1[:admin_pw_file] - }} + let(:ldap1_backend_config) do + { + 'type' => 'ldap', + 'ldap_uri' => ldap1_uri, + 'base_dn' => ldap1[:simpkv_base_dn], + 'admin_dn' => ldap1[:admin_dn], + 'admin_pw_file' => ldap1[:admin_pw_file] + } + end - let(:ldap1_clear_data_cmd) { + let(:ldap1_clear_data_cmd) do [ build_ldap_command('ldapdelete', ldap1_backend_config), '-r', - %Q{"ou=instances,#{ldap1[:simpkv_base_dn]}"} + %("ou=instances,#{ldap1[:simpkv_base_dn]}"), ].join(' ') - } + end let(:ldap2_name) { 'simp_data_without_tls' } let(:ldap2) { ldap_instances[ldap2_name] } let(:ldap2_uri) { "ldapi://%2fvar%2frun%2fslapd-#{ldap2_name}.socket" } - let(:ldap2_backend_config) {{ - 'type' => 'ldap', - 'ldap_uri' => ldap2_uri, - 'base_dn' => ldap2[:simpkv_base_dn], - 'admin_dn' => ldap2[:admin_dn], - 'admin_pw_file' => ldap2[:admin_pw_file] - }} + let(:ldap2_backend_config) do + { + 'type' => 'ldap', + 'ldap_uri' => ldap2_uri, + 'base_dn' => ldap2[:simpkv_base_dn], + 'admin_dn' => ldap2[:admin_dn], + 'admin_pw_file' => ldap2[:admin_pw_file] + } + end - let(:ldap2_clear_data_cmd) { + let(:ldap2_clear_data_cmd) do [ build_ldap_command('ldapdelete', ldap2_backend_config), '-r', - %Q{"ou=instances,#{ldap2[:simpkv_base_dn]}"} + %("ou=instances,#{ldap2[:simpkv_base_dn]}"), ].join(' ') - } + end # Command to run on the test host to clear out all stored key data. - let(:clear_data_cmd) { + let(:clear_data_cmd) do [ file_clear_data_cmd, ldap1_clear_data_cmd, - ldap2_clear_data_cmd + ldap2_clear_data_cmd, ].join(' ; ') - } + end - let(:backend_hiera) { + let(:backend_hiera) do backend_configs = { id1 => file_backend_config, id2 => ldap1_backend_config, @@ -82,7 +88,7 @@ } generate_backend_hiera(backend_configs) - } + end hosts.each do |host| context "with LDAP and file keystores on #{host}" do diff --git a/spec/acceptance/suites/multiple_plugins/validate_multiple_plugins_entries.rb b/spec/acceptance/suites/multiple_plugins/validate_multiple_plugins_entries.rb index 1ca40d0..16e5ace 100644 --- a/spec/acceptance/suites/multiple_plugins/validate_multiple_plugins_entries.rb +++ b/spec/acceptance/suites/multiple_plugins/validate_multiple_plugins_entries.rb @@ -34,24 +34,22 @@ # # @return Whether validation of keys succeeded # -def validate_multiple_plugin_entries(key_info, keys_should_exist, backend_hiera, host) +def validate_multiple_plugin_entries(key_info, keys_should_exist, backend_hiera, _host) errors = [] key_info.each do |app_id, key_struct| config = backend_config_for_app_id(app_id, nil, backend_hiera) unless (config['type'] == 'file') || (config['type'] == 'ldap') - fail("Unsupported backend type '#{config['type']}' found in backend hiera:\n#{backend_hiera}") + raise("Unsupported backend type '#{config['type']}' found in backend hiera:\n#{backend_hiera}") end - key_struct.each do |key_type, keys| - keys.each do |key, key_data| - result = {} - if keys_should_exist - exp = "validate_#{config['type']}_key_entry_present(key, key_type, key_data, config, host)" - result = eval(exp) - else - exp = "validate_#{config['type']}_key_entry_absent(key, key_type, config, host)" - result = eval(exp) - end + key_struct.each_value do |keys| + keys.each do |_key, _key_data| + exp = if keys_should_exist + "validate_#{config['type']}_key_entry_present(key, key_type, key_data, config, host)" + else + "validate_#{config['type']}_key_entry_absent(key, key_type, config, host)" + end + result = eval(exp) unless result[:success] errors << result[:err_msg] @@ -60,7 +58,7 @@ def validate_multiple_plugin_entries(key_info, keys_should_exist, backend_hiera, end end - if errors.size == 0 + if errors.empty? true else warn('Validation Failures:') diff --git a/spec/data_helper.rb b/spec/data_helper.rb index 7f4e010..bfdef00 100644 --- a/spec/data_helper.rb +++ b/spec/data_helper.rb @@ -21,102 +21,94 @@ def data_dir # serialization/deserialization that requires # significant rework. May be addressed later. def data_info - binary_file1_content = IO.read(File.join(data_dir, 'test_krb5.keytab') - ).force_encoding('ASCII-8BIT') + binary_file1_content = IO.read(File.join(data_dir, 'test_krb5.keytab')).force_encoding('ASCII-8BIT') - binary_file2_content = IO.read(File.join(data_dir, 'random') - ).force_encoding('ASCII-8BIT') + binary_file2_content = IO.read(File.join(data_dir, 'random')).force_encoding('ASCII-8BIT') - data_info = { + { 'Boolean' => { - :value => true, - :metadata => { 'foo'=>'bar', 'baz'=>42 }, - :serialized_value => '{"value":true,"metadata":{"foo":"bar","baz":42}}' + value: true, + metadata: { 'foo' => 'bar', 'baz' => 42 }, + serialized_value: '{"value":true,"metadata":{"foo":"bar","baz":42}}' }, 'valid UTF-8 String' => { - :value => 'some string', - :metadata => {}, - :serialized_value => '{"value":"some string","metadata":{}}' + value: 'some string', + metadata: {}, + serialized_value: '{"value":"some string","metadata":{}}' }, 'malformed UTF-8 String' => { - :value => binary_file1_content.dup.force_encoding('UTF-8'), - :metadata => { 'foo'=>'bar', 'baz'=>42 }, - :serialized_value => - '{"value":"' + Base64.strict_encode64(binary_file1_content) + '",' + - '"encoding":"base64",' + - '"original_encoding":"ASCII-8BIT",' + + value: binary_file1_content.dup.force_encoding('UTF-8'), + metadata: { 'foo' => 'bar', 'baz' => 42 }, + serialized_value: '{"value":"' + Base64.strict_encode64(binary_file1_content) + '",' \ + '"encoding":"base64",' \ + '"original_encoding":"ASCII-8BIT",' \ '"metadata":{"foo":"bar","baz":42}}', # only difference is encoding: deserialized value will have the # correct encoding of ASCII-8BIT, as the simpkv adapter 'fixes' # the encoding...this behavior is subject to change - :deserialized_value => binary_file1_content + deserialized_value: binary_file1_content }, 'ASCII-8BIT String' => { - :value => binary_file2_content, - :metadata => { 'foo'=>'bar', 'baz'=>42 }, - :serialized_value => - '{"value":"' + Base64.strict_encode64(binary_file2_content) + '",' + - '"encoding":"base64",' + - '"original_encoding":"ASCII-8BIT",' + + value: binary_file2_content, + metadata: { 'foo' => 'bar', 'baz' => 42 }, + serialized_value: '{"value":"' + Base64.strict_encode64(binary_file2_content) + '",' \ + '"encoding":"base64",' \ + '"original_encoding":"ASCII-8BIT",' \ '"metadata":{"foo":"bar","baz":42}}' }, 'Integer' => { - :value => 255, - :metadata => {}, - :serialized_value => '{"value":255,"metadata":{}}' + value: 255, + metadata: {}, + serialized_value: '{"value":255,"metadata":{}}' }, 'Float' => { - :value => 2.3849, - :metadata => { 'foo' => { 'bar' => 'baz' }}, - :serialized_value => '{"value":2.3849,"metadata":{"foo":{"bar":"baz"}}}' + value: 2.3849, + metadata: { 'foo' => { 'bar' => 'baz' } }, + serialized_value: '{"value":2.3849,"metadata":{"foo":{"bar":"baz"}}}' }, 'Array of valid UTF-8 strings' => { - :value => [ 'valid UTF-8 1', 'valid UTF-8 2'], - :metadata => { 'foo'=>'bar', 'baz'=>42 }, - :serialized_value => - '{"value":["valid UTF-8 1","valid UTF-8 2"],' + + value: [ 'valid UTF-8 1', 'valid UTF-8 2'], + metadata: { 'foo' => 'bar', 'baz' => 42 }, + serialized_value: '{"value":["valid UTF-8 1","valid UTF-8 2"],' \ '"metadata":{"foo":"bar","baz":42}}' }, 'Array of binary strings' => { - :skip => 'Not yet supported', - :metadata => {}, - :value => [ - binary_file1_content.dup.force_encoding('UTF-8'), - binary_file2_content + skip: 'Not yet supported', + metadata: {}, + value: [ + binary_file1_content.dup.force_encoding('UTF-8'), + binary_file2_content, ], - :serialized_value => 'TBD' + serialized_value: 'TBD' }, 'Hash with valid UTF-8 strings' => { - :value => { + value: { 'key1' => 'test_string', 'key2' => 1000, 'key3' => false, 'key4' => { 'nestedkey1' => 'nested_test_string' } }, - :metadata => { 'foo'=>'bar', 'baz'=>42 }, - :serialized_value => - '{"value":' + - '{' + - '"key1":"test_string",' + - '"key2":1000,' + - '"key3":false,' + - '"key4":{"nestedkey1":"nested_test_string"}' + - '},' + + metadata: { 'foo' => 'bar', 'baz' => 42 }, + serialized_value: '{"value":' \ + '{' \ + '"key1":"test_string",' \ + '"key2":1000,' \ + '"key3":false,' \ + '"key4":{"nestedkey1":"nested_test_string"}' \ + '},' \ '"metadata":{"foo":"bar","baz":42}}' }, 'Hash with binary strings' => { - :skip => 'Not yet supported', - :value => { + skip: 'Not yet supported', + value: { 'key1' => binary_file1_content.dup.force_encoding('UTF-8'), 'key2' => 1000, 'key3' => false, 'key4' => { 'nestedkey1' => binary_file2_content } }, - :metadata => {}, - :serialized_value => 'TBD' + metadata: {}, + serialized_value: 'TBD' } } - end end - diff --git a/spec/functions/simpkv/delete_spec.rb b/spec/functions/simpkv/delete_spec.rb index af9c3a8..64036c7 100644 --- a/spec/functions/simpkv/delete_spec.rb +++ b/spec/functions/simpkv/delete_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe 'simpkv::delete' do - # tell puppet-rspec to set Puppet environment to 'myenv' let(:environment) { 'myenv' } @@ -14,35 +13,35 @@ @root_path_default_app_id = File.join(@tmpdir, 'simpkv', 'default_app_id') @root_path_default = File.join(@tmpdir, 'simpkv', 'default') options_base = { - 'backends' => { + 'backends' => { # will use failer plugin for catastrophic error cases, because # it is badly behaved and raises exceptions on all operations - 'test_failer' => { - 'id' => 'test', - 'type' => 'failer', - 'fail_constructor' => false # true = raise in constructor + 'test_failer' => { + 'id' => 'test', + 'type' => 'failer', + 'fail_constructor' => false # true = raise in constructor }, # will use file plugin for non-catastrophic test cases - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path_test_file }, - 'myapp' => { + 'myapp' => { 'id' => 'default_app_id', 'type' => 'file', 'root_path' => @root_path_default_app_id }, - 'default' => { + 'default' => { 'id' => 'default', 'type' => 'file', 'root_path' => @root_path_default } } } - @options_failer = options_base.merge ({ 'backend' => 'test_failer' } ) - @options_test_file = options_base.merge ({ 'backend' => 'test_file' } ) - @options_default_app_id = options_base.merge ({ 'app_id' => 'myapp10' } ) + @options_failer = options_base.merge({ 'backend' => 'test_failer' }) + @options_test_file = options_base.merge({ 'backend' => 'test_file' }) + @options_default_app_id = options_base.merge({ 'app_id' => 'myapp10' }) @options_default = options_base end @@ -56,58 +55,58 @@ let(:default_keydir) { File.join(@root_path_default, 'environments', environment) } let(:key) { 'mykey' } - it 'should delete an existing key in a specific backend in options' do + it 'deletes an existing key in a specific backend in options' do FileUtils.mkdir_p(test_file_keydir) key_file = File.join(test_file_keydir, key) FileUtils.touch(key_file) is_expected.to run.with_params(key, @options_test_file).and_return(true) - expect( File.exist?(key_file) ).to be false + expect(File.exist?(key_file)).to be false end - it 'should delete an existing key in the default backend in options when app_id unspecified' do + it 'deletes an existing key in the default backend in options when app_id unspecified' do FileUtils.mkdir_p(default_keydir) key_file = File.join(default_keydir, key) FileUtils.touch(key_file) is_expected.to run.with_params(key, @options_default).and_return(true) - expect( File.exist?(key_file) ).to be false + expect(File.exist?(key_file)).to be false end - it 'should delete an existing key in the default backend for the app_id' do + it 'deletes an existing key in the default backend for the app_id' do FileUtils.mkdir_p(default_app_id_keydir) key_file = File.join(default_app_id_keydir, key) FileUtils.touch(key_file) is_expected.to run.with_params(key, @options_default_app_id).and_return(true) - expect( File.exist?(key_file) ).to be false + expect(File.exist?(key_file)).to be false end - it 'should delete an existing key in the auto-default backend when backend config missing' do + it 'deletes an existing key in the auto-default backend when backend config missing' do # mocking is REQUIRED for GitLab allow(Dir).to receive(:exist?).with(any_args).and_call_original - allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return( false ) + allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return(false) allow(FileUtils).to receive(:mkdir_p).with(any_args).and_call_original - allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default'). - and_raise(Errno::EACCES, 'Permission denied') + allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default') + .and_raise(Errno::EACCES, 'Permission denied') # The test's Puppet.settings[:vardir] gets created when the subject (function object) # is constructed - subject() + subject key_file = File.join(Puppet.settings[:vardir], 'simp', 'simpkv', 'file', 'auto_default', 'environments', environment, key) FileUtils.mkdir_p(File.dirname(key_file)) FileUtils.touch(key_file) is_expected.to run.with_params(key).and_return(true) - expect( File.exist?(key_file) ).to be false + expect(File.exist?(key_file)).to be false end - it 'should succeed even when the key does not exist in a specific backend in options' do + it 'succeeds even when the key does not exist in a specific backend in options' do is_expected.to run.with_params(key, @options_test_file).and_return(true) end - it 'should use global key when global config is set' do + it 'uses global key when global config is set' do options = @options_default.dup options['global'] = true key_file = File.join(@root_path_default, 'globals', key) @@ -115,42 +114,41 @@ FileUtils.touch(key_file) is_expected.to run.with_params(key, options).and_return(true) - expect( File.exist?(key_file) ).to be false + expect(File.exist?(key_file)).to be false end - it 'should fail when backend delete fails and `softfail` is false' do - is_expected.to run.with_params(key, @options_failer). - and_raise_error(RuntimeError, /simpkv Error for simpkv::delete with key='#{key}'/) + it 'fails when backend delete fails and `softfail` is false' do + is_expected.to run.with_params(key, @options_failer) + .and_raise_error(RuntimeError, %r{simpkv Error for simpkv::delete with key='#{key}'}) end - it 'should log warning and return false when backend delete fails and `softfail` is true' do + it 'logs warning and return false when backend delete fails and `softfail` is true' do options = @options_failer.dup options['softfail'] = true is_expected.to run.with_params(key, options).and_return(false) - #FIXME check warning log + # FIXME: check warning log end end context 'other error cases' do - it 'should fail when key fails validation' do + it 'fails when key fails validation' do params = [ '$this is an invalid key!', @options_test_file ] - is_expected.to run.with_params(*params). - and_raise_error(ArgumentError, /contains disallowed whitespace/) + is_expected.to run.with_params(*params) + .and_raise_error(ArgumentError, %r{contains disallowed whitespace}) end - it 'should fail when simpkv cannot be added to the catalog instance' do + it 'fails when simpkv cannot be added to the catalog instance' do allow(File).to receive(:exist?).and_return(false) - is_expected.to run.with_params('mykey', @options_test_file). - and_raise_error(LoadError, /simpkv Internal Error: unable to load/) + is_expected.to run.with_params('mykey', @options_test_file) + .and_raise_error(LoadError, %r{simpkv Internal Error: unable to load}) end - it 'should fail when merged simpkv options is invalid' do - bad_options = @options_default.merge ({ 'backend' => 'oops_backend' } ) - is_expected.to run.with_params('mykey', bad_options). and_raise_error(ArgumentError, - /simpkv Configuration Error for simpkv::delete with key='mykey'/) + it 'fails when merged simpkv options is invalid' do + bad_options = @options_default.merge({ 'backend' => 'oops_backend' }) + is_expected.to run.with_params('mykey', bad_options). and_raise_error(ArgumentError, + %r{simpkv Configuration Error for simpkv::delete with key='mykey'}) end end - end diff --git a/spec/functions/simpkv/deletetree_spec.rb b/spec/functions/simpkv/deletetree_spec.rb index dc53dec..e73ddb2 100644 --- a/spec/functions/simpkv/deletetree_spec.rb +++ b/spec/functions/simpkv/deletetree_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' describe 'simpkv::deletetree' do - # tell puppet-rspec to set Puppet environment to 'myenv' let(:environment) { 'myenv' } + let(:keydir) { 'app1' } # Going to use file plugin and the test plugins in spec/support/test_plugins # for these unit tests. @@ -14,35 +14,35 @@ @root_path_default_app_id = File.join(@tmpdir, 'simpkv', 'default_app_id') @root_path_default = File.join(@tmpdir, 'simpkv', 'default') options_base = { - 'backends' => { + 'backends' => { # will use failer plugin for catastrophic error cases, because # it is badly behaved and raises exceptions on all operations - 'test_failer' => { - 'id' => 'test', - 'type' => 'failer', - 'fail_constructor' => false # true = raise in constructor + 'test_failer' => { + 'id' => 'test', + 'type' => 'failer', + 'fail_constructor' => false # true = raise in constructor }, # will use file plugin for non-catastrophic test cases - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path_test_file }, - 'myapp' => { + 'myapp' => { 'id' => 'default_app_id', 'type' => 'file', 'root_path' => @root_path_default_app_id }, - 'default' => { + 'default' => { 'id' => 'default', 'type' => 'file', 'root_path' => @root_path_default } } } - @options_failer = options_base.merge ({ 'backend' => 'test_failer' } ) - @options_test_file = options_base.merge ({ 'backend' => 'test_file' } ) - @options_default_app_id = options_base.merge ({ 'app_id' => 'myapp10' } ) + @options_failer = options_base.merge({ 'backend' => 'test_failer' }) + @options_test_file = options_base.merge({ 'backend' => 'test_file' }) + @options_default_app_id = options_base.merge({ 'app_id' => 'myapp10' }) @options_default = options_base end @@ -50,119 +50,115 @@ FileUtils.remove_entry_secure(@tmpdir) end - let(:keydir) { 'app1' } - context 'basic operation' do let(:test_file_env_root_dir) { File.join(@root_path_test_file, 'environments', environment) } let(:default_app_id_env_root_dir) { File.join(@root_path_default_app_id, 'environments', environment) } let(:default_env_root_dir) { File.join(@root_path_default, 'environments', environment) } - it 'should delete an existing, non-empty key folder in a specific backend in options' do + it 'deletes an existing, non-empty key folder in a specific backend in options' do actual_keydir = File.join(test_file_env_root_dir, keydir) FileUtils.mkdir_p(actual_keydir) key_file = File.join(actual_keydir, 'key') FileUtils.touch(key_file) is_expected.to run.with_params(keydir, @options_test_file).and_return(true) - expect( Dir.exist?(actual_keydir) ).to be false + expect(Dir.exist?(actual_keydir)).to be false end - it 'should delete an existing key folder in the default backend in options when app_id unspecified' do + it 'deletes an existing key folder in the default backend in options when app_id unspecified' do actual_keydir = File.join(default_env_root_dir, keydir) FileUtils.mkdir_p(actual_keydir) key_file = File.join(actual_keydir, 'key') FileUtils.touch(key_file) is_expected.to run.with_params(keydir, @options_default).and_return(true) - expect( Dir.exist?(actual_keydir) ).to be false + expect(Dir.exist?(actual_keydir)).to be false end - it 'should delete an existing key folder in the default backend for app_id' do + it 'deletes an existing key folder in the default backend for app_id' do actual_keydir = File.join(default_app_id_env_root_dir, keydir) FileUtils.mkdir_p(actual_keydir) key_file = File.join(actual_keydir, 'key') FileUtils.touch(key_file) is_expected.to run.with_params(keydir, @options_default_app_id).and_return(true) - expect( Dir.exist?(actual_keydir) ).to be false + expect(Dir.exist?(actual_keydir)).to be false end - it 'should delete an existing key folder in the auto-default backend when backend config missing' do + it 'deletes an existing key folder in the auto-default backend when backend config missing' do # mocking is REQUIRED for GitLab allow(Dir).to receive(:exist?).with(any_args).and_call_original - allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return( false ) + allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return(false) allow(FileUtils).to receive(:mkdir_p).with(any_args).and_call_original - allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default'). - and_raise(Errno::EACCES, 'Permission denied') + allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default') + .and_raise(Errno::EACCES, 'Permission denied') # The test's Puppet.settings[:vardir] gets created when the subject (function object) # is constructed - subject() + subject actual_keydir = File.join(Puppet.settings[:vardir], 'simp', 'simpkv', 'file', 'auto_default', 'environments', environment, keydir) FileUtils.mkdir_p(File.dirname(actual_keydir)) is_expected.to run.with_params(keydir, @options_default_app_id).and_return(true) - expect( Dir.exist?(actual_keydir) ).to be false + expect(Dir.exist?(actual_keydir)).to be false end - it 'should delete an existing empty key folder in a specific backend in options' do + it 'deletes an existing empty key folder in a specific backend in options' do actual_keydir = File.join(test_file_env_root_dir, keydir) FileUtils.mkdir_p(actual_keydir) is_expected.to run.with_params(keydir, @options_test_file).and_return(true) - expect( Dir.exist?(actual_keydir) ).to be false + expect(Dir.exist?(actual_keydir)).to be false end - it 'should succeed even when the key folder does not exist in a specific backend in options' do + it 'succeeds even when the key folder does not exist in a specific backend in options' do is_expected.to run.with_params(keydir, @options_test_file).and_return(true) end - it 'should use global key folder when global config is set' do + it 'uses global key folder when global config is set' do options = @options_default.dup options['global'] = true actual_keydir = File.join(@root_path_default, 'globals', keydir) FileUtils.mkdir_p(actual_keydir) is_expected.to run.with_params(keydir, options).and_return(true) - expect( File.exist?(actual_keydir) ).to be false + expect(File.exist?(actual_keydir)).to be false end - - it 'should fail when backend deletetree fails and `softfail` is false' do - is_expected.to run.with_params(keydir, @options_failer). - and_raise_error(RuntimeError, /simpkv Error for simpkv::deletetree with keydir='#{keydir}'/) + it 'fails when backend deletetree fails and `softfail` is false' do + is_expected.to run.with_params(keydir, @options_failer) + .and_raise_error(RuntimeError, %r{simpkv Error for simpkv::deletetree with keydir='#{keydir}'}) end - it 'should log warning and return false when backend deletetree fails and `softfail` is true' do + it 'logs warning and return false when backend deletetree fails and `softfail` is true' do options = @options_failer.dup options['softfail'] = true is_expected.to run.with_params(keydir, options).and_return(false) - #FIXME check warning log + # FIXME: check warning log end end context 'other error cases' do - it 'should fail when key folder fails validation' do + it 'fails when key folder fails validation' do params = [ '$this is an invalid key folder!', @options_test_file ] - is_expected.to run.with_params(*params). - and_raise_error(ArgumentError, /contains disallowed whitespace/) + is_expected.to run.with_params(*params) + .and_raise_error(ArgumentError, %r{contains disallowed whitespace}) end - it 'should fail when simpkv cannot be added to the catalog instance' do + it 'fails when simpkv cannot be added to the catalog instance' do allow(File).to receive(:exist?).and_return(false) - is_expected.to run.with_params(keydir, @options_test_file). - and_raise_error(LoadError, /simpkv Internal Error: unable to load/) + is_expected.to run.with_params(keydir, @options_test_file) + .and_raise_error(LoadError, %r{simpkv Internal Error: unable to load}) end - it 'should fail when merged simpkv options is invalid' do - bad_options = @options_default.merge ({ 'backend' => 'oops_backend' } ) - is_expected.to run.with_params(keydir, bad_options). - and_raise_error(ArgumentError, - /simpkv Configuration Error for simpkv::deletetree with keydir='#{keydir}'/) + it 'fails when merged simpkv options is invalid' do + bad_options = @options_default.merge({ 'backend' => 'oops_backend' }) + is_expected.to run.with_params(keydir, bad_options) + .and_raise_error(ArgumentError, + %r{simpkv Configuration Error for simpkv::deletetree with keydir='#{keydir}'}) end end - end diff --git a/spec/functions/simpkv/exists_spec.rb b/spec/functions/simpkv/exists_spec.rb index 47dbc14..1f3f9f5 100644 --- a/spec/functions/simpkv/exists_spec.rb +++ b/spec/functions/simpkv/exists_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe 'simpkv::exists' do - # tell puppet-rspec to set Puppet environment to 'myenv' let(:environment) { 'myenv' } @@ -14,35 +13,35 @@ @root_path_default_app_id = File.join(@tmpdir, 'simpkv', 'default_app_id') @root_path_default = File.join(@tmpdir, 'simpkv', 'default') options_base = { - 'backends' => { + 'backends' => { # will use failer plugin for catastrophic error cases, because # it is badly behaved and raises exceptions on all operations - 'test_failer' => { - 'id' => 'test', - 'type' => 'failer', - 'fail_constructor' => false # true = raise in constructor + 'test_failer' => { + 'id' => 'test', + 'type' => 'failer', + 'fail_constructor' => false # true = raise in constructor }, # will use file plugin for non-catastrophic test cases - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path_test_file }, - 'myapp' => { + 'myapp' => { 'id' => 'default_app_id', 'type' => 'file', 'root_path' => @root_path_default_app_id }, - 'default' => { + 'default' => { 'id' => 'default', 'type' => 'file', 'root_path' => @root_path_default } } } - @options_failer = options_base.merge ({ 'backend' => 'test_failer' } ) - @options_test_file = options_base.merge ({ 'backend' => 'test_file' } ) - @options_default_app_id = options_base.merge ({ 'app_id' => 'myapp10' } ) + @options_failer = options_base.merge({ 'backend' => 'test_failer' }) + @options_test_file = options_base.merge({ 'backend' => 'test_file' }) + @options_default_app_id = options_base.merge({ 'app_id' => 'myapp10' }) @options_default = options_base end @@ -56,7 +55,7 @@ let(:default_keydir) { File.join(@root_path_default, 'environments', environment) } let(:key) { 'mykey' } - it 'should return true when the key exists at a specific backend in options' do + it 'returns true when the key exists at a specific backend in options' do FileUtils.mkdir_p(test_file_keydir) key_file = File.join(test_file_keydir, key) FileUtils.touch(key_file) @@ -64,7 +63,7 @@ is_expected.to run.with_params(key, @options_test_file).and_return(true) end - it 'should return true when the key exists at the default backend in options when app_id unspecified' do + it 'returns true when the key exists at the default backend in options when app_id unspecified' do FileUtils.mkdir_p(default_keydir) key_file = File.join(default_keydir, key) FileUtils.touch(key_file) @@ -72,7 +71,7 @@ is_expected.to run.with_params(key, @options_default).and_return(true) end - it 'should return true when the key exists at the default backend for the app_id' do + it 'returns true when the key exists at the default backend for the app_id' do FileUtils.mkdir_p(default_app_id_keydir) key_file = File.join(default_app_id_keydir, key) FileUtils.touch(key_file) @@ -80,17 +79,17 @@ is_expected.to run.with_params(key, @options_default_app_id).and_return(true) end - it 'should return true when the key exists in the auto-default backend when backend config missing' do + it 'returns true when the key exists in the auto-default backend when backend config missing' do # mocking is REQUIRED for GitLab allow(Dir).to receive(:exist?).with(any_args).and_call_original - allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return( false ) + allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return(false) allow(FileUtils).to receive(:mkdir_p).with(any_args).and_call_original - allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default'). - and_raise(Errno::EACCES, 'Permission denied') + allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default') + .and_raise(Errno::EACCES, 'Permission denied') # The test's Puppet.settings[:vardir] gets created when the subject (function object) # is constructed - subject() + subject key_file = File.join(Puppet.settings[:vardir], 'simp', 'simpkv', 'file', 'auto_default', 'environments', environment, key) FileUtils.mkdir_p(File.dirname(key_file)) @@ -99,24 +98,24 @@ is_expected.to run.with_params(key).and_return(true) end - it 'should return true when the key folder exists at a specific backend in options' do + it 'returns true when the key folder exists at a specific backend in options' do sub_keydir = 'app1' FileUtils.mkdir_p(File.join(test_file_keydir, sub_keydir)) is_expected.to run.with_params(sub_keydir, @options_test_file).and_return(true) end - it 'should return false when the key does not exist at a specific backend in options' do + it 'returns false when the key does not exist at a specific backend in options' do is_expected.to run.with_params(key, @options_test_file).and_return(false) end - it 'should return false when the key folder does not exists at a specific backend in options' do + it 'returns false when the key folder does not exists at a specific backend in options' do FileUtils.mkdir_p(test_file_keydir) is_expected.to run.with_params('missing/sub/dir', @options_test_file).and_return(false) end - it 'should use global key when global config is set' do + it 'uses global key when global config is set' do options = @options_default.dup options['global'] = true key_file = File.join(@root_path_default, 'globals', key) @@ -126,40 +125,39 @@ is_expected.to run.with_params(key, options).and_return(true) end - it 'should fail when backend exists fails and `softfail` is false' do - is_expected.to run.with_params(key, @options_failer). - and_raise_error(RuntimeError, /simpkv Error for simpkv::exists with key='#{key}'/) + it 'fails when backend exists fails and `softfail` is false' do + is_expected.to run.with_params(key, @options_failer) + .and_raise_error(RuntimeError, %r{simpkv Error for simpkv::exists with key='#{key}'}) end - it 'should log warning and return nil when backend exists fails and `softfail` is true' do + it 'logs warning and return nil when backend exists fails and `softfail` is true' do options = @options_failer.dup options['softfail'] = true is_expected.to run.with_params(key, options).and_return(nil) - #FIXME check warning log + # FIXME: check warning log end end context 'other error cases' do - it 'should fail when key fails validation' do + it 'fails when key fails validation' do params = [ '$this is an invalid key!', @options_test_file ] - is_expected.to run.with_params(*params). - and_raise_error(ArgumentError, /contains disallowed whitespace/) + is_expected.to run.with_params(*params) + .and_raise_error(ArgumentError, %r{contains disallowed whitespace}) end - it 'should fail when simpkv cannot be added to the catalog instance' do + it 'fails when simpkv cannot be added to the catalog instance' do allow(File).to receive(:exist?).and_return(false) - is_expected.to run.with_params('mykey', @options_test_file). - and_raise_error(LoadError, /simpkv Internal Error: unable to load/) + is_expected.to run.with_params('mykey', @options_test_file) + .and_raise_error(LoadError, %r{simpkv Internal Error: unable to load}) end - it 'should fail when merged simpkv options is invalid' do - bad_options = @options_default.merge ({ 'backend' => 'oops_backend' } ) - is_expected.to run.with_params('mykey', bad_options). - and_raise_error(ArgumentError, - /simpkv Configuration Error for simpkv::exists with key='mykey'/) + it 'fails when merged simpkv options is invalid' do + bad_options = @options_default.merge({ 'backend' => 'oops_backend' }) + is_expected.to run.with_params('mykey', bad_options) + .and_raise_error(ArgumentError, + %r{simpkv Configuration Error for simpkv::exists with key='mykey'}) end end - end diff --git a/spec/functions/simpkv/get_spec.rb b/spec/functions/simpkv/get_spec.rb index c4272de..58b3cb7 100644 --- a/spec/functions/simpkv/get_spec.rb +++ b/spec/functions/simpkv/get_spec.rb @@ -1,9 +1,12 @@ require 'spec_helper' describe 'simpkv::get' do - # tell puppet-rspec to set Puppet environment to 'myenv' let(:environment) { 'myenv' } + let(:key) { 'mykey' } + let(:value) { false } + let(:metadata) { { 'foo' => 'bar', 'baz' => 42 } } + let(:serialized_value) { '{"value":false,"metadata":{"foo":"bar","baz":42}}' } # Going to use file plugin and the test plugins in spec/support/test_plugins # for these unit tests. @@ -14,35 +17,35 @@ @root_path_default_app_id = File.join(@tmpdir, 'simpkv', 'default_app_id') @root_path_default = File.join(@tmpdir, 'simpkv', 'default') options_base = { - 'backends' => { + 'backends' => { # will use failer plugin for catastrophic error cases, because # it is badly behaved and raises exceptions on all operations - 'test_failer' => { - 'id' => 'test', - 'type' => 'failer', - 'fail_constructor' => false # true = raise in constructor + 'test_failer' => { + 'id' => 'test', + 'type' => 'failer', + 'fail_constructor' => false # true = raise in constructor }, # will use file plugin for non-catastrophic test cases - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path_test_file }, - 'myapp' => { + 'myapp' => { 'id' => 'default_app_id', 'type' => 'file', 'root_path' => @root_path_default_app_id }, - 'default' => { + 'default' => { 'id' => 'default', 'type' => 'file', 'root_path' => @root_path_default } } } - @options_failer = options_base.merge ({ 'backend' => 'test_failer' } ) - @options_test_file = options_base.merge ({ 'backend' => 'test_file' } ) - @options_default_app_id = options_base.merge ({ 'app_id' => 'myapp10' } ) + @options_failer = options_base.merge({ 'backend' => 'test_failer' }) + @options_test_file = options_base.merge({ 'backend' => 'test_file' }) + @options_default_app_id = options_base.merge({ 'app_id' => 'myapp10' }) @options_default = options_base end @@ -50,21 +53,16 @@ FileUtils.remove_entry_secure(@tmpdir) end - let(:key) { 'mykey' } - let(:value) { false } - let(:metadata) { { 'foo' => 'bar', 'baz' => 42 } } - let(:serialized_value) { '{"value":false,"metadata":{"foo":"bar","baz":42}}' } - context 'basic operation' do let(:test_file_keydir) { File.join(@root_path_test_file, 'environments', environment) } let(:default_app_id_keydir) { File.join(@root_path_default_app_id, 'environments', environment) } let(:default_keydir) { File.join(@root_path_default, 'environments', environment) } - data_info.each do |summary,info| - it "should retrieve key with #{summary} value + metadata from a specific backend in options" do - skip info[:skip] if info.has_key?(:skip) + data_info.each do |summary, info| + it "retrieves key with #{summary} value + metadata from a specific backend in options" do + skip info[:skip] if info.key?(:skip) - if info.has_key?(:deserialized_value) + if info.key?(:deserialized_value) # This key is set when the entry has malformed binary data that is # improperly encoded as UTF-8. Current adapter behavior is fix the # encoding on retrieval, but that behavior may not be needed. @@ -81,7 +79,7 @@ end end - it 'should retrieve the key,value,metadata tuple from the default backend in options when app_id unspecified' do + it 'retrieves the key,value,metadata tuple from the default backend in options when app_id unspecified' do FileUtils.mkdir_p(default_keydir) key_file = File.join(default_keydir, key) File.open(key_file, 'w') { |file| file.write(serialized_value) } @@ -90,7 +88,7 @@ is_expected.to run.with_params(key, @options_default).and_return(expected) end - it 'should retrieve the key,value,metadata tuple from the default backend for app_id' do + it 'retrieves the key,value,metadata tuple from the default backend for app_id' do FileUtils.mkdir_p(default_app_id_keydir) key_file = File.join(default_app_id_keydir, key) File.open(key_file, 'w') { |file| file.write(serialized_value) } @@ -99,17 +97,17 @@ is_expected.to run.with_params(key, @options_default_app_id).and_return(expected) end - it 'should retrieve the key,value,metadata tuple from the auto-default backend when backend config missing' do + it 'retrieves the key,value,metadata tuple from the auto-default backend when backend config missing' do # mocking is REQUIRED for GitLab allow(Dir).to receive(:exist?).with(any_args).and_call_original - allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return( false ) + allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return(false) allow(FileUtils).to receive(:mkdir_p).with(any_args).and_call_original - allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default'). - and_raise(Errno::EACCES, 'Permission denied') + allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default') + .and_raise(Errno::EACCES, 'Permission denied') # The test's Puppet.settings[:vardir] gets created when the subject (function object) # is constructed - subject() + subject key_file = File.join(Puppet.settings[:vardir], 'simp', 'simpkv', 'file', 'auto_default', 'environments', environment, key) FileUtils.mkdir_p(File.dirname(key_file)) @@ -119,7 +117,7 @@ is_expected.to run.with_params(key).and_return(expected) end - it 'should use global key when global config is set' do + it 'uses global key when global config is set' do options = @options_default.dup options['global'] = true key_file = File.join(@root_path_default, 'globals', key) @@ -130,40 +128,39 @@ is_expected.to run.with_params(key, options).and_return(expected) end - it 'should fail when backend get fails and `softfail` is false' do - is_expected.to run.with_params(key, @options_failer). - and_raise_error(RuntimeError, /simpkv Error for simpkv::get with key='#{key}'/) + it 'fails when backend get fails and `softfail` is false' do + is_expected.to run.with_params(key, @options_failer) + .and_raise_error(RuntimeError, %r{simpkv Error for simpkv::get with key='#{key}'}) end - it 'should log warning and return nil when backend get fails and `softfail` is true' do + it 'logs warning and return nil when backend get fails and `softfail` is true' do options = @options_failer.dup options['softfail'] = true is_expected.to run.with_params(key, options).and_return(nil) - #FIXME check warning log + # FIXME: check warning log end end context 'other error cases' do - it 'should fail when key fails validation' do + it 'fails when key fails validation' do params = [ '$this is an invalid key!', @options_test_file ] - is_expected.to run.with_params(*params). - and_raise_error(ArgumentError, /contains disallowed whitespace/) + is_expected.to run.with_params(*params) + .and_raise_error(ArgumentError, %r{contains disallowed whitespace}) end - it 'should fail when simpkv cannot be added to the catalog instance' do + it 'fails when simpkv cannot be added to the catalog instance' do allow(File).to receive(:exist?).and_return(false) - is_expected.to run.with_params('mykey', @options_test_file). - and_raise_error(LoadError, /simpkv Internal Error: unable to load/) + is_expected.to run.with_params('mykey', @options_test_file) + .and_raise_error(LoadError, %r{simpkv Internal Error: unable to load}) end - it 'should fail when merged simpkv options is invalid' do - bad_options = @options_default.merge ({ 'backend' => 'oops_backend' } ) - is_expected.to run.with_params('mykey', bad_options). - and_raise_error(ArgumentError, - /simpkv Configuration Error for simpkv::get with key='mykey'/) + it 'fails when merged simpkv options is invalid' do + bad_options = @options_default.merge({ 'backend' => 'oops_backend' }) + is_expected.to run.with_params('mykey', bad_options) + .and_raise_error(ArgumentError, + %r{simpkv Configuration Error for simpkv::get with key='mykey'}) end end - end diff --git a/spec/functions/simpkv/list_spec.rb b/spec/functions/simpkv/list_spec.rb index fa0c404..60d0ab3 100644 --- a/spec/functions/simpkv/list_spec.rb +++ b/spec/functions/simpkv/list_spec.rb @@ -5,9 +5,9 @@ def prepopulate_key_files(root_dir, keydir) FileUtils.mkdir_p(actual_keydir) data_info.each do |description, info| - next if (info.has_key?(:skip) || info.has_key?(:deserialized_value)) + next if info.key?(:skip) || info.key?(:deserialized_value) - filename = File.join(actual_keydir, description.gsub(' ','_')) + filename = File.join(actual_keydir, description.tr(' ', '_')) File.open(filename, 'w') { |file| file.write(info[:serialized_value]) } end @@ -19,9 +19,28 @@ def prepopulate_key_files(root_dir, keydir) end describe 'simpkv::list' do - # tell puppet-rspec to set Puppet environment to 'myenv' let(:environment) { 'myenv' } + let(:keydir) { 'app1' } + let(:key_list) do + list = data_info.map { |description, info| + if info.key?(:skip) || info.key?(:deserialized_value) + ['skip', nil] + else + info_hash = { 'value' => info[:value] } + info_hash['metadata'] = info[:metadata] unless info[:metadata].empty? + [ description.tr(' ', '_').to_s, info_hash ] + end + }.to_h + list.delete('skip') + list + end + let(:full_list) do + { 'keys' => key_list, 'folders' => ['subapp1', 'subapp2', 'subapp3'] } + end + let(:test_file_env_root_dir) { File.join(@root_path_test_file, 'environments', environment) } + let(:default_app_id_env_root_dir) { File.join(@root_path_default_app_id, 'environments', environment) } + let(:default_env_root_dir) { File.join(@root_path_default, 'environments', environment) } # Going to use file plugin and the test plugins in spec/support/test_plugins # for these unit tests. @@ -32,35 +51,35 @@ def prepopulate_key_files(root_dir, keydir) @root_path_default_app_id = File.join(@tmpdir, 'simpkv', 'default_app_id') @root_path_default = File.join(@tmpdir, 'simpkv', 'default') options_base = { - 'backends' => { + 'backends' => { # will use failer plugin for catastrophic error cases, because # it is badly behaved and raises exceptions on all operations - 'test_failer' => { - 'id' => 'test', - 'type' => 'failer', - 'fail_constructor' => false # true = raise in constructor + 'test_failer' => { + 'id' => 'test', + 'type' => 'failer', + 'fail_constructor' => false # true = raise in constructor }, # will use file plugin for non-catastrophic test cases - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path_test_file }, - 'myapp' => { + 'myapp' => { 'id' => 'default_app_id', 'type' => 'file', 'root_path' => @root_path_default_app_id }, - 'default' => { + 'default' => { 'id' => 'default', 'type' => 'file', 'root_path' => @root_path_default } } } - @options_failer = options_base.merge ({ 'backend' => 'test_failer' } ) - @options_test_file = options_base.merge ({ 'backend' => 'test_file' } ) - @options_default_app_id = options_base.merge ({ 'app_id' => 'myapp10' } ) + @options_failer = options_base.merge({ 'backend' => 'test_failer' }) + @options_test_file = options_base.merge({ 'backend' => 'test_file' }) + @options_default_app_id = options_base.merge({ 'app_id' => 'myapp10' }) @options_default = options_base end @@ -68,61 +87,39 @@ def prepopulate_key_files(root_dir, keydir) FileUtils.remove_entry_secure(@tmpdir) end - let(:keydir) { 'app1' } - let(:key_list) { - list = data_info.map { |description, info| - if info.has_key?(:skip) || info.has_key?(:deserialized_value) - ['skip', nil] - else - info_hash = { 'value' => info[:value] } - info_hash['metadata'] = info[:metadata] unless info[:metadata].empty? - [ "#{description.gsub(' ','_')}", info_hash ] - end - }.to_h - list.delete('skip') - list - } - let(:full_list) { - { 'keys' => key_list, 'folders' => ['subapp1', 'subapp2', 'subapp3'] } - } - - let(:test_file_env_root_dir) { File.join(@root_path_test_file, 'environments', environment) } - let(:default_app_id_env_root_dir) { File.join(@root_path_default_app_id, 'environments', environment) } - let(:default_env_root_dir) { File.join(@root_path_default, 'environments', environment) } - context 'basic operation' do - it 'should retrieve key list from a specific backend in options when keys exist' do + it 'retrieves key list from a specific backend in options when keys exist' do prepopulate_key_files(test_file_env_root_dir, keydir) - is_expected.to run.with_params(keydir, @options_test_file). - and_return(full_list) + is_expected.to run.with_params(keydir, @options_test_file) + .and_return(full_list) end - it 'should retrieve key list from the default backend in options when keys exist and app_id unspecified' do + it 'retrieves key list from the default backend in options when keys exist and app_id unspecified' do prepopulate_key_files(default_env_root_dir, keydir) - is_expected.to run.with_params(keydir, @options_default). - and_return(full_list) + is_expected.to run.with_params(keydir, @options_default) + .and_return(full_list) end - it 'should retrieve key list from the default backend for the app_id when keys exist' do + it 'retrieves key list from the default backend for the app_id when keys exist' do prepopulate_key_files(default_app_id_env_root_dir, keydir) - is_expected.to run.with_params(keydir, @options_default_app_id). - and_return(full_list) + is_expected.to run.with_params(keydir, @options_default_app_id) + .and_return(full_list) end - it 'should retrieve key list from the auto-default backend when keys exist and backend config missing' do + it 'retrieves key list from the auto-default backend when keys exist and backend config missing' do # mocking is REQUIRED for GitLab allow(Dir).to receive(:exist?).with(any_args).and_call_original - allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return( false ) + allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return(false) allow(FileUtils).to receive(:mkdir_p).with(any_args).and_call_original - allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default'). - and_raise(Errno::EACCES, 'Permission denied') + allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default') + .and_raise(Errno::EACCES, 'Permission denied') # The test's Puppet.settings[:vardir] gets created when the subject (function object) # is constructed - subject() + subject env_root_dir = File.join(Puppet.settings[:vardir], 'simp', 'simpkv', 'file', 'auto_default', 'environments', environment) prepopulate_key_files(env_root_dir, keydir) @@ -130,20 +127,20 @@ def prepopulate_key_files(root_dir, keydir) is_expected.to run.with_params(keydir).and_return(full_list) end - it 'should return an empty key list when no keys exist but the directory exists' do + it 'returns an empty key list when no keys exist but the directory exists' do # directory has to exist or it is considered a failure actual_keydir = File.join(default_env_root_dir, keydir) FileUtils.mkdir_p(actual_keydir) - is_expected.to run.with_params(keydir, @options_default).and_return({'keys'=>{}, 'folders'=>[]}) + is_expected.to run.with_params(keydir, @options_default).and_return({ 'keys' => {}, 'folders' => [] }) end - it 'should fail when the directory does not exist and `softfail` is false' do - is_expected.to run.with_params(keydir, @options_default). - and_raise_error(RuntimeError, /simpkv Error for simpkv::list with keydir='#{keydir}'/) + it 'fails when the directory does not exist and `softfail` is false' do + is_expected.to run.with_params(keydir, @options_default) + .and_raise_error(RuntimeError, %r{simpkv Error for simpkv::list with keydir='#{keydir}'}) end - it 'should use global keydir when global config is set' do + it 'uses global keydir when global config is set' do options = @options_default.dup options['global'] = true prepopulate_key_files(File.join(@root_path_default, 'globals'), keydir) @@ -151,40 +148,39 @@ def prepopulate_key_files(root_dir, keydir) is_expected.to run.with_params(keydir, options).and_return(full_list) end - it 'should fail when backend list fails and `softfail` is false' do - is_expected.to run.with_params(keydir, @options_failer). - and_raise_error(RuntimeError, /simpkv Error for simpkv::list with keydir='#{keydir}'/) + it 'fails when backend list fails and `softfail` is false' do + is_expected.to run.with_params(keydir, @options_failer) + .and_raise_error(RuntimeError, %r{simpkv Error for simpkv::list with keydir='#{keydir}'}) end - it 'should log warning and return nil when backend list fails and `softfail` is true' do + it 'logs warning and return nil when backend list fails and `softfail` is true' do options = @options_failer.dup options['softfail'] = true is_expected.to run.with_params(keydir, options).and_return(nil) - #FIXME check warning log + # FIXME: check warning log end end context 'other error cases' do - it 'should fail when key fails validation' do + it 'fails when key fails validation' do params = [ '$this is an invalid key dir!', @options_test_file ] - is_expected.to run.with_params(*params). - and_raise_error(ArgumentError, /contains disallowed whitespace/) + is_expected.to run.with_params(*params) + .and_raise_error(ArgumentError, %r{contains disallowed whitespace}) end - it 'should fail when simpkv cannot be added to the catalog instance' do + it 'fails when simpkv cannot be added to the catalog instance' do allow(File).to receive(:exist?).and_return(false) - is_expected.to run.with_params(keydir, @options_test_file). - and_raise_error(LoadError, /simpkv Internal Error: unable to load/) + is_expected.to run.with_params(keydir, @options_test_file) + .and_raise_error(LoadError, %r{simpkv Internal Error: unable to load}) end - it 'should fail when merged simpkv options is invalid' do - bad_options = @options_default.merge ({ 'backend' => 'oops_backend' } ) - is_expected.to run.with_params(keydir, bad_options). - and_raise_error(ArgumentError, - /simpkv Configuration Error for simpkv::list with keydir='#{keydir}'/) + it 'fails when merged simpkv options is invalid' do + bad_options = @options_default.merge({ 'backend' => 'oops_backend' }) + is_expected.to run.with_params(keydir, bad_options) + .and_raise_error(ArgumentError, + %r{simpkv Configuration Error for simpkv::list with keydir='#{keydir}'}) end end - end diff --git a/spec/functions/simpkv/put_spec.rb b/spec/functions/simpkv/put_spec.rb index a097efe..849134d 100644 --- a/spec/functions/simpkv/put_spec.rb +++ b/spec/functions/simpkv/put_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' describe 'simpkv::put' do - # tell puppet-rspec to set Puppet environment to 'myenv' let(:environment) { 'myenv' } @@ -14,35 +13,35 @@ @root_path_default_app_id = File.join(@tmpdir, 'simpkv', 'default_app_id') @root_path_default = File.join(@tmpdir, 'simpkv', 'default') options_base = { - 'backends' => { + 'backends' => { # will use failer plugin for catastrophic error cases, because # it is badly behaved and raises exceptions on all operations - 'test_failer' => { - 'id' => 'test', - 'type' => 'failer', - 'fail_constructor' => false # true = raise in constructor + 'test_failer' => { + 'id' => 'test', + 'type' => 'failer', + 'fail_constructor' => false # true = raise in constructor }, # will use file plugin for non-catastrophic test cases - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path_test_file }, - 'myapp' => { + 'myapp' => { 'id' => 'default_app_id', 'type' => 'file', 'root_path' => @root_path_default_app_id }, - 'default' => { + 'default' => { 'id' => 'default', 'type' => 'file', 'root_path' => @root_path_default } } } - @options_failer = options_base.merge ({ 'backend' => 'test_failer' } ) - @options_test_file = options_base.merge ({ 'backend' => 'test_file' } ) - @options_default_app_id = options_base.merge ({ 'app_id' => 'myapp10' } ) + @options_failer = options_base.merge({ 'backend' => 'test_failer' }) + @options_test_file = options_base.merge({ 'backend' => 'test_file' }) + @options_default_app_id = options_base.merge({ 'app_id' => 'myapp10' }) @options_default = options_base end @@ -55,98 +54,97 @@ let(:value) { 'myvalue' } let(:metadata) { { 'foo' => 'bar', 'baz' => 42 } } - data_info.each do |summary,info| - it "should store key with #{summary} value + metadata to a specific backend in options" do - skip info[:skip] if info.has_key?(:skip) + data_info.each do |summary, info| + it "stores key with #{summary} value + metadata to a specific backend in options" do + skip info[:skip] if info.key?(:skip) - params = [ key, info[:value] , info[:metadata], @options_test_file ] + params = [ key, info[:value], info[:metadata], @options_test_file ] is_expected.to run.with_params(*params).and_return(true) key_file = File.join(@root_path_test_file, 'environments', environment, key) - expect( File.exist?(key_file) ).to be true - expect( File.read(key_file) ).to eq(info[:serialized_value]) + expect(File.exist?(key_file)).to be true + expect(File.read(key_file)).to eq(info[:serialized_value]) end end - it 'should store key,value,metadata tuple to the default backend in options when app_id unspecified' do - is_expected.to run.with_params(key, value , metadata, @options_default). - and_return(true) + it 'stores key,value,metadata tuple to the default backend in options when app_id unspecified' do + is_expected.to run.with_params(key, value, metadata, @options_default) + .and_return(true) key_file = File.join(@root_path_default, 'environments', environment, key) - expect( File.exist?(key_file) ).to be true + expect(File.exist?(key_file)).to be true end - it 'should store key,value,metadata tuple to the auto-default backend when backend config missing' do + it 'stores key,value,metadata tuple to the auto-default backend when backend config missing' do # mocking is REQUIRED for GitLab allow(Dir).to receive(:exist?).with(any_args).and_call_original - allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return( false ) + allow(Dir).to receive(:exist?).with('/var/simp/simpkv/file/auto_default').and_return(false) allow(FileUtils).to receive(:mkdir_p).with(any_args).and_call_original - allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default'). - and_raise(Errno::EACCES, 'Permission denied') + allow(FileUtils).to receive(:mkdir_p).with('/var/simp/simpkv/file/auto_default') + .and_raise(Errno::EACCES, 'Permission denied') is_expected.to run.with_params(key, value, metadata).and_return(true) key_file = File.join(Puppet.settings[:vardir], 'simp', 'simpkv', 'file', 'auto_default', 'environments', environment, key) - expect( File.exist?(key_file) ).to be true + expect(File.exist?(key_file)).to be true end - it 'should store key,value,metadata tuple to the default backend for app_id' do - is_expected.to run.with_params(key, value , metadata, @options_default_app_id). - and_return(true) + it 'stores key,value,metadata tuple to the default backend for app_id' do + is_expected.to run.with_params(key, value, metadata, @options_default_app_id) + .and_return(true) key_file = File.join(@root_path_default_app_id, 'environments', environment, key) - expect( File.exist?(key_file) ).to be true + expect(File.exist?(key_file)).to be true end - it 'should use global key when global config is set' do + it 'uses global key when global config is set' do options = @options_default.dup options['global'] = true - is_expected.to run.with_params(key, value , metadata, options). - and_return(true) + is_expected.to run.with_params(key, value, metadata, options) + .and_return(true) env_key_file = File.join(@root_path_default, 'environments', environment, key) - expect( File.exist?(env_key_file) ).to be false + expect(File.exist?(env_key_file)).to be false key_file = File.join(@root_path_default, 'globals', key) - expect( File.exist?(key_file) ).to be true + expect(File.exist?(key_file)).to be true end - it 'should fail when backend put fails and `softfail` is false' do - is_expected.to run.with_params(key, value , metadata, @options_failer). - and_raise_error(RuntimeError, /simpkv Error for simpkv::put with key='#{key}'/) + it 'fails when backend put fails and `softfail` is false' do + is_expected.to run.with_params(key, value, metadata, @options_failer) + .and_raise_error(RuntimeError, %r{simpkv Error for simpkv::put with key='#{key}'}) end - it 'should log warning and return false when backend put fails and `softfail` is true' do + it 'logs warning and return false when backend put fails and `softfail` is true' do options = @options_failer.dup options['softfail'] = true - is_expected.to run.with_params(key, value , metadata, options). - and_return(false) + is_expected.to run.with_params(key, value, metadata, options) + .and_return(false) - #FIXME check warning log + # FIXME: check warning log end end context 'other error cases' do - it 'should fail when key fails validation' do + it 'fails when key fails validation' do params = [ '$this is an invalid key!', 'value', {}, @options_test_file ] - is_expected.to run.with_params(*params). - and_raise_error(ArgumentError, /contains disallowed whitespace/) + is_expected.to run.with_params(*params) + .and_raise_error(ArgumentError, %r{contains disallowed whitespace}) end - it 'should fail when simpkv cannot be added to the catalog instance' do + it 'fails when simpkv cannot be added to the catalog instance' do allow(File).to receive(:exist?).and_return(false) - is_expected.to run.with_params('mykey', 'myvalue' , {}, @options_test_file). - and_raise_error(LoadError, /simpkv Internal Error: unable to load/) + is_expected.to run.with_params('mykey', 'myvalue', {}, @options_test_file) + .and_raise_error(LoadError, %r{simpkv Internal Error: unable to load}) end - it 'should fail when merged simpkv options is invalid' do - bad_options = @options_default.merge ({ 'backend' => 'oops_backend' } ) - is_expected.to run.with_params('mykey', 'myvalue' , {}, bad_options). - and_raise_error(ArgumentError, - /simpkv Configuration Error for simpkv::put with key='mykey'/) + it 'fails when merged simpkv options is invalid' do + bad_options = @options_default.merge({ 'backend' => 'oops_backend' }) + is_expected.to run.with_params('mykey', 'myvalue', {}, bad_options) + .and_raise_error(ArgumentError, + %r{simpkv Configuration Error for simpkv::put with key='mykey'}) end end - end diff --git a/spec/functions/simpkv/support/config/merge_spec.rb b/spec/functions/simpkv/support/config/merge_spec.rb index 367c51d..23e1166 100644 --- a/spec/functions/simpkv/support/config/merge_spec.rb +++ b/spec/functions/simpkv/support/config/merge_spec.rb @@ -1,14 +1,13 @@ require 'spec_helper' describe 'simpkv::support::config::merge' do - let(:backends) { [ 'file' ] } # tell puppet-rspec to set Puppet environment to 'myenv' let(:environment) { 'myenv' } context 'simpkv::options and app_id not specified' do - it "should just add 'environment' to merged config when all other config specified" do + it "justs add 'environment' to merged config when all other config specified" do input_config = { 'backend' => 'default', 'global' => true, @@ -26,7 +25,7 @@ is_expected.to run.with_params(input_config, backends).and_return(output_config) end - it "should add default 'backend' to merged config when missing" do + it "adds default 'backend' to merged config when missing" do input_config = { 'global' => false, 'softfail' => true, @@ -41,11 +40,11 @@ output_config['environment'] = environment output_config['backend'] = 'default' - is_expected.to run.with_params(input_config, backends). - and_return(output_config) + is_expected.to run.with_params(input_config, backends) + .and_return(output_config) end - it "should add 'global' to merged config when missing" do + it "adds 'global' to merged config when missing" do input_config = { 'backend' => 'default', 'softfail' => true, @@ -60,12 +59,11 @@ output_config['environment'] = environment output_config['global'] = false - is_expected.to run.with_params(input_config, backends). - and_return(output_config) + is_expected.to run.with_params(input_config, backends) + .and_return(output_config) end - - it "should add 'softfail' to merged config when missing" do + it "adds 'softfail' to merged config when missing" do input_config = { 'backend' => 'default', 'global' => true, @@ -80,11 +78,11 @@ output_config['environment'] = environment output_config['softfail'] = false - is_expected.to run.with_params(input_config, backends). - and_return(output_config) + is_expected.to run.with_params(input_config, backends) + .and_return(output_config) end - it "should add 'backends' with file backend auto-default when backends missing" do + it "adds 'backends' with file backend auto-default when backends missing" do output_config = { 'environment' => environment, 'global' => false, @@ -97,11 +95,11 @@ } } } - is_expected.to run.with_params({}, backends). - and_return(output_config) + is_expected.to run.with_params({}, backends) + .and_return(output_config) end - it 'should fail when input config is invalid' do + it 'fails when input config is invalid' do options = { 'backends' => { 'default' => { @@ -110,17 +108,16 @@ } } } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /simpkv backend plugin 'does_not_exist' not available/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{simpkv backend plugin 'does_not_exist' not available}) end - end context 'simpkv::options specified' do let(:hieradata) { 'one_backend' } - it 'should return simpkv::options config when no input config is specified' do + it 'returns simpkv::options config when no input config is specified' do output_config = { 'backend' => 'default', 'environment' => environment, @@ -136,11 +133,11 @@ } } - is_expected.to run.with_params({}, backends). - and_return(output_config) + is_expected.to run.with_params({}, backends) + .and_return(output_config) end - it 'should merge input config and simpkv::options but defer to input config' do + it 'merges input config and simpkv::options but defer to input config' do input_config = { 'backend' => 'test', 'global' => true, @@ -173,17 +170,16 @@ } } } - is_expected.to run.with_params(input_config, backends). - and_return(output_config) + is_expected.to run.with_params(input_config, backends) + .and_return(output_config) end - - it 'should fail when merged config is invalid' do + it 'fails when merged config is invalid' do input_config = { 'backend' => 'test' } - is_expected.to run.with_params(input_config, backends). - and_raise_error(ArgumentError, - /No simpkv backend 'test' with 'id' and 'type' attributes has been configured/) + is_expected.to run.with_params(input_config, backends) + .and_raise_error(ArgumentError, + %r{No simpkv backend 'test' with 'id' and 'type' attributes has been configured}) end end @@ -192,8 +188,9 @@ # alias expanded version of simpkv:options in multiple_backends.yaml with # environment added - let(:simpkv_options) { { - 'environment' => environment, + let(:simpkv_options) do + { + 'environment' => environment, 'global' => false, 'softfail' => false, 'backends' => { @@ -221,9 +218,10 @@ 'lock_timeout_seconds' => 30 } } - } } + } + end - it "should set 'backend' to match 'app_id' when exact match exists" do + it "sets 'backend' to match 'app_id' when exact match exists" do expected = simpkv_options.dup expected['app_id'] = 'myapp1_special_snowflake' expected['backend'] = 'myapp1_special_snowflake' @@ -231,23 +229,23 @@ backends).and_return(expected) end - it "should set 'backend' to longest match of 'app_id' beginning when start with match exists" do + it "sets 'backend' to longest match of 'app_id' beginning when start with match exists" do expected = simpkv_options.dup expected['app_id'] = 'myapp10' expected['backend'] = 'myapp1' - is_expected.to run.with_params({ 'app_id' => 'myapp10' }, backends). - and_return(expected) + is_expected.to run.with_params({ 'app_id' => 'myapp10' }, backends) + .and_return(expected) end - it "should set 'backend' to default when no 'app_id' start with match is found" do + it "sets 'backend' to default when no 'app_id' start with match is found" do expected = simpkv_options.dup expected['app_id'] = 'other_myapp' expected['backend'] = 'default' - is_expected.to run.with_params({ 'app_id' => 'other_myapp' }, backends). - and_return(expected) + is_expected.to run.with_params({ 'app_id' => 'other_myapp' }, backends) + .and_return(expected) end - it "should ignore 'app_id' when 'backend' is specified" do + it "ignores 'app_id' when 'backend' is specified" do expected = simpkv_options.dup expected['app_id'] = 'myapp1' expected['backend'] = 'default' diff --git a/spec/functions/simpkv/support/config/validate_spec.rb b/spec/functions/simpkv/support/config/validate_spec.rb index 84bef50..4c92d85 100644 --- a/spec/functions/simpkv/support/config/validate_spec.rb +++ b/spec/functions/simpkv/support/config/validate_spec.rb @@ -1,22 +1,20 @@ require 'spec_helper' describe 'simpkv::support::config::validate' do - let(:backends) { [ 'file' ] } context 'valid backend config' do - - it 'should allow valid config' do + it 'allows valid config' do config = { 'backend' => 'test_file', 'environment' => 'production', 'backends' => { - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file' }, # this duplicate is OK because its config exactly matches test_file - 'test_file_dup' => { + 'test_file_dup' => { 'id' => 'test', 'type' => 'file' }, @@ -40,80 +38,78 @@ end context 'invalid backend config' do - it "should fail when options is missing 'backend'" do + it "fails when options is missing 'backend'" do options = {} - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /'backend' not specified in simpkv configuration/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{'backend' not specified in simpkv configuration}) end - it "should fail when options is missing 'backends'" do + it "fails when options is missing 'backends'" do options = { 'backend' => 'file' } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /'backends' not specified in simpkv configuration/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{'backends' not specified in simpkv configuration}) end - it "should fail when 'backends' in not a Hash" do + it "fails when 'backends' in not a Hash" do options = { 'backend' => 'file', 'backends' => [] } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /'backends' in simpkv configuration is not a Hash/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{'backends' in simpkv configuration is not a Hash}) end - it "should fail when 'backends' does not have an entry for 'backend'" do + it "fails when 'backends' does not have an entry for 'backend'" do options = { 'backend' => 'file', 'backends' => {} } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /No simpkv backend 'file' with 'id' and 'type' attributes has been configured/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{No simpkv backend 'file' with 'id' and 'type' attributes has been configured}) end - it "should fail when 'backends' entry for 'backend' is not a Hash" do + it "fails when 'backends' entry for 'backend' is not a Hash" do options = { 'backend' => 'file', 'backends' => { 'file' => [] } } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /No simpkv backend 'file' with 'id' and 'type' attributes has been configured/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{No simpkv backend 'file' with 'id' and 'type' attributes has been configured}) end - it "should fail when 'backends' entry for 'backend' is missing 'id'" do + it "fails when 'backends' entry for 'backend' is missing 'id'" do options = { 'backend' => 'file', 'backends' => { 'file' => {} } } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /No simpkv backend 'file' with 'id' and 'type' attributes has been configured/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{No simpkv backend 'file' with 'id' and 'type' attributes has been configured}) end - it "should fail when 'backends' entry for 'backend' is missing 'type'" do - options = { 'backend' => 'file', 'backends' => { 'file' => { 'id' => 'test'} } } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /No simpkv backend 'file' with 'id' and 'type' attributes has been configured/) + it "fails when 'backends' entry for 'backend' is missing 'type'" do + options = { 'backend' => 'file', 'backends' => { 'file' => { 'id' => 'test' } } } + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{No simpkv backend 'file' with 'id' and 'type' attributes has been configured}) end - it "should fail when the plugin for 'backend' has not been loaded" do + it "fails when the plugin for 'backend' has not been loaded" do options = { 'backend' => 'file', - 'backends' => { 'file' => { 'id' => 'test', 'type' => 'file'} } + 'backends' => { 'file' => { 'id' => 'test', 'type' => 'file' } } } - is_expected.to run.with_params(options, [ 'consul' ]). - and_raise_error(ArgumentError, - /simpkv backend plugin 'file' not available/) + is_expected.to run.with_params(options, [ 'consul' ]) + .and_raise_error(ArgumentError, + %r{simpkv backend plugin 'file' not available}) end - it "should fail when 'backends' contains conflicting configs for the same plugin instance" do + it "fails when 'backends' contains conflicting configs for the same plugin instance" do options = { 'backend' => 'file1', 'backends' => { - 'file1' => { 'id' => 'test', 'type' => 'file'}, + 'file1' => { 'id' => 'test', 'type' => 'file' }, # this should have a different id because it has different config - 'file2' => { 'id' => 'test', 'type' => 'file', 'foo' => 'bar'} - } + 'file2' => { 'id' => 'test', 'type' => 'file', 'foo' => 'bar' } + } } - is_expected.to run.with_params(options, backends). - and_raise_error(ArgumentError, - /simpkv config contains different backend configs for type=file id=test/) + is_expected.to run.with_params(options, backends) + .and_raise_error(ArgumentError, + %r{simpkv config contains different backend configs for type=file id=test}) end - end - end diff --git a/spec/functions/simpkv/support/key/validate_spec.rb b/spec/functions/simpkv/support/key/validate_spec.rb index 3f77901..5763335 100644 --- a/spec/functions/simpkv/support/key/validate_spec.rb +++ b/spec/functions/simpkv/support/key/validate_spec.rb @@ -1,16 +1,15 @@ require 'spec_helper' describe 'simpkv::support::key::validate' do - context 'valid keys' do [ 'simple', 'looks/like/a/file/path', 'looks/like/a/directory/path/', 'simp-simp_snmpd:password.auth', - 'this/.../technically/is/ok' + 'this/.../technically/is/ok', ].each do |key| - it "should allow key='#{key}'" do + it "allows key='#{key}'" do is_expected.to run.with_params(key) end end @@ -22,40 +21,38 @@ [ ' ', "\t", "\r", "\n" ].each do |ws_char| - it "should fail when key contains whitespace character #{ws_char.inspect}" do + it "fails when key contains whitespace character #{ws_char.inspect}" do key = 'key' + ws_char is_expected.to run.with_params(key).and_raise_error(ArgumentError, - /key '#{Regexp.escape(key)}' contains disallowed whitespace/) + %r{key '#{Regexp.escape(key)}' contains disallowed whitespace}) end end - it 'should fail when key contains uppercase letters' do + it 'fails when key contains uppercase letters' do key = 'Uppercase/Characters/NOT/Allowed' is_expected.to run.with_params(key).and_raise_error(ArgumentError, - /key '#{Regexp.escape(key)}' contains unsupported characters/) + %r{key '#{Regexp.escape(key)}' contains unsupported characters}) end [ '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '+', '`', '=', - '{', '}', '[', ']', '|', '\\', ';', "'", '"', '<', '>', ',', '?' - ].each do |bad_char| - it "should fail when key contains disallowed special character '#{bad_char}'" do + '{', '}', '[', ']', '|', '\\', ';', "'", '"', '<', '>', ',', '?'].each do |bad_char| + it "fails when key contains disallowed special character '#{bad_char}'" do key = 'key' + bad_char is_expected.to run.with_params(key).and_raise_error(ArgumentError, - /key '#{Regexp.escape(key)}' contains unsupported characters/) + %r{key '#{Regexp.escape(key)}' contains unsupported characters}) end end - it 'should fail when key contains disallowed /./ sequence' do + it 'fails when key contains disallowed /./ sequence' do key = 'looks/like/an/./unexpanded/linux/path' is_expected.to run.with_params(key).and_raise_error(ArgumentError, - /key '#{Regexp.escape(key)}' contains disallowed '\/\.\/' or '\/\.\.\/' sequence/) + %r{key '#{Regexp.escape(key)}' contains disallowed '/\./' or '/\.\./' sequence}) end - it 'should fail when key contains disallowed /../ sequence' do + it 'fails when key contains disallowed /../ sequence' do key = 'looks/like/another/../unexpanded/linux/path' is_expected.to run.with_params(key).and_raise_error(ArgumentError, - /key '#{Regexp.escape(key)}' contains disallowed '\/\.\/' or '\/\.\.\/' sequence/) + %r{key '#{Regexp.escape(key)}' contains disallowed '/\./' or '/\.\./' sequence}) end end - end diff --git a/spec/functions/simpkv/support/load_spec.rb b/spec/functions/simpkv/support/load_spec.rb index 9bfc090..ac0a262 100644 --- a/spec/functions/simpkv/support/load_spec.rb +++ b/spec/functions/simpkv/support/load_spec.rb @@ -1,43 +1,40 @@ require 'spec_helper' describe 'simpkv::support::load' do + it 'adds simpkv accessors to catalog instance at global scope when none exists' do + is_expected.to run.with_params - it 'should add simpkv accessors to catalog instance at global scope when none exists' do - is_expected.to run.with_params() - - expect( catalogue.respond_to?(:simpkv) ).to be true - expect( catalogue.respond_to?(:simpkv=) ).to be true + expect(catalogue.respond_to?(:simpkv)).to be true + expect(catalogue.respond_to?(:simpkv=)).to be true [ :delete, :deletetree, :exists, :get, :list, - :put - ].each do |api_method| - expect( catalogue.simpkv.respond_to?(api_method) ).to be true + :put].each do |api_method| + expect(catalogue.simpkv.respond_to?(api_method)).to be true end end - it 'should use existing simpkv adapter instance when catalog has simpkv accessors' do - is_expected.to run.with_params() + it 'uses existing simpkv adapter instance when catalog has simpkv accessors' do + is_expected.to run.with_params simpkv_class_id1 = catalogue.simpkv.to_s - is_expected.to run.with_params() + is_expected.to run.with_params simpkv_class_id2 = catalogue.simpkv.to_s expect(simpkv_class_id1).to eq simpkv_class_id2 end - it 'should fail when simpkv.rb does not exist' do + it 'fails when simpkv.rb does not exist' do allow(File).to receive(:exist?).with(any_args).and_call_original - allow(File).to receive(:exist?).with(/simpkv\/loader.rb/).and_return(false) - is_expected.to run.with_params().and_raise_error(LoadError, /simpkv Internal Error: unable to load .* File not found/) + allow(File).to receive(:exist?).with(%r{simpkv/loader.rb}).and_return(false) + is_expected.to run.with_params.and_raise_error(LoadError, %r{simpkv Internal Error: unable to load .* File not found}) end - it 'should fail when simpkv.rb is malformed Ruby' do + it 'fails when simpkv.rb is malformed Ruby' do allow(File).to receive(:read).with(any_args).and_call_original - allow(File).to receive(:read).with(/simpkv\/loader.rb/).and_return("if true\n") - is_expected.to run.with_params().and_raise_error(LoadError, /simpkv Internal Error: unable to load .* syntax error/) - end - + allow(File).to receive(:read).with(%r{simpkv/loader.rb}).and_return("if true\n") + is_expected.to run.with_params.and_raise_error(LoadError, %r{simpkv Internal Error: unable to load .* syntax error}) + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b9f548b..915783e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # # ------------------------------------------------------------------------------ # NOTICE: **This file is maintained with puppetsync** @@ -93,7 +94,7 @@ def set_hieradata(hieradata) # If nothing else... c.default_facts = { production: { - #:fqdn => 'production.rspec.test.localdomain', + # :fqdn => 'production.rspec.test.localdomain', path: '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin', concat_basedir: '/tmp' } @@ -154,9 +155,9 @@ def set_hieradata(hieradata) # sanitize hieradata if defined?(hieradata) - set_hieradata(hieradata.gsub(':', '_')) + set_hieradata(hieradata.tr(':', '_')) elsif defined?(class_name) - set_hieradata(class_name.gsub(':', '_')) + set_hieradata(class_name.tr(':', '_')) end end @@ -168,9 +169,7 @@ def set_hieradata(hieradata) end Dir.glob("#{RSpec.configuration.module_path}/*").each do |dir| - begin - Pathname.new(dir).realpath - rescue StandardError - raise "ERROR: The module '#{dir}' is not installed. Tests cannot continue." - end + Pathname.new(dir).realpath +rescue StandardError + raise "ERROR: The module '#{dir}' is not installed. Tests cannot continue." end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index e1dcb84..5fe6ada 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -23,7 +23,6 @@ end end - RSpec.configure do |c| # ensure that environment OS is ready on each host fix_errata_on hosts @@ -37,29 +36,25 @@ # Configure all nodes in nodeset c.before :suite do + # Install modules and dependencies from spec/fixtures/modules + copy_fixture_modules_to(hosts) begin - # Install modules and dependencies from spec/fixtures/modules - copy_fixture_modules_to( hosts ) - begin - server = only_host_with_role(hosts, 'server') - rescue ArgumentError =>e - server = only_host_with_role(hosts, 'default') - end - - # Generate and install PKI certificates on each SUT - Dir.mktmpdir do |cert_dir| - run_fake_pki_ca_on(server, hosts, cert_dir ) - hosts.each{ |sut| copy_pki_to( sut, cert_dir, '/etc/pki/simp-testing' )} - end + server = only_host_with_role(hosts, 'server') + rescue ArgumentError => e + server = only_host_with_role(hosts, 'default') + end - # add PKI keys - copy_keydist_to(server) - rescue StandardError, ScriptError => e - if ENV['PRY'] - require 'pry'; binding.pry - else - raise e - end + # Generate and install PKI certificates on each SUT + Dir.mktmpdir do |cert_dir| + run_fake_pki_ca_on(server, hosts, cert_dir) + hosts.each { |sut| copy_pki_to(sut, cert_dir, '/etc/pki/simp-testing') } end + + # add PKI keys + copy_keydist_to(server) + rescue StandardError, ScriptError => e + raise e unless ENV['PRY'] + require 'pry' + binding.pry end end diff --git a/spec/support/modules/test_plugins1/lib/puppet_x/simpkv/failer_plugin.rb b/spec/support/modules/test_plugins1/lib/puppet_x/simpkv/failer_plugin.rb index 9651d4b..1e44ff9 100644 --- a/spec/support/modules/test_plugins1/lib/puppet_x/simpkv/failer_plugin.rb +++ b/spec/support/modules/test_plugins1/lib/puppet_x/simpkv/failer_plugin.rb @@ -5,8 +5,7 @@ # Each plugin **MUST** be an anonymous class accessible only through # a `plugin_class` local variable. -plugin_class = Class.new do - +Class.new do ###### Public Plugin API ###### # Construct an instance of this plugin setting its instance name @@ -39,10 +38,7 @@ def configure(options) end # @return unique identifier assigned to this plugin instance - def name - @name - end - + attr_reader :name # Deletes a `key` from the configured backend. # @@ -52,7 +48,7 @@ def name # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def delete(key) + def delete(_key) raise('delete catastrophic failure') end @@ -64,7 +60,7 @@ def delete(key) # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def deletetree(keydir) + def deletetree(_keydir) raise('deletetree catastrophic failure') end @@ -78,7 +74,7 @@ def deletetree(keydir) # * :err_msg - String. Explanatory text when status could not be # determined; nil otherwise. # - def exists(key) + def exists(_key) raise('exists catastrophic failure') end @@ -91,7 +87,7 @@ def exists(key) # be retrieved # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def get(key) + def get(_key) raise('get catastrophic failure') end @@ -106,7 +102,7 @@ def get(key) # retrieval operation failed # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def list(keydir) + def list(_keydir) raise('list catastrophic failure') end @@ -119,8 +115,7 @@ def list(keydir) # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def put(key, value) + def put(_key, _value) raise('put catastrophic failure') end - end diff --git a/spec/support/modules/test_plugins2/lib/puppet_x/simpkv/failer_plugin.rb b/spec/support/modules/test_plugins2/lib/puppet_x/simpkv/failer_plugin.rb index a94ec4f..f12b86d 100644 --- a/spec/support/modules/test_plugins2/lib/puppet_x/simpkv/failer_plugin.rb +++ b/spec/support/modules/test_plugins2/lib/puppet_x/simpkv/failer_plugin.rb @@ -4,8 +4,7 @@ # Each plugin **MUST** be an anonymous class accessible only through # a `plugin_class` local variable. -plugin_class = Class.new do - +Class.new do ###### Public Plugin API ###### # Construct an instance of this plugin setting its instance name @@ -38,10 +37,7 @@ def configure(options) end # @return unique identifier assigned to this plugin instance - def name - @name - end - + attr_reader :name # Deletes a `key` from the configured backend. # @@ -51,7 +47,7 @@ def name # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def delete(key) + def delete(_key) raise('Catastrophic failure for delete') end @@ -63,7 +59,7 @@ def delete(key) # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def deletetree(keydir) + def deletetree(_keydir) raise('Catastrophic failure for deletetree') end @@ -77,7 +73,7 @@ def deletetree(keydir) # * :err_msg - String. Explanatory text when status could not be # determined; nil otherwise. # - def exists(key) + def exists(_key) raise('Catastrophic failure for exists') end @@ -90,7 +86,7 @@ def exists(key) # be retrieved # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def get(key) + def get(_key) raise('Catastrophic failure for get') end @@ -105,7 +101,7 @@ def get(key) # retrieval operation failed # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def list(keydir) + def list(_keydir) raise('Catastrophic failure for list') end @@ -118,8 +114,7 @@ def list(keydir) # * :result - Boolean indicating whether operation succeeded # * :err_msg - String. Explanatory text upon failure; nil otherwise. # - def put(key, value) + def put(_key, _value) raise('Catastrophic failure for put') end - end diff --git a/spec/unit/puppet_x/simpkv/file_plugin_spec.rb b/spec/unit/puppet_x/simpkv/file_plugin_spec.rb index 6b588d6..9879fe1 100644 --- a/spec/unit/puppet_x/simpkv/file_plugin_spec.rb +++ b/spec/unit/puppet_x/simpkv/file_plugin_spec.rb @@ -11,12 +11,12 @@ obj = Object.new obj.instance_eval(File.read(plugin_file), plugin_file) -def locked_key_file_operation(root_path, key, value, &block) +def locked_key_file_operation(root_path, key, value) # create the file to be locked key_file = File.join(root_path, key) File.open(key_file, 'w') { |file| file.write(value) } - locker_thread = nil # thread that will lock the file + locker_thread = nil # thread that will lock the file mutex = Mutex.new locked = ConditionVariable.new begin @@ -34,13 +34,11 @@ def locked_key_file_operation(root_path, key, value, &block) puts ' >> Lock released with close' end - # wait for the thread to signal the lock has taken place mutex.synchronize { locked.wait(mutex) } # exercise the accessor - block.call - + yield ensure if locker_thread # wait until thread has paused @@ -51,7 +49,6 @@ def locked_key_file_operation(root_path, key, value, &block) locker_thread.join end end - end describe 'simpkv file plugin anonymous class' do @@ -61,7 +58,7 @@ def locked_key_file_operation(root_path, key, value, &block) @options = { 'backend' => 'test', 'backends' => { - 'test' => { + 'test' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path, @@ -88,96 +85,92 @@ def locked_key_file_operation(root_path, key, value, &block) end context 'success cases' do - it 'should create the root_path tree when none exists' do - expect{ @plugin.configure(@options) }.to_not raise_error - expect( Dir.exist?(@root_path) ).to be true - expect( Dir.exist?(File.join(@root_path, 'globals')) ).to be true - expect( Dir.exist?(File.join(@root_path, 'environments')) ).to be true + it 'creates the root_path tree when none exists' do + expect { @plugin.configure(@options) }.not_to raise_error + expect(Dir.exist?(@root_path)).to be true + expect(Dir.exist?(File.join(@root_path, 'globals'))).to be true + expect(Dir.exist?(File.join(@root_path, 'environments'))).to be true end - it 'should not fail if the root_path tree exists' do + it 'does not fail if the root_path tree exists' do FileUtils.mkdir_p(@root_path) - expect{ @plugin.configure(@options) }.to_not raise_error + expect { @plugin.configure(@options) }.not_to raise_error end end context 'error cases' do - it 'should fail when options is not a Hash' do - expect { @plugin.configure('oops') }. - to raise_error(/Plugin misconfigured/) + it 'fails when options is not a Hash' do + expect { @plugin.configure('oops') } + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when options missing 'backend' key" do - expect { @plugin.configure({}) }. - to raise_error(/Plugin misconfigured/) + it "fails when options missing 'backend' key" do + expect { @plugin.configure({}) } + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when options missing 'backends' key" do - options = { - 'backend' => 'test' - } - expect { @plugin.configure({}) }. - to raise_error(/Plugin misconfigured: {}/) + it "fails when options missing 'backends' key" do + expect { @plugin.configure({}) } + .to raise_error(%r{Plugin misconfigured: {}}) end - it "should fail when options 'backends' key is not a Hash" do + it "fails when options 'backends' key is not a Hash" do options = { 'backend' => 'test', 'backends' => 'oops' } - expect { @plugin.configure(options) }. - to raise_error(/Plugin misconfigured/) + expect { @plugin.configure(options) } + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when options 'backends' does not have the specified backend" do + it "fails when options 'backends' does not have the specified backend" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'} + 'test1' => { 'id' => 'test', 'type' => 'consul' } } } - expect { @plugin.configure(options) }. - to raise_error(/Plugin misconfigured/) + expect { @plugin.configure(options) } + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when the correct 'backends' element has no 'id' key" do + it "fails when the correct 'backends' element has no 'id' key" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'}, + 'test1' => { 'id' => 'test', 'type' => 'consul' }, 'test' => {} } } - expect { @plugin.configure(options) }. - to raise_error(/Plugin misconfigured/) + expect { @plugin.configure(options) } + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when the correct 'backends' element has no 'type' key" do + it "fails when the correct 'backends' element has no 'type' key" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'}, + 'test1' => { 'id' => 'test', 'type' => 'consul' }, 'test' => { 'id' => 'test' } } } - expect { @plugin.configure(options) }. - to raise_error(/Plugin misconfigured/) + expect { @plugin.configure(options) } + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when the correct 'backends' element has wrong 'type' value" do + it "fails when the correct 'backends' element has wrong 'type' value" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'}, + 'test1' => { 'id' => 'test', 'type' => 'consul' }, 'test' => { 'id' => 'test', 'type' => 'filex' } } } - expect { @plugin.configure(options) }. - to raise_error(/Plugin misconfigured/) + expect { @plugin.configure(options) } + .to raise_error(%r{Plugin misconfigured}) end - - it 'should fail when configured root path cannot be created' do + it 'fails when configured root path cannot be created' do options = { 'backend' => 'test', 'backends' => { @@ -189,12 +182,12 @@ def locked_key_file_operation(root_path, key, value, &block) } } - allow(Dir).to receive(:exist?).with('/can/not/be/created').and_return( false ) - allow(FileUtils).to receive(:mkdir_p).with('/can/not/be/created'). - and_raise(Errno::EACCES, 'Permission denied') + allow(Dir).to receive(:exist?).with('/can/not/be/created').and_return(false) + allow(FileUtils).to receive(:mkdir_p).with('/can/not/be/created') + .and_raise(Errno::EACCES, 'Permission denied') - expect { @plugin.configure(options) }. - to raise_error(/Unable to create configured root path/) + expect { @plugin.configure(options) } + .to raise_error(%r{Unable to create configured root path}) end end end @@ -206,256 +199,253 @@ def locked_key_file_operation(root_path, key, value, &block) end describe 'delete' do - it 'should return :result=true when the key file does not exist' do - expect( @plugin.delete('does/not/exist/key')[:result] ).to be true - expect( @plugin.delete('does/not/exist/key')[:err_msg] ).to be_nil + it 'returns :result=true when the key file does not exist' do + expect(@plugin.delete('does/not/exist/key')[:result]).to be true + expect(@plugin.delete('does/not/exist/key')[:err_msg]).to be_nil end - it 'should return :result=true when the key file can be deleted' do + it 'returns :result=true when the key file can be deleted' do key_file = File.join(@root_path, 'key1') FileUtils.touch(key_file) - expect( @plugin.delete('key1')[:result] ).to be true - expect( @plugin.delete('key1')[:err_msg] ).to be_nil - expect( File.exist?(key_file) ).to be false + expect(@plugin.delete('key1')[:result]).to be true + expect(@plugin.delete('key1')[:err_msg]).to be_nil + expect(File.exist?(key_file)).to be false end - it 'should return :result=false and an :err_msg when the key is a dir not a file' do + it 'returns :result=false and an :err_msg when the key is a dir not a file' do keydir = 'keydir' FileUtils.mkdir_p(File.join(@root_path, keydir)) result = @plugin.delete(keydir) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/Key specifies a folder/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{Key specifies a folder}) end - it 'should return :result=false and an :err_msg when the key file delete fails' do + it 'returns :result=false and an :err_msg when the key file delete fails' do key_file = File.join(@root_path, 'key1') - allow(File).to receive(:unlink).with(key_file). - and_raise(Errno::EACCES, 'Permission denied') + allow(File).to receive(:unlink).with(key_file) + .and_raise(Errno::EACCES, 'Permission denied') result = @plugin.delete('key1') - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/Delete of '.*' failed:/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{Delete of '.*' failed:}) end end describe 'deletetree' do - it 'should return :result=true when the key folder does not exist' do - expect( @plugin.deletetree('does/not/exist/folder')[:result] ).to be true - expect( @plugin.deletetree('does/not/exist/folder')[:err_msg] ).to be_nil + it 'returns :result=true when the key folder does not exist' do + expect(@plugin.deletetree('does/not/exist/folder')[:result]).to be true + expect(@plugin.deletetree('does/not/exist/folder')[:err_msg]).to be_nil end - it 'should return :result=true when the key folder can be deleted' do + it 'returns :result=true when the key folder can be deleted' do key_dir = File.join(@root_path, 'production') FileUtils.mkdir_p(key_dir) FileUtils.touch(File.join(key_dir, 'key1')) FileUtils.touch(File.join(key_dir, 'key2')) - expect( @plugin.deletetree('production')[:result] ).to be true - expect( @plugin.deletetree('production')[:err_msg] ).to be_nil - expect( Dir.exist?(key_dir) ).to be false + expect(@plugin.deletetree('production')[:result]).to be true + expect(@plugin.deletetree('production')[:err_msg]).to be_nil + expect(Dir.exist?(key_dir)).to be false end - it 'should return :result=false and an :err_msg when the key folder delete fails' do + it 'returns :result=false and an :err_msg when the key folder delete fails' do key_dir = File.join(@root_path, 'production/gen_passwd') FileUtils.mkdir_p(key_dir) - allow(FileUtils).to receive(:rm_r).with(key_dir). - and_raise(Errno::EACCES, 'Permission denied') + allow(FileUtils).to receive(:rm_r).with(key_dir) + .and_raise(Errno::EACCES, 'Permission denied') result = @plugin.deletetree('production/gen_passwd') - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/Folder delete of '.*' failed:/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{Folder delete of '.*' failed:}) end end describe 'exists' do - it 'should return :result=false when the key does not exist or is inaccessible' do + it 'returns :result=false when the key does not exist or is inaccessible' do result = @plugin.exists('does/not/exist/key') - expect( result[:result] ).to be false - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to be false + expect(result[:err_msg]).to be_nil end - it 'should return :result=true when the key file exists and is accessible' do + it 'returns :result=true when the key file exists and is accessible' do key_file = File.join(@root_path, 'key1') FileUtils.touch(key_file) result = @plugin.exists('key1') - expect( result[:result] ).to be true - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to be true + expect(result[:err_msg]).to be_nil end - it 'should return :result=true when the key folder exists and is accessible' do + it 'returns :result=true when the key folder exists and is accessible' do key_folder = File.join(@root_path, 'app1') FileUtils.mkdir_p(key_folder) result = @plugin.exists('app1') - expect( result[:result] ).to be true - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to be true + expect(result[:err_msg]).to be_nil end end describe 'get' do - it 'should return set :result when the key file exists and is accessible' do + it 'returns set :result when the key file exists and is accessible' do key_file = File.join(@root_path, 'key1') value = 'value for key1' File.open(key_file, 'w') { |file| file.write(value) } result = @plugin.get('key1') - expect( result[:result] ).to eq value - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to eq value + expect(result[:err_msg]).to be_nil end - it 'should return unset :result and an :err_msg when the key is a dir not a file' do + it 'returns unset :result and an :err_msg when the key is a dir not a file' do keydir = 'keydir' FileUtils.mkdir_p(File.join(@root_path, keydir)) result = @plugin.get(keydir) - expect( result[:result] ).to be_nil - expect( result[:err_msg] ).to match(/Key specifies a folder/) + expect(result[:result]).to be_nil + expect(result[:err_msg]).to match(%r{Key specifies a folder}) end - it 'should return an unset :result and an :err_msg when the key file does not exist' do + it 'returns an unset :result and an :err_msg when the key file does not exist' do result = @plugin.get('does/not/exist/key') - expect( result[:result] ).to be_nil - expect( result[:err_msg] ).to match(/Key not found/) + expect(result[:result]).to be_nil + expect(result[:err_msg]).to match(%r{Key not found}) end - it 'should return an unset :result and an :err_msg when times out waiting for key lock' do + it 'returns an unset :result and an :err_msg when times out waiting for key lock' do key = 'key1' value = 'value for key1' locked_key_file_operation(@root_path, key, value) do puts " >> Executing plugin get() for '#{key}'" result = @plugin.get(key) - expect( result[:result] ).to be_nil - expect( result[:err_msg] ).to match /Timed out waiting for lock of key file/ + expect(result[:result]).to be_nil + expect(result[:err_msg]).to match(%r{Timed out waiting for lock of key file}) end # just to be sure lock is appropriately cleared... result = @plugin.get(key) - expect( result[:result] ).to_not be_nil - expect( result[:err_msg] ).to be_nil + expect(result[:result]).not_to be_nil + expect(result[:err_msg]).to be_nil end - it 'should return an unset :result and an :err_msg when the key file exists but is not accessible' do + it 'returns an unset :result and an :err_msg when the key file exists but is not accessible' do # mock a key file that is inaccessible key_file = File.join(@root_path, 'production/key1') - allow(File).to receive(:open).with(key_file, 'r'). - and_raise(Errno::EACCES, 'Permission denied') + allow(File).to receive(:open).with(key_file, 'r') + .and_raise(Errno::EACCES, 'Permission denied') result = @plugin.get('production/key1') - expect( result[:result] ).to be_nil - expect( result[:err_msg] ).to match(/Cannot read '#{Regexp.escape(key_file)}'/) + expect(result[:result]).to be_nil + expect(result[:err_msg]).to match(%r{Cannot read '#{Regexp.escape(key_file)}'}) end end # using plugin's put() in this test, because it is fully tested below describe 'list' do - - it 'should return an empty :result when key folder is empty' do + it 'returns an empty :result when key folder is empty' do key_dir = File.join(@root_path, 'production') FileUtils.mkdir_p(key_dir) result = @plugin.list('production') - expect( result[:result] ).to eq({ :keys => {}, :folders => []}) - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to eq({ keys: {}, folders: [] }) + expect(result[:err_msg]).to be_nil end - it 'should return full list of key/value pairs and sub-folders in :result when key folder content is accessible' do + it 'returns full list of key/value pairs and sub-folders in :result when key folder content is accessible' do expected = { - :keys => { + keys: { 'key1' => 'value for key1', 'key2' => 'value for key2', 'key3' => 'value for key3' }, - :folders => [ + folders: [ 'app1', - 'app2' + 'app2', ] } - expected[:keys].each { |key,value| @plugin.put("production/#{key}", value) } + expected[:keys].each { |key, value| @plugin.put("production/#{key}", value) } expected[:folders].each { |folder| @plugin.put("production/#{folder}/key", "#{folder}/key value") } result = @plugin.list('production') - expect( result[:result] ).to eq(expected) - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to eq(expected) + expect(result[:err_msg]).to be_nil end - it 'should return partial list of key/value pairs in :result when some key folder content is not accessible' do + it 'returns partial list of key/value pairs in :result when some key folder content is not accessible' do expected = { - :keys => { + keys: { 'key1' => 'value for key1', 'key3' => 'value for key3' }, - :folders => [] + folders: [] } - expected[:keys].each { |key,value| @plugin.put("production/#{key}", value) } + expected[:keys].each { |key, value| @plugin.put("production/#{key}", value) } # create a file for 'production/key2', but make it inaccessible via a lock locked_key_file_operation(@root_path, 'production/key2', 'value for key2') do puts " >> Executing plugin list() for 'production'" result = @plugin.list('production') - expect( result[:result] ).to eq(expected) - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to eq(expected) + expect(result[:err_msg]).to be_nil end - end - it 'should return an unset :result and an :err_msg when key folder does not exist or is inaccessible' do + it 'returns an unset :result and an :err_msg when key folder does not exist or is inaccessible' do result = @plugin.list('production') - expect( result[:result] ).to be_nil - expect( result[:err_msg] ).to match(/Key folder '.*' not found/) + expect(result[:result]).to be_nil + expect(result[:err_msg]).to match(%r{Key folder '.*' not found}) end end describe 'name' do - it 'should return configured name' do - expect( @plugin.name ).to eq @plugin_name + it 'returns configured name' do + expect(@plugin.name).to eq @plugin_name end end # using plugin's get() in this test, because it has already been # fully tested describe 'put' do - it 'should return :result=true when the key file does not exist for a simple key' do + it 'returns :result=true when the key file does not exist for a simple key' do key = 'key1' value = 'value for key1' result = @plugin.put(key, value) - expect( result[:result] ).to be true - expect( result[:err_msg] ).to be_nil - expect( @plugin.get(key)[:result] ).to eq value + expect(result[:result]).to be true + expect(result[:err_msg]).to be_nil + expect(@plugin.get(key)[:result]).to eq value key_file = File.join(@root_path, key) - expect( File.stat(key_file).mode & 0777 ).to eq 0660 + expect(File.stat(key_file).mode & 0o777).to eq 0o660 end - it 'should return :result=true when the key file does not exist for a complex key' do + it 'returns :result=true when the key file does not exist for a complex key' do key = 'production/gen_passwd/key1' value = 'value for key1' result = @plugin.put(key, value) - expect( result[:result] ).to be true - expect( result[:err_msg] ).to be_nil - expect( @plugin.get(key)[:result] ).to eq value + expect(result[:result]).to be true + expect(result[:err_msg]).to be_nil + expect(@plugin.get(key)[:result]).to eq value key_file = File.join(@root_path, key) - expect( File.stat(key_file).mode & 0777 ).to eq 0660 - expect( File.stat(File.join(@root_path, 'production')).mode & 0777 ).to eq 0770 - expect( File.stat(File.join(@root_path, 'production', 'gen_passwd')).mode & 0777 ).to eq 0770 + expect(File.stat(key_file).mode & 0o777).to eq 0o660 + expect(File.stat(File.join(@root_path, 'production')).mode & 0o777).to eq 0o770 + expect(File.stat(File.join(@root_path, 'production', 'gen_passwd')).mode & 0o777).to eq 0o770 end - it 'should fix permissions and return :result=true when the key file exists '\ - 'and is owned by user' do + it 'fixes permissions and return :result=true when the key file exists and is owned by user' do key = 'key1' key_file = File.join(@root_path, key) FileUtils.touch(key_file) - FileUtils.chmod(0640, key_file) + FileUtils.chmod(0o640, key_file) value1 = 'value for key1 which is longer than second value' value2 = 'second value for key1' value3 = 'third value for key1 which is longer than second value' @plugin.put(key, value1) - expect( File.stat(key_file).mode & 0777 ).to eq 0660 + expect(File.stat(key_file).mode & 0o777).to eq 0o660 result = @plugin.put(key, value2) - expect( result[:result] ).to be true - expect( result[:err_msg] ).to be_nil - expect( @plugin.get(key)[:result] ).to eq value2 + expect(result[:result]).to be true + expect(result[:err_msg]).to be_nil + expect(@plugin.get(key)[:result]).to eq value2 result = @plugin.put(key, value3) - expect( result[:result] ).to be true - expect( result[:err_msg] ).to be_nil - expect( @plugin.get(key)[:result] ).to eq value3 + expect(result[:result]).to be true + expect(result[:err_msg]).to be_nil + expect(@plugin.get(key)[:result]).to eq value3 end - it 'should return :result=false and an :err_msg when times out waiting for key lock' do + it 'returns :result=false and an :err_msg when times out waiting for key lock' do key = 'key1' value1 = 'first value for key1' value2 = 'second value for key1' @@ -463,24 +453,24 @@ def locked_key_file_operation(root_path, key, value, &block) locked_key_file_operation(@root_path, key, value1) do puts " >> Executing plugin.put() for '#{key}'" result = @plugin.put(key, value2) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match /Timed out waiting for lock of key file/ + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{Timed out waiting for lock of key file}) end # just to be sure lock is appropriately cleared... result = @plugin.put(key, value2) - expect( result[:result] ).to be true - expect( result[:err_msg] ).to be_nil + expect(result[:result]).to be true + expect(result[:err_msg]).to be_nil end - it 'should return :result=false an an :err_msg when the key file cannot be created' do + it 'returns :result=false an an :err_msg when the key file cannot be created' do key_file = File.join(@root_path, 'key') - allow(File).to receive(:open).with(key_file, File::RDWR|File::CREAT). - and_raise(Errno::EACCES, 'Permission denied') + allow(File).to receive(:open).with(key_file, File::RDWR | File::CREAT) + .and_raise(Errno::EACCES, 'Permission denied') result = @plugin.put('key', 'value') - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/Cannot write to '#{Regexp.escape(key_file)}'/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{Cannot write to '#{Regexp.escape(key_file)}'}) end end end @@ -492,39 +482,39 @@ def locked_key_file_operation(root_path, key, value, &block) end describe 'ensure_folder_path' do - it 'should create folder path with correct permissions when not present' do + it 'creates folder path with correct permissions when not present' do @plugin.ensure_folder_path('some/folder/path') [ File.join(@root_path, 'some'), File.join(@root_path, 'some', 'folder'), - File.join(@root_path, 'some', 'folder', 'path') + File.join(@root_path, 'some', 'folder', 'path'), ].each do |path| - expect( Dir.exist?(path) ).to be true + expect(Dir.exist?(path)).to be true stat = File.stat(path) - expect( stat.mode & 00777 ). to eq 0770 + expect(stat.mode & 0o0777). to eq 0o770 end end - it 'should create missing subdirs of folder path' do + it 'creates missing subdirs of folder path' do FileUtils.mkdir(File.join(@root_path, 'some')) @plugin.ensure_folder_path('some/folder/path') [ File.join(@root_path, 'some', 'folder'), - File.join(@root_path, 'some', 'folder', 'path') + File.join(@root_path, 'some', 'folder', 'path'), ].each do |path| - expect( Dir.exist?(path) ).to be true + expect(Dir.exist?(path)).to be true stat = File.stat(path) - expect( stat.mode & 00777 ). to eq 0770 + expect(stat.mode & 0o0777). to eq 0o770 end end - it 'should call verify_dir_access on existing subdirs of folder path' do + it 'calls verify_dir_access on existing subdirs of folder path' do FileUtils.mkdir_p(File.join(@root_path, 'some', 'folder', 'path')) allow(@plugin).to receive(:verify_dir_access).with(any_args).and_call_original [ 'some', File.join('some', 'folder'), - File.join('some', 'folder', 'path') + File.join('some', 'folder', 'path'), ].each do |path| expect(@plugin).to receive(:verify_dir_access).with(path).and_return(nil) end @@ -534,41 +524,44 @@ def locked_key_file_operation(root_path, key, value, &block) end describe 'ensure_root_path' do - let(:options) { { - 'backend' => 'test', + let(:options) do + { + 'backend' => 'test', 'backends' => { - 'test' => { + 'test' => { 'id' => 'test', 'type' => 'file' } } - } } + } + end context 'root_path config present' do - it 'should return configured root_path and call verify_dir_access when root_path exists' do + it 'returns configured root_path and call verify_dir_access when root_path exists' do # @root_path was already created when @plugin was constructed expect(@plugin).to receive(:verify_dir_access).with(@root_path).and_return(nil) - expect( @plugin.ensure_root_path(@options) ).to eq (@root_path) + expect(@plugin.ensure_root_path(@options)).to eq(@root_path) end - it 'should return configured root_path and create the paths when it does not exists' do + it 'returns configured root_path and create the paths when it does not exists' do root_path = File.join(@tmpdir, 'file') opts = options.dup opts['backends']['test']['root_path'] = root_path - expect( @plugin.ensure_root_path(opts) ).to eq (root_path) - expect( Dir.exist?(root_path) ).to be true - expect( File.stat(root_path).mode & 0777 ).to eq 0770 + expect(@plugin.ensure_root_path(opts)).to eq(root_path) + expect(Dir.exist?(root_path)).to be true + expect(File.stat(root_path).mode & 0o777).to eq 0o770 end - it 'should fail when configured root_path does not exist and cannot be created' do + it 'fails when configured root_path does not exist and cannot be created' do root_path = File.join(@tmpdir, 'file', 'test') opts = options.dup opts['backends']['test']['root_path'] = root_path allow(FileUtils).to receive(:mkdir_p).with(root_path) - .and_raise(Errno::EACCES, 'Permission denied') + .and_raise(Errno::EACCES, 'Permission denied') - expect{ @plugin.ensure_root_path(opts) }.to raise_error( - /Unable to create configured root path/) + expect { @plugin.ensure_root_path(opts) }.to raise_error( + %r{Unable to create configured root path}, + ) end end @@ -578,113 +571,114 @@ def locked_key_file_operation(root_path, key, value, &block) @default_path = File.join('/', 'var', 'simp', 'simpkv', @plugin_name) @fallback_path = File.join(@vardir, 'simp', 'simpkv', @plugin_name) allow(Puppet).to receive(:settings).with(any_args).and_call_original - allow(Puppet).to receive_message_chain(:settings,:[]).with(:vardir).and_return(@vardir) + allow(Puppet).to receive_message_chain(:settings, :[]).with(:vardir).and_return(@vardir) end - it 'should return default path in /var/simp and call verify_dir_access when path exists' do + it 'returns default path in /var/simp and call verify_dir_access when path exists' do expect(Dir).to receive(:exist?).with(@default_path).and_return(true).twice expect(@plugin).to receive(:verify_dir_access).with(@default_path).and_return(nil) - expect( @plugin.ensure_root_path(options) ).to eq (@default_path) + expect(@plugin.ensure_root_path(options)).to eq(@default_path) end - it 'should return fallback path in Puppet vardir and call '\ - 'verify_dir_access when default path does not exist but fallback path does' do + it 'returns fallback path in Puppet vardir and call verify_dir_access when default path does not exist but fallback path does' do expect(Dir).to receive(:exist?).with(@default_path).and_return(false) expect(Dir).to receive(:exist?).with(@fallback_path).and_return(true).twice expect(@plugin).to receive(:verify_dir_access).with(@fallback_path).and_return(nil) - expect( @plugin.ensure_root_path(options) ).to eq (@fallback_path) + expect(@plugin.ensure_root_path(options)).to eq(@fallback_path) end - it 'should create and return default path when neither default path exists' do + it 'creates and return default path when neither default path exists' do expect(Dir).to receive(:exist?).with(@default_path).and_return(false).twice expect(Dir).to receive(:exist?).with(@fallback_path).and_return(false) expect(FileUtils).to receive(:mkdir_p).with(@default_path).and_return(nil) - expect(FileUtils).to receive(:chmod).with(0770, @default_path).and_return(nil) - expect( @plugin.ensure_root_path(options) ).to eq (@default_path) + expect(FileUtils).to receive(:chmod).with(0o770, @default_path).and_return(nil) + expect(@plugin.ensure_root_path(options)).to eq(@default_path) end - it 'should create and return fallback path when neither default path exists '\ - 'and primary default cannot be created' do + it 'creates and return fallback path when neither default path exists and primary default cannot be created' do expect(Dir).to receive(:exist?).with(@default_path).and_return(false).twice expect(Dir).to receive(:exist?).with(@fallback_path).and_return(false) expect(FileUtils).to receive(:mkdir_p).with(@default_path) - .and_raise(Errno::EACCES, 'Permission denied') + .and_raise(Errno::EACCES, 'Permission denied') - expect( @plugin.ensure_root_path(options) ).to eq (@fallback_path) - expect( Dir.exist?(@fallback_path) ).to be true - expect( File.stat(@fallback_path).mode & 0777 ).to eq 0770 + expect(@plugin.ensure_root_path(options)).to eq(@fallback_path) + expect(Dir.exist?(@fallback_path)).to be true + expect(File.stat(@fallback_path).mode & 0o777).to eq 0o770 end - it 'should fail when neither default path exists and neither can be created' do + it 'fails when neither default path exists and neither can be created' do expect(Dir).to receive(:exist?).with(@default_path).and_return(false).twice expect(Dir).to receive(:exist?).with(@fallback_path).and_return(false) expect(FileUtils).to receive(:mkdir_p).with(@default_path) - .and_raise(Errno::EACCES, 'Permission denied') + .and_raise(Errno::EACCES, 'Permission denied') expect(FileUtils).to receive(:mkdir_p).with(@fallback_path) - .and_raise(Errno::EACCES, 'Permission denied') + .and_raise(Errno::EACCES, 'Permission denied') - expect{ @plugin.ensure_root_path(options) }.to raise_error( - /Unable to create default root path/) + expect { @plugin.ensure_root_path(options) }.to raise_error( + %r{Unable to create default root path}, + ) end end end describe 'verify_dir_access' do let(:dir) { 'some/folder/path' } + before :each do allow(Dir).to receive(:entries).with(any_args).and_call_original allow(File).to receive(:stat).with(any_args).and_call_original end - it 'should succeed when process user owns directory can read and modify it' do + it 'succeeds when process user owns directory can read and modify it' do expect(Dir).to receive(:entries).with(dir).and_return([]) mock_stat = OpenStruct.new mock_stat.uid = Process.uid mock_stat.gid = Process.gid - mock_stat.mode = 00750 + mock_stat.mode = 0o0750 expect(File).to receive(:stat).with(dir).and_return(mock_stat) - expect(FileUtils).to receive(:chmod).with(0770, dir).and_return(nil) + expect(FileUtils).to receive(:chmod).with(0o770, dir).and_return(nil) - expect{ @plugin.verify_dir_access(dir) }.to_not raise_error + expect { @plugin.verify_dir_access(dir) }.not_to raise_error end - it 'should succeed when process group can read and modify a dir it does not own' do + it 'succeeds when process group can read and modify a dir it does not own' do expect(Dir).to receive(:entries).with(dir).and_return([]) mock_stat = OpenStruct.new mock_stat.uid = Process.uid + 1 # make sure there is a mismatch! mock_stat.gid = Process.gid - mock_stat.mode = 00770 + mock_stat.mode = 0o0770 expect(File).to receive(:stat).with(dir).and_return(mock_stat) - allow(FileUtils).to receive(:chmod).with(0770, dir).and_return(nil) + allow(FileUtils).to receive(:chmod).with(0o770, dir).and_return(nil) - expect{ @plugin.verify_dir_access(dir) }.to_not raise_error + expect { @plugin.verify_dir_access(dir) }.not_to raise_error end - it 'should fail when directory cannot be read' do + it 'fails when directory cannot be read' do expect(Dir).to receive(:entries).with(dir).and_raise( - Errno::EACCES, 'Permission denied') + Errno::EACCES, 'Permission denied' + ) - expect{ @plugin.verify_dir_access(dir) }.to raise_error( - /Cannot access '#{Regexp.escape(dir)}'/) + expect { @plugin.verify_dir_access(dir) }.to raise_error( + %r{Cannot access '#{Regexp.escape(dir)}'}, + ) end - it 'should fail process group cannot modify directory' do + it 'fails process group cannot modify directory' do expect(Dir).to receive(:entries).with(dir).and_return([]) mock_stat = OpenStruct.new mock_stat.uid = Process.uid + 1 # make sure there is a mismatch! mock_stat.gid = Process.gid - mock_stat.mode = 00750 + mock_stat.mode = 0o0750 expect(File).to receive(:stat).with(dir).and_return(mock_stat) - expect{ @plugin.verify_dir_access(dir) }.to raise_error( - /Cannot modify '#{Regexp.escape(dir)}'/) + expect { @plugin.verify_dir_access(dir) }.to raise_error( + %r{Cannot modify '#{Regexp.escape(dir)}'}, + ) end end - end - end diff --git a/spec/unit/puppet_x/simpkv/ldap_plugin_spec.rb b/spec/unit/puppet_x/simpkv/ldap_plugin_spec.rb index f6b3772..7295b98 100644 --- a/spec/unit/puppet_x/simpkv/ldap_plugin_spec.rb +++ b/spec/unit/puppet_x/simpkv/ldap_plugin_spec.rb @@ -22,7 +22,7 @@ File.open(@admin_pw_file, 'w') { |file| file.puts('P@ssw0rdP@ssw0rd!') } @options = { 'backends' => { - 'default' => { + 'default' => { 'id' => 'default', 'type' => 'ldap', 'ldap_uri' => 'ldapi://simpkv.ldap.example.com', @@ -33,7 +33,7 @@ 'ldap_uri' => 'ldap://simpkv.ldap.example.com', 'admin_pw_file' => @admin_pw_file, }, - 'starttls' => { + 'starttls' => { 'id' => 'starttls', 'type' => 'ldap', 'ldap_uri' => 'ldap://simpkv.ldap.example.com', @@ -43,7 +43,7 @@ 'tls_key' => '/certdir/private/client.example.com.pem', 'tls_cacert' => '/certdir/cacerts/cacerts.pem' }, - 'tls' => { + 'tls' => { 'id' => 'tls', 'type' => 'ldap', 'ldap_uri' => 'ldaps://simpkv.ldap.example.com', @@ -64,45 +64,51 @@ let(:key) { 'environments/production/mykey' } let(:base_key) { File.basename(key) } let(:full_key_path) { "instances/default/#{key}" } - let(:production_dn) { 'ou=production,ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp'} + let(:production_dn) { 'ou=production,ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp' } let(:key_dn) { "simpkvKey=#{base_key},#{production_dn}" } let(:value) { 'myvalue' } - let(:stored_value) { %Q{{"value":"#{value}","metadata":{}}} } + let(:stored_value) { %({"value":"#{value}","metadata":{}}) } let(:folder) { 'environments/production/myfolder' } let(:base_folder) { File.basename(folder) } -# let(:full_folder_path) { "instances/default/#{folder}" } + # let(:full_folder_path) { "instances/default/#{folder}" } let(:folder_dn) { "ou=#{base_folder},#{production_dn}" } - let(:ldap_busy_response) {{ - :success => false, - :exitstatus => 51, - :stdout => '', - :stderr => 'ldapxxx failed:\nServer busy' - }} - - let(:ldap_no_such_object_response) {{ - :success => false, - :exitstatus => 32, - :stdout => '', - :stderr => 'No such object' - }} - - let(:ldap_other_error_response) {{ - :success => false, - :exitstatus => 1, - :stdout => '', - :stderr => 'ldapxxx failed:\nOther error' - }} + let(:ldap_busy_response) do + { + success: false, + exitstatus: 51, + stdout: '', + stderr: 'ldapxxx failed:\nServer busy' + } + end + + let(:ldap_no_such_object_response) do + { + success: false, + exitstatus: 32, + stdout: '', + stderr: 'No such object' + } + end + + let(:ldap_other_error_response) do + { + success: false, + exitstatus: 1, + stdout: '', + stderr: 'ldapxxx failed:\nOther error' + } + end # success response from run_command for which we only care about # :success or :exitstatus - let(:success_response_simple) {{ :success => true, :exitstatus => 0 }} + let(:success_response_simple) { { success: true, exitstatus: 0 } } context '#initialize' do it 'is expected to set name' do plugin_name = 'ldap/test' - plugin = plugin_class.new(plugin_name) + plugin = plugin_class.new(plugin_name) expect(plugin.name).to eq plugin_name end end @@ -110,90 +116,90 @@ # See parse_config tests for other permutations of valid and invalid config context '#configure' do before(:each) do - @plugin = plugin_class.new('ldap/default') + @plugin = plugin_class.new('ldap/default') end - it 'should succeed using valid config' do - options = @options.merge( {'backend' => 'default' } ) + it 'succeeds using valid config' do + options = @options.merge({ 'backend' => 'default' }) expect(@plugin).to receive(:set_base_ldap_commands) expect(@plugin).to receive(:verify_ldap_access) expect(@plugin).to receive(:ensure_instance_tree) - expect{ @plugin.configure(options) }.to_not raise_error + expect { @plugin.configure(options) }.not_to raise_error end context 'error cases' do - it 'should fail when options is not a Hash' do + it 'fails when options is not a Hash' do expect { @plugin.configure('oops') } - .to raise_error(/Plugin misconfigured/) + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when options missing 'backend' key" do + it "fails when options missing 'backend' key" do expect { @plugin.configure({}) } - .to raise_error(/Plugin misconfigured/) + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when options missing 'backends' key" do + it "fails when options missing 'backends' key" do options = { 'backend' => 'test' } expect { @plugin.configure(options) } - .to raise_error(/Plugin misconfigured: {.*backend.*}/) + .to raise_error(%r{Plugin misconfigured: {.*backend.*}}) end - it "should fail when options 'backends' key is not a Hash" do + it "fails when options 'backends' key is not a Hash" do options = { 'backend' => 'test', 'backends' => 'oops' } expect { @plugin.configure(options) } - .to raise_error(/Plugin misconfigured/) + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when options 'backends' does not have the specified backend" do + it "fails when options 'backends' does not have the specified backend" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'file'} + 'test1' => { 'id' => 'test', 'type' => 'file' } } } expect { @plugin.configure(options) } - .to raise_error(/Plugin misconfigured/) + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when the correct 'backends' element has no 'id' key" do + it "fails when the correct 'backends' element has no 'id' key" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'file'}, + 'test1' => { 'id' => 'test', 'type' => 'file' }, 'test' => {} } } expect { @plugin.configure(options) } - .to raise_error(/Plugin misconfigured/) + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when the correct 'backends' element has no 'type' key" do + it "fails when the correct 'backends' element has no 'type' key" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'file'}, + 'test1' => { 'id' => 'test', 'type' => 'file' }, 'test' => { 'id' => 'test' } } } expect { @plugin.configure(options) } - .to raise_error(/Plugin misconfigured/) + .to raise_error(%r{Plugin misconfigured}) end - it "should fail when the correct 'backends' element has wrong 'type' value" do + it "fails when the correct 'backends' element has wrong 'type' value" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'file'}, + 'test1' => { 'id' => 'test', 'type' => 'file' }, 'test' => { 'id' => 'test', 'type' => 'file' } } } expect { @plugin.configure(options) } - .to raise_error(/Plugin misconfigured/) + .to raise_error(%r{Plugin misconfigured}) end end end @@ -243,7 +249,7 @@ context 'after configure' do before(:each) do - options = @options.merge( {'backend' => 'default' } ) + options = @options.merge({ 'backend' => 'default' }) expect(Facter::Core::Execution).to receive(:which).with('ldapadd').and_return('/usr/bin/ldapadd') expect(Facter::Core::Execution).to receive(:which).with('ldapdelete').and_return('/usr/bin/ldapdelete') expect(Facter::Core::Execution).to receive(:which).with('ldapmodify').and_return('/usr/bin/ldapmodify') @@ -253,31 +259,30 @@ @plugin.configure(options) end - describe '#delete' do - it 'should return success when retries succeed' do + it 'returns success when retries succeed' do # ldapdelete will return busy code first time and then success - expect(@plugin).to receive(:run_command).with(/ldapdelete/) - .and_return(ldap_busy_response, success_response_simple) + expect(@plugin).to receive(:run_command).with(%r{ldapdelete}) + .and_return(ldap_busy_response, success_response_simple) result = @plugin.delete(key) expect(result[:result]).to be true expect(result[:err_msg]).to be_nil end - it 'should return failure when retries fail' do + it 'returns failure when retries fail' do # ldapdelete will return busy code both times - expect(@plugin).to receive(:run_command).with(/ldapdelete/) - .and_return(ldap_busy_response, ldap_busy_response) + expect(@plugin).to receive(:run_command).with(%r{ldapdelete}) + .and_return(ldap_busy_response, ldap_busy_response) result = @plugin.delete(key) expect(result[:result]).to be false expect(result[:err_msg]).to eq(ldap_busy_response[:stderr]) end - it 'should return failure when other ldapdelete failure occurs' do - expect(@plugin).to receive(:run_command).with(/ldapdelete/) - .and_return(ldap_other_error_response) + it 'returns failure when other ldapdelete failure occurs' do + expect(@plugin).to receive(:run_command).with(%r{ldapdelete}) + .and_return(ldap_other_error_response) result = @plugin.delete(key) expect(result[:result]).to be false @@ -286,15 +291,15 @@ end describe '#deletetree' do - it 'should remove the folder tree from the intenral set of existing folders upon success' do + it 'removes the folder tree from the intenral set of existing folders upon success' do @plugin.existing_folders.add('instances/default/globals/app1') @plugin.existing_folders.add('instances/default/globals/app1/group1') @plugin.existing_folders.add('instances/default/globals/app1/group1/user1') @plugin.existing_folders.add('instances/default/globals/app1/group2/user1') @plugin.existing_folders.add('instances/default/globals/app2') - expect(@plugin).to receive(:run_command).with(/ldapdelete/) - .and_return(success_response_simple) + expect(@plugin).to receive(:run_command).with(%r{ldapdelete}) + .and_return(success_response_simple) result = @plugin.deletetree('globals/app1') expect(result[:result]).to be true @@ -305,29 +310,29 @@ expect(@plugin.existing_folders).to eq(expected_folders) end - it 'should return success when retries succeed' do + it 'returns success when retries succeed' do # ldapdelete will return busy code first time and then success - expect(@plugin).to receive(:run_command).with(/ldapdelete/) - .and_return(ldap_busy_response, success_response_simple) + expect(@plugin).to receive(:run_command).with(%r{ldapdelete}) + .and_return(ldap_busy_response, success_response_simple) result = @plugin.deletetree(folder) expect(result[:result]).to be true expect(result[:err_msg]).to be_nil end - it 'should return failure when retries fail' do + it 'returns failure when retries fail' do # ldapdelete will return busy code both times - expect(@plugin).to receive(:run_command).with(/ldapdelete/) - .and_return(ldap_busy_response, ldap_busy_response) + expect(@plugin).to receive(:run_command).with(%r{ldapdelete}) + .and_return(ldap_busy_response, ldap_busy_response) result = @plugin.deletetree(folder) expect(result[:result]).to be false expect(result[:err_msg]).to eq(ldap_busy_response[:stderr]) end - it 'should return failure when other ldapdelete failure occurs' do - expect(@plugin).to receive(:run_command).with(/ldapdelete/) - .and_return(ldap_other_error_response) + it 'returns failure when other ldapdelete failure occurs' do + expect(@plugin).to receive(:run_command).with(%r{ldapdelete}) + .and_return(ldap_other_error_response) result = @plugin.deletetree(folder) expect(result[:result]).to be false @@ -336,35 +341,37 @@ end describe '#exists' do - let(:success_response_dn_match) {{ - :success => true, - :exitstatus => 0, - :stdout => "dn: #{key_dn}" - }} + let(:success_response_dn_match) do + { + success: true, + exitstatus: 0, + stdout: "dn: #{key_dn}" + } + end - it 'should return success when retries succeed' do + it 'returns success when retries succeed' do # ldapsearch will return busy code first time and then success - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, success_response_dn_match) + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, success_response_dn_match) result = @plugin.exists(key) expect(result[:result]).to be true expect(result[:err_msg]).to be_nil end - it 'should return failure when retries fail' do + it 'returns failure when retries fail' do # ldapsearch will return busy code both times - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, ldap_busy_response) + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, ldap_busy_response) result = @plugin.exists(key) expect(result[:result]).to be_nil expect(result[:err_msg]).to eq(ldap_busy_response[:stderr]) end - it 'should return failure when other ldapsearch failure occurs' do - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_other_error_response) + it 'returns failure when other ldapsearch failure occurs' do + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_other_error_response) result = @plugin.exists(key) expect(result[:result]).to be_nil @@ -373,35 +380,37 @@ end describe '#get' do - let(:success_response_simpkvKey) {{ - :success => true, - :exitstatus => 0, - :stdout => <<~EOM + let(:success_response_simpkvKey) do + { + success: true, + exitstatus: 0, + stdout: <<~EOM dn: #{key_dn} objectClass: simpkvEntry objectClass: top simpkvKey: #{base_key} simpkvJsonValue: #{stored_value} EOM - }} + } + end - it 'should return success when retries succeed' do + it 'returns success when retries succeed' do # ldapsearch will return busy code first time and then success - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, success_response_simpkvKey) + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, success_response_simpkvKey) result = @plugin.get(key) expect(result[:result]).to eq(stored_value) expect(result[:err_msg]).to be_nil end - it 'should fail when simpkvKey object missing simpkvJsonValue attribute' do + it 'fails when simpkvKey object missing simpkvJsonValue attribute' do # successful query result, but instead of simpkvJsonValue attribute # has simpkvValue attribute success_response_malformed_simpkvKey = { - :success => true, - :exitstatus => 0, - :stdout => <<~EOM + success: true, + exitstatus: 0, + stdout: <<~EOM dn: #{key_dn} objectClass: simpkvEntry objectClass: top @@ -410,27 +419,27 @@ EOM } - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(success_response_malformed_simpkvKey) + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(success_response_malformed_simpkvKey) result = @plugin.get(key) expect(result[:result]).to be_nil expect(result[:err_msg]).to match(%r{Key retrieval did not return key/value entry}) end - it 'should return failure when retries fail' do + it 'returns failure when retries fail' do # ldapsearch will return busy code both times - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, ldap_busy_response) + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, ldap_busy_response) result = @plugin.get(key) expect(result[:result]).to be_nil expect(result[:err_msg]).to eq(ldap_busy_response[:stderr]) end - it 'should return failure when other ldapsearch failure occurs' do - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_other_error_response) + it 'returns failure when other ldapsearch failure occurs' do + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_other_error_response) result = @plugin.get(key) expect(result[:result]).to be_nil @@ -439,10 +448,11 @@ end describe '#list' do - let(:success_response_not_empty) {{ - :success => true, - :exitstatus => 0, - :stdout => <<~EOM + let(:success_response_not_empty) do + { + success: true, + exitstatus: 0, + stdout: <<~EOM dn: #{folder_dn} ou: #{base_folder} objectClass: top @@ -454,37 +464,37 @@ simpkvKey: #{base_key} simpkvJsonValue: #{stored_value} EOM - }} + } + end - it 'should return success when retries succeed' do + it 'returns success when retries succeed' do # ldapsearch will return busy code first time and then success - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, success_response_not_empty) + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, success_response_not_empty) result = @plugin.list(File.dirname(folder)) expected_list = { - :keys => { base_key => stored_value }, - :folders => [ base_folder ] + keys: { base_key => stored_value }, + folders: [ base_folder ] } expect(result[:result]).to eq(expected_list) expect(result[:err_msg]).to be_nil end - - it 'should return failure when retries fail' do + it 'returns failure when retries fail' do # ldapsearch will return busy code both times - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, ldap_busy_response) + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, ldap_busy_response) result = @plugin.list(key) expect(result[:result]).to be_nil expect(result[:err_msg]).to eq(ldap_busy_response[:stderr]) end - it 'should return failure when other ldapsearch failure occurs' do - expect(@plugin).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_other_error_response) + it 'returns failure when other ldapsearch failure occurs' do + expect(@plugin).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_other_error_response) result = @plugin.list(key) expect(result[:result]).to be_nil @@ -493,23 +503,29 @@ end describe '#put' do - let(:failed_ldap_result) {{ - :success => false, - :exitstatus => 1, - :err_msg => 'Some interim ldap operation failed' - }} - - let(:successful_ldap_result) {{ - :success => true, - :exitstatus => 0 - }} - - let(:failed_update_result) {{ - :result => false, - :err_msg => 'Update failed' - }} - - it 'should return failure when ensure_folder_path fails' do + let(:failed_ldap_result) do + { + success: false, + exitstatus: 1, + err_msg: 'Some interim ldap operation failed' + } + end + + let(:successful_ldap_result) do + { + success: true, + exitstatus: 0 + } + end + + let(:failed_update_result) do + { + result: false, + err_msg: 'Update failed' + } + end + + it 'returns failure when ensure_folder_path fails' do expect(@plugin).to receive(:ensure_folder_path) .with('instances/default/environments/production') .and_return(failed_ldap_result) @@ -519,26 +535,25 @@ expect(result[:err_msg]).to eq(failed_ldap_result[:err_msg]) end - - it "should return failure when ldap_add with 'already exists' error and update_value_if_changed fails" do + it "returns failure when ldap_add with 'already exists' error and update_value_if_changed fails" do expect(@plugin).to receive(:ensure_folder_path) .with('instances/default/environments/production') .and_return(successful_ldap_result) already_exists_result = { - :success => false, - :exitstatus => 68, - :err_msg => 'Already exists' + success: false, + exitstatus: 68, + err_msg: 'Already exists' } expect(@plugin).to receive(:ldap_add).and_return(already_exists_result) - expect(@plugin).to receive(:update_value_if_changed).with(key,value) - .and_return(failed_update_result) + expect(@plugin).to receive(:update_value_if_changed).with(key, value) + .and_return(failed_update_result) result = @plugin.put(key, value) expect(result).to eq(failed_update_result) end - it 'should return failure when ldap_add fails with other error' do + it 'returns failure when ldap_add fails with other error' do expect(@plugin).to receive(:ensure_folder_path) .with('instances/default/environments/production') .and_return(successful_ldap_result) @@ -555,7 +570,7 @@ context 'internal methods' do before(:each) do @plugin = plugin_class.new('ldap/ldapi') - options = @options.merge( {'backend' => 'default' } ) + options = @options.merge({ 'backend' => 'default' }) # allow instead of expect because of set_base_ldap_commands test allow(Facter::Core::Execution).to receive(:which).with('ldapadd').and_return('/usr/bin/ldapadd') @@ -569,21 +584,21 @@ end describe '#ensure_folder_path' do - it 'should return success when no folders in existing_folders & all ldap_add ' do + it 'returns success when no folders in existing_folders & all ldap_add' do @plugin.existing_folders.clear [ 'dn: ou=instances,ou=simpkv,o=puppet,dc=simp', 'dn: ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp', 'dn: ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp', - 'dn: ou=production,ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp' + 'dn: ou=production,ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp', ].each do |dn| - expect(@plugin).to receive(:ldap_add).with(/#{dn}/, true) - .and_return(success_response_simple) + expect(@plugin).to receive(:ldap_add).with(%r{#{dn}}, true) + .and_return(success_response_simple) end expect(@plugin.ensure_folder_path(File.dirname(full_key_path))) - .to eq(success_response_simple.merge({ :err_msg => nil })) + .to eq(success_response_simple.merge({ err_msg: nil })) expected_folders = Set.new expected_folders.add('instances') @@ -593,39 +608,39 @@ expect(@plugin.existing_folders).to eq(expected_folders) end - it 'should return success when some folders in existing_folders & ldap_add succeeds for new folders' do + it 'returns success when some folders in existing_folders & ldap_add succeeds for new folders' do @plugin.existing_folders.clear @plugin.existing_folders.add('instances') @plugin.existing_folders.add('instances/default') @plugin.existing_folders.add('instances/default/environments') dn = 'dn: ou=production,ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp' - expect(@plugin).to receive(:ldap_add).with(/#{dn}/, true) - .and_return(success_response_simple) + expect(@plugin).to receive(:ldap_add).with(%r{#{dn}}, true) + .and_return(success_response_simple) expect(@plugin.ensure_folder_path(File.dirname(full_key_path))) - .to eq(success_response_simple.merge({ :err_msg => nil })) + .to eq(success_response_simple.merge({ err_msg: nil })) end - it 'should return failure if any ldap_add fails' do + it 'returns failure if any ldap_add fails' do @plugin.existing_folders.clear @plugin.existing_folders.add('instances') @plugin.existing_folders.add('instances/default') dn1 = 'dn: ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp' - expect(@plugin).to receive(:ldap_add).with(/#{dn1}/, true) - .and_return(success_response_simple) + expect(@plugin).to receive(:ldap_add).with(%r{#{dn1}}, true) + .and_return(success_response_simple) dn2 = 'dn: ou=production,ou=environments,ou=default,ou=instances,ou=simpkv,o=puppet,dc=simp' failed_add_response = { - :success => false, - :exitstatus => 1, - :err_msg => 'ldapadd failed' + success: false, + exitstatus: 1, + err_msg: 'ldapadd failed' } - expect(@plugin).to receive(:ldap_add).with(/#{dn2}/, true) - .and_return(failed_add_response) + expect(@plugin).to receive(:ldap_add).with(%r{#{dn2}}, true) + .and_return(failed_add_response) expect(@plugin.ensure_folder_path(File.dirname(full_key_path))) .to eq(failed_add_response) @@ -636,17 +651,19 @@ end describe '#ldap_add' do - let(:ldap_already_exists_response) {{ - :success => false, - :exitstatus => 68, - :stdout => '', - :stderr => 'ldapadd failed:\nDN already exists' - }} + let(:ldap_already_exists_response) do + { + success: false, + exitstatus: 68, + stdout: '', + stderr: 'ldapadd failed:\nDN already exists' + } + end context 'ignore_already_exists=false (default)' do - it 'should return failure when ldapadd fails because DN already exists' do - expect(@plugin).to receive(:run_command).with(/ldapadd/) - .and_return(ldap_already_exists_response) + it 'returns failure when ldapadd fails because DN already exists' do + expect(@plugin).to receive(:run_command).with(%r{ldapadd}) + .and_return(ldap_already_exists_response) result = @plugin.ldap_add('some ldif') expect(result[:success]).to be false @@ -654,10 +671,10 @@ expect(result[:err_msg]).to eq(ldap_already_exists_response[:stderr]) end - it 'should return success when retries succeed' do + it 'returns success when retries succeed' do # ldapadd will return busy code first time and then success - expect(@plugin).to receive(:run_command).with(/ldapadd/) - .and_return(ldap_busy_response, success_response_simple) + expect(@plugin).to receive(:run_command).with(%r{ldapadd}) + .and_return(ldap_busy_response, success_response_simple) result = @plugin.ldap_add('some ldif') expect(result[:success]).to be true @@ -665,10 +682,10 @@ expect(result[:err_msg]).to be_nil end - it 'should return failure when retries fail' do + it 'returns failure when retries fail' do # ldapadd will return busy code both times - expect(@plugin).to receive(:run_command).with(/ldapadd/) - .and_return(ldap_busy_response, ldap_busy_response) + expect(@plugin).to receive(:run_command).with(%r{ldapadd}) + .and_return(ldap_busy_response, ldap_busy_response) result = @plugin.ldap_add('some ldif') expect(result[:success]).to be false @@ -676,9 +693,9 @@ expect(result[:err_msg]).to eq(ldap_busy_response[:stderr]) end - it 'should return failure when other ldapadd failure occurs' do - expect(@plugin).to receive(:run_command).with(/ldapadd/) - .and_return(ldap_other_error_response) + it 'returns failure when other ldapadd failure occurs' do + expect(@plugin).to receive(:run_command).with(%r{ldapadd}) + .and_return(ldap_other_error_response) result = @plugin.ldap_add('some ldif') expect(result[:success]).to be false @@ -688,9 +705,9 @@ end context 'ignore_already_exists=true' do - it 'should return success when ldapadd fails because DN already exists' do - expect(@plugin).to receive(:run_command).with(/ldapadd/) - .and_return(ldap_already_exists_response) + it 'returns success when ldapadd fails because DN already exists' do + expect(@plugin).to receive(:run_command).with(%r{ldapadd}) + .and_return(ldap_already_exists_response) result = @plugin.ldap_add('some ldif', true) expect(result[:success]).to be true @@ -701,10 +718,10 @@ end describe '#ldap_modify' do - it 'should return success when retries succeed' do + it 'returns success when retries succeed' do # ldapmodify will return busy code first time and then success - expect(@plugin).to receive(:run_command).with(/ldapmodify/) - .and_return(ldap_busy_response, success_response_simple) + expect(@plugin).to receive(:run_command).with(%r{ldapmodify}) + .and_return(ldap_busy_response, success_response_simple) result = @plugin.ldap_modify('some LDIF content') expect(result[:success]).to be true @@ -712,10 +729,10 @@ expect(result[:err_msg]).to be_nil end - it 'should return failure when retries fail' do + it 'returns failure when retries fail' do # ldapmodify will return busy code both times - expect(@plugin).to receive(:run_command).with(/ldapmodify/) - .and_return(ldap_busy_response, ldap_busy_response) + expect(@plugin).to receive(:run_command).with(%r{ldapmodify}) + .and_return(ldap_busy_response, ldap_busy_response) result = @plugin.ldap_modify('some LDIF content') expect(result[:success]).to be false @@ -723,9 +740,9 @@ expect(result[:err_msg]).to eq(ldap_busy_response[:stderr]) end - it 'should return failure when DN no longer exists' do - expect(@plugin).to receive(:run_command).with(/ldapmodify/) - .and_return(ldap_no_such_object_response) + it 'returns failure when DN no longer exists' do + expect(@plugin).to receive(:run_command).with(%r{ldapmodify}) + .and_return(ldap_no_such_object_response) result = @plugin.ldap_modify('some LDIF content') expect(result[:success]).to be false @@ -733,9 +750,9 @@ expect(result[:err_msg]).to eq(ldap_no_such_object_response[:stderr]) end - it 'should return failure when other ldapmodify failure occurs' do - expect(@plugin).to receive(:run_command).with(/ldapmodify/) - .and_return(ldap_other_error_response) + it 'returns failure when other ldapmodify failure occurs' do + expect(@plugin).to receive(:run_command).with(%r{ldapmodify}) + .and_return(ldap_other_error_response) result = @plugin.ldap_modify('some LDIF content') expect(result[:success]).to be false @@ -746,24 +763,24 @@ describe '#path_to_dn' do context 'leaf_is_key=true (default)' do - it 'should return DN for simpkvKey node when path has no folders' do + it 'returns DN for simpkvKey node when path has no folders' do actual = @plugin.path_to_dn('key') expect(actual).to eq('simpkvKey=key,ou=simpkv,o=puppet,dc=simp') end - it 'should return DN for simpkvKey node when path has folders' do + it 'returns DN for simpkvKey node when path has folders' do actual = @plugin.path_to_dn('environments/dev/key') expect(actual).to eq('simpkvKey=key,ou=dev,ou=environments,ou=simpkv,o=puppet,dc=simp') end end context 'leaf_is_folder=false' do - it 'should return DN for ou node when path has no folders' do + it 'returns DN for ou node when path has no folders' do actual = @plugin.path_to_dn('folder', false) expect(actual).to eq('ou=folder,ou=simpkv,o=puppet,dc=simp') end - it 'should return DN for ou node when path has folders' do + it 'returns DN for ou node when path has folders' do actual = @plugin.path_to_dn('environments/dev/folder', false) expect(actual).to eq('ou=folder,ou=dev,ou=environments,ou=simpkv,o=puppet,dc=simp') end @@ -772,48 +789,48 @@ describe '#parse_config' do context 'valid configuration' do - it 'should default base_dn to ou=simpkv,o=puppet,dc=simp' do + it 'defaults base_dn to ou=simpkv,o=puppet,dc=simp' do config = @options['backends']['default'] opts = @plugin.parse_config(config) expect(opts[:base_dn]).to eq('ou=simpkv,o=puppet,dc=simp') end - it 'should default admin_dn to cn=Directory_Manager' do + it 'defaults admin_dn to cn=Directory_Manager' do config = @options['backends']['unencrypted'] opts = @plugin.parse_config(config) - expect(opts[:base_opts]).to match(/-D "cn=Directory_Manager"/) + expect(opts[:base_opts]).to match(%r{-D "cn=Directory_Manager"}) end - it 'should default retries to 1' do + it 'defaults retries to 1' do config = @options['backends']['default'] opts = @plugin.parse_config(config) expect(opts[:retries]).to eq(1) end - it 'should transform valid ldapi config without admin_dn and admin_pw_file' do + it 'transforms valid ldapi config without admin_dn and admin_pw_file' do config = @options['backends']['default'] opts = @plugin.parse_config(config) expect(opts[:cmd_env]).to eq('') expect(opts[:base_opts]).to eq("-Y EXTERNAL -H #{config['ldap_uri']}") end - it 'should transform valid ldapi config with admin_dn and admin_pw_file' do - config = @options['backends']['default'].merge( { - 'admin_dn' => 'cn=My_Directory_Manager', + it 'transforms valid ldapi config with admin_dn and admin_pw_file' do + config = @options['backends']['default'].merge({ + 'admin_dn' => 'cn=My_Directory_Manager', 'admin_pw_file' => @admin_pw_file - } ) + }) opts = @plugin.parse_config(config) expect(opts[:cmd_env]).to eq('') exp_base = [ '-x', - %Q{-D "#{config['admin_dn']}"}, + %(-D "#{config['admin_dn']}"), "-y #{config['admin_pw_file']}", - "-H #{config['ldap_uri']}" + "-H #{config['ldap_uri']}", ].join(' ') expect(opts[:base_opts]).to eq(exp_base) end - it 'should transform valid unencrypted ldap config' do + it 'transforms valid unencrypted ldap config' do config = @options['backends']['unencrypted'] opts = @plugin.parse_config(config) expect(opts[:cmd_env]).to eq('') @@ -821,13 +838,13 @@ '-x', '-D "cn=Directory_Manager"', "-y #{config['admin_pw_file']}", - "-H #{config['ldap_uri']}" + "-H #{config['ldap_uri']}", ].join(' ') expect(opts[:base_opts]).to eq(exp_base) end - it 'should transform valid unencrypted ldap config with enable_tls=false' do - config = @options['backends']['unencrypted'].merge( {'enable_tls' => false} ) + it 'transforms valid unencrypted ldap config with enable_tls=false' do + config = @options['backends']['unencrypted'].merge({ 'enable_tls' => false }) opts = @plugin.parse_config(config) expect(opts[:cmd_env]).to eq('') @@ -835,18 +852,18 @@ '-x', '-D "cn=Directory_Manager"', "-y #{config['admin_pw_file']}", - "-H #{config['ldap_uri']}" + "-H #{config['ldap_uri']}", ].join(' ') expect(opts[:base_opts]).to eq(exp_base) end - it 'should transform valid encrypted ldap (StartTLS) config' do + it 'transforms valid encrypted ldap (StartTLS) config' do config = @options['backends']['starttls'] opts = @plugin.parse_config(config) exp_env = [ "LDAPTLS_CERT=#{config['tls_cert']}", "LDAPTLS_KEY=#{config['tls_key']}", - "LDAPTLS_CACERT=#{config['tls_cacert']}" + "LDAPTLS_CACERT=#{config['tls_cacert']}", ].join(' ') expect(opts[:cmd_env]).to eq(exp_env) @@ -855,63 +872,63 @@ '-x', '-D "cn=Directory_Manager"', "-y #{config['admin_pw_file']}", - "-H #{config['ldap_uri']}" + "-H #{config['ldap_uri']}", ].join(' ') expect(opts[:base_opts]).to eq(exp_base) end - it 'should transform valid encrypted ldaps config' do + it 'transforms valid encrypted ldaps config' do config = @options['backends']['tls'] opts = @plugin.parse_config(config) exp_env = [ "LDAPTLS_CERT=#{config['tls_cert']}", "LDAPTLS_KEY=#{config['tls_key']}", - "LDAPTLS_CACERT=#{config['tls_cacert']}" + "LDAPTLS_CACERT=#{config['tls_cacert']}", ].join(' ') expect(opts[:cmd_env]).to eq(exp_env) exp_base = [ - '', + '', '-x', '-D "cn=Directory_Manager"', "-y #{config['admin_pw_file']}", - "-H #{config['ldap_uri']}" + "-H #{config['ldap_uri']}", ].join(' ') expect(opts[:base_opts]).to eq(exp_base) end end context 'invalid configuration' do - it 'should fail when ldap_uri is missing' do + it 'fails when ldap_uri is missing' do config = {} - expect{ @plugin.parse_config(config) } - .to raise_error(/Plugin missing 'ldap_uri' configuration/) + expect { @plugin.parse_config(config) } + .to raise_error(%r{Plugin missing 'ldap_uri' configuration}) end - it 'should fail if ldap_uri is malformed' do + it 'fails if ldap_uri is malformed' do config = { 'ldap_uri' => 'ldaps:/too.few.slashes.com' } - expect{ @plugin.parse_config(config) } - .to raise_error(/Invalid 'ldap_uri' configuration/) + expect { @plugin.parse_config(config) } + .to raise_error(%r{Invalid 'ldap_uri' configuration}) end - it 'should fail if admin_pw_file missing and not ldapi' do + it 'fails if admin_pw_file missing and not ldapi' do config = Marshal.load(Marshal.dump(@options['backends']['unencrypted'])) config.delete('admin_pw_file') - expect{ @plugin.parse_config(config) } - .to raise_error(/Plugin missing 'admin_pw_file' configuration/) + expect { @plugin.parse_config(config) } + .to raise_error(%r{Plugin missing 'admin_pw_file' configuration}) end - it 'should fail if admin_pw_file does not exist' do + it 'fails if admin_pw_file does not exist' do config = @options['backends']['default'].merge({ 'admin_pw_file' => '/does/not/exist' }) - expect{ @plugin.parse_config(config) } + expect { @plugin.parse_config(config) } .to raise_error(%r{Configured 'admin_pw_file' /does/not/exist does not exist}) end - it 'should fail if TLS configuration incomplete' do + it 'fails if TLS configuration incomplete' do config = Marshal.load(Marshal.dump(@options['backends']['tls'])) config.delete('tls_cacert') - expect{ @plugin.parse_config(config) } - .to raise_error(/TLS configuration incomplete/) + expect { @plugin.parse_config(config) } + .to raise_error(%r{TLS configuration incomplete}) end end end @@ -942,8 +959,8 @@ result = @plugin.parse_list_ldif(ldif) expected = { - :keys => { base_key => stored_value }, - :folders => [ base_folder ] + keys: { base_key => stored_value }, + folders: [ base_folder ] } expect(result).to eq(expected) end @@ -962,7 +979,7 @@ EOM result = @plugin.parse_list_ldif(ldif) - expected = { :keys=> {}, :folders => [ base_folder ] } + expected = { keys: {}, folders: [ base_folder ] } expect(result).to eq(expected) end @@ -980,7 +997,7 @@ EOM result = @plugin.parse_list_ldif(ldif) - expected = { :keys=> {}, :folders => [ base_folder ] } + expected = { keys: {}, folders: [ base_folder ] } expect(result).to eq(expected) end @@ -1005,8 +1022,8 @@ result = @plugin.parse_list_ldif(ldif) expected = { - :keys => { base_key => stored_value }, - :folders => [ base_folder ] + keys: { base_key => stored_value }, + folders: [ base_folder ] } expect(result).to eq(expected) end @@ -1016,27 +1033,27 @@ it 'returns success results when command succeeds' do command = "ls #{__FILE__}" result = @plugin.run_command(command) - expect( result[:success] ).to eq true - expect( result[:exitstatus] ).to eq 0 - expect( result[:stdout] ).to match "#{__FILE__}" - expect( result[:stderr] ).to eq '' + expect(result[:success]).to eq true + expect(result[:exitstatus]).to eq 0 + expect(result[:stdout]).to match __FILE__.to_s + expect(result[:stderr]).to eq '' end it 'returns failed results when command fails' do command = 'ls /some/missing/path1' result = @plugin.run_command(command) - expect( result[:success] ).to eq false - expect( result[:exitstatus] ).to eq 2 - expect( result[:stdout] ).to eq '' - expect( result[:stderr] ).to match(/No such file or directory/) + expect(result[:success]).to eq false + expect(result[:exitstatus]).to eq 2 + expect(result[:stdout]).to eq '' + expect(result[:stderr]).to match(%r{No such file or directory}) end end describe '#set_base_ldap_commands' do it 'fails when ldap* commands cannot be found' do expect(Facter::Core::Execution).to receive(:which).with('ldapadd').and_return(nil) - expect{ @plugin.set_base_ldap_commands('','some base opts') } - .to raise_error(/Missing required ldapadd command/) + expect { @plugin.set_base_ldap_commands('', 'some base opts') } + .to raise_error(%r{Missing required ldapadd command}) end end @@ -1075,20 +1092,21 @@ describe '#update_value_if_changed' do let(:new_stored_value) { '{"value":"new value","metadata":{}}' } - it 'should report failure when get() for the current value fails' do + + it 'reports failure when get() for the current value fails' do failed_get_result = { :result => nil, 'err_msg' => 'No such object' } expect(@plugin).to receive(:get).with(key).and_return(failed_get_result) result = @plugin.update_value_if_changed(key, new_stored_value) expect(result[:result]).to be false - expect(result[:err_msg]).to match(/Failed to retrieve current value for comparison/) + expect(result[:err_msg]).to match(%r{Failed to retrieve current value for comparison}) end - it 'should report failure when ldap_modify() fails' do + it 'reports failure when ldap_modify() fails' do success_get_result = { :result => stored_value, 'err_msg' => nil } expect(@plugin).to receive(:get).with(key).and_return(success_get_result) - expect(@plugin).to receive(:ldap_modify).with(/#{new_stored_value}/) - .and_return(ldap_other_error_response) + expect(@plugin).to receive(:ldap_modify).with(%r{#{new_stored_value}}) + .and_return(ldap_other_error_response) result = @plugin.update_value_if_changed(key, new_stored_value) expect(result[:result]).to be false @@ -1100,27 +1118,27 @@ describe '#verify_ldap_access' do before(:each) do @plugin2 = plugin_class.new('ldap/ldapi') - @options2 = @options.merge( {'backend' => 'default' } ) + @options2 = @options.merge({ 'backend' => 'default' }) expect(Facter::Core::Execution).to receive(:which).with('ldapadd').and_return('/usr/bin/ldapadd') expect(Facter::Core::Execution).to receive(:which).with('ldapdelete').and_return('/usr/bin/ldapdelete') expect(Facter::Core::Execution).to receive(:which).with('ldapmodify').and_return('/usr/bin/ldapmodify') expect(Facter::Core::Execution).to receive(:which).with('ldapsearch').and_return('/usr/bin/ldapsearch') end - it 'should succeed when retries succeed' do - expect(@plugin2).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, success_response_simple) + it 'succeeds when retries succeed' do + expect(@plugin2).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, success_response_simple) expect(@plugin2).to receive(:ensure_instance_tree) - expect{ @plugin2.configure(@options2) }.to_not raise_error + expect { @plugin2.configure(@options2) }.not_to raise_error end - it 'should fail when retries fail' do - expect(@plugin2).to receive(:run_command).with(/ldapsearch/) - .and_return(ldap_busy_response, ldap_busy_response) + it 'fails when retries fail' do + expect(@plugin2).to receive(:run_command).with(%r{ldapsearch}) + .and_return(ldap_busy_response, ldap_busy_response) - expect{ @plugin2.configure(@options2) } - .to raise_error(/Plugin could not access ou=simpkv,o=puppet,dc=simp/) + expect { @plugin2.configure(@options2) } + .to raise_error(%r{Plugin could not access ou=simpkv,o=puppet,dc=simp}) end end end diff --git a/spec/unit/puppet_x/simpkv/simpkv_spec.rb b/spec/unit/puppet_x/simpkv/simpkv_spec.rb index ae49ece..3479e02 100644 --- a/spec/unit/puppet_x/simpkv/simpkv_spec.rb +++ b/spec/unit/puppet_x/simpkv/simpkv_spec.rb @@ -11,11 +11,9 @@ obj = Object.new obj.instance_eval(File.read(simpkv_adapter_file), simpkv_adapter_file) - describe 'simpkv adapter anonymous class' do - # tell puppet-rspec to set Puppet environment to 'production' - let(:environment) {'production'} + let(:environment) { 'production' } # Going to use file plugin and the test plugins in spec/support/test_plugins # for these unit tests. @@ -28,28 +26,28 @@ 'backends' => { # will use failer plugin for catastrophic error cases, because # it is badly behaved and raises exceptions on all operations - 'test_failer' => { - 'id' => 'test', - 'type' => 'failer', - 'fail_configure' => false # true = raise in configure() + 'test_failer' => { + 'id' => 'test', + 'type' => 'failer', + 'fail_configure' => false # true = raise in configure() }, # will use file plugin for non-catastrophic test cases - 'test_file' => { + 'test_file' => { 'id' => 'test', 'type' => 'file', 'root_path' => @root_path } } } - @options_file = options_base.merge ({ 'backend' => 'test_file' } ) - @options_failer = options_base.merge ({ 'backend' => 'test_failer' } ) + @options_file = options_base.merge({ 'backend' => 'test_file' }) + @options_failer = options_base.merge({ 'backend' => 'test_failer' }) @options_failer_ctr = { 'backend' => 'test_failer', 'backends' => { - 'test_failer' => { + 'test_failer' => { 'id' => 'test', 'type' => 'failer', - 'fail_configure' => true # true = raise in configure() + 'fail_configure' => true # true = raise in configure() } } } @@ -59,22 +57,21 @@ FileUtils.remove_entry_secure(@tmpdir) end - context 'constructor' do - it 'should load valid plugin classes' do - expect{ simp_simpkv_adapter_class.new }.to_not raise_error + it 'loads valid plugin classes' do + expect { simp_simpkv_adapter_class.new }.not_to raise_error adapter = simp_simpkv_adapter_class.new - expect( adapter.plugin_info ).to_not be_empty - expect( adapter.plugin_info.keys.include?('file') ).to be true - expect( adapter.plugin_info.keys.include?('failer') ).to be true - expect( adapter.plugin_info.keys.include?('ldap') ).to be true - expect( adapter.plugin_info.keys.include?('malformed') ).to be false + expect(adapter.plugin_info).not_to be_empty + expect(adapter.plugin_info.keys.include?('file')).to be true + expect(adapter.plugin_info.keys.include?('failer')).to be true + expect(adapter.plugin_info.keys.include?('ldap')).to be true + expect(adapter.plugin_info.keys.include?('malformed')).to be false end - it 'should discard a plugin class with malformed Ruby' do + it 'discards a plugin class with malformed Ruby' do allow(Puppet).to receive(:warning) - adapter = simp_simpkv_adapter_class.new - expect(Puppet).to have_received(:warning).with(/simpkv plugin from .*malformed_plugin.rb failed to load/) + simp_simpkv_adapter_class.new + expect(Puppet).to have_received(:warning).with(%r{simpkv plugin from .*malformed_plugin.rb failed to load}) end end @@ -84,7 +81,7 @@ end context '#filter_backtrace' do - it 'should filter-out backtrace lines containing Puppet library internals' do + it 'filter-outs backtrace lines containing Puppet library internals' do # this is not even the full backtrace (~150 lines), but is good enough for testing full_backtrace = [ "/etc/puppetlabs/code/environments/production/modules/simpkv/lib/puppet_x/simpkv/file_plugin.rb:379:in `ensure_root_path'", @@ -113,7 +110,7 @@ "/etc/puppetlabs/code/environments/production/modules/simpkv/lib/puppet/functions/simpkv/put.rb:131:in `put'", ] - expect( @adapter.filter_backtrace(full_backtrace) ).to eq(expected) + expect(@adapter.filter_backtrace(full_backtrace)).to eq(expected) end end @@ -123,51 +120,51 @@ let(:normalized_global_key) { 'globals/my/test/key' } context 'with operation=:add_prefix (default)' do - it "should add the env path when only 'environment' option is specified" do - opts = {'environment' => 'production'} - expect( @adapter.normalize_key(key, opts) ).to eq normalized_env_key + it "adds the env path when only 'environment' option is specified" do + opts = { 'environment' => 'production' } + expect(@adapter.normalize_key(key, opts)).to eq normalized_env_key end - it "should add the env path when 'global'=false and 'environment' is set" do - opts = {'environment' => 'production', 'global' => false} - expect( @adapter.normalize_key(key, opts) ).to eq normalized_env_key + it "adds the env path when 'global'=false and 'environment' is set" do + opts = { 'environment' => 'production', 'global' => false } + expect(@adapter.normalize_key(key, opts)).to eq normalized_env_key end - it "should add the global path when 'global' is true" do - opts = {'environment' => 'production', 'global' => true} - expect( @adapter.normalize_key(key, opts) ).to eq normalized_global_key + it "adds the global path when 'global' is true" do + opts = { 'environment' => 'production', 'global' => true } + expect(@adapter.normalize_key(key, opts)).to eq normalized_global_key end end context 'with operation=:remove_prefix' do - it "should remove the env path when only 'environment' option is specified" do - opts = {'environment' => 'production'} - expect( @adapter.normalize_key(normalized_env_key, opts, :remove_prefix) ).to eq key + it "removes the env path when only 'environment' option is specified" do + opts = { 'environment' => 'production' } + expect(@adapter.normalize_key(normalized_env_key, opts, :remove_prefix)).to eq key end - it "should remove the env path when 'global'=false and 'environment' is set" do - opts = {'environment' => 'production', 'global' => false} - expect( @adapter.normalize_key(normalized_env_key, opts, :remove_prefix) ).to eq key + it "removes the env path when 'global'=false and 'environment' is set" do + opts = { 'environment' => 'production', 'global' => false } + expect(@adapter.normalize_key(normalized_env_key, opts, :remove_prefix)).to eq key end - it "should remove the global path when 'global' is true" do - opts = {'environment' => 'production', 'global' => true} - expect( @adapter.normalize_key(normalized_global_key, opts, :remove_prefix) ).to eq key + it "removes the global path when 'global' is true" do + opts = { 'environment' => 'production', 'global' => true } + expect(@adapter.normalize_key(normalized_global_key, opts, :remove_prefix)).to eq key end end end context '#plugin_instance' do context 'success cases' do - it 'should create an instance when config is correct' do + it 'creates an instance when config is correct' do instance = @adapter.plugin_instance(@options_file) file_class_id = @adapter.plugin_info['file'][:class].to_s - expect( instance.name ).to eq 'file/test' - expect( instance.to_s ).to match file_class_id + expect(instance.name).to eq 'file/test' + expect(instance.to_s).to match file_class_id end - it 'should retrieve an existing instance' do + it 'retrieves an existing instance' do instance1 = @adapter.plugin_instance(@options_file) instance1_id = instance1.to_s @@ -177,85 +174,83 @@ end context 'error cases' do - it 'should fail when options is not a Hash' do - expect { @adapter.plugin_instance('oops') }. - to raise_error(/Malformed backend config/) + it 'fails when options is not a Hash' do + expect { @adapter.plugin_instance('oops') } + .to raise_error(%r{Malformed backend config}) end - it "should fail when options missing 'backend' key" do - expect { @adapter.plugin_instance({}) }. - to raise_error(/Malformed backend config/) + it "fails when options missing 'backend' key" do + expect { @adapter.plugin_instance({}) } + .to raise_error(%r{Malformed backend config}) end - it "should fail when options missing 'backends' key" do + it "fails when options missing 'backends' key" do options = { 'backend' => 'test' } - expect { @adapter.plugin_instance(options) }. - to raise_error(/Malformed backend config/) + expect { @adapter.plugin_instance(options) } + .to raise_error(%r{Malformed backend config}) end - it "should fail when options 'backends' key is not a Hash" do + it "fails when options 'backends' key is not a Hash" do options = { 'backend' => 'test', 'backends' => 'oops' } - expect { @adapter.plugin_instance(options) }. - to raise_error(/Malformed backend config/) + expect { @adapter.plugin_instance(options) } + .to raise_error(%r{Malformed backend config}) end - it "should fail when options 'backends' does not have the specified backend" do + it "fails when options 'backends' does not have the specified backend" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'} + 'test1' => { 'id' => 'test', 'type' => 'consul' } } } - expect { @adapter.plugin_instance(options) }. - to raise_error(/Malformed backend config/) + expect { @adapter.plugin_instance(options) } + .to raise_error(%r{Malformed backend config}) end - it "should fail when the correct 'backends' element has no 'id' key" do + it "fails when the correct 'backends' element has no 'id' key" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'}, + 'test1' => { 'id' => 'test', 'type' => 'consul' }, 'test' => {} } } - expect { @adapter.plugin_instance(options) }. - to raise_error(/Malformed backend config/) + expect { @adapter.plugin_instance(options) } + .to raise_error(%r{Malformed backend config}) end - it "should fail when the correct 'backends' element has no 'type' key" do + it "fails when the correct 'backends' element has no 'type' key" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'}, + 'test1' => { 'id' => 'test', 'type' => 'consul' }, 'test' => { 'id' => 'test' } } } - expect { @adapter.plugin_instance(options) }. - to raise_error(/Malformed backend config/) + expect { @adapter.plugin_instance(options) } + .to raise_error(%r{Malformed backend config}) end - it "should fail when the correct 'backends' element has wrong 'type' value" do + it "fails when the correct 'backends' element has wrong 'type' value" do options = { 'backend' => 'test', 'backends' => { - 'test1' => { 'id' => 'test', 'type' => 'consul'}, + 'test1' => { 'id' => 'test', 'type' => 'consul' }, 'test' => { 'id' => 'test', 'type' => 'filex' } } } - expect { @adapter.plugin_instance(options) }. - to raise_error(/Malformed backend config/) + expect { @adapter.plugin_instance(options) } + .to raise_error(%r{Malformed backend config}) end - - it 'should fail when plugin instance cannot be created' do - - expect { @adapter.plugin_instance(@options_failer_ctr) }. - to raise_error(/Unable to construct 'failer\/test'/) + it 'fails when plugin instance cannot be created' do + expect { @adapter.plugin_instance(@options_failer_ctr) } + .to raise_error(%r{Unable to construct 'failer/test'}) end end end @@ -267,40 +262,43 @@ end context '#serialize and #serialize_string_value' do - data_info.each do |summary,info| - it "should properly serialize a #{summary}" do - skip info[:skip] if info.has_key?(:skip) - expect( @adapter.serialize(info[:value], info[:metadata]) ). - to eq info[:serialized_value] + data_info.each do |summary, info| + it "properlies serialize a #{summary}" do + skip info[:skip] if info.key?(:skip) + expect(@adapter.serialize(info[:value], info[:metadata])) + .to eq info[:serialized_value] end end end context '#deserialize and #deserialize_string_value' do - data_info.each do |summary,info| - it "should properly deserialize a #{summary}" do - skip info[:skip] if info.has_key?(:skip) - expected = info.has_key?(:deserialized_value) ? info[:deserialized_value] : info[:value] - expect( @adapter.deserialize(info[:serialized_value]) ). - to eq({ :value => expected, :metadata => info[:metadata] }) + data_info.each do |summary, info| + it "properlies deserialize a #{summary}" do + skip info[:skip] if info.key?(:skip) + expected = info.key?(:deserialized_value) ? info[:deserialized_value] : info[:value] + expect(@adapter.deserialize(info[:serialized_value])) + .to eq({ value: expected, metadata: info[:metadata] }) end end - it 'should fail when input is not in JSON format' do - expect{ @adapter.deserialize('this is not JSON')}. to raise_error( - RuntimeError, /Failed to deserialize: JSON parse error/) + it 'fails when input is not in JSON format' do + expect { @adapter.deserialize('this is not JSON') }. to raise_error( + RuntimeError, %r{Failed to deserialize: JSON parse error} + ) end - it "should fail when input does not have 'value' key" do - expect{ @adapter.deserialize('{"Value":255}')}. to raise_error( - RuntimeError, /Failed to deserialize: 'value' missing/) + it "fails when input does not have 'value' key" do + expect { @adapter.deserialize('{"Value":255}') }. to raise_error( + RuntimeError, %r{Failed to deserialize: 'value' missing} + ) end - it "should fail when input has unsupported 'encoding' key" do - serialized_value = '{"value":"some value","encoding":"oops",' + - '"original_encoding":"ASCII-8BIT"}' - expect{ @adapter.deserialize(serialized_value)}. to raise_error( - RuntimeError, /Failed to deserialize: Unsupported encoding/) + it "fails when input has unsupported 'encoding' key" do + serialized_value = '{"value":"some value","encoding":"oops",' \ + '"original_encoding":"ASCII-8BIT"}' + expect { @adapter.deserialize(serialized_value) }. to raise_error( + RuntimeError, %r{Failed to deserialize: Unsupported encoding} + ) end end end @@ -319,205 +317,206 @@ let(:key_plus_env) { 'environments/production/my/test/key' } let(:value) { 'some string' } let(:metadata) { { 'foo' => 'bar' } } - let(:serialized_value) { + let(:serialized_value) do '{"value":"some string","metadata":{"foo":"bar"}}' - } + end context '#backends' do - it 'should list available backend plugins' do + it 'lists available backend plugins' do # currently only 3 plugins (2 real and 1 for test only) - expect( @adapter.backends.sort ).to eq([ 'failer', 'file', 'ldap' ]) + expect(@adapter.backends.sort).to eq([ 'failer', 'file', 'ldap' ]) end end context '#delete' do - it 'should return plugin delete result' do + it 'returns plugin delete result' do @plugin.put(key_plus_env, serialized_value) - expect(@adapter.delete(key, @options_file)). - to eq({:result => true, :err_msg => nil}) + expect(@adapter.delete(key, @options_file)) + .to eq({ result: true, err_msg: nil }) - expect(@plugin.exists(key_plus_env)). - to eq({:result => false, :err_msg => nil}) + expect(@plugin.exists(key_plus_env)) + .to eq({ result: false, err_msg: nil }) end - it 'should return a failed result when plugin instance cannot be created' do + it 'returns a failed result when plugin instance cannot be created' do result = @adapter.delete(key, @options_failer_ctr) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/simpkv Error: Unable to construct 'failer\/test'/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{simpkv Error: Unable to construct 'failer/test'}) end - it 'should fail when plugin delete raises an exception' do + it 'fails when plugin delete raises an exception' do result = @adapter.delete(key, @options_failer) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/simpkv failer\/test Error: delete catastrophic failure/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{simpkv failer/test Error: delete catastrophic failure}) end end context '#deletetree' do - let(:keydir) { key.gsub('/key','') } - it 'should return plugin deletetree result' do + let(:keydir) { key.gsub('/key', '') } + + it 'returns plugin deletetree result' do @plugin.put(key_plus_env, serialized_value) - expect(@adapter.deletetree(keydir, @options_file)). - to eq({:result => true, :err_msg => nil}) + expect(@adapter.deletetree(keydir, @options_file)) + .to eq({ result: true, err_msg: nil }) - expect(@plugin.exists(key_plus_env)). - to eq({:result => false, :err_msg => nil}) + expect(@plugin.exists(key_plus_env)) + .to eq({ result: false, err_msg: nil }) end - it 'should return a failed result when plugin instance cannot be created' do + it 'returns a failed result when plugin instance cannot be created' do result = @adapter.deletetree(keydir, @options_failer_ctr) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/simpkv Error: Unable to construct 'failer\/test'/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{simpkv Error: Unable to construct 'failer/test'}) end - it 'should fail when plugin deletetree raises an exception' do + it 'fails when plugin deletetree raises an exception' do result = @adapter.deletetree(keydir, @options_failer) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/simpkv failer\/test Error: deletetree catastrophic failure/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{simpkv failer/test Error: deletetree catastrophic failure}) end end context '#exists' do - it 'should return plugin exists result for a key' do + it 'returns plugin exists result for a key' do @plugin.put(key_plus_env, serialized_value) - expect(@adapter.exists(key, @options_file)). - to eq({:result => true, :err_msg => nil}) + expect(@adapter.exists(key, @options_file)) + .to eq({ result: true, err_msg: nil }) end - it 'should return plugin exists result for a keydir' do + it 'returns plugin exists result for a keydir' do @plugin.put(key_plus_env, serialized_value) - expect(@adapter.exists(File.dirname(key), @options_file)). - to eq({:result => true, :err_msg => nil}) + expect(@adapter.exists(File.dirname(key), @options_file)) + .to eq({ result: true, err_msg: nil }) end - it 'should return a failed result when plugin instance cannot be created' do + it 'returns a failed result when plugin instance cannot be created' do result = @adapter.exists(key, @options_failer_ctr) - expect( result[:result] ).to be nil - expect( result[:err_msg] ).to match(/simpkv Error: Unable to construct 'failer\/test'/) + expect(result[:result]).to be nil + expect(result[:err_msg]).to match(%r{simpkv Error: Unable to construct 'failer/test'}) end - it 'should fail when plugin exists raises an exception' do + it 'fails when plugin exists raises an exception' do result = @adapter.exists(key, @options_failer) - expect( result[:result] ).to be nil - expect( result[:err_msg] ).to match(/simpkv failer\/test Error: exists catastrophic failure/) + expect(result[:result]).to be nil + expect(result[:err_msg]).to match(%r{simpkv failer/test Error: exists catastrophic failure}) end end context '#get' do - it 'should return deserialized plugin get result' do + it 'returns deserialized plugin get result' do @plugin.put(key_plus_env, serialized_value) - expect(@adapter.get(key, @options_file)). - to eq({ - :result => {:value => value, :metadata => metadata}, - :err_msg => nil - }) + expect(@adapter.get(key, @options_file)) + .to eq({ + result: { value: value, metadata: metadata }, + err_msg: nil + }) end - it 'should return a failed result when deserialization of plugin get result fails' do + it 'returns a failed result when deserialization of plugin get result fails' do @plugin.put(key_plus_env, 'This is not JSON') result = @adapter.get(key, @options_file) - expect( result.fetch(:result) ).to be_nil - expect( result[:err_msg] ).to match(/simpkv file\/test Error: Failed to deserialize/) + expect(result.fetch(:result)).to be_nil + expect(result[:err_msg]).to match(%r{simpkv file/test Error: Failed to deserialize}) end - it 'should return a failed result when plugin instance cannot be created' do + it 'returns a failed result when plugin instance cannot be created' do result = @adapter.get(key, @options_failer_ctr) - expect( result[:result] ).to be nil - expect( result[:err_msg] ).to match(/simpkv Error: Unable to construct 'failer\/test'/) + expect(result[:result]).to be nil + expect(result[:err_msg]).to match(%r{simpkv Error: Unable to construct 'failer/test'}) end - it 'should fail when plugin get raises an exception' do + it 'fails when plugin get raises an exception' do result = @adapter.get(key, @options_failer) - expect( result[:result] ).to be nil - expect( result[:err_msg] ).to match(/simpkv failer\/test Error: get catastrophic failure/) + expect(result[:result]).to be nil + expect(result[:err_msg]).to match(%r{simpkv failer/test Error: get catastrophic failure}) end end context '#list' do - let(:keydir) { key.gsub('/key','') } - it 'should return deserialized plugin list result' do + let(:keydir) { key.gsub('/key', '') } + + it 'returns deserialized plugin list result' do @plugin.put(key_plus_env, serialized_value) # create a sub-folder @plugin.put(key_plus_env.gsub('/key', '/app1/key'), serialized_value) - expect(@adapter.list(keydir, @options_file)). - to eq({ - :result => { - :keys => { - File.basename(key) => {:value => value, :metadata => metadata}, - }, - :folders => [ 'app1' ] - }, - :err_msg => nil - }) - end - - it "should return list of top level folders for the environment when passed '/' as the key" do + expect(@adapter.list(keydir, @options_file)) + .to eq({ + result: { + keys: { + File.basename(key) => { value: value, metadata: metadata }, + }, + folders: [ 'app1' ] + }, + err_msg: nil + }) + end + + it "returns list of top level folders for the environment when passed '/' as the key" do @plugin.put(key_plus_env, serialized_value) - expect(@adapter.list('/', @options_file)). - to eq({ - :result => { - :keys => {}, - :folders => [ 'my' ] - }, - :err_msg => nil - }) + expect(@adapter.list('/', @options_file)) + .to eq({ + result: { + keys: {}, + folders: [ 'my' ] + }, + err_msg: nil + }) end - it "should return list of environments when passed '/' as the key and environment is set to ''" do + it "returns list of environments when passed '/' as the key and environment is set to ''" do @plugin.put(key_plus_env, serialized_value) options = @options_file.dup - options['environment'] ='' - expect(@adapter.list('/', options)). - to eq({ - :result => { - :keys => {}, - :folders => [ 'production' ] - }, - :err_msg => nil - }) - end - - it 'should return a failed result when deserialization of plugin list result fails' do + options['environment'] = '' + expect(@adapter.list('/', options)) + .to eq({ + result: { + keys: {}, + folders: [ 'production' ] + }, + err_msg: nil + }) + end + + it 'returns a failed result when deserialization of plugin list result fails' do @plugin.put(key_plus_env, 'This is not JSON') result = @adapter.list(keydir, @options_file) - expect( result.fetch(:result) ).to be_nil - expect( result[:err_msg] ).to match(/simpkv file\/test Error: Failed to deserialize/) + expect(result.fetch(:result)).to be_nil + expect(result[:err_msg]).to match(%r{simpkv file/test Error: Failed to deserialize}) end - it 'should return a failed result when plugin instance cannot be created' do + it 'returns a failed result when plugin instance cannot be created' do result = @adapter.list(keydir, @options_failer_ctr) - expect( result[:result] ).to be nil - expect( result[:err_msg] ).to match(/simpkv Error: Unable to construct 'failer\/test'/) + expect(result[:result]).to be nil + expect(result[:err_msg]).to match(%r{simpkv Error: Unable to construct 'failer/test'}) end - it 'should fail when plugin list raises an exception' do + it 'fails when plugin list raises an exception' do result = @adapter.list(keydir, @options_failer) - expect( result[:result] ).to be nil - expect( result[:err_msg] ).to match(/simpkv failer\/test Error: list catastrophic failure/) + expect(result[:result]).to be nil + expect(result[:err_msg]).to match(%r{simpkv failer/test Error: list catastrophic failure}) end end context '#put' do - it 'should return plugin put result' do - expect(@adapter.put(key, value, metadata, @options_file)). - to eq({:result => true, :err_msg => nil}) + it 'returns plugin put result' do + expect(@adapter.put(key, value, metadata, @options_file)) + .to eq({ result: true, err_msg: nil }) - expect(@plugin.exists(key_plus_env)). - to eq({:result => true, :err_msg => nil}) + expect(@plugin.exists(key_plus_env)) + .to eq({ result: true, err_msg: nil }) end - it 'should return a failed result when plugin instance cannot be created' do + it 'returns a failed result when plugin instance cannot be created' do result = @adapter.put(key, value, metadata, @options_failer_ctr) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/simpkv Error: Unable to construct 'failer\/test'/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{simpkv Error: Unable to construct 'failer/test'}) end - it 'should fail when plugin put raises an exception' do + it 'fails when plugin put raises an exception' do result = @adapter.put(key, value, metadata, @options_failer) - expect( result[:result] ).to be false - expect( result[:err_msg] ).to match(/simpkv failer\/test Error: put catastrophic failure/) + expect(result[:result]).to be false + expect(result[:err_msg]).to match(%r{simpkv failer/test Error: put catastrophic failure}) end end end - end