bolt 0.20.6 → 0.20.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +10 -2
  3. data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +7 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +16 -0
  5. data/bolt-modules/boltlib/lib/puppet/functions/file_upload.rb +24 -6
  6. data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +15 -13
  7. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +8 -4
  8. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +9 -4
  9. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +18 -6
  10. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +12 -10
  11. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +24 -6
  12. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +34 -12
  13. data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +14 -2
  14. data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +9 -7
  15. data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +7 -2
  16. data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +14 -0
  17. data/lib/bolt/analytics.rb +14 -3
  18. data/lib/bolt/cli.rb +5 -1
  19. data/lib/bolt/executor.rb +5 -0
  20. data/lib/bolt/inventory.rb +8 -0
  21. data/lib/bolt/outputter/human.rb +3 -3
  22. data/lib/bolt/pal.rb +2 -1
  23. data/lib/bolt/version.rb +1 -1
  24. metadata +2 -10
  25. data/modules/facts/lib/puppet/functions/facts/group_by.rb +0 -14
  26. data/modules/facts/plans/info.pp +0 -15
  27. data/modules/facts/plans/init.pp +0 -16
  28. data/modules/facts/plans/retrieve.pp +0 -8
  29. data/modules/facts/tasks/bash.sh +0 -92
  30. data/modules/facts/tasks/init.json +0 -9
  31. data/modules/facts/tasks/powershell.ps1 +0 -56
  32. data/modules/facts/tasks/ruby.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ecd8364f409304d8286adae0544a3f2b34038403
4
- data.tar.gz: e13c9abe1b098794394947baec4da9d349a922fe
3
+ metadata.gz: d1a5c8ec4cf105ece549f43ed95bcaed30df97d8
4
+ data.tar.gz: 0b28cbab7855f68ef4ab9c797bf596e3313becf7
5
5
  SHA512:
6
- metadata.gz: d98430251616d064eb98830532ce8c7de35c4f60b7b55768b9d82a9fbbb9c183363888da3e98d2d915df9637ff488893a495f6a5fe0a6254ed329ecfa2077908
7
- data.tar.gz: 99827f1b25b5b83849c9900551168f3377b2f3b99da600c32f9284173247988c6fbf550ac737f81875d32ea78cf2885d2b9395879e314f6d64d4eb53ae2ff835
6
+ metadata.gz: 467977c61d4c83051978526cba46de367c0626dd4b3a11cb7030faeebd914b8094a66552537a4637c4fdbce2346c571f319a38be69fa29b8d3dadaed14fe14bb
7
+ data.tar.gz: 00834ae333d3d0cb4cd3e5b67c22f53811fe6c4c2d89de1a20e72bd749db697140511045a405f3f0e2320aa8338c238dff7c4bf3fb3adf9c3401048a8ae7f539
@@ -2,12 +2,17 @@
2
2
 
3
3
  require 'bolt/error'
4
4
 
5
- # Deep merges a hash of facts with the existing facts has on a target.
6
-
5
+ # Deep merges a hash of facts with the existing facts on a target.
7
6
  Puppet::Functions.create_function(:add_facts) do
7
+ # @param target A target.
8
+ # @param facts A hash of fact names to values that my include structured facts.
9
+ # @return The target's new facts.
10
+ # @example Adding facts to a target
11
+ # add_facts($target, { 'os' => { 'family' => 'windows', 'name' => 'windows' } })
8
12
  dispatch :add_facts do
9
13
  param 'Target', :target
10
14
  param 'Hash', :facts
15
+ return_type 'Hash[String, Data]'
11
16
  end
12
17
 
13
18
  def add_facts(target, facts)
@@ -25,6 +30,9 @@ Puppet::Functions.create_function(:add_facts) do
25
30
  )
26
31
  end
27
32
 
33
+ executor = Puppet.lookup(:bolt_executor) { nil }
34
+ executor&.report_function_call('add_facts')
35
+
28
36
  inventory.add_facts(target, facts)
29
37
  end
30
38
  end
@@ -3,8 +3,11 @@
3
3
  require 'bolt/error'
4
4
 
5
5
  # Returns the facts hash for a target.
6
- # This functions takes one parameter, the target to get facts for
7
6
  Puppet::Functions.create_function(:facts) do
7
+ # @param target A target.
8
+ # @return The target's facts.
9
+ # @example Getting facts
10
+ # facts($target)
8
11
  dispatch :facts do
9
12
  param 'Target', :target
10
13
  return_type 'Hash[String, Data]'
@@ -25,6 +28,9 @@ Puppet::Functions.create_function(:facts) do
25
28
  )
26
29
  end
27
30
 
31
+ executor = Puppet.lookup(:bolt_executor) { nil }
32
+ executor&.report_function_call('facts')
33
+
28
34
  inventory.facts(target)
29
35
  end
30
36
  end
@@ -7,6 +7,14 @@ require 'bolt/error'
7
7
  # Plan authors should call this function when their plan is not successful. The
8
8
  # error may then be caught by another plans run_plan function or in bolt itself
9
9
  Puppet::Functions.create_function(:fail_plan) do
10
+ # Fail a plan, generating an exception from the parameters.
11
+ # @param msg An error message.
12
+ # @param kind An easily matchable error kind.
13
+ # @param details Machine-parseable details about the error.
14
+ # @param issue_code Unused.
15
+ # @return Raises an exception.
16
+ # @example Raise an exception
17
+ # fail_plan('We goofed up', 'task-unexpected-result', { 'result' => 'null' })
10
18
  dispatch :from_args do
