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.
- checksums.yaml +4 -4
- data/lib/mcollective.rb +1 -2
- data/lib/mcollective/agent/bolt_tasks.ddl +253 -0
- data/lib/mcollective/agent/bolt_tasks.json +365 -0
- data/lib/mcollective/agent/bolt_tasks.rb +178 -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 +8 -4
- 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 +189 -0
- data/lib/mcollective/application/completion.rb +6 -6
- data/lib/mcollective/application/facts.rb +11 -11
- data/lib/mcollective/application/federation.rb +237 -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 +5 -51
- 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 +425 -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 +10 -13
- data/lib/mcollective/discovery.rb +24 -39
- 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/message.rb +8 -39
- data/lib/mcollective/monkey_patches.rb +2 -4
- data/lib/mcollective/optionparser.rb +2 -1
- data/lib/mcollective/pluginmanager.rb +3 -5
- data/lib/mcollective/pluginpackager.rb +1 -3
- data/lib/mcollective/pluginpackager/agent_definition.rb +3 -8
- 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 +13 -56
- 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 +946 -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 +751 -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 +6 -1
- 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
- metadata +65 -6
- data/lib/mcollective/application/describe_filter.rb +0 -87
- data/lib/mcollective/matcher.rb +0 -220
- data/lib/mcollective/matcher/parser.rb +0 -128
- data/lib/mcollective/matcher/scanner.rb +0 -241
|
@@ -1,111 +1,6 @@
|
|
|
1
|
-
class MCollective::Application::Rpc<MCollective::Application
|
|
1
|
+
class MCollective::Application::Rpc < MCollective::Application # rubocop:disable Style/ClassAndModuleChildren
|
|
2
2
|
description "Generic RPC agent client application"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
option :show_results,
|
|
8
|
-
:description => "Do not process results, just send request",
|
|
9
|
-
:arguments => ["--no-results", "--nr"],
|
|
10
|
-
:default => true,
|
|
11
|
-
:type => :bool
|
|
12
|
-
|
|
13
|
-
option :agent,
|
|
14
|
-
:description => "Agent to call",
|
|
15
|
-
:arguments => ["-a", "--agent AGENT"]
|
|
16
|
-
|
|
17
|
-
option :action,
|
|
18
|
-
:description => "Action to call",
|
|
19
|
-
:arguments => ["--action ACTION"]
|
|
20
|
-
|
|
21
|
-
option :arguments,
|
|
22
|
-
:description => "Arguments to pass to agent",
|
|
23
|
-
:arguments => ["--arg", "--argument ARGUMENT"],
|
|
24
|
-
:type => :array,
|
|
25
|
-
:default => [],
|
|
26
|
-
:validate => Proc.new {|val| val.match(/^(.+?)=(.+)$/) ? true : "Could not parse --arg #{val} should be of the form key=val" }
|
|
27
|
-
|
|
28
|
-
def post_option_parser(configuration)
|
|
29
|
-
# handle the alternative format that optparse cant parse
|
|
30
|
-
unless (configuration.include?(:agent) && configuration.include?(:action))
|
|
31
|
-
if ARGV.length >= 2
|
|
32
|
-
configuration[:agent] = ARGV[0]
|
|
33
|
-
ARGV.delete_at(0)
|
|
34
|
-
|
|
35
|
-
configuration[:action] = ARGV[0]
|
|
36
|
-
ARGV.delete_at(0)
|
|
37
|
-
|
|
38
|
-
ARGV.each do |v|
|
|
39
|
-
if v =~ /^(.+?)=(.+)$/
|
|
40
|
-
configuration[:arguments] = [] unless configuration.include?(:arguments)
|
|
41
|
-
configuration[:arguments] << v
|
|
42
|
-
else
|
|
43
|
-
STDERR.puts("Could not parse --arg #{v}")
|
|
44
|
-
exit(1)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
else
|
|
48
|
-
STDERR.puts("No agent, action and arguments specified")
|
|
49
|
-
exit(1)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# convert arguments to symbols for keys to comply with simplerpc conventions
|
|
54
|
-
args = configuration[:arguments].clone
|
|
55
|
-
configuration[:arguments] = {}
|
|
56
|
-
|
|
57
|
-
args.each do |v|
|
|
58
|
-
if v =~ /^(.+?)=(.+)$/
|
|
59
|
-
configuration[:arguments][$1.to_sym] = $2
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def string_to_ddl_type(arguments, ddl)
|
|
65
|
-
return if ddl.empty?
|
|
66
|
-
|
|
67
|
-
arguments.keys.each do |key|
|
|
68
|
-
if ddl[:input].keys.include?(key)
|
|
69
|
-
case ddl[:input][key][:type]
|
|
70
|
-
when :boolean
|
|
71
|
-
arguments[key] = MCollective::DDL.string_to_boolean(arguments[key])
|
|
72
|
-
|
|
73
|
-
when :number, :integer, :float
|
|
74
|
-
arguments[key] = MCollective::DDL.string_to_number(arguments[key])
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def main
|
|
81
|
-
mc = rpcclient(configuration[:agent])
|
|
82
|
-
|
|
83
|
-
mc.agent_filter(configuration[:agent])
|
|
84
|
-
|
|
85
|
-
string_to_ddl_type(configuration[:arguments], mc.ddl.action_interface(configuration[:action])) if mc.ddl
|
|
86
|
-
|
|
87
|
-
mc.validate_request(configuration[:action], configuration[:arguments])
|
|
88
|
-
|
|
89
|
-
if mc.reply_to
|
|
90
|
-
configuration[:arguments][:process_results] = true
|
|
91
|
-
|
|
92
|
-
puts "Request sent with id: " + mc.send(configuration[:action], configuration[:arguments]) + " replies to #{mc.reply_to}"
|
|
93
|
-
elsif !configuration[:show_results]
|
|
94
|
-
configuration[:arguments][:process_results] = false
|
|
95
|
-
|
|
96
|
-
puts "Request sent with id: " + mc.send(configuration[:action], configuration[:arguments])
|
|
97
|
-
else
|
|
98
|
-
discover_args = {:verbose => true}
|
|
99
|
-
|
|
100
|
-
mc.detect_and_set_stdin_discovery
|
|
101
|
-
|
|
102
|
-
mc.discover discover_args
|
|
103
|
-
|
|
104
|
-
printrpc mc.send(configuration[:action], configuration[:arguments])
|
|
105
|
-
|
|
106
|
-
printrpcstats :summarize => true, :caption => "#{configuration[:agent]}##{configuration[:action]} call stats" if mc.discover.size > 0
|
|
107
|
-
|
|
108
|
-
halt mc.stats
|
|
109
|
-
end
|
|
110
|
-
end
|
|
4
|
+
external(:command => "choria", :args => ["req"])
|
|
5
|
+
external_help(:command => "choria", :args => ["req", "--help"])
|
|
111
6
|
end
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
class Application
|
|
3
|
+
class Tasks < Application
|
|
4
|
+
description "Puppet Task Orchestrator"
|
|
5
|
+
|
|
6
|
+
usage <<-USAGE
|
|
7
|
+
|
|
8
|
+
mco tasks [--detail]
|
|
9
|
+
mco tasks <TASK NAME>
|
|
10
|
+
mco tasks run <TASK NAME> [OPTIONS]
|
|
11
|
+
mco tasks status <REQUEST> [FLAGS]
|
|
12
|
+
|
|
13
|
+
The Task Orchestrator is designed to provide a consistent
|
|
14
|
+
management environment for Puppet Tasks.
|
|
15
|
+
|
|
16
|
+
It will download tasks from your Puppet Server onto all nodes
|
|
17
|
+
and after verifying they were able to correctly download the
|
|
18
|
+
same task across the entire fleet will run the task.
|
|
19
|
+
|
|
20
|
+
Tasks are run in the background, the CLI can wait for up to 60
|
|
21
|
+
seconds for your task to complete and show the status or you
|
|
22
|
+
can use the status comment to review a completed task later.
|
|
23
|
+
USAGE
|
|
24
|
+
|
|
25
|
+
exclude_argument_sections "rpc"
|
|
26
|
+
|
|
27
|
+
def post_option_parser(configuration)
|
|
28
|
+
configuration[:__command] = ARGV.shift || "list"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def list_options
|
|
32
|
+
self.class.option :__detail,
|
|
33
|
+
:arguments => ["--detail"],
|
|
34
|
+
:description => "Show command descriptions",
|
|
35
|
+
:default => false,
|
|
36
|
+
:type => :boolean
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def status_options
|
|
40
|
+
application_options[:usage].clear
|
|
41
|
+
|
|
42
|
+
self.class.usage <<-USAGE
|
|
43
|
+
|
|
44
|
+
mco tasks status <REQUEST> [FLAGS]
|
|
45
|
+
|
|
46
|
+
Retrieves the status for a task you previously requested. It can be running or completed.
|
|
47
|
+
|
|
48
|
+
By default only failed exuecutions are shown, use --verbose to see them all.
|
|
49
|
+
|
|
50
|
+
USAGE
|
|
51
|
+
|
|
52
|
+
self.class.option :__summary,
|
|
53
|
+
:arguments => ["--summary"],
|
|
54
|
+
:description => "Only show a overall summary of the task",
|
|
55
|
+
:default => false,
|
|
56
|
+
:type => :boolean
|
|
57
|
+
|
|
58
|
+
self.class.option :__metadata,
|
|
59
|
+
:arguments => ["--metadata"],
|
|
60
|
+
:description => "Only show task metadata for each node",
|
|
61
|
+
:default => false,
|
|
62
|
+
:type => :boolean
|
|
63
|
+
|
|
64
|
+
self.class.option :__json_format,
|
|
65
|
+
:arguments => ["--json"],
|
|
66
|
+
:description => "Display results in JSON format",
|
|
67
|
+
:default => false,
|
|
68
|
+
:type => :boolean
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def run_options # rubocop:disable Metrics/MethodLength
|
|
72
|
+
application_options[:usage].clear
|
|
73
|
+
|
|
74
|
+
self.class.usage <<-USAGE
|
|
75
|
+
|
|
76
|
+
mco tasks run <TASK NAME> [OPTIONS]
|
|
77
|
+
|
|
78
|
+
Runs a task in the background and wait up to 50 seconds for it to complete.
|
|
79
|
+
|
|
80
|
+
Task inputs are handled using --argument=value for basic String, Numeric and Boolean
|
|
81
|
+
types, others can be passed using --input
|
|
82
|
+
|
|
83
|
+
Input can also be read from a file using "--input @file.json" or "--input @file.yaml".
|
|
84
|
+
|
|
85
|
+
For complex data types like Hashes, Arrays or Variants you have to supply input
|
|
86
|
+
as YAML or JSON.
|
|
87
|
+
|
|
88
|
+
Once a task is run the task ID will be displayed which can later be used with
|
|
89
|
+
the "mco tasks status" command to extract results.
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
|
|
93
|
+
Run myapp::upgrade task in the background and wait for it to complete:
|
|
94
|
+
|
|
95
|
+
mco tasks run myapp::upgrade --version 1.0.0
|
|
96
|
+
|
|
97
|
+
Run myapp::upgrade task in the background and return immediately:
|
|
98
|
+
|
|
99
|
+
mco tasks run myapp::upgrade --version 1.0.0 --background
|
|
100
|
+
|
|
101
|
+
Supply complex data input to the task:
|
|
102
|
+
|
|
103
|
+
Should input be given on both the CLI arguments and a file
|
|
104
|
+
the CLI arguments will override the file
|
|
105
|
+
|
|
106
|
+
mco tasks run myapp::upgrade --input @input.json
|
|
107
|
+
mco tasks run myapp::upgrade --input @input.yaml
|
|
108
|
+
mco tasks run myapp::upgrade --version 1.0.0 --input \\
|
|
109
|
+
'{"source": {
|
|
110
|
+
"url": "http://repo/archive-1.0.0.tgz",
|
|
111
|
+
"hash": "68b329da9893e34099c7d8ad5cb9c940"}}'
|
|
112
|
+
|
|
113
|
+
USAGE
|
|
114
|
+
|
|
115
|
+
task = ARGV[1]
|
|
116
|
+
|
|
117
|
+
abort("Please specify a task to run") unless task
|
|
118
|
+
|
|
119
|
+
cli.create_task_options(task, "production", self)
|
|
120
|
+
|
|
121
|
+
self.class.option :__summary,
|
|
122
|
+
:arguments => ["--summary"],
|
|
123
|
+
:description => "Only show a overall summary of the task",
|
|
124
|
+
:default => false,
|
|
125
|
+
:type => :boolean
|
|
126
|
+
|
|
127
|
+
self.class.option :__background,
|
|
128
|
+
:arguments => ["--background"],
|
|
129
|
+
:description => "Do not wait for the task to complete",
|
|
130
|
+
:default => false,
|
|
131
|
+
:type => :boolean
|
|
132
|
+
|
|
133
|
+
self.class.option :__json_input,
|
|
134
|
+
:arguments => ["--input INPUT"],
|
|
135
|
+
:description => "JSON input to pass to the task",
|
|
136
|
+
:required => false,
|
|
137
|
+
:type => String
|
|
138
|
+
|
|
139
|
+
self.class.option :__batch_size,
|
|
140
|
+
:arguments => ["--batch SIZE"],
|
|
141
|
+
:description => "Run tasks on nodes in batches",
|
|
142
|
+
:required => false,
|
|
143
|
+
:type => String
|
|
144
|
+
|
|
145
|
+
self.class.option :__batch_sleep,
|
|
146
|
+
:arguments => ["--batch-sleep SECONDS"],
|
|
147
|
+
:description => "Time to sleep between invocations of batches of nodes",
|
|
148
|
+
:required => false,
|
|
149
|
+
:default => 1,
|
|
150
|
+
:type => Integer
|
|
151
|
+
|
|
152
|
+
self.class.option :__run_as,
|
|
153
|
+
:arguments => ["--run-as USERNAME"],
|
|
154
|
+
:description => "Run task as user USERNAME",
|
|
155
|
+
:required => false,
|
|
156
|
+
:default => nil,
|
|
157
|
+
:type => String
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def say(msg="")
|
|
161
|
+
puts(msg) unless configuration[:__json_format]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def run_command
|
|
165
|
+
task = ARGV.shift
|
|
166
|
+
|
|
167
|
+
input = cli.task_input(configuration)
|
|
168
|
+
|
|
169
|
+
say("Retrieving task metadata for task %s from the Puppet Server" % task)
|
|
170
|
+
|
|
171
|
+
begin
|
|
172
|
+
meta = cli.task_metadata(task, "production")
|
|
173
|
+
rescue
|
|
174
|
+
abort($!.to_s)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
cli.transform_hash_strings(meta, input)
|
|
178
|
+
cli.validate_task_input(task, meta, input)
|
|
179
|
+
|
|
180
|
+
say("Attempting to download and run task %s on %d nodes" % [Util.colorize(:bold, task), bolt_tasks.discover.size])
|
|
181
|
+
say
|
|
182
|
+
|
|
183
|
+
download_files(task, meta["files"])
|
|
184
|
+
|
|
185
|
+
request = {
|
|
186
|
+
:task => task,
|
|
187
|
+
:files => meta["files"].to_json
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
request[:run_as] = configuration[:__run_as] if configuration[:__run_as]
|
|
191
|
+
|
|
192
|
+
request[:input] = input.to_json if input
|
|
193
|
+
|
|
194
|
+
if configuration[:__background]
|
|
195
|
+
puts("Starting task %s in the background" % [Util.colorize(:bold, task)])
|
|
196
|
+
|
|
197
|
+
if configuration[:__batch_size]
|
|
198
|
+
bolt_tasks.batch_size = configuration[:__batch_size]
|
|
199
|
+
bolt_tasks.batch_sleep_time = configuration[:__batch_sleep]
|
|
200
|
+
bolt_tasks.progress = true
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
printrpc bolt_tasks.run_no_wait(request)
|
|
204
|
+
printrpcstats
|
|
205
|
+
|
|
206
|
+
if bolt_tasks.stats.okcount > 0
|
|
207
|
+
puts
|
|
208
|
+
puts("Request detailed status for the task using 'mco tasks status %s'" % [Util.colorize(:bold, bolt_tasks.stats.requestid)])
|
|
209
|
+
end
|
|
210
|
+
else
|
|
211
|
+
say("Running task %s and waiting up to %s seconds for it to complete" % [
|
|
212
|
+
Util.colorize(:bold, task),
|
|
213
|
+
Util.colorize(:bold, bolt_tasks.ddl.meta[:timeout])
|
|
214
|
+
])
|
|
215
|
+
|
|
216
|
+
request_and_report(:run_and_wait, request)
|
|
217
|
+
end
|
|
218
|
+
ensure
|
|
219
|
+
reset_client!
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def download_files(task, files)
|
|
223
|
+
bolt_tasks.batch_size = 50
|
|
224
|
+
bolt_tasks.batch_sleep_time = 1
|
|
225
|
+
|
|
226
|
+
failed = false
|
|
227
|
+
|
|
228
|
+
downloads = []
|
|
229
|
+
cnt = bolt_tasks.discover.size
|
|
230
|
+
idx = 0
|
|
231
|
+
|
|
232
|
+
bolt_tasks.download(:environment => "production", :task => task, :files => files.to_json) do |_, s|
|
|
233
|
+
unless configuration[:__json_format]
|
|
234
|
+
print(cli.twirl("Downloading and verifying %d file(s) from the Puppet Server to all nodes:" % [files.size], cnt, idx + 1))
|
|
235
|
+
puts if cnt == idx + 1
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
idx += 1
|
|
239
|
+
downloads << s
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
downloads.select {|d| d[:statuscode] > 0}.each_with_index do |download, i|
|
|
243
|
+
failed = true
|
|
244
|
+
puts if i == 0
|
|
245
|
+
puts(" %s: %s" % [Util.colorize(:red, "Could not download files onto %s" % download[:sender]), download[:statusmsg]])
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
unless bolt_tasks.stats.noresponsefrom.empty?
|
|
249
|
+
puts
|
|
250
|
+
puts bolt_tasks.stats.no_response_report
|
|
251
|
+
failed = true
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
if failed
|
|
255
|
+
puts
|
|
256
|
+
abort("Could not download the task %s onto all nodes" % task)
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def status_command
|
|
261
|
+
taskid = ARGV.shift
|
|
262
|
+
|
|
263
|
+
abort("Please specify a task id to display") unless taskid
|
|
264
|
+
|
|
265
|
+
if configuration[:__metadata]
|
|
266
|
+
say("Requesting task metadata for request %s" % Util.colorize(:bold, taskid)) unless options[:verbose]
|
|
267
|
+
|
|
268
|
+
bolt_tasks.task_status(:task_id => taskid).each do |status|
|
|
269
|
+
cli.print_result_metadata(status)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
cli.print_rpc_stats(bolt_tasks.stats)
|
|
273
|
+
else
|
|
274
|
+
say("Requesting task status for request %s, showing failures only pass --verbose for all output" % Util.colorize(:bold, taskid)) unless options[:verbose]
|
|
275
|
+
|
|
276
|
+
request_and_report(:task_status, {:task_id => taskid}, taskid)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def request_and_report(action, arguments, taskid=nil) # rubocop:disable Metrics/MethodLength
|
|
281
|
+
task_not_known_nodes = 0
|
|
282
|
+
wrapper_failure = 0
|
|
283
|
+
completed_nodes = 0
|
|
284
|
+
running_nodes = 0
|
|
285
|
+
runtime = 0.0
|
|
286
|
+
success_nodes = 0
|
|
287
|
+
fail_nodes = 0
|
|
288
|
+
progress = configuration[:__summary] || configuration[:__batch_size] ? RPC::Progress.new : nil
|
|
289
|
+
cnt = 0
|
|
290
|
+
expected = bolt_tasks.discover.size
|
|
291
|
+
task_names = []
|
|
292
|
+
callers = []
|
|
293
|
+
|
|
294
|
+
if configuration[:__batch_size]
|
|
295
|
+
bolt_tasks.batch_size = configuration[:__batch_size]
|
|
296
|
+
bolt_tasks.batch_sleep_time = configuration[:__batch_sleep]
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
say
|
|
300
|
+
|
|
301
|
+
bolt_tasks.send(action, arguments) do |_, reply|
|
|
302
|
+
status = reply[:data]
|
|
303
|
+
|
|
304
|
+
if reply[:statuscode] == 3
|
|
305
|
+
fail_nodes += 1
|
|
306
|
+
task_not_known_nodes += 1
|
|
307
|
+
elsif [-1, 0].include?(status[:exitcode])
|
|
308
|
+
status[:completed] ? completed_nodes += 1 : running_nodes += 1
|
|
309
|
+
runtime += status[:runtime]
|
|
310
|
+
reply[:statuscode] == 0 ? success_nodes += 1 : fail_nodes += 1
|
|
311
|
+
elsif reply[:statuscode] == 5
|
|
312
|
+
wrapper_failure += 1
|
|
313
|
+
fail_nodes += 1
|
|
314
|
+
else
|
|
315
|
+
fail_nodes += 1
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
task_names << status[:task] if status[:task]
|
|
319
|
+
callers << status[:callerid] if status[:callerid]
|
|
320
|
+
|
|
321
|
+
if progress
|
|
322
|
+
print(progress.twirl(cnt + 1, expected))
|
|
323
|
+
|
|
324
|
+
say if cnt + 1 == expected
|
|
325
|
+
else
|
|
326
|
+
cli.print_result(reply)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
cnt += 1
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
taskid ||= bolt_tasks.stats.requestid
|
|
333
|
+
|
|
334
|
+
callers.compact!
|
|
335
|
+
callers.uniq!
|
|
336
|
+
task_names.compact!
|
|
337
|
+
task_names.uniq!
|
|
338
|
+
|
|
339
|
+
say
|
|
340
|
+
|
|
341
|
+
cli.print_task_summary(
|
|
342
|
+
taskid,
|
|
343
|
+
task_names,
|
|
344
|
+
callers,
|
|
345
|
+
completed_nodes,
|
|
346
|
+
running_nodes,
|
|
347
|
+
task_not_known_nodes,
|
|
348
|
+
wrapper_failure,
|
|
349
|
+
success_nodes,
|
|
350
|
+
fail_nodes,
|
|
351
|
+
runtime,
|
|
352
|
+
bolt_tasks.stats
|
|
353
|
+
)
|
|
354
|
+
ensure
|
|
355
|
+
reset_client!
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def list_command
|
|
359
|
+
cli.show_task_list("production", configuration[:__detail])
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def run
|
|
363
|
+
command = ARGV[0]
|
|
364
|
+
command = "list" unless valid_commands.include?(command)
|
|
365
|
+
|
|
366
|
+
send("%s_options" % command)
|
|
367
|
+
|
|
368
|
+
super
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def show_task_help(task)
|
|
372
|
+
cli.show_task_help(task, "production")
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def bolt_tasks
|
|
376
|
+
@_bolt_tasks ||= rpcclient("bolt_tasks")
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def reset_client!
|
|
380
|
+
bolt_tasks.batch_size = 0
|
|
381
|
+
bolt_tasks.progress = options[:verbose]
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def extract_environment_from_argv
|
|
385
|
+
idx = ARGV.index("--environment")
|
|
386
|
+
|
|
387
|
+
return "production" unless idx
|
|
388
|
+
|
|
389
|
+
ARGV[idx + 1]
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def valid_commands
|
|
393
|
+
methods.grep(/_command$/).map {|c| c.to_s.gsub("_command", "")}
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def choria
|
|
397
|
+
Util.loadclass("MCollective::Util::Choria")
|
|
398
|
+
|
|
399
|
+
@_choria ||= Util::Choria.new
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def tasks_support
|
|
403
|
+
@_tasks_support ||= choria.tasks_support
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def cli
|
|
407
|
+
format = configuration[:__json_format] ? :json : :default
|
|
408
|
+
|
|
409
|
+
if options
|
|
410
|
+
@_cli ||= tasks_support.cli(format, options[:verbose])
|
|
411
|
+
else
|
|
412
|
+
tasks_support.cli(format, false)
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def main
|
|
417
|
+
if valid_commands.include?(configuration[:__command])
|
|
418
|
+
send("%s_command" % configuration[:__command])
|
|
419
|
+
else
|
|
420
|
+
show_task_help(configuration[:__command])
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
end
|