bolt 0.22.0 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe765b38afea737ae2308098b790fde05b73da5d4eaa661c2121313ccb675d48
4
- data.tar.gz: 3280f5388127bce11a71f3aed0db819e7869f0d6751dedb3d0ec815c83623674
3
+ metadata.gz: c7e3c1e13c0b81acdf948d563eb5acc20710ba52c6aacd14580defbb722fa6ca
4
+ data.tar.gz: 5a382bffe6ac5eb12e7214a5f0f64581366a4e224f0a1968e5db8a656994f5a1
5
5
  SHA512:
6
- metadata.gz: 50c22855422b4a2cba254cb43647c8ead003b53816b082173a4383f143cf44e3b6a9ca20ff1792d986597e7256fffe875a7130fe036689860f8931f7c5622b29
7
- data.tar.gz: 101c06ea0ad6836d3c773ab877fbc74f972f38c14a33d92f00d0da52e83cd797c58a1b502fc79c0b8edd85df3cccc9bfbbb972ce54d64d09de4a6d7ca1a1f31f
6
+ metadata.gz: 5793f401349ef2a8985b97c4938cf61497c51abb39fcd65ca2fbc3c4173719366d659eeb302fb145e1e198e415ed62b50728743f0bf98440b9d8d837ce28617c
7
+ data.tar.gz: c9dc1835008deda159c9e317134dc68c67a24d5cab366cf72d608fd067d854d58ce1084f289aacb7764008a085d26363c82b186b6885ecf2bdab6ddf0eecc464
@@ -12,10 +12,11 @@ require 'bolt/util/puppet_log_level'
12
12
 
13
13
  module Bolt
14
14
  class Applicator
15
- def initialize(inventory, executor, modulepath, pdb_client, hiera_config, max_compiles)
15
+ def initialize(inventory, executor, modulepath, plugin_dirs, pdb_client, hiera_config, max_compiles)
16
16
  @inventory = inventory
17
17
  @executor = executor
18
18
  @modulepath = modulepath
19
+ @plugin_dirs = plugin_dirs
19
20
  @pdb_client = pdb_client
20
21
  @hiera_config = hiera_config ? validate_hiera_config(hiera_config) : nil
21
22
 
@@ -222,7 +223,7 @@ module Bolt
222
223
  sio = StringIO.new
223
224
  output = Minitar::Output.new(Zlib::GzipWriter.new(sio))
224
225
 
225
- Puppet.lookup(:current_environment).modules.each do |mod|
226
+ Puppet.lookup(:current_environment).override_with(modulepath: @plugin_dirs).modules.each do |mod|
226
227
  search_dirs = yield mod
227
228
 
228
229
  parent = Pathname.new(mod.path).parent
@@ -202,7 +202,10 @@ Available options are:
202
202
  end
203
203
  define('--modulepath MODULES',
204
204
  "List of directories containing modules, separated by '#{File::PATH_SEPARATOR}'") do |modulepath|
205
- @options[:modulepath] = modulepath.split(File::PATH_SEPARATOR)
205
+ # When specified from the CLI, modulepath entries are relative to pwd
206
+ @options[:modulepath] = modulepath.split(File::PATH_SEPARATOR).map do |moduledir|
207
+ File.expand_path(moduledir)
208
+ end
206
209
  end
207
210
  define('--boltdir FILEPATH',
208
211
  'Specify what Boltdir to load config from (default: autodiscovered from current working dir)') do |path|
@@ -217,7 +220,7 @@ Available options are:
217
220
  if ENV.include?(Bolt::Inventory::ENVIRONMENT_VAR)
218
221
  raise Bolt::CLIError, "Cannot pass inventory file when #{Bolt::Inventory::ENVIRONMENT_VAR} is set"
219
222
  end
220
- @options[:inventoryfile] = path
223
+ @options[:inventoryfile] = File.expand_path(path)
221
224
  end