11
19
  param 'String[1]', :msg
12
20
  optional_param 'String[1]', :kind
@@ -14,11 +22,19 @@ Puppet::Functions.create_function(:fail_plan) do
14
22
  optional_param 'String[1]', :issue_code
15
23
  end
16
24
 
25
+ # Fail a plan, generating an exception from an existing Error object.
26
+ # @param error An error object.
27
+ # @return Raises an exception.
28
+ # @example Raise an exception
29
+ # fail_plan(Error('We goofed up', 'task-unexpected-result', { 'result' => 'null' }))
17
30
  dispatch :from_error do
18
31
  param 'Error', :error
19
32
  end
20
33
 
21
34
  def from_args(msg, kind = nil, details = nil, issue_code = nil)
35
+ executor = Puppet.lookup(:bolt_executor) { nil }
36
+ executor&.report_function_call('fail_plan')
37
+
22
38
  raise Bolt::PlanFailure.new(msg, kind || 'bolt/plan-failure', details, issue_code)
23
39
  end
24
40
 
@@ -3,13 +3,19 @@
3
3
  require 'bolt/error'
4
4
 
5
5
  # Uploads the given file or directory to the given set of targets and returns the result from each upload.
6
- #
7
- # * This function does nothing if the list of targets is empty.
8
- # * It is possible to run on the target 'localhost'
9
- # * A target is a String with a targets's hostname or a Target.
10
- # * The returned value contains information about the result per target.
11
- #
6
+ # This function does nothing if the list of targets is empty.
12
7
  Puppet::Functions.create_function(:file_upload, Puppet::Functions::InternalFunction) do
8
+ # Upload a file.
9
+ # @param source A source path, either an absolute path or a modulename/filename selector for a file in
10
+ # <moduleroot>/files.
11
+ # @param destination An absolute path on the target(s).
12
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
13
+ # @param options Additional options: '_catch_errors', '_run_as'.
14
+ # @return A list of results, one entry per target.
15
+ # @example Upload a local file to Linux targets and change owner to 'root'
16
+ # file_upload('/var/tmp/payload.tgz', '/tmp/payload.tgz', $targets, '_run_as' => 'root')
17
+ # @example Upload a module file to a Windows target
18
+ # file_upload('postgres/default.conf', 'C:/ProgramData/postgres/default.conf', $target)
13
19
  dispatch :file_upload do
14
20
  scope_param
15
21
  param 'String[1]', :source
@@ -19,6 +25,16 @@ Puppet::Functions.create_function(:file_upload, Puppet::Functions::InternalFunct
19
25
  return_type 'ResultSet'
20
26
  end
21
27
 
28
+ # Upload a file, logging the provided description.
29
+ # @param source A source path, either an absolute path or a modulename/filename selector for a file in
30
+ # <moduleroot>/files.
31
+ # @param destination An absolute path on the target(s).
32
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
33
+ # @param description A description to be output when calling this function.
34
+ # @param options Additional options: '_catch_errors', '_run_as'.
35
+ # @return A list of results, one entry per target.
36
+ # @example Upload a file
37
+ # file_upload('/var/tmp/payload.tgz', '/tmp/payload.tgz', $targets, 'Uploading payload to unpack')
22
38
  dispatch :file_upload_with_description do
23
39
  scope_param
24
40
  param 'String[1]', :source
@@ -51,6 +67,8 @@ Puppet::Functions.create_function(:file_upload, Puppet::Functions::InternalFunct
51
67
  )
52
68
  end
53
69
 
70
+ executor.report_function_call('file_upload')
71
+
54
72
  found = Puppet::Parser::Files.find_file(source, scope.compiler.environment)
55
73
  unless found && Puppet::FileSystem.exist?(found)
56
74
  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
@@ -3,20 +3,19 @@
3
3
  require 'bolt/error'
4
4
 
5
5
  # Parses common ways of referring to targets and returns an array of Targets.
6
- #
7
- # Accepts input consisting of
8
- # - a group
9
- # - a target URI
10
- # - an array of groups and/or target URIs
11
- # - a string that consists of a comma-separated list of groups and/or target URIs
12
- #
13
- # Examples of the above would be
14
- # - 'group1'
15
- # - 'host1,group1,winrm://host2:54321'
16
- # - ['host1', 'group1', 'winrm://host2:54321']
17
- #
18
- # Returns an array of unique Targets resolved from any target URIs and groups.
19
6
  Puppet::Functions.create_function(:get_targets) do
7
+ # @param names A pattern or array of patterns identifying a set of targets.
8
+ # @return A list of unique Targets resolved from any target URIs and groups.
9
+ # @example Resolve a group
10
+ # get_targets('group1')
11
+ # @example Resolve a target URI
12
+ # get_targets('winrm://host2:54321')
13
+ # @example Resolve array of groups and/or target URIs
14
+ # get_targets(['host1', 'group1', 'winrm://host2:54321'])
15
+ # @example Resolve string consisting of a comma-separated list of groups and/or target URIs
16
+ # get_targets('host1,group1,winrm://host2:54321')
17
+ # @example Run on localhost
18
+ # get_targets('localhost')
20
19
  dispatch :get_targets do
21
20
  param 'Boltlib::TargetSpec', :names
22
21
  return_type 'Array[Target]'
@@ -37,6 +36,9 @@ Puppet::Functions.create_function(:get_targets) do
37
36
  )
