choria-mcorpc-support 2.20.8 → 2.23.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mcollective.rb +1 -1
- data/lib/mcollective/agent/bolt_tasks.ddl +235 -0
- data/lib/mcollective/agent/bolt_tasks.json +347 -0
- data/lib/mcollective/agent/bolt_tasks.rb +176 -0
- data/lib/mcollective/agent/choria_util.ddl +152 -0
- data/lib/mcollective/agent/choria_util.json +244 -0
- data/lib/mcollective/agent/rpcutil.ddl +7 -3
- data/lib/mcollective/agent/rpcutil.json +333 -0
- data/lib/mcollective/agent/scout.ddl +169 -0
- data/lib/mcollective/agent/scout.json +224 -0
- data/lib/mcollective/agents.rb +7 -6
- data/lib/mcollective/aggregate.rb +4 -4
- data/lib/mcollective/aggregate/average.rb +2 -2
- data/lib/mcollective/aggregate/base.rb +2 -2
- data/lib/mcollective/aggregate/result.rb +3 -3
- data/lib/mcollective/aggregate/result/collection_result.rb +2 -2
- data/lib/mcollective/aggregate/result/numeric_result.rb +2 -2
- data/lib/mcollective/aggregate/sum.rb +2 -2
- data/lib/mcollective/aggregate/summary.rb +3 -4
- data/lib/mcollective/application.rb +57 -21
- data/lib/mcollective/application/choria.rb +249 -0
- data/lib/mcollective/application/completion.rb +6 -6
- data/lib/mcollective/application/describe_filter.rb +20 -20
- data/lib/mcollective/application/facts.rb +19 -11
- data/lib/mcollective/application/federation.rb +239 -0
- data/lib/mcollective/application/find.rb +4 -4
- data/lib/mcollective/application/help.rb +3 -3
- data/lib/mcollective/application/inventory.rb +3 -341
- data/lib/mcollective/application/ping.rb +3 -77
- data/lib/mcollective/application/playbook.rb +207 -0
- data/lib/mcollective/application/plugin.rb +106 -106
- data/lib/mcollective/application/rpc.rb +3 -108
- data/lib/mcollective/application/tasks.rb +416 -0
- data/lib/mcollective/applications.rb +11 -10
- data/lib/mcollective/audit/choria.rb +33 -0
- data/lib/mcollective/cache.rb +2 -4
- data/lib/mcollective/client.rb +11 -10
- data/lib/mcollective/config.rb +21 -34
- data/lib/mcollective/connector/base.rb +2 -1
- data/lib/mcollective/connector/nats.ddl +9 -0
- data/lib/mcollective/connector/nats.rb +450 -0
- data/lib/mcollective/data.rb +8 -3
- data/lib/mcollective/data/agent_data.rb +1 -1
- data/lib/mcollective/data/base.rb +6 -5
- data/lib/mcollective/data/bolt_task_data.ddl +90 -0
- data/lib/mcollective/data/bolt_task_data.rb +32 -0
- data/lib/mcollective/data/collective_data.rb +1 -1
- data/lib/mcollective/data/fact_data.rb +6 -6
- data/lib/mcollective/data/fstat_data.rb +2 -4
- data/lib/mcollective/data/result.rb +7 -2
- data/lib/mcollective/ddl/agentddl.rb +5 -17
- data/lib/mcollective/ddl/base.rb +11 -14
- data/lib/mcollective/discovery.rb +12 -26
- data/lib/mcollective/discovery/choria.ddl +11 -0
- data/lib/mcollective/discovery/choria.rb +223 -0
- data/lib/mcollective/discovery/flatfile.rb +7 -8
- data/lib/mcollective/discovery/mc.rb +2 -2
- data/lib/mcollective/discovery/stdin.rb +17 -18
- data/lib/mcollective/exceptions.rb +13 -0
- data/lib/mcollective/facts/base.rb +9 -9
- data/lib/mcollective/facts/yaml_facts.rb +12 -12
- data/lib/mcollective/generators.rb +3 -3
- data/lib/mcollective/generators/agent_generator.rb +3 -4
- data/lib/mcollective/generators/base.rb +14 -15
- data/lib/mcollective/generators/data_generator.rb +5 -6
- data/lib/mcollective/log.rb +2 -2
- data/lib/mcollective/logger/base.rb +3 -2
- data/lib/mcollective/logger/console_logger.rb +10 -10
- data/lib/mcollective/logger/file_logger.rb +7 -7
- data/lib/mcollective/logger/syslog_logger.rb +11 -15
- data/lib/mcollective/matcher.rb +14 -14
- data/lib/mcollective/matcher/parser.rb +31 -41
- data/lib/mcollective/matcher/scanner.rb +69 -74
- data/lib/mcollective/message.rb +10 -17
- data/lib/mcollective/monkey_patches.rb +2 -4
- data/lib/mcollective/optionparser.rb +1 -0
- data/lib/mcollective/pluginmanager.rb +3 -5
- data/lib/mcollective/pluginpackager.rb +1 -3
- data/lib/mcollective/pluginpackager/agent_definition.rb +10 -11
- data/lib/mcollective/pluginpackager/forge_packager.rb +7 -9
- data/lib/mcollective/pluginpackager/standard_definition.rb +1 -2
- data/lib/mcollective/registration/base.rb +18 -16
- data/lib/mcollective/rpc.rb +2 -4
- data/lib/mcollective/rpc/actionrunner.rb +16 -18
- data/lib/mcollective/rpc/agent.rb +26 -43
- data/lib/mcollective/rpc/audit.rb +1 -0
- data/lib/mcollective/rpc/client.rb +67 -85
- data/lib/mcollective/rpc/helpers.rb +55 -62
- data/lib/mcollective/rpc/progress.rb +2 -2
- data/lib/mcollective/rpc/reply.rb +17 -19
- data/lib/mcollective/rpc/request.rb +7 -5
- data/lib/mcollective/rpc/result.rb +6 -8
- data/lib/mcollective/rpc/stats.rb +49 -58
- data/lib/mcollective/security/base.rb +29 -36
- data/lib/mcollective/security/choria.rb +765 -0
- data/lib/mcollective/shell.rb +9 -4
- data/lib/mcollective/signer/base.rb +28 -0
- data/lib/mcollective/signer/choria.rb +185 -0
- data/lib/mcollective/ssl.rb +8 -6
- data/lib/mcollective/util.rb +58 -55
- data/lib/mcollective/util/bolt_support.rb +176 -0
- data/lib/mcollective/util/bolt_support/plan_runner.rb +167 -0
- data/lib/mcollective/util/bolt_support/task_result.rb +94 -0
- data/lib/mcollective/util/bolt_support/task_results.rb +128 -0
- data/lib/mcollective/util/choria.rb +1103 -0
- data/lib/mcollective/util/indifferent_hash.rb +12 -0
- data/lib/mcollective/util/natswrapper.rb +242 -0
- data/lib/mcollective/util/playbook.rb +435 -0
- data/lib/mcollective/util/playbook/data_stores.rb +201 -0
- data/lib/mcollective/util/playbook/data_stores/base.rb +99 -0
- data/lib/mcollective/util/playbook/data_stores/consul_data_store.rb +88 -0
- data/lib/mcollective/util/playbook/data_stores/environment_data_store.rb +33 -0
- data/lib/mcollective/util/playbook/data_stores/etcd_data_store.rb +42 -0
- data/lib/mcollective/util/playbook/data_stores/file_data_store.rb +106 -0
- data/lib/mcollective/util/playbook/data_stores/shell_data_store.rb +103 -0
- data/lib/mcollective/util/playbook/inputs.rb +265 -0
- data/lib/mcollective/util/playbook/nodes.rb +207 -0
- data/lib/mcollective/util/playbook/nodes/mcollective_nodes.rb +86 -0
- data/lib/mcollective/util/playbook/nodes/pql_nodes.rb +40 -0
- data/lib/mcollective/util/playbook/nodes/shell_nodes.rb +55 -0
- data/lib/mcollective/util/playbook/nodes/terraform_nodes.rb +65 -0
- data/lib/mcollective/util/playbook/nodes/yaml_nodes.rb +47 -0
- data/lib/mcollective/util/playbook/playbook_logger.rb +47 -0
- data/lib/mcollective/util/playbook/puppet_logger.rb +51 -0
- data/lib/mcollective/util/playbook/report.rb +152 -0
- data/lib/mcollective/util/playbook/task_result.rb +55 -0
- data/lib/mcollective/util/playbook/tasks.rb +196 -0
- data/lib/mcollective/util/playbook/tasks/base.rb +45 -0
- data/lib/mcollective/util/playbook/tasks/graphite_event_task.rb +64 -0
- data/lib/mcollective/util/playbook/tasks/mcollective_task.rb +356 -0
- data/lib/mcollective/util/playbook/tasks/shell_task.rb +93 -0
- data/lib/mcollective/util/playbook/tasks/slack_task.rb +105 -0
- data/lib/mcollective/util/playbook/tasks/webhook_task.rb +136 -0
- data/lib/mcollective/util/playbook/template_util.rb +98 -0
- data/lib/mcollective/util/playbook/uses.rb +169 -0
- data/lib/mcollective/util/tasks_support.rb +733 -0
- data/lib/mcollective/util/tasks_support/cli.rb +260 -0
- data/lib/mcollective/util/tasks_support/default_formatter.rb +138 -0
- data/lib/mcollective/util/tasks_support/json_formatter.rb +108 -0
- data/lib/mcollective/validator.rb +8 -3
- data/lib/mcollective/validator/bolt_task_name_validator.ddl +7 -0
- data/lib/mcollective/validator/bolt_task_name_validator.rb +11 -0
- data/lib/mcollective/validator/length_validator.rb +1 -3
- data/lib/mcollective/validator/typecheck_validator.rb +4 -0
- metadata +67 -4
@@ -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
|