222
225
 
223
226
  separator 'Transports:'
@@ -25,7 +25,7 @@ module Bolt
25
25
  @path = Pathname.new(path).expand_path
26
26
  @config_file = @path + 'bolt.yaml'
27
27
  @inventory_file = @path + 'inventory.yaml'
28
- @modulepath = [(@path + 'modules').to_s]
28
+ @modulepath = [(@path + 'modules').to_s, (@path + 'site').to_s]
29
29
  @hiera_config = @path + 'hiera.yaml'
30
30
  @puppetfile = @path + 'Puppetfile'
31
31
  end
@@ -148,11 +148,17 @@ module Bolt
148
148
  update_logs(data['log'])
149
149
  end
150
150
 
151
- @modulepath = data['modulepath'].split(File::PATH_SEPARATOR) if data.key?('modulepath')
151
+ # Expand paths relative to the Boltdir. Any settings that came from the
152
+ # CLI will already be absolute, so the expand will be skipped.
153
+ if data.key?('modulepath')
154
+ @modulepath = data['modulepath'].split(File::PATH_SEPARATOR).map do |moduledir|
155
+ File.expand_path(moduledir, @boltdir.path)
156
+ end
157
+ end
152
158
 
153
- @inventoryfile = data['inventoryfile'] if data.key?('inventoryfile')
159
+ @inventoryfile = File.expand_path(data['inventoryfile'], @boltdir.path) if data.key?('inventoryfile')
154
160
 
155
- @hiera_config = data['hiera-config'] if data.key?('hiera-config')
161
+ @hiera_config = File.expand_path(data['hiera-config'], @boltdir.path) if data.key?('hiera-config')
156
162
  @compile_concurrency = data['compile-concurrency'] if data.key?('compile-concurrency')
157
163
 
158
164
  %w[concurrency format puppetdb color transport].each do |key|
@@ -40,7 +40,11 @@ module Bolt
40
40
 
41
41
  @noop = noop
42
42
  @run_as = nil
43
- @pool = Concurrent::ThreadPoolExecutor.new(max_threads: concurrency)
43
+ @pool = if concurrency > 0
44
+ Concurrent::ThreadPoolExecutor.new(max_threads: concurrency)
45
+ else
46
+ Concurrent.global_immediate_executor
47
+ end
44
48
  @logger.debug { "Started with #{concurrency} max thread(s)" }
45
49
  @notifier = Bolt::Notifier.new
46
50
  end
@@ -8,8 +8,8 @@ require 'bolt/applicator'
8
8
 
9
9
  module Bolt
10
10
  class PAL
11
- BOLTLIB_PATH = File.join(__dir__, '../../bolt-modules')
12
- MODULES_PATH = File.join(__dir__, '../../modules')
11
+ BOLTLIB_PATH = File.expand_path('../../bolt-modules', __dir__)
12
+ MODULES_PATH = File.expand_path('../../modules', __dir__)
13
13
 
14
14
  # PALError is used to convert errors from executing puppet code into
15
15
  # Bolt::Errors
@@ -44,9 +44,15 @@ module Bolt
44
44
  # This makes sure we don't accidentally create puppet dirs
45
45
  with_puppet_settings { |_| nil }
46
46
 
47
+ @original_modulepath = modulepath
47
48
  @modulepath = [BOLTLIB_PATH, *modulepath, MODULES_PATH]
48
49
  @hiera_config = hiera_config
49
50
  @max_compiles = max_compiles
51
+
52
+ @logger = Logging.logger[self]
53
+ if modulepath && !modulepath.empty?
54
+ @logger.info("Loading modules from #{@modulepath.join(File::PATH_SEPARATOR)}")
55
+ end
50
56
  end
51
57
 
52
58
  # Puppet logging is global so this is class method to avoid confusion
@@ -123,6 +129,10 @@ module Bolt
123
129
  inventory,
124
130
  executor,