38
37
  end
39
38
 
39
+ executor = Puppet.lookup(:bolt_executor) { nil }
40
+ executor&.report_function_call('get_targets')
41
+
40
42
  inventory.get_targets(names)
41
43
  end
42
44
  end
@@ -2,14 +2,15 @@
2
2
 
3
3
  require 'bolt/error'
4
4
 
5
- # Returns a hash of certname to facts objects for each matched Target. This
6
- # functions accepts an array of certnames and returns a hash of target
7
- # certnames and their corresponding facts hash.
5
+ # Collects facts based on a list of certnames.
8
6
  #
9
7
  # * If a node is not found in PuppetDB, it's included in the returned hash with empty facts hash.
10
8
  # * Otherwise the node is included in the hash with a value that is a hash of it's facts.
11
- #
12
9
  Puppet::Functions.create_function(:puppetdb_fact) do
10
+ # @param certnames Array of certnames.
11
+ # @return A hash of certname to facts hash for each matched Target.
12
+ # @example Get facts for nodes
13
+ # puppetdb_fact(['app.example.com', 'db.example.com'])
13
14
  dispatch :puppetdb_fact do
14
15
  param 'Array[String]', :certnames
15
16
  return_type 'Hash[String, Data]'
@@ -29,6 +30,9 @@ Puppet::Functions.create_function(:puppetdb_fact) do
29
30
  )
30
31
  end
31
32
 
33
+ executor = Puppet.lookup(:bolt_executor) { nil }
34
+ executor&.report_function_call('puppetdb_fact')
35
+
32
36
  puppetdb_client.facts_for_node(certnames)
33
37
  end
34
38
  end
@@ -2,15 +2,17 @@
2
2
 
3
3
  require 'bolt/error'
4
4
 
5
- #
6
- # Makes a query to puppetdb using the bolts puppetdb client.
7
- #
5
+ # Makes a query to puppetdb using Bolt's PuppetDB client.
8
6
  Puppet::Functions.create_function(:puppetdb_query) do
9
- # This type could be more specific ASTQuery = Array[Variant[String, ASTQuery]]
7
+ # @param query A PQL query.
8
+ # @return Results of the PuppetDB query.
9
+ # @example Request certnames for all nodes
10
+ # puppetdb_query('nodes[certname] {}')
10
11
  dispatch :make_query do
11
12
  param 'Variant[String, Array[Data]]', :query
12
13
  return_type 'Array[Data]'
13
14
  end
15
+ # The query type could be more specific ASTQuery = Array[Variant[String, ASTQuery]]
14
16
 
15
17
  def make_query(query)
16
18
  puppetdb_client = Puppet.lookup(:bolt_pdb_client) { nil }
@@ -20,6 +22,9 @@ Puppet::Functions.create_function(:puppetdb_query) do
20
22
  )
21
23
  end
22
24
 
25
+ executor = Puppet.lookup(:bolt_executor) { nil }
26
+ executor&.report_function_call('puppetdb_query')
27
+
23
28
  puppetdb_client.make_query(query)
24
29
  end
25
30
  end
@@ -3,13 +3,15 @@
3
3
  require 'bolt/error'
4
4
 
5
5
  # Runs a command on the given set of targets and returns the result from each command execution.
6
- #
7
- # * This function does nothing if the list of targets is empty.
8
- # * It is possible to run on the target 'localhost'
9
- # * A target is a String with a targets's hostname or a Target.
10
- # * The returned value contains information about the result per target.
11
- #
6
+ # This function does nothing if the list of targets is empty.
12
7
  Puppet::Functions.create_function(:run_command) do
8
+ # Run a command.
9
+ # @param command A command to run on target.
10
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
11
+ # @param options Additional options: '_catch_errors', '_run_as'.
12
+ # @return A list of results, one entry per target.
13
+ # @example Run a command on targets
14
+ # run_command('hostname', $targets, '_catch_errors' => true)
13
15
  dispatch :run_command do
14
16
  param 'String[1]', :command
15
17
  param 'Boltlib::TargetSpec', :targets
@@ -17,6 +19,14 @@ Puppet::Functions.create_function(:run_command) do
17
19
  return_type 'ResultSet'
18
20
  end
19
21
 
22
+ # Run a command, logging the provided description.
23
+ # @param command A command to run on target.
24
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
25
+ # @param description A description to be output when calling this function.
26
+ # @param options Additional options: '_catch_errors', '_run_as'.
27
+ # @return A list of results, one entry per target.
28
+ # @example Run a command on targets
29
+ # run_command('hostname', $targets, '_catch_errors' => true)
20
30
  dispatch :run_command_with_description do
21
31
  param 'String[1]', :command
22
32
  param 'Boltlib::TargetSpec', :targets
@@ -47,6 +57,8 @@ Puppet::Functions.create_function(:run_command) do
47
57
  )
48
58
  end
49
59
 
60
+ executor.report_function_call('run_command')
61
+
50
62
  # Ensure that given targets are all Target instances
51
63
  targets = inventory.get_targets(targets)
52
64
 
@@ -2,17 +2,13 @@
2
2
 
3
3
  require 'bolt/error'
4
4
 
