choria-mcorpc-support 2.21.1 → 2.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mcollective.rb +1 -2
  3. data/lib/mcollective/agent/bolt_tasks.ddl +253 -0
  4. data/lib/mcollective/agent/bolt_tasks.json +365 -0
  5. data/lib/mcollective/agent/bolt_tasks.rb +178 -0
  6. data/lib/mcollective/agent/choria_util.ddl +152 -0
  7. data/lib/mcollective/agent/choria_util.json +244 -0
  8. data/lib/mcollective/agent/rpcutil.ddl +8 -4
  9. data/lib/mcollective/agent/rpcutil.json +333 -0
  10. data/lib/mcollective/agent/scout.ddl +169 -0
  11. data/lib/mcollective/agent/scout.json +224 -0
  12. data/lib/mcollective/agents.rb +7 -6
  13. data/lib/mcollective/aggregate.rb +4 -4
  14. data/lib/mcollective/aggregate/average.rb +2 -2
  15. data/lib/mcollective/aggregate/base.rb +2 -2
  16. data/lib/mcollective/aggregate/result.rb +3 -3
  17. data/lib/mcollective/aggregate/result/collection_result.rb +2 -2
  18. data/lib/mcollective/aggregate/result/numeric_result.rb +2 -2
  19. data/lib/mcollective/aggregate/sum.rb +2 -2
  20. data/lib/mcollective/aggregate/summary.rb +3 -4
  21. data/lib/mcollective/application.rb +57 -21
  22. data/lib/mcollective/application/choria.rb +189 -0
  23. data/lib/mcollective/application/completion.rb +6 -6
  24. data/lib/mcollective/application/facts.rb +11 -11
  25. data/lib/mcollective/application/federation.rb +237 -0
  26. data/lib/mcollective/application/find.rb +4 -4
  27. data/lib/mcollective/application/help.rb +3 -3
  28. data/lib/mcollective/application/inventory.rb +3 -341
  29. data/lib/mcollective/application/ping.rb +5 -51
  30. data/lib/mcollective/application/playbook.rb +207 -0
  31. data/lib/mcollective/application/plugin.rb +106 -106
  32. data/lib/mcollective/application/rpc.rb +3 -108
  33. data/lib/mcollective/application/tasks.rb +425 -0
  34. data/lib/mcollective/applications.rb +11 -10
  35. data/lib/mcollective/audit/choria.rb +33 -0
  36. data/lib/mcollective/cache.rb +2 -4
  37. data/lib/mcollective/client.rb +11 -10
  38. data/lib/mcollective/config.rb +21 -34
  39. data/lib/mcollective/connector/base.rb +2 -1
  40. data/lib/mcollective/connector/nats.ddl +9 -0
  41. data/lib/mcollective/connector/nats.rb +450 -0
  42. data/lib/mcollective/data.rb +8 -3
  43. data/lib/mcollective/data/agent_data.rb +1 -1
  44. data/lib/mcollective/data/base.rb +6 -5
  45. data/lib/mcollective/data/bolt_task_data.ddl +90 -0
  46. data/lib/mcollective/data/bolt_task_data.rb +32 -0
  47. data/lib/mcollective/data/collective_data.rb +1 -1
  48. data/lib/mcollective/data/fact_data.rb +6 -6
  49. data/lib/mcollective/data/fstat_data.rb +2 -4
  50. data/lib/mcollective/data/result.rb +7 -2
  51. data/lib/mcollective/ddl/agentddl.rb +5 -17
  52. data/lib/mcollective/ddl/base.rb +10 -13
  53. data/lib/mcollective/discovery.rb +24 -39
  54. data/lib/mcollective/discovery/choria.ddl +11 -0
  55. data/lib/mcollective/discovery/choria.rb +223 -0
  56. data/lib/mcollective/discovery/flatfile.rb +7 -8
  57. data/lib/mcollective/discovery/mc.rb +2 -2
  58. data/lib/mcollective/discovery/stdin.rb +17 -18
  59. data/lib/mcollective/exceptions.rb +13 -0
  60. data/lib/mcollective/facts/base.rb +9 -9
  61. data/lib/mcollective/facts/yaml_facts.rb +12 -12
  62. data/lib/mcollective/generators.rb +3 -3
  63. data/lib/mcollective/generators/agent_generator.rb +3 -4
  64. data/lib/mcollective/generators/base.rb +14 -15
  65. data/lib/mcollective/generators/data_generator.rb +5 -6
  66. data/lib/mcollective/log.rb +2 -2
  67. data/lib/mcollective/logger/base.rb +3 -2
  68. data/lib/mcollective/logger/console_logger.rb +10 -10
  69. data/lib/mcollective/logger/file_logger.rb +7 -7
  70. data/lib/mcollective/logger/syslog_logger.rb +11 -15
  71. data/lib/mcollective/message.rb +8 -39
  72. data/lib/mcollective/monkey_patches.rb +2 -4
  73. data/lib/mcollective/optionparser.rb +2 -1
  74. data/lib/mcollective/pluginmanager.rb +3 -5
  75. data/lib/mcollective/pluginpackager.rb +1 -3
  76. data/lib/mcollective/pluginpackager/agent_definition.rb +3 -8
  77. data/lib/mcollective/pluginpackager/forge_packager.rb +7 -9
  78. data/lib/mcollective/pluginpackager/standard_definition.rb +1 -2
  79. data/lib/mcollective/registration/base.rb +18 -16
  80. data/lib/mcollective/rpc.rb +2 -4
  81. data/lib/mcollective/rpc/actionrunner.rb +16 -18
  82. data/lib/mcollective/rpc/agent.rb +26 -43
  83. data/lib/mcollective/rpc/audit.rb +1 -0
  84. data/lib/mcollective/rpc/client.rb +67 -85
  85. data/lib/mcollective/rpc/helpers.rb +55 -62
  86. data/lib/mcollective/rpc/progress.rb +2 -2
  87. data/lib/mcollective/rpc/reply.rb +17 -19
  88. data/lib/mcollective/rpc/request.rb +7 -5
  89. data/lib/mcollective/rpc/result.rb +6 -8
  90. data/lib/mcollective/rpc/stats.rb +49 -58
  91. data/lib/mcollective/security/base.rb +13 -56
  92. data/lib/mcollective/security/choria.rb +765 -0
  93. data/lib/mcollective/shell.rb +9 -4
  94. data/lib/mcollective/signer/base.rb +28 -0
  95. data/lib/mcollective/signer/choria.rb +185 -0
  96. data/lib/mcollective/ssl.rb +8 -6
  97. data/lib/mcollective/util.rb +58 -55
  98. data/lib/mcollective/util/bolt_support.rb +176 -0
  99. data/lib/mcollective/util/bolt_support/plan_runner.rb +167 -0
  100. data/lib/mcollective/util/bolt_support/task_result.rb +94 -0
  101. data/lib/mcollective/util/bolt_support/task_results.rb +128 -0
  102. data/lib/mcollective/util/choria.rb +946 -0
  103. data/lib/mcollective/util/indifferent_hash.rb +12 -0
  104. data/lib/mcollective/util/natswrapper.rb +242 -0
  105. data/lib/mcollective/util/playbook.rb +435 -0
  106. data/lib/mcollective/util/playbook/data_stores.rb +201 -0
  107. data/lib/mcollective/util/playbook/data_stores/base.rb +99 -0
  108. data/lib/mcollective/util/playbook/data_stores/consul_data_store.rb +88 -0
  109. data/lib/mcollective/util/playbook/data_stores/environment_data_store.rb +33 -0
  110. data/lib/mcollective/util/playbook/data_stores/etcd_data_store.rb +42 -0
  111. data/lib/mcollective/util/playbook/data_stores/file_data_store.rb +106 -0
  112. data/lib/mcollective/util/playbook/data_stores/shell_data_store.rb +103 -0
  113. data/lib/mcollective/util/playbook/inputs.rb +265 -0
  114. data/lib/mcollective/util/playbook/nodes.rb +207 -0
  115. data/lib/mcollective/util/playbook/nodes/mcollective_nodes.rb +86 -0
  116. data/lib/mcollective/util/playbook/nodes/pql_nodes.rb +40 -0
  117. data/lib/mcollective/util/playbook/nodes/shell_nodes.rb +55 -0
  118. data/lib/mcollective/util/playbook/nodes/terraform_nodes.rb +65 -0
  119. data/lib/mcollective/util/playbook/nodes/yaml_nodes.rb +47 -0
  120. data/lib/mcollective/util/playbook/playbook_logger.rb +47 -0
  121. data/lib/mcollective/util/playbook/puppet_logger.rb +51 -0
  122. data/lib/mcollective/util/playbook/report.rb +152 -0
  123. data/lib/mcollective/util/playbook/task_result.rb +55 -0
  124. data/lib/mcollective/util/playbook/tasks.rb +196 -0
  125. data/lib/mcollective/util/playbook/tasks/base.rb +45 -0
  126. data/lib/mcollective/util/playbook/tasks/graphite_event_task.rb +64 -0
  127. data/lib/mcollective/util/playbook/tasks/mcollective_task.rb +356 -0
  128. data/lib/mcollective/util/playbook/tasks/shell_task.rb +93 -0
  129. data/lib/mcollective/util/playbook/tasks/slack_task.rb +105 -0
  130. data/lib/mcollective/util/playbook/tasks/webhook_task.rb +136 -0
  131. data/lib/mcollective/util/playbook/template_util.rb +98 -0
  132. data/lib/mcollective/util/playbook/uses.rb +169 -0
  133. data/lib/mcollective/util/tasks_support.rb +751 -0
  134. data/lib/mcollective/util/tasks_support/cli.rb +260 -0
  135. data/lib/mcollective/util/tasks_support/default_formatter.rb +138 -0
  136. data/lib/mcollective/util/tasks_support/json_formatter.rb +108 -0
  137. data/lib/mcollective/validator.rb +6 -1
  138. data/lib/mcollective/validator/bolt_task_name_validator.ddl +7 -0
  139. data/lib/mcollective/validator/bolt_task_name_validator.rb +11 -0
  140. data/lib/mcollective/validator/length_validator.rb +1 -3
  141. metadata +65 -6
  142. data/lib/mcollective/application/describe_filter.rb +0 -87
  143. data/lib/mcollective/matcher.rb +0 -220
  144. data/lib/mcollective/matcher/parser.rb +0 -128
  145. data/lib/mcollective/matcher/scanner.rb +0 -241