125
131
  @modulepath,
132
+ # Skip syncing built-in plugins, since we vendor some Puppet 6
133
+ # versions of "core" types, which are already present on the agent,
134
+ # but may cause issues on Puppet 5 agents.
135
+ @original_modulepath,
126
136
  pdb_client,
127
137
  @hiera_config,
128
138
  @max_compiles
@@ -107,15 +107,11 @@ module Bolt
107
107
  end
108
108
 
109
109
  def user
110
- Addressable::URI.unencode_component(
111
- @uri_obj.user || @user
112
- )
110
+ Addressable::URI.unencode_component(@uri_obj.user) || @user
113
111
  end
114
112
 
115
113
  def password
116
- Addressable::URI.unencode_component(
117
- @uri_obj.password || @password
118
- )
114
+ Addressable::URI.unencode_component(@uri_obj.password) || @password
119
115
  end
120
116
  end
121
117
  end
@@ -58,10 +58,10 @@ module Bolt
58
58
  callback&.call(type: :node_start, target: target)
59
59
 
60
60
  result = begin
61
- yield
62
- rescue StandardError => ex
63
- Bolt::Result.from_exception(target, ex)
64
- end
61
+ yield
62
+ rescue StandardError => ex
63
+ Bolt::Result.from_exception(target, ex)
64
+ end
65
65
 
66
66
  callback&.call(type: :node_result, result: result)
67
67
  result
@@ -174,7 +174,7 @@ module Bolt
174
174
  def make_wrapper_stringio(task_path, stdin)
175
175
  StringIO.new(<<-SCRIPT)
176
176
  #!/bin/sh
177
- '#{task_path}' <<EOF
177
+ '#{task_path}' <<'EOF'
178
178
  #{stdin}
179
179
  EOF
180
180
  SCRIPT
@@ -73,7 +73,8 @@ module Bolt
73
73
  arguments = unwrap_sensitive_args(arguments)
74
74
 
75
75
  with_connection(target) do |conn|
76
- conn.with_remote_file(script) do |remote_path|
76
+ conn.with_remote_tempdir do |dir|
77
+ remote_path = conn.write_remote_executable(dir, script)
77
78
  if powershell_file?(remote_path)
78
79
  mapped_args = arguments.map do |a|
79
80
  "$invokeArgs.ArgumentList += @'\n#{a}\n'@"
@@ -107,13 +108,9 @@ catch
107
108
 
108
109
  def run_task(target, task, arguments, _options = {})
109
110
  if from_api?(task)
110
- # TODO: Remove as part of BOLT-664
111
- dir = Dir.mktmpdir
112
- executable = File.join(dir, task.file['filename'])
113
- File.open(executable, 'w') { |f|
114
- f.write(Base64.decode64(task.file['file_content']))
115
- }
116
- task.input_method = powershell_file?(executable) ? 'powershell' : 'both'
111
+ task.input_method = powershell_file?(task["file"]["filename"]) ? 'powershell' : 'both'
112
+ executable = { filename: task["file"]["filename"],
113
+ file_content: StringIO.new(Base64.decode64(task.file['file_content'])) }
117
114
  else
118
115
  executable = target.select_impl(task, PROVIDED_FEATURES)
119
116
  raise "No suitable implementation of #{task.name} for #{target.name}" unless executable
@@ -139,9 +136,17 @@ catch
139
136
  end
140
137
  end
141
138
 
142
- conn.with_remote_file(executable) do |remote_path|
139
+ conn.with_remote_tempdir do |dir|
140
+ remote_task_path = if from_api?(task)
141
+ conn.write_executable_from_content(dir,
142
+ executable[:file_content],
143
+ executable[:filename])
144
+ else
145
+ conn.write_remote_executable(dir, executable)
146
+ end
147
+ conn.shell_init
143
148
  output =
