puppet-debugger 0.17.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +12 -26
- data/.rubocop.yml +64 -232
- data/.rubocop_todo.yml +89 -147
- data/.vscode/launch.json +15 -0
- data/CHANGELOG.md +29 -0
- data/Gemfile +9 -6
- data/README.md +27 -14
- data/Rakefile +11 -12
- data/bin/pdb +1 -1
- data/lib/awesome_print/ext/awesome_puppet.rb +10 -8
- data/lib/plugins/puppet-debugger/input_responders/benchmark.rb +5 -4
- data/lib/plugins/puppet-debugger/input_responders/classes.rb +14 -2
- data/lib/plugins/puppet-debugger/input_responders/classification.rb +4 -2
- data/lib/plugins/puppet-debugger/input_responders/commands.rb +18 -18
- data/lib/plugins/puppet-debugger/input_responders/datatypes.rb +22 -6
- data/lib/plugins/puppet-debugger/input_responders/environment.rb +4 -2
- data/lib/plugins/puppet-debugger/input_responders/exit.rb +5 -3
- data/lib/plugins/puppet-debugger/input_responders/facterdb_filter.rb +4 -2
- data/lib/plugins/puppet-debugger/input_responders/facts.rb +4 -2
- data/lib/plugins/puppet-debugger/input_responders/functions.rb +34 -32
- data/lib/plugins/puppet-debugger/input_responders/help.rb +4 -2
- data/lib/plugins/puppet-debugger/input_responders/krt.rb +4 -2
- data/lib/plugins/puppet-debugger/input_responders/play.rb +22 -24
- data/lib/plugins/puppet-debugger/input_responders/reset.rb +5 -3
- data/lib/plugins/puppet-debugger/input_responders/resources.rb +16 -7
- data/lib/plugins/puppet-debugger/input_responders/set.rb +34 -32
- data/lib/plugins/puppet-debugger/input_responders/stacktrace.rb +31 -0
- data/lib/plugins/puppet-debugger/input_responders/types.rb +6 -2
- data/lib/plugins/puppet-debugger/input_responders/vars.rb +8 -7
- data/lib/plugins/puppet-debugger/input_responders/whereami.rb +5 -3
- data/lib/puppet-debugger/cli.rb +129 -91
- data/lib/puppet-debugger/code/code_file.rb +13 -14
- data/lib/puppet-debugger/code/code_range.rb +5 -3
- data/lib/puppet-debugger/code/loc.rb +1 -1
- data/lib/puppet-debugger/debugger_code.rb +2 -0
- data/lib/puppet-debugger/hooks.rb +15 -16
- data/lib/puppet-debugger/input_responder_plugin.rb +54 -52
- data/lib/puppet-debugger/monkey_patches.rb +4 -1
- data/lib/puppet-debugger/plugin_test_helper.rb +9 -8
- data/lib/puppet-debugger/support.rb +44 -18
- data/lib/puppet-debugger/support/environment.rb +6 -5
- data/lib/puppet-debugger/support/errors.rb +25 -27
- data/lib/puppet-debugger/support/facts.rb +5 -5
- data/lib/puppet-debugger/support/node.rb +4 -7
- data/lib/puppet-debugger/support/scope.rb +29 -0
- data/lib/puppet-debugger/trollop.rb +38 -31
- data/lib/puppet-debugger/version.rb +1 -1
- data/lib/puppet/application/debugger.rb +151 -126
- data/output.json +1 -0
- data/puppet-debugger.gemspec +18 -15
- data/spec/awesome_print/ext/awesome_puppet_spec.rb +30 -30
- data/spec/fixtures/pe-xl-core-0.puppet.vm.json +1 -0
- data/spec/fixtures/sample_start_debugger.pp +3 -2
- data/spec/hooks_spec.rb +33 -35
- data/spec/input_responder_plugin_spec.rb +7 -6
- data/spec/input_responders/benchmark_spec.rb +3 -1
- data/spec/input_responders/classes_spec.rb +12 -13
- data/spec/input_responders/classification_spec.rb +4 -2
- data/spec/input_responders/commands_spec.rb +2 -0
- data/spec/input_responders/datatypes_spec.rb +8 -2
- data/spec/input_responders/environment_spec.rb +2 -0
- data/spec/input_responders/exit_spec.rb +9 -11
- data/spec/input_responders/facterdb_filter_spec.rb +2 -0
- data/spec/input_responders/facts_spec.rb +2 -0
- data/spec/input_responders/functions_spec.rb +30 -28
- data/spec/input_responders/help_spec.rb +5 -3
- data/spec/input_responders/krt_spec.rb +3 -1
- data/spec/input_responders/play_spec.rb +10 -20
- data/spec/input_responders/reset_spec.rb +2 -0
- data/spec/input_responders/resources_spec.rb +7 -1
- data/spec/input_responders/set_spec.rb +3 -1
- data/spec/input_responders/stacktrace_spec.rb +15 -0
- data/spec/input_responders/types_spec.rb +2 -0
- data/spec/input_responders/vars_spec.rb +4 -4
- data/spec/input_responders/whereami_spec.rb +2 -0
- data/spec/pdb_spec.rb +0 -9
- data/spec/puppet/application/debugger_spec.rb +35 -17
- data/spec/puppet_debugger_spec.rb +81 -84
- data/spec/remote_node_spec.rb +1 -5
- data/spec/spec_helper.rb +22 -18
- data/spec/support_spec.rb +3 -5
- data/test_matrix.rb +1 -1
- metadata +54 -21
@@ -9,8 +9,6 @@ module PuppetDebugger
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
12
|
class FatalError < Error
|
15
13
|
end
|
16
14
|
|
@@ -22,9 +20,9 @@ module PuppetDebugger
|
|
22
20
|
|
23
21
|
class ConnectError < Error
|
24
22
|
def message
|
25
|
-
|
26
|
-
#{data[:message]}
|
27
|
-
|
23
|
+
<<~OUT
|
24
|
+
#{data[:message]}
|
25
|
+
OUT
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
@@ -36,9 +34,9 @@ EOF
|
|
36
34
|
|
37
35
|
class UndefinedNode < FatalError
|
38
36
|
def message
|
39
|
-
|
40
|
-
Cannot find node with name: #{data[:name]} on remote server
|
41
|
-
|
37
|
+
<<~OUT
|
38
|
+
Cannot find node with name: #{data[:name]} on remote server
|
39
|
+
OUT
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
@@ -48,36 +46,36 @@ Cannot find node with name: #{data[:name]} on remote server
|
|
48
46
|
|
49
47
|
class NoClassError < FatalError
|
50
48
|
def message
|
51
|
-
|
52
|
-
#{data[:message]}
|
53
|
-
You are missing puppet classes that are required for compilation.
|
54
|
-
Please ensure these classes are installed on this machine in any of the following paths:
|
55
|
-
#{data[:default_modules_paths]}
|
56
|
-
|
49
|
+
<<~OUT
|
50
|
+
#{data[:message]}
|
51
|
+
You are missing puppet classes that are required for compilation.
|
52
|
+
Please ensure these classes are installed on this machine in any of the following paths:
|
53
|
+
#{data[:default_modules_paths]}
|
54
|
+
OUT
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
60
58
|
class NodeDefinitionError < FatalError
|
61
59
|
def message
|
62
|
-
out =
|
63
|
-
You are missing a default node definition in your site.pp that is required for compilation.
|
64
|
-
Please ensure you have at least the following default node definition
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
in your #{data[:default_site_manifest]} file.
|
69
|
-
|
60
|
+
out = <<~OUT
|
61
|
+
You are missing a default node definition in your site.pp that is required for compilation.
|
62
|
+
Please ensure you have at least the following default node definition
|
63
|
+
node default {
|
64
|
+
# include classes here
|
65
|
+
}
|
66
|
+
in your #{data[:default_site_manifest]} file.
|
67
|
+
OUT
|
70
68
|
out.fatal
|
71
69
|
end
|
72
70
|
end
|
73
71
|
|
74
72
|
class AuthError < FatalError
|
75
73
|
def message
|
76
|
-
|
77
|
-
#{data[:message]}
|
78
|
-
You will need to edit your auth.conf or conf.d/auth.conf (puppetserver) to allow node calls.
|
79
|
-
|
80
|
-
|
74
|
+
<<~OUT
|
75
|
+
#{data[:message]}
|
76
|
+
You will need to edit your auth.conf or conf.d/auth.conf (puppetserver) to allow node calls.
|
77
|
+
OUT
|
78
|
+
end
|
81
79
|
end
|
82
80
|
end
|
83
81
|
end
|
@@ -46,11 +46,11 @@ module PuppetDebugger
|
|
46
46
|
def node_facts
|
47
47
|
node_facts = FacterDB.get_facts(dynamic_facterdb_filter).first
|
48
48
|
if node_facts.nil?
|
49
|
-
message =
|
50
|
-
Using filter: #{dynamic_facterdb_filter}
|
51
|
-
Bad FacterDB filter, please change the filter so it returns a result set.
|
52
|
-
See https://github.com/camptocamp/facterdb/#with-a-string-filter
|
53
|
-
|
49
|
+
message = <<~OUT
|
50
|
+
Using filter: #{dynamic_facterdb_filter}
|
51
|
+
Bad FacterDB filter, please change the filter so it returns a result set.
|
52
|
+
See https://github.com/camptocamp/facterdb/#with-a-string-filter
|
53
|
+
OUT
|
54
54
|
raise PuppetDebugger::Exception::BadFilter, message: message
|
55
55
|
end
|
56
56
|
# fix for when --show-legacy facts are not part of the facter 3 fact set
|
@@ -8,8 +8,6 @@ module PuppetDebugger
|
|
8
8
|
# creates a node object using defaults or gets the remote node
|
9
9
|
# object if the remote_node_name is defined
|
10
10
|
def create_node
|
11
|
-
Puppet[:trusted_server_facts] = true if Puppet.version.to_f >= 4.1 && Puppet.version.to_f < 6.0
|
12
|
-
|
13
11
|
if remote_node_name
|
14
12
|
# refetch
|
15
13
|
node_obj = set_node_from_name(remote_node_name)
|
@@ -34,6 +32,7 @@ module PuppetDebugger
|
|
34
32
|
# Collect our facts.
|
35
33
|
facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
|
36
34
|
raise "Could not find facts for #{Puppet[:node_name_value]}" unless facts
|
35
|
+
|
37
36
|
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
|
38
37
|
facts.name = Puppet[:node_name_value]
|
39
38
|
end
|
@@ -41,6 +40,7 @@ module PuppetDebugger
|
|
41
40
|
# Find our Node
|
42
41
|
node = Puppet::Node.indirection.find(Puppet[:node_name_value])
|
43
42
|
raise "Could not find node #{Puppet[:node_name_value]}" unless node
|
43
|
+
|
44
44
|
# Merge in the facts.
|
45
45
|
node.merge(facts.values) if facts
|
46
46
|
end
|
@@ -93,11 +93,8 @@ module PuppetDebugger
|
|
93
93
|
def set_node_from_name(name)
|
94
94
|
out_buffer.puts "Fetching node #{name}"
|
95
95
|
remote_node = get_remote_node(name)
|
96
|
-
|
97
|
-
|
98
|
-
raise PuppetDebugger::Exception::UndefinedNode, name: remote_node.name
|
99
|
-
end
|
100
|
-
remote_node_name = remote_node.name
|
96
|
+
raise PuppetDebugger::Exception::UndefinedNode, name: remote_node.name if remote_node&.parameters&.empty?
|
97
|
+
|
101
98
|
node_object = convert_remote_node(remote_node)
|
102
99
|
set_node(node_object)
|
103
100
|
end
|
@@ -8,6 +8,35 @@ module PuppetDebugger
|
|
8
8
|
@scope = value
|
9
9
|
end
|
10
10
|
|
11
|
+
def catalog
|
12
|
+
@catalog || scope.compiler.catalog
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_catalog_text(catalog)
|
16
|
+
return nil unless catalog
|
17
|
+
|
18
|
+
Puppet::FileSystem.read(catalog, encoding: 'utf-8')
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_catalog(catalog_file)
|
22
|
+
return unless catalog_file
|
23
|
+
|
24
|
+
catalog_text = get_catalog_text(catalog_file)
|
25
|
+
scope # required
|
26
|
+
Puppet.override({ current_environment: environment }, _('For puppet debugger')) do
|
27
|
+
format = Puppet::Resource::Catalog.default_format
|
28
|
+
begin
|
29
|
+
c = Puppet::Resource::Catalog.convert_from(format, catalog_text)
|
30
|
+
rescue StandardError => e
|
31
|
+
raise Puppet::Error, format(_('Could not deserialize catalog from %{format}: %{detail}'), format: format, detail: e), e.backtrace
|
32
|
+
end
|
33
|
+
# Resolve all deferred values and replace them / mutate the catalog
|
34
|
+
# Puppet 6 only
|
35
|
+
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, c) if Gem::Version.new(Puppet.version) >= Gem::Version.new('6.0.0')
|
36
|
+
@catalog = c
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
11
40
|
# @return [Puppet::Pops::Scope] - returns a puppet scope object
|
12
41
|
def scope
|
13
42
|
@scope ||= create_scope
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
# lib/trollop.rb -- trollop command-line processing library
|
3
4
|
# Copyright (c) 2008-2014 William Morgan.
|
4
5
|
# Copyright (c) 2014 Red Hat, Inc.
|
@@ -33,10 +34,10 @@ module Trollop
|
|
33
34
|
end
|
34
35
|
|
35
36
|
## Regex for floating point numbers
|
36
|
-
FLOAT_RE = /^-?((\d+(\.\d+)?)|(\.\d+))([eE][-+]?[\d]+)
|
37
|
+
FLOAT_RE = /^-?((\d+(\.\d+)?)|(\.\d+))([eE][-+]?[\d]+)?$/.freeze
|
37
38
|
|
38
39
|
## Regex for parameters
|
39
|
-
PARAM_RE = /^-(-|\.$|[^\d\.])
|
40
|
+
PARAM_RE = /^-(-|\.$|[^\d\.])/.freeze
|
40
41
|
|
41
42
|
## The commandline parser. In typical usage, the methods in this class
|
42
43
|
## will be handled internally by Trollop::options. In this case, only the
|
@@ -50,24 +51,24 @@ module Trollop
|
|
50
51
|
class Parser
|
51
52
|
## The set of values that indicate a flag option when passed as the
|
52
53
|
## +:type+ parameter of #opt.
|
53
|
-
FLAG_TYPES = [
|
54
|
+
FLAG_TYPES = %i[flag bool boolean].freeze
|
54
55
|
|
55
56
|
## The set of values that indicate a single-parameter (normal) option when
|
56
57
|
## passed as the +:type+ parameter of #opt.
|
57
58
|
##
|
58
59
|
## A value of +io+ corresponds to a readable IO resource, including
|
59
60
|
## a filename, URI, or the strings 'stdin' or '-'.
|
60
|
-
SINGLE_ARG_TYPES = [
|
61
|
+
SINGLE_ARG_TYPES = %i[int integer string double float io date].freeze
|
61
62
|
|
62
63
|
## The set of values that indicate a multiple-parameter option (i.e., that
|
63
64
|
## takes multiple space-separated values on the commandline) when passed as
|
64
65
|
## the +:type+ parameter of #opt.
|
65
|
-
MULTI_ARG_TYPES = [
|
66
|
+
MULTI_ARG_TYPES = %i[ints integers strings doubles floats ios dates].freeze
|
66
67
|
|
67
68
|
## The complete set of legal values for the +:type+ parameter of #opt.
|
68
69
|
TYPES = FLAG_TYPES + SINGLE_ARG_TYPES + MULTI_ARG_TYPES
|
69
70
|
|
70
|
-
INVALID_SHORT_ARG_REGEX = /[\d-]
|
71
|
+
INVALID_SHORT_ARG_REGEX = /[\d-]/.freeze #:nodoc:
|
71
72
|
|
72
73
|
## The values from the commandline that were not interpreted by #parse.
|
73
74
|
attr_reader :leftovers
|
@@ -151,8 +152,7 @@ module Trollop
|
|
151
152
|
when :doubles then :floats
|
152
153
|
when Class
|
153
154
|
case opts[:type].name
|
154
|
-
when 'TrueClass',
|
155
|
-
'FalseClass' then :flag
|
155
|
+
when 'TrueClass', 'FalseClass' then :flag
|
156
156
|
when 'String' then :string
|
157
157
|
when 'Integer' then :int
|
158
158
|
when 'Float' then :float
|
@@ -164,6 +164,7 @@ module Trollop
|
|
164
164
|
when nil then nil
|
165
165
|
else
|
166
166
|
raise ArgumentError, "unsupported argument type '#{opts[:type]}'" unless TYPES.include?(opts[:type])
|
167
|
+
|
167
168
|
opts[:type]
|
168
169
|
end
|
169
170
|
|
@@ -175,14 +176,13 @@ module Trollop
|
|
175
176
|
opts[:default].first
|
176
177
|
else
|
177
178
|
opts[:default]
|
178
|
-
|
179
|
+
end
|
179
180
|
|
180
181
|
type_from_default =
|
181
182
|
case disambiguated_default
|
182
183
|
when Integer then :int
|
183
184
|
when Numeric then :float
|
184
|
-
when TrueClass,
|
185
|
-
FalseClass then :flag
|
185
|
+
when TrueClass, FalseClass then :flag
|
186
186
|
when String then :string
|
187
187
|
when IO then :io
|
188
188
|
when Date then :date
|
@@ -190,6 +190,7 @@ module Trollop
|
|
190
190
|
if opts[:default].empty?
|
191
191
|
if opts[:type]
|
192
192
|
raise ArgumentError, 'multiple argument type must be plural' unless MULTI_ARG_TYPES.include?(opts[:type])
|
193
|
+
|
193
194
|
nil
|
194
195
|
else
|
195
196
|
raise ArgumentError, "multiple argument type cannot be deduced from an empty array for '#{opts[:default][0].class.name}'"
|
@@ -220,7 +221,7 @@ module Trollop
|
|
220
221
|
when /^--([^-].*)$/ then Regexp.last_match(1)
|
221
222
|
when /^[^-]/ then opts[:long]
|
222
223
|
else raise ArgumentError, "invalid long option name #{opts[:long].inspect}"
|
223
|
-
|
224
|
+
end
|
224
225
|
raise ArgumentError, "long option name #{opts[:long].inspect} is already taken; please specify a (different) :long" if @long[opts[:long]]
|
225
226
|
|
226
227
|
## fill in :short
|
@@ -229,7 +230,7 @@ module Trollop
|
|
229
230
|
when /^-(.)$/ then Regexp.last_match(1)
|
230
231
|
when nil, :none, /^.$/ then opts[:short]
|
231
232
|
else raise ArgumentError, "invalid short option name '#{opts[:short].inspect}'"
|
232
|
-
|
233
|
+
end
|
233
234
|
|
234
235
|
if opts[:short]
|
235
236
|
raise ArgumentError, "short option name #{opts[:short].inspect} is already taken; please specify a (different) :short" if @short[opts[:short]]
|
@@ -255,21 +256,21 @@ module Trollop
|
|
255
256
|
## Sets the version string. If set, the user can request the version
|
256
257
|
## on the commandline. Should probably be of the form "<program name>
|
257
258
|
## <version number>".
|
258
|
-
def version(
|
259
|
-
|
259
|
+
def version(value = nil)
|
260
|
+
value ? @version = value : @version
|
260
261
|
end
|
261
262
|
|
262
263
|
## Sets the usage string. If set the message will be printed as the
|
263
264
|
## first line in the help (educate) output and ending in two new
|
264
265
|
## lines.
|
265
|
-
def usage(
|
266
|
-
|
266
|
+
def usage(value = nil)
|
267
|
+
value ? @usage = value : @usage
|
267
268
|
end
|
268
269
|
|
269
270
|
## Adds a synopsis (command summary description) right below the
|
270
271
|
## usage line, or as the first line if usage isn't specified.
|
271
|
-
def synopsis(
|
272
|
-
|
272
|
+
def synopsis(value = nil)
|
273
|
+
value ? @synopsis = value : @synopsis
|
273
274
|
end
|
274
275
|
|
275
276
|
## Adds text to the help display. Can be interspersed with calls to
|
@@ -347,22 +348,20 @@ module Trollop
|
|
347
348
|
["--#{Regexp.last_match(1)}", true]
|
348
349
|
else
|
349
350
|
[arg, false]
|
350
|
-
|
351
|
+
end
|
351
352
|
|
352
353
|
sym = case arg
|
353
354
|
when /^-([^-])$/ then @short[Regexp.last_match(1)]
|
354
355
|
when /^--([^-]\S*)$/ then @long[Regexp.last_match(1)] || @long["no-#{Regexp.last_match(1)}"]
|
355
356
|
else raise CommandlineError, "invalid argument syntax: '#{arg}'"
|
356
|
-
|
357
|
+
end
|
357
358
|
|
358
359
|
sym = nil if arg =~ /--no-/ # explicitly invalidate --no-no- arguments
|
359
360
|
|
360
361
|
next 0 if ignore_invalid_options && !sym
|
361
362
|
raise CommandlineError, "unknown argument '#{arg}'" unless sym
|
362
363
|
|
363
|
-
if given_args.include?(sym) && !@specs[sym][:multi]
|
364
|
-
raise CommandlineError, "option '#{arg}' specified multiple times"
|
365
|
-
end
|
364
|
+
raise CommandlineError, "option '#{arg}' specified multiple times" if given_args.include?(sym) && !@specs[sym][:multi]
|
366
365
|
|
367
366
|
given_args[sym] ||= {}
|
368
367
|
given_args[sym][:arg] = arg
|
@@ -396,9 +395,13 @@ module Trollop
|
|
396
395
|
|
397
396
|
case type
|
398
397
|
when :depends
|
399
|
-
syms.each
|
398
|
+
syms.each do |sym|
|
399
|
+
raise CommandlineError, "--#{@specs[constraint_sym][:long]} requires --#{@specs[sym][:long]}" unless given_args.include? sym
|
400
|
+
end
|
400
401
|
when :conflicts
|
401
|
-
syms.each
|
402
|
+
syms.each do |sym|
|
403
|
+
raise CommandlineError, "--#{@specs[constraint_sym][:long]} conflicts with --#{@specs[sym][:long]}" if given_args.include?(sym) && (sym != constraint_sym)
|
404
|
+
end
|
402
405
|
end
|
403
406
|
end
|
404
407
|
|
@@ -413,6 +416,7 @@ module Trollop
|
|
413
416
|
opts = @specs[sym]
|
414
417
|
if params.empty? && opts[:type] != :flag
|
415
418
|
raise CommandlineError, "option '#{arg}' needs a parameter" unless opts[:default]
|
419
|
+
|
416
420
|
params << (opts[:default].is_a?(Array) ? opts[:default].clone : [opts[:default]])
|
417
421
|
end
|
418
422
|
|
@@ -527,7 +531,7 @@ module Trollop
|
|
527
531
|
spec[:default].join(', ')
|
528
532
|
else
|
529
533
|
spec[:default].to_s
|
530
|
-
|
534
|
+
end
|
531
535
|
|
532
536
|
if spec[:default]
|
533
537
|
if spec[:desc] =~ /\.$/
|
@@ -553,7 +557,7 @@ module Trollop
|
|
553
557
|
end
|
554
558
|
else
|
555
559
|
80
|
556
|
-
|
560
|
+
end
|
557
561
|
end
|
558
562
|
|
559
563
|
def legacy_width
|
@@ -580,15 +584,15 @@ module Trollop
|
|
580
584
|
## The per-parser version of Trollop::die (see that for documentation).
|
581
585
|
def die(arg, msg = nil, error_code = nil)
|
582
586
|
if msg
|
583
|
-
|
587
|
+
warn "Error: argument --#{@specs[arg][:long]} #{msg}."
|
584
588
|
else
|
585
|
-
|
589
|
+
warn "Error: #{arg}."
|
586
590
|
end
|
587
591
|
if @educate_on_error
|
588
592
|
$stderr.puts
|
589
593
|
educate $stderr
|
590
594
|
else
|
591
|
-
|
595
|
+
warn 'Try --help for help.'
|
592
596
|
end
|
593
597
|
exit(error_code || -1)
|
594
598
|
end
|
@@ -602,6 +606,7 @@ module Trollop
|
|
602
606
|
|
603
607
|
until i >= args.length
|
604
608
|
return remains += args[i..-1] if @stop_words.member? args[i]
|
609
|
+
|
605
610
|
case args[i]
|
606
611
|
when /^--$/ # arg terminator
|
607
612
|
return remains += args[(i + 1)..-1]
|
@@ -662,11 +667,13 @@ module Trollop
|
|
662
667
|
|
663
668
|
def parse_integer_parameter(param, arg)
|
664
669
|
raise CommandlineError, "option '#{arg}' needs an integer" unless param =~ /^-?[\d_]+$/
|
670
|
+
|
665
671
|
param.to_i
|
666
672
|
end
|
667
673
|
|
668
674
|
def parse_float_parameter(param, arg)
|
669
675
|
raise CommandlineError, "option '#{arg}' needs a floating-point number" unless param =~ FLOAT_RE
|
676
|
+
|
670
677
|
param.to_f
|
671
678
|
end
|
672
679
|
|
@@ -1,186 +1,199 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require 'puppet/application'
|
4
|
+
require 'optparse'
|
5
|
+
require 'puppet/util/command_line'
|
6
6
|
|
7
7
|
class Puppet::Application::Debugger < Puppet::Application
|
8
8
|
attr_reader :use_stdin
|
9
9
|
|
10
|
-
option(
|
10
|
+
option('--execute EXECUTE', '-e') do |arg|
|
11
11
|
options[:code] = arg
|
12
12
|
end
|
13
13
|
|
14
|
-
option(
|
14
|
+
option('--facterdb-filter FILTER') do |arg|
|
15
15
|
options[:use_facterdb] = true unless options[:node_name]
|
16
|
-
ENV[
|
16
|
+
ENV['DEBUGGER_FACTERDB_FILTER'] = arg if arg
|
17
17
|
end
|
18
18
|
|
19
|
-
option(
|
19
|
+
option('--test') do |_arg|
|
20
20
|
options[:quiet] = true
|
21
21
|
options[:run_once] = true
|
22
22
|
@use_stdin = true
|
23
23
|
end
|
24
24
|
|
25
|
-
option(
|
25
|
+
option('--no-facterdb') { |_arg| options[:use_facterdb] = false }
|
26
26
|
|
27
|
-
option(
|
27
|
+
option('--log-level LEVEL', '-l') do |arg|
|
28
28
|
Puppet::Util::Log.level = arg.to_sym
|
29
29
|
end
|
30
30
|
|
31
|
-
option(
|
31
|
+
option('--catalog catalog', '-c catalog') do |arg|
|
32
|
+
options[:catalog] = arg
|
33
|
+
end
|
34
|
+
|
35
|
+
option('--quiet', '-q') { |_arg| options[:quiet] = true }
|
32
36
|
|
33
|
-
option(
|
37
|
+
option('--play URL', '-p') do |arg|
|
34
38
|
options[:play] = arg
|
35
39
|
end
|
36
40
|
|
37
|
-
option(
|
41
|
+
option('--stdin', '-s') { |_arg| @use_stdin = true }
|
38
42
|
|
39
|
-
option(
|
43
|
+
option('--run-once', '-r') { |_arg| options[:run_once] = true }
|
40
44
|
|
41
|
-
option(
|
45
|
+
option('--node-name CERTNAME', '-n') do |arg|
|
42
46
|
options[:use_facterdb] = false
|
43
47
|
options[:node_name] = arg
|
44
48
|
end
|
45
49
|
|
46
50
|
def help
|
47
|
-
|
51
|
+
<<~HELP
|
48
52
|
|
49
|
-
puppet-debugger(8) -- Starts a debugger session using the puppet-debugger tool
|
50
|
-
========
|
53
|
+
puppet-debugger(8) -- Starts a debugger session using the puppet-debugger tool
|
54
|
+
========
|
51
55
|
|
52
|
-
SYNOPSIS
|
53
|
-
--------
|
54
|
-
A interactive command line tool for evaluating the puppet language and debugging
|
55
|
-
puppet code.
|
56
|
+
SYNOPSIS
|
57
|
+
--------
|
58
|
+
A interactive command line tool for evaluating the puppet language and debugging
|
59
|
+
puppet code.
|
56
60
|
|
57
|
-
USAGE
|
58
|
-
-----
|
59
|
-
puppet debugger [--help] [--version] [-e|--execute CODE] [--facterdb-filter FILTER]
|
60
|
-
|
61
|
-
|
61
|
+
USAGE
|
62
|
+
-----
|
63
|
+
puppet debugger [--help] [--version] [-e|--execute CODE] [--facterdb-filter FILTER]
|
64
|
+
[--test] [--no-facterdb] [-q|--quiet] [-p|--play URL] [-s|--stdin]
|
65
|
+
[-r|--run-once] [-n|--node-name CERTNAME]
|
62
66
|
|
63
67
|
|
64
|
-
DESCRIPTION
|
65
|
-
-----------
|
66
|
-
A interactive command line tool for evaluating the puppet language and debugging
|
67
|
-
puppet code.
|
68
|
+
DESCRIPTION
|
69
|
+
-----------
|
70
|
+
A interactive command line tool for evaluating the puppet language and debugging
|
71
|
+
puppet code.
|
72
|
+
|
73
|
+
USAGE WITH DEBUG MODULE
|
74
|
+
-----------------------
|
75
|
+
Use the puppet debugger in conjunction with the debug::break() puppet function
|
76
|
+
to pry into your code during compilation. Get immediate insight in how the puppet4
|
77
|
+
languge works during the execution of your code.
|
68
78
|
|
69
|
-
|
70
|
-
-----------------------
|
71
|
-
Use the puppet debugger in conjunction with the debug::break() puppet function
|
72
|
-
to pry into your code during compilation. Get immediate insight in how the puppet4
|
73
|
-
languge works during the execution of your code.
|
79
|
+
To use the break function install the module via: puppet module install nwops/debug
|
74
80
|
|
75
|
-
|
81
|
+
Now place the debug::break() function anywhere in your code to
|
76
82
|
|
77
|
-
|
83
|
+
Example:
|
84
|
+
puppet debugger -e '$abs_vars = [-11,-22,-33].map | Integer $num | { debug::break() ; notice($num) }'
|
78
85
|
|
79
|
-
|
80
|
-
|
86
|
+
See: https://github.com/nwops/puppet-debug
|
87
|
+
OPTIONS
|
88
|
+
-------
|
89
|
+
Note that any setting that's valid in the configuration
|
90
|
+
file is also a valid long argument. For example, 'server' is a valid
|
91
|
+
setting, so you can specify '--server <servername>' as
|
92
|
+
an argument.
|
81
93
|
|
82
|
-
See
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
setting, so you can specify '--server <servername>' as
|
88
|
-
an argument.
|
94
|
+
See the configuration file documentation at
|
95
|
+
http://docs.puppetlabs.com/references/stable/configuration.html for the
|
96
|
+
full list of acceptable parameters. A commented list of all
|
97
|
+
configuration options can also be generated by running puppet debugger with
|
98
|
+
'--genconfig'.
|
89
99
|
|
90
|
-
|
91
|
-
|
92
|
-
full list of acceptable parameters. A commented list of all
|
93
|
-
configuration options can also be generated by running puppet debugger with
|
94
|
-
'--genconfig'.
|
100
|
+
* --help:
|
101
|
+
Print this help message
|
95
102
|
|
96
|
-
* --
|
97
|
-
|
103
|
+
* --version:
|
104
|
+
Print the puppet version number and exit.
|
98
105
|
|
99
|
-
* --
|
100
|
-
|
106
|
+
* --execute:
|
107
|
+
Execute a specific piece of Puppet code
|
101
108
|
|
102
|
-
* --
|
103
|
-
|
109
|
+
* --facterdb-filter
|
110
|
+
Disables the usage of the current node level facts and uses cached facts
|
111
|
+
from facterdb. Specifying a filter will override the default facterdb filter.
|
112
|
+
Not specifiying a filter will use the default CentOS based filter.
|
113
|
+
This will greatly speed up the start time of the debugger since
|
114
|
+
you are using cached facts. Additionally, using facterdb also allows you
|
115
|
+
to play with many other operating system facts that you might not have access
|
116
|
+
to. For example filters please see the facterdb docs.
|
104
117
|
|
105
|
-
|
106
|
-
Disables the usage of the current node level facts and uses cached facts
|
107
|
-
from facterdb. Specifying a filter will override the default facterdb filter.
|
108
|
-
Not specifiying a filter will use the default CentOS based filter.
|
109
|
-
This will greatly speed up the start time of the debugger since
|
110
|
-
you are using cached facts. Additionally, using facterdb also allows you
|
111
|
-
to play with many other operating system facts that you might not have access
|
112
|
-
to. For example filters please see the facterdb docs.
|
118
|
+
See https://github.com/camptocamp/facterdb for more info
|
113
119
|
|
114
|
-
|
120
|
+
* --no-facterdb
|
121
|
+
Use the facts found on this node instead of cached facts from facterdb.
|
115
122
|
|
116
|
-
* --
|
117
|
-
|
123
|
+
* --log-level
|
124
|
+
Set the Puppet log level which can be very useful with using the debugger.
|
118
125
|
|
119
|
-
* --
|
120
|
-
|
126
|
+
* --quiet
|
127
|
+
Do not display the debugger help script upon startup.
|
121
128
|
|
122
|
-
* --
|
123
|
-
|
129
|
+
* --play
|
130
|
+
Plays back the code file supplied into the debugger. Can also supply
|
131
|
+
any http based url.
|
124
132
|
|
125
|
-
* --
|
126
|
-
|
127
|
-
any http based url.
|
133
|
+
* --run-once
|
134
|
+
Return the result from the debugger and exit
|
128
135
|
|
129
|
-
* --
|
130
|
-
|
136
|
+
* --stdin
|
137
|
+
Read from stdin instead of starting the debugger right away. Useful when piping code into the debugger.
|
131
138
|
|
132
|
-
* --
|
133
|
-
|
139
|
+
* --catalog:
|
140
|
+
Import a JSON catalog (such as one generated with 'puppet master --compile'). You need to
|
141
|
+
specify a valid JSON encoded catalog file. Gives you the ability
|
142
|
+
to inspect the catalog and all the parameter values that make up the resources. Can
|
143
|
+
specify a file or pipe to stdin with '-'.
|
134
144
|
|
135
|
-
* --node-name
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
145
|
+
* --node-name
|
146
|
+
Retrieves the node information remotely via the puppet server given the node name.
|
147
|
+
This is extremely useful when trying to debug classification issues, as this can show
|
148
|
+
classes and parameters retrieved from the ENC. You can also play around with the real facts
|
149
|
+
of the remote node as well.
|
140
150
|
|
141
|
-
|
142
|
-
|
151
|
+
Note: this requires special permission in your puppet server's auth.conf file to allow
|
152
|
+
access to make remote calls from this node: #{Puppet[:certname]}. If you are running
|
153
|
+
the debugger from the puppet server as root you do not need any special setup.
|
143
154
|
|
144
|
-
|
155
|
+
You must also have a signed cert and be able to connect to the server from this system.
|
145
156
|
|
146
|
-
|
157
|
+
Mutually exclusive with --facterdb-filter
|
147
158
|
|
148
|
-
* --test
|
149
|
-
|
159
|
+
* --test
|
160
|
+
Runs the code in the debugger and exit without showing the help screen ( --quiet --run-once, --stdin)
|
150
161
|
|
151
|
-
EXAMPLE
|
152
|
-
-------
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
+
EXAMPLE
|
163
|
+
-------
|
164
|
+
$ puppet debugger
|
165
|
+
$ echo "notice('hello, can you hear me?')" | puppet debugger --test
|
166
|
+
$ echo "notice('hello, can you hear me?')" | puppet debugger --stdin
|
167
|
+
$ puppet debugger --execute "notice('hello')"
|
168
|
+
$ puppet debugger --facterdb-filter 'facterversion=/^2.4\./ and operatingsystem=Debian'
|
169
|
+
$ puppet debugger --play https://gist.github.com/logicminds/4f6bcfd723c92aad1f01f6a800319fa4
|
170
|
+
$ puppet debugger --facterdb-filter 'facterversion=/^2.4\./ and operatingsystem=Debian' \\
|
171
|
+
--play https://gist.github.com/logicminds/4f6bcfd723c92aad1f01f6a800319fa4
|
172
|
+
$ puppet debugger --node-name
|
162
173
|
|
163
174
|
|
164
|
-
AUTHOR
|
165
|
-
------
|
166
|
-
Corey Osman <corey@nwops.io>
|
175
|
+
AUTHOR
|
176
|
+
------
|
177
|
+
Corey Osman <corey@nwops.io>
|
167
178
|
|
168
179
|
|
169
|
-
COPYRIGHT
|
170
|
-
---------
|
171
|
-
Copyright (c) 2019 NWOps
|
180
|
+
COPYRIGHT
|
181
|
+
---------
|
182
|
+
Copyright (c) 2019 NWOps
|
172
183
|
|
173
184
|
HELP
|
174
185
|
end
|
175
186
|
|
176
187
|
def initialize(command_line = Puppet::Util::CommandLine.new)
|
177
188
|
@command_line = CommandLineArgs.new(command_line.subcommand_name, command_line.args.dup)
|
178
|
-
@options = { use_facterdb: true, play: nil, run_once: false,
|
189
|
+
@options = { use_facterdb: true, play: nil, run_once: false,
|
190
|
+
node_name: nil, quiet: false, help: false, scope: nil,
|
191
|
+
catalog: nil }
|
179
192
|
@use_stdin = false
|
180
193
|
begin
|
181
|
-
require
|
182
|
-
rescue LoadError
|
183
|
-
Puppet.err(
|
194
|
+
require 'puppet-debugger'
|
195
|
+
rescue LoadError
|
196
|
+
Puppet.err('You must install the puppet-debugger: gem install puppet-debugger')
|
184
197
|
end
|
185
198
|
end
|
186
199
|
|
@@ -188,26 +201,26 @@ Copyright (c) 2019 NWOps
|
|
188
201
|
# if this is a file we don't play back since its part of the environment
|
189
202
|
# if just the code we put in a file and use the play feature of the debugger
|
190
203
|
# we could do the same thing with the passed in manifest file but that might be too much code to show
|
191
|
-
|
192
204
|
if options[:code]
|
193
205
|
code_input = options.delete(:code)
|
194
|
-
file = Tempfile.new([
|
195
|
-
File.open(file,
|
206
|
+
file = Tempfile.new(['puppet_debugger_input', '.pp'])
|
207
|
+
File.open(file, 'w') do |f|
|
196
208
|
f.write(code_input)
|
197
209
|
end
|
198
210
|
options[:play] = file
|
199
211
|
elsif command_line.args.empty? && use_stdin
|
200
212
|
code_input = STDIN.read
|
201
|
-
file = Tempfile.new([
|
202
|
-
File.open(file,
|
213
|
+
file = Tempfile.new(['puppet_debugger_input', '.pp'])
|
214
|
+
File.open(file, 'w') do |f|
|
203
215
|
f.write(code_input)
|
204
216
|
end
|
205
217
|
options[:play] = file
|
206
218
|
elsif !command_line.args.empty?
|
207
219
|
manifest = command_line.args.shift
|
208
220
|
raise "Could not find file #{manifest}" unless Puppet::FileSystem.exist?(manifest)
|
209
|
-
|
210
|
-
|
221
|
+
|
222
|
+
Puppet.warning("Only one file can be used per run. Skipping #{command_line.args.join(', ')}") unless command_line.args.empty?
|
223
|
+
options[:play] = manifest
|
211
224
|
end
|
212
225
|
begin
|
213
226
|
if !options[:use_facterdb] && options[:node_name].nil?
|
@@ -220,16 +233,23 @@ Copyright (c) 2019 NWOps
|
|
220
233
|
end
|
221
234
|
::PuppetDebugger::Cli.start_without_stdin(options)
|
222
235
|
rescue Exception => e
|
223
|
-
|
224
|
-
|
236
|
+
case e.class.to_s
|
237
|
+
when 'SystemExit'
|
238
|
+
nil
|
239
|
+
else
|
240
|
+
puts e.message
|
241
|
+
puts e.backtrace
|
242
|
+
end
|
225
243
|
end
|
226
244
|
end
|
227
245
|
|
228
246
|
def create_environment(manifest)
|
229
247
|
configured_environment = Puppet.lookup(:current_environment)
|
230
|
-
manifest
|
231
|
-
configured_environment.override_with(manifest: manifest)
|
248
|
+
if manifest
|
249
|
+
configured_environment.override_with(manifest: manifest)
|
250
|
+
else
|
232
251
|
configured_environment
|
252
|
+
end
|
233
253
|
end
|
234
254
|
|
235
255
|
def create_node(environment)
|
@@ -239,14 +259,16 @@ Copyright (c) 2019 NWOps
|
|
239
259
|
unless facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
|
240
260
|
raise "Could not find facts for #{Puppet[:node_name_value]}"
|
241
261
|
end
|
262
|
+
|
242
263
|
Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
|
243
264
|
facts.name = Puppet[:node_name_value]
|
244
265
|
end
|
245
|
-
Puppet.override({ current_environment: environment },
|
266
|
+
Puppet.override({ current_environment: environment }, 'For puppet debugger') do
|
246
267
|
# Find our Node
|
247
268
|
unless node = Puppet::Node.indirection.find(Puppet[:node_name_value])
|
248
269
|
raise "Could not find node #{Puppet[:node_name_value]}"
|
249
270
|
end
|
271
|
+
|
250
272
|
# Merge in the facts.
|
251
273
|
node.merge(facts.values) if facts
|
252
274
|
end
|
@@ -269,11 +291,14 @@ Copyright (c) 2019 NWOps
|
|
269
291
|
if $stdout.isatty
|
270
292
|
options = options.merge(scope: scope)
|
271
293
|
# required in order to use convert puppet hash into ruby hash with symbols
|
272
|
-
options = options.each_with_object({})
|
294
|
+
options = options.each_with_object({}) do |(k, v), data|
|
295
|
+
data[k.to_sym] = v
|
296
|
+
data
|
297
|
+
end
|
273
298
|
# options[:source_file], options[:source_line] = stacktrace.last
|
274
299
|
::PuppetRepl::Cli.start(options)
|
275
300
|
else
|
276
|
-
Puppet.info
|
301
|
+
Puppet.info 'puppet debug: refusing to start the debugger without a tty'
|
277
302
|
end
|
278
303
|
end
|
279
304
|
|
@@ -284,7 +309,7 @@ Copyright (c) 2019 NWOps
|
|
284
309
|
# for compatibility with older puppet versions
|
285
310
|
# The basics behind this are to find the `.pp` file in the list of loaded code
|
286
311
|
def stacktrace
|
287
|
-
|
312
|
+
caller.each_with_object([]) do |loc, memo|
|
288
313
|
if loc =~ /\A(.*\.pp)?:([0-9]+):in\s(.*)/
|
289
314
|
# if the file is not found we set to code
|
290
315
|
# and read from Puppet[:code]
|