puppet-debugger 0.19.0 → 1.0.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 +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]
|