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,106 @@
|
|
|
1
|
+
require_relative "base"
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "yaml"
|
|
5
|
+
|
|
6
|
+
module MCollective
|
|
7
|
+
module Util
|
|
8
|
+
class Playbook
|
|
9
|
+
class DataStores
|
|
10
|
+
class FileDataStore < Base
|
|
11
|
+
attr_accessor :file, :format, :create
|
|
12
|
+
|
|
13
|
+
def startup_hook
|
|
14
|
+
@file_mutex = Mutex.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def from_hash(properties)
|
|
18
|
+
@file = properties["file"]
|
|
19
|
+
@format = properties["format"]
|
|
20
|
+
@create = !!properties["create"]
|
|
21
|
+
|
|
22
|
+
validate_configuration!
|
|
23
|
+
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def validate_configuration!
|
|
28
|
+
raise("No file given to use as data source") unless @file
|
|
29
|
+
raise("No file format given") unless @format
|
|
30
|
+
raise("File format has to be one of 'json' or 'yaml'") unless ["json", "yaml"].include?(@format)
|
|
31
|
+
|
|
32
|
+
@file = File.expand_path(@file)
|
|
33
|
+
|
|
34
|
+
FileUtils.touch(@file) if @create && !File.exist?(@file)
|
|
35
|
+
|
|
36
|
+
raise("Cannot find data file %s" % @file) unless File.exist?(@file)
|
|
37
|
+
raise("Cannot read data file %s" % @file) unless File.readable?(@file)
|
|
38
|
+
raise("Cannot write data file %s" % @file) unless File.writable?(@file)
|
|
39
|
+
|
|
40
|
+
raise("The data file must contain a Hash or be empty") unless data.is_a?(Hash)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def data
|
|
44
|
+
@file_mutex.synchronize do
|
|
45
|
+
parse_data
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def parse_data
|
|
50
|
+
return({}) if File.size(@file) == 0
|
|
51
|
+
|
|
52
|
+
case @format
|
|
53
|
+
when "json"
|
|
54
|
+
JSON.parse(File.read(@file))
|
|
55
|
+
when "yaml"
|
|
56
|
+
YAML.load(File.read(@file))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def save_data(raw_data)
|
|
61
|
+
File.open(@file, "w") do |f|
|
|
62
|
+
case @format
|
|
63
|
+
when "json"
|
|
64
|
+
f.print(JSON.dump(raw_data))
|
|
65
|
+
when "yaml"
|
|
66
|
+
f.print(YAML.dump(raw_data))
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def read(key)
|
|
72
|
+
raise("No such key %s" % [key]) unless include?(key)
|
|
73
|
+
|
|
74
|
+
data[key]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def write(key, value)
|
|
78
|
+
@file_mutex.synchronize do
|
|
79
|
+
raw_data = parse_data
|
|
80
|
+
|
|
81
|
+
raw_data[key] = value
|
|
82
|
+
|
|
83
|
+
save_data(raw_data)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
read(key)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def delete(key)
|
|
90
|
+
@file_mutex.synchronize do
|
|
91
|
+
raw_data = parse_data
|
|
92
|
+
|
|
93
|
+
raw_data.delete(key)
|
|
94
|
+
|
|
95
|
+
save_data(raw_data)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def include?(key)
|
|
100
|
+
data.include?(key)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require_relative "base"
|
|
2
|
+
|
|
3
|
+
module MCollective
|
|
4
|
+
module Util
|
|
5
|
+
class Playbook
|
|
6
|
+
class DataStores
|
|
7
|
+
class ShellDataStore < Base
|
|
8
|
+
attr_reader :command, :timeout, :environment, :cwd
|
|
9
|
+
|
|
10
|
+
def write(key, value)
|
|
11
|
+
run("write", key, "CHORIA_DATA_VALUE" => value)
|
|
12
|
+
|
|
13
|
+
nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def delete(key)
|
|
17
|
+
run("delete", key)
|
|
18
|
+
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def read(key)
|
|
23
|
+
run("read", key).stdout.chomp
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def run(action, key, environment={})
|
|
27
|
+
validate_key(key)
|
|
28
|
+
|
|
29
|
+
command = "%s --%s" % [@command, action]
|
|
30
|
+
options = shell_options
|
|
31
|
+
|
|
32
|
+
options["environment"].merge!(
|
|
33
|
+
environment.merge(
|
|
34
|
+
"CHORIA_DATA_KEY" => key,
|
|
35
|
+
"CHORIA_DATA_ACTION" => action
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
shell = run_command(command, options)
|
|
40
|
+
|
|
41
|
+
unless shell.status.exitstatus == 0
|
|
42
|
+
Log.warn("While running command %s: %s" % [command, shell.stderr])
|
|
43
|
+
raise("Could not %s key %s, got exitcode %d" % [action, key, shell.status.exitstatus])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
shell
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def run_command(command, options)
|
|
50
|
+
shell = Shell.new(command, options)
|
|
51
|
+
shell.runcommand
|
|
52
|
+
shell
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def validate_key(key)
|
|
56
|
+
raise("Valid keys must match ^[a-zA-Z0-9_-]+$") unless key =~ /^[a-zA-Z0-9_-]+$/
|
|
57
|
+
|
|
58
|
+
true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def from_hash(properties)
|
|
62
|
+
@command = properties["command"]
|
|
63
|
+
@timeout = properties.fetch("timeout", 10)
|
|
64
|
+
@environment = properties.fetch("environment", {})
|
|
65
|
+
@cwd = properties["cwd"]
|
|
66
|
+
|
|
67
|
+
self
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def validate_configuration!
|
|
71
|
+
raise("A command is required") unless @command
|
|
72
|
+
raise("Command %s is not executable" % @command) unless File.executable?(@command)
|
|
73
|
+
raise("Timeout should be an integer") unless @timeout.to_i.to_s == @timeout.to_s
|
|
74
|
+
|
|
75
|
+
if @environment
|
|
76
|
+
raise("Environment should be a hash") unless @environment.is_a?(Hash)
|
|
77
|
+
|
|
78
|
+
all_strings = @environment.map {|k, v| k.is_a?(String) && v.is_a?(String)}.all?
|
|
79
|
+
raise("All keys and values in the environment must be strings") unless all_strings
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
if @cwd
|
|
83
|
+
raise("cwd %s does not exist" % @cwd) unless File.exist?(@cwd)
|
|
84
|
+
raise("cwd %s is not a directory" % @cwd) unless File.directory?(@cwd)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def shell_options
|
|
89
|
+
unless @__options
|
|
90
|
+
@__options = {}
|
|
91
|
+
@__options["cwd"] = @cwd if @cwd
|
|
92
|
+
@__options["environment"] = @environment
|
|
93
|
+
@__options["timeout"] = Integer(@timeout)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# bacause environment is being edited
|
|
97
|
+
Marshal.load(Marshal.dump(@__options))
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module Util
|
|
3
|
+
class Playbook
|
|
4
|
+
class Inputs
|
|
5
|
+
def initialize(playbook)
|
|
6
|
+
@playbook = playbook
|
|
7
|
+
@inputs = {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# List of known input names
|
|
11
|
+
#
|
|
12
|
+
# @return [Array<String>]
|
|
13
|
+
def keys
|
|
14
|
+
@inputs.keys
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# List of known input names that have static values
|
|
18
|
+
#
|
|
19
|
+
# @return [Array<String>]
|
|
20
|
+
def static_keys
|
|
21
|
+
keys - dynamic_keys
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# List of known input names that have dynamic values
|
|
25
|
+
#
|
|
26
|
+
# @return [Array<String>]
|
|
27
|
+
def dynamic_keys
|
|
28
|
+
@inputs.select do |_, props|
|
|
29
|
+
props[:dynamic]
|
|
30
|
+
end.keys
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Creates options for each input in the application
|
|
34
|
+
#
|
|
35
|
+
# @param application [MCollective::Application]
|
|
36
|
+
# @param set_required [Boolean] when true required inputs will be required on the CLI
|
|
37
|
+
# @raise [StandardError] for invalidly defined inputs
|
|
38
|
+
def add_cli_options(application, set_required)
|
|
39
|
+
@inputs.each do |input, props|
|
|
40
|
+
i_props = props[:properties]
|
|
41
|
+
|
|
42
|
+
next if i_props["dynamic"]
|
|
43
|
+
|
|
44
|
+
type = case i_props["type"]
|
|
45
|
+
when :string, "String"
|
|
46
|
+
String
|
|
47
|
+
when :fixnum, "Fixnum", "Integer"
|
|
48
|
+
Integer
|
|
49
|
+
when :float, "Float"
|
|
50
|
+
Float
|
|
51
|
+
when :numeric, "Numeric"
|
|
52
|
+
Numeric
|
|
53
|
+
when :array, ":array", "Array"
|
|
54
|
+
:array
|
|
55
|
+
when :bool, ":bool", ":boolean", "Boolean"
|
|
56
|
+
:boolean
|
|
57
|
+
else
|
|
58
|
+
raise("Invalid input type %s given for input %s" % [i_props["type"], input])
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
description = "%s (%s) %s" % [i_props["description"], type, i_props["default"] ? ("default: %s" % i_props["default"]) : ""]
|
|
62
|
+
|
|
63
|
+
option_params = {
|
|
64
|
+
:description => description,
|
|
65
|
+
:arguments => ["--%s %s" % [input.downcase, input.upcase]],
|
|
66
|
+
:type => type
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
option_params[:arguments] = ["--%s" % input.downcase] if type == :boolean
|
|
70
|
+
|
|
71
|
+
option_params[:required] = i_props["required"] if set_required && !i_props.include?("data")
|
|
72
|
+
|
|
73
|
+
application.class.option(input, option_params)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Attempts to find values for all declared inputs
|
|
78
|
+
#
|
|
79
|
+
# During tests saving to the ds can be skipped by setting
|
|
80
|
+
# @save_during_prepare to false
|
|
81
|
+
#
|
|
82
|
+
# @param data [Hash] input data from CLI etc
|
|
83
|
+
# @return [void]
|
|
84
|
+
# @raise [StandardError] when required data could not be found
|
|
85
|
+
# @raise [StandardError] when validation fails for any data
|
|
86
|
+
def prepare(data={})
|
|
87
|
+
@inputs.each do |input, props|
|
|
88
|
+
next unless data.include?(input)
|
|
89
|
+
next if data[input].nil?
|
|
90
|
+
next if props[:properties]["dynamic"]
|
|
91
|
+
|
|
92
|
+
validate_data(input, data[input])
|
|
93
|
+
|
|
94
|
+
props[:value] = data[input]
|
|
95
|
+
props[:dynamic] = false
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
validate_requirements
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Checks if a input is dynamic
|
|
102
|
+
#
|
|
103
|
+
# Dynaic inputs are those where the data is sourced from
|
|
104
|
+
# a data source, an input that has a data source defined
|
|
105
|
+
# and had a specific input given will not be dynamic
|
|
106
|
+
#
|
|
107
|
+
# @return [Boolean]
|
|
108
|
+
def dynamic?(input)
|
|
109
|
+
@inputs[input][:dynamic]
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def include?(input)
|
|
113
|
+
@inputs.include?(input)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Looks up data from a datastore, returns default when not found
|
|
117
|
+
#
|
|
118
|
+
# @param input [String] input name
|
|
119
|
+
# @return [Object] value from the ds
|
|
120
|
+
# @raise [StandardError] for invalid inputs and ds errors
|
|
121
|
+
def lookup_from_datastore(input)
|
|
122
|
+
raise("Unknown input %s" % input) unless include?(input)
|
|
123
|
+
|
|
124
|
+
properties = @inputs[input][:properties]
|
|
125
|
+
|
|
126
|
+
value = @playbook.data_stores.read(properties["data"])
|
|
127
|
+
validate_data(input, value)
|
|
128
|
+
|
|
129
|
+
value
|
|
130
|
+
rescue
|
|
131
|
+
raise("Could not resolve %s for input %s: %s: %s" % [properties["data"], input, $!.class, $!.to_s]) unless properties.include?("default")
|
|
132
|
+
|
|
133
|
+
Log.warn("Could not find %s, returning default value" % properties["data"])
|
|
134
|
+
|
|
135
|
+
properties["default"]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Saves static property values in their associated data stores for any keys with save set
|
|
139
|
+
def save_input_data
|
|
140
|
+
@inputs.each do |input, props|
|
|
141
|
+
next unless props[:properties]["save"]
|
|
142
|
+
next unless props[:properties]["data"]
|
|
143
|
+
next unless props[:value]
|
|
144
|
+
next if props[:dynamic]
|
|
145
|
+
|
|
146
|
+
save_to_datastore(input)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Saves the value of a input to the data entry associated with it
|
|
151
|
+
#
|
|
152
|
+
# @see #save_input_data
|
|
153
|
+
# @param input [String] input name
|
|
154
|
+
# @raise [StandardError] for invalid inputs and ds errors
|
|
155
|
+
def save_to_datastore(input)
|
|
156
|
+
raise("Unknown input %s" % input) unless include?(input)
|
|
157
|
+
|
|
158
|
+
i_data = @inputs[input]
|
|
159
|
+
|
|
160
|
+
raise("Input %s has no value, cannot store it" % input) unless i_data.include?(:value)
|
|
161
|
+
|
|
162
|
+
Log.debug("Saving value for input %s to data item %s" % [input, i_data[:properties]["data"]])
|
|
163
|
+
|
|
164
|
+
@playbook.data_stores.write(i_data[:properties]["data"], i_data[:value])
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Retrieves the value for a specific input
|
|
168
|
+
#
|
|
169
|
+
# @param input [String] input name
|
|
170
|
+
# @return [Object]
|
|
171
|
+
# @raise [StandardError] for unknown inputs
|
|
172
|
+
def [](input)
|
|
173
|
+
raise("Unknown input %s" % input) unless include?(input)
|
|
174
|
+
|
|
175
|
+
props = @inputs[input][:properties]
|
|
176
|
+
|
|
177
|
+
if @inputs[input].include?(:value)
|
|
178
|
+
Log.debug("Resolving %s as static" % [input])
|
|
179
|
+
@inputs[input][:value]
|
|
180
|
+
elsif props.include?("data")
|
|
181
|
+
Log.debug("Resolving %s as dynamic" % [input])
|
|
182
|
+
lookup_from_datastore(input)
|
|
183
|
+
elsif props.include?("default")
|
|
184
|
+
Log.debug("Resolving %s as default" % [input])
|
|
185
|
+
props["default"]
|
|
186
|
+
else
|
|
187
|
+
raise("Input %s has no value, data source or default" % [input])
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Retrieves the properties for a specific input
|
|
192
|
+
#
|
|
193
|
+
# @param input [String] input name
|
|
194
|
+
# @return [Hash]
|
|
195
|
+
# @raise [StandardError] for unknown inputs
|
|
196
|
+
def input_properties(input)
|
|
197
|
+
if include?(input)
|
|
198
|
+
@inputs[input][:properties]
|
|
199
|
+
else
|
|
200
|
+
raise("Unknown input %s" % input)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Checks all required inputs have values
|
|
205
|
+
#
|
|
206
|
+
# @raise [StandardError] when not
|
|
207
|
+
def validate_requirements
|
|
208
|
+
invalid = @inputs.map do |input, props|
|
|
209
|
+
next unless props[:properties]["required"]
|
|
210
|
+
next if props[:properties].include?("data")
|
|
211
|
+
|
|
212
|
+
unless props[:value]
|
|
213
|
+
Log.warn("Input %s requires a value but has none or nil" % input)
|
|
214
|
+
input
|
|
215
|
+
end
|
|
216
|
+
end.compact
|
|
217
|
+
|
|
218
|
+
raise("Values were required but not given for inputs: %s" % invalid.join(", ")) unless invalid.empty?
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Validates a piece of data against an input
|
|
222
|
+
#
|
|
223
|
+
# @todo this seems quite limited, we have to expand with real needs
|
|
224
|
+
# @param input [String] a valid input name
|
|
225
|
+
# @param value [Object] a value to validate
|
|
226
|
+
# @raise [StandardError] on validation failure
|
|
227
|
+
def validate_data(input, value)
|
|
228
|
+
return unless @inputs[input][:properties].include?("validation")
|
|
229
|
+
|
|
230
|
+
validator = @inputs[input][:properties]["validation"]
|
|
231
|
+
|
|
232
|
+
case validator
|
|
233
|
+
when /^:(.+)/
|
|
234
|
+
validator = $1.intern
|
|
235
|
+
when /^\/(.+)\/$/
|
|
236
|
+
validator = Regexp.new($1)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
Log.debug("Validating input %s using %s validator" % [input, validator])
|
|
240
|
+
|
|
241
|
+
Validator.validate(value, validator)
|
|
242
|
+
rescue
|
|
243
|
+
Log.warn("Attempt to validate input %s with validator %s failed: %s" % [input, validator, $!.to_s]) if validator
|
|
244
|
+
|
|
245
|
+
raise("Failed to validate value for input %s: %s" % [input, $!.to_s])
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def from_hash(data)
|
|
249
|
+
data.each do |input, props|
|
|
250
|
+
props["required"] = true unless props.include?("required")
|
|
251
|
+
|
|
252
|
+
Log.debug("Loading input %s" % [input])
|
|
253
|
+
|
|
254
|
+
@inputs[input] = {
|
|
255
|
+
:properties => props,
|
|
256
|
+
:dynamic => props.include?("data")
|
|
257
|
+
}
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
self
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|