bolt 0.17.1 → 0.17.2
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/run_task.rb +25 -13
- data/lib/bolt/cli.rb +45 -15
- data/lib/bolt/config.rb +48 -132
- data/lib/bolt/executor.rb +3 -10
- data/lib/bolt/inventory.rb +15 -1
- data/lib/bolt/puppetdb.rb +11 -0
- data/lib/bolt/puppetdb/client.rb +68 -0
- data/lib/bolt/puppetdb/config.rb +76 -0
- data/lib/bolt/target.rb +5 -4
- data/lib/bolt/transport/base.rb +11 -2
- data/lib/bolt/transport/local.rb +11 -5
- data/lib/bolt/transport/orch.rb +16 -5
- data/lib/bolt/transport/ssh.rb +32 -1
- data/lib/bolt/transport/ssh/connection.rb +17 -10
- data/lib/bolt/transport/winrm.rb +18 -1
- data/lib/bolt/transport/winrm/connection.rb +15 -16
- data/lib/bolt/util.rb +15 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_ext/puppetdb_inventory.rb +5 -135
- data/vendored/facter/lib/facter/ec2/rest.rb +1 -1
- data/vendored/hiera/lib/hiera/version.rb +1 -1
- data/vendored/puppet/lib/puppet/application/agent.rb +1 -3
- data/vendored/puppet/lib/puppet/application/apply.rb +2 -4
- data/vendored/puppet/lib/puppet/application/cert.rb +6 -1
- data/vendored/puppet/lib/puppet/application/device.rb +100 -13
- data/vendored/puppet/lib/puppet/application/facts.rb +5 -0
- data/vendored/puppet/lib/puppet/application/lookup.rb +11 -1
- data/vendored/puppet/lib/puppet/configurer.rb +17 -4
- data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
- data/vendored/puppet/lib/puppet/datatypes.rb +1 -1
- data/vendored/puppet/lib/puppet/defaults.rb +1 -1
- data/vendored/puppet/lib/puppet/environments.rb +2 -2
- data/vendored/puppet/lib/puppet/error.rb +6 -3
- data/vendored/puppet/lib/puppet/external/dot.rb +0 -7
- data/vendored/puppet/lib/puppet/external/nagios/parser.rb +1 -1
- data/vendored/puppet/lib/puppet/face/config.rb +41 -8
- data/vendored/puppet/lib/puppet/face/epp.rb +30 -5
- data/vendored/puppet/lib/puppet/face/facts.rb +49 -0
- data/vendored/puppet/lib/puppet/face/help.rb +33 -35
- data/vendored/puppet/lib/puppet/face/man.rb +55 -12
- data/vendored/puppet/lib/puppet/face/parser.rb +30 -3
- data/vendored/puppet/lib/puppet/file_bucket/file.rb +0 -2
- data/vendored/puppet/lib/puppet/file_serving/base.rb +10 -10
- data/vendored/puppet/lib/puppet/functions.rb +1 -3
- data/vendored/puppet/lib/puppet/functions/alert.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/all.rb +6 -6
- data/vendored/puppet/lib/puppet/functions/annotate.rb +10 -10
- data/vendored/puppet/lib/puppet/functions/any.rb +6 -6
- data/vendored/puppet/lib/puppet/functions/assert_type.rb +4 -4
- data/vendored/puppet/lib/puppet/functions/binary_file.rb +14 -2
- data/vendored/puppet/lib/puppet/functions/break.rb +31 -2
- data/vendored/puppet/lib/puppet/functions/call.rb +4 -4
- data/vendored/puppet/lib/puppet/functions/contain.rb +19 -3
- data/vendored/puppet/lib/puppet/functions/convert_to.rb +6 -5
- data/vendored/puppet/lib/puppet/functions/crit.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/debug.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/defined.rb +11 -9
- data/vendored/puppet/lib/puppet/functions/dig.rb +26 -2
- data/vendored/puppet/lib/puppet/functions/each.rb +8 -8
- data/vendored/puppet/lib/puppet/functions/emerg.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/empty.rb +79 -0
- data/vendored/puppet/lib/puppet/functions/err.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/filter.rb +7 -7
- data/vendored/puppet/lib/puppet/functions/find_file.rb +15 -1
- data/vendored/puppet/lib/puppet/functions/flatten.rb +64 -0
- data/vendored/puppet/lib/puppet/functions/hiera.rb +6 -6
- data/vendored/puppet/lib/puppet/functions/hiera_array.rb +6 -6
- data/vendored/puppet/lib/puppet/functions/hiera_hash.rb +6 -6
- data/vendored/puppet/lib/puppet/functions/hiera_include.rb +8 -8
- data/vendored/puppet/lib/puppet/functions/include.rb +28 -2
- data/vendored/puppet/lib/puppet/functions/info.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/inline_epp.rb +2 -2
- data/vendored/puppet/lib/puppet/functions/join.rb +56 -0
- data/vendored/puppet/lib/puppet/functions/keys.rb +25 -0
- data/vendored/puppet/lib/puppet/functions/length.rb +44 -0
- data/vendored/puppet/lib/puppet/functions/lest.rb +39 -1
- data/vendored/puppet/lib/puppet/functions/map.rb +10 -9
- data/vendored/puppet/lib/puppet/functions/match.rb +6 -6
- data/vendored/puppet/lib/puppet/functions/new.rb +995 -2
- data/vendored/puppet/lib/puppet/functions/next.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/notice.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/reduce.rb +6 -6
- data/vendored/puppet/lib/puppet/functions/regsubst.rb +9 -3
- data/vendored/puppet/lib/puppet/functions/require.rb +36 -2
- data/vendored/puppet/lib/puppet/functions/return.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/reverse_each.rb +71 -2
- data/vendored/puppet/lib/puppet/functions/slice.rb +23 -9
- data/vendored/puppet/lib/puppet/functions/split.rb +12 -10
- data/vendored/puppet/lib/puppet/functions/step.rb +73 -1
- data/vendored/puppet/lib/puppet/functions/strftime.rb +176 -2
- data/vendored/puppet/lib/puppet/functions/then.rb +65 -2
- data/vendored/puppet/lib/puppet/functions/tree_each.rb +19 -19
- data/vendored/puppet/lib/puppet/functions/type.rb +42 -1
- data/vendored/puppet/lib/puppet/functions/unique.rb +13 -13
- data/vendored/puppet/lib/puppet/functions/unwrap.rb +8 -4
- data/vendored/puppet/lib/puppet/functions/values.rb +25 -0
- data/vendored/puppet/lib/puppet/functions/versioncmp.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/with.rb +6 -4
- data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +1 -1
- data/vendored/puppet/lib/puppet/indirector/facts/facter.rb +1 -3
- data/vendored/puppet/lib/puppet/indirector/facts/rest.rb +21 -0
- data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +0 -4
- data/vendored/puppet/lib/puppet/indirector/file_content/http.rb +3 -1
- data/vendored/puppet/lib/puppet/indirector/indirection.rb +5 -3
- data/vendored/puppet/lib/puppet/indirector/request.rb +6 -2
- data/vendored/puppet/lib/puppet/module/task.rb +2 -2
- data/vendored/puppet/lib/puppet/module_tool/tar/mini.rb +57 -4
- data/vendored/puppet/lib/puppet/network/authconfig.rb +1 -1
- data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +1 -0
- data/vendored/puppet/lib/puppet/network/resolver.rb +1 -2
- data/vendored/puppet/lib/puppet/node.rb +4 -3
- data/vendored/puppet/lib/puppet/parser/compiler.rb +12 -5
- data/vendored/puppet/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/functions/fqdn_rand.rb +15 -4
- data/vendored/puppet/lib/puppet/parser/functions/new.rb +31 -46
- data/vendored/puppet/lib/puppet/parser/parser_factory.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/resource.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/type_loader.rb +11 -11
- data/vendored/puppet/lib/puppet/pops/evaluator/closure.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/evaluator/collector_transformer.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/evaluator/epp_evaluator.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_resource_support.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +5 -2
- data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/issue_reporter.rb +18 -1
- data/vendored/puppet/lib/puppet/pops/issues.rb +6 -3
- data/vendored/puppet/lib/puppet/pops/loader/ruby_data_type_instantiator.rb +1 -2
- data/vendored/puppet/lib/puppet/pops/loader/ruby_function_instantiator.rb +1 -2
- data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +4 -4
- data/vendored/puppet/lib/puppet/pops/loader/type_definition_instantiator.rb +4 -1
- data/vendored/puppet/lib/puppet/pops/loaders.rb +18 -7
- data/vendored/puppet/lib/puppet/pops/lookup/global_data_provider.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/model/factory.rb +6 -3
- data/vendored/puppet/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
- data/vendored/puppet/lib/puppet/pops/model/pn_transformer.rb +400 -0
- data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/parser/heredoc_support.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/parser/lexer_support.rb +3 -2
- data/vendored/puppet/lib/puppet/pops/parser/locator.rb +0 -2
- data/vendored/puppet/lib/puppet/pops/parser/pn_parser.rb +316 -0
- data/vendored/puppet/lib/puppet/pops/pcore.rb +17 -17
- data/vendored/puppet/lib/puppet/pops/pn.rb +236 -0
- data/vendored/puppet/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/types/class_loader.rb +6 -3
- data/vendored/puppet/lib/puppet/pops/types/implementation_registry.rb +28 -35
- data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -3
- data/vendored/puppet/lib/puppet/pops/types/p_timespan_type.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/types/p_type_set_type.rb +24 -1
- data/vendored/puppet/lib/puppet/pops/types/ruby_generator.rb +3 -4
- data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +0 -4
- data/vendored/puppet/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/types/type_parser.rb +14 -7
- data/vendored/puppet/lib/puppet/pops/types/types.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/utils.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +6 -2
- data/vendored/puppet/lib/puppet/provider/group/groupadd.rb +3 -1
- data/vendored/puppet/lib/puppet/provider/group/windows_adsi.rb +4 -7
- data/vendored/puppet/lib/puppet/provider/nameservice.rb +3 -3
- data/vendored/puppet/lib/puppet/provider/package/dnf.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/pacman.rb +4 -4
- data/vendored/puppet/lib/puppet/provider/package/pip.rb +3 -3
- data/vendored/puppet/lib/puppet/provider/package/pkgdmg.rb +3 -3
- data/vendored/puppet/lib/puppet/provider/package/pkgutil.rb +2 -2
- data/vendored/puppet/lib/puppet/provider/package/portage.rb +9 -9
- data/vendored/puppet/lib/puppet/provider/package/zypper.rb +2 -2
- data/vendored/puppet/lib/puppet/provider/service/base.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/service/smf.rb +3 -2
- data/vendored/puppet/lib/puppet/provider/user/useradd.rb +6 -2
- data/vendored/puppet/lib/puppet/provider/user/windows_adsi.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +3 -2
- data/vendored/puppet/lib/puppet/reference/configuration.rb +2 -0
- data/vendored/puppet/lib/puppet/reference/type.rb +11 -11
- data/vendored/puppet/lib/puppet/resource.rb +1 -1
- data/vendored/puppet/lib/puppet/resource/capability_finder.rb +2 -2
- data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -2
- data/vendored/puppet/lib/puppet/resource/status.rb +9 -2
- data/vendored/puppet/lib/puppet/resource/type.rb +1 -1
- data/vendored/puppet/lib/puppet/settings.rb +31 -19
- data/vendored/puppet/lib/puppet/settings/base_setting.rb +5 -0
- data/vendored/puppet/lib/puppet/settings/config_file.rb +1 -1
- data/vendored/puppet/lib/puppet/settings/ttl_setting.rb +5 -0
- data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +2 -2
- data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +0 -2
- data/vendored/puppet/lib/puppet/transaction/additional_resource_generator.rb +2 -2
- data/vendored/puppet/lib/puppet/transaction/event.rb +1 -1
- data/vendored/puppet/lib/puppet/transaction/report.rb +1 -1
- data/vendored/puppet/lib/puppet/type.rb +9 -13
- data/vendored/puppet/lib/puppet/type/augeas.rb +2 -2
- data/vendored/puppet/lib/puppet/type/cron.rb +11 -6
- data/vendored/puppet/lib/puppet/type/exec.rb +1 -1
- data/vendored/puppet/lib/puppet/type/file.rb +4 -5
- data/vendored/puppet/lib/puppet/type/host.rb +1 -1
- data/vendored/puppet/lib/puppet/type/k5login.rb +30 -54
- data/vendored/puppet/lib/puppet/type/package.rb +3 -3
- data/vendored/puppet/lib/puppet/type/schedule.rb +12 -12
- data/vendored/puppet/lib/puppet/type/scheduled_task.rb +2 -2
- data/vendored/puppet/lib/puppet/type/ssh_authorized_key.rb +5 -5
- data/vendored/puppet/lib/puppet/type/sshkey.rb +2 -2
- data/vendored/puppet/lib/puppet/type/tidy.rb +9 -2
- data/vendored/puppet/lib/puppet/type/user.rb +1 -1
- data/vendored/puppet/lib/puppet/type/yumrepo.rb +25 -4
- data/vendored/puppet/lib/puppet/type/zfs.rb +4 -0
- data/vendored/puppet/lib/puppet/util.rb +0 -4
- data/vendored/puppet/lib/puppet/util/backups.rb +1 -1
- data/vendored/puppet/lib/puppet/util/http_proxy.rb +4 -2
- data/vendored/puppet/lib/puppet/util/inifile.rb +3 -4
- data/vendored/puppet/lib/puppet/util/log.rb +2 -5
- data/vendored/puppet/lib/puppet/util/network_device/cisco/facts.rb +1 -1
- data/vendored/puppet/lib/puppet/util/reference.rb +1 -8
- data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
- data/vendored/puppet/lib/puppet/util/warnings.rb +0 -2
- data/vendored/puppet/lib/puppet/util/windows/adsi.rb +15 -18
- data/vendored/puppet/lib/puppet/util/windows/com.rb +2 -1
- data/vendored/puppet/lib/puppet/util/windows/file.rb +2 -2
- data/vendored/puppet/lib/puppet/util/windows/principal.rb +7 -6
- data/vendored/puppet/lib/puppet/util/windows/sid.rb +60 -7
- data/vendored/puppet/lib/puppet/util/windows/taskscheduler.rb +0 -9
- data/vendored/puppet/lib/puppet/version.rb +1 -1
- data/vendored/puppet/lib/puppet_pal.rb +53 -48
- metadata +15 -2
data/lib/bolt/transport/winrm.rb
CHANGED
@@ -7,7 +7,24 @@ module Bolt
|
|
7
7
|
-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass
|
8
8
|
].freeze
|
9
9
|
|
10
|
-
def
|
10
|
+
def self.options
|
11
|
+
%w[port user password connect-timeout ssl tmpdir cacert extensions]
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.validate(options)
|
15
|
+
ssl_flag = options['ssl']
|
16
|
+
unless !!ssl_flag == ssl_flag
|
17
|
+
raise Bolt::CLIError, 'ssl option must be a Boolean true or false'
|
18
|
+
end
|
19
|
+
|
20
|
+
timeout_value = options['connect-timeout']
|
21
|
+
unless timeout_value.is_a?(Integer) || timeout_value.nil?
|
22
|
+
error_msg = "connect-timeout value must be an Integer, received #{timeout_value}:#{timeout_value.class}"
|
23
|
+
raise Bolt::CLIError, error_msg
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
11
28
|
super
|
12
29
|
require 'winrm'
|
13
30
|
require 'winrm-fs'
|
@@ -7,13 +7,18 @@ module Bolt
|
|
7
7
|
class Connection
|
8
8
|
attr_reader :logger, :target
|
9
9
|
|
10
|
+
DEFAULT_EXTENSIONS = ['.ps1', '.rb', '.pp'].freeze
|
11
|
+
|
10
12
|
def initialize(target)
|
11
13
|
@target = target
|
12
14
|
|
13
|
-
default_port = target.options[
|
15
|
+
default_port = target.options['ssl'] ? HTTPS_PORT : HTTP_PORT
|
14
16
|
@port = @target.port || default_port
|
15
17
|
@user = @target.user
|
16
|
-
|
18
|
+
|
19
|
+
# Accept a single entry or a list, ensure each is prefixed with '.'
|
20
|
+
extensions = [target.options['extensions'] || []].flatten.map { |ext| ext[0] != '.' ? '.' + ext : ext }
|
21
|
+
@extensions = DEFAULT_EXTENSIONS.to_set.merge(extensions)
|
17
22
|
|
18
23
|
@logger = Logging.logger[@target.host]
|
19
24
|
end
|
@@ -22,7 +27,7 @@ module Bolt
|
|
22
27
|
HTTPS_PORT = 5986
|
23
28
|
|
24
29
|
def connect
|
25
|
-
if target.options[
|
30
|
+
if target.options['ssl']
|
26
31
|
scheme = 'https'
|
27
32
|
transport = :ssl
|
28
33
|
else
|
@@ -35,9 +40,9 @@ module Bolt
|
|
35
40
|
password: target.password,
|
36
41
|
retry_limit: 1,
|
37
42
|
transport: transport,
|
38
|
-
ca_trust_path: target.options[
|
43
|
+
ca_trust_path: target.options['cacert'] }
|
39
44
|
|
40
|
-
Timeout.timeout(target.options[
|
45
|
+
Timeout.timeout(target.options['connect-timeout']) do
|
41
46
|
@connection = ::WinRM::Connection.new(options)
|
42
47
|
transport_logger = Logging.logger[::WinRM]
|
43
48
|
transport_logger.level = :warn
|
@@ -50,11 +55,11 @@ module Bolt
|
|
50
55
|
rescue Timeout::Error
|
51
56
|
# If we're using the default port with SSL, a timeout probably means the
|
52
57
|
# host doesn't support SSL.
|
53
|
-
if target.options[
|
54
|
-
|
58
|
+
if target.options['ssl'] && @port == HTTPS_PORT
|
59
|
+
the_problem = "\nUse --no-ssl if this host isn't configured to use SSL for WinRM"
|
55
60
|
end
|
56
61
|
raise Bolt::Node::ConnectError.new(
|
57
|
-
"Timeout after #{target.options[
|
62
|
+
"Timeout after #{target.options['connect-timeout']} seconds connecting to #{endpoint}#{the_problem}",
|
58
63
|
'CONNECT_ERROR'
|
59
64
|
)
|
60
65
|
rescue ::WinRM::WinRMAuthorizationError
|
@@ -64,7 +69,7 @@ module Bolt
|
|
64
69
|
)
|
65
70
|
rescue OpenSSL::SSL::SSLError => e
|
66
71
|
# If we're using SSL with the default non-SSL port, mention that as a likely problem
|
67
|
-
if target.options[
|
72
|
+
if target.options['ssl'] && @port == HTTP_PORT
|
68
73
|
theres_your_problem = "\nAre you using SSL to connect to a non-SSL port?"
|
69
74
|
end
|
70
75
|
raise Bolt::Node::ConnectError.new(
|
@@ -419,12 +424,6 @@ exit $(Invoke-Interpreter @invokeArgs)
|
|
419
424
|
PS
|
420
425
|
end
|
421
426
|
|
422
|
-
DEFAULT_EXTENSIONS = ['.ps1', '.rb', '.pp'].freeze
|
423
|
-
|
424
|
-
PS_ARGS = %w[
|
425
|
-
-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass
|
426
|
-
].freeze
|
427
|
-
|
428
427
|
def write_remote_file(source, destination)
|
429
428
|
fs = ::WinRM::FS::FileManager.new(@connection)
|
430
429
|
# TODO: raise FileError here if this fails
|
@@ -432,7 +431,7 @@ PS
|
|
432
431
|
end
|
433
432
|
|
434
433
|
def make_tempdir
|
435
|
-
find_parent = target.options[
|
434
|
+
find_parent = target.options['tmpdir'] ? "\"#{target.options['tmpdir']}\"" : '[System.IO.Path]::GetTempPath()'
|
436
435
|
result = execute(<<-PS)
|
437
436
|
$parent = #{find_parent}
|
438
437
|
$name = [System.IO.Path]::GetRandomFileName()
|
data/lib/bolt/util.rb
CHANGED
@@ -43,6 +43,21 @@ module Bolt
|
|
43
43
|
hash1.merge(hash2, &recursive_merge)
|
44
44
|
end
|
45
45
|
|
46
|
+
# Accepts a Data object and returns a copy with all hash keys
|
47
|
+
# modifed by block. use &:to_s to stringify keys or :to_sym to symbolize them
|
48
|
+
def walk_keys(data, &block)
|
49
|
+
if data.is_a? Hash
|
50
|
+
data.each_with_object({}) do |(k, v), acc|
|
51
|
+
v = walk_keys(v, &block)
|
52
|
+
acc[yield(k)] = v
|
53
|
+
end
|
54
|
+
elsif data.is_a? Array
|
55
|
+
data.map { |v| walk_keys(v, &block) }
|
56
|
+
else
|
57
|
+
data
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
46
61
|
# Performs a deep_clone, using an identical copy if the cloned structure contains multiple
|
47
62
|
# references to the same object and prevents endless recursion.
|
48
63
|
# Credit to Jan Molic via https://github.com/rubyworks/facets/blob/master/LICENSE.txt
|
data/lib/bolt/version.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'bolt/puppetdb/config'
|
3
4
|
require 'json'
|
4
5
|
require 'httpclient'
|
5
6
|
require 'optparse'
|
@@ -7,137 +8,6 @@ require 'yaml'
|
|
7
8
|
|
8
9
|
module Bolt
|
9
10
|
class PuppetDBInventory
|
10
|
-
class Client
|
11
|
-
def self.from_config(config)
|
12
|
-
uri = if config['server_urls'].is_a? String
|
13
|
-
config['server_urls']
|
14
|
-
else
|
15
|
-
config['server_urls'].first
|
16
|
-
end
|
17
|
-
uri = URI.parse(uri)
|
18
|
-
uri.port ||= 8081
|
19
|
-
|
20
|
-
cacert = File.expand_path(config['cacert'])
|
21
|
-
token = config.token
|
22
|
-
|
23
|
-
cert = config['cert']
|
24
|
-
key = config['key']
|
25
|
-
|
26
|
-
new(uri, cacert, token: token, cert: cert, key: key)
|
27
|
-
end
|
28
|
-
|
29
|
-
def initialize(uri, cacert, token: nil, cert: nil, key: nil)
|
30
|
-
@uri = uri
|
31
|
-
@cacert = cacert
|
32
|
-
@token = token
|
33
|
-
@cert = cert
|
34
|
-
@key = key
|
35
|
-
end
|
36
|
-
|
37
|
-
def query_certnames(query)
|
38
|
-
return [] unless query
|
39
|
-
|
40
|
-
body = JSON.generate(query: query)
|
41
|
-
|
42
|
-
response = http_client.post("#{@uri}/pdb/query/v4", body: body, header: headers)
|
43
|
-
if response.code != 200
|
44
|
-
raise "Failed to query PuppetDB: #{response.body}"
|
45
|
-
else
|
46
|
-
results = JSON.parse(response.body)
|
47
|
-
if results.first && !results.first.key?('certname')
|
48
|
-
raise "Query results did not contain a 'certname' field: got #{results.first.keys.join(', ')}"
|
49
|
-
end
|
50
|
-
results.map { |result| result['certname'] }.uniq
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def http_client
|
55
|
-
return @http if @http
|
56
|
-
@http = HTTPClient.new
|
57
|
-
@http.ssl_config.set_client_cert_file(@cert, @key)
|
58
|
-
@http.ssl_config.add_trust_ca(@cacert)
|
59
|
-
|
60
|
-
@http
|
61
|
-
end
|
62
|
-
|
63
|
-
def headers
|
64
|
-
headers = { 'Content-Type' => 'application/json' }
|
65
|
-
headers['X-Authentication'] = @token if @token
|
66
|
-
headers
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
class Config
|
71
|
-
DEFAULT_TOKEN = File.expand_path('~/.puppetlabs/token')
|
72
|
-
DEFAULT_CONFIG = File.expand_path('~/.puppetlabs/client-tools/puppetdb.conf')
|
73
|
-
|
74
|
-
def initialize(config_file, options)
|
75
|
-
@settings = load_config(config_file)
|
76
|
-
@settings.merge!(options)
|
77
|
-
|
78
|
-
expand_paths
|
79
|
-
validate
|
80
|
-
end
|
81
|
-
|
82
|
-
def load_config(filename)
|
83
|
-
if filename
|
84
|
-
if File.exist?(filename)
|
85
|
-
config = JSON.parse(File.read(filename))
|
86
|
-
else
|
87
|
-
raise "config file #{filename} does not exist"
|
88
|
-
end
|
89
|
-
elsif File.exist?(DEFAULT_CONFIG)
|
90
|
-
config = JSON.parse(File.read(DEFAULT_CONFIG))
|
91
|
-
else
|
92
|
-
config = {}
|
93
|
-
end
|
94
|
-
config.fetch('puppetdb', {})
|
95
|
-
end
|
96
|
-
|
97
|
-
def token
|
98
|
-
return @token if @token
|
99
|
-
if @settings['token']
|
100
|
-
File.read(@settings['token'])
|
101
|
-
elsif File.exist?(DEFAULT_TOKEN)
|
102
|
-
File.read(DEFAULT_TOKEN)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def [](key)
|
107
|
-
@settings[key]
|
108
|
-
end
|
109
|
-
|
110
|
-
def expand_paths
|
111
|
-
%w[cacert cert key token].each do |file|
|
112
|
-
@settings[file] = File.expand_path(@settings[file]) if @settings[file]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def validate_file_exists(file)
|
117
|
-
if @settings[file] && !File.exist?(@settings[file])
|
118
|
-
raise "#{file} file #{@settings[file]} does not exist"
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def validate
|
123
|
-
unless @settings['server_urls']
|
124
|
-
raise "server_urls must be specified in the config file or with --url"
|
125
|
-
end
|
126
|
-
unless @settings['cacert']
|
127
|
-
raise "cacert must be specified in the config file or with --cacert"
|
128
|
-
end
|
129
|
-
|
130
|
-
if (@settings['cert'] && !@settings['key']) ||
|
131
|
-
(!@settings['cert'] && @settings['key'])
|
132
|
-
raise "cert and key must be specified together"
|
133
|
-
end
|
134
|
-
|
135
|
-
validate_file_exists('cacert')
|
136
|
-
validate_file_exists('cert')
|
137
|
-
validate_file_exists('key')
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
11
|
class CLI
|
142
12
|
def initialize(args)
|
143
13
|
@args = args
|
@@ -158,7 +28,7 @@ module Bolt
|
|
158
28
|
end
|
159
29
|
opts.on('--token-file TOKEN',
|
160
30
|
"Path to the token file",
|
161
|
-
"Default: #{Config::DEFAULT_TOKEN} if present") do |token|
|
31
|
+
"Default: #{Bolt::PuppetDB::Config::DEFAULT_TOKEN} if present") do |token|
|
162
32
|
@cli_opts['token'] = token
|
163
33
|
end
|
164
34
|
opts.on('--url URL', "The URL of the PuppetDB server to connect to") do |url|
|
@@ -166,7 +36,7 @@ module Bolt
|
|
166
36
|
end
|
167
37
|
opts.on('--config CONFIG',
|
168
38
|
"The puppetdb.conf file to read configuration from",
|
169
|
-
"Default: #{Config::DEFAULT_CONFIG} if present") do |file|
|
39
|
+
"Default: #{Bolt::PuppetDB::Config::DEFAULT_CONFIG} if present") do |file|
|
170
40
|
@config_file = File.expand_path(file)
|
171
41
|
end
|
172
42
|
opts.on('--output FILE', '-o FILE',
|
@@ -211,8 +81,8 @@ query results.
|
|
211
81
|
raise "Unknown argument(s) #{positional_args.join(', ')}"
|
212
82
|
end
|
213
83
|
|
214
|
-
config = Config.new(@config_file, @cli_opts)
|
215
|
-
@puppetdb_client = Client.from_config(config)
|
84
|
+
config = Bolt::PuppetDB::Config.new(@config_file, @cli_opts)
|
85
|
+
@puppetdb_client = Bolt::PuppetDB::Client.from_config(config)
|
216
86
|
|
217
87
|
unless File.readable?(inventory_file)
|
218
88
|
raise "Can't read the inventory file #{inventory_file}"
|
@@ -25,7 +25,7 @@ module Facter
|
|
25
25
|
attempts = 0
|
26
26
|
|
27
27
|
begin
|
28
|
-
open(@baseurl, :proxy => nil, :read_timeout => timeout).read
|
28
|
+
open(@baseurl, :proxy => nil, :read_timeout => timeout, :open_timeout => timeout).read
|
29
29
|
able_to_connect = true
|
30
30
|
rescue OpenURI::HTTPError => e
|
31
31
|
if e.message.match /404 Not Found/i
|
@@ -422,9 +422,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
422
422
|
# we want the last report to be persisted locally
|
423
423
|
Puppet::Transaction::Report.indirection.cache_class = :yaml
|
424
424
|
|
425
|
-
if Puppet[:
|
426
|
-
Puppet::Resource::Catalog.indirection.cache_class = nil
|
427
|
-
elsif Puppet[:catalog_cache_terminus]
|
425
|
+
if Puppet[:catalog_cache_terminus]
|
428
426
|
Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
|
429
427
|
end
|
430
428
|
|
@@ -245,7 +245,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
245
245
|
$stderr.puts _("%{file} is not readable") % { file: file }
|
246
246
|
exit(63)
|
247
247
|
end
|
248
|
-
node.classes = Puppet::FileSystem.read(file, :encoding => 'utf-8').split(/[\s
|
248
|
+
node.classes = Puppet::FileSystem.read(file, :encoding => 'utf-8').split(/[\s]+/)
|
249
249
|
end
|
250
250
|
end
|
251
251
|
|
@@ -322,9 +322,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
322
322
|
Puppet.settings.use :main, :agent, :ssl
|
323
323
|
|
324
324
|
|
325
|
-
if Puppet[:
|
326
|
-
Puppet::Resource::Catalog.indirection.cache_class = nil
|
327
|
-
elsif Puppet[:catalog_cache_terminus]
|
325
|
+
if Puppet[:catalog_cache_terminus]
|
328
326
|
Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
|
329
327
|
end
|
330
328
|
|
@@ -268,7 +268,12 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
268
268
|
hosts = command_line.args.collect { |h| h.downcase }
|
269
269
|
end
|
270
270
|
begin
|
271
|
-
|
271
|
+
if subcommand == :destroy
|
272
|
+
raise _("Refusing to destroy all certs, provide an explicit list of certs to destroy") if hosts == :all
|
273
|
+
|
274
|
+
signed_hosts = hosts - @ca.waiting?
|
275
|
+
apply(@ca, :revoke, options.merge(:to => signed_hosts)) unless signed_hosts.empty?
|
276
|
+
end
|
272
277
|
apply(@ca, subcommand, options.merge(:to => hosts, :digest => @digest))
|
273
278
|
rescue => detail
|
274
279
|
Puppet.log_exception(detail)
|
@@ -24,13 +24,16 @@ class Puppet::Application::Device < Puppet::Application
|
|
24
24
|
end
|
25
25
|
|
26
26
|
{
|
27
|
+
:apply => nil,
|
27
28
|
:waitforcert => nil,
|
28
29
|
:detailed_exitcodes => false,
|
29
30
|
:verbose => false,
|
30
31
|
:debug => false,
|
31
32
|
:centrallogs => false,
|
32
33
|
:setdest => false,
|
34
|
+
:resource => false,
|
33
35
|
:target => nil,
|
36
|
+
:to_yaml => false,
|
34
37
|
}.each do |opt,val|
|
35
38
|
options[opt] = val
|
36
39
|
end
|
@@ -40,12 +43,18 @@ class Puppet::Application::Device < Puppet::Application
|
|
40
43
|
|
41
44
|
option("--centrallogging")
|
42
45
|
option("--debug","-d")
|
46
|
+
option("--resource","-r")
|
47
|
+
option("--to_yaml","-y")
|
43
48
|
option("--verbose","-v")
|
44
49
|
|
45
50
|
option("--detailed-exitcodes") do |arg|
|
46
51
|
options[:detailed_exitcodes] = true
|
47
52
|
end
|
48
53
|
|
54
|
+
option("--apply MANIFEST") do |arg|
|
55
|
+
options[:apply] = arg.to_s
|
56
|
+
end
|
57
|
+
|
49
58
|
option("--logdest DEST", "-l DEST") do |arg|
|
50
59
|
handle_logdest_arg(arg)
|
51
60
|
end
|
@@ -85,6 +94,7 @@ USAGE
|
|
85
94
|
puppet device [-d|--debug] [--detailed-exitcodes] [--deviceconfig <file>]
|
86
95
|
[-h|--help] [-l|--logdest syslog|<file>|console]
|
87
96
|
[-v|--verbose] [-w|--waitforcert <seconds>]
|
97
|
+
[-a|--apply <file>] [-r|--resource <type> [name]]
|
88
98
|
[-t|--target <device>] [--user=<user>] [-V|--version]
|
89
99
|
|
90
100
|
|
@@ -150,10 +160,21 @@ you can specify '--server <servername>' as an argument.
|
|
150
160
|
appending nature of logging. It must be appended manually to make the content
|
151
161
|
valid JSON.
|
152
162
|
|
163
|
+
* --apply:
|
164
|
+
Apply a manifest against a remote target. Target must be specified.
|
165
|
+
|
166
|
+
* --resource:
|
167
|
+
Displays a resource state as Puppet code, roughly equivalent to
|
168
|
+
`puppet resource`. Can be filterd by title. Requires --target be specified.
|
169
|
+
|
153
170
|
* --target:
|
154
171
|
Target a specific device/certificate in the device.conf. Doing so will perform a
|
155
172
|
device run against only that device/certificate.
|
156
173
|
|
174
|
+
* --to_yaml:
|
175
|
+
Output found resources in yaml format, suitable to use with Hiera and
|
176
|
+
create_resources.
|
177
|
+
|
157
178
|
* --user:
|
158
179
|
The user to run as.
|
159
180
|
|
@@ -170,7 +191,7 @@ you can specify '--server <servername>' as an argument.
|
|
170
191
|
|
171
192
|
EXAMPLE
|
172
193
|
-------
|
173
|
-
$ puppet device --
|
194
|
+
$ puppet device --target remotehost --verbose
|
174
195
|
|
175
196
|
AUTHOR
|
176
197
|
------
|
@@ -182,10 +203,24 @@ COPYRIGHT
|
|
182
203
|
Copyright (c) 2011 Puppet Inc., LLC
|
183
204
|
Licensed under the Apache 2.0 License
|
184
205
|
HELP
|
185
|
-
|
206
|
+
end
|
186
207
|
|
187
208
|
|
188
209
|
def main
|
210
|
+
if options[:resource] and !options[:target]
|
211
|
+
Puppet.err _("resource command requires target")
|
212
|
+
exit(1)
|
213
|
+
end
|
214
|
+
unless options[:apply].nil?
|
215
|
+
if options[:target].nil?
|
216
|
+
Puppet.err _("missing argument: --target is required when using --apply")
|
217
|
+
exit(1)
|
218
|
+
end
|
219
|
+
unless File.file?(options[:apply])
|
220
|
+
Puppet.err _("%{file} does not exist, cannot apply") % { file: options[:apply] }
|
221
|
+
exit(1)
|
222
|
+
end
|
223
|
+
end
|
189
224
|
vardir = Puppet[:vardir]
|
190
225
|
confdir = Puppet[:confdir]
|
191
226
|
certname = Puppet[:certname]
|
@@ -212,27 +247,61 @@ Licensed under the Apache 2.0 License
|
|
212
247
|
# Handle nil scheme & port
|
213
248
|
scheme = "#{device_url.scheme}://" if device_url.scheme
|
214
249
|
port = ":#{device_url.port}" if device_url.port
|
215
|
-
Puppet.info _("starting applying configuration to %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
|
216
250
|
|
217
251
|
# override local $vardir and $certname
|
218
252
|
Puppet[:confdir] = ::File.join(Puppet[:devicedir], device.name)
|
219
253
|
Puppet[:vardir] = ::File.join(Puppet[:devicedir], device.name)
|
220
254
|
Puppet[:certname] = device.name
|
221
255
|
|
222
|
-
# this will reload and recompute default settings and create the devices sub vardir, or we hope so :-)
|
223
|
-
Puppet.settings.use :main, :agent, :ssl
|
224
|
-
|
225
256
|
# this init the device singleton, so that the facts terminus
|
226
257
|
# and the various network_device provider can use it
|
227
258
|
Puppet::Util::NetworkDevice.init(device)
|
228
259
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
260
|
+
if options[:resource]
|
261
|
+
type, name = parse_args(command_line.args)
|
262
|
+
Puppet.info _("retrieving resource: %{resource} from %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { resource: type, target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
|
263
|
+
|
264
|
+
resources = find_resources(type, name)
|
265
|
+
|
266
|
+
if options[:to_yaml]
|
267
|
+
text = resources.map do |resource|
|
268
|
+
resource.prune_parameters(:parameters_to_include => @extra_params).to_hierayaml.force_encoding(Encoding.default_external)
|
269
|
+
end.join("\n")
|
270
|
+
text.prepend("#{type.downcase}:\n")
|
271
|
+
else
|
272
|
+
text = resources.map do |resource|
|
273
|
+
resource.prune_parameters(:parameters_to_include => @extra_params).to_manifest.force_encoding(Encoding.default_external)
|
274
|
+
end.join("\n")
|
275
|
+
end
|
276
|
+
(puts text)
|
277
|
+
elsif options[:apply]
|
278
|
+
# avoid reporting to server
|
279
|
+
Puppet::Transaction::Report.indirection.terminus_class = :yaml
|
280
|
+
Puppet::Resource::Catalog.indirection.cache_class = nil
|
281
|
+
|
282
|
+
require 'puppet/application/apply'
|
283
|
+
begin
|
284
|
+
|
285
|
+
Puppet[:node_terminus] = :plain
|
286
|
+
Puppet[:catalog_terminus] = :compiler
|
287
|
+
Puppet[:catalog_cache_terminus] = nil
|
288
|
+
Puppet[:facts_terminus] = :network_device
|
289
|
+
Puppet.override(:network_device => true) do
|
290
|
+
Puppet::Application::Apply.new(Puppet::Util::CommandLine.new('puppet', ["apply", options[:apply]])).run_command
|
291
|
+
end
|
292
|
+
end
|
293
|
+
else
|
294
|
+
Puppet.info _("starting applying configuration to %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
|
295
|
+
# this will reload and recompute default settings and create the devices sub vardir
|
296
|
+
Puppet.settings.use :main, :agent, :ssl
|
297
|
+
# ask for a ssl cert if needed, but at least
|
298
|
+
# setup the ssl system for this device.
|
299
|
+
setup_host
|
300
|
+
|
301
|
+
require 'puppet/configurer'
|
302
|
+
configurer = Puppet::Configurer.new
|
303
|
+
configurer.run(:network_device => true, :pluginsync => Puppet::Configurer.should_pluginsync?)
|
304
|
+
end
|
236
305
|
rescue => detail
|
237
306
|
Puppet.log_exception(detail)
|
238
307
|
# If we rescued an error, then we return 1 as the exit code
|
@@ -258,6 +327,24 @@ Licensed under the Apache 2.0 License
|
|
258
327
|
end
|
259
328
|
end
|
260
329
|
|
330
|
+
def parse_args(args)
|
331
|
+
type = args.shift or raise _("You must specify the type to display")
|
332
|
+
Puppet::Type.type(type) or raise _("Could not find type %{type}") % { type: type }
|
333
|
+
name = args.shift
|
334
|
+
|
335
|
+
[type, name]
|
336
|
+
end
|
337
|
+
|
338
|
+
def find_resources(type, name)
|
339
|
+
key = [type, name].join('/')
|
340
|
+
|
341
|
+
if name
|
342
|
+
[ Puppet::Resource.indirection.find( key ) ]
|
343
|
+
else
|
344
|
+
Puppet::Resource.indirection.search( key, {} )
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
261
348
|
def setup_host
|
262
349
|
@host = Puppet::SSL::Host.new
|
263
350
|
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
|