5
- # Runs the `plan` referenced by its name passing giving arguments to it given as a hash of name to value mappings.
6
- # A plan is autoloaded from under <root>/plans if not already defined.
7
- #
8
- # @example defining and running a plan
9
- # plan myplan($x) {
10
- # # do things with tasks
11
- # notice "plan done with param x = ${x}"
12
- # }
13
- # run_plan('myplan', { x => 'testing' })
14
- #
5
+ # Runs the `plan` referenced by its name. A plan is autoloaded from <moduleroot>/plans.
15
6
  Puppet::Functions.create_function(:run_plan, Puppet::Functions::InternalFunction) do
7
+ # @param plan_name The plan to run.
8
+ # @param named_args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as'.
9
+ # @return [PlanResult] The result of running the plan. Undef if plan does not explicitly return results.
10
+ # @example Run a plan
11
+ # run_plan('canary', 'command' => 'false', 'nodes' => $targets, '_catch_errors' => true)
16
12
  dispatch :run_plan do
17
13
  scope_param
18
14
  param 'String', :plan_name
@@ -33,6 +29,12 @@ Puppet::Functions.create_function(:run_plan, Puppet::Functions::InternalFunction
33
29
  )
34
30
  end
35
31
 
32
+ # Bolt calls this function internally to trigger plans from the CLI. We
33
+ # don't want to count those invocations.
34
+ unless named_args['_bolt_api_call']
35
+ executor.report_function_call('run_plan')
36
+ end
37
+
36
38
  params = named_args.reject { |k, _| k.start_with?('_') }
37
39
 
38
40
  loaders = closure_scope.compiler.loaders
@@ -1,13 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Uploads the given script to the given set of targets and returns the result of having each target execute the script.
4
- #
5
- # * This function does nothing if the list of targets is empty.
6
- # * It is possible to run on the target 'localhost'
7
- # * A target is a String with a targets's hostname or a Target.
8
- # * The returned value contains information about the result per target.
9
- #
4
+ # This function does nothing if the list of targets is empty.
10
5
  Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFunction) do
6
+ # Run a script.
7
+ # @param script Path to a script to run on target. May be an absolute path or a modulename/filename selector for a
8
+ # file in <moduleroot>/files.
9
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
10
+ # @param options Specify an array of arguments to the 'arguments' key to be passed to the script.
11
+ # Additional options: '_catch_errors', '_run_as'.
12
+ # @return A list of results, one entry per target.
13
+ # @example Run a local script on Linux targets as 'root'
14
+ # run_script('/var/tmp/myscript', $targets, '_run_as' => 'root')
15
+ # @example Run a module-provided script with arguments
16
+ # file_upload('iis/setup.ps1', $target, 'arguments' => ['/u', 'Administrator'])
11
17
  dispatch :run_script do
12
18
  scope_param
13
19
  param 'String[1]', :script
@@ -16,6 +22,16 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti
16
22
  return_type 'ResultSet'
17
23
  end
18
24
 
25
+ # Run a script, logging the provided description.
26
+ # @param script Path to a script to run on target. May be an absolute path or a modulename/filename selector for a
27
+ # file in <moduleroot>/files.
28
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
29
+ # @param description A description to be output when calling this function.
30
+ # @param options Specify an array of arguments to the 'arguments' key to be passed to the script.
31
+ # Additional options: '_catch_errors', '_run_as'.
32
+ # @return A list of results, one entry per target.
33
+ # @example Run a script
34
+ # file_upload('/var/tmp/myscript', $targets, 'Downloading my application')
19
35
  dispatch :run_script_with_description do
20
36
  scope_param
21
37
  param 'String[1]', :script
@@ -47,6 +63,8 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti
47
63
  )
48
64
  end
49
65
 
66
+ executor.report_function_call('run_script')
67
+
50
68
  found = Puppet::Parser::Files.find_file(script, scope.compiler.environment)
51
69
  unless found && Puppet::FileSystem.exist?(found)
52
70
  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
@@ -3,36 +3,52 @@
3
3
  require 'bolt/error'
4
4
 
5
5
  # Runs a given instance of a `Task` on the given set of targets and returns the result from each.
6
- #
7
- # * This function does nothing if the list of targets is empty.
8
- # * It is possible to run on the target 'localhost'
9
- # * A target is a String with a targets's hostname or a Target.
10
- # * The returned value contains information about the result per target.
11
- #
6
+ # This function does nothing if the list of targets is empty.
12
7
  Puppet::Functions.create_function(:run_task) do
13
- dispatch :run_task_with_description do
8
+ # Run a task.
9
+ # @param task_name The task to run.
10
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
11
+ # @param task_args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as'.
12
+ # @return A list of results, one entry per target.
13
+ # @example Run a task as root
14
+ # run_task('facts', $targets, '_run_as' => 'root')
15
+ dispatch :run_task do
14
16
  param 'String[1]', :task_name
15
17
  param 'Boltlib::TargetSpec', :targets
16
- param 'String', :description
17
18
  optional_param 'Hash[String[1], Any]', :task_args
18
19
  return_type 'ResultSet'
19
20
  end
20
21
 
21
- dispatch :run_task do
22
+ # Run a task, logging the provided description.
23
+ # @param task_name The task to run.
24
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
25
+ # @param description A description to be output when calling this function.
26
+ # @param task_args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as'.
27
+ # @return A list of results, one entry per target.
28
+ # @example Run a task
29
+ # run_task('facts', $targets, 'Gather OS facts')
30
+ dispatch :run_task_with_description do
22
31
  param 'String[1]', :task_name
