puppet-debugger 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.1
data/Gemfile CHANGED
@@ -11,6 +11,11 @@ group :test do
11
11
  gem "bundler"
12
12
  gem "simplecov", ">= 0"
13
13
  gem 'rake'
14
+ gem 'release_me'
15
+ end
16
+
17
+ group :validate do
18
+ gem 'rubocop'
14
19
  end
15
20
 
16
21
  group :development do
data/Gemfile.lock CHANGED
@@ -2,6 +2,7 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  CFPropertyList (2.2.8)
5
+ ast (2.3.0)
5
6
  awesome_print (1.7.0)
6
7
  coderay (1.1.1)
7
8
  diff-lcs (1.2.5)
@@ -17,6 +18,9 @@ GEM
17
18
  json (1.8.3)
18
19
  json_pure (1.8.3)
19
20
  method_source (0.8.2)
21
+ parser (2.3.2.0)
22
+ ast (~> 2.2)
23
+ powerpack (0.1.1)
20
24
  pry (0.10.4)
21
25
  coderay (~> 1.1.0)
22
26
  method_source (~> 0.8.1)
@@ -25,9 +29,11 @@ GEM
25
29
  facter (> 2.0, < 4)
26
30
  hiera (>= 2.0, < 4)
27
31
  json_pure (~> 1.8)
32
+ rainbow (2.1.0)
28
33
  rake (11.2.2)
29
34
  rdoc (3.12.2)
30
35
  json (~> 1.4)
36
+ release_me (0.1.1)
31
37
  rspec (3.5.0)
32
38
  rspec-core (~> 3.5.0)
33
39
  rspec-expectations (~> 3.5.0)
@@ -41,12 +47,20 @@ GEM
41
47
  diff-lcs (>= 1.2.0, < 2.0)
42
48
  rspec-support (~> 3.5.0)
43
49
  rspec-support (3.5.0)
50
+ rubocop (0.45.0)
51
+ parser (>= 2.3.1.1, < 3.0)
52
+ powerpack (~> 0.1)
53
+ rainbow (>= 1.99.1, < 3.0)
54
+ ruby-progressbar (~> 1.7)
55
+ unicode-display_width (~> 1.0, >= 1.0.1)
56
+ ruby-progressbar (1.8.1)
44
57
  simplecov (0.12.0)
45
58
  docile (~> 1.1.0)
46
59
  json (>= 1.8, < 3)
47
60
  simplecov-html (~> 0.10.0)
48
61
  simplecov-html (0.10.0)
49
62
  slop (3.6.0)
63
+ unicode-display_width (1.1.1)
50
64
 
51
65
  PLATFORMS
52
66
  ruby
@@ -57,10 +71,12 @@ DEPENDENCIES
57
71
  facterdb (~> 0.3)
58
72
  json_pure (<= 2.0.1)
59
73
  pry
60
- puppet (~> 4.3)
74
+ puppet (>= 3.8)
61
75
  rake
62
76
  rdoc (~> 3.12)
77
+ release_me
63
78
  rspec
79
+ rubocop
64
80
  simplecov
65
81
 
66
82
  BUNDLED WITH
data/bin/pdb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
  require_relative '../lib/puppet-debugger'
3
4
 
4
5
  PuppetDebugger::Cli.start
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module AwesomePrint
2
3
  module Puppet
3
4
  def self.included(base)
@@ -10,11 +11,11 @@ module AwesomePrint
10
11
  def cast_with_puppet_resource(object, type)
11
12
  cast = cast_without_puppet_resource(object, type)
12
13
  # check the object to see if it has an acestor (< ) of the specified type
13
- if (defined?(::Puppet::Type)) && (object.class < ::Puppet::Type)
14
+ if defined?(::Puppet::Type) && (object.class < ::Puppet::Type)
14
15
  cast = :puppet_type
15
- elsif (defined?(::Puppet::Pops::Types)) && (object.class < ::Puppet::Pops::Types)
16
+ elsif defined?(::Puppet::Pops::Types) && (object.class < ::Puppet::Pops::Types)
16
17
  cast = :puppet_type
17
- elsif (defined?(::Puppet::Parser::Resource)) && (object.class < ::Puppet::Parser::Resource)
18
+ elsif defined?(::Puppet::Parser::Resource) && (object.class < ::Puppet::Parser::Resource)
18
19
  cast = :puppet_resource
19
20
  elsif /Puppet::Pops::Types/.match(object.class.to_s)
20
21
  cast = :puppet_type
@@ -30,9 +31,9 @@ module AwesomePrint
30
31
  def awesome_puppet_type(object)
31
32
  return '' if object.nil?
