bolt 3.15.0 → 3.18.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 +4 -4
- data/Puppetfile +7 -7
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +1 -4
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -4
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +1 -4
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +1 -4
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +1 -4
- data/lib/bolt/analytics.rb +4 -21
- data/lib/bolt/application.rb +627 -0
- data/lib/bolt/applicator.rb +7 -6
- data/lib/bolt/apply_inventory.rb +3 -3
- data/lib/bolt/apply_result.rb +2 -2
- data/lib/bolt/bolt_option_parser.rb +27 -3
- data/lib/bolt/catalog.rb +10 -11
- data/lib/bolt/cli.rb +607 -809
- data/lib/bolt/config/modulepath.rb +1 -1
- data/lib/bolt/config/options.rb +32 -13
- data/lib/bolt/config/transport/base.rb +4 -4
- data/lib/bolt/config/transport/docker.rb +2 -2
- data/lib/bolt/config/transport/local.rb +2 -2
- data/lib/bolt/config/transport/lxd.rb +2 -2
- data/lib/bolt/config/transport/orch.rb +2 -2
- data/lib/bolt/config/transport/podman.rb +2 -2
- data/lib/bolt/config/transport/remote.rb +2 -2
- data/lib/bolt/config/transport/ssh.rb +2 -2
- data/lib/bolt/config/transport/winrm.rb +2 -2
- data/lib/bolt/config.rb +5 -5
- data/lib/bolt/container_result.rb +2 -2
- data/lib/bolt/error.rb +1 -1
- data/lib/bolt/executor.rb +17 -14
- data/lib/bolt/fiber_executor.rb +9 -5
- data/lib/bolt/inventory/group.rb +4 -4
- data/lib/bolt/inventory/inventory.rb +64 -41
- data/lib/bolt/inventory/options.rb +1 -1
- data/lib/bolt/inventory/target.rb +1 -1
- data/lib/bolt/inventory.rb +10 -17
- data/lib/bolt/module_installer/installer.rb +2 -2
- data/lib/bolt/module_installer/puppetfile/forge_module.rb +1 -1
- data/lib/bolt/module_installer/puppetfile/git_module.rb +1 -1
- data/lib/bolt/module_installer/puppetfile/module.rb +1 -1
- data/lib/bolt/module_installer/puppetfile.rb +27 -13
- data/lib/bolt/module_installer/resolver.rb +3 -3
- data/lib/bolt/module_installer/specs/forge_spec.rb +1 -1
- data/lib/bolt/module_installer/specs/git_spec.rb +1 -1
- data/lib/bolt/module_installer/specs.rb +3 -3
- data/lib/bolt/module_installer.rb +6 -6
- data/lib/bolt/node/errors.rb +1 -1
- data/lib/bolt/node/output.rb +1 -1
- data/lib/bolt/outputter/human.rb +85 -34
- data/lib/bolt/outputter/json.rb +63 -38
- data/lib/bolt/outputter/logger.rb +1 -1
- data/lib/bolt/outputter/rainbow.rb +1 -1
- data/lib/bolt/outputter.rb +4 -4
- data/lib/bolt/pal/logging.rb +1 -1
- data/lib/bolt/pal/yaml_plan/evaluator.rb +1 -1
- data/lib/bolt/pal/yaml_plan/loader.rb +2 -2
- data/lib/bolt/pal/yaml_plan/step.rb +11 -11
- data/lib/bolt/pal/yaml_plan/transpiler.rb +3 -3
- data/lib/bolt/pal/yaml_plan.rb +2 -2
- data/lib/bolt/pal.rb +11 -11
- data/lib/bolt/plan_creator.rb +88 -29
- data/lib/bolt/plan_future.rb +11 -6
- data/lib/bolt/plan_result.rb +3 -3
- data/lib/bolt/plugin/cache.rb +2 -2
- data/lib/bolt/plugin/module.rb +1 -1
- data/lib/bolt/plugin.rb +18 -24
- data/lib/bolt/project.rb +4 -11
- data/lib/bolt/project_manager/config_migrator.rb +1 -1
- data/lib/bolt/project_manager/inventory_migrator.rb +1 -1
- data/lib/bolt/project_manager/migrator.rb +1 -1
- data/lib/bolt/project_manager/module_migrator.rb +5 -5
- data/lib/bolt/project_manager.rb +23 -4
- data/lib/bolt/puppetdb/config.rb +1 -1
- data/lib/bolt/puppetdb.rb +3 -3
- data/lib/bolt/result.rb +1 -1
- data/lib/bolt/result_set.rb +2 -1
- data/lib/bolt/shell/bash.rb +12 -2
- data/lib/bolt/shell/powershell.rb +9 -2
- data/lib/bolt/shell.rb +2 -2
- data/lib/bolt/target.rb +2 -2
- data/lib/bolt/transport/base.rb +1 -1
- data/lib/bolt/transport/docker/connection.rb +1 -1
- data/lib/bolt/transport/docker.rb +2 -2
- data/lib/bolt/transport/local/connection.rb +19 -3
- data/lib/bolt/transport/local.rb +3 -3
- data/lib/bolt/transport/lxd/connection.rb +1 -1
- data/lib/bolt/transport/lxd.rb +4 -4
- data/lib/bolt/transport/orch/connection.rb +13 -1
- data/lib/bolt/transport/orch.rb +2 -2
- data/lib/bolt/transport/podman/connection.rb +1 -1
- data/lib/bolt/transport/podman.rb +2 -2
- data/lib/bolt/transport/remote.rb +2 -2
- data/lib/bolt/transport/simple.rb +3 -3
- data/lib/bolt/transport/ssh/connection.rb +3 -3
- data/lib/bolt/transport/ssh.rb +5 -5
- data/lib/bolt/transport/winrm/connection.rb +2 -2
- data/lib/bolt/transport/winrm.rb +3 -3
- data/lib/bolt/util.rb +8 -31
- data/lib/bolt/validator.rb +1 -1
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt.rb +1 -1
- data/lib/bolt_server/file_cache.rb +12 -0
- data/lib/bolt_server/schemas/action-apply.json +32 -0
- data/lib/bolt_server/schemas/action-apply_prep.json +19 -0
- data/lib/bolt_server/transport_app.rb +129 -26
- data/lib/bolt_spec/bolt_context.rb +7 -5
- data/lib/bolt_spec/plans/mock_executor.rb +3 -3
- data/lib/bolt_spec/run.rb +1 -1
- data/libexec/bolt_catalog +1 -1
- metadata +7 -5
- data/lib/bolt/secret.rb +0 -37
@@ -3,13 +3,15 @@
|
|
3
3
|
require 'open3'
|
4
4
|
require 'fileutils'
|
5
5
|
require 'tempfile'
|
6
|
-
|
7
|
-
|
6
|
+
require_relative '../../../bolt/node/output'
|
7
|
+
require_relative '../../../bolt/util'
|
8
8
|
|
9
9
|
module Bolt
|
10
10
|
module Transport
|
11
11
|
class Local < Simple
|
12
12
|
class Connection
|
13
|
+
RUBY_ENV_VARS = %w[GEM_PATH GEM_HOME RUBYLIB RUBYLIB_PREFIX RUBYOPT RUBYPATH RUBYSHELL].freeze
|
14
|
+
|
13
15
|
attr_accessor :user, :logger, :target
|
14
16
|
|
15
17
|
def initialize(target)
|
@@ -68,7 +70,21 @@ module Bolt
|
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
71
|
-
|
73
|
+
# Only do this if bundled-ruby is set to false, not nil
|
74
|
+
ruby_env_vars = if target.transport_config['bundled-ruby'] == false
|
75
|
+
RUBY_ENV_VARS.each_with_object({}) do |e, acc|
|
76
|
+
acc[e] = ENV["BOLT_ORIG_#{e}"] if ENV["BOLT_ORIG_#{e}"]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
if target.transport_config['bundled-ruby'] == false &&
|
81
|
+
Gem.loaded_specs.keys.include?('bundler')
|
82
|
+
Bundler.with_unbundled_env do
|
83
|
+
Open3.popen3(ruby_env_vars || {}, *command)
|
84
|
+
end
|
85
|
+
else
|
86
|
+
Open3.popen3(ruby_env_vars || {}, *command)
|
87
|
+
end
|
72
88
|
end
|
73
89
|
|
74
90
|
# This is used by the Bash shell to decide whether to `cd` before
|
data/lib/bolt/transport/local.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require_relative '../../bolt/logger'
|
4
|
+
require_relative '../../bolt/transport/simple'
|
5
5
|
|
6
6
|
module Bolt
|
7
7
|
module Transport
|
@@ -21,4 +21,4 @@ module Bolt
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
require_relative 'local/connection'
|
data/lib/bolt/transport/lxd.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative '../../bolt/logger'
|
4
|
+
require_relative '../../bolt/node/errors'
|
5
|
+
require_relative '../../bolt/transport/simple'
|
6
6
|
|
7
7
|
module Bolt
|
8
8
|
module Transport
|
@@ -23,4 +23,4 @@ module Bolt
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
require_relative 'lxd/connection'
|
@@ -36,7 +36,8 @@ module Bolt
|
|
36
36
|
end
|
37
37
|
logger.debug("Creating orchestrator client for #{client_opts}")
|
38
38
|
@client = OrchestratorClient.new(client_opts, true)
|
39
|
-
@
|
39
|
+
@plan_context = plan_context
|
40
|
+
@plan_job = start_plan(@plan_context)
|
40
41
|
logger.debug("Started plan #{@plan_job}")
|
41
42
|
@environment = opts["task-environment"]
|
42
43
|
end
|
@@ -87,6 +88,17 @@ module Bolt
|
|
87
88
|
def run_task(targets, task, arguments, options)
|
88
89
|
body = build_request(targets, task, arguments, options[:description])
|
89
90
|
@client.run_task(body)
|
91
|
+
rescue OrchestratorClient::ApiError => e
|
92
|
+
if e.data['kind'] == 'puppetlabs.orchestrator/plan-already-finished'
|
93
|
+
@logger.debug("Retrying the task")
|
94
|
+
# Instead of recursing, just retry once
|
95
|
+
@plan_job = start_plan(@plan_context)
|
96
|
+
# Rebuild the request with the new plan job ID
|
97
|
+
body = build_request(targets, task, arguments, options[:description])
|
98
|
+
@client.run_task(body)
|
99
|
+
else
|
100
|
+
raise e
|
101
|
+
end
|
90
102
|
end
|
91
103
|
|
92
104
|
def query_inventory(targets)
|
data/lib/bolt/transport/orch.rb
CHANGED
@@ -4,8 +4,8 @@ require 'base64'
|
|
4
4
|
require 'find'
|
5
5
|
require 'json'
|
6
6
|
require 'pathname'
|
7
|
-
|
8
|
-
|
7
|
+
require_relative '../../bolt/transport/base'
|
8
|
+
require_relative 'orch/connection'
|
9
9
|
|
10
10
|
module Bolt
|
11
11
|
module Transport
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'json'
|
4
4
|
require 'shellwords'
|
5
|
-
|
5
|
+
require_relative '../../bolt/transport/base'
|
6
6
|
|
7
7
|
module Bolt
|
8
8
|
module Transport
|
@@ -16,4 +16,4 @@ module Bolt
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
require_relative 'podman/connection'
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'logging'
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
require_relative '../../bolt/result'
|
5
|
+
require_relative '../../bolt/shell'
|
6
|
+
require_relative '../../bolt/transport/base'
|
7
7
|
|
8
8
|
module Bolt
|
9
9
|
module Transport
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'logging'
|
4
4
|
require 'shellwords'
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
require_relative '../../../bolt/node/errors'
|
6
|
+
require_relative '../../../bolt/node/output'
|
7
|
+
require_relative '../../../bolt/util'
|
8
8
|
|
9
9
|
module Bolt
|
10
10
|
module Transport
|
data/lib/bolt/transport/ssh.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require_relative '../../bolt/logger'
|
4
|
+
require_relative '../../bolt/node/errors'
|
5
|
+
require_relative '../../bolt/transport/simple'
|
6
6
|
|
7
7
|
module Bolt
|
8
8
|
module Transport
|
@@ -44,5 +44,5 @@ module Bolt
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
require_relative 'ssh/connection'
|
48
|
+
require_relative 'ssh/exec_connection'
|
data/lib/bolt/transport/winrm.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require_relative '../../bolt/node/errors'
|
4
|
+
require_relative '../../bolt/transport/base'
|
5
5
|
|
6
6
|
module Bolt
|
7
7
|
module Transport
|
@@ -30,4 +30,4 @@ module Bolt
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
require_relative 'winrm/connection'
|
data/lib/bolt/util.rb
CHANGED
@@ -103,7 +103,7 @@ module Bolt
|
|
103
103
|
# absolute path or Puppet module syntax lookup. Returns the path to the
|
104
104
|
# file if found, or nil.
|
105
105
|
#
|
106
|
-
def find_file_from_scope(file, scope
|
106
|
+
def find_file_from_scope(file, scope)
|
107
107
|
# If we got an absolute path, just return that.
|
108
108
|
return file if Pathname.new(file).absolute?
|
109
109
|
|
@@ -112,44 +112,21 @@ module Bolt
|
|
112
112
|
mod_path = scope.compiler.environment.module(module_name)&.path
|
113
113
|
|
114
114
|
# Search the module for the file, falling back to new-style paths if enabled.
|
115
|
-
|
115
|
+
search_module(mod_path, file_pattern) if mod_path
|
116
116
|
end
|
117
117
|
|
118
|
-
# This
|
119
|
-
#
|
120
|
-
#
|
121
|
-
# searches subdirectories in the module in order of precedence.
|
118
|
+
# This searches a module for files under 'files/' or 'scripts/', falling
|
119
|
+
# back to the new style of file loading. It takes the absolute path to the
|
120
|
+
# module root and the relative path provided by the user.
|
122
121
|
#
|
123
|
-
def
|
124
|
-
# If the first part of the path is 'scripts' or 'files', the path may
|
125
|
-
# be a new-style file location and should fall back to the new path.
|
126
|
-
subdir_or_file = split_path(module_file).first
|
127
|
-
case subdir_or_file
|
128
|
-
# For any subdirs that may indicate the user passed a new-style path,
|
129
|
-
# first look in 'mymod/files/<relative_path>' (old-style) then fall
|
130
|
-
# back to 'mymod/<relative_path>' (new-style) if enabled.
|
131
|
-
when 'scripts', 'files'
|
132
|
-
search_module(module_path, module_file, fallback)
|
133
|
-
else
|
134
|
-
# If the path definitely isn't new-style, only look in the 'files/'
|
135
|
-
# directory.
|
136
|
-
search_module(module_path, module_file)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# This searches a module for files under 'files/' or 'scripts/',
|
141
|
-
# optionally falling back to the new style of file loading. It takes the
|
142
|
-
# absolute path to the module root, the relative path provided by the
|
143
|
-
# user, and whether to fall back to the new-style script loading if the
|
144
|
-
# file isn't found in 'files/'.
|
145
|
-
#
|
146
|
-
private def search_module(module_path, module_file, fallback = false)
|
122
|
+
def search_module(module_path, module_file)
|
147
123
|
if File.exist?(File.join(module_path, 'files', module_file))
|
148
124
|
File.join(module_path, 'files', module_file)
|
149
|
-
elsif File.exist?(File.join(module_path, module_file))
|
125
|
+
elsif File.exist?(File.join(module_path, module_file))
|
150
126
|
File.join(module_path, module_file)
|
151
127
|
end
|
152
128
|
end
|
129
|
+
alias find_file_in_module search_module
|
153
130
|
|
154
131
|
# Copied directly from puppet/lib/puppet/parser/files.rb
|
155
132
|
#
|
data/lib/bolt/validator.rb
CHANGED
data/lib/bolt/version.rb
CHANGED
data/lib/bolt.rb
CHANGED
@@ -182,5 +182,17 @@ module BoltServer
|
|
182
182
|
end
|
183
183
|
end
|
184
184
|
end
|
185
|
+
|
186
|
+
def get_cached_project_file(versioned_project, file_name)
|
187
|
+
file_dir = create_cache_dir(versioned_project)
|
188
|
+
file_path = File.join(file_dir, file_name)
|
189
|
+
serial_execute { File.read(file_path) if File.exist?(file_path) }
|
190
|
+
end
|
191
|
+
|
192
|
+
def cache_project_file(versioned_project, file_name, data)
|
193
|
+
file_dir = create_cache_dir(versioned_project)
|
194
|
+
file_path = File.join(file_dir, file_name)
|
195
|
+
serial_execute { File.open(file_path, 'w') { |f| f.write(data) } }
|
196
|
+
end
|
185
197
|
end
|
186
198
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
3
|
+
"title": "apply request",
|
4
|
+
"description": "POST <transport>/apply request schema",
|
5
|
+
"type": "object",
|
6
|
+
"properties": {
|
7
|
+
"versioned_project": {
|
8
|
+
"type": "string",
|
9
|
+
"description": "Project from which to load code"
|
10
|
+
},
|
11
|
+
"parameters": {
|
12
|
+
"type": "object",
|
13
|
+
"properties": {
|
14
|
+
"catalog": {
|
15
|
+
"type": "object",
|
16
|
+
"description": "Compiled catalog to apply"
|
17
|
+
},
|
18
|
+
"apply_options": {
|
19
|
+
"type": "object",
|
20
|
+
"description": "Options for application of a catalog"
|
21
|
+
}
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"job_id": {
|
25
|
+
"type": "integer",
|
26
|
+
"description": "job-id associated with request"
|
27
|
+
},
|
28
|
+
"target": { "$ref": "partial:target-any" }
|
29
|
+
},
|
30
|
+
"required": ["target", "versioned_project", "parameters", "job_id"],
|
31
|
+
"additionalProperties": false
|
32
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
3
|
+
"title": "apply_prep request",
|
4
|
+
"description": "POST <transport>/apply_prep request schema",
|
5
|
+
"type": "object",
|
6
|
+
"properties": {
|
7
|
+
"versioned_project": {
|
8
|
+
"type": "String",
|
9
|
+
"description": "Project from which to load code"
|
10
|
+
},
|
11
|
+
"target": { "$ref": "partial:target-any" },
|
12
|
+
"job_id": {
|
13
|
+
"type": "integer",
|
14
|
+
"description": "job-id associated with request"
|
15
|
+
}
|
16
|
+
},
|
17
|
+
"required": ["target", "versioned_project", "job_id"],
|
18
|
+
"additionalProperties": false
|
19
|
+
}
|
@@ -43,6 +43,8 @@ module BoltServer
|
|
43
43
|
transport-ssh
|
44
44
|
transport-winrm
|
45
45
|
connect-data
|
46
|
+
action-apply_prep
|
47
|
+
action-apply
|
46
48
|
].freeze
|
47
49
|
|
48
50
|
# PE_BOLTLIB_PATH is intended to function exactly like the BOLTLIB_PATH used
|
@@ -75,6 +77,12 @@ module BoltServer
|
|
75
77
|
# This is needed until the PAL is threadsafe.
|
76
78
|
@pal_mutex = Mutex.new
|
77
79
|
|
80
|
+
# Avoid redundant plugin tarbal construction
|
81
|
+
@plugin_mutex = Mutex.new
|
82
|
+
|
83
|
+
# Avoid redundant project_task metadata construction
|
84
|
+
@task_metadata_mutex = Mutex.new
|
85
|
+
|
78
86
|
@logger = Bolt::Logger.logger(self)
|
79
87
|
|
80
88
|
super(nil)
|
@@ -118,12 +126,7 @@ module BoltServer
|
|
118
126
|
end
|
119
127
|
end
|
120
128
|
|
121
|
-
def
|
122
|
-
validate_schema(@schemas["action-run_task"], body)
|
123
|
-
|
124
|
-
task_data = body['task']
|
125
|
-
task = Bolt::Task::PuppetServer.new(task_data['name'], task_data['metadata'], task_data['files'], @file_cache)
|
126
|
-
parameters = body['parameters'] || {}
|
129
|
+
def task_helper(target, task, parameters)
|
127
130
|
# Wrap parameters marked with '"sensitive": true' in the task metadata with a
|
128
131
|
# Sensitive wrapper type. This way it's not shown in logs.
|
129
132
|
if (param_spec = task.parameters)
|
@@ -142,6 +145,102 @@ module BoltServer
|
|
142
145
|
end
|
143
146
|
end
|
144
147
|
|
148
|
+
def run_task(target, body)
|
149
|
+
validate_schema(@schemas["action-run_task"], body)
|
150
|
+
|
151
|
+
task_data = body['task']
|
152
|
+
task = Bolt::Task::PuppetServer.new(task_data['name'], task_data['metadata'], task_data['files'], @file_cache)
|
153
|
+
task_helper(target, task, body['parameters'] || {})
|
154
|
+
end
|
155
|
+
|
156
|
+
def extract_install_task(target)
|
157
|
+
unless target.plugin_hooks['puppet_library']['task']
|
158
|
+
raise BoltServer::RequestError,
|
159
|
+
"Target must have 'task' plugin hook"
|
160
|
+
end
|
161
|
+
install_task = target.plugin_hooks['puppet_library']['task'].split('::', 2)
|
162
|
+
install_task << 'init' if install_task.count == 1
|
163
|
+
install_task
|
164
|
+
end
|
165
|
+
|
166
|
+
# This helper is responsible for computing or retrieving from the cache a plugin tarball. There are
|
167
|
+
# two supported plugin types 'fact_plugins', and 'all_plugins'. Note that this is cached based on
|
168
|
+
# versioned_project as there are no plugins in the "builtin content" directory
|
169
|
+
def plugin_tarball(versioned_project, tarball_type)
|
170
|
+
tarball_types = %w[fact_plugins all_plugins]
|
171
|
+
unless tarball_types.include?(tarball_type)
|
172
|
+
raise ArgumentError,
|
173
|
+
"tarball_type must be one of: #{tarball_types.join(', ')}"
|
174
|
+
end
|
175
|
+
# lock this so that in the case an apply/apply_prep with multiple targets hits this endpoint
|
176
|
+
# the tarball computation only happens once (all the other targets will just need to read the cached data)
|
177
|
+
@plugin_mutex.synchronize do
|
178
|
+
if (tarball = @file_cache.get_cached_project_file(versioned_project, tarball_type))
|
179
|
+
tarball
|
180
|
+
else
|
181
|
+
new_tarball = build_project_plugins_tarball(versioned_project) do |mod|
|
182
|
+
search_dirs = []
|
183
|
+
search_dirs << mod.plugins if mod.plugins?
|
184
|
+
search_dirs << mod.pluginfacts if mod.pluginfacts?
|
185
|
+
if tarball_type == 'all_plugins'
|
186
|
+
search_dirs << mod.files if mod.files?
|
187
|
+
search_dirs << mod.scripts if mod.scripts?
|
188
|
+
type_files = "#{mod.path}/types"
|
189
|
+
search_dirs << type_files if File.exist?(type_files)
|
190
|
+
end
|
191
|
+
search_dirs
|
192
|
+
end
|
193
|
+
@file_cache.cache_project_file(versioned_project, tarball_type, new_tarball)
|
194
|
+
new_tarball
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# This helper is responsible for computing or retrieving task metadata for a project.
|
200
|
+
# It expects task name in segments and uses the combination of task name and versioned_project
|
201
|
+
# as a unique identifier for caching in addition to the job_id. The job id is added to protect against
|
202
|
+
# a case where the buildtin content is update (where the apply_helpers would be managed)
|
203
|
+
def project_task_metadata(versioned_project, task_name_segments, job_id)
|
204
|
+
cached_file_name = "#{task_name_segments.join('_')}_#{job_id}"
|
205
|
+
# lock this so that in the case an apply/apply_prep with multiple targets hits this endpoint the
|
206
|
+
# metadata computation will only be computed once, then the cache will be read.
|
207
|
+
@task_metadata_mutex.synchronize do
|
208
|
+
if (metadata = @file_cache.get_cached_project_file(versioned_project, cached_file_name))
|
209
|
+
JSON.parse(metadata)
|
210
|
+
else
|
211
|
+
new_metadata = in_bolt_project(versioned_project) do |context|
|
212
|
+
ps_parameters = {
|
213
|
+
'versioned_project' => versioned_project
|
214
|
+
}
|
215
|
+
pe_task_info(context[:pal], *task_name_segments, ps_parameters)
|
216
|
+
end
|
217
|
+
@file_cache.cache_project_file(versioned_project, cached_file_name, new_metadata.to_json)
|
218
|
+
new_metadata
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def apply_prep(target, body)
|
224
|
+
validate_schema(@schemas["action-apply_prep"], body)
|
225
|
+
plugins_tarball = plugin_tarball(body['versioned_project'], 'fact_plugins')
|
226
|
+
install_task_segments = extract_install_task(target.first)
|
227
|
+
task_data = project_task_metadata(body['versioned_project'], install_task_segments, body["job_id"])
|
228
|
+
task = Bolt::Task::PuppetServer.new(task_data['name'], task_data['metadata'], task_data['files'], @file_cache)
|
229
|
+
install_task_result = task_helper(target, task, target.first.plugin_hooks['puppet_library']['parameters'] || {})
|
230
|
+
return install_task_result unless install_task_result.ok
|
231
|
+
task_data = project_task_metadata(body['versioned_project'], %w[apply_helpers custom_facts], body["job_id"])
|
232
|
+
task = Bolt::Task::PuppetServer.new(task_data['name'], task_data['metadata'], task_data['files'], @file_cache)
|
233
|
+
task_helper(target, task, { 'plugins' => plugins_tarball })
|
234
|
+
end
|
235
|
+
|
236
|
+
def apply(target, body)
|
237
|
+
validate_schema(@schemas["action-apply"], body)
|
238
|
+
plugins_tarball = plugin_tarball(body['versioned_project'], 'all_plugins')
|
239
|
+
task_data = project_task_metadata(body['versioned_project'], %w[apply_helpers apply_catalog], body["job_id"])
|
240
|
+
task = Bolt::Task::PuppetServer.new(task_data['name'], task_data['metadata'], task_data['files'], @file_cache)
|
241
|
+
task_helper(target, task, body['parameters'].merge({ 'plugins' => plugins_tarball }))
|
242
|
+
end
|
243
|
+
|
145
244
|
def run_command(target, body)
|
146
245
|
validate_schema(@schemas["action-run_command"], body)
|
147
246
|
command = body['command']
|
@@ -370,13 +469,26 @@ module BoltServer
|
|
370
469
|
pal.in_bolt_compiler do
|
371
470
|
mod = Puppet.lookup(:current_environment).module(module_name)
|
372
471
|
raise BoltServer::RequestError, "module_name: '#{module_name}' does not exist" unless mod
|
373
|
-
|
472
|
+
# First, look in the 'old' location <module>/files/<path>.
|
473
|
+
# If not found, and the path starts with `files` or `scripts`, munge
|
474
|
+
# the path and look inside that directory.
|
475
|
+
if (abs_path = mod.file(file))
|
476
|
+
abs_path
|
477
|
+
else
|
478
|
+
subdir, relative_path = file.split(File::SEPARATOR, 2)
|
479
|
+
case subdir
|
480
|
+
when 'files'
|
481
|
+
mod.file(relative_path)
|
482
|
+
when 'scripts'
|
483
|
+
mod.script(relative_path)
|
484
|
+
end
|
485
|
+
end
|
374
486
|
end
|
375
487
|
end
|
376
488
|
|
377
489
|
unless abs_file_path
|
378
490
|
raise BoltServer::RequestError,
|
379
|
-
"file: '#{file}' does not exist inside
|
491
|
+
"file: '#{file}' does not exist inside #{module_name} 'files' or 'scripts' directories"
|
380
492
|
end
|
381
493
|
|
382
494
|
fileset = Puppet::FileServing::Fileset.new(abs_file_path, 'recurse' => 'yes')
|
@@ -476,6 +588,8 @@ module BoltServer
|
|
476
588
|
run_task
|
477
589
|
run_script
|
478
590
|
upload_file
|
591
|
+
apply
|
592
|
+
apply_prep
|
479
593
|
].freeze
|
480
594
|
|
481
595
|
def make_ssh_target(target_hash)
|
@@ -499,7 +613,8 @@ module BoltServer
|
|
499
613
|
'config' => {
|
500
614
|
'transport' => 'ssh',
|
501
615
|
'ssh' => opts.slice(*Bolt::Config::Transport::SSH.options)
|
502
|
-
}
|
616
|
+
},
|
617
|
+
'plugin_hooks' => target_hash['plugin_hooks']
|
503
618
|
}
|
504
619
|
|
505
620
|
inventory = Bolt::Inventory.empty
|
@@ -537,7 +652,8 @@ module BoltServer
|
|
537
652
|
'config' => {
|
538
653
|
'transport' => 'winrm',
|
539
654
|
'winrm' => opts.slice(*Bolt::Config::Transport::WinRM.options)
|
540
|
-
}
|
655
|
+
},
|
656
|
+
'plugin_hooks' => target_hash['plugin_hooks']
|
541
657
|
}
|
542
658
|
|
543
659
|
inventory = Bolt::Inventory.empty
|
@@ -730,7 +846,7 @@ module BoltServer
|
|
730
846
|
}
|
731
847
|
|
732
848
|
connect_plugin = BoltServer::Plugin::PuppetConnectData.new(body['puppet_connect_data'])
|
733
|
-
plugins = Bolt::Plugin.
|
849
|
+
plugins = Bolt::Plugin.new(context[:config], context[:pal], load_plugins: false)
|
734
850
|
plugins.add_plugin(connect_plugin)
|
735
851
|
%w[aws_inventory azure_inventory gcloud_inventory].each do |plugin_name|
|
736
852
|
plugins.add_module_plugin(plugin_name) if plugins.known_plugin?(plugin_name)
|
@@ -756,12 +872,7 @@ module BoltServer
|
|
756
872
|
raise BoltServer::RequestError, "'versioned_project' is a required argument" if params['versioned_project'].nil?
|
757
873
|
content_type :json
|
758
874
|
|
759
|
-
plugins_tarball =
|
760
|
-
search_dirs = []
|
761
|
-
search_dirs << mod.plugins if mod.plugins?
|
762
|
-
search_dirs << mod.pluginfacts if mod.pluginfacts?
|
763
|
-
search_dirs
|
764
|
-
end
|
875
|
+
plugins_tarball = plugin_tarball(params['versioned_project'], 'fact_plugins')
|
765
876
|
|
766
877
|
[200, plugins_tarball.to_json]
|
767
878
|
end
|
@@ -773,15 +884,7 @@ module BoltServer
|
|
773
884
|
raise BoltServer::RequestError, "'versioned_project' is a required argument" if params['versioned_project'].nil?
|
774
885
|
content_type :json
|
775
886
|
|
776
|
-
plugins_tarball =
|
777
|
-
search_dirs = []
|
778
|
-
search_dirs << mod.plugins if mod.plugins?
|
779
|
-
search_dirs << mod.pluginfacts if mod.pluginfacts?
|
780
|
-
search_dirs << mod.files if mod.files?
|
781
|
-
type_files = "#{mod.path}/types"
|
782
|
-
search_dirs << type_files if File.exist?(type_files)
|
783
|
-
search_dirs
|
784
|
-
end
|
887
|
+
plugins_tarball = plugin_tarball(params['versioned_project'], 'all_plugins')
|
785
888
|
|
786
889
|
[200, plugins_tarball.to_json]
|
787
890
|
end
|