23
32
  param 'Boltlib::TargetSpec', :targets
33
+ param 'String', :description
24
34
  optional_param 'Hash[String[1], Any]', :task_args
25
35
  return_type 'ResultSet'
26
36
  end
27
37
 
28
- # this is used from 'bolt task run'
38
+ # Run a task, calling the block as each node starts and finishes execution. This is used from 'bolt task run'
39
+ # @param task_name The task to run.
40
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
41
+ # @param description A description to be output when calling this function.
42
+ # @param task_args Arguments to the plan. Can also include additional options: '_catch_errors', '_run_as'.
43
+ # @param block A block that's invoked as actions are started and finished on each node.
44
+ # @return A list of results, one entry per target.
29
45
  dispatch :run_task_raw do
30
46
  param 'String[1]', :task_name
31
47
  param 'Boltlib::TargetSpec', :targets
32
48
  param 'Optional[String]', :description
33
49
  optional_param 'Hash[String[1], Any]', :task_args
34
- # return_type 'ResultSet'
35
- block_param
50
+ block_param 'Callable[Struct[{type => Enum[node_start, node_result], target => Target}], 1, 1]', :block
51
+ return_type 'ResultSet'
36
52
  end
37
53
 
38
54
  def run_task(task_name, targets, task_args = nil)
@@ -64,6 +80,12 @@ Puppet::Functions.create_function(:run_task) do
64
80
  )
65
81
  end
66
82
 
83
+ # Bolt calls this function internally to trigger tasks from the CLI. We
84
+ # don't want to count those invocations.
85
+ unless task_args['_bolt_api_call']
86
+ executor.report_function_call('run_task')
87
+ end
88
+
67
89
  # Ensure that given targets are all Target instances
68
90
  targets = inventory.get_targets(targets)
69
91
 
@@ -2,9 +2,18 @@
2
2
 
3
3
  require 'bolt/error'
4
4
 
5
- # Sets a particular feature to present on a target.
6
-
5
+ # Sets a particular feature to present on a target. Features are used to determine what implementation
6
+ # of a task should be run. Currently supported features are
7
+ # - powershell
8
+ # - shell
9
+ # - puppet-agent
7
10
  Puppet::Functions.create_function(:set_feature) do
11
+ # @param target The Target object to add features to. See {get_targets}.
12
+ # @param feature The string identifying the feature.
13
+ # @param value Whether the feature is supported.
14
+ # @return [Undef]
15
+ # @example Add the puppet-agent feature to a target
16
+ # set_feature($target, 'puppet-agent', true)
8
17
  dispatch :set_feature do
9
18
  param 'Target', :target
10
19
  param 'String', :feature
@@ -26,6 +35,9 @@ Puppet::Functions.create_function(:set_feature) do
26
35
  )
27
36
  end
28
37
 
38
+ executor = Puppet.lookup(:bolt_executor) { nil }
39
+ executor&.report_function_call('set_feature')
40
+
29
41
  inventory.set_feature(target, feature, value)
30
42
 
31
43
  target
@@ -3,14 +3,13 @@
3
3
  require 'bolt/error'
4
4
 
5
5
  # Sets a variable { key => value } for a target.
6
- #
7
- # This function takes 3 parameters:
8
- # * A Target object to set the variable for
9
- # * The key for the variable (String)
10
- # * The value of the variable (Data)
11
- #
12
- # Returns undef.
13
6
  Puppet::Functions.create_function(:set_var) do
7
+ # @param target The Target object to set the variable for. See {get_targets}.
8
+ # @param key The key for the variable.
9
+ # @param value The value of the variable.
10
+ # @return [Undef]
11
+ # @example Set a variable on a target
12
+ # $target.set_var('ephemeral', true)
14
13
  dispatch :set_var do
15
14
  param 'Target', :target
16
15
  param 'String', :key
@@ -32,6 +31,9 @@ Puppet::Functions.create_function(:set_var) do
32
31
  )
33
32
  end
34
33
 
34
+ executor = Puppet.lookup(:bolt_executor) { nil }
35
+ executor&.report_function_call('set_var')
36
+
35
37
  inventory.set_var(target, key, value)
36
38
  end
37
39
  end
@@ -5,11 +5,13 @@ require 'bolt/error'
5
5
  # Returns a hash of the 'vars' (variables) assigned to a target through the
6
6
  # inventory file or `set_var` function.
7
7
  #
8
- # Accepts no parameters.
9
- #
10
8
  # Plan authors can call this function on a target to get the variable hash
11
9
  # for that target.
12
10
  Puppet::Functions.create_function(:vars) do
11
+ # @param target The Target object to get variables from. See {get_targets}.
12
+ # @return A hash of the 'vars' (variables) assigned to a target.
13
+ # @example Get vars for a target
14
+ # $target.vars
13
15
  dispatch :vars do
14
16
  param 'Target', :target
15
17
  return_type 'Hash[String, Data]'
@@ -30,6 +32,9 @@ Puppet::Functions.create_function(:vars) do
30
32
  )
31
33
  end
32
34
 
35
+ executor = Puppet.lookup(:bolt_executor) { nil }
36
+ executor&.report_function_call('vars')
37
+
33
38
  inventory.vars(target)
34
39
  end
35
40
  end
