puppet-debugger 0.19.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +10 -27
- data/.rubocop.yml +64 -232
- data/.rubocop_todo.yml +89 -147
- data/CHANGELOG.md +12 -1
- data/Gemfile +7 -5
- data/README.md +4 -5
- 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 +4 -1
- 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 +11 -5
- data/lib/plugins/puppet-debugger/input_responders/environment.rb +4 -2
- data/lib/plugins/puppet-debugger/input_responders/exit.rb +4 -2
- 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 +5 -2
- data/lib/plugins/puppet-debugger/input_responders/set.rb +34 -32
- data/lib/plugins/puppet-debugger/input_responders/stacktrace.rb +23 -0
- data/lib/plugins/puppet-debugger/input_responders/types.rb +6 -2
- data/lib/plugins/puppet-debugger/input_responders/vars.rb +6 -5
- data/lib/plugins/puppet-debugger/input_responders/whereami.rb +5 -3
- data/lib/puppet-debugger/cli.rb +118 -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 +27 -17
- data/lib/puppet-debugger/support/environment.rb +4 -4
- 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 -5
- data/lib/puppet-debugger/support/scope.rb +19 -17
- data/lib/puppet-debugger/trollop.rb +38 -31
- data/lib/puppet-debugger/version.rb +1 -1
- data/lib/puppet/application/debugger.rb +141 -135
- data/output.json +1 -0
- data/puppet-debugger.gemspec +17 -16
- data/spec/awesome_print/ext/awesome_puppet_spec.rb +30 -30
- 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 -10
- 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 +4 -3
- 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 +4 -2
- 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 +3 -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 +18 -19
- 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 +48 -31
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Help < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[help].freeze
|
6
8
|
SUMMARY = 'Show the help screen with version information.'
|
7
9
|
COMMAND_GROUP = :help
|
8
10
|
|
9
|
-
def run(
|
11
|
+
def run(_args = [])
|
10
12
|
PuppetDebugger::Cli.print_repl_desc
|
11
13
|
end
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Krt < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[krt].freeze
|
6
8
|
SUMMARY = 'List all the known resource types.'
|
7
9
|
COMMAND_GROUP = :scope
|
8
10
|
|
9
|
-
def run(
|
11
|
+
def run(_args = [])
|
10
12
|
debugger.known_resource_types.ai(sort_keys: true, indent: -1)
|
11
13
|
end
|
12
14
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Play < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[play].freeze
|
6
8
|
SUMMARY = 'Playback a file or URL as input.'
|
7
9
|
COMMAND_GROUP = :editing
|
8
10
|
|
@@ -20,7 +22,7 @@ module PuppetDebugger
|
|
20
22
|
elsif File.exist? config[:play]
|
21
23
|
play_back_string(File.read(config[:play]))
|
22
24
|
else config[:play]
|
23
|
-
|
25
|
+
debugger.out_buffer.puts "puppet-debugger can't play #{config[:play]}'"
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -29,29 +31,29 @@ module PuppetDebugger
|
|
29
31
|
require 'uri'
|
30
32
|
url_data = URI(url)
|
31
33
|
case url_data.host
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
when /^gist\.github*/
|
35
|
+
url = url += '.txt' unless url_data.path =~ /raw/
|
36
|
+
url
|
37
|
+
when /^github.com/
|
38
|
+
url.gsub('blob', 'raw') if url_data.path =~ /blob/
|
39
|
+
when /^gist.github.com/
|
40
|
+
url = url += '.txt' unless url_data.path =~ /raw/
|
41
|
+
url
|
42
|
+
when /^gitlab.com/
|
43
|
+
if url_data.path =~ /snippets/
|
44
|
+
url += '/raw' unless url_data.path =~ /raw/
|
39
45
|
url
|
40
|
-
when /^gitlab.com/
|
41
|
-
if url_data.path =~ /snippets/
|
42
|
-
url += '/raw' unless url_data.path =~ /raw/
|
43
|
-
url
|
44
|
-
else
|
45
|
-
url.gsub('blob', 'raw')
|
46
|
-
end
|
47
46
|
else
|
48
|
-
url
|
47
|
+
url.gsub('blob', 'raw')
|
48
|
+
end
|
49
|
+
else
|
50
|
+
url
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
54
|
# opens the url and reads the data
|
53
55
|
def fetch_url_data(url)
|
54
|
-
open(url).read
|
56
|
+
URI.open(url).read # open(url).read
|
55
57
|
end
|
56
58
|
|
57
59
|
def play_back_url(url)
|
@@ -72,12 +74,8 @@ module PuppetDebugger
|
|
72
74
|
begin
|
73
75
|
full_buffer += buf
|
74
76
|
# unless this is puppet code, otherwise skip repl keywords
|
75
|
-
|
76
|
-
|
77
|
-
else
|
78
|
-
debugger.parser.parse_string(full_buffer)
|
79
|
-
debugger.out_buffer.write('>> ')
|
80
|
-
end
|
77
|
+
debugger.parser.parse_string(full_buffer) unless PuppetDebugger::InputResponders::Commands.command_list_regex.match(buf)
|
78
|
+
debugger.out_buffer.write('>> ')
|
81
79
|
rescue Puppet::ParseErrorWithIssue => e
|
82
80
|
if debugger.multiline_input?(e)
|
83
81
|
full_buffer += "\n"
|
@@ -1,19 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Reset < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[reset].freeze
|
6
8
|
SUMMARY = 'Reset the debugger to a clean state.'
|
7
9
|
COMMAND_GROUP = :context
|
8
10
|
|
9
|
-
def run(
|
11
|
+
def run(_args = [])
|
10
12
|
debugger.set_scope(nil)
|
11
13
|
debugger.set_remote_node_name(nil)
|
12
14
|
debugger.set_node(nil)
|
13
15
|
debugger.set_facts(nil)
|
14
16
|
debugger.set_environment(nil)
|
15
17
|
debugger.set_compiler(nil)
|
16
|
-
#debugger.handle_input(":set loglevel #{debugger.log_level}")
|
18
|
+
# debugger.handle_input(":set loglevel #{debugger.log_level}")
|
17
19
|
nil
|
18
20
|
end
|
19
21
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Resources < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[resources].freeze
|
6
8
|
SUMMARY = 'List all the resources current in the catalog.'
|
7
9
|
COMMAND_GROUP = :scope
|
8
10
|
|
@@ -13,11 +15,12 @@ module PuppetDebugger
|
|
13
15
|
res.to_s.gsub(/\[/, "['").gsub(/\]/, "']") # ensure the title has quotes
|
14
16
|
end
|
15
17
|
output = "Resources not shown in any specific order\n".warning
|
16
|
-
output
|
18
|
+
output + modified.ai
|
17
19
|
end
|
18
20
|
|
19
21
|
def find_resources(resources, filter = [])
|
20
22
|
return resources if filter.nil? || filter.empty?
|
23
|
+
|
21
24
|
filter_string = filter.join(' ').downcase
|
22
25
|
resources.find_all do |resource|
|
23
26
|
resource.name.to_s.downcase.include?(filter_string) || resource.type.to_s.downcase.include?(filter_string)
|
@@ -1,28 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Set < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[set :set].freeze
|
6
8
|
SUMMARY = 'Set the a puppet debugger config'
|
7
9
|
COMMAND_GROUP = :scope
|
8
|
-
KEYWORDS = %w
|
9
|
-
LOGLEVELS = %w
|
10
|
+
KEYWORDS = %w[node loglevel].freeze
|
11
|
+
LOGLEVELS = %w[debug info].freeze
|
10
12
|
|
11
13
|
def self.command_completion(buffer_words)
|
12
14
|
next_word = buffer_words.shift
|
13
15
|
case next_word
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
LOGLEVELS
|
19
|
-
end
|
20
|
-
when 'debug', 'info','node'
|
21
|
-
[]
|
22
|
-
when nil
|
23
|
-
%w(node loglevel)
|
16
|
+
when 'loglevel'
|
17
|
+
if buffer_words.count.positive?
|
18
|
+
LOGLEVELS.grep(/^#{Regexp.escape(buffer_words.first)}/)
|
24
19
|
else
|
25
|
-
|
20
|
+
LOGLEVELS
|
21
|
+
end
|
22
|
+
when 'debug', 'info', 'node'
|
23
|
+
[]
|
24
|
+
when nil
|
25
|
+
%w[node loglevel]
|
26
|
+
else
|
27
|
+
KEYWORDS.grep(/^#{Regexp.escape(next_word)}/)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -37,24 +39,24 @@ module PuppetDebugger
|
|
37
39
|
# args = input.split(' ')
|
38
40
|
# args.shift # throw away the set
|
39
41
|
case input.shift
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
42
|
+
when /node/
|
43
|
+
if name = input.shift
|
44
|
+
output = "Resetting to use node #{name}"
|
45
|
+
debugger.set_scope(nil)
|
46
|
+
debugger.set_node(nil)
|
47
|
+
debugger.set_facts(nil)
|
48
|
+
debugger.set_environment(nil)
|
49
|
+
debugger.set_compiler(nil)
|
50
|
+
set_log_level(debugger.log_level)
|
51
|
+
debugger.set_remote_node_name(name)
|
52
|
+
else
|
53
|
+
debugger.out_buffer.puts 'Must supply a valid node name'
|
54
|
+
end
|
55
|
+
when /loglevel/
|
56
|
+
if level = input.shift
|
57
|
+
set_log_level(level)
|
58
|
+
output = "loglevel #{Puppet::Util::Log.level} is set"
|
59
|
+
end
|
58
60
|
end
|
59
61
|
output
|
60
62
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puppet-debugger/input_responder_plugin'
|
4
|
+
module PuppetDebugger
|
5
|
+
module InputResponders
|
6
|
+
class Stacktrace < InputResponderPlugin
|
7
|
+
COMMAND_WORDS = %w[stacktrace].freeze
|
8
|
+
SUMMARY = 'Show the stacktrace for how we got here'
|
9
|
+
COMMAND_GROUP = :tools
|
10
|
+
|
11
|
+
# @return [Array]- returns a array of pp files that are involved in the stacktrace
|
12
|
+
def run(_args = [])
|
13
|
+
s = stacktrace
|
14
|
+
s.empty? ? 'stacktrace not available'.warning : s.ai
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Array] - an array of files
|
18
|
+
def stacktrace
|
19
|
+
Puppet::Pops::PuppetStack.stacktrace.find_all { |line| !line.include?('unknown') }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Types < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[types].freeze
|
6
8
|
SUMMARY = 'List all the types available in the environment.'
|
7
9
|
COMMAND_GROUP = :environment
|
8
10
|
|
9
11
|
# @return - returns a list of types available to the environment
|
10
12
|
# if a error occurs we we run the types function again
|
11
|
-
def run(
|
13
|
+
def run(_args = [])
|
12
14
|
types
|
13
15
|
end
|
14
16
|
|
@@ -19,6 +21,7 @@ module PuppetDebugger
|
|
19
21
|
Puppet::Type.loadall
|
20
22
|
Puppet::Type.eachtype do |t|
|
21
23
|
next if t.name == :component
|
24
|
+
|
22
25
|
loaded_types << t.name.to_s
|
23
26
|
end
|
24
27
|
loaded_types.ai
|
@@ -27,6 +30,7 @@ module PuppetDebugger
|
|
27
30
|
Puppet.info(e.message)
|
28
31
|
# prevent more than two calls and recursive loop
|
29
32
|
return if caller_locations(1, 10).find_all { |f| f.label == 'types' }.count > 2
|
33
|
+
|
30
34
|
types
|
31
35
|
end
|
32
36
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Vars < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[vars ls].freeze
|
6
8
|
SUMMARY = 'List all the variables in the current scopes.'
|
7
9
|
COMMAND_GROUP = :scope
|
8
10
|
|
@@ -16,11 +18,11 @@ module PuppetDebugger
|
|
16
18
|
variables = debugger.scope.to_hash.delete_if { |key, _value| debugger.node.facts.values.key?(key) }
|
17
19
|
variables['facts'] = 'removed by the puppet-debugger' if variables.key?('facts')
|
18
20
|
output = 'Facts were removed for easier viewing'.ai + "\n"
|
19
|
-
output
|
21
|
+
output + variables.ai(sort_keys: true, indent: -1)
|
20
22
|
end
|
21
23
|
|
22
24
|
def resource_parameters(resources, filter = [])
|
23
|
-
find_resources(resources, filter).each_with_object({}) do |
|
25
|
+
find_resources(resources, filter).each_with_object({}) do |resource, acc|
|
24
26
|
name = "#{resource.type}[#{resource.name}]"
|
25
27
|
acc[name] = parameters_to_h(resource)
|
26
28
|
acc
|
@@ -28,7 +30,7 @@ module PuppetDebugger
|
|
28
30
|
end
|
29
31
|
|
30
32
|
def parameters_to_h(resource)
|
31
|
-
resource.parameters.each_with_object({}) do |
|
33
|
+
resource.parameters.each_with_object({}) do |param, params|
|
32
34
|
name = param.first.to_s
|
33
35
|
params[name] = param.last.respond_to?(:value) ? param.last.value : param.last
|
34
36
|
params
|
@@ -41,7 +43,6 @@ module PuppetDebugger
|
|
41
43
|
resource.name.to_s.downcase.include?(filter_string) || resource.type.to_s.downcase.include?(filter_string)
|
42
44
|
end
|
43
45
|
end
|
44
|
-
|
45
46
|
end
|
46
47
|
end
|
47
48
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'puppet-debugger/input_responder_plugin'
|
2
4
|
module PuppetDebugger
|
3
5
|
module InputResponders
|
4
6
|
class Whereami < InputResponderPlugin
|
5
|
-
COMMAND_WORDS = %w
|
7
|
+
COMMAND_WORDS = %w[whereami].freeze
|
6
8
|
SUMMARY = 'Show code surrounding the current context.'
|
7
9
|
COMMAND_GROUP = :context
|
8
10
|
|
@@ -21,8 +23,8 @@ module PuppetDebugger
|
|
21
23
|
else
|
22
24
|
code = DebuggerCode.from_file(file, :puppet)
|
23
25
|
end
|
24
|
-
|
25
|
-
|
26
|
+
code.with_marker(line_num).around(line_num, num_lines)
|
27
|
+
.with_line_numbers.with_indentation(5).with_file_reference.to_s
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
data/lib/puppet-debugger/cli.rb
CHANGED
@@ -1,31 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
|
3
|
+
require 'puppet'
|
4
|
+
require 'readline'
|
5
|
+
require 'json'
|
6
|
+
require 'puppet-debugger/support'
|
7
|
+
require 'pluginator'
|
8
|
+
require 'puppet-debugger/hooks'
|
9
|
+
require 'forwardable'
|
10
|
+
require 'plugins/puppet-debugger/input_responders/functions'
|
11
|
+
require 'plugins/puppet-debugger/input_responders/datatypes'
|
12
|
+
require 'tty-pager'
|
13
13
|
module PuppetDebugger
|
14
14
|
class Cli
|
15
15
|
include PuppetDebugger::Support
|
16
16
|
extend Forwardable
|
17
17
|
attr_accessor :settings, :log_level, :in_buffer, :out_buffer, :html_mode, :extra_prompt, :bench
|
18
|
-
attr_reader :source_file, :source_line_num, :hooks
|
18
|
+
attr_reader :source_file, :source_line_num, :hooks, :options
|
19
19
|
def_delegators :hooks, :exec_hook, :add_hook, :delete_hook
|
20
|
-
|
20
|
+
OUT_SYMBOL = ' => '
|
21
21
|
def initialize(options = {})
|
22
22
|
do_initialize if Puppet[:codedir].nil?
|
23
23
|
Puppet.settings[:name] = :debugger
|
24
|
+
@options = options
|
24
25
|
Puppet[:static_catalogs] = false unless Puppet.settings[:static_catalogs].nil?
|
25
26
|
set_remote_node_name(options[:node_name])
|
26
27
|
initialize_from_scope(options[:scope])
|
27
28
|
set_catalog(options[:catalog])
|
28
|
-
@log_level =
|
29
|
+
@log_level = 'notice'
|
29
30
|
@out_buffer = options[:out_buffer] || $stdout
|
30
31
|
@html_mode = options[:html_mode] || false
|
31
32
|
@source_file = options[:source_file] || nil
|
@@ -33,13 +34,13 @@ module PuppetDebugger
|
|
33
34
|
@in_buffer = options[:in_buffer] || $stdin
|
34
35
|
Readline.input = @in_buffer
|
35
36
|
Readline.output = @out_buffer
|
36
|
-
Readline.completion_append_character =
|
37
|
-
Readline.basic_word_break_characters =
|
37
|
+
Readline.completion_append_character = ''
|
38
|
+
Readline.basic_word_break_characters = ' '
|
38
39
|
Readline.completion_proc = command_completion
|
39
40
|
AwesomePrint.defaults = {
|
40
41
|
html: @html_mode,
|
41
42
|
sort_keys: true,
|
42
|
-
indent: 2
|
43
|
+
indent: 2
|
43
44
|
}
|
44
45
|
end
|
45
46
|
|
@@ -50,11 +51,12 @@ module PuppetDebugger
|
|
50
51
|
proc do |input|
|
51
52
|
words = Readline.line_buffer.split(Readline.basic_word_break_characters)
|
52
53
|
next key_words.grep(/^#{Regexp.escape(input)}/) if words.empty?
|
54
|
+
|
53
55
|
first_word = words.shift
|
54
56
|
plugins = PuppetDebugger::InputResponders::Commands.plugins.find_all do |p|
|
55
57
|
p::COMMAND_WORDS.find { |word| word.start_with?(first_word) }
|
56
58
|
end
|
57
|
-
if plugins.count == 1
|
59
|
+
if (plugins.count == 1) && /\A#{first_word}\s/.match(Readline.line_buffer)
|
58
60
|
plugins.first.command_completion(words)
|
59
61
|
else
|
60
62
|
key_words.grep(/^#{Regexp.escape(input)}/)
|
@@ -76,7 +78,8 @@ module PuppetDebugger
|
|
76
78
|
PuppetDebugger::InputResponders::Functions.instance.debugger = self
|
77
79
|
funcs = PuppetDebugger::InputResponders::Functions.instance.func_list
|
78
80
|
PuppetDebugger::InputResponders::Datatypes.instance.debugger = self
|
79
|
-
(scoped_vars + funcs + static_responder_list +
|
81
|
+
(scoped_vars + funcs + static_responder_list +
|
82
|
+
PuppetDebugger::InputResponders::Datatypes.instance.all_data_types).uniq.sort
|
80
83
|
end
|
81
84
|
|
82
85
|
# looks up the type in the catalog by using the type and title
|
@@ -116,87 +119,107 @@ module PuppetDebugger
|
|
116
119
|
# if the only output is a resource then return it
|
117
120
|
# otherwise it is multiple items or an actually array
|
118
121
|
return output.first if output.count == 1
|
122
|
+
|
119
123
|
return output
|
120
124
|
end
|
121
125
|
result
|
122
126
|
end
|
123
127
|
|
124
128
|
def responder_list
|
125
|
-
|
129
|
+
Pluginator.find(PuppetDebugger)
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [TTY::Pager] the pager object, disable if CI or testing is present
|
133
|
+
def pager
|
134
|
+
@pager ||= TTY::Pager.new(output: out_buffer, enabled: pager_enabled?)
|
135
|
+
end
|
136
|
+
|
137
|
+
def pager_enabled?
|
138
|
+
ENV['CI'].nil?
|
139
|
+
end
|
140
|
+
|
141
|
+
# @param output [String] - the content to output
|
142
|
+
# @summary outputs the output to the output buffer
|
143
|
+
# uses the pager if the screen height is less than the height of the
|
144
|
+
# output content
|
145
|
+
# Disabled if CI or testing is being done
|
146
|
+
def handle_output(output)
|
147
|
+
return if output.nil?
|
148
|
+
if pager_enabled? && output.lines.count >= TTY::Screen.height
|
149
|
+
output << "\n"
|
150
|
+
pager.page(output)
|
151
|
+
else
|
152
|
+
out_buffer.puts(output) unless output.empty?
|
153
|
+
end
|
126
154
|
end
|
127
155
|
|
128
156
|
# this method handles all input and expects a string of text.
|
129
|
-
#
|
157
|
+
# @param input [String] - the input content to parse or run
|
130
158
|
def handle_input(input)
|
131
159
|
raise ArgumentError unless input.instance_of?(String)
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
160
|
+
|
161
|
+
output =
|
162
|
+
begin
|
163
|
+
case input.strip
|
164
|
+
when PuppetDebugger::InputResponders::Commands.command_list_regex
|
165
|
+
args = input.split(' ')
|
166
|
+
command = args.shift
|
167
|
+
plugin = PuppetDebugger::InputResponders::Commands.plugin_from_command(command)
|
168
|
+
plugin.execute(args, self) || ''
|
169
|
+
when '_'
|
170
|
+
" => #{@last_item}"
|
171
|
+
else
|
172
|
+
result = puppet_eval(input)
|
173
|
+
@last_item = result
|
174
|
+
o = normalize_output(result)
|
175
|
+
o.nil? ? '' : o.ai
|
176
|
+
end
|
177
|
+
rescue PuppetDebugger::Exception::InvalidCommand => e
|
178
|
+
e.message.fatal
|
179
|
+
rescue LoadError => e
|
180
|
+
e.message.fatal
|
181
|
+
rescue Errno::ETIMEDOUT => e
|
182
|
+
e.message.fatal
|
183
|
+
rescue ArgumentError => e
|
184
|
+
e.message.fatal
|
185
|
+
rescue Puppet::ResourceError => e
|
186
|
+
e.message.fatal
|
187
|
+
rescue Puppet::Error => e
|
188
|
+
e.message.fatal
|
189
|
+
rescue Puppet::ParseErrorWithIssue => e
|
190
|
+
e.message.fatal
|
191
|
+
rescue PuppetDebugger::Exception::FatalError => e
|
192
|
+
handle_output(e.message.fatal)
|
193
|
+
exit 1 # this can sometimes causes tests to fail
|
194
|
+
rescue PuppetDebugger::Exception::Error => e
|
195
|
+
e.message.fatal
|
196
|
+
rescue ::RuntimeError => e
|
197
|
+
handle_output(e.message.fatal)
|
198
|
+
exit 1
|
148
199
|
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
output = e.message.fatal
|
153
|
-
rescue Errno::ETIMEDOUT => e
|
154
|
-
output = e.message.fatal
|
155
|
-
rescue ArgumentError => e
|
156
|
-
output = e.message.fatal
|
157
|
-
rescue Puppet::ResourceError => e
|
158
|
-
output = e.message.fatal
|
159
|
-
rescue Puppet::Error => e
|
160
|
-
output = e.message.fatal
|
161
|
-
rescue Puppet::ParseErrorWithIssue => e
|
162
|
-
output = e.message.fatal
|
163
|
-
rescue PuppetDebugger::Exception::FatalError => e
|
164
|
-
output = e.message.fatal
|
165
|
-
out_buffer.puts output
|
166
|
-
exit 1 # this can sometimes causes tests to fail
|
167
|
-
rescue PuppetDebugger::Exception::Error => e
|
168
|
-
output = e.message.fatal
|
169
|
-
rescue ::RuntimeError => e
|
170
|
-
output = e.message.fatal
|
171
|
-
out_buffer.puts output
|
172
|
-
exit 1
|
173
|
-
end
|
174
|
-
unless output.empty?
|
175
|
-
out_buffer.print " => "
|
176
|
-
out_buffer.puts output unless output.empty?
|
177
|
-
exec_hook :after_output, out_buffer, self, self
|
178
|
-
end
|
200
|
+
output = OUT_SYMBOL + output unless output.empty?
|
201
|
+
handle_output(output)
|
202
|
+
exec_hook :after_output, out_buffer, self, self
|
179
203
|
end
|
180
204
|
|
181
205
|
def self.print_repl_desc
|
182
|
-
|
183
|
-
Ruby Version: #{RUBY_VERSION}
|
184
|
-
Puppet Version: #{Puppet.version}
|
185
|
-
Puppet Debugger Version: #{PuppetDebugger::VERSION}
|
186
|
-
Created by: NWOps <corey@nwops.io>
|
187
|
-
Type "commands" for a list of debugger commands
|
188
|
-
or "help" to show the help screen.
|
206
|
+
<<~OUT
|
207
|
+
Ruby Version: #{RUBY_VERSION}
|
208
|
+
Puppet Version: #{Puppet.version}
|
209
|
+
Puppet Debugger Version: #{PuppetDebugger::VERSION}
|
210
|
+
Created by: NWOps <corey@nwops.io>
|
211
|
+
Type "commands" for a list of debugger commands
|
212
|
+
or "help" to show the help screen.
|
189
213
|
|
190
214
|
|
191
|
-
|
192
|
-
output
|
215
|
+
OUT
|
193
216
|
end
|
194
217
|
|
195
218
|
# tries to determine if the input is going to be a multiline input
|
196
219
|
# by reading the parser error message
|
197
220
|
# @return [Boolean] - return true if this is a multiline input, false otherwise
|
198
|
-
def multiline_input?(
|
199
|
-
case
|
221
|
+
def multiline_input?(data)
|
222
|
+
case data.message
|
200
223
|
when /Syntax error at end of/i
|
201
224
|
true
|
202
225
|
else
|
@@ -211,7 +234,7 @@ or "help" to show the help screen.
|
|
211
234
|
# input
|
212
235
|
def read_loop
|
213
236
|
line_number = 1
|
214
|
-
full_buffer =
|
237
|
+
full_buffer = ''
|
215
238
|
while buf = Readline.readline("#{line_number}:#{extra_prompt}>> ", true)
|
216
239
|
begin
|
217
240
|
full_buffer += buf
|
@@ -222,14 +245,14 @@ or "help" to show the help screen.
|
|
222
245
|
parser.parse_string(full_buffer)
|
223
246
|
rescue Puppet::ParseErrorWithIssue => e
|
224
247
|
if multiline_input?(e)
|
225
|
-
out_buffer.print
|
248
|
+
out_buffer.print ' '
|
226
249
|
full_buffer += "\n"
|
227
250
|
next
|
228
251
|
end
|
229
252
|
end
|
230
253
|
end
|
231
254
|
handle_input(full_buffer)
|
232
|
-
full_buffer =
|
255
|
+
full_buffer = ''
|
233
256
|
end
|
234
257
|
end
|
235
258
|
end
|
@@ -251,7 +274,7 @@ or "help" to show the help screen.
|
|
251
274
|
repl_obj.out_buffer.puts print_repl_desc unless options[:quiet]
|
252
275
|
repl_obj.handle_input(options[:content]) if options[:content]
|
253
276
|
# TODO: make the output optional so we can have different output destinations
|
254
|
-
repl_obj.handle_input(
|
277
|
+
repl_obj.handle_input('whereami') if options[:source_file] && options[:source_line]
|
255
278
|
repl_obj.handle_input("play #{options[:play]}") if options[:play]
|
256
279
|
repl_obj.read_loop unless options[:run_once]
|
257
280
|
end
|
@@ -262,11 +285,15 @@ or "help" to show the help screen.
|
|
262
285
|
# @param [Hash] puppet scope object
|
263
286
|
def self.start(options = { scope: nil })
|
264
287
|
opts = Trollop.options do
|
265
|
-
opt :play,
|
266
|
-
opt :run_once,
|
267
|
-
opt :node_name,
|
268
|
-
opt :catalog,
|
269
|
-
opt :quiet,
|
288
|
+
opt :play, 'Url or file to load from', required: false, type: String
|
289
|
+
opt :run_once, 'Evaluate and quit', required: false, default: false
|
290
|
+
opt :node_name, 'Remote Node to grab facts from', required: false, type: String
|
291
|
+
opt :catalog, 'Import a catalog file to inspect', required: false, type: String
|
292
|
+
opt :quiet, 'Do not display banner', required: false, default: false
|
293
|
+
end
|
294
|
+
if !STDIN.tty? && !STDIN.closed?
|
295
|
+
options[:run_once] = true
|
296
|
+
options[:quiet] = true
|
270
297
|
end
|
271
298
|
options = opts.merge(options)
|
272
299
|
options[:play] = options[:play].path if options[:play].respond_to?(:path)
|
@@ -274,14 +301,14 @@ or "help" to show the help screen.
|
|
274
301
|
repl_obj.out_buffer.puts print_repl_desc unless options[:quiet]
|
275
302
|
if options[:play]
|
276
303
|
repl_obj.handle_input("play #{options[:play]}")
|
277
|
-
elsif ARGF.filename
|
278
|
-
# when the user supplied a file name without using the args (stdin)
|
279
|
-
path = File.expand_path(ARGF.filename)
|
280
|
-
repl_obj.handle_input("play #{path}")
|
281
|
-
elsif (ARGF.filename == "-") && (!STDIN.tty? && !STDIN.closed?)
|
304
|
+
elsif (ARGF.filename == '-') && (!STDIN.tty? && !STDIN.closed?)
|
282
305
|
# when the user supplied a file content using stdin, aka. cat,pipe,echo or redirection
|
283
306
|
input = ARGF.read
|
284
307
|
repl_obj.handle_input(input)
|
308
|
+
elsif ARGF.filename != '-'
|
309
|
+
# when the user supplied a file name without using the args (stdin)
|
310
|
+
path = File.expand_path(ARGF.filename)
|
311
|
+
repl_obj.handle_input("play #{path}")
|
285
312
|
end
|
286
313
|
# helper code to make tests exit the loop
|
287
314
|
repl_obj.read_loop unless options[:run_once]
|