144
- if powershell_file?(remote_path) && stdin.nil?
149
+ if powershell_file?(remote_task_path) && stdin.nil?
145
150
  # NOTE: cannot redirect STDIN to a .ps1 script inside of PowerShell
146
151
  # must create new powershell.exe process like other interpreters
147
152
  # fortunately, using PS with stdin input_method should never happen
@@ -150,22 +155,19 @@ catch
150
155
  $private:tempArgs = Get-ContentAsJson (
151
156
  $utf8.GetString([System.Convert]::FromBase64String('#{Base64.encode64(JSON.dump(arguments))}'))
152
157
  )
153
- $allowedArgs = (Get-Command "#{remote_path}").Parameters.Keys
158
+ $allowedArgs = (Get-Command "#{remote_task_path}").Parameters.Keys
154
159
  $private:taskArgs = @{}
155
160
  $private:tempArgs.Keys | ? { $allowedArgs -contains $_ } | % { $private:taskArgs[$_] = $private:tempArgs[$_] }
156
- try { & "#{remote_path}" @taskArgs } catch { Write-Error $_.Exception; exit 1 }
161
+ try { & "#{remote_task_path}" @taskArgs } catch { Write-Error $_.Exception; exit 1 }
157
162
  PS
158
163
  else
159
- conn.execute(%(try { & "#{remote_path}" } catch { Write-Error $_.Exception; exit 1 }))
164
+ conn.execute(%(try { & "#{remote_task_path}" } catch { Write-Error $_.Exception; exit 1 }))
160
165
  end
161
166
  else
162
- path, args = *process_from_extension(remote_path)
167
+ path, args = *process_from_extension(remote_task_path)
163
168
  conn.execute_process(path, args, stdin)
164
169
  end
165
170
 
166
- if from_api?(task)
167
- FileUtils.remove_entry dir
168
- end
169
171
  Bolt::Result.for_task(target, output.stdout.string,
170
172
  output.stderr.string,
171
173
  output.exit_code)
@@ -99,6 +99,7 @@ module Bolt
99
99
  return nil if @shell_initialized
100
100
  result = execute(<<-PS)
101
101
  $ENV:PATH += ";${ENV:ProgramFiles}\\Puppet Labs\\Puppet\\bin\\;" +
102
+ "${ENV:ProgramFiles}\\Puppet Labs\\Puppet\\puppet\\bin;" +
102
103
  "${ENV:ProgramFiles}\\Puppet Labs\\Puppet\\sys\\ruby\\bin\\"
103
104
  $ENV:RUBYLIB = "${ENV:ProgramFiles}\\Puppet Labs\\Puppet\\puppet\\lib;" +
104
105
  "${ENV:ProgramFiles}\\Puppet Labs\\Puppet\\facter\\lib;" +
@@ -335,8 +336,9 @@ PS
335
336
 
336
337
  def write_remote_file(source, destination)
337
338
  fs = ::WinRM::FS::FileManager.new(@connection)
338
- # TODO: raise FileError here if this fails
339
339
  fs.upload(source, destination)
340
+ rescue StandardError => e
341
+ raise Bolt::Node::FileError.new(e.message, 'WRITE_ERROR')
340
342
  end
341
343
 
342
344
  def make_tempdir
@@ -354,25 +356,35 @@ PS
354
356
  result.stdout.string.chomp
355
357
  end
356
358
 
357
- def with_remote_file(file)
358
- ext = File.extname(file)
359
+ def with_remote_tempdir
360
+ dir = make_tempdir
361
+ yield dir
362
+ ensure
363
+ execute(<<-PS)
364
+ Remove-Item -Force -Recurse -Path "#{dir}"
365
+ PS
366
+ end
367
+
368
+ def validate_extensions(ext)
359
369
  unless @extensions.include?(ext)
360
370
  raise Bolt::Node::FileError.new("File extension #{ext} is not enabled, "\
361
371
  "to run it please add to 'winrm: extensions'", 'FILETYPE_ERROR')