@@ -1,12 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Define a block where default logging is suppressed. Messages for actions within this block
4
+ # will be logged at `info` level instead of `notice`, so they will not be seen normally but
5
+ # will still be present when `verbose` logging is requested.
3
6
  Puppet::Functions.create_function(:without_default_logging) do
7
+ # @param block The block where action logging is suppressed.
8
+ # @return [Undef]
9
+ # @example Suppress default logging for a series of functions
10
+ # without_default_logging() || {
11
+ # notice("Deploying on ${nodes}")
12
+ # get_targets($nodes).each |$node| {
13
+ # run_task(deploy, $node)
14
+ # }
15
+ # }
4
16
  dispatch :without_default_logging do
5
17
  block_param 'Callable[0, 0]', :block
6
18
  end
7
19
 
8
20
  def without_default_logging
9
21
  executor = Puppet.lookup(:bolt_executor) { nil }
22
+ executor.report_function_call('without_default_logging')
23
+
10
24
  old_log = executor.plan_logging
11
25
  executor.plan_logging = false
12
26
  begin
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bolt/util'
3
4
  require 'bolt/version'
4
5
  require 'httpclient'
5
6
  require 'json'
@@ -13,6 +14,12 @@ module Bolt
13
14
  APPLICATION_NAME = 'bolt'
14
15
  TRACKING_ID = 'UA-120367942-1'
15
16
  TRACKING_URL = 'https://google-analytics.com/collect'
17
+ CUSTOM_DIMENSIONS = {
18
+ operating_system: :cd1,
19
+ inventory_nodes: :cd2,
20
+ inventory_groups: :cd3,
21
+ target_nodes: :cd4
22
+ }.freeze
16
23
 
17
24
  def self.build_client
18
25
  logger = Logging.logger[self]
@@ -60,13 +67,17 @@ module Bolt
60
67
  @os = compute_os
61
68
  end
62
69
 
63
- def screen_view(screen)
70
+ def screen_view(screen, **kwargs)
71
+ custom_dimensions = Bolt::Util.walk_keys(kwargs) do |k|
72
+ CUSTOM_DIMENSIONS[k] || raise("Unknown analytics key '#{k}'")
73
+ end
74
+
64
75
  screen_view_params = {
65
76
  # Type
66
77
  t: 'screenview',
67
78
  # Screen Name
68
79
  cd: screen
69
- }
80
+ }.merge(custom_dimensions)
70
81
 
71
82
  submit(base_params.merge(screen_view_params))
72
83
  end
@@ -146,7 +157,7 @@ module Bolt
146
157
  @logger = Logging.logger[self]
147
158
  end
148
159
 
149
- def screen_view(screen)
160
+ def screen_view(screen, **_kwargs)
150
161
  @logger.debug "Skipping submission of '#{screen}' screenview because analytics is disabled"
151
162
  end
152
163
 
@@ -501,7 +501,11 @@ Available options are:
501
501
  if options[:action] == 'show' && options[:object]
502
502
  screen += '_object'
503
503
  end
504
- @analytics.screen_view(screen)
504
+
505
+ @analytics.screen_view(screen,
506
+ target_nodes: options.fetch(:targets, []).count,
507
+ inventory_nodes: inventory.node_names.count,
508
+ inventory_groups: inventory.group_names.count)
505
509
 
506
510
  if options[:mode] == 'plan' || options[:mode] == 'task'
507
511
  pal = Bolt::PAL.new(config)
@@ -123,6 +123,10 @@ module Bolt
123
123
  @reported_transports.add(name)
124
124
  end
125
125
 
126
+ def report_function_call(function)
127
+ @analytics&.event('Plan', 'call_function', function)
128
+ end
129
+
126
130
  def with_node_logging(description, batch)
127
131
  @logger.info("#{description} on #{batch.map(&:uri)}")
128
132
  result = yield
@@ -170,6 +174,7 @@ module Bolt
170
174
  log_action(description, targets) do
171
175
  notify = proc { |event| @notifier.notify(callback, event) if callback }
172
176
  options = { '_run_as' => run_as }.merge(options) if run_as
177
+ arguments['_task'] = task.name
173
178
 
174
179
  results = batch_execute(targets) do |transport, batch|
175
180
  with_node_logging("Running task #{task.name} with '#{arguments}' via #{task.input_method}", batch) do
@@ -78,6 +78,14 @@ module Bolt
78
78
  @group_lookup = @groups.collect_groups
79
79
  end
80
80
 
81
+ def group_names
82
+ @group_lookup.keys
83
+ end
84
+
85
+ def node_names
86
+ @groups.node_names
87
+ end
88
+
81
89
  def get_targets(targets)
82
90
  targets = expand_targets(targets)
83
91
  targets = if targets.is_a? Array
@@ -112,7 +112,7 @@ module Bolt
112
112
  )
113
113
  end
114
114
 
115
- # @param [Hash] A hash representing the task
115
+ # @param [Hash] task A hash representing the task
116
116
  def print_task_info(task)
117
117
  # Building lots of strings...
118
118
  pretty_params = +""
@@ -142,7 +142,7 @@ module Bolt
142
142
  @stream.puts(task_info)
143
143
  end
144
144
 
145
- # @param [Hash] A hash representing the plan
145
+ # @param [Hash] plan A hash representing the plan
146
146
  def print_plan_info(plan)
147
147
  # Building lots of strings...
148
148
  pretty_params = +""
