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
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
require_relative "nodes/mcollective_nodes"
|
|
2
|
+
require_relative "nodes/pql_nodes"
|
|
3
|
+
require_relative "nodes/yaml_nodes"
|
|
4
|
+
require_relative "nodes/shell_nodes"
|
|
5
|
+
require_relative "nodes/terraform_nodes"
|
|
6
|
+
|
|
7
|
+
module MCollective
|
|
8
|
+
module Util
|
|
9
|
+
class Playbook
|
|
10
|
+
class Nodes
|
|
11
|
+
attr_reader :nodes
|
|
12
|
+
|
|
13
|
+
def initialize(playbook)
|
|
14
|
+
@playbook = playbook
|
|
15
|
+
@nodes = {}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# List of known node set names
|
|
19
|
+
#
|
|
20
|
+
# @return [Array<String>]
|
|
21
|
+
def keys
|
|
22
|
+
@nodes.keys
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Nodes belonging to a specific node set
|
|
26
|
+
#
|
|
27
|
+
# @param nodeset [String] node set name
|
|
28
|
+
# @return [Array<String>]
|
|
29
|
+
# @raise [StandardError] when node set is unknown
|
|
30
|
+
def [](nodeset)
|
|
31
|
+
if include?(nodeset)
|
|
32
|
+
@nodes[nodeset][:discovered]
|
|
33
|
+
else
|
|
34
|
+
raise("Unknown node set %s" % nodeset)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Properties for a certain node set
|
|
39
|
+
#
|
|
40
|
+
# @param nodes [String] node set name
|
|
41
|
+
# @return [Hash]
|
|
42
|
+
# @raise [StandardError] when node set is unknown
|
|
43
|
+
def properties(nodes)
|
|
44
|
+
if include?(nodes)
|
|
45
|
+
@nodes[nodes][:properties]
|
|
46
|
+
else
|
|
47
|
+
raise("Unknown node set %s" % nodes)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Determines if a node set is known
|
|
52
|
+
#
|
|
53
|
+
# @param nodes [String] node set name
|
|
54
|
+
# @return [Boolean]
|
|
55
|
+
def include?(nodes)
|
|
56
|
+
@nodes.include?(nodes)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def prepare
|
|
60
|
+
@nodes.each do |node_set, dets|
|
|
61
|
+
@playbook.in_context(node_set) do
|
|
62
|
+
Log.debug("Preparing nodeset %s" % node_set)
|
|
63
|
+
|
|
64
|
+
resolve_nodes(node_set)
|
|
65
|
+
check_empty(node_set)
|
|
66
|
+
limit_nodes(node_set)
|
|
67
|
+
validate_nodes(node_set)
|
|
68
|
+
|
|
69
|
+
Log.info("Discovered %d node(s) in node set %s" % [dets[:discovered].size, node_set])
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
@playbook.in_context("conn.test") { test_nodes }
|
|
74
|
+
@playbook.in_context("ddl.test") { check_uses }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Resolve the node list using the resolver class
|
|
78
|
+
#
|
|
79
|
+
# @param node_set [String] node set name
|
|
80
|
+
def resolve_nodes(node_set)
|
|
81
|
+
node_props = @nodes[node_set]
|
|
82
|
+
node_props[:resolver].prepare
|
|
83
|
+
node_props[:discovered] = node_props[:resolver].discover.uniq
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Checks if the agents on the nodes matches the desired versions
|
|
87
|
+
#
|
|
88
|
+
# @raise [StandardError] on error
|
|
89
|
+
def check_uses
|
|
90
|
+
agent_nodes = {}
|
|
91
|
+
|
|
92
|
+
@nodes.map do |_, dets|
|
|
93
|
+
dets[:properties].fetch("uses", []).each do |agent|
|
|
94
|
+
agent_nodes[agent] ||= []
|
|
95
|
+
agent_nodes[agent].concat(dets[:discovered])
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
@playbook.validate_agents(agent_nodes) unless agent_nodes.empty?
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Determines if a nodeset needs connectivity test
|
|
103
|
+
#
|
|
104
|
+
# @param nodes [String] node set name
|
|
105
|
+
# @return [Boolean]
|
|
106
|
+
# @raise [StandardError] for unknown node sets
|
|
107
|
+
def should_test?(nodes)
|
|
108
|
+
!!properties(nodes)["test"]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def mcollective_task
|
|
112
|
+
Tasks::McollectiveTask.new(@playbook)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Tests a RPC ping to the discovered nodes
|
|
116
|
+
#
|
|
117
|
+
# @todo is this really needed?
|
|
118
|
+
# @raise [StandardError] on error
|
|
119
|
+
def test_nodes
|
|
120
|
+
nodes_to_test = @nodes.map do |nodes, _|
|
|
121
|
+
self[nodes] if should_test?(nodes)
|
|
122
|
+
end.flatten.compact
|
|
123
|
+
|
|
124
|
+
return if nodes_to_test.empty?
|
|
125
|
+
|
|
126
|
+
Log.info("Checking connectivity for %d nodes" % nodes_to_test.size)
|
|
127
|
+
|
|
128
|
+
rpc = mcollective_task
|
|
129
|
+
rpc.from_hash(
|
|
130
|
+
"nodes" => nodes_to_test,
|
|
131
|
+
"action" => "rpcutil.ping",
|
|
132
|
+
"silent" => true
|
|
133
|
+
)
|
|
134
|
+
success, msg, _ = rpc.run
|
|
135
|
+
|
|
136
|
+
raise("Connectivity test failed for some nodes: %s" % [msg]) unless success
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Checks that discovered nodes matches stated expectations
|
|
140
|
+
#
|
|
141
|
+
# @param nodes [String] node set name
|
|
142
|
+
# @raise [StandardError] on error
|
|
143
|
+
def validate_nodes(nodes)
|
|
144
|
+
return if properties(nodes)["empty_ok"]
|
|
145
|
+
|
|
146
|
+
raise("Node set %s needs at least %d nodes, got %d" % [nodes, properties(nodes)["at_least"], self[nodes].size]) unless self[nodes].size >= properties(nodes)["at_least"]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Handles an empty discovered list
|
|
150
|
+
#
|
|
151
|
+
# @param nodes [String] node set name
|
|
152
|
+
# @raise [StandardError] when empty
|
|
153
|
+
def check_empty(nodes)
|
|
154
|
+
raise(properties(nodes)["when_empty"] || "Did not discover any nodes for nodeset %s" % nodes) if self[nodes].empty? && !properties(nodes)["empty_ok"]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Limits the discovered list for a node set based on the playbook limits
|
|
158
|
+
#
|
|
159
|
+
# @todo more intelegent limiting with weighted randoms like mco rpc client
|
|
160
|
+
# @param nodes [String] node set name
|
|
161
|
+
def limit_nodes(nodes)
|
|
162
|
+
return if self[nodes].empty?
|
|
163
|
+
|
|
164
|
+
if limit = properties(nodes)["limit"]
|
|
165
|
+
Log.debug("Limiting node set %s to %d nodes from %d" % [nodes, limit, @nodes[nodes][:discovered].size])
|
|
166
|
+
@nodes[nodes][:discovered] = @nodes[nodes][:discovered][0..(limit - 1)]
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Retrieves a new instance of the resolver for a certain type of discovery
|
|
171
|
+
#
|
|
172
|
+
# @param type [String] finds classes called *Nodes::TypeNodes* based on this type
|
|
173
|
+
def resolver_for(type)
|
|
174
|
+
klass_name = "%sNodes" % type.capitalize
|
|
175
|
+
|
|
176
|
+
Nodes.const_get(klass_name).new
|
|
177
|
+
rescue NameError
|
|
178
|
+
raise("Cannot find a handler for Node Set type %s" % type)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def from_hash(data)
|
|
182
|
+
data.each do |nodes, props|
|
|
183
|
+
resolver = resolver_for(props["type"])
|
|
184
|
+
resolver.from_hash(props)
|
|
185
|
+
resolver.validate_configuration!
|
|
186
|
+
|
|
187
|
+
node_props = {
|
|
188
|
+
"at_least" => 1,
|
|
189
|
+
"empty_ok" => false,
|
|
190
|
+
"when_empty" => "Did not discover any nodes for nodeset %s" % nodes
|
|
191
|
+
}.merge(props)
|
|
192
|
+
|
|
193
|
+
node_props["at_least"] = 0 if node_props["empty_ok"]
|
|
194
|
+
|
|
195
|
+
@nodes[nodes] = {
|
|
196
|
+
:resolver => resolver,
|
|
197
|
+
:discovered => [],
|
|
198
|
+
:properties => node_props
|
|
199
|
+
}
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
self
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module Util
|
|
3
|
+
class Playbook
|
|
4
|
+
class Nodes
|
|
5
|
+
class McollectiveNodes
|
|
6
|
+
def initialize
|
|
7
|
+
@discovery_method = "mc"
|
|
8
|
+
@agents = []
|
|
9
|
+
@facts = []
|
|
10
|
+
@classes = []
|
|
11
|
+
@identity = []
|
|
12
|
+
@compound = nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def prepare; end
|
|
16
|
+
|
|
17
|
+
# @todo
|
|
18
|
+
def validate_configuration!; end
|
|
19
|
+
|
|
20
|
+
# Creates and cache an RPC::Client for the configured agent
|
|
21
|
+
#
|
|
22
|
+
# @param from_cache [Boolean] when false a new instance is always returned
|
|
23
|
+
# @return [RPC::Client]
|
|
24
|
+
def client(from_cache: true)
|
|
25
|
+
if from_cache
|
|
26
|
+
@_rpc_client ||= create_and_configure_client
|
|
27
|
+
else
|
|
28
|
+
create_and_configure_client
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Creates a new RPC::Client and configures it with the configured settings
|
|
33
|
+
#
|
|
34
|
+
# @todo discovery
|
|
35
|
+
# @return [RPC::Client]
|
|
36
|
+
def create_and_configure_client
|
|
37
|
+
client = RPC::Client.new(@agents[0], :configfile => Util.config_file_for_user, :options => Util.default_options)
|
|
38
|
+
client.progress = false
|
|
39
|
+
client.discovery_method = @discovery_method
|
|
40
|
+
|
|
41
|
+
@classes.each do |filter|
|
|
42
|
+
client.class_filter(filter)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
@facts.each do |filter|
|
|
46
|
+
client.fact_filter(filter)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
@agents.each do |filter|
|
|
50
|
+
client.agent_filter(filter)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
@identity.each do |filter|
|
|
54
|
+
client.identity_filter(filter)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
client.compound_filter(@compound) if @compound
|
|
58
|
+
|
|
59
|
+
client
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Initialize the nodes source from a hash
|
|
63
|
+
#
|
|
64
|
+
# @param data [Hash] input data matching nodes.json schema
|
|
65
|
+
# @return [McollectiveNodes]
|
|
66
|
+
def from_hash(data)
|
|
67
|
+
@discovery_method = data.fetch("discovery_method", "mc")
|
|
68
|
+
@agents = data.fetch("agents", ["rpcutil"])
|
|
69
|
+
@facts = data.fetch("facts", [])
|
|
70
|
+
@classes = data.fetch("classes", [])
|
|
71
|
+
@identity = data.fetch("identities", [])
|
|
72
|
+
@compound = data["compound"]
|
|
73
|
+
|
|
74
|
+
@_rpc_client = nil
|
|
75
|
+
|
|
76
|
+
self
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def discover
|
|
80
|
+
client.discover
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "mcollective/util/choria"
|
|
2
|
+
|
|
3
|
+
module MCollective
|
|
4
|
+
module Util
|
|
5
|
+
class Playbook
|
|
6
|
+
class Nodes
|
|
7
|
+
class PqlNodes
|
|
8
|
+
def initialize
|
|
9
|
+
@query = nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def prepare; end
|
|
13
|
+
|
|
14
|
+
def validate_configuration!
|
|
15
|
+
raise("No PQL query specified") unless @query
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def choria
|
|
19
|
+
@_choria ||= Util::Choria.new(false)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Initialize the nodes source from a hash
|
|
23
|
+
#
|
|
24
|
+
# @param data [Hash] input data matching nodes.json schema
|
|
25
|
+
# @return [PqlNodes]
|
|
26
|
+
def from_hash(data)
|
|
27
|
+
@query = data["query"]
|
|
28
|
+
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Performs the PQL query and extracts certnames
|
|
33
|
+
def discover
|
|
34
|
+
choria.pql_query(@query, true)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module Util
|
|
3
|
+
class Playbook
|
|
4
|
+
class Nodes
|
|
5
|
+
class ShellNodes
|
|
6
|
+
def initialize
|
|
7
|
+
@script = nil
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def prepare; end
|
|
11
|
+
|
|
12
|
+
def validate_configuration!
|
|
13
|
+
raise("No node source script specified") unless @script
|
|
14
|
+
raise("Node source script is not executable") unless File.executable?(@script)
|
|
15
|
+
raise("Node source script produced no results") if data.empty?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def from_hash(data)
|
|
19
|
+
@script = data["script"]
|
|
20
|
+
@_data = nil
|
|
21
|
+
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def valid_hostname?(host)
|
|
26
|
+
host =~ /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def data
|
|
30
|
+
return @_data if @_data
|
|
31
|
+
|
|
32
|
+
shell = Shell.new(@script, "timeout" => 10)
|
|
33
|
+
shell.runcommand
|
|
34
|
+
|
|
35
|
+
exitcode = shell.status.exitstatus
|
|
36
|
+
|
|
37
|
+
raise("Could not discover nodes via shell method, command exited with code %d" % [exitcode]) unless exitcode == 0
|
|
38
|
+
|
|
39
|
+
@_data = shell.stdout.lines.map do |line|
|
|
40
|
+
line.chomp!
|
|
41
|
+
|
|
42
|
+
raise("%s is not a valid hostname" % line) unless valid_hostname?(line)
|
|
43
|
+
|
|
44
|
+
line
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def discover
|
|
49
|
+
data
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module Util
|
|
3
|
+
class Playbook
|
|
4
|
+
class Nodes
|
|
5
|
+
class TerraformNodes
|
|
6
|
+
def prepare; end
|
|
7
|
+
|
|
8
|
+
def validate_configuration!
|
|
9
|
+
raise("The supplied terraform path %s is not executable" % @terraform) if @terraform && !File.executable?(@terraform)
|
|
10
|
+
raise("A terraform state file is needed") unless @state
|
|
11
|
+
raise("The terraform statefile %s is not readable" % @state) unless File.readable?(@state)
|
|
12
|
+
raise("An output name is needed") unless @output
|
|
13
|
+
|
|
14
|
+
Validator.validate(@terraform, :shellsafe)
|
|
15
|
+
Validator.validate(@state, :shellsafe)
|
|
16
|
+
Validator.validate(@output, :shellsafe)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def from_hash(data)
|
|
20
|
+
@state = data["statefile"]
|
|
21
|
+
@output = data["output"]
|
|
22
|
+
@terraform = data.fetch("terraform", choria.which("terraform"))
|
|
23
|
+
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def valid_hostname?(host)
|
|
28
|
+
host =~ /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def tf_output
|
|
32
|
+
shell = Shell.new("%s output -state %s -json %s 2>&1" % [@terraform, @state, @output])
|
|
33
|
+
shell.runcommand
|
|
34
|
+
|
|
35
|
+
raise("Terraform exited with code %d: %s" % [shell.status.exitstatus, shell.stdout]) unless shell.status.exitstatus == 0
|
|
36
|
+
|
|
37
|
+
shell.stdout
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def output_data
|
|
41
|
+
return @_data if @_data
|
|
42
|
+
|
|
43
|
+
data = JSON.parse(tf_output)
|
|
44
|
+
|
|
45
|
+
raise("Only terraform outputs of type list is supported") unless data["type"] == "list"
|
|
46
|
+
|
|
47
|
+
data["value"].each do |result|
|
|
48
|
+
raise("%s is not a valid hostname" % result) unless valid_hostname?(result)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@_data = data["value"]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def choria
|
|
55
|
+
@_choria ||= Util::Choria.new(false)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def discover
|
|
59
|
+
output_data
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|