diff --git a/.rubocop.yml b/.rubocop.yml index eb8aa56ed..39664d024 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,3 +6,8 @@ inherit_gem: AllCops: TargetRubyVersion: '3.2' + Exclude: + - vendor/**/* + - .vendor/**/* + - spec/fixtures/**/* + - modules/**/* diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 2b586bbdc..7d2bf4490 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,19 +1,18 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-auto-gen-timestamp` -# using RuboCop version 1.75.8. +# using RuboCop version 1.79.2. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 15 +# Offense count: 14 # This cop supports safe autocorrection (--autocorrect). Layout/ClosingHeredocIndentation: Exclude: - 'acceptance/setup/common/pre-suite/010_install_ruby.rb' - 'acceptance/tests/apply_plan_ssh.rb' - 'lib/bolt/inventory/group.rb' - - 'scripts/server_client.rb' - 'spec/integration/transport/winrm_spec.rb' - 'spec/pal/result_set_spec.rb' - 'spec/pal/result_spec.rb' @@ -22,12 +21,7 @@ Layout/ClosingHeredocIndentation: - 'spec/unit/pal_spec.rb' - 'spec/unit/util/format_spec.rb' -# Offense count: 124 -# This cop supports safe autocorrection (--autocorrect). -Layout/EmptyLineAfterGuardClause: - Enabled: false - -# Offense count: 666 +# Offense count: 656 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. # SupportedHashRocketStyles: key, separator, table @@ -36,29 +30,11 @@ Layout/EmptyLineAfterGuardClause: Layout/HashAlignment: Enabled: false -# Offense count: 54 +# Offense count: 53 # This cop supports safe autocorrection (--autocorrect). Layout/HeredocIndentation: Enabled: false -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: leading, trailing -Layout/LineContinuationLeadingSpace: - Exclude: - - 'lib/bolt/config/transport/options.rb' - - 'lib/bolt/pal/yaml_plan/parameter.rb' - - 'rakelib/docs.rake' - - 'spec/unit/pal/yaml_plan/step_spec.rb' - -# Offense count: 252 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: space, no_space -Layout/LineContinuationSpacing: - Enabled: false - # Offense count: 24 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, IndentationWidth. @@ -66,28 +42,6 @@ Layout/LineContinuationSpacing: Layout/LineEndStringConcatenationIndentation: Enabled: false -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: final_newline, final_blank_line -Layout/TrailingEmptyLines: - Exclude: - - 'modules/aggregate/lib/puppet/functions/aggregate/nodes.rb' - - 'modules/aggregate/spec/functions/nodes_spec.rb' - -# Offense count: 14 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowInHeredoc. -Layout/TrailingWhitespace: - Exclude: - - 'lib/bolt/bolt_option_parser.rb' - - 'lib/bolt/module_installer/puppetfile.rb' - - 'lib/bolt/outputter/human.rb' - - 'lib/bolt/pal/yaml_plan/step/resources.rb' - - 'lib/bolt/plan_creator.rb' - - 'spec/integration/transport/winrm_spec.rb' - - 'spec/unit/outputter/human_spec.rb' - # Offense count: 11 # This cop supports safe autocorrection (--autocorrect). Lint/AmbiguousOperatorPrecedence: @@ -157,7 +111,12 @@ Lint/UselessConstantScoping: Exclude: - 'lib/bolt/transport/winrm/connection.rb' -# Offense count: 8 +# Offense count: 2 +Lint/UselessOr: + Exclude: + - 'spec/integration/transport/winrm_spec.rb' + +# Offense count: 6 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, BlockForwardingName. # SupportedStyles: anonymous, explicit @@ -165,10 +124,30 @@ Naming/BlockForwarding: Exclude: - 'lib/bolt/executor.rb' - 'lib/bolt/pal.rb' - - 'lib/bolt_server/file_cache.rb' - 'lib/bolt_spec/bolt_context.rb' -# Offense count: 15 +# Offense count: 16 +# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates. +# AllowedMethods: call +# WaywardPredicates: nonzero? +Naming/PredicateMethod: + Exclude: + - 'bolt-modules/file/lib/puppet/functions/file/exists.rb' + - 'bolt-modules/file/lib/puppet/functions/file/readable.rb' + - 'lib/bolt/module_installer/specs/id/gitclone.rb' + - 'lib/bolt/pal/yaml_plan/parameter.rb' + - 'lib/bolt/project_manager/config_migrator.rb' + - 'lib/bolt/puppetdb/config.rb' + - 'lib/bolt/result_set.rb' + - 'lib/bolt_spec/plans/action_stubs/command_stub.rb' + - 'lib/bolt_spec/plans/action_stubs/download_stub.rb' + - 'lib/bolt_spec/plans/action_stubs/plan_stub.rb' + - 'lib/bolt_spec/plans/action_stubs/script_stub.rb' + - 'lib/bolt_spec/plans/action_stubs/task_stub.rb' + - 'lib/bolt_spec/plans/action_stubs/upload_stub.rb' + - 'lib/bolt_spec/plans/publish_stub.rb' + +# Offense count: 13 # Configuration parameters: MinSize. Performance/CollectionLiteralInLoop: Exclude: @@ -177,7 +156,6 @@ Performance/CollectionLiteralInLoop: - 'lib/bolt/fiber_executor.rb' - 'lib/bolt/outputter/human.rb' - 'lib/bolt/result.rb' - - 'lib/bolt/transport/orch.rb' - 'lib/bolt/transport/winrm/connection.rb' - 'libexec/apply_catalog.rb' - 'rakelib/pwsh.rake' @@ -231,11 +209,10 @@ Performance/MapCompact: - 'lib/bolt/applicator.rb' - 'lib/bolt_spec/plans/mock_executor.rb' -# Offense count: 3 +# Offense count: 2 Performance/MapMethodChain: Exclude: - 'lib/bolt/outputter/human.rb' - - 'spec/unit/executor_spec.rb' # Offense count: 6 Performance/MethodObjectAsBlock: @@ -293,12 +270,6 @@ Performance/Sum: Exclude: - 'lib/bolt/executor.rb' -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Performance/TimesMap: - Exclude: - - 'spec/bolt_server/file_cache_spec.rb' - # Offense count: 13 # This cop supports unsafe autocorrection (--autocorrect-all). Performance/UnfreezeString: @@ -320,11 +291,11 @@ Performance/ZipWithoutBlock: Exclude: - 'lib/bolt/transport/base.rb' -# Offense count: 33 +# Offense count: 29 RSpec/AnyInstance: Enabled: false -# Offense count: 45 +# Offense count: 44 RSpec/Be: Enabled: false @@ -335,18 +306,12 @@ RSpec/BeEmpty: Exclude: - 'spec/unit/project_manager/module_migrator_spec.rb' -# Offense count: 103 +# Offense count: 93 # This cop supports unsafe autocorrection (--autocorrect-all). RSpec/BeEq: Enabled: false -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -RSpec/BeEql: - Exclude: - - 'modules/puppet_connect/spec/plans/test_input_data_spec.rb' - -# Offense count: 17 +# Offense count: 15 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: be, be_nil @@ -358,9 +323,27 @@ RSpec/BeNil: - 'spec/unit/project_manager/module_migrator_spec.rb' - 'spec/unit/target_spec.rb' -# Offense count: 27 +# Offense count: 20 RSpec/BeforeAfterAll: - Enabled: false + Exclude: + - '**/spec/spec_helper.rb' + - '**/spec/rails_helper.rb' + - '**/spec/support/**/*.rb' + - 'bolt-modules/boltlib/spec/functions/run_container_spec.rb' + - 'spec/bolt_spec/run_spec.rb' + - 'spec/integration/apply_spec.rb' + - 'spec/integration/puppetdb/client_spec.rb' + - 'spec/integration/puppetdb/puppetdb_spec.rb' + - 'spec/pal/apply_result_spec.rb' + - 'spec/pal/facts_spec.rb' + - 'spec/pal/features_spec.rb' + - 'spec/pal/result_set_spec.rb' + - 'spec/pal/result_spec.rb' + - 'spec/pal/target_spec.rb' + - 'spec/pal/vars_spec.rb' + - 'spec/shared_examples/transport.rb' + - 'spec/unit/logger_spec.rb' + - 'spec/unit/pal_spec.rb' # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). @@ -375,22 +358,21 @@ RSpec/ClassCheck: RSpec/ContextMethod: Enabled: false -# Offense count: 341 +# Offense count: 331 # Configuration parameters: Prefixes, AllowedPatterns. # Prefixes: when, with, without RSpec/ContextWording: Enabled: false -# Offense count: 120 +# Offense count: 109 # Configuration parameters: IgnoredMetadata. RSpec/DescribeClass: Enabled: false -# Offense count: 28 +# Offense count: 20 RSpec/DescribeSymbol: Exclude: - 'spec/integration/pal_spec.rb' - - 'spec/integration/transport/orch_spec.rb' - 'spec/unit/apply_result_spec.rb' - 'spec/unit/inventory/inventory_spec.rb' - 'spec/unit/inventory_spec.rb' @@ -399,65 +381,34 @@ RSpec/DescribeSymbol: - 'spec/unit/plugin/module_spec.rb' - 'spec/unit/result_spec.rb' -# Offense count: 283 +# Offense count: 268 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants. # SupportedStyles: described_class, explicit RSpec/DescribedClass: Enabled: false -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -RSpec/EmptyLineAfterExampleGroup: - Exclude: - - 'spec/bolt_server/transport_app_spec.rb' - -# Offense count: 43 -# This cop supports safe autocorrection (--autocorrect). -RSpec/EmptyLineAfterFinalLet: - Enabled: false - -# Offense count: 5 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowConsecutiveOneLiners. -RSpec/EmptyLineAfterHook: - Exclude: - - 'spec/integration/local_spec.rb' - - 'spec/integration/transpiler_spec.rb' - - 'spec/unit/executor_spec.rb' - - 'spec/unit/fiber_executor_spec.rb' - - 'spec/unit/pal_spec.rb' - -# Offense count: 729 +# Offense count: 655 # Configuration parameters: CountAsOne. RSpec/ExampleLength: Max: 42 -# Offense count: 182 +# Offense count: 177 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: CustomTransform, IgnoredWords, DisallowedExamples. # DisallowedExamples: works RSpec/ExampleWording: Enabled: false -# Offense count: 4 -# This cop supports safe autocorrection (--autocorrect). -RSpec/ExcessiveDocstringSpacing: - Exclude: - - 'spec/bolt_server/config_spec.rb' - - 'spec/integration/transport/winrm_spec.rb' - - 'spec/unit/plugin/puppetdb_spec.rb' - -# Offense count: 35 +# Offense count: 32 RSpec/ExpectInHook: Exclude: - 'spec/bolt_spec/run_spec.rb' - 'spec/integration/logging_spec.rb' - 'spec/integration/modules/write_file_spec.rb' - - 'spec/integration/transport/orch_spec.rb' - 'spec/unit/cli_spec.rb' -# Offense count: 283 +# Offense count: 276 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: implicit, each, example @@ -469,31 +420,30 @@ RSpec/IdenticalEqualityAssertion: Exclude: - 'spec/unit/application_spec.rb' -# Offense count: 381 +# Offense count: 371 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: single_line_only, single_statement_only, disallow, require_implicit RSpec/ImplicitSubject: Enabled: false -# Offense count: 74 +# Offense count: 71 # This cop supports safe autocorrection (--autocorrect). RSpec/IncludeExamples: Enabled: false -# Offense count: 16 +# Offense count: 14 # Configuration parameters: Max, AllowedIdentifiers, AllowedPatterns. RSpec/IndexedLet: Exclude: - 'bolt-modules/boltlib/spec/functions/remove_from_group_spec.rb' - - 'spec/unit/executor_spec.rb' - 'spec/unit/module_installer/specs_spec.rb' - 'spec/unit/outputter/json_spec.rb' - 'spec/unit/project_manager/inventory_migrator_spec.rb' - 'spec/unit/result_set_spec.rb' - 'spec/unit/util/format_spec.rb' -# Offense count: 257 +# Offense count: 255 # Configuration parameters: AssignmentOnly. RSpec/InstanceVariable: Enabled: false @@ -525,13 +475,13 @@ RSpec/MatchArray: - 'spec/unit/target_spec.rb' - 'spec/unit/transport/ssh/connection_spec.rb' -# Offense count: 364 +# Offense count: 336 # Configuration parameters: . # SupportedStyles: have_received, receive RSpec/MessageSpies: EnforcedStyle: receive -# Offense count: 160 +# Offense count: 154 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: hash, symbol @@ -546,11 +496,7 @@ RSpec/MultipleDescribes: - 'spec/unit/analytics_spec.rb' - 'spec/unit/config/options_spec.rb' -# Offense count: 723 -RSpec/MultipleExpectations: - Max: 9 - -# Offense count: 681 +# Offense count: 649 # Configuration parameters: AllowSubject. RSpec/MultipleMemoizedHelpers: Max: 27 @@ -571,7 +517,7 @@ RSpec/NamedSubject: - 'spec/unit/transport/ssh/connection_spec.rb' - 'spec/unit/transport/ssh/exec_connection_spec.rb' -# Offense count: 114 +# Offense count: 93 # Configuration parameters: AllowedGroups. RSpec/NestedGroups: Max: 5 @@ -644,23 +590,21 @@ RSpec/RepeatedExample: - 'spec/integration/private_plan_spec.rb' - 'spec/integration/project_spec.rb' -# Offense count: 11 +# Offense count: 8 RSpec/RepeatedExampleGroupDescription: Exclude: - - 'spec/bolt_server/transport_app_spec.rb' - 'spec/integration/docker_spec.rb' - 'spec/integration/pal_spec.rb' - 'spec/unit/plan_future_spec.rb' - 'spec/unit/plugin/puppet_library_spec.rb' -# Offense count: 13 +# Offense count: 12 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AutoCorrect. RSpec/ScatteredLet: Exclude: - 'bolt-modules/boltlib/spec/functions/set_resources_spec.rb' - 'spec/integration/inventory_spec.rb' - - 'spec/integration/transport/orch_spec.rb' - 'spec/unit/applicator_spec.rb' - 'spec/unit/executor_spec.rb' @@ -671,7 +615,7 @@ RSpec/SortMetadata: - 'spec/integration/apply_error_spec.rb' - 'spec/integration/inventory_spec.rb' -# Offense count: 80 +# Offense count: 78 # Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata. # Include: **/*_spec.rb RSpec/SpecFilePathFormat: @@ -686,7 +630,7 @@ RSpec/SpecFilePathSuffix: - 'bolt-modules/boltlib/spec/functions/puppetdb_query.rb' - 'spec/integration/task_param.rb' -# Offense count: 127 +# Offense count: 104 RSpec/StubbedMock: Enabled: false @@ -711,24 +655,22 @@ RSpec/VariableDefinition: Exclude: - 'spec/integration/plugin/task_spec.rb' -# Offense count: 7 +# Offense count: 4 # This cop supports unsafe autocorrection (--autocorrect-all). RSpec/VerifiedDoubleReference: Exclude: - - 'spec/integration/transport/orch_spec.rb' - 'spec/lib/bolt_spec/logger.rb' - 'spec/unit/applicator_spec.rb' - 'spec/unit/inventory/group_spec.rb' -# Offense count: 111 +# Offense count: 109 # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. RSpec/VerifiedDoubles: Enabled: false -# Offense count: 2 +# Offense count: 1 RSpec/VoidExpect: Exclude: - - 'spec/bolt_server/app_integration_spec.rb' - 'spec/unit/plugin/env_var_spec.rb' # Offense count: 2 @@ -738,14 +680,14 @@ RSpec/Yield: - 'spec/unit/application_spec.rb' - 'spec/unit/cli_spec.rb' -# Offense count: 52 +# Offense count: 51 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols, AllowModifiersOnAttrs, AllowModifiersOnAliasMethod. # SupportedStyles: inline, group Style/AccessModifierDeclarations: Enabled: false -# Offense count: 30 +# Offense count: 28 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowOnlyRestArgument, UseAnonymousForwarding, RedundantRestArgumentNames, RedundantKeywordRestArgumentNames, RedundantBlockArgumentNames. # RedundantRestArgumentNames: args, arguments @@ -759,7 +701,6 @@ Style/ArgumentsForwarding: - 'lib/bolt/outputter/json.rb' - 'lib/bolt/pal.rb' - 'lib/bolt/plan_result.rb' - - 'lib/bolt_server/file_cache.rb' - 'lib/bolt_spec/bolt_context.rb' - 'spec/lib/bolt_spec/integration.rb' @@ -769,7 +710,7 @@ Style/ArrayIntersect: Exclude: - 'bolt-modules/boltlib/lib/puppet/functions/download_file.rb' -# Offense count: 273 +# Offense count: 242 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces @@ -787,7 +728,7 @@ Style/ConcatArrayLiterals: - 'spec/integration/cli/cli_spec.rb' - 'spec/unit/module_installer_spec.rb' -# Offense count: 193 +# Offense count: 181 # Configuration parameters: AllowedConstants. Style/Documentation: Enabled: false @@ -818,9 +759,9 @@ Style/ExplicitBlockArgument: - 'lib/bolt/result_set.rb' - 'spec/lib/bolt_spec/errors.rb' -# Offense count: 17 +# Offense count: 16 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowedVars. +# Configuration parameters: AllowedVars, DefaultToNil. Style/FetchEnvVar: Exclude: - 'acceptance/Rakefile' @@ -832,7 +773,6 @@ Style/FetchEnvVar: - 'lib/bolt/config.rb' - 'lib/bolt/plugin/env_var.rb' - 'lib/bolt/puppetdb/config.rb' - - 'lib/bolt_server/config.rb' - 'scripts/generate_changelog.rb' - 'spec/integration/local_spec.rb' - 'spec/lib/bolt_spec/env_var.rb' @@ -849,24 +789,22 @@ Style/FileNull: Exclude: - 'lib/bolt/puppetdb/config.rb' -# Offense count: 6 +# Offense count: 4 # This cop supports safe autocorrection (--autocorrect). Style/FileRead: Exclude: - - 'lib/bolt/transport/orch.rb' - 'libexec/bolt_catalog' - 'spec/integration/local_spec.rb' - 'spec/integration/transport/ssh_spec.rb' - 'spec/integration/winrm_spec.rb' -# Offense count: 2 +# Offense count: 1 # This cop supports safe autocorrection (--autocorrect). Style/FileWrite: Exclude: - - 'lib/bolt_server/file_cache.rb' - 'spec/lib/bolt_spec/pal.rb' -# Offense count: 107 +# Offense count: 97 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. Style/GuardClause: @@ -884,14 +822,12 @@ Style/HashAsLastArrayItem: - 'spec/unit/applicator_spec.rb' - 'spec/unit/pal/yaml_plan/evaluator_spec.rb' -# Offense count: 4 +# Offense count: 2 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowSplatArgument. Style/HashConversion: Exclude: - 'lib/bolt/cli.rb' - - 'lib/bolt/transport/orch.rb' - - 'lib/bolt_server/transport_app.rb' # Offense count: 4 # This cop supports unsafe autocorrection (--autocorrect-all). @@ -904,33 +840,19 @@ Style/HashEachMethods: - 'lib/bolt/shell/bash.rb' - 'spec/unit/executor_spec.rb' -# Offense count: 6 +# Offense count: 5 # This cop supports unsafe autocorrection (--autocorrect-all). Style/HashExcept: Exclude: - 'lib/bolt/module_installer.rb' - 'lib/bolt/plugin/cache.rb' - 'lib/bolt/result.rb' - - 'lib/bolt/transport/orch/connection.rb' -# Offense count: 3 -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/HashSlice: - Exclude: - - 'lib/bolt/transport/orch/connection.rb' - - 'lib/bolt_server/base_config.rb' - -# Offense count: 159 +# Offense count: 160 # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Enabled: false -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/MapIntoArray: - Exclude: - - 'lib/bolt_server/acl.rb' - # Offense count: 7 # This cop supports unsafe autocorrection (--autocorrect-all). Style/MapToHash: @@ -957,13 +879,13 @@ Style/MutableConstant: Exclude: - 'lib/bolt/bolt_option_parser.rb' -# Offense count: 32 +# Offense count: 27 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: Strict, AllowedNumbers, AllowedPatterns. Style/NumericLiterals: MinDigits: 7 -# Offense count: 14 +# Offense count: 13 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison @@ -978,11 +900,10 @@ Style/NumericPredicate: - 'lib/bolt/puppetdb/config.rb' - 'lib/bolt/result.rb' - 'lib/bolt/transport/ssh/connection.rb' - - 'lib/bolt_server/transport_app.rb' - 'lib/bolt_spec/plans/action_stubs.rb' - 'libexec/apply_catalog.rb' -# Offense count: 20 +# Offense count: 19 # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: @@ -1015,11 +936,10 @@ Style/RedundantFreeze: - 'lib/bolt/pal/yaml_plan.rb' - 'libexec/query_resources.rb' -# Offense count: 6 +# Offense count: 5 # This cop supports safe autocorrection (--autocorrect). Style/RedundantInterpolationUnfreeze: Exclude: - - 'config/transport_service_config.rb' - 'lib/bolt/inventory/group.rb' - 'lib/bolt/outputter/human.rb' - 'rakelib/pwsh.rake' @@ -1038,12 +958,11 @@ Style/RedundantRegexpArgument: - 'lib/bolt/pal/yaml_plan/step/eval.rb' - 'rakelib/docs.rake' -# Offense count: 3 +# Offense count: 2 # This cop supports safe autocorrection (--autocorrect). Style/RedundantSelfAssignmentBranch: Exclude: - 'lib/bolt/catalog/logging.rb' - - 'lib/bolt_server/transport_app.rb' - 'rakelib/schemas.rake' # Offense count: 10 @@ -1135,7 +1054,7 @@ Style/StderrPuts: Style/StringConcatenation: Enabled: false -# Offense count: 3463 +# Offense count: 3271 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes @@ -1151,28 +1070,28 @@ Style/SuperArguments: - 'lib/bolt/error.rb' - 'lib/bolt_spec/plans/action_stubs/plan_stub.rb' -# Offense count: 30 +# Offense count: 29 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, AllowSafeAssignment. # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex Style/TernaryParentheses: Enabled: false -# Offense count: 539 +# Offense count: 522 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInArguments: Enabled: false -# Offense count: 246 +# Offense count: 225 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma Style/TrailingCommaInArrayLiteral: Enabled: false -# Offense count: 1609 +# Offense count: 1510 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma @@ -1184,3 +1103,10 @@ Style/TrailingCommaInHashLiteral: Style/YAMLFileRead: Exclude: - 'spec/unit/module_installer_spec.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. +# URISchemes: http, https +Layout/LineLength: + Max: 121 diff --git a/acceptance/tests/task_local.rb b/acceptance/tests/task_local.rb index d61f8cb36..6ef5e7317 100644 --- a/acceptance/tests/task_local.rb +++ b/acceptance/tests/task_local.rb @@ -6,6 +6,7 @@ test_name "bolt task run should execute tasks on localhost via local transport" do extend Acceptance::BoltCommandHelper extend Acceptance::BoltSetupHelper + dir = bolt.tmpdir('local_task') if bolt['platform'] =~ /windows/ diff --git a/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb b/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb index db9c5b5de..2813d72b6 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb @@ -84,6 +84,7 @@ def run_task(targets, task, args = {}, options = {}) tarball = applicator.build_plugin_tarball do |mod| next unless required_modules.empty? || required_modules.include?(mod.name) + search_dirs = [] search_dirs << mod.plugins if mod.plugins? search_dirs << mod.pluginfacts if mod.pluginfacts? @@ -111,6 +112,7 @@ def run_task(targets, task, args = {}, options = {}) hook_results.each do |result| next unless result.ok? + inventory.set_feature(result.target, 'puppet-agent') end @@ -143,7 +145,7 @@ def run_task(targets, task, args = {}, options = {}) if unsupported_puppet?(result['clientversion']) Bolt::Logger.deprecate( "unsupported_puppet", - "Detected unsupported Puppet agent version #{result['clientversion']} on target "\ + "Detected unsupported Puppet agent version #{result['clientversion']} on target " \ "#{result.target}. Bolt supports Puppet agent 6.0.0 and higher." ) end diff --git a/bolt-modules/boltlib/lib/puppet/functions/download_file.rb b/bolt-modules/boltlib/lib/puppet/functions/download_file.rb index 2cd76eddc..06c7500ca 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/download_file.rb @@ -124,6 +124,7 @@ def download_file_with_description(source, destination, targets, description = n if !r.ok && !options[:catch_errors] raise Bolt::RunFailure.new(r, 'download_file', source) end + r end end diff --git a/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb b/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb index 30aad0687..10e321032 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb @@ -34,6 +34,7 @@ def run_task(executor, targets, name, args = {}) task = Bolt::Task.from_task_signature(tasksig) results = executor.run_task(targets, task, args) raise Bolt::RunFailure.new(results, 'run_task', task.name) unless results.ok? + results end @@ -80,6 +81,7 @@ def get_resources(target_spec, resources) } results = executor.run_task(targets, task, arguments) raise Bolt::RunFailure.new(results, 'run_task', task.name) unless results.ok? + results end end diff --git a/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb b/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb index f345dd0e5..9e04a2644 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb @@ -86,7 +86,7 @@ def puppetdb_command_with_instance(command, version, payload, instance) # Error if the PDB client does not implement :send_command unless puppetdb_client.respond_to?(:send_command) raise Bolt::Error.new( - "PuppetDB client #{puppetdb_client.class} does not implement :send_command, "\ + "PuppetDB client #{puppetdb_client.class} does not implement :send_command, " \ "unable to invoke command.", 'bolt/pdb-command' ) diff --git a/bolt-modules/boltlib/lib/puppet/functions/run_container.rb b/bolt-modules/boltlib/lib/puppet/functions/run_container.rb index f61f537d3..1d6f0a836 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/run_container.rb @@ -127,7 +127,7 @@ def validate_options(options) end if (bad_vs = volumes.reject { |k, v| k.is_a?(String) && v.is_a?(String) }).any? - msg = "Option 'volumes' only accepts strings for keys and values. "\ + msg = "Option 'volumes' only accepts strings for keys and values. " \ "Received: #{bad_vs.map(&:inspect).join(', ')}" raise Bolt::ValidationError, msg end @@ -153,7 +153,7 @@ def validate_options(options) end if (bad_ps = ports.reject { |k, v| k.is_a?(Integer) && v.is_a?(Integer) }).any? - msg = "Option 'ports' only accepts integers for keys and values. "\ + msg = "Option 'ports' only accepts integers for keys and values. " \ "Received: #{bad_ps.map(&:inspect).join(', ')}" raise Bolt::ValidationError, msg end diff --git a/bolt-modules/boltlib/lib/puppet/functions/run_script.rb b/bolt-modules/boltlib/lib/puppet/functions/run_script.rb index 3e8fd97a8..43e9fe6a4 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/run_script.rb @@ -139,6 +139,7 @@ def run_script_with_description(scope, script, targets, description = nil, optio if !r.ok && !options[:catch_errors] raise Bolt::RunFailure.new(r, 'run_script', script) end + r end end diff --git a/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb b/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb index 81daae970..8882c5b0f 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb @@ -134,8 +134,8 @@ def set_resources(target, resources) unless resource.target == target file, line = Puppet::Pops::PuppetStack.top_of_stack - raise Bolt::ValidationError, "Cannot set resource #{resource.reference} for target "\ - "#{resource.target} on target #{target}. "\ + raise Bolt::ValidationError, "Cannot set resource #{resource.reference} for target " \ + "#{resource.target} on target #{target}. " \ "#{Puppet::Util::Errors.error_location(file, line)}" end diff --git a/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb b/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb index 4a0c2e1e5..6dfd58261 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb @@ -95,6 +95,7 @@ def upload_file_with_description(scope, source, destination, targets, descriptio if !r.ok && !options[:catch_errors] raise Bolt::RunFailure.new(r, 'upload_file', source) end + r end end diff --git a/bolt-modules/boltlib/lib/puppet/functions/wait.rb b/bolt-modules/boltlib/lib/puppet/functions/wait.rb index a98ad96f7..878b03b35 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/wait.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/wait.rb @@ -111,7 +111,7 @@ def inner_wait(futures: nil, timeout: nil, options: {}) valid, unknown = options.partition { |k, _v| %w[_catch_errors].include?(k) }.map(&:to_h) if unknown.any? file, line = Puppet::Pops::PuppetStack.top_of_stack - msg = "The wait() function call in #{file}#L#{line} received unknown options "\ + msg = "The wait() function call in #{file}#L#{line} received unknown options " \ "#{unknown.keys}. Removing unknown options and continuing..." Bolt::Logger.warn("plan_function_options", msg) end diff --git a/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb b/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb index 43dbe2fdb..091e6c27c 100644 --- a/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +++ b/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb @@ -54,6 +54,7 @@ def wait_until_available(targets, options = nil) if !r.ok && !options['_catch_errors'] raise Bolt::RunFailure.new(r, 'wait_until_available') end + r end end diff --git a/bolt-modules/boltlib/spec/functions/add_facts_spec.rb b/bolt-modules/boltlib/spec/functions/add_facts_spec.rb index f6820096d..365b761b6 100644 --- a/bolt-modules/boltlib/spec/functions/add_facts_spec.rb +++ b/bolt-modules/boltlib/spec/functions/add_facts_spec.rb @@ -6,6 +6,7 @@ describe 'add_facts' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:target) { inventory.get_target('example') } @@ -37,6 +38,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that add_facts is not available' do is_expected.to run.with_params(target, {}) .and_raise_error(/Plan language function 'add_facts' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/add_to_group_spec.rb b/bolt-modules/boltlib/spec/functions/add_to_group_spec.rb index a95d65983..6503da3ca 100644 --- a/bolt-modules/boltlib/spec/functions/add_to_group_spec.rb +++ b/bolt-modules/boltlib/spec/functions/add_to_group_spec.rb @@ -5,6 +5,7 @@ describe 'add_to_group' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:target) { inventory.get_target('example') } @@ -36,6 +37,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that add_to_group is not available' do is_expected.to run.with_params(target, group) .and_raise_error(/Plan language function 'add_to_group' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/apply_prep_spec.rb b/bolt-modules/boltlib/spec/functions/apply_prep_spec.rb index 8f04d3610..3ce38ed1e 100644 --- a/bolt-modules/boltlib/spec/functions/apply_prep_spec.rb +++ b/bolt-modules/boltlib/spec/functions/apply_prep_spec.rb @@ -12,6 +12,7 @@ describe 'apply_prep' do include PuppetlabsSpec::Fixtures + let(:applicator) { mock('Bolt::Applicator') } let(:config) { Bolt::Config.default } let(:executor) { Bolt::Executor.new } @@ -314,6 +315,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that apply_prep is not available' do is_expected.to run.with_params('foo') .and_raise_error(/Plan language function 'apply_prep' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/background_spec.rb b/bolt-modules/boltlib/spec/functions/background_spec.rb index 5446f34fd..0c1960be2 100644 --- a/bolt-modules/boltlib/spec/functions/background_spec.rb +++ b/bolt-modules/boltlib/spec/functions/background_spec.rb @@ -7,6 +7,7 @@ describe 'background' do include PuppetlabsSpec::Fixtures + let(:name) { "Pluralize" } let(:object) { "noodle" } let(:future) { Bolt::PlanFuture.new('foo', name, plan_id: 1234) } diff --git a/bolt-modules/boltlib/spec/functions/download_file_spec.rb b/bolt-modules/boltlib/spec/functions/download_file_spec.rb index b6d2263ab..69dde67c3 100644 --- a/bolt-modules/boltlib/spec/functions/download_file_spec.rb +++ b/bolt-modules/boltlib/spec/functions/download_file_spec.rb @@ -9,6 +9,7 @@ describe 'download_file' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { mock('inventory') } let(:project) { Bolt::Project.default_project } diff --git a/bolt-modules/boltlib/spec/functions/fail_plan_spec.rb b/bolt-modules/boltlib/spec/functions/fail_plan_spec.rb index c3562263d..6cee94ec2 100644 --- a/bolt-modules/boltlib/spec/functions/fail_plan_spec.rb +++ b/bolt-modules/boltlib/spec/functions/fail_plan_spec.rb @@ -6,6 +6,7 @@ describe 'fail_plan' do include PuppetlabsSpec::Fixtures + let(:tasks_enabled) { true } let(:executor) { Bolt::Executor.new } @@ -36,6 +37,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that fail_plan is not available' do is_expected.to run.with_params('foo') .and_raise_error(/Plan language function 'fail_plan' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/get_resources_spec.rb b/bolt-modules/boltlib/spec/functions/get_resources_spec.rb index d2c1daddc..e4f4fc539 100644 --- a/bolt-modules/boltlib/spec/functions/get_resources_spec.rb +++ b/bolt-modules/boltlib/spec/functions/get_resources_spec.rb @@ -10,6 +10,7 @@ describe 'get_resources' do include PuppetlabsSpec::Fixtures + let(:applicator) { mock('Bolt::Applicator') } let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } @@ -82,6 +83,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that get_resources is not available' do is_expected.to run.with_params(hostnames, 'file') .and_raise_error(/Plan language function 'get_resources' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/get_target_spec.rb b/bolt-modules/boltlib/spec/functions/get_target_spec.rb index a7f2da595..a17cb5709 100644 --- a/bolt-modules/boltlib/spec/functions/get_target_spec.rb +++ b/bolt-modules/boltlib/spec/functions/get_target_spec.rb @@ -6,6 +6,7 @@ describe 'get_target' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:tasks_enabled) { true } diff --git a/bolt-modules/boltlib/spec/functions/parallelize_spec.rb b/bolt-modules/boltlib/spec/functions/parallelize_spec.rb index 64b41163d..9d8b97304 100644 --- a/bolt-modules/boltlib/spec/functions/parallelize_spec.rb +++ b/bolt-modules/boltlib/spec/functions/parallelize_spec.rb @@ -8,6 +8,7 @@ describe 'parallelize' do include PuppetlabsSpec::Fixtures + let(:array) { %w[a b c d a b a] } let(:future) { Bolt::PlanFuture.new(nil, 1, name: 'name', plan_id: 1234) } let(:executor) { Bolt::Executor.new } diff --git a/bolt-modules/boltlib/spec/functions/remove_from_group_spec.rb b/bolt-modules/boltlib/spec/functions/remove_from_group_spec.rb index 40d48c09b..230c49e36 100644 --- a/bolt-modules/boltlib/spec/functions/remove_from_group_spec.rb +++ b/bolt-modules/boltlib/spec/functions/remove_from_group_spec.rb @@ -2,6 +2,7 @@ describe 'remove_from_group' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:config) { Bolt::Config.default } let(:pal) { nil } @@ -44,6 +45,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that remove_from_group is not available' do is_expected.to run.with_params(target1, parent) .and_raise_error(/Plan language function 'remove_from_group' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/resolve_references_spec.rb b/bolt-modules/boltlib/spec/functions/resolve_references_spec.rb index 69ade61df..f17a6a6cd 100644 --- a/bolt-modules/boltlib/spec/functions/resolve_references_spec.rb +++ b/bolt-modules/boltlib/spec/functions/resolve_references_spec.rb @@ -5,6 +5,7 @@ describe 'resolve_references' do include PuppetlabsSpec::Fixtures + let(:project) { Bolt::Project.create_project('./spec/fixtures') } let(:config) { Bolt::Config.new(project, {}) } let(:pal) { diff --git a/bolt-modules/boltlib/spec/functions/run_command_spec.rb b/bolt-modules/boltlib/spec/functions/run_command_spec.rb index 71f75b097..3d0ebb2ff 100644 --- a/bolt-modules/boltlib/spec/functions/run_command_spec.rb +++ b/bolt-modules/boltlib/spec/functions/run_command_spec.rb @@ -26,6 +26,7 @@ let(:command) { 'hostname' } let(:result) { Bolt::Result.new(target, value: { 'stdout' => hostname }) } let(:result_set) { Bolt::ResultSet.new([result]) } + before(:each) do Puppet.features.stubs(:bolt?).returns(true) end @@ -211,6 +212,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that run_command is not available' do is_expected.to run .with_params('echo hello', []) diff --git a/bolt-modules/boltlib/spec/functions/run_container_spec.rb b/bolt-modules/boltlib/spec/functions/run_container_spec.rb index 477d18bee..d0e6839e8 100644 --- a/bolt-modules/boltlib/spec/functions/run_container_spec.rb +++ b/bolt-modules/boltlib/spec/functions/run_container_spec.rb @@ -69,8 +69,8 @@ def image end let(:msg) { - "docker: Error response from daemon: OCI runtime create failed: "\ - "container_linux.go:367: starting container process caused: exec: "\ + "docker: Error response from daemon: OCI runtime create failed: " \ + "container_linux.go:367: starting container process caused: exec: " \ "\"foo\": executable file not found in $PATH: unknown.\n" } let(:value) do diff --git a/bolt-modules/boltlib/spec/functions/run_plan_spec.rb b/bolt-modules/boltlib/spec/functions/run_plan_spec.rb index 9af6a90f2..033c70ffe 100644 --- a/bolt-modules/boltlib/spec/functions/run_plan_spec.rb +++ b/bolt-modules/boltlib/spec/functions/run_plan_spec.rb @@ -8,6 +8,7 @@ describe 'run_plan' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:tasks_enabled) { true } let(:inventory) { Bolt::Inventory.empty } @@ -108,6 +109,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that run_plan is not available' do is_expected.to run.with_params('test::run_me') .and_raise_error(/Plan language function 'run_plan' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/run_script_spec.rb b/bolt-modules/boltlib/spec/functions/run_script_spec.rb index 99571aac0..1093cd704 100644 --- a/bolt-modules/boltlib/spec/functions/run_script_spec.rb +++ b/bolt-modules/boltlib/spec/functions/run_script_spec.rb @@ -8,6 +8,7 @@ describe 'run_script' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { mock('inventory') } let(:tasks_enabled) { true } @@ -28,6 +29,7 @@ let(:target) { Bolt::Target.new(hostname) } let(:result) { Bolt::Result.new(target, value: { 'stdout' => hostname }) } let(:result_set) { Bolt::ResultSet.new([result]) } + before(:each) do Puppet.features.stubs(:bolt?).returns(true) end diff --git a/bolt-modules/boltlib/spec/functions/run_task_spec.rb b/bolt-modules/boltlib/spec/functions/run_task_spec.rb index 271252e4e..a53146216 100644 --- a/bolt-modules/boltlib/spec/functions/run_task_spec.rb +++ b/bolt-modules/boltlib/spec/functions/run_task_spec.rb @@ -24,6 +24,7 @@ def matches?(available_parameters) describe 'run_task' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:tasks_enabled) { true } diff --git a/bolt-modules/boltlib/spec/functions/run_task_with_spec.rb b/bolt-modules/boltlib/spec/functions/run_task_with_spec.rb index 86f9cc10e..80cb1c0c9 100644 --- a/bolt-modules/boltlib/spec/functions/run_task_with_spec.rb +++ b/bolt-modules/boltlib/spec/functions/run_task_with_spec.rb @@ -22,6 +22,7 @@ def matches?(available_parameters) describe 'run_task_with' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:tasks_enabled) { true } diff --git a/bolt-modules/boltlib/spec/functions/set_config_spec.rb b/bolt-modules/boltlib/spec/functions/set_config_spec.rb index 43eb847a1..b3b0972df 100644 --- a/bolt-modules/boltlib/spec/functions/set_config_spec.rb +++ b/bolt-modules/boltlib/spec/functions/set_config_spec.rb @@ -6,6 +6,7 @@ describe 'set_config' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:target) { inventory.get_target('example') } diff --git a/bolt-modules/boltlib/spec/functions/set_feature_spec.rb b/bolt-modules/boltlib/spec/functions/set_feature_spec.rb index 86f96d17d..ad9715563 100644 --- a/bolt-modules/boltlib/spec/functions/set_feature_spec.rb +++ b/bolt-modules/boltlib/spec/functions/set_feature_spec.rb @@ -6,6 +6,7 @@ describe 'set_feature' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:target) { inventory.get_target('example') } diff --git a/bolt-modules/boltlib/spec/functions/set_resources_spec.rb b/bolt-modules/boltlib/spec/functions/set_resources_spec.rb index bf0371f08..2634329a4 100644 --- a/bolt-modules/boltlib/spec/functions/set_resources_spec.rb +++ b/bolt-modules/boltlib/spec/functions/set_resources_spec.rb @@ -97,6 +97,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that set_resources is not available' do is_expected.to run.with_params(target, resource) .and_raise_error(/Plan language function 'set_resources' cannot be used/) diff --git a/bolt-modules/boltlib/spec/functions/set_var_spec.rb b/bolt-modules/boltlib/spec/functions/set_var_spec.rb index c4c033cfa..34a41be57 100644 --- a/bolt-modules/boltlib/spec/functions/set_var_spec.rb +++ b/bolt-modules/boltlib/spec/functions/set_var_spec.rb @@ -6,6 +6,7 @@ describe 'set_var' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { Bolt::Inventory.empty } let(:target) { inventory.get_target('example') } diff --git a/bolt-modules/boltlib/spec/functions/upload_file_spec.rb b/bolt-modules/boltlib/spec/functions/upload_file_spec.rb index 3771e8a01..4a924b875 100644 --- a/bolt-modules/boltlib/spec/functions/upload_file_spec.rb +++ b/bolt-modules/boltlib/spec/functions/upload_file_spec.rb @@ -8,6 +8,7 @@ describe 'upload_file' do include PuppetlabsSpec::Fixtures + let(:executor) { Bolt::Executor.new } let(:inventory) { mock('inventory') } let(:tasks_enabled) { true } @@ -32,6 +33,7 @@ let(:full_path) { File.join(module_root, 'files/uploads/index.html') } let(:full_dir_path) { File.dirname(full_path) } let(:destination) { '/var/www/html' } + before(:each) do Puppet.features.stubs(:bolt?).returns(true) end diff --git a/bolt-modules/boltlib/spec/functions/wait_spec.rb b/bolt-modules/boltlib/spec/functions/wait_spec.rb index ea22d86e1..6fea89baa 100644 --- a/bolt-modules/boltlib/spec/functions/wait_spec.rb +++ b/bolt-modules/boltlib/spec/functions/wait_spec.rb @@ -7,6 +7,7 @@ describe 'wait' do include PuppetlabsSpec::Fixtures + let(:name) { "Pluralize" } let(:future) { Bolt::PlanFuture.new('foo', name, plan_id: 1234) } let(:executor) { Bolt::Executor.new } diff --git a/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb b/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb index 2b719bb25..96bb554c0 100644 --- a/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +++ b/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb @@ -35,6 +35,7 @@ def do_until(options = {}) until (x = yield) i += 1 break if limit != 0 && i >= limit + Kernel.sleep(interval) if interval end x diff --git a/bolt-modules/dir/spec/functions/dir/children_spec.rb b/bolt-modules/dir/spec/functions/dir/children_spec.rb index 3fcb14c08..57761919b 100644 --- a/bolt-modules/dir/spec/functions/dir/children_spec.rb +++ b/bolt-modules/dir/spec/functions/dir/children_spec.rb @@ -5,6 +5,7 @@ describe 'dir::children' do include PuppetlabsSpec::Fixtures + let(:path) { fixtures('modules', 'test') } around(:each) do |example| @@ -18,6 +19,7 @@ context 'finding an absolute path' do let(:abs_path) { File.expand_path(File.join(path, 'facts.d')) } + it { is_expected.to run.with_params(abs_path).and_return(%w[.hidden fact.py two.sh]) } diff --git a/bolt-modules/out/spec/functions/out/verbose_spec.rb b/bolt-modules/out/spec/functions/out/verbose_spec.rb index 95ca463e5..465b74b05 100644 --- a/bolt-modules/out/spec/functions/out/verbose_spec.rb +++ b/bolt-modules/out/spec/functions/out/verbose_spec.rb @@ -31,6 +31,7 @@ context 'without tasks enabled' do let(:tasks_enabled) { false } + it 'fails and reports that out::verbose is not available' do is_expected.to run.with_params('This is a message') .and_raise_error(/Plan language function 'out::verbose' cannot be used/) diff --git a/dev-resources/bump_mods.rb b/dev-resources/bump_mods.rb index 925218b35..a9d5349b5 100644 --- a/dev-resources/bump_mods.rb +++ b/dev-resources/bump_mods.rb @@ -46,8 +46,10 @@ def puppetfile_set_mod_versions!(versions_new) # update lines lines.each do |line| next unless line.start_with?("mod 'puppetlabs") + match = module_re.match(line) next unless match + mod = match[1].strip ver_old = match[2].strip ver_new = versions_new[mod] diff --git a/lib/bolt/analytics.rb b/lib/bolt/analytics.rb index 7d6d95327..b507eea35 100644 --- a/lib/bolt/analytics.rb +++ b/lib/bolt/analytics.rb @@ -59,7 +59,7 @@ def self.config_path if File.exist?(path) if File.exist?(old_path) - message = "Detected analytics configuration files at '#{old_path}' and '#{path}'. Loading "\ + message = "Detected analytics configuration files at '#{old_path}' and '#{path}'. Loading " \ "analytics configuration from '#{path}'." Bolt::Logger.warn_once('duplicate_analytics', message) end diff --git a/lib/bolt/application.rb b/lib/bolt/application.rb index d5b694b9b..2021a3cf2 100644 --- a/lib/bolt/application.rb +++ b/lib/bolt/application.rb @@ -57,10 +57,10 @@ def apply(manifest, targets, code: '', noop: false) if defined?(ast.body) && (ast.body.is_a?(Puppet::Pops::Model::HostClassDefinition) || ast.body.is_a?(Puppet::Pops::Model::ResourceTypeDefinition)) - message = "Manifest only contains definitions and will result in no changes on the targets. "\ - "Definitions must be declared for their resources to be applied. You can read more "\ - "about defining and declaring classes and types in the Puppet documentation at "\ - "https://puppet.com/docs/puppet/latest/lang_classes.html and "\ + message = "Manifest only contains definitions and will result in no changes on the targets. " \ + "Definitions must be declared for their resources to be applied. You can read more " \ + "about defining and declaring classes and types in the Puppet documentation at " \ + "https://puppet.com/docs/puppet/latest/lang_classes.html and " \ "https://puppet.com/docs/puppet/latest/lang_defined_types.html" Bolt::Logger.warn("empty_manifest", message) end @@ -281,7 +281,7 @@ def install_modules(outputter, force: false, resolve: true) if config.project.modules.empty? && resolve outputter.print_message( - "Project configuration file #{config.project.project_file} does not "\ + "Project configuration file #{config.project.project_file} does not " \ "specify any module dependencies. Nothing to do." ) return true @@ -431,8 +431,8 @@ def apply_policies(policies, targets, noop: false) # CODEREVIEW: Phrasing raise Bolt::Error.new( - "The following policies are not available to the project: '#{unavailable_policies.join("', '")}'. "\ - "You must list policies in a project's 'policies' setting before Bolt can apply them to targets. "\ + "The following policies are not available to the project: '#{unavailable_policies.join("', '")}'. " \ + "You must list policies in a project's 'policies' setting before Bolt can apply them to targets. " \ "For a list of policies available to the project, run '#{command}'.", 'bolt/unavailable-policy-error' ) @@ -452,7 +452,7 @@ def apply_policies(policies, targets, noop: false) # CODEREVIEW: Phrasing if unloadable_policies.any? raise Bolt::Error.new( - "The following policies cannot be loaded: '#{unloadable_policies.join("', '")}'. "\ + "The following policies cannot be loaded: '#{unloadable_policies.join("', '")}'. " \ "Policies must be a Puppet class saved to a project's or module's manifests directory.", 'bolt/unloadable-policy-error' ) @@ -501,7 +501,7 @@ def new_policy(name) # Error if name is not namespaced to project unless prefix == @config.project.name raise Bolt::ValidationError, - "Policy name '#{name}' must begin with project name '#{@config.project.name}'. Did "\ + "Policy name '#{name}' must begin with project name '#{@config.project.name}'. Did " \ "you mean '#{@config.project.name}::#{name}'?" end @@ -570,9 +570,9 @@ def list_policies command = Bolt::Util.powershell? ? 'New-BoltPolicy -Name ' : 'bolt policy new ' raise Bolt::Error.new( - "Project configuration file #{@config.project.project_file} does not "\ - "specify any policies. You can add policies to the project by including "\ - "a 'policies' key or creating a new policy using the '#{command}' "\ + "Project configuration file #{@config.project.project_file} does not " \ + "specify any policies. You can add policies to the project by including " \ + "a 'policies' key or creating a new policy using the '#{command}' " \ "command.", 'bolt/no-policies-error' ) @@ -711,7 +711,7 @@ def list_tasks(filter: nil) unless project.project_file? command = Bolt::Util.powershell? ? 'New-BoltProject' : 'bolt project init' - msg = "Could not find project configuration file #{project.project_file}, unable "\ + msg = "Could not find project configuration file #{project.project_file}, unable " \ "to install modules. To create a Bolt project, run '#{command}'." raise Bolt::Error.new(msg, 'bolt/missing-project-config-error') @@ -725,6 +725,7 @@ def list_tasks(filter: nil) # private def filter_content(content, filter) return content unless content && filter + content.select { |name,| name.include?(filter) } end @@ -737,6 +738,7 @@ def list_tasks(filter: nil) # private def find_file(path) return path if File.exist?(path) || Pathname.new(path).absolute? + modulepath = Bolt::Config::Modulepath.new(config.modulepath) modules = Bolt::Module.discover(modulepath.full_modulepath, config.project) mod, file = path.split(File::SEPARATOR, 2) @@ -758,6 +760,7 @@ def list_tasks(filter: nil) files.each_with_object({}) do |file, guides| next if file !~ /\.(yaml|yml)\z/ + topic = File.basename(file, ".*") guides[topic] = File.join(root_path, file) end diff --git a/lib/bolt/applicator.rb b/lib/bolt/applicator.rb index e30c6fe2e..6fe54b58d 100644 --- a/lib/bolt/applicator.rb +++ b/lib/bolt/applicator.rb @@ -174,6 +174,7 @@ def validate_hiera_config(hiera_config) elsif data['version'] != 5 raise Bolt::ParseError, "Hiera v5 is required, found v#{data['version'] || 3} in #{hiera_config}" end + hiera_config end end @@ -181,6 +182,7 @@ def validate_hiera_config(hiera_config) def apply(args, apply_body, scope) raise(ArgumentError, 'apply requires a TargetSpec') if args.empty? raise(ArgumentError, 'apply requires at least one statement in the apply block') if apply_body.nil? + type0 = Puppet.lookup(:pal_script_compiler).type('TargetSpec') Puppet::Pal.assert_type(type0, args[0], 'apply targets') @@ -241,6 +243,7 @@ def apply_ast(raw_ast, targets, options, plan_vars = {}) @plugin_tarball = Concurrent::Delay.new do build_plugin_tarball do |mod| next unless required_modules.nil? || required_modules.include?(mod.name) + search_dirs = [] search_dirs << mod.plugins if mod.plugins? search_dirs << mod.pluginfacts if mod.pluginfacts? @@ -317,6 +320,7 @@ def apply_ast(raw_ast, targets, options, plan_vars = {}) if !r.ok && !options[:catch_errors] raise Bolt::ApplyFailure, r end + r end diff --git a/lib/bolt/bolt_option_parser.rb b/lib/bolt/bolt_option_parser.rb index e1024d8d1..405e38700 100644 --- a/lib/bolt/bolt_option_parser.rb +++ b/lib/bolt/bolt_option_parser.rb @@ -450,7 +450,7 @@ module Manage Bolt project modules MODULE_HELP = <<~HELP #{colorize(:cyan, 'Name')} module - + #{colorize(:cyan, 'Usage')} bolt module [options] @@ -470,7 +470,7 @@ module Manage Bolt project modules MODULE_ADD_HELP = <<~HELP #{colorize(:cyan, 'Name')} module add - + #{colorize(:cyan, 'Usage')} bolt module add [options] @@ -503,7 +503,7 @@ module generate-types MODULE_INSTALL_HELP = <<~HELP #{colorize(:cyan, 'Name')} module install - + #{colorize(:cyan, 'Usage')} bolt module install [options] @@ -581,10 +581,10 @@ module show PLAN_NEW_HELP = <<~HELP #{colorize(:cyan, 'Name')} plan new - + #{colorize(:cyan, 'Usage')} bolt plan new [options] - + #{colorize(:cyan, 'Description')} Create a new plan in the current project. @@ -1049,6 +1049,7 @@ def initialize(options) if ENV.include?(Bolt::Inventory::ENVIRONMENT_VAR) raise Bolt::CLIError, "Cannot pass inventory file when #{Bolt::Inventory::ENVIRONMENT_VAR} is set" end + @options[:inventoryfile] = File.expand_path(path) end define('--[no-]save-rerun', 'Whether to update the rerun file after this command.') do |save| @@ -1063,6 +1064,7 @@ def initialize(options) unless envvar.include?('=') raise Bolt::CLIError, "Environment variables must be specified using 'myenvvar=key' format" end + @options[:env_vars] ||= {} @options[:env_vars].store(*envvar.split('=', 2)) end @@ -1129,7 +1131,7 @@ def initialize(options) separator "\n#{self.class.colorize(:cyan, 'Display options')}" define('--filter FILTER', 'Filter tasks and plans by a matching substring.') do |filter| unless /^[a-z0-9_:]+$/.match(filter) - msg = "Illegal characters in filter string '#{filter}'. Filters can "\ + msg = "Illegal characters in filter string '#{filter}'. Filters can " \ "only include lowercase letters, numbers, underscores, and colons." raise Bolt::CLIError, msg end diff --git a/lib/bolt/cli.rb b/lib/bolt/cli.rb index 803cf32a2..8ff4ff711 100644 --- a/lib/bolt/cli.rb +++ b/lib/bolt/cli.rb @@ -294,8 +294,8 @@ def parse end if options[:action] == 'apply' && options[:leftovers].any? - raise Bolt::CLIError, "Unknown argument(s) #{options[:leftovers].join(', ')}. "\ - "To apply multiple policies, provide a comma-separated list of "\ + raise Bolt::CLIError, "Unknown argument(s) #{options[:leftovers].join(', ')}. " \ + "To apply multiple policies, provide a comma-separated list of " \ "policy names." end @@ -310,7 +310,7 @@ def parse if options[:subcommand] == 'module' && options[:action] == 'install' && options[:object] command = Bolt::Util.powershell? ? 'Add-BoltModule -Module' : 'bolt module add' - raise Bolt::CLIError, "Invalid argument '#{options[:object]}'. To add a new module to "\ + raise Bolt::CLIError, "Invalid argument '#{options[:object]}'. To add a new module to " \ "the project, run '#{command} #{options[:object]}'." end @@ -827,6 +827,7 @@ def execute(options) # private def parse_vars(vars) return unless vars + Hash[vars.map { |a| a.split('=', 2) }] end @@ -880,7 +881,7 @@ def execute(options) # private def validate_ps_version if Bolt::Util.powershell? - command = "powershell.exe -NoProfile -NonInteractive -NoLogo -ExecutionPolicy "\ + command = "powershell.exe -NoProfile -NonInteractive -NoLogo -ExecutionPolicy " \ "Bypass -Command $PSVersionTable.PSVersion.Major" stdout, _stderr, _status = Open3.capture3(command) @@ -935,7 +936,7 @@ def execute(options) private def with_signal_handling handler = Signal.trap :INT do |signo| Bolt::Logger.logger(self).info( - "Exiting after receiving SIG#{Signal.signame(signo)} signal. "\ + "Exiting after receiving SIG#{Signal.signame(signo)} signal. " \ "There might be processes left executing on some targets." ) exit! diff --git a/lib/bolt/config.rb b/lib/bolt/config.rb index 05d0964a7..e0856798c 100644 --- a/lib/bolt/config.rb +++ b/lib/bolt/config.rb @@ -101,7 +101,7 @@ def self.load_bolt_defaults_yaml(dir) Bolt::Logger.warn( "unsupported_project_config", - "Unsupported project configuration detected in '#{filepath}': #{project_config.keys}. "\ + "Unsupported project configuration detected in '#{filepath}': #{project_config.keys}. " \ "Project configuration should be set in 'bolt-project.yaml'." ) end @@ -114,8 +114,8 @@ def self.load_bolt_defaults_yaml(dir) Bolt::Logger.warn( "unsupported_inventory_config", - "Unsupported inventory configuration detected in '#{filepath}': #{transport_config.keys}. "\ - "Transport configuration should be set under the 'inventory-config' option or "\ + "Unsupported inventory configuration detected in '#{filepath}': #{transport_config.keys}. " \ + "Transport configuration should be set under the 'inventory-config' option or " \ "in 'inventory.yaml'." ) end @@ -126,13 +126,13 @@ def self.load_bolt_defaults_yaml(dir) if data.key?('inventory-config') unless data['inventory-config'].is_a?(Hash) raise Bolt::ValidationError, - "Option 'inventory-config' must be of type Hash, received #{data['inventory-config']} "\ + "Option 'inventory-config' must be of type Hash, received #{data['inventory-config']} " \ "#{data['inventory-config']} (file: #{filepath})" end if data['inventory-config'].key?('_plugin') raise Bolt::ValidationError, - "Found unsupported key '_plugin' for option 'inventory-config'; supported keys are "\ + "Found unsupported key '_plugin' for option 'inventory-config'; supported keys are " \ "'#{INVENTORY_OPTIONS.keys.join("', '")}' (file: #{filepath})" end @@ -309,6 +309,7 @@ def deep_clone private def normalize_log(target) return target if target == 'console' + target = target[5..-1] if target.start_with?('file:') 'file:' + File.expand_path(target, @project.path) end @@ -334,7 +335,7 @@ def deep_clone def validate if @data['modulepath']&.include?(@project.managed_moduledir.to_s) raise Bolt::ValidationError, - "Found invalid path in modulepath: #{@project.managed_moduledir}. This path "\ + "Found invalid path in modulepath: #{@project.managed_moduledir}. This path " \ "is automatically appended to the modulepath and cannot be configured." end @@ -479,6 +480,7 @@ def analytics # Check if there is a case-insensitive match to the path def check_path_case(type, paths) return if paths.nil? + matches = matching_paths(paths) if matches.any? diff --git a/lib/bolt/config/options.rb b/lib/bolt/config/options.rb index a51c4bc08..2f52dd1f4 100644 --- a/lib/bolt/config/options.rb +++ b/lib/bolt/config/options.rb @@ -91,8 +91,8 @@ module Options _plugin: true }, "server_urls" => { - description: "An array containing the PuppetDB host to connect to. Include the protocol `https` "\ - "and the port, which is usually `8081`. For example, "\ + description: "An array containing the PuppetDB host to connect to. Include the protocol `https` " \ + "and the port, which is usually `8081`. For example, " \ "`https://my-puppetdb-server.com:8081`.", type: Array, _example: ["https://puppet.example.com:8081"], @@ -110,26 +110,26 @@ module Options # https://github.com/puppetlabs/bolt/blob/main/schemas/README.md OPTIONS = { "analytics" => { - description: "Whether to disable analytics. Setting this option to 'false' in the system-wide "\ - "or user-level configuration will disable analytics for all projects, even if this "\ + description: "Whether to disable analytics. Setting this option to 'false' in the system-wide " \ + "or user-level configuration will disable analytics for all projects, even if this " \ "option is set to 'true' at the project level.", type: [TrueClass, FalseClass], _example: false }, "apply-settings" => { - description: "A map of Puppet settings to use when applying Puppet code using the `apply` "\ + description: "A map of Puppet settings to use when applying Puppet code using the `apply` " \ "plan function or the `bolt apply` command.", type: Hash, properties: { "evaltrace" => { - description: "Whether each resource should log when it is being evaluated. This allows "\ + description: "Whether each resource should log when it is being evaluated. This allows " \ "you to interactively see exactly what is being done.", type: [TrueClass, FalseClass], _example: true, _default: false }, "log_level" => { - description: "The log level for logs in apply reports from Puppet. These can be seen "\ + description: "The log level for logs in apply reports from Puppet. These can be seen " \ "in ApplyResults.", type: String, enum: %w[debug info notice warning err alert emerg crit], @@ -143,7 +143,7 @@ module Options _default: false }, "trace" => { - description: "Whether to print stack traces on some errors. Will print internal Ruby "\ + description: "Whether to print stack traces on some errors. Will print internal Ruby " \ "stack trace interleaved with Puppet function frames.", type: [TrueClass, FalseClass], _example: true, @@ -176,8 +176,8 @@ module Options _default: "100 or 1/7 the ulimit, whichever is lower." }, "disable-warnings" => { - description: "An array of IDs of warnings to suppress. Warnings with a matching ID will not be logged "\ - "by Bolt. If you are upgrading Bolt to a new major version, you should re-enable all warnings "\ + description: "An array of IDs of warnings to suppress. Warnings with a matching ID will not be logged " \ + "by Bolt. If you are upgrading Bolt to a new major version, you should re-enable all warnings " \ "until you have finished upgrading.", type: Array, items: { @@ -203,11 +203,11 @@ module Options type: [TrueClass, FalseClass], _example: true, _default: false, - _deprecation: "Bolt no longer honors this option and enables loading scripts from the scripts "\ + _deprecation: "Bolt no longer honors this option and enables loading scripts from the scripts " \ "directory by default." }, "script_interpreter" => { - description: "Use a target's [`interpreters` configuration](bolt_transports_reference.md#interpreters) "\ + description: "Use a target's [`interpreters` configuration](bolt_transports_reference.md#interpreters) " \ "when running a script.", type: [TrueClass, FalseClass], _example: true, @@ -225,8 +225,8 @@ module Options _default: "project/hiera.yaml" }, "inventory-config" => { - description: "A map of default configuration options for the inventory. This includes options "\ - "for setting the default transport to use when connecting to targets, as well as "\ + description: "A map of default configuration options for the inventory. This includes options " \ + "for setting the default transport to use when connecting to targets, as well as " \ "options for configuring the default behavior of each transport.", type: Hash, _plugin: false, @@ -247,11 +247,11 @@ module Options _example: { "ttl" => 3600 } }, "log" => { - description: "A map of configuration for the logfile output. Under `log`, you can configure log options "\ - "for `console` and add configuration for individual log files, such as "\ - "`~/.puppetlabs/bolt/debug.log`. Individual log files must be valid filepaths. If the log "\ - "file does not exist, then Bolt will create it before logging information. Set the value to "\ - "`disable` to remove a log file defined at an earlier level of the config hierarchy. By "\ + description: "A map of configuration for the logfile output. Under `log`, you can configure log options " \ + "for `console` and add configuration for individual log files, such as " \ + "`~/.puppetlabs/bolt/debug.log`. Individual log files must be valid filepaths. If the log " \ + "file does not exist, then Bolt will create it before logging information. Set the value to " \ + "`disable` to remove a log file defined at an earlier level of the config hierarchy. By " \ "default, Bolt logs to a bolt-debug.log file in the Bolt project directory.", type: Hash, properties: { @@ -292,7 +292,7 @@ module Options "~/logs/debug.log" => { "append" => false, "level" => "debug" } } }, "modulepath" => { - description: "An array of directories that Bolt loads content such as plans and tasks from. Read more "\ + description: "An array of directories that Bolt loads content such as plans and tasks from. Read more " \ "about modules in [Module structure](module_structure.md).", type: [Array, String], items: { @@ -303,8 +303,8 @@ module Options _default: ["project/modules"] }, "module-install" => { - description: "Options that configure where Bolt downloads modules from. This option is only used when "\ - "installing modules using the `bolt module add|install` commands and "\ + description: "Options that configure where Bolt downloads modules from. This option is only used when " \ + "installing modules using the `bolt module add|install` commands and " \ "`Add|Install-BoltModule` cmdlets.", type: Hash, properties: { @@ -313,7 +313,7 @@ module Options type: Hash, properties: { "authorization_token" => { - description: "The token used to authorize requests to the Forge host. Must also specify "\ + description: "The token used to authorize requests to the Forge host. Must also specify " \ "`baseurl` when using this option.", type: String, _example: "Bearer eyJhbGciOiJIUzI1NiIsInR5c...", @@ -348,9 +348,9 @@ module Options _plugin: false }, "modules" => { - description: "A list of module dependencies for the project. Each dependency is a map of data specifying "\ - "the module to install. To install the project's module dependencies, run the `bolt module "\ - "install` command. For more information about specifying modules, see [the "\ + description: "A list of module dependencies for the project. Each dependency is a map of data specifying " \ + "the module to install. To install the project's module dependencies, run the `bolt module " \ + "install` command. For more information about specifying modules, see [the " \ "documentation](https://pup.pt/bolt-module-specs).", type: Array, items: { @@ -368,7 +368,7 @@ module Options type: [TrueClass, FalseClass] }, "version_requirement" => { - description: "The version requirement for the module. Accepts a specific version (1.2.3), version "\ + description: "The version requirement for the module. Accepts a specific version (1.2.3), version " \ "shorthand (1.2.x), or a version range (>= 1.2.0).", type: String } @@ -409,36 +409,36 @@ module Options ] }, "name" => { - description: "The name of the Bolt project. When this option is configured, the project is considered a "\ - "[Bolt project](projects.md), allowing Bolt to load content from the project directory "\ + description: "The name of the Bolt project. When this option is configured, the project is considered a " \ + "[Bolt project](projects.md), allowing Bolt to load content from the project directory " \ "as though it were a module.", type: String, _plugin: false, _example: "myproject" }, "plans" => { - description: "A list of plan names and glob patterns to filter the project's plans by. This option is used "\ - "to limit the visibility of plans for users of the project. For example, project authors "\ - "might want to limit the visibility of plans that are bundled with Bolt or plans that should "\ - "only be run as part of another plan. When this option is not configured, all plans are "\ - "visible. This option does not prevent users from running plans that are not part of this "\ + description: "A list of plan names and glob patterns to filter the project's plans by. This option is used " \ + "to limit the visibility of plans for users of the project. For example, project authors " \ + "might want to limit the visibility of plans that are bundled with Bolt or plans that should " \ + "only be run as part of another plan. When this option is not configured, all plans are " \ + "visible. This option does not prevent users from running plans that are not part of this " \ "list.", type: Array, _plugin: false, _example: ["myproject", "myproject::foo", "myproject::bar", "myproject::deploy::*"] }, "plugin-hooks" => { - description: "A map of [plugin hooks](writing_plugins.md#hooks) and which plugins a hook should use. "\ - "The only configurable plugin hook is `puppet_library`, which can use two possible plugins: "\ - "[`puppet_agent`](https://github.com/puppetlabs/puppetlabs-puppet_agent#puppet_agentinstall) "\ + description: "A map of [plugin hooks](writing_plugins.md#hooks) and which plugins a hook should use. " \ + "The only configurable plugin hook is `puppet_library`, which can use two possible plugins: " \ + "[`puppet_agent`](https://github.com/puppetlabs/puppetlabs-puppet_agent#puppet_agentinstall) " \ "and [`task`](using_plugins.md#task).", type: Hash, _plugin: true, _example: { "puppet_library" => { "plugin" => "puppet_agent", "version" => "6.15.0", "_run_as" => "root" } } }, "plugins" => { - description: "A map of plugins and their configuration data, where each key is the name of a plugin and "\ - "its value is a map of configuration data. Configurable options are specified by the plugin. "\ + description: "A map of plugins and their configuration data, where each key is the name of a plugin and " \ + "its value is a map of configuration data. Configurable options are specified by the plugin. " \ "Read more about configuring plugins in [Using plugins](using_plugins.md#configuring-plugins).", type: Hash, additionalProperties: { @@ -449,24 +449,24 @@ module Options _example: { "pkcs7" => { "keysize" => 1024 } } }, "policies" => { - description: "A list of policy names and glob patterns to filter the project's policies by. This option "\ - "is used to specify which policies are available to a project and can be applied to targets. "\ - "When this option is not configured, policies are not available to the project and cannot "\ + description: "A list of policy names and glob patterns to filter the project's policies by. This option " \ + "is used to specify which policies are available to a project and can be applied to targets. " \ + "When this option is not configured, policies are not available to the project and cannot " \ "be applied to targets.", type: Array, _plugin: false, _example: ["myproject::apache", "myproject::postgres"] }, "puppetdb" => { - description: "A map containing options for [configuring the Bolt PuppetDB "\ + description: "A map containing options for [configuring the Bolt PuppetDB " \ "client](bolt_connect_puppetdb.md).", type: Hash, properties: PUPPETDB_OPTIONS, _plugin: true }, "puppetdb-instances" => { - description: "A map of named PuppetDB instances and their configuration, where keys are the name "\ - "of a PuppetDB instance and values are maps of configuration options. For more "\ + description: "A map of named PuppetDB instances and their configuration, where keys are the name " \ + "of a PuppetDB instance and values are maps of configuration options. For more " \ "information, see [Connecting Bolt to PuppetDB](bolt_connect_puppetdb.md).", type: Hash, additionalProperties: { @@ -476,15 +476,15 @@ module Options _plugin: true }, "rerunfile" => { - description: "The path to the project's rerun file. The rerun file is used to store information "\ + description: "The path to the project's rerun file. The rerun file is used to store information " \ "about targets from the most recent run. Expands relative to the project directory.", type: String, _example: "/Users/bolt/project/rerun.json", _plugin: true }, "save-rerun" => { - description: "Whether to update `.rerun.json` in the Bolt project directory. If "\ - "your target names include passwords, set this value to `false` to avoid "\ + description: "Whether to update `.rerun.json` in the Bolt project directory. If " \ + "your target names include passwords, set this value to `false` to avoid " \ "writing passwords to disk.", type: [TrueClass, FalseClass], _plugin: false, @@ -499,7 +499,7 @@ module Options _default: true }, "stream" => { - description: "Whether to stream output from scripts and commands to the console. "\ + description: "Whether to stream output from scripts and commands to the console. " \ "**This option is experimental**.", type: [TrueClass, FalseClass], _plugin: false, @@ -507,11 +507,11 @@ module Options _example: true }, "tasks" => { - description: "A list of task names and glob patterns to filter the project's tasks by. This option is used "\ - "to limit the visibility of tasks for users of the project. For example, project authors "\ - "might want to limit the visibility of tasks that are bundled with Bolt or plans that should "\ - "only be run as part of a larger workflow. When this option is not configured, all tasks "\ - "are visible. This option does not prevent users from running tasks that are not part of "\ + description: "A list of task names and glob patterns to filter the project's tasks by. This option is used " \ + "to limit the visibility of tasks for users of the project. For example, project authors " \ + "might want to limit the visibility of tasks that are bundled with Bolt or plans that should " \ + "only be run as part of a larger workflow. When this option is not configured, all tasks " \ + "are visible. This option does not prevent users from running tasks that are not part of " \ "this list.", type: Array, items: { @@ -521,8 +521,8 @@ module Options _example: ["myproject", "myproject::foo", "myproject::bar", "myproject::deploy_*"] }, "trusted-external-command" => { - description: "The path to an executable on the Bolt controller that can produce external trusted facts. "\ - "**External trusted facts are experimental in both Puppet and Bolt and this API might "\ + description: "The path to an executable on the Bolt controller that can produce external trusted facts. " \ + "**External trusted facts are experimental in both Puppet and Bolt and this API might " \ "change or be removed.**", type: String, _plugin: false, @@ -536,7 +536,7 @@ module Options # 'config'. INVENTORY_OPTIONS = { "transport" => { - description: "The default transport to use when the transport for a target is not "\ + description: "The default transport to use when the transport for a target is not " \ "specified in the URI.", type: String, enum: TRANSPORT_CONFIG.keys, @@ -557,14 +557,14 @@ module Options _example: { cleanup: false } }, "local" => { - description: "A map of configuration options for the local transport. The set of available options is "\ + description: "A map of configuration options for the local transport. The set of available options is " \ "platform dependent.", type: Hash, _plugin: true, _example: { "cleanup" => false, "tmpdir" => "/tmp/bolt" } }, "lxd" => { - description: "A map of configuration options for the LXD transport. The LXD transport is "\ + description: "A map of configuration options for the LXD transport. The LXD transport is " \ "experimental and might include breaking changes between minor versions.", type: Hash, _plugin: true, diff --git a/lib/bolt/config/transport/base.rb b/lib/bolt/config/transport/base.rb index d4fc22790..8a7b55251 100644 --- a/lib/bolt/config/transport/base.rb +++ b/lib/bolt/config/transport/base.rb @@ -113,6 +113,7 @@ def self.schema private def assert_hash_or_config(data) return if data.is_a?(Hash) || data.is_a?(self.class) + raise Bolt::ValidationError, "Transport config must be a Hash or #{self.class}, received #{data.class} #{data.inspect}" end diff --git a/lib/bolt/config/transport/options.rb b/lib/bolt/config/transport/options.rb index 7f7fca4e4..f480a2cce 100644 --- a/lib/bolt/config/transport/options.rb +++ b/lib/bolt/config/transport/options.rb @@ -18,11 +18,11 @@ module Options }, "batch-mode" => { type: [TrueClass, FalseClass], - description: "Whether to disable password querying. When set to `false`, SSH will fall back to "\ - "prompting for a password if key authentication fails. This might cause Bolt to hang. "\ - "To prevent Bolt from hanging, you can configure `ssh-command` to use an SSH utility "\ - "such as sshpass that supports providing a password non-interactively. For more "\ - "information, see [Providing a password non-interactively using "\ + description: "Whether to disable password querying. When set to `false`, SSH will fall back to " \ + "prompting for a password if key authentication fails. This might cause Bolt to hang. " \ + "To prevent Bolt from hanging, you can configure `ssh-command` to use an SSH utility " \ + "such as sshpass that supports providing a password non-interactively. For more " \ + "information, see [Providing a password non-interactively using " \ "`native-ssh`](troubleshooting.md#providing-a-password-non-interactively-using-native-ssh).", _plugin: true, _default: true, @@ -43,9 +43,9 @@ module Options }, "cleanup" => { type: [TrueClass, FalseClass], - description: "Whether to clean up temporary files created on targets. When running commands on a target, "\ - "Bolt might create temporary files. After completing the command, these files are "\ - "automatically deleted. This value can be set to 'false' if you wish to leave these "\ + description: "Whether to clean up temporary files created on targets. When running commands on a target, " \ + "Bolt might create temporary files. After completing the command, these files are " \ + "automatically deleted. This value can be set to 'false' if you wish to leave these " \ "temporary files on the target.", _plugin: true, _default: true, @@ -53,7 +53,7 @@ module Options }, "connect-timeout" => { type: Integer, - description: "How long to wait in seconds when establishing connections. Set this value higher if you "\ + description: "How long to wait in seconds when establishing connections. Set this value higher if you " \ "frequently encounter connection timeout errors when running Bolt.", minimum: 1, _plugin: true, @@ -62,9 +62,9 @@ module Options }, "copy-command" => { type: [Array, String], - description: "The command to use when copying files using native SSH. Bolt runs ` "\ - "`. This option is used when you need support for features or algorithms that are not "\ - "supported by the net-ssh Ruby library. **This option is experimental.** You can read more "\ + description: "The command to use when copying files using native SSH. Bolt runs ` " \ + "`. This option is used when you need support for features or algorithms that are not " \ + "supported by the net-ssh Ruby library. **This option is experimental.** You can read more " \ "about this option in [Native SSH transport](experimental_features.md#native-ssh-transport).", items: { type: String @@ -83,11 +83,11 @@ module Options }, "encryption-algorithms" => { type: Array, - description: "A list of encryption algorithms to use when establishing a connection "\ - "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be "\ - "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, "\ - "non-deprecated algorithms are available by default when this option is not used. To "\ - "reference all default algorithms using this option, add 'defaults' to the list of "\ + description: "A list of encryption algorithms to use when establishing a connection " \ + "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be " \ + "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, " \ + "non-deprecated algorithms are available by default when this option is not used. To " \ + "reference all default algorithms using this option, add 'defaults' to the list of " \ "supported algorithms.", uniqueItems: true, items: { @@ -98,11 +98,11 @@ module Options }, "extensions" => { type: Array, - description: "A list of file extensions that are accepted for scripts or tasks on "\ - "Windows. Scripts with these file extensions rely on the target's file "\ - "type association to run. For example, if Python is installed on the "\ - "system, a `.py` script runs with `python.exe`. The extensions `.ps1`, "\ - "`.rb`, and `.pp` are always allowed and run via hard-coded "\ + description: "A list of file extensions that are accepted for scripts or tasks on " \ + "Windows. Scripts with these file extensions rely on the target's file " \ + "type association to run. For example, if Python is installed on the " \ + "system, a `.py` script runs with `python.exe`. The extensions `.ps1`, " \ + "`.rb`, and `.pp` are always allowed and run via hard-coded " \ "executables.", uniqueItems: true, items: { @@ -113,7 +113,7 @@ module Options }, "file-protocol" => { type: String, - description: "Which file transfer protocol to use. Either `winrm` or `smb`. Using `smb` is "\ + description: "Which file transfer protocol to use. Either `winrm` or `smb`. Using `smb` is " \ "recommended for large file transfers.", enum: %w[smb winrm], _plugin: true, @@ -128,11 +128,11 @@ module Options }, "host-key-algorithms" => { type: Array, - description: "A list of host key algorithms to use when establishing a connection "\ - "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be "\ - "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, "\ - "non-deprecated algorithms are available by default when this option is not used. To "\ - "reference all default algorithms using this option, add 'defaults' to the list of "\ + description: "A list of host key algorithms to use when establishing a connection " \ + "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be " \ + "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, " \ + "non-deprecated algorithms are available by default when this option is not used. To " \ + "reference all default algorithms using this option, add 'defaults' to the list of " \ "supported algorithms.", uniqueItems: true, items: { @@ -149,10 +149,10 @@ module Options }, "interpreters" => { type: Hash, - description: "A map of an extension name to the absolute path of an executable, enabling you to "\ - "override the shebang defined in a task executable. The extension can optionally be "\ - "specified with the `.` character (`.py` and `py` both map to a task executable "\ - "`task.py`) and the extension is case sensitive. When a target's name is `localhost`, "\ + description: "A map of an extension name to the absolute path of an executable, enabling you to " \ + "override the shebang defined in a task executable. The extension can optionally be " \ + "specified with the `.` character (`.py` and `py` both map to a task executable " \ + "`task.py`) and the extension is case sensitive. When a target's name is `localhost`, " \ "Ruby tasks run with the Bolt Ruby interpreter by default.", additionalProperties: { type: [String, Array], @@ -181,11 +181,11 @@ module Options }, "kex-algorithms" => { type: Array, - description: "A list of key exchange algorithms to use when establishing a connection "\ - "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be "\ - "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, "\ - "non-deprecated algorithms are available by default when this option is not used. To "\ - "reference all default algorithms using this option, add 'defaults' to the list of "\ + description: "A list of key exchange algorithms to use when establishing a connection " \ + "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be " \ + "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, " \ + "non-deprecated algorithms are available by default when this option is not used. To " \ + "reference all default algorithms using this option, add 'defaults' to the list of " \ "supported algorithms.", uniqueItems: true, items: { @@ -212,11 +212,11 @@ module Options }, "mac-algorithms" => { type: Array, - description: "List of message authentication code algorithms to use when establishing a connection "\ - "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be "\ - "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, "\ - "non-deprecated algorithms are available by default when this option is not used. To "\ - "reference all default algorithms using this option, add 'defaults' to the list of "\ + description: "List of message authentication code algorithms to use when establishing a connection " \ + "to a target. Supported algorithms are defined by the Ruby net-ssh library and can be " \ + "viewed [here](https://github.com/net-ssh/net-ssh#supported-algorithms). All supported, " \ + "non-deprecated algorithms are available by default when this option is not used. To " \ + "reference all default algorithms using this option, add 'defaults' to the list of " \ "supported algorithms.", uniqueItems: true, items: { @@ -227,7 +227,7 @@ module Options }, "native-ssh" => { type: [TrueClass, FalseClass], - description: "This enables the native SSH transport, which shells out to SSH instead of using the "\ + description: "This enables the native SSH transport, which shells out to SSH instead of using the " \ "net-ssh Ruby library", _default: false, _example: true @@ -247,8 +247,8 @@ module Options }, "private-key" => { type: [Hash, String], - description: "Either the path to the private key file to use for authentication, or "\ - "a hash with the key `key-data` and the contents of the private key. Note that "\ + description: "Either the path to the private key file to use for authentication, or " \ + "a hash with the key `key-data` and the contents of the private key. Note that " \ "the key cannot be encrypted if using the `key-data` hash.", required: ["key-data"], properties: { @@ -289,16 +289,16 @@ module Options }, "run-as" => { type: String, - description: "The user to run commands as after login. The run-as user must be different than the "\ + description: "The user to run commands as after login. The run-as user must be different than the " \ "login user.", _plugin: true, _example: "root" }, "run-as-command" => { type: Array, - description: "The command to elevate permissions. Bolt appends the user and command strings to the "\ - "configured `run-as-command` before running it on the target. This command must not require "\ - " aninteractive password prompt, and the `sudo-password` option is ignored when "\ + description: "The command to elevate permissions. Bolt appends the user and command strings to the " \ + "configured `run-as-command` before running it on the target. This command must not require " \ + "aninteractive password prompt, and the `sudo-password` option is ignored when " \ "`run-as-command` is specified. The `run-as-command` must be specified as an array.", items: { type: String @@ -316,9 +316,9 @@ module Options }, "script-dir" => { type: String, - description: "The subdirectory of the tmpdir to use in place of a randomized "\ - "subdirectory for uploading and executing temporary files on the "\ - "target. It's expected that this directory already exists as a subdir "\ + description: "The subdirectory of the tmpdir to use in place of a randomized " \ + "subdirectory for uploading and executing temporary files on the " \ + "target. It's expected that this directory already exists as a subdir " \ "of tmpdir, which is either configured or defaults to `/tmp`.", _plugin: true, _example: "bolt_scripts" @@ -345,9 +345,9 @@ module Options }, "ssh-command" => { type: [Array, String], - description: "The command and options to use when SSHing. This option is used when you need support for "\ - "features or algorithms that are not supported by the net-ssh Ruby library. **This option "\ - "is experimental.** You can read more about this option in [Native SSH "\ + description: "The command and options to use when SSHing. This option is used when you need support for " \ + "features or algorithms that are not supported by the net-ssh Ruby library. **This option " \ + "is experimental.** You can read more about this option in [Native SSH " \ "transport](experimental_features.md#native-ssh-transport).", items: { type: String @@ -372,10 +372,10 @@ module Options }, "sudo-executable" => { type: String, - description: "The executable to use when escalating to the configured `run-as` user. This is useful "\ - "when you want to escalate using the configured `sudo-password`, since `run-as-command` "\ - "does not use `sudo-password` or support prompting. The command executed on the target "\ - "is ` -S -u -p custom_bolt_prompt `. **This option is "\ + description: "The executable to use when escalating to the configured `run-as` user. This is useful " \ + "when you want to escalate using the configured `sudo-password`, since `run-as-command` " \ + "does not use `sudo-password` or support prompting. The command executed on the target " \ + "is ` -S -u -p custom_bolt_prompt `. **This option is " \ "experimental.**", _plugin: true, _example: "dzdo" diff --git a/lib/bolt/executor.rb b/lib/bolt/executor.rb index 548bdbcee..0700617bd 100644 --- a/lib/bolt/executor.rb +++ b/lib/bolt/executor.rb @@ -82,6 +82,7 @@ def initialize(concurrency = 1, def transport(transport) impl = @transports[transport || 'ssh'] raise(Bolt::UnknownTransportError, transport) unless impl + # If there was an error creating the transport, ensure it gets thrown impl.no_error! impl.value @@ -105,6 +106,7 @@ def publish_event(event) # If types isn't set or if the subscriber is subscribed to # that type of event, publish the event next unless types.nil? || types.include?(event[:type]) + @publisher.post(subscriber) do |sub| # Wait for user to input to prompt before printing anything sleep(0.1) while @prompting @@ -127,10 +129,10 @@ def shutdown def queue_execute(targets) if @warn_concurrency && targets.length > @concurrency @warn_concurrency = false - msg = "The ulimit is low, which might cause file limit issues. Default concurrency has been set to "\ - "'#{@concurrency}' to mitigate those issues, which might cause Bolt to run slow. "\ - "Disable this warning by configuring ulimit using 'ulimit -n ' in your shell "\ - "configuration, or by configuring Bolt's concurrency. "\ + msg = "The ulimit is low, which might cause file limit issues. Default concurrency has been set to " \ + "'#{@concurrency}' to mitigate those issues, which might cause Bolt to run slow. " \ + "Disable this warning by configuring ulimit using 'ulimit -n ' in your shell " \ + "configuration, or by configuring Bolt's concurrency. " \ "See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details." Bolt::Logger.warn("low_ulimit", msg) end @@ -167,6 +169,7 @@ def queue_execute(targets) # exception and some promise is still missing a result. result_promises.each do |target, promise| next if promise.fulfilled? + error = $ERROR_INFO || Bolt::Error.new("No result was returned for #{target.uri}", "puppetlabs.bolt/missing-result-error") promise.set(Bolt::Result.from_exception(target, error)) @@ -477,6 +480,7 @@ def wait_until_available(targets, start = wait_now until yield raise(TimeoutError, 'Timed out waiting for target') if (wait_now - start).to_i >= timeout + sleep(retry_interval) end end @@ -484,6 +488,7 @@ def wait_until_available(targets, def prompt(prompt, options) unless $stdin.tty? return options[:default] if options[:default] + raise Bolt::Error.new('STDIN is not a tty, unable to prompt', 'bolt/no-tty-error') end diff --git a/lib/bolt/fiber_executor.rb b/lib/bolt/fiber_executor.rb index 5296f754e..386a90d41 100644 --- a/lib/bolt/fiber_executor.rb +++ b/lib/bolt/fiber_executor.rb @@ -82,6 +82,7 @@ def round_robin # Once we've restarted the Fiber, check to see if it's finished again # and cleanup if it has. next if future.alive? + @logger.trace("Cleaning up future '#{future.name}'") # If the future errored and the main plan has already exited, log the @@ -99,6 +100,7 @@ def round_robin # execute before checking again. This mitigates CPU # thrashing. return unless active_futures.all? { |f| %i[returned_immediately unfinished].include?(f.value) } + @logger.trace("Nothing can be resumed. Rechecking in 0.5 seconds.") sleep(0.5) @@ -145,7 +147,7 @@ def wait(futures, timeout: nil, catch_errors: false, **_kwargs) # futures being waited on. until (futures = get_futures_for_plan(plan_id: plan_id)).map(&:alive?).none? if futures.map(&:fiber).include?(Fiber.current) - msg = "The wait() function cannot be called with no arguments inside a "\ + msg = "The wait() function cannot be called with no arguments inside a " \ "background block in the same plan." raise Bolt::Error.new(msg, 'bolt/infinite-wait') end diff --git a/lib/bolt/inventory.rb b/lib/bolt/inventory.rb index 3bb48c2ce..3b5b53aa0 100644 --- a/lib/bolt/inventory.rb +++ b/lib/bolt/inventory.rb @@ -71,6 +71,7 @@ def self.from_config(config, plugins) source = ENVIRONMENT_VAR data = YAML.safe_load(ENV[ENVIRONMENT_VAR]) raise Bolt::ParseError, "Could not parse inventory from $#{ENVIRONMENT_VAR}" unless data.is_a?(Hash) + logger.debug("Loaded inventory from environment variable #{ENVIRONMENT_VAR}") rescue Psych::Exception raise Bolt::ParseError, "Could not parse inventory from $#{ENVIRONMENT_VAR}" diff --git a/lib/bolt/inventory/group.rb b/lib/bolt/inventory/group.rb index f8a5a98c1..8ee99c748 100644 --- a/lib/bolt/inventory/group.rb +++ b/lib/bolt/inventory/group.rb @@ -179,6 +179,7 @@ def insert_alia(target_name, aliases) if (found = @aliases[alia]) raise ValidationError.new(alias_conflict(alia, found, target_name), @name) end + @aliases[alia] = target_name end end @@ -339,8 +340,10 @@ def resolve_data_keys(data, target = nil) Bolt::Config::Options::TRANSPORT_CONFIG.each_key do |transport| next unless result['config'].key?(transport) + transport_config = result['config'][transport] next unless transport_config.is_a?(Hash) + transport_config = Bolt::Util.postwalk_vals(transport_config) do |val| if val.is_a?(Hash) val = val.compact diff --git a/lib/bolt/inventory/inventory.rb b/lib/bolt/inventory/inventory.rb index b2bd75cf4..bfbe50937 100644 --- a/lib/bolt/inventory/inventory.rb +++ b/lib/bolt/inventory/inventory.rb @@ -109,6 +109,7 @@ def get_target(target) if target_array.count > 1 raise ValidationError.new("'#{target}' refers to #{target_array.count} targets", nil) end + target_array.first end @@ -158,6 +159,7 @@ def resolve_name(target, ext_glob: false) # Find groups that match the glob group_lookup.each do |name, grp| next unless match_wildcard?(target, name, ext_glob: ext_glob) + targets += grp.all_targets.to_a end diff --git a/lib/bolt/inventory/options.rb b/lib/bolt/inventory/options.rb index 81f6c48b7..99cba6059 100644 --- a/lib/bolt/inventory/options.rb +++ b/lib/bolt/inventory/options.rb @@ -21,7 +21,7 @@ module Options # https://github.com/puppetlabs/bolt/blob/main/schemas/README.md DEFINITIONS = { "alias" => { - description: "A unique alias to refer to the target. Aliases cannot conflict "\ + description: "A unique alias to refer to the target. Aliases cannot conflict " \ "with the name of a group, the name of a target, or another alias.", type: [String, Array], uniqueItems: true, @@ -74,16 +74,16 @@ module Options _plugin: true }, "name" => { - description: "A human-readable name to refer to the group or target. Names "\ - "cannot conflict with the name of a group, the name of a target, "\ - "or the alias of a target. A name is required for a group and is "\ + description: "A human-readable name to refer to the group or target. Names " \ + "cannot conflict with the name of a group, the name of a target, " \ + "or the alias of a target. A name is required for a group and is " \ "required for a target unless the uri option is set.", type: String, _plugin: true }, "plugin_hooks" => { - description: "Configuration for the Puppet library plugin used to install the "\ - "Puppet agent on the target. For more information, see "\ + description: "Configuration for the Puppet library plugin used to install the " \ + "Puppet agent on the target. For more information, see " \ "https://pup.pt/bolt-plugin-hooks", type: Hash, properties: { @@ -115,7 +115,7 @@ module Options _plugin: true }, "uri" => { - description: "The URI of the target. This option is required unless the name "\ + description: "The URI of the target. This option is required unless the name " \ "option is set.", type: String, format: "uri", diff --git a/lib/bolt/inventory/target.rb b/lib/bolt/inventory/target.rb index 0496c37b3..9e9d85739 100644 --- a/lib/bolt/inventory/target.rb +++ b/lib/bolt/inventory/target.rb @@ -59,6 +59,7 @@ def initialize(target_data, inventory) def set_local_defaults return if @set_local_default + defaults = { 'local' => { 'interpreters' => { '.rb' => RbConfig.ruby } } } @@ -176,8 +177,8 @@ def validate if (dotted = facts.keys.select { |name| name.include?('.') }).any? Bolt::Logger.deprecate( 'dotted_fact_name', - "Target '#{safe_name}' includes dotted fact names: '#{dotted.join("', '")}'. Dotted fact "\ - "names are deprecated and Bolt does not automatically convert facts with dotted names to "\ + "Target '#{safe_name}' includes dotted fact names: '#{dotted.join("', '")}'. Dotted fact " \ + "names are deprecated and Bolt does not automatically convert facts with dotted names to " \ "structured facts. For more information, see https://pup.pt/bolt-dotted-facts" ) end diff --git a/lib/bolt/logger.rb b/lib/bolt/logger.rb index fa564872e..37b883f59 100644 --- a/lib/bolt/logger.rb +++ b/lib/bolt/logger.rb @@ -231,11 +231,13 @@ def self.flush_queue # private_class_method def self.do_warn(msg, id) return if @disable_warnings.include?(id) + logger(self).warn(msg) end private_class_method def self.do_warn_once(msg, id) return unless @warnings.add?(id) + do_warn(msg, id) end diff --git a/lib/bolt/module.rb b/lib/bolt/module.rb index b0f2ca660..7775ea66d 100644 --- a/lib/bolt/module.rb +++ b/lib/bolt/module.rb @@ -15,6 +15,7 @@ def self.discover(modulepath, project) modulepath.each do |path| next unless File.exist?(path) && File.directory?(path) + Dir.children(path) .map { |dir| File.join(path, dir) } .select { |dir| File.directory?(dir) } diff --git a/lib/bolt/module_installer.rb b/lib/bolt/module_installer.rb index da549273f..897d6992c 100644 --- a/lib/bolt/module_installer.rb +++ b/lib/bolt/module_installer.rb @@ -23,7 +23,7 @@ def add(name, specs, puppetfile_path, moduledir, project_file, config) # Exit early if project config already includes a spec with this name. if project_specs.include?(name) @outputter.print_message( - "Project configuration file #{project_file} already includes specification "\ + "Project configuration file #{project_file} already includes specification " \ "with name #{name}. Nothing to do." ) return true @@ -92,11 +92,13 @@ def print_puppetfile_diff(old, new) # modified. old = (old&.modules || []).each_with_object({}) do |mod, acc| next unless mod.type == :forge + acc[mod.full_name] = mod end new = new.modules.each_with_object({}) do |mod, acc| next unless mod.type == :forge + acc[mod.full_name] = mod end diff --git a/lib/bolt/module_installer/puppetfile.rb b/lib/bolt/module_installer/puppetfile.rb index d768a9300..24f0a2f47 100644 --- a/lib/bolt/module_installer/puppetfile.rb +++ b/lib/bolt/module_installer/puppetfile.rb @@ -56,7 +56,7 @@ def self.parse(path, skip_unsupported_modules: false) else unless skip_unsupported_modules raise Bolt::ValidationError, - "Cannot parse Puppetfile at #{path}, module '#{mod.title}' is not a "\ + "Cannot parse Puppetfile at #{path}, module '#{mod.title}' is not a " \ "Puppet Forge or Git module." end end @@ -105,7 +105,7 @@ def assert_satisfies(specs) Puppetfile does not include modules that satisfy the following specifications: #{unsatisfied_specs.map(&:to_hash).to_yaml.lines.drop(1).join.chomp} - + This Puppetfile might not be managed by Bolt. To forcibly overwrite the Puppetfile, run '#{command}'. MESSAGE @@ -116,9 +116,9 @@ def assert_satisfies(specs) if versionless_mods.any? message = <<~MESSAGE.chomp Puppetfile includes Forge modules without a version requirement: - + #{versionless_mods.map(&:to_spec).join.chomp} - + This Puppetfile might not be managed by Bolt. To forcibly overwrite the Puppetfile, run '#{command}'. MESSAGE diff --git a/lib/bolt/module_installer/resolver.rb b/lib/bolt/module_installer/resolver.rb index 7985b8abb..86816f9e8 100644 --- a/lib/bolt/module_installer/resolver.rb +++ b/lib/bolt/module_installer/resolver.rb @@ -98,8 +98,8 @@ def resolve(specs, config = {}) # names, but we error early here to provide a more helpful message. if (name_conflicts = modules.map(&:name) & unresolved.map(&:name)).any? raise Bolt::Error.new( - "Detected unresolved module specifications with the same name as a resolved module "\ - "dependency: #{name_conflicts.join(', ')}. Either remove the unresolved module specification "\ + "Detected unresolved module specifications with the same name as a resolved module " \ + "dependency: #{name_conflicts.join(', ')}. Either remove the unresolved module specification " \ "or set the module with the conflicting dependency to not resolve.", "bolt/module-name-conflict-error" ) diff --git a/lib/bolt/module_installer/specs/forge_spec.rb b/lib/bolt/module_installer/specs/forge_spec.rb index 65ede484d..bb56749cd 100644 --- a/lib/bolt/module_installer/specs/forge_spec.rb +++ b/lib/bolt/module_installer/specs/forge_spec.rb @@ -38,9 +38,9 @@ def self.implements?(hash) private def parse_name(name) unless (match = name.match(NAME_REGEX)) raise Bolt::ValidationError, - "Invalid name for Forge module specification: #{name}. Name must match "\ - "'owner/name'. Owner segment can only include letters or digits. Name "\ - "segment must start with a lowercase letter and can only include lowercase "\ + "Invalid name for Forge module specification: #{name}. Name must match " \ + "'owner/name'. Owner segment can only include letters or digits. Name " \ + "segment must start with a lowercase letter and can only include lowercase " \ "letters, digits, and underscores." end @@ -53,7 +53,7 @@ def self.implements?(hash) [version_requirement, SemanticPuppet::VersionRange.parse(version_requirement || '>= 0')] rescue StandardError raise Bolt::ValidationError, - "Invalid version requirement for Forge module specification #{@full_name}: "\ + "Invalid version requirement for Forge module specification #{@full_name}: " \ "#{version_requirement.inspect}" end diff --git a/lib/bolt/module_installer/specs/git_spec.rb b/lib/bolt/module_installer/specs/git_spec.rb index e4543f3bf..49567289c 100644 --- a/lib/bolt/module_installer/specs/git_spec.rb +++ b/lib/bolt/module_installer/specs/git_spec.rb @@ -39,7 +39,7 @@ def initialize(init_hash, config = {}) if @name.nil? && @resolve == false raise Bolt::ValidationError, - "Missing name for Git module specification: #{@git}. Git module specifications "\ + "Missing name for Git module specification: #{@git}. Git module specifications " \ "must include a 'name' key when 'resolve' is false." end @@ -61,9 +61,9 @@ def self.implements?(hash) unless (match = name.match(NAME_REGEX)) raise Bolt::ValidationError, - "Invalid name for Git module specification: #{name}. Name must match "\ - "'name' or 'owner/name'. Owner segment can only include letters or digits. "\ - "Name segment must start with a lowercase letter and can only include "\ + "Invalid name for Git module specification: #{name}. Name must match " \ + "'name' or 'owner/name'. Owner segment can only include letters or digits. " \ + "Name segment must start with a lowercase letter and can only include " \ "lowercase letters, digits, and underscores." end @@ -123,8 +123,8 @@ def sha unless module_id raise Bolt::Error.new( - "Unable to locate metadata and calculate SHA for ref #{@ref} at #{@git}. This may "\ - "not be a valid module. For more information about how Bolt attempted to locate "\ + "Unable to locate metadata and calculate SHA for ref #{@ref} at #{@git}. This may " \ + "not be a valid module. For more information about how Bolt attempted to locate " \ "this information, check the debugging logs.", 'bolt/missing-module-metadata-error' ) diff --git a/lib/bolt/module_installer/specs/id/gitclone.rb b/lib/bolt/module_installer/specs/id/gitclone.rb index d761a4ac7..c527abc51 100644 --- a/lib/bolt/module_installer/specs/id/gitclone.rb +++ b/lib/bolt/module_installer/specs/id/gitclone.rb @@ -96,6 +96,7 @@ class GitClone < Base Bolt::Logger.debug("Executing command '#{bare_clone.join(' ')}'") _out, err, status = Open3.capture3(*bare_clone) return true if status.success? + Bolt::Logger.debug("Unable to clone bare repository at #{loc(git, proxy)}: #{err}") # Fall back to cloning the full repository diff --git a/lib/bolt/module_installer/specs/id/github.rb b/lib/bolt/module_installer/specs/id/github.rb index 57afffd83..9d824dfbb 100644 --- a/lib/bolt/module_installer/specs/id/github.rb +++ b/lib/bolt/module_installer/specs/id/github.rb @@ -16,6 +16,7 @@ class GitHub < Base private_class_method def self.name_and_sha(git, ref, proxy) repo = parse_repo(git) return nil unless repo + [request_name(repo, ref, proxy), request_sha(repo, ref, proxy)] end @@ -72,7 +73,7 @@ class GitHub < Base message = "GitHub API rate limit exceeded, unable to calculate SHA." unless ENV['GITHUB_TOKEN'] - message += " To increase your rate limit, set the GITHUB_TOKEN environment "\ + message += " To increase your rate limit, set the GITHUB_TOKEN environment " \ "variable with a GitHub personal access token." end diff --git a/lib/bolt/module_installer/specs/id/gitlab.rb b/lib/bolt/module_installer/specs/id/gitlab.rb index 870dce4ee..43318a666 100644 --- a/lib/bolt/module_installer/specs/id/gitlab.rb +++ b/lib/bolt/module_installer/specs/id/gitlab.rb @@ -16,6 +16,7 @@ class GitLab < Base private_class_method def self.name_and_sha(git, ref, proxy) repo = parse_repo(git) return nil unless repo + [request_name(repo, ref, proxy), request_sha(repo, ref, proxy)] end @@ -74,7 +75,7 @@ class GitLab < Base message = "GitLab API rate limit exceeded, unable to calculate SHA." unless ENV['GITLAB_TOKEN'] - message += " To increase your rate limit, set the GITLAB_TOKEN environment "\ + message += " To increase your rate limit, set the GITLAB_TOKEN environment " \ "variable with a GitLab personal access token." end diff --git a/lib/bolt/outputter/human.rb b/lib/bolt/outputter/human.rb index 5aeab22ac..54a6b1419 100644 --- a/lib/bolt/outputter/human.rb +++ b/lib/bolt/outputter/human.rb @@ -36,6 +36,7 @@ def colorize(color, string) def start_spin return unless @spin && @stream.isatty && !@spinning + @spinning = true @spin_thread = Thread.new do loop do @@ -47,6 +48,7 @@ def start_spin def stop_spin return unless @spin && @stream.isatty && @spinning + @spinning = false @spin_thread.terminate @stream.print("\b") @@ -61,6 +63,7 @@ def remove_trail(string) # def wrap(string, width = 80) return string unless string.is_a?(String) + string.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n") end @@ -68,6 +71,7 @@ def wrap(string, width = 80) # def truncate(string, width = 80) return string unless string.is_a?(String) && string.length > width + string.lines.first[0...width].gsub(/\s\w+\s*$/, '...') end @@ -164,6 +168,7 @@ def print_result(result) result.resource_logs.each do |log| # Omit low-level info/debug messages next if %w[info debug].include?(log['level']) + message = format_log(log) @stream.puts(indent(2, message)) end @@ -656,7 +661,7 @@ def print_new_plan(name:, path:) print_message(<<~OUTPUT) Created plan '#{name}' at '#{path}' - + Show this plan with: #{show_command} #{name} Run this plan with: @@ -675,7 +680,7 @@ def print_new_policy(name:, path:) print_message(<<~OUTPUT) Created policy '#{name}' at '#{path}' - + Apply this policy with: #{apply_command} Show available policies with: @@ -786,8 +791,8 @@ def print_target_info(adhoc:, inventory:, flag:, **_kwargs) info = +'' # Add target count summary - count = "#{inventory_count + adhoc_count} total, "\ - "#{inventory_count} from inventory, "\ + count = "#{inventory_count + adhoc_count} total, " \ + "#{inventory_count} from inventory, " \ "#{adhoc_count} adhoc" info << colorize(:cyan, "Target count\n") info << indent(2, count) diff --git a/lib/bolt/outputter/rainbow.rb b/lib/bolt/outputter/rainbow.rb index cb1a811ab..f1d4915e8 100644 --- a/lib/bolt/outputter/rainbow.rb +++ b/lib/bolt/outputter/rainbow.rb @@ -65,6 +65,7 @@ def colorize(color, string) def start_spin return unless @spin && @stream.isatty && !@spinning + @spinning = true @spin_thread = Thread.new do loop do diff --git a/lib/bolt/pal.rb b/lib/bolt/pal.rb index 5857a9e48..523d9d13d 100644 --- a/lib/bolt/pal.rb +++ b/lib/bolt/pal.rb @@ -147,6 +147,7 @@ def register_resource_types(loaders) def detect_project_conflict(project, environment) return unless project && project.load_as_module? + # The environment modulepath has stripped out non-existent directories, # so we don't need to check for them modules = environment.modulepath.flat_map do |path| @@ -192,7 +193,7 @@ def in_bolt_compiler(compiler_params: {}) rescue Puppet::PreformattedError => e if e.issue_code == :UNKNOWN_VARIABLE && %w[facts trusted server_facts settings].include?(e.arguments[:name]) - message = "Evaluation Error: Variable '#{e.arguments[:name]}' is not available in the current scope "\ + message = "Evaluation Error: Variable '#{e.arguments[:name]}' is not available in the current scope " \ "unless explicitly defined." details = { file: e.file, line: e.line, column: e.pos } PALError.new(message, details) @@ -210,6 +211,7 @@ def in_bolt_compiler(compiler_params: {}) if r.is_a?(StandardError) && !r.is_a?(Bolt::PuppetError) raise r end + r end @@ -339,6 +341,7 @@ def list_tasks_with_cache(filter_content: false) # If any file has been updated since we last cached, update the # cache next unless file_modified?(f['path'], f['mtime']) + data = get_task_info(task_name, with_mtime: true) data = Bolt::Util.walk_keys(data, &:to_s) # Tell Bolt to write to the cache file once we're done diff --git a/lib/bolt/pal/yaml_plan/parameter.rb b/lib/bolt/pal/yaml_plan/parameter.rb index 15e6977e9..956704855 100644 --- a/lib/bolt/pal/yaml_plan/parameter.rb +++ b/lib/bolt/pal/yaml_plan/parameter.rb @@ -26,8 +26,8 @@ def validate_param(param, definition) definition_keys = definition.keys.to_set unless PARAMETER_KEYS.superset?(definition_keys) invalid_keys = definition_keys - PARAMETER_KEYS - raise Bolt::Error.new("Plan parameter #{param.inspect} contains illegal key(s)" \ - " #{invalid_keys.to_a.inspect}", + raise Bolt::Error.new("Plan parameter #{param.inspect} contains illegal key(s) " \ + "#{invalid_keys.to_a.inspect}", "bolt/invalid-plan") end end diff --git a/lib/bolt/pal/yaml_plan/step/resources.rb b/lib/bolt/pal/yaml_plan/step/resources.rb index fad1aa70a..ed7f51039 100644 --- a/lib/bolt/pal/yaml_plan/step/resources.rb +++ b/lib/bolt/pal/yaml_plan/step/resources.rb @@ -58,7 +58,7 @@ def evaluate(scope, evaluator) * => $res['parameters'], } } - + # Add relationships if there is more than one resource if $resources.length > 1 { ($resources.length - 1).each |$index| { diff --git a/lib/bolt/plan_creator.rb b/lib/bolt/plan_creator.rb index e2411dcd6..7f44a6b80 100644 --- a/lib/bolt/plan_creator.rb +++ b/lib/bolt/plan_creator.rb @@ -10,8 +10,8 @@ module PlanCreator def self.validate_plan_name(project, plan_name) if project.name.nil? raise Bolt::Error.new( - "Project directory '#{project.path}' is not a named project. Unable to create "\ - "a project-level plan. To name a project, set the 'name' key in the 'bolt-project.yaml' "\ + "Project directory '#{project.path}' is not a named project. Unable to create " \ + "a project-level plan. To name a project, set the 'name' key in the 'bolt-project.yaml' " \ "configuration file.", "bolt/unnamed-project-error" ) @@ -36,7 +36,7 @@ def self.validate_plan_name(project, plan_name) prefix, _, basename = segment_plan_name(plan_name) unless prefix == project.name - message = "Incomplete plan name: A plan name must be prefixed with the name of the "\ + message = "Incomplete plan name: A plan name must be prefixed with the name of the " \ "project or module. Did you mean '#{project.name}::#{plan_name}'?" raise Bolt::ValidationError, message @@ -44,6 +44,7 @@ def self.validate_plan_name(project, plan_name) %w[pp yaml].each do |ext| next unless (path = project.plans_path + "#{basename}.#{ext}").exist? + raise Bolt::Error.new( "A plan with the name '#{plan_name}' already exists at '#{path}', nothing to do.", 'bolt/existing-plan-error' @@ -146,7 +147,7 @@ def self.segment_plan_name(plan_name) <<~YAML # This is the structure of a simple plan. To learn more about writing # YAML plans, see the documentation: http://pup.pt/bolt-yaml-plans - + # The description sets the description of the plan that will appear # in 'bolt plan show' output. description: A plan created with bolt plan new diff --git a/lib/bolt/plugin.rb b/lib/bolt/plugin.rb index ab02107f7..3c7807b38 100644 --- a/lib/bolt/plugin.rb +++ b/lib/bolt/plugin.rb @@ -203,6 +203,7 @@ def add_module_plugin(plugin_name) def config_for_plugin(plugin_name) return {} unless @unresolved_plugin_configs.include?(plugin_name) + if @resolution_stack.include?(plugin_name) msg = "Configuration for plugin '#{plugin_name}' depends on the plugin itself" raise PluginError.new(msg, 'bolt/plugin-error') @@ -225,6 +226,7 @@ def get_hook(plugin_name, hook) plugin = by_name(plugin_name) raise PluginError::Unknown, plugin_name unless plugin raise PluginError::UnsupportedHook.new(plugin_name, hook) unless plugin.hooks.include?(hook) + @analytics.report_bundled_content("Plugin #{hook}", plugin_name) plugin.method(hook) @@ -260,6 +262,7 @@ def list_plugins when Bolt::Plugin::Module plugin.hook_map.each do |hook, spec| next unless hooks.include?(hook) + hooks[hook][name] = spec['task'].description end else @@ -277,6 +280,7 @@ def list_plugins private def load_all_plugins modules.each do |name, mod| next unless mod.plugin? + by_name(name) end diff --git a/lib/bolt/plugin/cache.rb b/lib/bolt/plugin/cache.rb index 04f1309e9..f216e29c8 100644 --- a/lib/bolt/plugin/cache.rb +++ b/lib/bolt/plugin/cache.rb @@ -17,6 +17,7 @@ def initialize(reference, plugin_cache_file, default_config) def read_and_clean_cache return if ttl == 0 + validate # Luckily we don't need to use a serious hash algorithm @@ -53,6 +54,7 @@ def validate # The default cache `plugin-cache` will be validated by the config # validator return if reference['_cache'].nil? + r = reference['_cache'] unless r.is_a?(Hash) raise Bolt::ValidationError, diff --git a/lib/bolt/plugin/module.rb b/lib/bolt/plugin/module.rb index 9565502e3..8ed4edd74 100644 --- a/lib/bolt/plugin/module.rb +++ b/lib/bolt/plugin/module.rb @@ -67,6 +67,7 @@ def load_data def process_schema(schema) raise InvalidPluginData.new('config specification is not an object', name) unless schema.is_a?(Hash) + schema.each do |key, val| unless key =~ /\A[a-z][a-z0-9_]*\z/ raise InvalidPluginData.new("config specification key, '#{key}', is not allowed", name) @@ -102,6 +103,7 @@ def validate_config(config, config_schema) unless spec['pcore_type'].instance?(val) raise Bolt::ValidationError, "#{name} plugin expects a #{spec['type']} for key #{key}, got: #{val}" end + val.nil? end nil @@ -177,8 +179,10 @@ def extract_task_parameter_schema # Get the intersection of expected types (using Set) type_set = @hook_map.each_with_object({}) do |(_hook, task), acc| next unless (schema = task['task'].metadata['parameters']) + schema.each do |param, scheme| next unless scheme['type'].is_a?(String) + scheme['type'] = Set.new([scheme['type']]) if acc.dig(param, 'type').is_a?(Set) scheme['type'].merge(acc[param]['type']) @@ -189,6 +193,7 @@ def extract_task_parameter_schema # Convert Set to string type_set.each do |_param, schema| next unless schema['type'] + schema['type'] = if schema['type'].size > 1 "Optional[Variant[#{schema['type'].to_a.join(', ')}]]" else @@ -210,6 +215,7 @@ def run_task(task, opts) options).first raise Bolt::Error.new(result.error_hash['msg'], result.error_hash['kind']) unless result.ok + result.value end @@ -217,6 +223,7 @@ def run_hook(hook_name, opts, value = true) hook = @hook_map[hook_name] # This shouldn't happen if the Plugin api is used raise PluginError::UnsupportedHook.new(name, hook_name) unless hook + result = run_task(hook['task'], opts) if value diff --git a/lib/bolt/plugin/puppet_connect_data.rb b/lib/bolt/plugin/puppet_connect_data.rb index 3ba1384b7..681240ea4 100644 --- a/lib/bolt/plugin/puppet_connect_data.rb +++ b/lib/bolt/plugin/puppet_connect_data.rb @@ -38,6 +38,7 @@ def initialize(context:, **_opts) if current_value.is_a?(Hash) && current_value.key?('_plugin') raise invalid_input_data_err("the #{key} key's value contains a plugin reference") end + current_value end end diff --git a/lib/bolt/plugin/task.rb b/lib/bolt/plugin/task.rb index 4ac2d9c0d..dcd447143 100644 --- a/lib/bolt/plugin/task.rb +++ b/lib/bolt/plugin/task.rb @@ -30,16 +30,19 @@ def run_task(opts) options = { catch_errors: true } raise Bolt::ValidationError, "Task plugin requires that the 'task' is specified" unless opts['task'] + task = @context.get_validated_task(opts['task'], params) result = @context.run_local_task(task, params, options).first raise Bolt::Error.new(result.error_hash['msg'], result.error_hash['kind']) if result.error_hash + result end def validate_options(opts) raise Bolt::ValidationError, "Task plugin requires that the 'task' is specified" unless opts['task'] + @context.get_validated_task(opts['task'], opts['parameters'] || {}) end alias validate_resolve_reference validate_options diff --git a/lib/bolt/project.rb b/lib/bolt/project.rb index 072f01b49..e7e9b2546 100644 --- a/lib/bolt/project.rb +++ b/lib/bolt/project.rb @@ -55,7 +55,7 @@ def self.create_project(path, type = 'option') rescue StandardError Bolt::Logger.warn( "non_writeable_project", - "Could not create default project at #{path}. Continuing without a writeable project. "\ + "Could not create default project at #{path}. Continuing without a writeable project. " \ "Log and rerun files will not be written." ) end @@ -67,7 +67,7 @@ def self.create_project(path, type = 'option') if !Bolt::Util.windows? && type != 'environment' && fullpath.world_writable? raise Bolt::Error.new( - "Project directory '#{fullpath}' is world-writable which poses a security risk. Set "\ + "Project directory '#{fullpath}' is world-writable which poses a security risk. Set " \ "BOLT_PROJECT='#{fullpath}' to force the use of this project directory.", "bolt/world-writable-error" ) @@ -203,7 +203,7 @@ def validate and can include lowercase letters, numbers, and underscores. ERROR_STRING elsif Dir.children(Bolt::Config::Modulepath::BOLTLIB_PATH).include?(name) - raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\ + raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts " \ "with a built-in Bolt module of the same name." end elsif name.nil? && diff --git a/lib/bolt/project_manager.rb b/lib/bolt/project_manager.rb index 7316f60d1..2a1c294c6 100644 --- a/lib/bolt/project_manager.rb +++ b/lib/bolt/project_manager.rb @@ -70,14 +70,14 @@ def create(path, name, modules) if modules command = Bolt::Util.powershell? ? 'Add-BoltModule -Module' : 'bolt module add' raise Bolt::Error.new( - "Found existing project directory with #{config.basename} at #{project}, "\ - "unable to initialize project with modules. To add modules to the project, "\ + "Found existing project directory with #{config.basename} at #{project}, " \ + "unable to initialize project with modules. To add modules to the project, " \ "run '#{command} ' instead.", 'bolt/existing-project-error' ) else raise Bolt::Error.new( - "Found existing project directory with #{config.basename} at #{project}, "\ + "Found existing project directory with #{config.basename} at #{project}, " \ "unable to initialize project.", 'bolt/existing-project-error' ) @@ -85,27 +85,27 @@ def create(path, name, modules) elsif old_config.exist? command = Bolt::Util.powershell? ? 'Update-BoltProject' : 'bolt project migrate' raise Bolt::Error.new( - "Found existing project directory with #{old_config.basename} at #{project}, "\ - "unable to initialize project. #{old_config.basename} is deprecated. To "\ + "Found existing project directory with #{old_config.basename} at #{project}, " \ + "unable to initialize project. #{old_config.basename} is deprecated. To " \ "update the project to current best practices, run '#{command}'.", 'bolt/existing-project-error' ) elsif modules && puppetfile.exist? raise Bolt::Error.new( - "Found existing Puppetfile at #{puppetfile}, unable to initialize project "\ + "Found existing Puppetfile at #{puppetfile}, unable to initialize project " \ "with modules.", 'bolt/existing-puppetfile-error' ) elsif project_name !~ Bolt::Module::MODULE_NAME_REGEX if name raise Bolt::ValidationError, - "The provided project name '#{project_name}' is invalid; project name must "\ - "begin with a lowercase letter and can include lowercase letters, "\ + "The provided project name '#{project_name}' is invalid; project name must " \ + "begin with a lowercase letter and can include lowercase letters, " \ "numbers, and underscores." else command = Bolt::Util.powershell? ? 'New-BoltProject -Name' : 'bolt project init' raise Bolt::ValidationError, - "The current directory name '#{project_name}' is an invalid project name. "\ + "The current directory name '#{project_name}' is an invalid project name. " \ "Please specify a name using '#{command} '." end end @@ -162,8 +162,8 @@ def migrate @outputter.print_message("Migrating project #{@config.project.path}\n\n") @outputter.print_action_step( - "Migrating a Bolt project might make irreversible changes to the project's "\ - "configuration and inventory files. Before continuing, make sure the "\ + "Migrating a Bolt project might make irreversible changes to the project's " \ + "configuration and inventory files. Before continuing, make sure the " \ "project has a backup or uses a version control system." ) diff --git a/lib/bolt/project_manager/config_migrator.rb b/lib/bolt/project_manager/config_migrator.rb index 35fb343e1..5250dcdef 100644 --- a/lib/bolt/project_manager/config_migrator.rb +++ b/lib/bolt/project_manager/config_migrator.rb @@ -41,7 +41,7 @@ def migrate(config_file, project_file, inventory_file, backup_dir) begin @outputter.print_action_step( - "Moving transportation configuration options '#{transport_data.keys.join(', ')}' "\ + "Moving transportation configuration options '#{transport_data.keys.join(', ')}' " \ "from bolt.yaml to inventory.yaml" ) @@ -57,8 +57,8 @@ def migrate(config_file, project_file, inventory_file, backup_dir) command = Bolt::Util.powershell? ? 'Get-Help about_bolt_project' : 'bolt guide project' @outputter.print_action_step( - "Successfully migrated config. Please add a 'name' key to bolt-project.yaml "\ - "to use project-level tasks and plans. Learn more about projects by running "\ + "Successfully migrated config. Please add a 'name' key to bolt-project.yaml " \ + "to use project-level tasks and plans. Learn more about projects by running " \ "'#{command}'." ) diff --git a/lib/bolt/project_manager/inventory_migrator.rb b/lib/bolt/project_manager/inventory_migrator.rb index cce49fdfc..dc0bec253 100644 --- a/lib/bolt/project_manager/inventory_migrator.rb +++ b/lib/bolt/project_manager/inventory_migrator.rb @@ -34,7 +34,7 @@ def migrate(inventory_file, backup_dir) true rescue StandardError => e raise Bolt::FileError.new( - "Unable to write to #{inventory_file}: #{e.message}. See "\ + "Unable to write to #{inventory_file}: #{e.message}. See " \ "http://pup.pt/bolt-inventory to manually update.", inventory_file ) diff --git a/lib/bolt/project_manager/module_migrator.rb b/lib/bolt/project_manager/module_migrator.rb index e3cb639c4..2253c18aa 100644 --- a/lib/bolt/project_manager/module_migrator.rb +++ b/lib/bolt/project_manager/module_migrator.rb @@ -21,8 +21,8 @@ def migrate(project, configured_modulepath) # Notify user to manually migrate modules if using non-default modulepath if configured_modulepath != new_modulepath && configured_modulepath != old_modulepath @outputter.print_action_step( - "Project has a non-default configured modulepath, unable to automatically "\ - "migrate project modules. To migrate project modules manually, see "\ + "Project has a non-default configured modulepath, unable to automatically " \ + "migrate project modules. To migrate project modules manually, see " \ "http://pup.pt/bolt-modules" ) true @@ -106,7 +106,7 @@ def migrate(project, configured_modulepath) Bolt::ModuleInstaller::Installer.new.install(puppetfile_path, managed_moduledir) else @outputter.print_action_step( - "Project does not include any managed modules, deleting Puppetfile "\ + "Project does not include any managed modules, deleting Puppetfile " \ "at #{puppetfile_path}" ) FileUtils.rm(puppetfile_path) @@ -118,9 +118,9 @@ def migrate(project, configured_modulepath) # private def select_modules(modules) @outputter.print_action_step( - "Select modules that are direct dependencies of your project. Bolt will "\ - "automatically manage dependencies for each module selected, so do not "\ - "select a module's dependencies unless you use content from it directly "\ + "Select modules that are direct dependencies of your project. Bolt will " \ + "automatically manage dependencies for each module selected, so do not " \ + "select a module's dependencies unless you use content from it directly " \ "in your project." ) @@ -161,6 +161,7 @@ def migrate(project, configured_modulepath) source.each_child do |mod| next unless mod.directory? next if (moduledir + mod.basename).directory? + FileUtils.mv(mod, moduledir) end diff --git a/lib/bolt/puppetdb/config.rb b/lib/bolt/puppetdb/config.rb index 914ac196d..f62795438 100644 --- a/lib/bolt/puppetdb/config.rb +++ b/lib/bolt/puppetdb/config.rb @@ -61,6 +61,7 @@ def self.default_config def token return @token if @token_computed + # Allow nil in config to skip loading a token if @settings.include?('token') if @settings['token'] @@ -81,6 +82,7 @@ def token def expand_paths(project_path) %w[cacert cert key token].each do |file| next unless @settings[file] + @settings[file] = File.expand_path(@settings[file], project_path) end end @@ -89,6 +91,7 @@ def validate_file_exists(file) if @settings[file] && !File.exist?(@settings[file]) raise Bolt::PuppetDBError, "#{file} file #{@settings[file]} does not exist" end + true end @@ -107,6 +110,7 @@ def server_urls def uri return @uri if @uri + require 'addressable/uri' uri = case @settings['server_urls'] diff --git a/lib/bolt/puppetdb/instance.rb b/lib/bolt/puppetdb/instance.rb index 15e927c8c..26992ae90 100644 --- a/lib/bolt/puppetdb/instance.rb +++ b/lib/bolt/puppetdb/instance.rb @@ -105,6 +105,7 @@ def send_command(command, version, payload) def http_client return @http if @http + # lazy-load expensive gem code require 'httpclient' @logger.trace("Creating HTTP Client") diff --git a/lib/bolt/rerun.rb b/lib/bolt/rerun.rb index a103e8fe6..d94c31cfb 100644 --- a/lib/bolt/rerun.rb +++ b/lib/bolt/rerun.rb @@ -16,6 +16,7 @@ def data unless @data.is_a?(Array) && @data.all? { |r| r['target'] && r['status'] } raise Bolt::FileError.new("Missing data in rerun file: #{@path}", @path) end + @data end diff --git a/lib/bolt/resource_instance.rb b/lib/bolt/resource_instance.rb index 3e9f5a685..cf4a3cd9e 100644 --- a/lib/bolt/resource_instance.rb +++ b/lib/bolt/resource_instance.rb @@ -14,7 +14,7 @@ def self._pcore_type # Needed by Puppet to serialize with _pcore_init_hash instead of the object's attributes def self._pcore_init_from_hash(_init_hash) - raise "ResourceInstance shouldn't be instantiated from a pcore_init class method. "\ + raise "ResourceInstance shouldn't be instantiated from a pcore_init class method. " \ "How did this get called?" end diff --git a/lib/bolt/result.rb b/lib/bolt/result.rb index a2964a0e1..dacac8198 100644 --- a/lib/bolt/result.rb +++ b/lib/bolt/result.rb @@ -81,7 +81,7 @@ def self.for_task(target, stdout, stderr, exit_code, task, position) unless value['_error'].is_a?(Hash) && value['_error'].key?('msg') details['original_error'] = value['_error'] value['_error'] = { - 'msg' => "Invalid error returned from task #{task}: #{value['_error'].inspect}. Error "\ + 'msg' => "Invalid error returned from task #{task}: #{value['_error'].inspect}. Error " \ "must be an object with a msg key.", 'kind' => 'bolt/invalid-task-error', 'details' => details @@ -148,6 +148,7 @@ def initialize(target, error: nil, message: nil, value: nil, action: 'action', o if error && !error.is_a?(Hash) raise "TODO: how did we get a string error" end + @value['_error'] = error if error @value['_output'] = message if message end diff --git a/lib/bolt/shell.rb b/lib/bolt/shell.rb index aa19dd450..6acf5ad03 100644 --- a/lib/bolt/shell.rb +++ b/lib/bolt/shell.rb @@ -11,7 +11,7 @@ def initialize(target, conn) if Bolt::Logger.stream Bolt::Logger.warn_once("stream_experimental", - "The 'stream' option is experimental, and might "\ + "The 'stream' option is experimental, and might " \ "include breaking changes between minor versions.") @stream_logger = Bolt::Logger.logger(:stream) # Don't send stream messages to the parent logger diff --git a/lib/bolt/shell/bash.rb b/lib/bolt/shell/bash.rb index 5c533b0b9..bbb7b1308 100644 --- a/lib/bolt/shell/bash.rb +++ b/lib/bolt/shell/bash.rb @@ -301,6 +301,7 @@ def make_tmpdir if result.exit_code != 0 raise Bolt::Node::FileError.new("Could not make tmpdir: #{result.stderr.string}", 'TMPDIR_ERROR') end + path = tmppath || result.stdout.string.chomp Bolt::Shell::Bash::Tmpdir.new(self, path) end @@ -482,7 +483,7 @@ def execute(command, sudoable: false, **options) when 0 @logger.trace { "Command `#{command_str}` returned successfully" } when 126 - msg = "\n\nThis might be caused by the default tmpdir being mounted "\ + msg = "\n\nThis might be caused by the default tmpdir being mounted " \ "using 'noexec'. See http://pup.pt/task-failure for details and workarounds." result_output.stderr << msg result_output.merged_output << msg diff --git a/lib/bolt/shell/powershell.rb b/lib/bolt/shell/powershell.rb index 2dfbba8c9..c77607d4a 100644 --- a/lib/bolt/shell/powershell.rb +++ b/lib/bolt/shell/powershell.rb @@ -22,8 +22,8 @@ def validate_ps_version if !version.empty? && version.to_i < 3 # This lets us know how many targets have Powershell 2, and lets the # user know how many targets they have with PS2 - msg = "Detected PowerShell 2 on one or more targets.\nPowerShell 2 "\ - "is unsupported. See bolt-debug.log or run with '--log-level debug' to see the full "\ + msg = "Detected PowerShell 2 on one or more targets.\nPowerShell 2 " \ + "is unsupported. See bolt-debug.log or run with '--log-level debug' to see the full " \ "list of targets with PowerShell 2." Bolt::Logger.deprecate_once("powershell_2", msg) @@ -45,7 +45,7 @@ def powershell_file?(path) def validate_extensions(ext) unless @extensions.include?(ext) - raise Bolt::Node::FileError.new("File extension #{ext} is not enabled, "\ + raise Bolt::Node::FileError.new("File extension #{ext} is not enabled, " \ "to run it please add to 'winrm: extensions'", 'FILETYPE_ERROR') end end @@ -143,6 +143,7 @@ def make_tmpdir if result.exit_code != 0 raise Bolt::Node::FileError.new("Could not make tmpdir: #{result.stderr.string}", 'TMPDIR_ERROR') end + result.stdout.string.chomp end diff --git a/lib/bolt/task.rb b/lib/bolt/task.rb index 1dd20a4d3..6c7bad981 100644 --- a/lib/bolt/task.rb +++ b/lib/bolt/task.rb @@ -99,12 +99,14 @@ def select_implementation(target, provided_features = []) Set.new(imp['requirements']).subset?(available_features) && !!remote_impl == @remote end raise NoImplementationError.new(target, self) unless impl + impl = impl.dup impl['path'] = file_path(impl['name']) impl.delete('requirements') impl else raise NoImplementationError.new(target, self) unless !!metadata['remote'] == @remote + name = files.first['name'] { 'name' => name, 'path' => file_path(name) } end @@ -117,6 +119,7 @@ def select_implementation(target, provided_features = []) impl['files'] = filenames.map do |file| path = file_path(file) raise "No file found for reference #{file}" if path.nil? + { 'name' => file, 'path' => path } end diff --git a/lib/bolt/task/run.rb b/lib/bolt/task/run.rb index 2ce514978..92783c151 100644 --- a/lib/bolt/task/run.rb +++ b/lib/bolt/task/run.rb @@ -47,6 +47,7 @@ def run_task(task, targets, params, options, executor) if !result.ok && !options[:catch_errors] raise Bolt::RunFailure.new(result, 'run_task', task.name) end + result end end diff --git a/lib/bolt/transport/docker/connection.rb b/lib/bolt/transport/docker/connection.rb index 03f4dc94d..152277d55 100644 --- a/lib/bolt/transport/docker/connection.rb +++ b/lib/bolt/transport/docker/connection.rb @@ -11,6 +11,7 @@ class Connection def initialize(target) raise Bolt::ValidationError, "Target #{target.safe_name} does not have a host" unless target.host + @target = target @user = ENV['USER'] || Etc.getlogin @logger = Bolt::Logger.logger(target.safe_name) @@ -53,6 +54,7 @@ def connect output = execute_local_json_command('ps', ['--no-trunc']) index = output.find_index { |item| item["ID"].start_with?(target.host) || item["Names"] == target.host } raise "Could not find a container with name or ID matching '#{target.host}'" if index.nil? + # Now find the indepth container information output = execute_local_json_command('inspect', [output[index]["ID"]]) # Store the container information for later diff --git a/lib/bolt/transport/jail/connection.rb b/lib/bolt/transport/jail/connection.rb index 4d857dd6b..73b3f909b 100644 --- a/lib/bolt/transport/jail/connection.rb +++ b/lib/bolt/transport/jail/connection.rb @@ -11,6 +11,7 @@ class Connection def initialize(target) raise Bolt::ValidationError, "Target #{target.safe_name} does not have a host" unless target.host + @target = target @user = @target.user || ENV['USER'] || Etc.getlogin @logger = Bolt::Logger.logger(target.safe_name) @@ -38,6 +39,7 @@ def connect output = JSON.parse(`jls --libxo=json`) @jail_info = output['jail-information']['jail'].select { |jail| jail['hostname'] == target.host }.first raise "Could not find a jail with name matching #{target.host}" if @jail_info.nil? + @logger.trace { "Opened session" } true rescue StandardError => e diff --git a/lib/bolt/transport/lxd.rb b/lib/bolt/transport/lxd.rb index a04d9b670..dc92cb525 100644 --- a/lib/bolt/transport/lxd.rb +++ b/lib/bolt/transport/lxd.rb @@ -13,7 +13,7 @@ def provided_features def with_connection(target, options = {}) Bolt::Logger.warn_once("lxd_experimental", - "The LXD transport is experimental, and might "\ + "The LXD transport is experimental, and might " \ "include breaking changes between minor versions.") conn = Connection.new(target, options) conn.connect diff --git a/lib/bolt/transport/lxd/connection.rb b/lib/bolt/transport/lxd/connection.rb index 1fb2ff468..358ec67ee 100644 --- a/lib/bolt/transport/lxd/connection.rb +++ b/lib/bolt/transport/lxd/connection.rb @@ -36,10 +36,12 @@ def connect unless status.exitstatus.zero? raise "Error listing available containers: #{err}" end + containers = JSON.parse(out) if containers.empty? raise "Could not find a container with name or ID matching '#{container_id}'" end + @logger.trace("Opened session") true rescue StandardError => e diff --git a/lib/bolt/transport/podman/connection.rb b/lib/bolt/transport/podman/connection.rb index c797ec855..7a426631b 100644 --- a/lib/bolt/transport/podman/connection.rb +++ b/lib/bolt/transport/podman/connection.rb @@ -11,6 +11,7 @@ class Connection < Connection def initialize(target) raise Bolt::ValidationError, "Target #{target.safe_name} does not have a host" unless target.host + @target = target @user = ENV['USER'] || Etc.getlogin @logger = Bolt::Logger.logger(target.safe_name) @@ -44,6 +45,7 @@ def connect Array(item["Names"]).include?(@target.host) } raise "Could not find a container with name or ID matching '#{@target.host}'" if container.nil? + # Now find the indepth container information id = container["ID"] || container["Id"] output = execute_local_json_command('inspect', [id]) diff --git a/lib/bolt/transport/remote.rb b/lib/bolt/transport/remote.rb index 0e90795da..a8635e5fc 100644 --- a/lib/bolt/transport/remote.rb +++ b/lib/bolt/transport/remote.rb @@ -16,6 +16,7 @@ def initialize(executor) def get_proxy(target) inventory = target.inventory raise "Target was created without inventory? Not get_targets?" unless inventory + proxy = inventory.get_targets(target.options['run-on'] || 'localhost').first if proxy.transport == 'remote' diff --git a/lib/bolt/transport/ssh/connection.rb b/lib/bolt/transport/ssh/connection.rb index 7757f375c..e8856e425 100644 --- a/lib/bolt/transport/ssh/connection.rb +++ b/lib/bolt/transport/ssh/connection.rb @@ -227,7 +227,7 @@ def execute(command_str) end [in_wr, out_rd, err_rd, th] rescue Errno::EMFILE => e - msg = "#{e.message}. This might be resolved by increasing your user limit "\ + msg = "#{e.message}. This might be resolved by increasing your user limit " \ "with 'ulimit -n 1024'. See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details." raise Bolt::Error.new(msg, 'bolt/too-many-files') end diff --git a/lib/bolt/transport/winrm/connection.rb b/lib/bolt/transport/winrm/connection.rb index 2f34ffa03..a2e3c377f 100644 --- a/lib/bolt/transport/winrm/connection.rb +++ b/lib/bolt/transport/winrm/connection.rb @@ -11,6 +11,7 @@ class Connection def initialize(target, transport_logger) raise Bolt::ValidationError, "Target #{target.safe_name} does not have a host" unless target.host + @target = target default_port = target.options['ssl'] ? HTTPS_PORT : HTTP_PORT @@ -81,8 +82,8 @@ def connect theres_your_problem = "\nAre you using SSL to connect to a non-SSL port?" end if target.options['ssl-verify'] && e.message.include?('certificate verify failed') - theres_your_problem = "\nIs the remote host using a self-signed SSL "\ - "certificate? Use --no-ssl-verify to disable "\ + theres_your_problem = "\nIs the remote host using a self-signed SSL " \ + "certificate? Use --no-ssl-verify to disable " \ "remote host SSL verification." end raise Bolt::Node::ConnectError.new( @@ -137,7 +138,7 @@ def execute(command) [inp, out_rd, err_rd, th] rescue Errno::EMFILE => e - msg = "#{e.message}. This might be resolved by increasing your user limit "\ + msg = "#{e.message}. This might be resolved by increasing your user limit " \ "with 'ulimit -n 1024'. See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details." raise Bolt::Error.new(msg, 'bolt/too-many-files') rescue StandardError diff --git a/lib/bolt/util.rb b/lib/bolt/util.rb index 56a4615fa..3c64a2323 100644 --- a/lib/bolt/util.rb +++ b/lib/bolt/util.rb @@ -52,7 +52,7 @@ def read_yaml_hash(path, file_name) content = File.open(path, "r:UTF-8") { |f| YAML.safe_load(f.read) } || {} unless content.is_a?(Hash) raise Bolt::FileError.new( - "Invalid content for #{file_name} file at #{path}\nContent should be a Hash or empty, "\ + "Invalid content for #{file_name} file at #{path}\nContent should be a Hash or empty, " \ "not #{content.class}", path ) @@ -62,11 +62,11 @@ def read_yaml_hash(path, file_name) rescue Errno::ENOENT raise Bolt::FileError.new("Could not read #{file_name} file at #{path}", path) rescue Psych::SyntaxError => e - raise Bolt::FileError.new("Could not parse #{file_name} file at #{path}, line #{e.line}, "\ + raise Bolt::FileError.new("Could not parse #{file_name} file at #{path}, line #{e.line}, " \ "column #{e.column}\n#{e.problem}", path) rescue Psych::BadAlias => e - raise Bolt::FileError.new('Bolt does not support the use of aliases in YAML files. Alias '\ + raise Bolt::FileError.new('Bolt does not support the use of aliases in YAML files. Alias ' \ "detected in #{file_name} file at #{path}\n#{e.message}", path) rescue Psych::Exception => e raise Bolt::FileError.new("Could not parse #{file_name} file at #{path}\n#{e.message}", @@ -147,7 +147,7 @@ def module_name(path) # Only accept paths with '/plans/' or '/tasks/' unless path.match?(regex) - msg = "Could not determine module from #{path}. "\ + msg = "Could not determine module from #{path}. " \ "The path must include 'plans' or 'tasks' directory" raise Bolt::Error.new(msg, 'bolt/modulepath-error') end @@ -361,6 +361,7 @@ def validate_file(type, path, allow_dir = false) elsif stat.directory? Dir.foreach(path) do |file| next if %w[. ..].include?(file) + validate_file(type, File.join(path, file), allow_dir) end end @@ -431,11 +432,13 @@ def format_env_vars_for_cli(env_vars) def unix_basename(path) raise Bolt::ValidationError, "path must be a String, received #{path.class} #{path}" unless path.is_a?(String) + path.split('/').last end def windows_basename(path) raise Bolt::ValidationError, "path must be a String, received #{path.class} #{path}" unless path.is_a?(String) + path.split(%r{[/\\]}).last end diff --git a/lib/bolt/util/format.rb b/lib/bolt/util/format.rb index 691764b4e..fcc00ddc8 100644 --- a/lib/bolt/util/format.rb +++ b/lib/bolt/util/format.rb @@ -56,6 +56,7 @@ def stringify(message) logs = result.resource_logs&.map do |log| # Omit low-level info/debug messages next if %w[info debug].include?(log['level']) + indent(2, format_log(log)) end hash = result.to_data diff --git a/lib/bolt/validator.rb b/lib/bolt/validator.rb index 10a05b30d..7ab6aa076 100644 --- a/lib/bolt/validator.rb +++ b/lib/bolt/validator.rb @@ -172,7 +172,7 @@ def validate(data, schema, location = nil) private def plugin_reference?(value, plugin_supported) if value.is_a?(Hash) && value.key?('_plugin') unless plugin_supported - @errors << "Value at '#{path}' is a plugin reference, which is unsupported at "\ + @errors << "Value at '#{path}' is a plugin reference, which is unsupported at " \ "this location" end diff --git a/lib/bolt_spec/plans/action_stubs.rb b/lib/bolt_spec/plans/action_stubs.rb index 3010b2809..f75f394b4 100644 --- a/lib/bolt_spec/plans/action_stubs.rb +++ b/lib/bolt_spec/plans/action_stubs.rb @@ -103,6 +103,7 @@ def check_resultset(result_set, object) unless result_set.is_a?(Bolt::ResultSet) raise "Return block for #{object} did not return a Bolt::ResultSet" end + result_set end @@ -110,6 +111,7 @@ def check_plan_result(plan_result, plan_clj) unless plan_result.is_a?(Bolt::PlanResult) raise "Return block for #{plan_clj.closure_name} did not return a Bolt::PlanResult" end + plan_result end @@ -144,6 +146,7 @@ def not_be_called def return(&block) raise "Cannot set return values and return block." if @data_set + @return_block = block self end @@ -153,12 +156,14 @@ def return(&block) def return_for_targets(data) data.each_with_object(@data) do |(target, result), hsh| raise "Mocked results must be hashes: #{target}: #{result}" unless result.is_a? Hash + # set the inventory from the BoltSpec::Plans, otherwise if we try to convert # this target to a string, it will fail to string conversion because the # inventory is nil hsh[target] = result_for(Bolt::Target.new(target, @inventory), **Bolt::Util.walk_keys(result, &:to_sym)) end raise "Cannot set return values and return block." if @return_block + @data_set = true self end diff --git a/lib/bolt_spec/plans/mock_executor.rb b/lib/bolt_spec/plans/mock_executor.rb index 502723ca9..964ed1345 100644 --- a/lib/bolt_spec/plans/mock_executor.rb +++ b/lib/bolt_spec/plans/mock_executor.rb @@ -251,11 +251,13 @@ def with_node_logging(_description, targets) def queue_execute(targets) raise "Unexpected call to apply(#{targets})" unless @allow_apply + targets end def await_results(promises) raise "Unexpected call to apply(#{targets})" unless @allow_apply + Bolt::ResultSet.new(promises.map { |target| Bolt::ApplyResult.new(target) }) end # End Apply mocking diff --git a/libexec/apply_catalog.rb b/libexec/apply_catalog.rb index de12b8cc4..e46fbc58f 100755 --- a/libexec/apply_catalog.rb +++ b/libexec/apply_catalog.rb @@ -57,6 +57,7 @@ # explicitly packaged plugins should take precedence args['bolt_builtin_content'].each do |builtin_dir| next unless Dir.exist?(builtin_dir) + Dir.foreach(builtin_dir) do |dir| unless ['.', '..'].include? dir full_path = File.join(builtin_dir, dir, 'lib') @@ -74,7 +75,7 @@ begin require 'puppet/resource_api/transport' rescue LoadError - msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api "\ + msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api " \ "gem version 1.8.0 or greater is required on the proxy target" puts msg exit 1 diff --git a/libexec/custom_facts.rb b/libexec/custom_facts.rb index db65e93c3..3bdbd0ffc 100755 --- a/libexec/custom_facts.rb +++ b/libexec/custom_facts.rb @@ -39,7 +39,7 @@ begin require 'puppet/resource_api/transport' rescue LoadError - msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api "\ + msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api " \ "gem version 1.8.0 or greater is required on the proxy target" puts msg exit 1 diff --git a/libexec/query_resources.rb b/libexec/query_resources.rb index c044520fd..eadf6f462 100755 --- a/libexec/query_resources.rb +++ b/libexec/query_resources.rb @@ -46,7 +46,7 @@ def instance(type_name, resource_name) begin require 'puppet/resource_api/transport' rescue LoadError - msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api "\ + msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api " \ "gem version 1.8.0 or greater is required on the proxy target" puts msg exit 1 diff --git a/openbolt.gemspec b/openbolt.gemspec index ac762cc94..ca18f7990 100644 --- a/openbolt.gemspec +++ b/openbolt.gemspec @@ -70,5 +70,5 @@ Gem::Specification.new do |spec| spec.add_development_dependency "octokit", ">= 4.0", "< 9" spec.add_development_dependency "rake", ">= 12.0", "< 14" spec.add_development_dependency "rspec", ">= 3.0", "< 4" - spec.add_development_dependency 'voxpupuli-rubocop', '~> 4.1.0' + spec.add_development_dependency 'voxpupuli-rubocop', '~> 4.2.0' end diff --git a/rakelib/docs.rake b/rakelib/docs.rake index 355284000..cab404305 100644 --- a/rakelib/docs.rake +++ b/rakelib/docs.rake @@ -284,14 +284,14 @@ begin apply = { "name" => "apply", - "desc" => "Applies a block of manifest code to the targets.\n\nApplying manifest "\ - "code requires facts to compile a catalog. Targets must also have "\ - "the Puppet agent package installed to apply manifest code. To prep "\ - "targets for an apply, call the [apply_prep](#apply-prep) function before "\ - "the apply function.\n\nTo learn more about applying manifest code from a plan, "\ - "see [Applying manifest blocks from a Puppet "\ - "plan](applying_manifest_blocks.md#applying-manifest-blocks-from-a-puppet-plan).\n\n"\ - "> **Note:** The `apply` function returns a `ResultSet` object containing `ApplyResult`\n"\ + "desc" => "Applies a block of manifest code to the targets.\n\nApplying manifest " \ + "code requires facts to compile a catalog. Targets must also have " \ + "the Puppet agent package installed to apply manifest code. To prep " \ + "targets for an apply, call the [apply_prep](#apply-prep) function before " \ + "the apply function.\n\nTo learn more about applying manifest code from a plan, " \ + "see [Applying manifest blocks from a Puppet " \ + "plan](applying_manifest_blocks.md#applying-manifest-blocks-from-a-puppet-plan).\n\n" \ + "> **Note:** The `apply` function returns a `ResultSet` object containing `ApplyResult`\n" \ "> objects.", "examples" => [ { @@ -300,8 +300,8 @@ begin }, { "desc" => "Apply manifest code as another user, catching any errors.", - "exmp" => "$apply_results = apply($targets, '_catch_errors' => true, '_run_as' => 'bolt') {\n"\ - " file { '/etc/puppetlabs':\n ensure => present\n }\n}" + "exmp" => "$apply_results = apply($targets, '_catch_errors' => true, '_run_as' => 'bolt') {\n " \ + "file { '/etc/puppetlabs':\n ensure => present\n }\n}" } ], "signatures" => [ @@ -310,27 +310,27 @@ begin "return" => "ResultSet", "options" => { "_catch_errors" => { - "desc" => "When `true`, returns a `ResultSet` including failed results, rather "\ + "desc" => "When `true`, returns a `ResultSet` including failed results, rather " \ "than failing the plan.", "type" => "Boolean" }, "_description" => { - "desc" => "Adds a description to the apply block, allowing you to distinguish "\ + "desc" => "Adds a description to the apply block, allowing you to distinguish " \ "apply blocks.", "type" => "String" }, "_noop" => { - "desc" => "When `true`, applies the manifest block in Puppet no-operation mode, "\ + "desc" => "When `true`, applies the manifest block in Puppet no-operation mode, " \ "returning a report of the changes it would make while taking no action.", "type" => "Boolean" }, "_puppetdb" => { - "desc" => "The named PuppetDB instance to connect to when making PuppetDB queries "\ + "desc" => "The named PuppetDB instance to connect to when making PuppetDB queries " \ "during catalog compilation.", "type" => "String" }, "_run_as" => { - "desc" => "The user to apply the manifest block as. Only available for transports "\ + "desc" => "The user to apply the manifest block as. Only available for transports " \ "that support the `run-as` option.", "type" => "String" } diff --git a/rakelib/pwsh.rake b/rakelib/pwsh.rake index 9a44f8aa0..4fa1ebf61 100644 --- a/rakelib/pwsh.rake +++ b/rakelib/pwsh.rake @@ -14,6 +14,7 @@ namespace :pwsh do files = Dir.children(source).sort.map { |f| File.join(source, f) } files.each_with_object({}) do |file, _guides| next if file !~ /\.(yaml|yml)\z/ + info = Bolt::Util.read_yaml_hash(file, 'guide') # Make sure both topic and guide keys are defined diff --git a/rakelib/schemas.rake b/rakelib/schemas.rake index e1467315e..f058b498a 100644 --- a/rakelib/schemas.rake +++ b/rakelib/schemas.rake @@ -190,11 +190,13 @@ def to_schema(data, plugin = false) # Recurse through some properties, as each can have their own defintions. %i[items additionalProperties].each do |key| next unless data.key?(key) + data[key] = to_schema(data[key], plugin) end %i[properties definitions].each do |key| next unless data.key?(key) + data[key] = data[key].transform_values { |opt| to_schema(opt, plugin) } end diff --git a/scripts/generate_changelog.rb b/scripts/generate_changelog.rb index f6ad34c17..fd9135f68 100755 --- a/scripts/generate_changelog.rb +++ b/scripts/generate_changelog.rb @@ -27,7 +27,7 @@ def labels def client unless @client unless ENV['GITHUB_TOKEN'] - warn "Missing GitHub personal access token. Set $GITHUB_TOKEN with a "\ + warn "Missing GitHub personal access token. Set $GITHUB_TOKEN with a " \ "personal access token to use this script." exit 1 end @@ -107,6 +107,7 @@ def update_changelog entries.each_value do |type| next unless type[:entries].any? + new_lines << "### #{type[:name]}\n" type[:entries].each do |entry| diff --git a/scripts/update_modules.rb b/scripts/update_modules.rb index cf04d0651..1c3f1df83 100755 --- a/scripts/update_modules.rb +++ b/scripts/update_modules.rb @@ -36,6 +36,7 @@ def mod(name, args) response = http.get("/v3/modules/#{name}") next unless response.is_a?(Net::HTTPOK) + latest_version = JSON.parse(response.body).dig('current_release', 'version') if version != latest_version diff --git a/spec/integration/apply_compile_spec.rb b/spec/integration/apply_compile_spec.rb index 01a783e8a..b3c485932 100644 --- a/spec/integration/apply_compile_spec.rb +++ b/spec/integration/apply_compile_spec.rb @@ -64,7 +64,7 @@ def get_notifies(result) notify = get_notifies(result) expect(notify.count).to eq(1) expect(notify[0]['title']).to eq( - "trusted {authenticated => local, certname => #{uri}, extensions => {}, "\ + "trusted {authenticated => local, certname => #{uri}, extensions => {}, " \ "hostname => #{uri}, domain => , external => {}}" ) end @@ -76,7 +76,7 @@ def get_notifies(result) notify = get_notifies(result) expect(notify.count).to eq(1) expect(notify[0]['title']).to eq( - "trusted {authenticated => local, certname => #{uri}, extensions => {}, "\ + "trusted {authenticated => local, certname => #{uri}, extensions => {}, " \ "hostname => #{uri}, domain => , external => {hot => cocoa, pepper => mint}}" ) end @@ -471,6 +471,7 @@ def get_notifies(result) context 'with fact/variable collisions' do let(:lines) { @log_output.readlines } + after(:each) { @log_output.level = :all } it 'warns about collisions' do diff --git a/spec/integration/apply_error_spec.rb b/spec/integration/apply_error_spec.rb index 1ee4e0ae5..b9806487b 100644 --- a/spec/integration/apply_error_spec.rb +++ b/spec/integration/apply_error_spec.rb @@ -39,6 +39,7 @@ context 'when it cannot connect to the target' do let(:password) { 'incorrect_password' } + it 'displays a connection error' do result = run_cli_json(%w[plan run basic::class] + config_flags) error = result['details']['result_set'][0]['value']['_error'] diff --git a/spec/integration/apply_spec.rb b/spec/integration/apply_spec.rb index cb039e599..aad2c2e93 100644 --- a/spec/integration/apply_spec.rb +++ b/spec/integration/apply_spec.rb @@ -226,8 +226,10 @@ local_pid = resources['Notify[local pid]']['events'][0]['desired_value'][/(\d+)/, 1] raise 'local pid was not found' if local_pid.nil? + remote_pid = resources['Notify[remote pid]']['events'][0]['desired_value'][/(\d+)/, 1] raise 'remote pid was not found' if remote_pid.nil? + expect(local_pid).not_to eq(remote_pid) end end diff --git a/spec/integration/catch_errors_spec.rb b/spec/integration/catch_errors_spec.rb index 9af5602ff..280fa5562 100644 --- a/spec/integration/catch_errors_spec.rb +++ b/spec/integration/catch_errors_spec.rb @@ -83,6 +83,7 @@ context "when breaking" do let(:plan) { "catch_errors::break" } + it "breaks from enumeration" do params = { list: %w[firstcomment b c] } result = run_cli_json(%W[plan run #{plan} --params #{params.to_json}] + diff --git a/spec/integration/inventory_spec.rb b/spec/integration/inventory_spec.rb index d6dd8beda..3224a40f8 100644 --- a/spec/integration/inventory_spec.rb +++ b/spec/integration/inventory_spec.rb @@ -92,6 +92,7 @@ context 'with a uriless target' do let(:target) { 'uriless' } + it 'connects to run a command' do result = run_one_node(run_command) expect(result).to be @@ -117,6 +118,7 @@ context 'when running a plan' do let(:run_plan) { ['plan', 'run', 'inventory::get_host'] + config_flags } + it 'can access the host' do r = run_cli_json(run_plan + ['--targets', 'hostless']) expect(r).to eq('result' => nil) diff --git a/spec/integration/local_spec.rb b/spec/integration/local_spec.rb index 1af096db5..b2eb35577 100644 --- a/spec/integration/local_spec.rb +++ b/spec/integration/local_spec.rb @@ -115,6 +115,7 @@ context 'with environment variables set' do before(:each) { ENV['test_var'] = "testing this" } after(:each) { ENV.delete('test_var') } + # Only works with localhost's default configuration let(:uri) { 'localhost' } diff --git a/spec/integration/plugin/task_spec.rb b/spec/integration/plugin/task_spec.rb index 94543adce..4e9bfbe9f 100644 --- a/spec/integration/plugin/task_spec.rb +++ b/spec/integration/plugin/task_spec.rb @@ -136,6 +136,7 @@ let(:inventory) { { 'targets' => [plugin] } } + it 'supports a target lookup' do output = run_cli(command) @@ -175,6 +176,7 @@ 'parameters' => params } } + it 'errors when the task fails' do result = run_cli_json(command) expect(result['msg']).to match(/The task failed/) diff --git a/spec/integration/puppetdb/puppetdb_spec.rb b/spec/integration/puppetdb/puppetdb_spec.rb index 424cb9589..3018f9806 100644 --- a/spec/integration/puppetdb/puppetdb_spec.rb +++ b/spec/integration/puppetdb/puppetdb_spec.rb @@ -38,6 +38,7 @@ 5.times do retrieved = client.facts_for_node([target]) break unless retrieved.empty? + sleep 5 end expect(retrieved).to eq(target => facts) diff --git a/spec/integration/shareable_task_spec.rb b/spec/integration/shareable_task_spec.rb index 746a84470..cc046996d 100644 --- a/spec/integration/shareable_task_spec.rb +++ b/spec/integration/shareable_task_spec.rb @@ -35,7 +35,7 @@ end it 'fails with an invalid path' do - msg = Regexp.new('Files must be saved in module directories that Puppet makes '\ + msg = Regexp.new('Files must be saved in module directories that Puppet makes ' \ 'available via mount points: files, lib, scripts, tasks') expect { run_cli_json(%w[task run shareable::invalid_path] + config_flags) diff --git a/spec/integration/transpiler_spec.rb b/spec/integration/transpiler_spec.rb index d1f6838af..59f49ca57 100644 --- a/spec/integration/transpiler_spec.rb +++ b/spec/integration/transpiler_spec.rb @@ -10,6 +10,7 @@ include BoltSpec::Integration after(:each) { Puppet.settings.send(:clear_everything_for_tests) } + let(:modulepath) { fixtures_path('modules') } let(:yaml_path) { File.join(modulepath, 'yaml', 'plans') } let(:plan_path) { File.join(yaml_path, 'conversion.yaml') } diff --git a/spec/integration/transport/winrm_spec.rb b/spec/integration/transport/winrm_spec.rb index 336a4f15f..daea8c3c5 100644 --- a/spec/integration/transport/winrm_spec.rb +++ b/spec/integration/transport/winrm_spec.rb @@ -421,7 +421,7 @@ def stub_winrm_to_raise(klass, message) [String] $Name ) - + Write-Output "Hello $Name" PS @@ -842,7 +842,7 @@ def stub_winrm_to_raise(klass, message) end end - context "fails for PowerShell terminating errors: " do + context "fails for PowerShell terminating errors:" do it "exception thrown", winrm: true do contents = <<-PS throw "My Error" diff --git a/spec/lib/bolt_spec/bolt_server.rb b/spec/lib/bolt_spec/bolt_server.rb index ec51635bd..a8db71409 100644 --- a/spec/lib/bolt_spec/bolt_server.rb +++ b/spec/lib/bolt_spec/bolt_server.rb @@ -101,6 +101,7 @@ def get_task_data(task) unless resp.code == '200' raise "request #{path} #{params} failed with: #{resp.body}" end + JSON.parse(resp.body) end diff --git a/spec/lib/bolt_spec/options.rb b/spec/lib/bolt_spec/options.rb index adaf4a617..7755bf06a 100644 --- a/spec/lib/bolt_spec/options.rb +++ b/spec/lib/bolt_spec/options.rb @@ -30,6 +30,7 @@ def assert_type_description(definitions) end next unless definition.key?(:items) + msg = ":items key for option '#{option}' must be a Hash" expect(definition[:items].class).to eq(Hash), msg diff --git a/spec/lib/bolt_spec/task.rb b/spec/lib/bolt_spec/task.rb index 2dd2ac9f7..fc10e92c7 100644 --- a/spec/lib/bolt_spec/task.rb +++ b/spec/lib/bolt_spec/task.rb @@ -33,6 +33,7 @@ def task_type(name, executable = nil, input_method = nil) end include BoltSpec::Files + def with_task_containing(name, contents, input_method, extension = nil) with_tempfile_containing(name, contents, extension) do |file| yield mock_task(name, file.path, input_method) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 285886899..9584a9f65 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -35,6 +35,7 @@ RSpec.configure do |config| Bolt::Logger.initialize_logging include RSpec::LoggingHelper + config.capture_log_messages # rspec-expectations config diff --git a/spec/unit/apply_result_spec.rb b/spec/unit/apply_result_spec.rb index 5ce2c5715..f30f4a52b 100644 --- a/spec/unit/apply_result_spec.rb +++ b/spec/unit/apply_result_spec.rb @@ -64,6 +64,7 @@ describe :from_task_result do context 'with an unparseable result' do let(:result_value) { 'oops' } + it 'generates an error when keys are missing' do expect(apply_result.ok).to eq(false) expect(apply_result['_error']['kind']).to eq('bolt/invalid-report') @@ -72,6 +73,7 @@ context 'with missing keys' do let(:result_value) { {} } + it 'generates an error when keys are missing' do expect(apply_result.ok).to eq(false) expect(apply_result['_error']['kind']).to eq('bolt/invalid-report') diff --git a/spec/unit/catalog_spec.rb b/spec/unit/catalog_spec.rb index 06ab1b9af..1fe836d13 100644 --- a/spec/unit/catalog_spec.rb +++ b/spec/unit/catalog_spec.rb @@ -11,6 +11,7 @@ describe Bolt::Catalog do include BoltSpec::Files + let(:uri) { 'catalog' } let(:target) { inventory.get_target(uri) } let(:inventory) { Bolt::Inventory.empty } diff --git a/spec/unit/fiber_executor_spec.rb b/spec/unit/fiber_executor_spec.rb index 32958786e..29594f1cd 100644 --- a/spec/unit/fiber_executor_spec.rb +++ b/spec/unit/fiber_executor_spec.rb @@ -146,6 +146,7 @@ end allow(Fiber).to receive(:yield) end + let(:timeout) { 0.1 } it "raises an error if any Futures exceed the timeout without catch_errors" do diff --git a/spec/unit/inventory/group_spec.rb b/spec/unit/inventory/group_spec.rb index d3cfde5a0..b1dc647d5 100644 --- a/spec/unit/inventory/group_spec.rb +++ b/spec/unit/inventory/group_spec.rb @@ -724,6 +724,7 @@ context 'with unexpected keys' do let(:mock_logger) { instance_double("Logging.logger") } + before(:each) do allow(Bolt::Logger).to receive(:logger).and_return(mock_logger) end diff --git a/spec/unit/outputter/human_spec.rb b/spec/unit/outputter/human_spec.rb index 1247ab3d9..7238c2598 100644 --- a/spec/unit/outputter/human_spec.rb +++ b/spec/unit/outputter/human_spec.rb @@ -638,7 +638,7 @@ Tasks module::task_one module::task_two a description - + Plans module::plan_one a description module::plan_two diff --git a/spec/unit/pal/yaml_plan/step_spec.rb b/spec/unit/pal/yaml_plan/step_spec.rb index cf91c851d..c2a7faf92 100644 --- a/spec/unit/pal/yaml_plan/step_spec.rb +++ b/spec/unit/pal/yaml_plan/step_spec.rb @@ -92,8 +92,8 @@ def make_string(str) "parameters" => { "butter" => "crunchy peanut" } } end let(:output) { - " run_task('jam::raspberry', $bread, 'delicious',"\ - " {'butter' => 'crunchy peanut'})\n" + " run_task('jam::raspberry', $bread, 'delicious', " \ + "{'butter' => 'crunchy peanut'})\n" } include_examples 'metaparameters' diff --git a/spec/unit/pal/yaml_plan_spec.rb b/spec/unit/pal/yaml_plan_spec.rb index 0c3745dab..21ac8f497 100644 --- a/spec/unit/pal/yaml_plan_spec.rb +++ b/spec/unit/pal/yaml_plan_spec.rb @@ -249,6 +249,7 @@ describe Bolt::PAL::YamlPlan::EvaluableString do let(:evaluator) { Puppet::Pops::Parser::EvaluatingParser.new } + describe Bolt::PAL::YamlPlan::DoubleQuotedString do it "treats literal strings as literal strings" do str = described_class.new("hello world") diff --git a/spec/unit/pal_spec.rb b/spec/unit/pal_spec.rb index f7ffd0a01..6bd873dfa 100644 --- a/spec/unit/pal_spec.rb +++ b/spec/unit/pal_spec.rb @@ -10,6 +10,7 @@ Puppet.settings.send(:clear_everything_for_tests) Bolt::PAL.load_puppet end + after(:each) { Puppet.settings.send(:clear_everything_for_tests) } let(:project) { Bolt::Project.new({ 'name' => 'pal_test' }, Dir.getwd) } diff --git a/spec/unit/plugin/cache_spec.rb b/spec/unit/plugin/cache_spec.rb index 2cf65d636..f37668d24 100644 --- a/spec/unit/plugin/cache_spec.rb +++ b/spec/unit/plugin/cache_spec.rb @@ -26,6 +26,7 @@ 'var' => env_var, '_cache' => 120 } } + it "fails" do expect { plugin_cache.validate } .to raise_error(Bolt::ValidationError, /_cache must be a Hash/) @@ -38,6 +39,7 @@ 'var' => env_var, '_cache' => { 'tl' => 120 } } } + it "fails" do expect { plugin_cache.validate } .to raise_error(Bolt::ValidationError, /_cache must set 'ttl' key/) diff --git a/spec/unit/plugin/env_var_spec.rb b/spec/unit/plugin/env_var_spec.rb index 75db0158b..e1c2567e9 100644 --- a/spec/unit/plugin/env_var_spec.rb +++ b/spec/unit/plugin/env_var_spec.rb @@ -30,6 +30,7 @@ describe 'when optional is true' do let(:env_var_data) { super().merge({ 'optional' => true }) } + it 'raises a validation error when no var is provided' do env_var_data.delete('var') expect { subject.validate_resolve_reference(env_var_data) } @@ -44,6 +45,7 @@ describe 'when default is provided' do let(:env_var_data) { super().merge({ 'default' => 'DEFAULT_STRING' }) } + it 'raises a validation error when no var is provided' do env_var_data.delete('var') expect { subject.validate_resolve_reference(env_var_data) } diff --git a/spec/unit/plugin/puppetdb_spec.rb b/spec/unit/plugin/puppetdb_spec.rb index e7c5ef98d..bc618b048 100644 --- a/spec/unit/plugin/puppetdb_spec.rb +++ b/spec/unit/plugin/puppetdb_spec.rb @@ -41,6 +41,7 @@ 'value' => name_fact }] } end + before(:each) do allow(plugin.puppetdb_client).to receive(:query_certnames).and_return([certname]) allow(plugin.puppetdb_client).to receive(:fact_values).and_return(values_hash) @@ -253,7 +254,7 @@ { 'name' => 'certname' } end - context " with no fact_values" do + context "with no fact_values" do let(:data) { nil } it "returns the certname" do @@ -262,7 +263,7 @@ end end - context " with fact_values" do + context "with fact_values" do let(:data) do { certname => [{ 'path' => [1], diff --git a/spec/unit/transport/local_spec.rb b/spec/unit/transport/local_spec.rb index 17af46e39..d4c8c691b 100644 --- a/spec/unit/transport/local_spec.rb +++ b/spec/unit/transport/local_spec.rb @@ -96,6 +96,7 @@ def get_target(inventory, name, alia = nil) context 'without with_connection' do let(:data) { { 'targets' => [] } } + it 'applies bundled-ruby config' do target = get_target(inventory, 'local://foo') expect(target.transport).to eq('local') diff --git a/spec/unit/util_spec.rb b/spec/unit/util_spec.rb index dd96112a5..8356a009f 100644 --- a/spec/unit/util_spec.rb +++ b/spec/unit/util_spec.rb @@ -7,6 +7,7 @@ describe Bolt::Util do include BoltSpec::Files + context "when creating a typed name from a modulepath" do it "removes init from the typed name" do expect(Bolt::Util.module_name('mymod/plans/init.pp')).to eq('mymod')