bolt 1.6.0 → 1.7.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/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +0 -1
- data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +76 -0
- data/lib/bolt/applicator.rb +9 -0
- data/lib/bolt/bolt_option_parser.rb +3 -3
- data/lib/bolt/config.rb +6 -1
- data/lib/bolt/transport/ssh.rb +2 -1
- data/lib/bolt/transport/ssh/connection.rb +3 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_spec/plans.rb +5 -0
- data/lib/bolt_spec/plans/action_stubs.rb +2 -1
- data/lib/bolt_spec/plans/action_stubs/script_stub.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs/task_stub.rb +1 -1
- data/lib/bolt_spec/run.rb +35 -1
- data/libexec/query_resources.rb +49 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd168415311b9cd4c08f4bbd2a22df94d9ba2f513fa989868507118065720ce8
|
4
|
+
data.tar.gz: c5504e881412f51be3a583bb8d091370e4b571ef1a3ed46bca436e433d98fc96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6934e093666be2c77949a390411237128fd535ac2dbe86435e4a34718eb7f72f39c5ba2412085e02d875daf7b677ffea45acc391bf3a82eb41ad607b8fc8e58e
|
7
|
+
data.tar.gz: e7decf1272c8654b10dbb513a1d89cdb6b49ee90f81e562c9f234d235b75e592c0e8f4d8dcabaf7653d75e9f737eb87cac8f16e68c9453f73651edeecd95f636
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/task'
|
4
|
+
|
5
|
+
# Query the state of resources on a list of targets using resource definitions in Bolt's modulepath.
|
6
|
+
# The results are returned as a list of hashes representing each resource.
|
7
|
+
#
|
8
|
+
# Requires the Puppet Agent be installed on the target, which can be accomplished with apply_prep
|
9
|
+
# or by directly running the puppet_agent::install task.
|
10
|
+
Puppet::Functions.create_function(:get_resources) do
|
11
|
+
# @param targets A pattern or array of patterns identifying a set of targets.
|
12
|
+
# @param resources A resource type or instance, or an array of such.
|
13
|
+
# @example Collect resource states for packages and a file
|
14
|
+
# get_resources('target1,target2', [Package, File[/etc/puppetlabs]])
|
15
|
+
dispatch :get_resources do
|
16
|
+
param 'Boltlib::TargetSpec', :targets
|
17
|
+
param 'Variant[String, Resource, Array[Variant[String, Resource]]]', :resources
|
18
|
+
end
|
19
|
+
|
20
|
+
def script_compiler
|
21
|
+
@script_compiler ||= Puppet::Pal::ScriptCompiler.new(closure_scope.compiler)
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_task(executor, targets, name, args = {})
|
25
|
+
tasksig = script_compiler.task_signature(name)
|
26
|
+
raise Bolt::Error.new("#{name} could not be found", 'bolt/get-resources') unless tasksig
|
27
|
+
|
28
|
+
task = Bolt::Task.new(tasksig.task_hash)
|
29
|
+
results = executor.run_task(targets, task, args)
|
30
|
+
raise Bolt::RunFailure.new(results, 'run_task', task.name) unless results.ok?
|
31
|
+
results
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_resources(target_spec, resources)
|
35
|
+
applicator = Puppet.lookup(:apply_executor) { nil }
|
36
|
+
executor = Puppet.lookup(:bolt_executor) { nil }
|
37
|
+
inventory = Puppet.lookup(:bolt_inventory) { nil }
|
38
|
+
unless applicator && executor && inventory && Puppet.features.bolt?
|
39
|
+
raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
|
40
|
+
Puppet::Pops::Issues::TASK_MISSING_BOLT, action: _('get_resources')
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
resources = [resources].flatten
|
45
|
+
resources.each do |resource|
|
46
|
+
if resource !~ /^\w+$/ && resource !~ /^\w+\[.+\]$/
|
47
|
+
raise Bolt::Error.new("#{resource} is not a valid resource type or type instance name", 'bolt/get-resources')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
executor.report_function_call('get_resources')
|
52
|
+
|
53
|
+
targets = inventory.get_targets(target_spec)
|
54
|
+
|
55
|
+
executor.log_action('gather resources', targets) do
|
56
|
+
executor.without_default_logging do
|
57
|
+
# Gather facts, including custom facts
|
58
|
+
plugins = applicator.build_plugin_tarball do |mod|
|
59
|
+
search_dirs = []
|
60
|
+
search_dirs << mod.plugins if mod.plugins?
|
61
|
+
search_dirs << mod.pluginfacts if mod.pluginfacts?
|
62
|
+
search_dirs
|
63
|
+
end
|
64
|
+
|
65
|
+
task = applicator.query_resources_task
|
66
|
+
arguments = {
|
67
|
+
'resources' => resources,
|
68
|
+
'plugins' => Puppet::Pops::Types::PSensitiveType::Sensitive.new(plugins)
|
69
|
+
}
|
70
|
+
results = executor.run_task(targets, task, arguments)
|
71
|
+
raise Bolt::RunFailure.new(results, 'run_task', task.name) unless results.ok?
|
72
|
+
results
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/bolt/applicator.rb
CHANGED
@@ -56,6 +56,15 @@ module Bolt
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
def query_resources_task
|
60
|
+
@query_resources_task ||= begin
|
61
|
+
path = File.join(libexec, 'query_resources.rb')
|
62
|
+
file = { 'name' => 'query_resources.rb', 'path' => path }
|
63
|
+
metadata = { 'supports_noop' => true, 'input_method' => 'stdin' }
|
64
|
+
Bolt::Task.new(name: 'apply_helpers::query_resources', files: [file], metadata: metadata)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
59
68
|
def compile(target, ast, plan_vars)
|
60
69
|
trusted = Puppet::Context::TrustedInformation.new('local', target.host, {})
|
61
70
|
|
@@ -214,7 +214,7 @@ Usage: bolt apply <manifest.pp> [options]
|
|
214
214
|
'Maximum number of simultaneous manifest block compiles (default: number of cores)') do |concurrency|
|
215
215
|
@options[:'compile-concurrency'] = concurrency
|
216
216
|
end
|
217
|
-
define('--modulepath MODULES',
|
217
|
+
define('-m', '--modulepath MODULES',
|
218
218
|
"List of directories containing modules, separated by '#{File::PATH_SEPARATOR}'") do |modulepath|
|
219
219
|
# When specified from the CLI, modulepath entries are relative to pwd
|
220
220
|
@options[:modulepath] = modulepath.split(File::PATH_SEPARATOR).map do |moduledir|
|
@@ -229,7 +229,7 @@ Usage: bolt apply <manifest.pp> [options]
|
|
229
229
|
'Specify where to load config from (default: ~/.puppetlabs/bolt/bolt.yaml)') do |path|
|
230
230
|
@options[:configfile] = path
|
231
231
|
end
|
232
|
-
define('--inventoryfile FILEPATH',
|
232
|
+
define('-i', '--inventoryfile FILEPATH',
|
233
233
|
'Specify where to load inventory from (default: ~/.puppetlabs/bolt/inventory.yaml)') do |path|
|
234
234
|
if ENV.include?(Bolt::Inventory::ENVIRONMENT_VAR)
|
235
235
|
raise Bolt::CLIError, "Cannot pass inventory file when #{Bolt::Inventory::ENVIRONMENT_VAR} is set"
|
@@ -262,7 +262,7 @@ Usage: bolt apply <manifest.pp> [options]
|
|
262
262
|
define('-h', '--help', 'Display help') do |_|
|
263
263
|
@options[:help] = true
|
264
264
|
end
|
265
|
-
define('--verbose', 'Display verbose logging') do |_|
|
265
|
+
define('-v', '--verbose', 'Display verbose logging') do |_|
|
266
266
|
@options[:verbose] = true
|
267
267
|
end
|
268
268
|
define('--debug', 'Display debug logging') do |_|
|
data/lib/bolt/config.rb
CHANGED
@@ -146,7 +146,12 @@ module Bolt
|
|
146
146
|
# Expand paths relative to the Boltdir. Any settings that came from the
|
147
147
|
# CLI will already be absolute, so the expand will be skipped.
|
148
148
|
if data.key?('modulepath')
|
149
|
-
|
149
|
+
moduledirs = if data['modulepath'].is_a?(String)
|
150
|
+
data['modulepath'].split(File::PATH_SEPARATOR)
|
151
|
+
else
|
152
|
+
data['modulepath']
|
153
|
+
end
|
154
|
+
@modulepath = moduledirs.map do |moduledir|
|
150
155
|
File.expand_path(moduledir, @boltdir.path)
|
151
156
|
end
|
152
157
|
end
|
data/lib/bolt/transport/ssh.rb
CHANGED
@@ -9,7 +9,8 @@ module Bolt
|
|
9
9
|
module Transport
|
10
10
|
class SSH < Base
|
11
11
|
def self.options
|
12
|
-
%w[port user password sudo-password private-key host-key-check
|
12
|
+
%w[port user password sudo-password private-key host-key-check
|
13
|
+
connect-timeout tmpdir run-as tty run-as-command proxyjump]
|
13
14
|
end
|
14
15
|
|
15
16
|
def provided_features
|
@@ -5,6 +5,7 @@ require 'shellwords'
|
|
5
5
|
require 'bolt/node/errors'
|
6
6
|
require 'bolt/node/output'
|
7
7
|
require 'bolt/util'
|
8
|
+
require 'net/ssh/proxy/jump'
|
8
9
|
|
9
10
|
module Bolt
|
10
11
|
module Transport
|
@@ -116,6 +117,8 @@ module Bolt
|
|
116
117
|
end
|
117
118
|
options[:timeout] = target.options['connect-timeout'] if target.options['connect-timeout']
|
118
119
|
|
120
|
+
options[:proxy] = Net::SSH::Proxy::Jump.new(target.options['proxyjump']) if target.options['proxyjump']
|
121
|
+
|
119
122
|
if @load_config
|
120
123
|
# Mirroring:
|
121
124
|
# https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/authentication/agent.rb#L80
|
data/lib/bolt/version.rb
CHANGED
data/lib/bolt_spec/plans.rb
CHANGED
@@ -211,6 +211,11 @@ module BoltSpec
|
|
211
211
|
nil
|
212
212
|
end
|
213
213
|
|
214
|
+
def allow_get_resources
|
215
|
+
allow_task('apply_helpers::query_resources')
|
216
|
+
nil
|
217
|
+
end
|
218
|
+
|
214
219
|
# Example helpers to mock other run functions
|
215
220
|
# The with_targets method makes sense for all stubs
|
216
221
|
# with_params could be reused for options
|
@@ -36,7 +36,7 @@ module BoltSpec
|
|
36
36
|
def initialize(expect = false)
|
37
37
|
@calls = 0
|
38
38
|
@expect = expect
|
39
|
-
@expected_calls =
|
39
|
+
@expected_calls = nil
|
40
40
|
# invocation spec
|
41
41
|
@invocation = {}
|
42
42
|
# return value
|
@@ -63,6 +63,7 @@ module BoltSpec
|
|
63
63
|
# This changes the stub from an allow to an expect which will validate
|
64
64
|
# that it has been called.
|
65
65
|
def expect_call
|
66
|
+
@expected_calls = 1
|
66
67
|
@expect = true
|
67
68
|
self
|
68
69
|
end
|
data/lib/bolt_spec/run.rb
CHANGED
@@ -9,7 +9,6 @@ require 'bolt/puppetdb'
|
|
9
9
|
require 'bolt/util'
|
10
10
|
|
11
11
|
# This is intended to provide a relatively stable method of executing bolt in process from tests.
|
12
|
-
# Currently it provides run_task, run_plan, run_script and run_command helpers.
|
13
12
|
module BoltSpec
|
14
13
|
module Run
|
15
14
|
def run_task(task_name, targets, params = nil, config: nil, inventory: nil)
|
@@ -49,6 +48,27 @@ module BoltSpec
|
|
49
48
|
Bolt::Util.walk_keys(result, &:to_s)
|
50
49
|
end
|
51
50
|
|
51
|
+
def apply_manifest(manifest, targets, execute: false, noop: false, config: nil, inventory: nil)
|
52
|
+
# The execute parameter is equivalent to the --execute option
|
53
|
+
if execute
|
54
|
+
code = manifest
|
55
|
+
else
|
56
|
+
begin
|
57
|
+
unless File.stat(manifest).readable?
|
58
|
+
raise BOLT::FileError.new("The manifest '#{manifest}' is unreadable", manifest)
|
59
|
+
end
|
60
|
+
rescue Errno::ENOENT
|
61
|
+
raise Bolt::FileError.new("The manifest '#{manifest}' does not exist", manifest)
|
62
|
+
end
|
63
|
+
code = File.read(File.expand_path(manifest))
|
64
|
+
filename = manifest
|
65
|
+
end
|
66
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
67
|
+
runner.apply_manifest(code, targets, filename, noop)
|
68
|
+
end
|
69
|
+
JSON.parse(result.to_json)
|
70
|
+
end
|
71
|
+
|
52
72
|
class BoltRunner
|
53
73
|
# Creates a temporary boltdir so no settings are picked up
|
54
74
|
# WARNING: puppetdb config and orch config which do not use the boltdir may
|
@@ -107,6 +127,20 @@ module BoltSpec
|
|
107
127
|
targets = inventory.get_targets(targets)
|
108
128
|
executor.run_script(targets, script, arguments, options)
|
109
129
|
end
|
130
|
+
|
131
|
+
def apply_manifest(code, targets, filename = nil, noop = false)
|
132
|
+
ast = pal.parse_manifest(code, filename)
|
133
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics, noop)
|
134
|
+
targets = inventory.get_targets(targets)
|
135
|
+
|
136
|
+
pal.in_plan_compiler(executor, inventory, puppetdb_client) do |compiler|
|
137
|
+
compiler.call_function('apply_prep', targets)
|
138
|
+
end
|
139
|
+
|
140
|
+
pal.with_bolt_executor(executor, inventory, puppetdb_client) do
|
141
|
+
Puppet.lookup(:apply_executor).apply_ast(ast, targets, '_catch_errors' => true, '_noop' => noop)
|
142
|
+
end
|
143
|
+
end
|
110
144
|
end
|
111
145
|
end
|
112
146
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#! /opt/puppetlabs/puppet/bin/ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require 'puppet'
|
6
|
+
require 'puppet/module_tool/tar'
|
7
|
+
require 'tempfile'
|
8
|
+
|
9
|
+
args = JSON.parse(STDIN.read)
|
10
|
+
|
11
|
+
RESOURCE_INSTANCE = /^([^\[]+)\[([^\]]+)\]$/.freeze
|
12
|
+
|
13
|
+
def instance(type_name, resource_name)
|
14
|
+
resource = Puppet::Resource.indirection.find("#{type_name}/#{resource_name}")
|
15
|
+
stringify_resource(resource)
|
16
|
+
end
|
17
|
+
|
18
|
+
Dir.mktmpdir do |puppet_root|
|
19
|
+
# Create temporary directories for all core Puppet settings so we don't clobber
|
20
|
+
# existing state or read from puppet.conf. Also create a temporary modulepath.
|
21
|
+
moduledir = File.join(puppet_root, 'modules')
|
22
|
+
Dir.mkdir(moduledir)
|
23
|
+
cli = Puppet::Settings::REQUIRED_APP_SETTINGS.flat_map do |setting|
|
24
|
+
["--#{setting}", File.join(puppet_root, setting.to_s.chomp('dir'))]
|
25
|
+
end
|
26
|
+
cli << '--modulepath' << moduledir
|
27
|
+
Puppet.initialize_settings(cli)
|
28
|
+
|
29
|
+
Tempfile.open('plugins.tar.gz') do |plugins|
|
30
|
+
File.binwrite(plugins, Base64.decode64(args['plugins']))
|
31
|
+
Puppet::ModuleTool::Tar.instance.unpack(plugins, moduledir, Etc.getlogin || Etc.getpwuid.name)
|
32
|
+
end
|
33
|
+
|
34
|
+
env = Puppet.lookup(:environments).get('production')
|
35
|
+
env.each_plugin_directory do |dir|
|
36
|
+
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
37
|
+
end
|
38
|
+
|
39
|
+
resources = args['resources'].flat_map do |resource_desc|
|
40
|
+
if (match = RESOURCE_INSTANCE.match(resource_desc))
|
41
|
+
Puppet::Resource.indirection.find("#{match[1]}/#{match[2]}", environment: env)
|
42
|
+
else
|
43
|
+
Puppet::Resource.indirection.search(resource_desc, environment: env)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
puts({ 'resources' => resources }.to_json)
|
47
|
+
end
|
48
|
+
|
49
|
+
exit 0
|
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: 1.
|
4
|
+
version: 1.7.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-12-
|
11
|
+
date: 2018-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -301,6 +301,7 @@ files:
|
|
301
301
|
- bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb
|
302
302
|
- bolt-modules/boltlib/lib/puppet/functions/facts.rb
|
303
303
|
- bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb
|
304
|
+
- bolt-modules/boltlib/lib/puppet/functions/get_resources.rb
|
304
305
|
- bolt-modules/boltlib/lib/puppet/functions/get_targets.rb
|
305
306
|
- bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb
|
306
307
|
- bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb
|
@@ -390,6 +391,7 @@ files:
|
|
390
391
|
- libexec/apply_catalog.rb
|
391
392
|
- libexec/bolt_catalog
|
392
393
|
- libexec/custom_facts.rb
|
394
|
+
- libexec/query_resources.rb
|
393
395
|
- modules/aggregate/lib/puppet/functions/aggregate/count.rb
|
394
396
|
- modules/aggregate/lib/puppet/functions/aggregate/nodes.rb
|
395
397
|
- modules/aggregate/plans/count.pp
|