362
372
  end
363
- file_base = File.basename(file)
364
- dir = make_tempdir
365
- dest = "#{dir}\\#{file_base}"
366
- begin
367
- write_remote_file(file, dest)
368
- shell_init
369
- yield dest
370
- ensure
371
- execute(<<-PS)
372
- Remove-Item -Force "#{dest}"
373
- Remove-Item -Force "#{dir}"
374
- PS
375
- end
373
+ end
374
+
375
+ def write_remote_executable(dir, file, filename = nil)
376
+ filename ||= File.basename(file)
377
+ validate_extensions(File.extname(filename))
378
+ remote_path = "#{dir}\\#{filename}"
379
+ write_remote_file(file, remote_path)
380
+ remote_path
381
+ end
382
+
383
+ def write_executable_from_content(dir, content, filename)
384
+ validate_extensions(File.extname(filename))
385
+ remote_path = "#{dir}\\#{filename}"
386
+ write_remote_file(content, remote_path)
387
+ remote_path
376
388
  end
377
389
  end
378
390
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '0.22.0'
4
+ VERSION = '0.23.0'
5
5
  end
@@ -0,0 +1,71 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "SSH run_task request",
4
+ "description": "POST ssh/run_task request schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "target": {
8
+ "type": "object",
9
+ "description": "Target information to run task on",
10
+ "properties": {
11
+ "hostname": {
12
+ "type": "string",
13
+ "description": "Target identifier"
14
+ },
15
+ "user": {
16
+ "type": "string",
17
+ "description": "Login user"
18
+ },
19
+ "password": {
20
+ "type": "string",
21
+ "description": "Password for SSH transport authentication"
22
+ },
23
+ "private-key-content": {
24
+ "type": "string",
25
+ "description": "Contents of private key for SSH"
26
+ },
27
+ "port": {
28
+ "type": "integer",
29
+ "description": "Connection port"
30
+ },
31
+ "connect-timeout": {
32
+ "type": "integer",
33
+ "description": "How long Bolt should wait when establishing connections"
34
+ },
35
+ "run-as-command": {
36
+ "type": "array",
37
+ "description": "Command elevate permissions",
38
+ "items": { "type": "string" }
39
+ },
40
+ "run-as": {
41
+ "type": "string",
42
+ "description": "A different user to run commands as after login"
43
+ },
44
+ "tmpdir": {
45
+ "type": "string",
46
+ "description": "The directory to upload and execute temporary files on the target"
47
+ },
48
+ "host-key-check": {
49
+ "type": "boolean",
50
+ "description": "Whether to perform host key validation when connecting over SSH"
51
+ },
52
+ "sudo-password": {
53
+ "type": "string",
54
+ "description": "Password to use when changing users via run-as"
55
+ }
56
+ },
57
+ "oneOf": [
58
+ { "required": ["password"] },
59
+ { "required": ["private-key-content"] }
60
+ ],
61
+ "required": ["hostname", "user"],
62
+ "additionalProperties": false
63
+ },
64
+ "task": { "$ref": "file:task"},
65
+ "parameters": {
66
+ "type": "object",
67
+ "description": "JSON formatted parameters to be provided to task"
68
+ }
69
+ },
70
+ "required": ["target", "task"]
71
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "id": "file:task",
3
+ "$schema": "http://json-schema.org/draft-04/schema#",
4
+ "title": "Task",
5
+ "description": "Task schema for bolt-server",
6
+ "type": "object",
7
+ "description": "The task is a JSON object which includes the following keys",
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "Task name"
12
+ },
13
+ "metadata": {
14
+ "type": "object",
15
+ "description": "The metadata object is optional, and contains metadata about the task being run",
16
+ "properties": {
17
+ "description": {
18
+ "type": "string",
19
+ "description": "The task description from it's metadata"
20
+ },
21
+ "parameters": {
22
+ "type": "object",
23
+ "description": "Object whose keys are parameter names, and values are objects",
24
+ "properties": {
25
+ "description": {
26
+ "type": "string",
27
+ "description": "Parameter description"
28
+ },
29
+ "type": {
30
+ "type": "string",
31
+ "description": "The type the parameter should accept"
32
+ }
33
+ }
34
+ }
35
+ },
36
+ "additionalProperties": false
37
+ },
38
+ "file": {
39
+ "type": "object",
40
+ "description": "File name and content",
41
+ "properties": {
42
+ "filename": {
43
+ "type": "string",
44
+ "description": "Name of the task file"
45
+ },
46
+ "file_content": {
47
+ "type": "string",
48
+ "description": "Task's base64 encoded file content"
49
+ }
50
+ },
51
+ "required": ["filename", "file_content"],
52
+ "additionalProperties": false
53
+ }
54
+ },
55
+ "required": ["name", "file"],
56
+ "additionalProperties": false
57
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "WinRm run_task request",
4
+ "description": "POST winrm/run_task request schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "target": {
8
+ "type": "object",
9
+ "description": "Target information to run task on",
10
+ "properties": {
11
+ "hostname": {
12
+ "type": "string",
13
+ "description": "Target identifier"
14
+ },
15
+ "user": {
16
+ "type": "string",
17
+ "description": "Login user"
18
+ },
19
+ "password": {
20
+ "type": "string",
21
+ "description": "Password for SSH transport authentication"
22
+ },
23
+ "port": {
24
+ "type": "integer",
25
+ "description": "Connection port"
26
+ },
27
+ "connect-timeout": {
28
+ "type": "integer",
29
+ "description": "How long Bolt should wait when establishing connections"
30
+ },
31
+ "tmpdir": {
32
+ "type": "string",
33
+ "description": "The directory to upload and execute temporary files on the target"
34
+ },
35
+ "ssl": {
36
+ "type": "boolean",
37
+ "description": "When true, Bolt will use https connections for WinRM"
38
+ },
39
+ "ssl-verify": {
40
+ "type": "boolean",
41
+ "description": "When true, verifies the targets certificate matches the cacert"
42
+ },
43
+ "cacert": {
44
+ "type": "string",
45
+ "description": "The path to the CA certificate"
46
+ },
47
+ "extensions": {
48
+ "type": "array",
49
+ "description": "List of file extensions that are accepted for scripts or tasks"
50
+ }
51
+ },
52
+ "required": ["hostname", "user", "password"],
53
+ "additionalProperties": false
54
+ },
55
+ "task": { "$ref": "file:task"},
56
+ "parameters": {
57
+ "type": "object",
58
+ "description": "JSON formatted parameters to be provided to task"
59
+ }
60
+ },
61
+ "required": ["target", "task"]
62
+ }
@@ -4,15 +4,41 @@ require 'sinatra'
4
4
  require 'bolt'