32
33
  return object.to_s unless object.respond_to?(:name) && object.respond_to?(:title)
33
- h = object.to_hash.merge(:name => object.name, :title => object.title)
34
+ h = object.to_hash.merge(name: object.name, title: object.title)
34
35
  res_str = awesome_hash(h)
35
- "#{object.class} #{res_str.gsub(':', '')}"
36
+ "#{object.class} #{res_str.delete(':')}"
36
37
  end
37
38
  end
38
39
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'puppet/application'
2
3
  require 'optparse'
3
4
  require 'puppet/util/command_line'
@@ -5,38 +6,38 @@ require 'puppet/util/command_line'
5
6
  class Puppet::Application::Debugger < Puppet::Application
6
7
  attr_reader :use_facterdb, :use_stdin
7
8
 
8
- option("--execute EXECUTE","-e") do |arg|
9
+ option('--execute EXECUTE', '-e') do |arg|
9
10
  options[:code] = arg
10
11
  end
11
12
 
12
- option("--facterdb-filter FILTER") do |arg|
13
+ option('--facterdb-filter FILTER') do |arg|
13
14
  @use_facterdb = true unless options[:node_name]
14
15
  ENV['DEBUGGER_FACTERDB_FILTER'] = arg if arg
15
16
  end
16
17
 
17
- option("--test") do |_arg|
18
+ option('--test') do |_arg|
18
19
  options[:quiet] = true
19
20
  options[:run_once] = true
20
21
  @use_stdin = true
21
22
  end
22
23
 
23
- option("--no-facterdb") { |_arg| @use_facterdb = false }
24
+ option('--no-facterdb') { |_arg| @use_facterdb = false }
24
25
 
25
- option("--log-level LEVEL","-l") do |arg|
26
+ option('--log-level LEVEL', '-l') do |arg|
26
27
  Puppet::Util::Log.level = arg.to_sym
27
28
  end
28
29
 
29
- option("--quiet", "-q") { |_arg| options[:quiet] = true }
30
+ option('--quiet', '-q') { |_arg| options[:quiet] = true }
30
31
 
31
- option("--play URL", "-p") do |arg|
32
+ option('--play URL', '-p') do |arg|
32
33
  options[:play] = arg
33
34
  end
34
35
 
35
- option("--stdin", "-s") { |_arg| @use_stdin = true }
36
+ option('--stdin', '-s') { |_arg| @use_stdin = true }
36
37
 
37
- option("--run-once", '-r') { |_arg| options[:run_once] = true }
38
+ option('--run-once', '-r') { |_arg| options[:run_once] = true }
38
39
 
39
- option("--node-name CERTNAME", '-n') do |arg|
40
+ option('--node-name CERTNAME', '-n') do |arg|
40
41
  @use_facterdb = false
41
42
  options[:node_name] = arg
42
43
  end
@@ -173,7 +174,7 @@ Copyright (c) 2016 NWOps
173
174
 
174
175
  def app_defaults
175
176
  Puppet::Settings.app_defaults_for_run_mode(self.class.run_mode).merge(
176
- :name => name
177
+ name: name
177
178
  )
178
179
  end
179
180
 
@@ -208,26 +209,26 @@ Copyright (c) 2016 NWOps
208
209
  f.write(code_input)
209
210
  end
210
211
  options[:play] = file
211
- elsif command_line.args.length == 0 and use_stdin
212
+ elsif command_line.args.empty? && use_stdin
212
213
  code_input = STDIN.read
213
214
  file = Tempfile.new(['puppet_repl_input', '.pp'])
214
215
  File.open(file, 'w') do |f|
215
216
  f.write(code_input)
216
217
  end
217
218
  options[:play] = file
218
- elsif command_line.args.length > 0
219
+ elsif !command_line.args.empty?
219
220
  manifest = command_line.args.shift
220
221
  raise "Could not find file #{manifest}" unless Puppet::FileSystem.exist?(manifest)
221
- Puppet.warning("Only one file can be used per run. Skipping #{command_line.args.join(', ')}") if command_line.args.size > 0
222
+ Puppet.warning("Only one file can be used per run. Skipping #{command_line.args.join(', ')}") unless command_line.args.empty?
222
223
  options[:play] = file
223
224
  end
224
- if ! use_facterdb and options[:node_name].nil?
225
+ if !use_facterdb && options[:node_name].nil?
225
226
  debug_environment = create_environment(nil)
226
227
  Puppet.notice('Gathering node facts...')
227
228
  node = create_node(debug_environment)
228
229
  scope = create_scope(node)
229
230
  # start_debugger(scope)