@@ -161,7 +161,7 @@ module Bolt
161
161
  @stream.puts(plan_info)
162
162
  end
163
163
 
164
- # @param [Bolt::PlanResult] A PlanResult object
164
+ # @param [Bolt::PlanResult] plan_result A PlanResult object
165
165
  def print_plan_result(plan_result)
166
166
  if plan_result.value.nil?
167
167
  @stream.puts("Plan completed successfully with no result")
@@ -240,13 +240,14 @@ module Bolt
240
240
 
241
241
  def run_task(task_name, targets, params, executor, inventory, description = nil, &eventblock)
242
242
  in_task_compiler(executor, inventory) do |compiler|
243
+ params = params.merge('_bolt_api_call' => true)
243
244
  compiler.call_function('run_task', task_name, targets, description, params, &eventblock)
244
245
  end
245
246
  end
246
247
 
247
248
  def run_plan(plan_name, params, executor = nil, inventory = nil, pdb_client = nil)
248
249
  in_plan_compiler(executor, inventory, pdb_client) do |compiler|
249
- r = compiler.call_function('run_plan', plan_name, params)
250
+ r = compiler.call_function('run_plan', plan_name, params.merge('_bolt_api_call' => true))
250
251
  Bolt::PlanResult.from_pcore(r, 'success')
251
252
  end
252
253
  rescue Bolt::Error => e
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '0.20.6'
4
+ VERSION = '0.20.7'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.6
4
+ version: 0.20.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-07 00:00:00.000000000 Z
11
+ date: 2018-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -394,14 +394,6 @@ files:
394
394
  - modules/canary/lib/puppet/functions/canary/random_split.rb
395
395
  - modules/canary/lib/puppet/functions/canary/skip.rb
396
396
  - modules/canary/plans/init.pp
397
- - modules/facts/lib/puppet/functions/facts/group_by.rb
398
- - modules/facts/plans/info.pp
399
- - modules/facts/plans/init.pp
400
- - modules/facts/plans/retrieve.pp
401
- - modules/facts/tasks/bash.sh
402
- - modules/facts/tasks/init.json
403
- - modules/facts/tasks/powershell.ps1
404
- - modules/facts/tasks/ruby.rb
405
397
  - modules/puppetdb_fact/plans/init.pp
406
398
  - vendored/facter/lib/facter.rb