5
5
  require 'bolt/task'
6
6
  require 'json'
7
+ require 'json-schema'
7
8
 
8
9
  class TransportAPI < Sinatra::Base
9
10
  # This disables Sinatra's error page generation
10
11
  set :show_exceptions, false
11
12
 
13
+ def initialize(app = nil)
14
+ @schemas = {
15
+ "ssh-run_task" => JSON.parse(File.read(File.join(__dir__, 'schemas', 'ssh-run_task.json'))),
16
+ "winrm-run_task" => JSON.parse(File.read(File.join(__dir__, 'schemas', 'winrm-run_task.json')))
17
+ }
18
+ shared_schema = JSON::Schema.new(JSON.parse(File.read(File.join(__dir__, 'schemas', 'task.json'))),
19
+ Addressable::URI.parse("file:task"))
20
+ JSON::Validator.add_schema(shared_schema)
21
+
22
+ @executor = Bolt::Executor.new(0, load_config: false)
23
+
24
+ super(app)
25
+ end
26
+
12
27
  get '/' do
13
28
  200
14
29
  end
15
30
 
31
+ if ENV['RACK_ENV'] == 'dev'
32
+ get '/admin/gc' do
33
+ GC.start
34
+ 200
35
+ end
36
+ end
37
+
38
+ get '/admin/gc_stat' do
39
+ [200, GC.stat.to_json]
40
+ end
41
+
16
42
  get '/500_error' do