230
- options.merge!({:scope => scope})
231
+ options[:scope] = scope
231
232
  end
232
233
  ::PuppetDebugger::Cli.start_without_stdin(options)
233
234
  end
@@ -235,7 +236,7 @@ Copyright (c) 2016 NWOps
235
236
  def create_environment(manifest)
236
237
  configured_environment = Puppet.lookup(:current_environment)
237
238
  manifest ?
238
- configured_environment.override_with(:manifest => manifest) :
239
+ configured_environment.override_with(manifest: manifest) :
239
240
  configured_environment
240
241
  end
241
242
 
@@ -250,7 +251,7 @@ Copyright (c) 2016 NWOps
250
251
  facts.name = Puppet[:node_name_value]
251
252
  end
252
253
 
253
- Puppet.override({:current_environment => environment}, "For puppet debugger") do
254
+ Puppet.override({ current_environment: environment }, 'For puppet debugger') do
254
255
  # Find our Node
255
256
  unless node = Puppet::Node.indirection.find(Puppet[:node_name_value])
256
257
  raise "Could not find node #{Puppet[:node_name_value]}"
@@ -275,10 +276,10 @@ Copyright (c) 2016 NWOps
275
276
 
276
277
  def start_debugger(scope, options = {})
277
278
  if $stdout.isatty
278
- options = options.merge({:scope => scope})
279
+ options = options.merge(scope: scope)
279
280
  # required in order to use convert puppet hash into ruby hash with symbols
280
- options = options.inject({}){|data,(k,v)| data[k.to_sym] = v; data}
281
- #options[:source_file], options[:source_line] = stacktrace.last
281
+ options = options.each_with_object({}) { |(k, v), data| data[k.to_sym] = v; data }
282
+ # options[:source_file], options[:source_line] = stacktrace.last
282
283
  ::PuppetRepl::Cli.start(options)
283
284
  else
284
285
  Puppet.info 'puppet debug: refusing to start the debugger without a tty'
@@ -292,15 +293,14 @@ Copyright (c) 2016 NWOps
292
293
  # for compatibility with older puppet versions
293
294
  # The basics behind this are to find the `.pp` file in the list of loaded code
294
295
  def stacktrace
295
- result = caller().reduce([]) do |memo, loc|
296
+ result = caller.each_with_object([]) do |loc, memo|
296
297
  if loc =~ /\A(.*\.pp)?:([0-9]+):in\s(.*)/
297
298
  # if the file is not found we set to code
298
299
  # and read from Puppet[:code]
299
300
  # $3 is reserved for the stacktrace type
300
- memo << [$1.nil? ? :code : $1, $2.to_i]
301
+ memo << [Regexp.last_match(1).nil? ? :code : Regexp.last_match(1), Regexp.last_match(2).to_i]
301
302
  end
302
303
  memo
303
304
  end.reverse
304
305
  end
305
-
306
306
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'puppet'
2
3
  require 'readline'
3
4
  require 'json'
@@ -9,23 +10,23 @@ module PuppetDebugger
9
10
 
10
11
  attr_accessor :settings, :log_level, :in_buffer, :out_buffer, :html_mode
11
12
 
12
- def initialize(options={})
13
+ def initialize(options = {})
13
14
  @log_level = 'notice'
14
15
  @out_buffer = options[:out_buffer] || $stdout
15
16
  @html_mode = options[:html_mode] || false
16
17
  @source_file = options[:source_file] || nil
17
18
  @source_line_num = options[:source_line] || nil
18
19
  @in_buffer = options[:in_buffer] || $stdin