407
399
  - vendored/facter/lib/facter/Cfkey.rb
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # A simple wrapper of the ruby's group_by function.
4
- Puppet::Functions.create_function(:'facts::group_by') do
5
- dispatch :native_group_by do
6
- param 'Iterable', :collection
7
- block_param
8
- return_type 'Hash'
9
- end
10
-
11
- def native_group_by(collection, &block)
12
- collection.group_by(&block)
13
- end
14
- end
@@ -1,15 +0,0 @@
1
- # A plan that prints basic OS information for the specified nodes. It first
2
- # runs the facts::retrieve plan to retrieve facts from the nodes, then
3
- # compiles the desired OS information from the os fact value of each nodes.
4
- #
5
- # The $nodes parameter is a list of the nodes for which to print the OS
6
- # information.
7
- plan facts::info(TargetSpec $nodes) {
8
- return run_plan(facts::retrieve, nodes => $nodes).reduce([]) |$info, $r| {
9
- if ($r.ok) {
10
- $info + "${r.target.name}: ${r[os][name]} ${r[os][release][full]} (${r[os][family]})"
11
- } else {
12
- $info # don't include any info for nodes which failed
13
- }
14
- }
15
- }
@@ -1,16 +0,0 @@
1
- # A plan that stores facts retrieved by the facts::retrieve plan
2
- # from the specified nodes into the inventory.
3
- #
4
- # The $nodes parameter is a list of nodes to retrieve the facts for.
5
- plan facts(TargetSpec $nodes) {
6
- $result_set = run_plan(facts::retrieve, nodes => $nodes)
7
-
8
- $result_set.each |$result| {
9
- # Store facts for nodes from which they were succefully retrieved
10
- if ($result.ok) {
11
- add_facts($result.target, $result.value)
12
- }
13
- }
14
-
15
- return $result_set
16
- }
@@ -1,8 +0,0 @@
1
- # A plan that retrieves facts from the specified nodes by running
2
- # the 'facts' task on each.
3
- #
4
- # The $nodes parameter is a list of the nodes to retrieve the facts
5
- # from.
6
- plan facts::retrieve(TargetSpec $nodes) {
7
- return run_task('facts', $nodes, '_catch_errors' => true)
8
- }
@@ -1,92 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # Delegate to facter if available
4
- command -v facter > /dev/null 2>&1 && exec facter -p --json
5
-
6
- minor () {
7
- minor="${*#*.}"
8
- [ "$minor" == "$*" ] || echo "${minor%%.*}"
9
- }
10
-
11
- # Determine the OS name
12
- if [ -f /etc/redhat-release ]; then
13
- if egrep -iq centos /etc/redhat-release; then
14
- name=CentOS
15
- elif egrep -iq 'Fedora release' /etc/redhat-release; then
16
- name=Fedora
17
- fi
18
- release=$(sed -r -e 's/^.* release ([0-9]+(\.[0-9]+)?).*$/\1/' \
19
- /etc/redhat-release)
20
- fi
21
-
22
- if [ -z "${name}" ]; then
23
- LSB_RELEASE=$(command -v lsb_release)
24
- if [ -n "$LSB_RELEASE" ]; then
25
- if [ -z "$name" ]; then
26
- name=$($LSB_RELEASE -i | sed -re 's/^.*:[ \t]*//')
27
- fi
28
- release=$($LSB_RELEASE -r | sed -re 's/^.*:[ \t]*//')
29
- fi
30
- fi
31
-
32
- # if lsb not available try os-release
33
- if [ -z "${name}" ]; then
34
- if [ -e /etc/os-release ]; then
35
- name=$(grep "^NAME" /etc/os-release | cut -d'=' -f2 | sed "s/\"//g")
36
- release=$(grep "^VERSION_ID" /etc/os-release | cut -d'=' -f2 | sed "s/\"//g")
37
- elif [-e /usr/lib/os-release ]; then
38
- name=$(grep "^NAME" /usr/lib/os-release | cut -d'=' -f2 | sed "s/\"//g")
39
- release=$(grep "^VERSION_ID" /usr/lib/os-release | cut -d'=' -f2 | sed "s/\"//g")
40
- fi
41
- if [ -n "${name}" ]; then
42
- if echo "${name}" | egrep -iq "(.*red)(.*hat)"; then
43
- name="RedHat"
44
- elif echo "${name}" | egrep -iq "debian"; then
45
- name="Debian"
46
- fi
47
- fi
48
- fi
49
-
50
- if [ -z "${name}" ]; then
51
- name=$(uname)
52
- release=$(uname -r)
53
- fi
54
-
55
- case $name in
56
- RedHat|Fedora|CentOS|Scientific|SLC|Ascendos|CloudLinux)
57
- family=RedHat;;
58
- HuaweiOS|LinuxMint|Ubuntu|Debian)
59
- family=Debian;;
60
- *)
61
- family=$name;;
62
- esac
63
-
64
- # Print it all out
65
- if [ -z "$name" ]; then
66
- cat <<JSON
67
- {
68
- "_error": {
69
- "kind": "facts/noname",
70
- "msg": "Could not determine OS name"
71
- }
72
- }
73
- JSON
74
- else
75
- cat <<JSON
76
- {
77
- "os": {
78
- "name": "${name}",
79
- JSON
80
- [ -n "$release" ] && cat <<JSON
81
- "release": {
82
- "full": "${release}",
83
- "major": "${release%%.*}",
84
- "minor": "`minor "${release}"`"
85
- },
86
- JSON
87
- cat <<JSON
88
- "family": "${family}"
89
- }
90
- }
91
- JSON
92
- fi
@@ -1,9 +0,0 @@
1
- {
2
- "description": "Gather system facts",
3
- "parameters": {},
4
- "implementations": [
5
- {"name": "ruby.rb", "requirements": ["puppet-agent"]},
6
- {"name": "powershell.ps1", "requirements": ["powershell"]},
7
- {"name": "bash.sh", "requirements": ["shell"]}
8
- ]
9
- }
@@ -1,56 +0,0 @@
1
- #!powershell.exe
2
-
3
- # Delegate to facter if available
4
- if (Get-Command facter -ErrorAction SilentlyContinue) {
5
- facter -p --json
6
- }
7
- else {
8
- # The number 2 in the condition below is the value of
9
- # the [System.PlatformID]::Win32NT constant. We don't
10
- # use the constant here as it doesn't work on Windows
11
- # Server Core.
12
- if ([System.Environment]::OSVersion.Platform -gt 2) {
13
- @'
14
- {
15
- "_error": {
16
- "kind": "facts/noname",
17
- "msg": "Could not determine OS name"
18
- }
19
- }
20
- '@
21
- }
22
- else {
23
- $release = [System.Environment]::OSVersion.Version.ToString() -replace '\.[^.]*\z'
24
- $version = $release -replace '\.[^.]*\z'
25
-
26
- # This fails for regular users unless explicitly enabled
27
- $os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
28
- $consumerrel = $os.ProductType -eq '1'
29
-
30
- $release = switch($version){
31
- '10.0'{ if ($consumerrel) { '10' } else { '2016' } }
32
- '6.3' { if ($consumerrel) { '8.1' } else { '2012 R2' } }
33
- '6.2' { if ($consumerrel) { '8' } else { '2012' } }
34
- '6.1' { if ($consumerrel) { '7' } else { '2008 R2' } }
35
- '6.0' { if ($consumerrel) { 'Vista' } else { '2008' } }
36
- '5.2' {
37
- if ($consumerrel) { 'XP' } else {
38
- if ($os.OtherTypeDescription -eq 'R2') { '2003 R2' } else { '2003' }
39
- }
40
- }
41
- }
42
-
43
- @"
44
- {
45
- "os": {
46
- "name": "windows",
47
- "release": {
48
- "full": "$release",
49
- "major": "$release"
50
- },
51
- "family": "windows"
52
- }
53
- }
54
- "@
55
- }
56
- }
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- def facter_executable
5
- if ENV.key? 'Path'
6
- ENV['Path'].split(';').each do |p|
7
- if p =~ /Puppet\\bin\\?$/
8
- return File.join(p, 'facter')
9
- end
10
- end
11
- 'C:\Program Files\Puppet Labs\Puppet\bin\facter'
12
- else
13
- '/opt/puppetlabs/puppet/bin/facter'
14
- end
15
- end
16
-
17
- # Delegate to facter
18
- exec(facter_executable, '-p', '--json')