17
43
  raise 'Unexpected error'
18
44
  end
@@ -21,13 +47,13 @@ class TransportAPI < Sinatra::Base
21
47
  content_type :json
22
48
 
23
49
  body = JSON.parse(request.body.read)
50
+ schema_error = JSON::Validator.fully_validate(@schemas["ssh-run_task"], body)
51
+ return [400, schema_error.join] if schema_error.any?
52
+
24
53
  keys = %w[user password port ssh-key-content connect-timeout run-as-command run-as
25
54
  tmpdir host-key-check known-hosts-content private-key-content sudo-password]
26
55
  opts = body['target'].select { |k, _| keys.include? k }
27
56
 
28
- if opts['private-key-content'] && opts['password']
29
- return [400, "Only include one of 'password' and 'private-key-content'"]
30
- end
31
57
  if opts['private-key-content']
32
58
  opts['private-key'] = { 'key-data' => opts['private-key-content'] }
33
59
  opts.delete('private-key-content')
@@ -37,10 +63,8 @@ class TransportAPI < Sinatra::Base
37
63
  task = Bolt::Task.new(body['task'])
38
64
  parameters = body['parameters'] || {}
39
65
 
40
- executor = Bolt::Executor.new(load_config: false)
41
-
42
66
  # Since this will only be on one node we can just return the first result
43
- results = executor.run_task(target, task, parameters)
67
+ results = @executor.run_task(target, task, parameters)
44
68
  [200, results.first.to_json]
45
69
  end
46
70
 
@@ -48,6 +72,9 @@ class TransportAPI < Sinatra::Base
48
72
  content_type :json
49
73
 
50
74
  body = JSON.parse(request.body.read)
75
+ schema_error = JSON::Validator.fully_validate(@schemas["winrm-run_task"], body)
76
+ return [400, schema_error.join] if schema_error.any?
77
+
51
78
  keys = %w[user password port connect-timeout ssl ssl-verify tmpdir cacert extensions]
52
79
  opts = body['target'].select { |k, _| keys.include? k }
53
80
  opts['protocol'] = 'winrm'
@@ -55,10 +82,8 @@ class TransportAPI < Sinatra::Base
55
82
  task = Bolt::Task.new(body['task'])
56
83
  parameters = body['parameters'] || {}
57
84
 
58
- executor = Bolt::Executor.new(load_config: false)
59
-
60
85
  # Since this will only be on one node we can just return the first result
61
- results = executor.run_task(target, task, parameters)
86
+ results = @executor.run_task(target, task, parameters)
62
87
  [200, results.first.to_json]
63
88
  end
64
89
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.0
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-05 00:00:00.000000000 Z
11
+ date: 2018-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '1.1'
145
+ version: '1.3'
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '1.1'
152
+ version: '1.3'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: CFPropertyList
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -357,6 +357,9 @@ files:
357
357
  - lib/bolt/util/puppet_log_level.rb
358
358
  - lib/bolt/version.rb
359
359
  - lib/bolt_ext/puppetdb_inventory.rb
360
+ - lib/bolt_ext/schemas/ssh-run_task.json
361
+ - lib/bolt_ext/schemas/task.json
362
+ - lib/bolt_ext/schemas/winrm-run_task.json
360
363
  - lib/bolt_ext/server.rb
361
364
  - lib/bolt_ext/server_acl.rb
362
365
  - lib/bolt_ext/server_config.rb