19
- comp = Proc.new do |s|
20
+ comp = proc do |s|
20
21
  key_words.grep(/^#{Regexp.escape(s)}/)
21
22
  end
22
- Readline.completion_append_character = ""
23
- Readline.basic_word_break_characters = " "
23
+ Readline.completion_append_character = ''
24
+ Readline.basic_word_break_characters = ' '
24
25
  Readline.completion_proc = comp
25
26
  AwesomePrint.defaults = {
26
- :html => @html_mode,
27
- :sort_keys => true,
28
- :indent => 2
27
+ html: @html_mode,
28
+ sort_keys: true,
29
+ indent: 2
29
30
  }
30
31
  do_initialize
31
32
  end
@@ -36,16 +37,16 @@ module PuppetDebugger
36
37
  # list so its not explicitly clear what the keyword
37
38
  variables = scope.to_hash.keys
38
39
  # prepend a :: to topscope variables
39
- scoped_vars = variables.map { |k,v| scope.compiler.topscope.exist?(k) ? "$::#{k}" : "$#{k}" }
40
+ scoped_vars = variables.map { |k, _v| scope.compiler.topscope.exist?(k) ? "$::#{k}" : "$#{k}" }
40
41
  # append a () to functions so we know they are functions
41
- funcs = function_map.keys.map { |k| "#{k.split('::').last}()"}
42
+ funcs = function_map.keys.map { |k| "#{k.split('::').last}()" }
42
43
  (scoped_vars + funcs + static_responder_list).uniq.sort
43
44
  end
44
45
 
45
46
  # looks up the type in the catalog by using the type and title
46
47
  # and returns the resource in ral format
47
48
  def to_resource_declaration(type)
48
- if type.respond_to?(:type_name) and type.respond_to?(:title)
49
+ if type.respond_to?(:type_name) && type.respond_to?(:title)
49
50
  title = type.title
50
51
  type_name = type.type_name
51
52
  elsif type_result = /(\w+)\['?(\w+)'?\]/.match(type.to_s)
@@ -57,13 +58,11 @@ module PuppetDebugger
57
58
  return type
58
59
  end
59
60
  res = scope.catalog.resource(type_name, title)
60
- if res
61
- return res.to_ral
62
- end
61
+ return res.to_ral if res
63
62
  # don't return anything or returns nil if item is not in the catalog
64
63
  end
65
64
 
66
- # ruturns a formatted array
65
+ # returns a formatted array
67
66
  def expand_resource_type(types)
68
67
  output = [types].flatten.map do |t|
69
68
  if t.class.to_s =~ /Puppet::Pops::Types/
@@ -78,9 +77,7 @@ module PuppetDebugger
78
77
  def normalize_output(result)
79
78
  if result.instance_of?(Array)
80
79
  output = expand_resource_type(result)
81
- if output.count == 1
82
- return output.first
83
- end
80
+ return output.first if output.count == 1
84
81
  return output
85
82
  elsif result.class.to_s =~ /Puppet::Pops::Types/
86
83
  return to_resource_declaration(result)
@@ -91,56 +88,54 @@ module PuppetDebugger
91
88
  # this method handles all input and expects a string of text.
92
89
  #
93
90
  def handle_input(input)
94
- raise ArgumentError unless input.instance_of?(String)
95
- begin
96
- output = ''
97
- case input
98
- when /^play|^classification|^whereami|^facterdb_filter|^facts|^vars|^functions|^classes|^resources|^krt|^environment|^reset|^help/
99
- args = input.split(' ')
100
- command = args.shift.to_sym
101
- if self.respond_to?(command)
102
- output = self.send(command, args)
103
- end
104
- return out_buffer.puts output
105
- when /exit/
106
- exit 0
107
- when /^:set/
108
- output = handle_set(input)
109
- when '_'
110
- output = " => #{@last_item}"
111
- else
112
- result = puppet_eval(input)
113
- @last_item = result
114
- output = normalize_output(result)
115
- if output.nil?
116
- output = ""
117
- else
118
- output = output.ai
119
- end
120
- end
121
- rescue LoadError => e
122
- output = e.message.fatal
123
- rescue Errno::ETIMEDOUT => e
124
- output = e.message.fatal
125
- rescue ArgumentError => e
126
- output = e.message.fatal
127
- rescue Puppet::ResourceError => e
128
- output = e.message.fatal
129
- rescue Puppet::Error => e
130
- output = e.message.fatal
131
- rescue Puppet::ParseErrorWithIssue => e
132
- output = e.message.fatal
133
- rescue PuppetDebugger::Exception::FatalError => e
134
- output = e.message.fatal
135
- out_buffer.puts output
136
- exit 1 # this can sometimes causes tests to fail
137
- rescue PuppetDebugger::Exception::Error => e
138
- output = e.message.fatal
139
- end
140
- unless output.empty?
141
- out_buffer.print " => "
142
- out_buffer.puts output unless output.empty?
91
+ raise ArgumentError unless input.instance_of?(String)
92
+ begin
93
+ output = ''
94
+ case input
95
+ when /^play|^classification|^whereami|^facterdb_filter|^facts|^vars|^functions|^classes|^resources|^krt|^environment|^reset|^help/
96
+ args = input.split(' ')
97
+ command = args.shift.to_sym
98
+ output = send(command, args) if respond_to?(command)
99
+ return out_buffer.puts output
100
+ when /exit/
101
+ exit 0
102
+ when /^:set/
103
+ output = handle_set(input)
104
+ when '_'
105
+ output = " => #{@last_item}"
106
+ else
107
+ result = puppet_eval(input)
108
+ @last_item = result
109
+ output = normalize_output(result)
110
+ output = if output.nil?
111
+ ''
112
+ else
113
+ output.ai
114
+ end
143
115
  end
116
+ rescue LoadError => e
117
+ output = e.message.fatal
118
+ rescue Errno::ETIMEDOUT => e
119
+ output = e.message.fatal
120
+ rescue ArgumentError => e
121
+ output = e.message.fatal
122
+ rescue Puppet::ResourceError => e
123
+ output = e.message.fatal
124
+ rescue Puppet::Error => e
125
+ output = e.message.fatal
126
+ rescue Puppet::ParseErrorWithIssue => e
127
+ output = e.message.fatal
128
+ rescue PuppetDebugger::Exception::FatalError => e
129
+ output = e.message.fatal
130
+ out_buffer.puts output
131
+ exit 1 # this can sometimes causes tests to fail
132
+ rescue PuppetDebugger::Exception::Error => e
133
+ output = e.message.fatal
134
+ end
135
+ unless output.empty?
136
+ out_buffer.print ' => '
137
+ out_buffer.puts output unless output.empty?
138
+ end
144
139
  end
145
140
 
146
141
  def self.print_repl_desc
@@ -195,15 +190,17 @@ Type "exit", "functions", "vars", "krt", "whereami", "facts", "resources", "clas
195
190
  end
196
191
  end
197
192
 
198
- # used to start a repl without attempting to read from stdin
193
+ # used to start a debugger session without attempting to read from stdin
199
194
  # or
195
+ # this is primarily used by the debug::break() module function and the puppet debugger face
200
196
  # @param [Hash] must contain at least the puppet scope object
201
- def self.start_without_stdin(options={:scope => nil})
197
+ def self.start_without_stdin(options = { scope: nil })
202
198
  puts print_repl_desc unless options[:quiet]
203
199
  repl_obj = PuppetDebugger::Cli.new(options)
204
200
  repl_obj.remote_node_name = options[:node_name] if options[:node_name]
205
201
  repl_obj.initialize_from_scope(options[:scope])
206
- puts repl_obj.whereami if options[:source_file] and options[:source_line]
202
+ # TODO: make the output optional so we can have different output destinations
203
+ puts repl_obj.whereami if options[:source_file] && options[:source_line]
207
204
  repl_obj.play_back(options) if options[:play]
208
205
  repl_obj.read_loop unless options[:run_once]
209
206
  end
@@ -212,12 +209,12 @@ Type "exit", "functions", "vars", "krt", "whereami", "facts", "resources", "clas
212
209
  # if from stdin, the repl will process the input and exit
213
210
  # if from a file, the repl will process the file and continue to prompt
214
211
  # @param [Hash] puppet scope object
215
- def self.start(options={:scope => nil})
216
- opts = Trollop::options do
217
- opt :play, "Url or file to load from", :required => false, :type => String
218
- opt :run_once, "Evaluate and quit", :required => false, :default => false
219
- opt :node_name, "Remote Node to grab facts from", :required => false, :type => String
220
- opt :quiet, "Do not display banner", :required => false, :default => false
212
+ def self.start(options = { scope: nil })
213
+ opts = Trollop.options do
214
+ opt :play, 'Url or file to load from', required: false, type: String
215
+ opt :run_once, 'Evaluate and quit', required: false, default: false
216
+ opt :node_name, 'Remote Node to grab facts from', required: false, type: String
217
+ opt :quiet, 'Do not display banner', required: false, default: false
221
218
  end
222
219
  options = opts.merge(options)
223
220
  puts print_repl_desc unless options[:quiet]
@@ -227,18 +224,16 @@ Type "exit", "functions", "vars", "krt", "whereami", "facts", "resources", "clas
227
224
  if options[:play]
228
225
  repl_obj.play_back(opts)
229
226
  # when the user supplied a file name without using the args (stdin)
230
- elsif ARGF.filename != "-"
227
+ elsif ARGF.filename != '-'
231
228
  path = File.expand_path(ARGF.filename)
232
- repl_obj.play_back(:play => path)
229
+ repl_obj.play_back(play: path)
233
230
  # when the user supplied a file content using stdin, aka. cat,pipe,echo or redirection
234
- elsif ARGF.filename == "-" and (not STDIN.tty? and not STDIN.closed?)
231
+ elsif (ARGF.filename == '-') && (!STDIN.tty? && !STDIN.closed?)
235
232
  input = ARGF.read
236
233
  repl_obj.handle_input(input)
237
234
  end
238
235
  # helper code to make tests exit the loop
239
- unless options[:run_once]
240
- repl_obj.read_loop
241
- end
236
+ repl_obj.read_loop unless options[:run_once]
242
237
  end
243
238
  end
244
239
  end