@@ -0,0 +1,176 @@
1
+ require "mcollective"
2
+ require_relative "choria"
3
+ require_relative "playbook"
4
+
5
+ require_relative "bolt_support/task_result"
6
+ require_relative "bolt_support/task_results"
7
+ require_relative "bolt_support/plan_runner"
8
+
9
+ module MCollective
10
+ module Util
11
+ class BoltSupport
12
+ def choria
13
+ @_choria ||= Choria.new
14
+ end
15
+
16
+ # Converts the current Puppet loglevel to one we understand
17
+ #
18
+ # @return ["debug", "info", "warn", "error", "fatal"]
19
+ def self.loglevel
20
+ case Puppet::Util::Log.level
21
+ when :notice, :warning
22
+ "warn"
23
+ when :err
24
+ "error"
25
+ when :alert, :emerg, :crit
26
+ "fatal"
27
+ else
28
+ Puppet::Util::Log.level.to_s
29
+ end
30
+ end
31
+
32
+ # Configures MCollective and initialize the Bolt Support class
33
+ #
34
+ # @return [BoltSupport]
35
+ def self.init_choria
36
+ Config.instance.loadconfig(Util.config_file_for_user) unless Config.instance.configured
37
+
38
+ new
39
+ end
40
+
41
+ # Creates a configured instance of the Playbook
42
+ #
43
+ # @return [Playbook]
44
+ def playbook
45
+ @_playbook ||= begin
46
+ pb = Playbook.new(self.class.loglevel)
47
+ pb.logger = Playbook::Puppet_Logger
48
+ pb.set_logger_level
49
+ pb
50
+ end
51
+ end
52
+
53
+ def nodes
54
+ @_nodes ||= Playbook::Nodes.new(playbook)
55
+ end
56
+
57
+ # Discovers nodes using playbook node sets
58
+ #
59
+ # @param scope [Puppet::Parser::Scope] scope to log against
60
+ # @param type [String] a known node set type like `terraform`
61
+ # @param properties [Hash] properties valid for the node set type
62
+ def discover_nodes(scope, type, properties)
63
+ uses_properties = properties.delete("uses") || {}
64
+ playbook.logger.scope = scope
65
+ assign_playbook_name(scope)
66
+ playbook.uses.from_hash(uses_properties)
67
+
68
+ nodes.from_hash("task_nodes" => properties.merge(
69
+ "type" => type,
70
+ "uses" => uses_properties.keys
71
+ ))
72
+
73
+ nodes.prepare
74
+ nodes["task_nodes"]
75
+ end
76
+
77
+ # Retrieves a data item from a data store
78
+ #
79
+ # @param scope [Puppet::Parser::Scope] scope to log against
80
+ # @param item [String] the item to fetch
81
+ # @param properties [Hash] the data source properties
82
+ def data_read(scope, item, properties)
83
+ playbook.logger.scope = scope
84
+ assign_playbook_name(scope)
85
+ playbook.data_stores.from_hash("plan_store" => properties)
86
+ playbook.data_stores.prepare
87
+ playbook.data_stores.read("plan_store/%s" % item)
88
+ end
89
+
90
+ # Writes a value to a data store
91
+ #
92
+ # @param scope [Puppet::Parser::Scope] scope to log against
93
+ # @param item [String] the item to fetch
94
+ # @param value [String] the item to fetch
95
+ # @param properties [Hash] the data source properties
96
+ # @return [String] the data that was written
97
+ def data_write(scope, item, value, properties)
98
+ config = {"plan_store" => properties}
99
+
100
+ playbook.logger.scope = scope
101
+ assign_playbook_name(scope)
102
+ playbook.data_stores.from_hash(config)
103
+ playbook.data_stores.prepare
104
+ playbook.data_stores.write("plan_store/%s" % item, value)
105
+ end
106
+
107
+ # Performs a block within a lock in a data store
108
+ #
109
+ # @param scope [Puppet::Parser::Scope] scope to log against
110
+ # @param item [String] the lock key
111
+ # @param properties [Hash] the data source properties
112
+ def data_lock(scope, item, properties, &blk)
113
+ locked = false
114
+ lock_path = "plan_store/%s" % item
115
+ config = {"plan_store" => properties}
116
+
117
+ playbook.logger.scope = scope
118
+ assign_playbook_name(scope)
119
+ playbook.data_stores.from_hash(config)
120
+ playbook.data_stores.prepare
121
+
122
+ playbook.data_stores.lock(lock_path)
123
+ locked = true
124
+
125
+ yield
126
+ ensure
127
+ playbook.data_stores.release(lock_path) if locked
128
+ end
129
+
130
+ # Runs a playbook task and return execution results
131
+ #
132
+ # @param scope [Puppet::Parser::Scope] scope to log against
133
+ # @param type [String] the task type
134
+ # @param properties [Hash] properties passed to the task
135
+ # @return [BoltSupport::TaskResults]
136
+ def run_task(scope, type, properties)
137
+ task_properties = properties.reject {|k, _| k.start_with?("_") }
138
+ playbook.logger.scope = scope
139
+ assign_playbook_name(scope)
140
+
141
+ tasks = playbook.tasks.load_tasks([type => task_properties], "tasks")
142
+
143
+ playbook.tasks.run_task(tasks[0], "plan", false)
144
+
145
+ result = tasks[0][:result]
146
+ runner = tasks[0][:runner]
147
+
148
+ execution_result = runner.to_execution_result([result.success, result.msg, result.data])
149
+
150
+ results = execution_result.map do |node, result_properties|
151
+ TaskResult.new(node, JSON.parse(result_properties.to_json))
152
+ end
153
+
154
+ task_results = TaskResults.new(results, nil)
155
+ task_results.message = result.msg
156
+
157
+ return task_results if result.success
158
+ return task_results if properties.fetch("fail_ok", false)
159
+ return task_results if properties["_catch_errors"]
160
+
161
+ raise(result.msg)
162
+ end
163
+
164
+ # Assigns the playbook name based on the fact choria.plan
165
+ #
166
+ # @see PlanRunner#in_environment
167
+ def assign_playbook_name(scope)
168
+ return unless scope
169
+ return unless scope["facts"]["choria"]
170
+ return unless scope["facts"]["choria"]["playbook"]
171
+
172
+ playbook.metadata["name"] = scope["facts"]["choria"]["playbook"]
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,167 @@
1
+ require "puppet"
2
+ require "puppet_pal"
3
+ require "tmpdir"
4
+
5
+ module MCollective
6
+ module Util
7
+ class BoltSupport
8
+ class PlanRunner
9
+ def self.init_puppet
10
+ TaskResults.include_iterable
11
+ Puppet::Util::Log.newdestination(:console)
12
+ end
13
+
14
+ init_puppet
15
+
16
+ attr_reader :modulepath
17
+
18
+ # @param plan [String] the name of the plan to use
19
+ # @param tmpdir [String] the path to an already existing temporary directory
20
+ # @param modulepath [String,nil] a : seperated list of locations to look for modules, uses puppet basemodulepath if nil
21
+ # @param loglevel [debug, info, warn, err]
22
+ def initialize(plan, tmpdir, modulepath, loglevel)
23
+ @plan = plan
24
+ @loglevel = loglevel
25
+ @tmpdir = tmpdir
26
+
27
+ raise("A temporary directory could not be created") unless @tmpdir
28
+ raise("A temporary directory could not be created") unless File.directory?(@tmpdir)
29
+
30
+ @modulepath = modulepath
31
+
32
+ unless @modulepath
33
+ initialize_settings
34
+ @modulepath = Puppet.settings[:basemodulepath]
35
+ end
36
+
37
+ @modulepath = @modulepath.split(":")
38
+
39
+ Puppet[:log_level] = @loglevel
40
+ end
41
+
42
+ # Determines if the requested plan exist
43
+ #
44
+ # @return [Boolean]
45
+ def exist?
46
+ with_script_compiler do |compiler|
47
+ return !!compiler.plan_signature(@plan)
48
+ end
49
+ end
50
+
51
+ # Initialize Puppet to use the configured tmp dir
52
+ def puppet_cli_options
53
+ Puppet::Settings::REQUIRED_APP_SETTINGS.map do |setting|
54
+ "--%s %s" % [setting, @tmpdir]
55
+ end
56
+ end
57
+
58
+ # Retrieves the signature of a plan - its parameters and types
59
+ #
60
+ # NOTE: at present it's not possible to extract description or default values
61
+ #
62
+ # @return [Hash]
63
+ def plan_signature
64
+ with_script_compiler do |compiler|
65
+ sig = compiler.plan_signature(@plan)
66
+
67
+ raise("Cannot find playbook %s in %s" % [@plan, @modulepath.join(":")]) unless sig
68
+
69
+ sig.params_type.elements.map do |elem|
70
+ [elem.name, {
71
+ "type" => elem.value_type.to_s,
72
+ "required" => !elem.key_type.is_a?(Puppet::Pops::Types::POptionalType)
73
+ }]
74
+ end
75
+ end
76
+ end
77
+
78
+ # Yields a PAL script compiler in the temporary environment
79
+ def with_script_compiler(&block)
80
+ in_environment do |env|
81
+ env.with_script_compiler(&block)
82
+ end
83
+ end
84
+
85
+ # Facts to use in the environment
86
+ def facts
87
+ {
88
+ "choria" => {
89
+ "playbook" => @plan
90
+ }
91
+ }
92
+ end
93
+
94
+ def initialize_settings
95
+ Puppet.initialize_settings(puppet_cli_options) unless Puppet.settings.global_defaults_initialized?
96
+ end
97
+
98
+ # Sets up a temporary environment
99
+ def in_environment(&block)
100
+ initialize_settings
101
+
102
+ Puppet::Pal.in_tmp_environment("choria", :modulepath => @modulepath, :facts => facts, &block)
103
+ end
104
+
105
+ # Converts a Puppet type into something mcollective understands
106
+ #
107
+ # This is inevitably hacky by its nature, there is no way for me to
108
+ # parse the types. PAL might get some helpers for this but till then
109
+ # this is going to have to be best efforts.
110
+ #
111
+ # When there is a too complex situation users can always put in --input
112
+ # and some JSON to work around it until something better comes around
113
+ #
114
+ # @param type [String] a puppet type
115
+ # @return [Class, Boolean] The data type, if its an array input or not
116
+ def puppet_type_to_ruby(type)
117
+ array = false
118
+
119
+ type = $1 if type =~ /Optional\[(.+)/
120
+
121
+ if type =~ /Array\[(.+)/
122
+ type = $1
123
+ array = true
124
+ end
125
+
126
+ return [Numeric, array] if type =~ /Integer/
127
+ return [Numeric, array] if type =~ /Float/
128
+ return [Hash, array] if type =~ /Hash/
129
+ return [:boolean, array] if type =~ /Boolean/
130
+
131
+ [String, array]
132
+ end
133
+
134
+ def run!(params)
135
+ with_script_compiler do |compiler|
136
+ compiler.call_function("choria::run_playbook", @plan, params)
137
+ end
138
+ end
139
+
140
+ # Adds the CLI options for an application based on the playbook inputs
141
+ #
142
+ # @param application [MCollective::Application]
143
+ # @param set_required [Boolean]
144
+ def add_cli_options(application, set_required=false)
145
+ sig = plan_signature
146
+
147
+ return if sig.nil? || sig.empty?
148
+
149
+ sig.each do |name, details|
150
+ type, array = puppet_type_to_ruby(details["type"])
151
+
152
+ properties = {
153
+ :description => "Plan input property (%s)" % details["type"],
154
+ :arguments => "--%s %s" % [name.downcase, name.upcase],
155
+ :type => array ? :array : type
156
+ }
157
+
158
+ properties[:required] = true if details["required"] && set_required
159
+ properties[:arguments] = "--[no-]%s" % name.downcase if type == :boolean
160
+
161
+ application.class.option(name, properties)
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,94 @@
1
+ module MCollective
2
+ module Util
3
+ class BoltSupport
4
+ class TaskResult
5
+ attr_reader :host, :result
6
+
7
+ # Method used by Puppet to create the TaskResult from a hash
8
+ #
9
+ # @param hash [Hash] hash as prodused by various execution_result method
10
+ # @return [TaskResult]
11
+ def self.from_asserted_hash(hash)
12
+ new(hash.keys.first, hash.values.first)
13
+ end
14
+
15
+ # @param host [String] node name
16
+ # @param result [Hash] result value as produced by execution_result methods
17
+ def initialize(host, result)
18
+ @host = host
19
+ @result = result
20
+ end
21
+
22
+ def to_hash
23
+ {@host => @result}
24
+ end
25
+
26
+ def to_json(obj={})
27
+ to_hash.to_json(obj)
28
+ end
29
+
30
+ # A error object if this represents an error
31
+ #
32
+ # @return [Puppet::DataTypes::Error, nil]
33
+ def error
34
+ if @result["error"]
35
+ if defined?(Puppet::DataTypes::Error)
36
+ Puppet::DataTypes::Error.from_asserted_hash(@result["error"])
37
+ else
38
+ @result["error"]
39
+ end
40
+ end
41
+ end
42
+
43
+ # The type of task that created this result
44
+ #
45
+ # @return String examples like mcollective, data etc
46
+ def type
47
+ @result["type"]
48
+ end
49
+
50
+ # If this task result represents a succesful task
51
+ #
52
+ # This supposed fail_ok, any task with that set will be considered passed
53
+ #
54
+ # @return Boolean
55
+ def ok
56
+ return true if @result["fail_ok"]
57
+
58
+ !@result.include?("error")
59
+ end
60
+ alias :ok? :ok
61
+
62
+ def fail_ok
63
+ @result["fail_ok"]
64
+ end
65
+ alias :fail_ok? :fail_ok
66
+
67
+ # Access the value data embedded in the result
68
+ #
69
+ # @param key [String] data to access
70
+ # @return [Object] the specifiv item in the value hash or the raw value
71
+ def [](key)
72
+ return @result["value"] unless @result["value"].is_a?(Hash)
73
+
74
+ @result["value"][key]
75
+ end
76
+
77
+ # Access the value data in raw form
78
+ #
79
+ # @return [Object] whatever value the task produced
80
+ def value
81
+ @result["value"]
82
+ end
83
+
84
+ def to_s
85
+ if Object.const_defined?(:Puppet)
86
+ Puppet::Pops::Types::StringConverter.convert(self, "%p")
87
+ else
88
+ super
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,128 @@
1
+ module MCollective
2
+ module Util
3
+ class BoltSupport
4
+ class TaskResults
5
+ attr_reader :results, :exception
6
+ attr_writer :message
7
+
8
+ include Enumerable
9
+
10
+ def self.include_iterable
11
+ include(Puppet::Pops::Types::Iterable)
12
+ include(Puppet::Pops::Types::IteratorProducer)
13
+ end
14
+
15
+ # Method used by Puppet to create the TaskResults from a array
16
+ #
17
+ # @param results [Array<TaskResult>] hash as prodused by various execution_result method
18
+ # @return [TaskResults]
19
+ def self.from_asserted_hash(results, exception=nil)
20
+ new(results, exception)
21
+ end
22
+
23
+ # @param results [Array<TaskResult>]
24
+ def initialize(results, exception=nil)
25
+ @results = results
26
+ @exception = exception
27
+ end
28
+
29
+ def to_json(obj={})
30
+ @results.to_json(obj)
31
+ end
32
+
33
+ # Iterate over all results
34
+ #
35
+ # @yield [TaskResult]
36
+ def each(&block)
37
+ @results.each(&block)
38
+ end
39
+
40
+ # Set of all the results that are errors regardless of fail_ok
41
+ #
42
+ # @return [TaskResults]
43
+ def error_set
44
+ TaskResults.new(@results.select(&:error))
45
+ end
46
+
47
+ # Set of all the results that are ok regardless of fail_ok
48
+ #
49
+ # @return [TaskResults]
50
+ def ok_set
51
+ TaskResults.new(@results.reject(&:error))
52
+ end
53
+
54
+ # Determines if all results are ok, considers fail_ok
55
+ #
56
+ # @return [Boolean]
57
+ def ok
58
+ @results.all?(&:ok)
59
+ end
60
+ alias :ok? :ok
61
+
62
+ def fail_ok
63
+ @results.all?(&:fail_ok)
64
+ end
65
+ alias :fail_ok? :fail_ok
66
+
67
+ def message
68
+ return exception.to_s if exception
69
+
70
+ @message
71
+ end
72
+
73
+ # List of node names for all results
74
+ #
75
+ # @return [Array<String>]
76
+ def hosts
77
+ @results.map(&:host)
78
+ end
79
+
80
+ # First result in the set
81
+ #
82
+ # @return [TaskResult]
83
+ def first
84
+ @results.first
85
+ end
86
+
87
+ # Finds a result by name
88
+ #
89
+ # @param host [String] node hostname
90
+ # @return [TaskResult,nil]
91
+ def find(host)
92
+ @results.find {|r| r.host == host}
93
+ end
94
+
95
+ # Determines if the resultset is empty
96
+ #
97
+ # @return [Boolean]
98
+ def empty
99
+ @results.empty?
100
+ end
101
+ alias :empty? :empty
102
+
103
+ # Determines the count of results in the set
104
+ #
105
+ # @return [Integer]
106
+ def count
107
+ @results.size
108
+ end
109
+
110
+ def to_s
111
+ if Object.const_defined?(:Puppet)
112
+ Puppet::Pops::Types::StringConverter.convert(self, "%p")
113
+ else
114
+ super
115
+ end
116
+ end
117
+
118
+ def iterator
119
+ if Object.const_defined?(:Puppet) && Puppet.const_defined?(:Pops) && self.class.included_modules.include?(Puppet::Pops::Types::Iterable)
120
+ return Puppet::Pops::Types::Iterable.on(@results, TaskResult)
121
+ end
122
+
123
+ raise(NotImplementedError, "iterator requires puppet code to be loaded.")
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end