-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathrun_script.rb
More file actions
146 lines (129 loc) · 6.31 KB
/
run_script.rb
File metadata and controls
146 lines (129 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# frozen_string_literal: true
# Uploads the given script to the given set of targets and returns the result of having each target execute the script.
# This function does nothing if the list of targets is empty.
#
# > **Note:** Not available in apply block
Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFunction) do
# Run a script.
# @param script Path to a script to run on target. Can be an absolute path or a modulename/filename selector for a
# file in $MODULEROOT/files.
# @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
# @param options A hash of additional options.
# @option options [Array[String]] arguments An array of arguments to be passed to the script.
# Cannot be used with `pwsh_params`.
# @option options [Hash] pwsh_params Map of named parameters to pass to a PowerShell script.
# Cannot be used with `arguments`.
# @option options [Boolean] _catch_errors Whether to catch raised errors.
# @option options [String] _run_as User to run as using privilege escalation.
# @option options [Hash[String, Any]] _env_vars Map of environment variables to set.
# @return A list of results, one entry per target.
# @example Run a local script on Linux targets as 'root'
# run_script('/var/tmp/myscript', $targets, '_run_as' => 'root')
# @example Run a module-provided script with arguments
# run_script('iis/setup.ps1', $target, 'arguments' => ['/u', 'Administrator'])
# @example Pass named parameters to a PowerShell script
# run_script('iis/setup.ps1', $target, 'pwsh_params' => { 'User' => 'Administrator' })
dispatch :run_script do
scope_param
param 'String[1]', :script
param 'Boltlib::TargetSpec', :targets
optional_param 'Hash[String[1], Any]', :options
return_type 'ResultSet'
end
# Run a script, logging the provided description.
# @param script Path to a script to run on target. Can be an absolute path or a modulename/filename selector for a
# file in $MODULEROOT/files.
# @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
# @param description A description to be output when calling this function.
# @param options A hash of additional options.
# @option options [Array[String]] arguments An array of arguments to be passed to the script.
# Cannot be used with `pwsh_params`.
# @option options [Hash] pwsh_params Map of named parameters to pass to a PowerShell script.
# Cannot be used with `arguments`.
# @option options [Boolean] _catch_errors Whether to catch raised errors.
# @option options [String] _run_as User to run as using privilege escalation.
# @option options [Hash[String, Any]] _env_vars Map of environment variables to set.
# @return A list of results, one entry per target.
# @example Run a script
# run_script('/var/tmp/myscript', $targets, 'Downloading my application')
dispatch :run_script_with_description do
scope_param
param 'String[1]', :script
param 'Boltlib::TargetSpec', :targets
param 'String', :description
optional_param 'Hash[String[1], Any]', :options
return_type 'ResultSet'
end
def run_script(scope, script, targets, options = {})
run_script_with_description(scope, script, targets, nil, options)
end
def run_script_with_description(scope, script, targets, description = nil, options = {})
unless Puppet[:tasks]
raise Puppet::ParseErrorWithIssue
.from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'run_script')
end
if options.key?('arguments') && options.key?('pwsh_params')
raise Bolt::ValidationError, "Cannot specify both 'arguments' and 'pwsh_params'"
end
if options.key?('pwsh_params') && !options['pwsh_params'].is_a?(Hash)
raise Bolt::ValidationError, "Option 'pwsh_params' must be a hash"
end
if options.key?('arguments') && !options['arguments'].is_a?(Array)
raise Bolt::ValidationError, "Option 'arguments' must be an array"
end
arguments = options['arguments'] || []
pwsh_params = options['pwsh_params']
options = options.select { |opt| opt.start_with?('_') }.transform_keys { |k| k.sub(/^_/, '').to_sym }
options[:description] = description if description
options[:pwsh_params] = pwsh_params if pwsh_params
# Ensure env_vars is a hash and that each hash value is transformed to JSON
# so we don't accidentally pass Ruby-style data to the target.
if options[:env_vars]
unless options[:env_vars].is_a?(Hash)
raise Bolt::ValidationError, "Option 'env_vars' must be a hash"
end
if (bad_keys = options[:env_vars].keys.reject { |k| k.is_a?(String) }).any?
raise Bolt::ValidationError,
"Keys for option 'env_vars' must be strings: #{bad_keys.map(&:inspect).join(', ')}"
end
options[:env_vars] = options[:env_vars].transform_values do |val|
[Array, Hash].include?(val.class) ? val.to_json : val
end
end
executor = Puppet.lookup(:bolt_executor)
inventory = Puppet.lookup(:bolt_inventory)
# Send Analytics Report
executor.report_function_call(self.class.name)
# Find the file path if it exists, otherwise return nil
found = Bolt::Util.find_file_from_scope(script, scope)
unless found && Puppet::FileSystem.exist?(found)
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: script
)
end
unless Puppet::FileSystem.file?(found)
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
Puppet::Pops::Issues::NOT_A_FILE, file: script
)
end
executor.report_file_source(self.class.name, script)
# Ensure that given targets are all Target instances)
targets = inventory.get_targets(targets)
if targets.empty?
Bolt::ResultSet.new([])
else
file_line = Puppet::Pops::PuppetStack.top_of_stack
r = if executor.in_parallel?
executor.run_in_thread do
executor.run_script(targets, found, arguments, options, file_line)
end
else
executor.run_script(targets, found, arguments, options, file_line)
end
if !r.ok && !options[:catch_errors]
raise Bolt::RunFailure.new(r, 'run_script', script)
end
r
end
end
end