puppet-debugger 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitlab-ci.yml +30 -13
  4. data/.rubocop.yml +3 -1
  5. data/.rubocop_todo.yml +11 -2
  6. data/.ruby-version +1 -1
  7. data/CHANGELOG.md +9 -0
  8. data/DEVELOPMENT.md +6 -1
  9. data/Gemfile +14 -12
  10. data/Plugin_development.md +304 -0
  11. data/README.md +4 -7
  12. data/Rakefile +6 -5
  13. data/bin/pdb +1 -0
  14. data/lib/awesome_print/ext/awesome_puppet.rb +1 -0
  15. data/lib/plugins/puppet-debugger/input_responders/benchmark.rb +40 -0
  16. data/lib/plugins/puppet-debugger/input_responders/classes.rb +15 -0
  17. data/lib/plugins/puppet-debugger/input_responders/classification.rb +14 -0
  18. data/lib/plugins/puppet-debugger/input_responders/commands.rb +95 -0
  19. data/lib/plugins/puppet-debugger/input_responders/datatypes.rb +17 -0
  20. data/lib/plugins/puppet-debugger/input_responders/environment.rb +14 -0
  21. data/lib/plugins/puppet-debugger/input_responders/exit.rb +14 -0
  22. data/lib/plugins/puppet-debugger/input_responders/facterdb_filter.rb +16 -0
  23. data/lib/plugins/puppet-debugger/input_responders/facts.rb +15 -0
  24. data/lib/plugins/puppet-debugger/input_responders/functions.rb +15 -0
  25. data/lib/plugins/puppet-debugger/input_responders/help.rb +14 -0
  26. data/lib/plugins/puppet-debugger/input_responders/krt.rb +14 -0
  27. data/lib/{puppet-debugger/support → plugins/puppet-debugger/input_responders}/play.rb +37 -26
  28. data/lib/plugins/puppet-debugger/input_responders/reset.rb +21 -0
  29. data/lib/plugins/puppet-debugger/input_responders/resources.rb +22 -0
  30. data/lib/plugins/puppet-debugger/input_responders/set.rb +55 -0
  31. data/lib/plugins/puppet-debugger/input_responders/types.rb +35 -0
  32. data/lib/plugins/puppet-debugger/input_responders/vars.rb +18 -0
  33. data/lib/plugins/puppet-debugger/input_responders/whereami.rb +29 -0
  34. data/lib/puppet-debugger.rb +12 -1
  35. data/lib/puppet-debugger/cli.rb +38 -22
  36. data/lib/puppet-debugger/code/code_file.rb +16 -15
  37. data/lib/puppet-debugger/code/code_range.rb +1 -0
  38. data/lib/puppet-debugger/code/loc.rb +1 -0
  39. data/lib/puppet-debugger/debugger_code.rb +1 -0
  40. data/lib/puppet-debugger/hooks.rb +174 -0
  41. data/lib/puppet-debugger/input_responder_plugin.rb +45 -0
  42. data/lib/puppet-debugger/plugin_test_helper.rb +44 -0
  43. data/lib/puppet-debugger/support.rb +13 -9
  44. data/lib/puppet-debugger/support/compiler.rb +1 -0
  45. data/lib/puppet-debugger/support/environment.rb +2 -0
  46. data/lib/puppet-debugger/support/errors.rb +9 -0
  47. data/lib/puppet-debugger/support/facts.rb +2 -1
  48. data/lib/puppet-debugger/support/functions.rb +3 -1
  49. data/lib/puppet-debugger/support/loader.rb +2 -0
  50. data/lib/puppet-debugger/support/node.rb +1 -0
  51. data/lib/puppet-debugger/support/scope.rb +1 -0
  52. data/lib/puppet/application/debugger.rb +1 -0
  53. data/lib/version.rb +2 -1
  54. data/puppet-debugger.gemspec +20 -15
  55. data/run_container_test.sh +1 -1
  56. data/spec/environment_spec.rb +2 -1
  57. data/spec/facts_spec.rb +1 -0
  58. data/spec/hooks_spec.rb +341 -0
  59. data/spec/input_responder_plugin_spec.rb +45 -0
  60. data/spec/input_responders/help_spec.rb +17 -0
  61. data/spec/input_responders/krt_spec.rb +12 -0
  62. data/spec/input_responders/play_spec.rb +160 -0
  63. data/spec/pdb_spec.rb +1 -0
  64. data/spec/puppet/application/debugger_spec.rb +1 -2
  65. data/spec/puppet_debugger_spec.rb +49 -88
  66. data/spec/remote_node_spec.rb +3 -2
  67. data/spec/spec_helper.rb +7 -0
  68. data/spec/support_spec.rb +5 -116
  69. data/test_matrix.rb +2 -0
  70. metadata +65 -12
  71. data/Gemfile.lock +0 -95
  72. data/lib/puppet-debugger/support/input_responders.rb +0 -191
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44f5198a38560ebf262df1bb5d9fb27b4689f6d0
4
- data.tar.gz: 76718414d5e49a617b755e6157f29b2188ff52cf
3
+ metadata.gz: 6e41642281d06f230cba649f0ad0cca8845fc713
4
+ data.tar.gz: 5f51ef9afa5c431937be5fa750978b3bedcf1b70
5
5
  SHA512:
6
- metadata.gz: 84b776b0a55d4d9cc116d4bf5a9ef8d67ecde7a8b6ac357b9f9af5dd990c555f258de0ea87ba1c5a359733ff8ec6524eac4e60d0a66d4858e8dbb4a0299a2c1c
7
- data.tar.gz: d47bae21bef89a828e225bcb9095bb4bd1c7a40af174891ae4c17bd69eb487795deff60718ccac0aa9b1e1e7e48fa433b6ed140386e69418be2b29ce79aa00b0
6
+ metadata.gz: 991540c9bb5dbd2e8995695818f0c05ce139c2832cfccd793ad01b3c062d242fd70026b4d4b2d19773b0268d0bc6d8d6709241dbe8bf030dd0663215ec43f1bf
7
+ data.tar.gz: bd44969d0b5b2c934de7f4705ed6fa9828363d9c5e8a4a8bbcd672da351885552ab3e54d2b8197a26b56d6729fab21a97aa7eb536f4c6da0e07c73e1959ee6d5
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  # rcov generated
2
+ Gemfile.lock
2
3
  .bash_history
3
4
  .gems
4
5
  .gem
data/.gitlab-ci.yml CHANGED
@@ -31,7 +31,7 @@ rubocop_ruby:
31
31
  only:
32
32
  - branches
33
33
  tags:
34
- - ruby2.2
34
+ - ruby
35
35
  script:
36
36
  - bundle install
37
37
  - bundle exec rubocop -D
@@ -73,8 +73,13 @@ bump_and_tag:
73
73
  .ruby_23: &ruby23
74
74
  image: ruby:2.3
75
75
 
76
+ .ruby_24: &ruby24
77
+ image: ruby:2.4
78
+
76
79
  gem_production:
77
80
  image: ruby:2.1
81
+ tags:
82
+ - ruby
78
83
  before_script:
79
84
  - gem install dpl
80
85
  stage: deploy
@@ -85,72 +90,84 @@ gem_production:
85
90
 
86
91
  puppet_38_ruby193:
87
92
  variables:
88
- PUPPET_GEM_VERSION: "~> 3.8"
93
+ PUPPET_GEM_VERSION: "~> 3.8.0"
89
94
  <<: *puppet_job_def
90
95
  <<: *ruby193
91
96
 
92
97
  puppet_38_ruby20:
93
98
  variables:
94
- PUPPET_GEM_VERSION: "~> 3.8"
99
+ PUPPET_GEM_VERSION: "~> 3.8.0"
95
100
  <<: *puppet_job_def
96
101
  <<: *ruby20
97
102
 
98
103
  puppet_38_ruby21:
99
104
  variables:
100
- PUPPET_GEM_VERSION: "~> 3.8"
105
+ PUPPET_GEM_VERSION: "~> 3.8.0"
101
106
  <<: *puppet_job_def
102
107
  <<: *ruby21
103
108
 
104
109
  puppet_43_ruby20:
105
110
  variables:
106
- PUPPET_GEM_VERSION: "~> 4.3"
111
+ PUPPET_GEM_VERSION: "~> 4.3.0"
107
112
  <<: *puppet_job_def
108
113
  <<: *ruby20
109
114
 
110
115
  puppet_43_ruby21:
111
116
  variables:
112
- PUPPET_GEM_VERSION: "~> 4.3"
117
+ PUPPET_GEM_VERSION: "~> 4.3.0"
113
118
  <<: *puppet_job_def
114
119
  <<: *ruby21
115
120
 
116
121
  puppet_43_ruby22:
117
122
  variables:
118
- PUPPET_GEM_VERSION: "~> 4.3"
123
+ PUPPET_GEM_VERSION: "~> 4.3.0"
119
124
  <<: *puppet_job_def
120
125
  <<: *ruby22
121
126
 
122
127
  puppet_44_ruby21:
123
128
  variables:
124
- PUPPET_GEM_VERSION: "~> 4.4"
129
+ PUPPET_GEM_VERSION: "~> 4.4.0"
125
130
  <<: *puppet_job_def
126
131
  <<: *ruby21
127
132
 
128
133
  puppet_44_ruby22:
129
134
  variables:
130
- PUPPET_GEM_VERSION: "~> 4.4"
135
+ PUPPET_GEM_VERSION: "~> 4.4.0"
131
136
  <<: *puppet_job_def
132
137
  <<: *ruby22
133
138
 
134
139
  puppet_45_ruby21:
135
140
  variables:
136
- PUPPET_GEM_VERSION: "~> 4.5"
141
+ PUPPET_GEM_VERSION: "~> 4.5.0"
137
142
  <<: *puppet_job_def
138
143
  <<: *ruby21
139
144
 
140
145
  puppet_46_ruby22:
141
146
  variables:
142
- PUPPET_GEM_VERSION: "~> 4.6"
147
+ PUPPET_GEM_VERSION: "~> 4.6.0"
143
148
  <<: *puppet_job_def
144
149
  <<: *ruby22
145
150
 
146
151
  puppet_47_ruby22:
147
152
  variables:
148
- PUPPET_GEM_VERSION: "~> 4.7"
153
+ PUPPET_GEM_VERSION: "~> 4.7.0"
149
154
  <<: *puppet_job_def
150
155
  <<: *ruby22
151
156
 
152
157
  puppet_48_ruby22:
153
158
  variables:
154
- PUPPET_GEM_VERSION: "~> 4.8"
159
+ PUPPET_GEM_VERSION: "~> 4.8.0"
155
160
  <<: *puppet_job_def
156
161
  <<: *ruby22
162
+
163
+ puppet_49_ruby23:
164
+ variables:
165
+ PUPPET_GEM_VERSION: "~> 4.9.0"
166
+ <<: *puppet_job_def
167
+ <<: *ruby23
168
+
169
+ puppet_410_ruby24:
170
+ variables:
171
+ PUPPET_GEM_VERSION: "~> 4.10.0"
172
+ <<: *puppet_job_def
173
+ <<: *ruby24
data/.rubocop.yml CHANGED
@@ -15,6 +15,7 @@ AllCops:
15
15
  - lib/version.rb
16
16
  - lib/puppet-debugger.rb
17
17
  - bin
18
+
18
19
  # Offense count: 7
19
20
  # Configuration parameters: AllowSafeAssignment.
20
21
  Lint/AssignmentInCondition:
@@ -30,7 +31,8 @@ Lint/Debugger:
30
31
  Exclude:
31
32
  - spec/**/*.rb
32
33
 
33
-
34
+ Style/NumericPredicate:
35
+ Enabled: false
34
36
  # Offense count: 1
35
37
  # Cop supports --auto-correct.
36
38
  # Configuration parameters: AlignWith, SupportedStyles, AutoCorrect.
data/.rubocop_todo.yml CHANGED
@@ -63,10 +63,18 @@ Lint/UselessAssignment:
63
63
  Metrics/AbcSize:
64
64
  Max: 150
65
65
 
66
+ Style/IndentHeredoc:
67
+ Enabled: false
68
+
69
+ Style/FileName:
70
+ Exclude:
71
+ - Rakefile
72
+ - Gemfile
73
+ - puppet-debugger.gemspec
66
74
  # Offense count: 3
67
75
  # Configuration parameters: CountComments.
68
76
  Metrics/BlockLength:
69
- Max: 442
77
+ Max: 518
70
78
 
71
79
  # Offense count: 3
72
80
  Metrics/BlockNesting:
@@ -89,7 +97,7 @@ Metrics/MethodLength:
89
97
  # Offense count: 2
90
98
  # Configuration parameters: CountComments.
91
99
  Metrics/ModuleLength:
92
- Max: 115
100
+ Max: 168
93
101
 
94
102
  # Offense count: 10
95
103
  Metrics/PerceivedComplexity:
@@ -154,6 +162,7 @@ Style/GuardClause:
154
162
  - 'lib/puppet-debugger/support/input_responders.rb'
155
163
  - 'lib/puppet-debugger/support/play.rb'
156
164
  - 'lib/trollop.rb'
165
+ - puppet-debugger.gemspec
157
166
 
158
167
  # Offense count: 2
159
168
  Style/IdenticalConditionalBranches:
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.3.3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## Unreleased
2
+
3
+ ## 0.7.0
4
+ * Adds new commands command
5
+ * Adds new help command
6
+ * Adds plugin framework
7
+ * Adds hooks framework
8
+ * Moves all commands to plugins
9
+ * Adds pluginator gem
1
10
  ## 0.6.1
2
11
  * Adds benchmark feature
3
12
  ## 0.6.0
data/DEVELOPMENT.md CHANGED
@@ -5,4 +5,9 @@ The puppet command will then load the face so you can use with `puppet debugger`
5
5
 
6
6
  `export RUBYLIB=lib/`
7
7
 
8
- `puppet debugger`
8
+ `puppet debugger`
9
+
10
+
11
+ ## Plugin Development
12
+ * [Plugin Development Guide](Plugin_development.md)
13
+
data/Gemfile CHANGED
@@ -1,21 +1,23 @@
1
- source "http://rubygems.org"
2
- gem 'puppet', ENV['PUPPET_GEM_VERSION'] || "~> 4.9.0"
3
- gem 'facterdb', ">= 0.3.8"
4
- gem 'awesome_print', "~> 1.6"
5
-
6
- group :test do
1
+ # frozen_string_literal: true
2
+ source 'http://rubygems.org'
3
+ gem 'awesome_print', '~> 1.7'
4
+ gem 'facterdb', '~> 0.3.8'
5
+ gem 'puppet', ENV['PUPPET_GEM_VERSION'] || '~> 4.10.1'
6
+ gem 'pluginator', '~> 1.4.1'
7
+ group :test, :development do
7
8
  # ruby versions prior to 2.0 cannot install json_pure 2.0.2+
9
+ gem 'bundler'
10
+ gem 'CFPropertyList'
8
11
  gem 'json_pure', '<= 2.0.1'
9
- gem "rdoc", "~> 3.12"
10
- gem "rspec"
11
- gem "bundler"
12
- gem "simplecov", ">= 0"
12
+ gem 'pry'
13
+ gem 'puppet-debugger', path: './'
13
14
  gem 'rake'
15
+ gem 'rdoc', '~> 3.12'
14
16
  gem 'release_me'
15
- gem 'pry'
17
+ gem 'rspec', '~> 3.6'
18
+ gem 'simplecov', '>= 0'
16
19
  end
17
20
 
18
21
  group :validate do
19
22
  gem 'rubocop'
20
23
  end
21
-
@@ -0,0 +1,304 @@
1
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
2
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
3
+ **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
4
+
5
+ - [Plugin Development Guide](#plugin-development-guide)
6
+ - [Creating a new Plugin](#creating-a-new-plugin)
7
+ - [Creating a plugin as a gem](#creating-a-plugin-as-a-gem)
8
+ - [Testing your gem plugin code](#testing-your-gem-plugin-code)
9
+ - [Creating a plugin to be merged into core](#creating-a-plugin-to-be-merged-into-core)
10
+ - [New Plugin Instructions](#new-plugin-instructions)
11
+ - [Required Directory layout](#required-directory-layout)
12
+ - [Run Method](#run-method)
13
+ - [Required Constants](#required-constants)
14
+ - [Command words](#command-words)
15
+ - [Summary](#summary)
16
+ - [Command groups](#command-groups)
17
+ - [Plugin API](#plugin-api)
18
+ - [Debugger Hooks](#debugger-hooks)
19
+ - [Hook Events](#hook-events)
20
+ - [Calling other plugins](#calling-other-plugins)
21
+ - [Indirectly](#indirectly)
22
+ - [Directly](#directly)
23
+ - [Testing your plugin code](#testing-your-plugin-code)
24
+ - [Examples](#examples)
25
+
26
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
27
+
28
+ # Plugin Development Guide
29
+ The puppet debugger now features a plugin system. This was added to support future expansion
30
+ via third party developers.
31
+
32
+ At this time there is only a single type of plugin called InputResponder, but in the future there will be additional types of plugins.
33
+
34
+ ## Creating a new Plugin
35
+ There are two ways to package a plugin.
36
+
37
+ 1. create a core plugin to be merged into the puppet-debugger codebase
38
+ 2. create a external plugin packaged as a gem and distributed via gem server such as rubygems.org
39
+
40
+ If you think your plugin should be in the core please create a PR and ensure you have unit test coverage for your plugin.
41
+
42
+ ## Creating a plugin as a gem
43
+ For reference you can use the following doc [How to create a gem](http://bundler.io/v1.15/guides/creating_gem.html)
44
+
45
+ 1. Create the gem via `bundle gem <plugin_name>`
46
+
47
+ ```
48
+ bundle gem --test=rspec fancy_plugin
49
+ cd fancy_plugin
50
+ mkdir -p lib/plugins/puppet-debugger/input_responders
51
+
52
+ ```
53
+
54
+ 2. Add the following to your Gemfile
55
+ ```ruby
56
+ group :dev, :test do
57
+ gem 'puppet-debugger'
58
+ gem 'pry'
59
+ gem 'CFPropertyList'
60
+ gem 'rake'
61
+ gem 'rspec', '>= 3.6'
62
+ # loads itself so you don't have to update RUBYLIB path
63
+ gem 'your_plugin', path: './'
64
+ end
65
+ ```
66
+
67
+ 3. bundle install
68
+ 2. Follow the [New Plugin Instructions](#new-plugin-instructions)
69
+ 3. Version the gem
70
+ 4. Package and push the gem to rubygems.
71
+ 5. Tell others about it.
72
+
73
+ ### Testing your gem plugin code
74
+ In order to test your plugin gem with the puppet-debugger you will need to add your gem's lib path to the RUBYLIB environment variable.
75
+
76
+ `RUBYLIB=~/path_to_gem/lib:$RUBYLIB puppet debugger`
77
+
78
+ Once this is set, puppet-debugger will discover your gem automatically and you should see it in the commands list.
79
+
80
+ Note: if you add the your plugin to the Gemfile as shown above in step 2 there is no need to set the RUBYLIB variable.
81
+
82
+ ## Creating a plugin to be merged into core
83
+ 1. Fork the puppet-debugger repo
84
+ 1. Follow the [New Plugin Instructions](#new-plugin-instructions)
85
+ 2. Submit a PR
86
+
87
+
88
+ ## New Plugin Instructions
89
+ 1. Create a file with the name of your plugin lib/plugins/puppet-debugger/input_responders/fancy_plugin.rb
90
+ 2. Add the following content to the plugin.
91
+
92
+ ```
93
+ require 'puppet-debugger/input_responder_plugin'
94
+ module PuppetDebugger
95
+ module InputResponders
96
+ class Fancy < InputResponderPlugin
97
+ COMMAND_WORDS = %w(fancy)
98
+ SUMMARY = 'This is a fancy plugin'
99
+ COMMAND_GROUP = :tools
100
+
101
+ def run(args = [])
102
+ 'hello from a fancy plugin'
103
+ end
104
+ end
105
+ end
106
+ end
107
+ ```
108
+
109
+ 4. ensure the class name is the same as the file name which follows ruby best practices
110
+ 5. Add words to the COMMAND_WORDS constant which will be used to run your plugin from the debugger.
111
+ 6. Add a short summary that describes your plugin's functionality
112
+ 7. Add a group to which your plugin should belong to. This appears in the `commands` plugin output.
113
+ 8. You must implement the [Run Method](#run-method). This method is called when your plugin's command word is entered.
114
+ 9. Write unit tests to validate your code works.
115
+
116
+ You can review the [Required Constants](#required-constants) docs for more info.
117
+
118
+ ## Required Directory layout
119
+ In order for you plugin to be discovered you must create this exact directly layout. Your plugin file must be in
120
+ the following directory `lib/plugins/puppet-debugger/input_responders/`
121
+
122
+ If you are packaging as a gem you must still provide this directory layout in addition to whatever other supporting files
123
+ are also in your gem.
124
+
125
+ ## Run Method
126
+
127
+ Your plugin must override the run method. When your plugin is executed, an array is passed as the args variable.
128
+ This variable contains all the arguments that can be supplied to your plugin. It is not required that you utilize
129
+ the `args` variable as some plugins run without arguments but it must be the only argument.
130
+
131
+ For example: `fancy hello there sir` would be passed as ['hello', 'there', 'sir'] to your plugin's run method.
132
+
133
+
134
+ ```ruby
135
+ def run(args = [])
136
+ greeting = args.first
137
+ "#{greeting} from a fancy plugin"
138
+ end
139
+
140
+ ```
141
+
142
+ ## Required Constants
143
+
144
+ ### Command words
145
+ These are the words the user will enter to interact with your plugin. You can provide
146
+ multiple words but only the first word will show up in the commands help screen.
147
+
148
+ Example:
149
+
150
+ ```
151
+ 2:>> classes
152
+ [
153
+ [0] "settings",
154
+ [1] "__node_regexp__foo"
155
+ ]
156
+ 2:>>
157
+ ```
158
+
159
+ Ensure you set the following in your plugin class
160
+ `COMMAND_WORDS = %w(fancy werd)`
161
+
162
+ ### Summary
163
+ Set the Summary Constant to tell users what your plugin does. This will show up in the commands help
164
+ screen.
165
+
166
+ ```bash
167
+ Tools
168
+ fancy This is a fancy plugin that does nothing
169
+ ```
170
+
171
+ `SUMMARY = 'This is a fancy plugin that does nothing'`
172
+
173
+
174
+ ### Command groups
175
+ The group name appears on the commands help screen and categories tools
176
+ based on the value of the command_group constant ie. `COMMAND_GROUP = :tools`
177
+
178
+ Below is a list of groups you can use to categorize your plugin. Groups are created dynamically by simply supplying
179
+ a new group name.
180
+
181
+ * `:help`
182
+ * `:tools`
183
+ * `:scope`
184
+ * `:node`
185
+ * `:environment`
186
+ * `:editing`
187
+ * `:context`
188
+
189
+ ## Plugin API
190
+ Every plugin has access to debugger's central objects. You may need to use these objects to implement your plugin.
191
+
192
+ Objects exposed that you might want access to:
193
+
194
+ * debugger (direct use is not recommended)
195
+ * scope (The puppet scope object)
196
+ * node (The puppet node object)
197
+ * environment (The puppet environment object)
198
+ * facts (The puppet facts hash)
199
+ * compiler (The puppet compiler object)
200
+ * catalog (The puppet catalog)
201
+ * function_map (Current map of functions)
202
+
203
+ While you do have access to the `debugger` object itself and everything inside this object. I would recommend not using the debugger
204
+ object directly since the debugger code base is changing rapidly. Usage can result in a broken plugin. If you are using
205
+ the debugger object directly please open an issue so we can create a interface for your use case to provide future compatibility.
206
+
207
+ ## Debugger Hooks
208
+ In addition the plugin API you can run code during certain events in the debugger lifecycle. This allows you to run your plugin code
209
+ only when certain actions occur. Please remember that your hook's code will be run multiple times during the debugger's session.
210
+
211
+ If your hook code takes a while to run, please ensure it runs fast or throw the code into a separate thread if applicable.
212
+
213
+ ### Hook Events
214
+ Below is a list of the current events that you can hook into.
215
+
216
+ * after_output (After the debugger has returned control back to the console)
217
+ * before_eval (Occurs before puppet evaluates the code)
218
+ * after_eval (Occurs after puppet evaluates the code and before the debugger sends the output to the console)
219
+
220
+ To hook into a debugger event you just add a hook via the `add_hook` method with the name of the event you wish to hook into.
221
+
222
+ An example of this pattern is below. In this example, when `graph` is entered by the user, the plugin toggles the execution
223
+ of creating a graph after the output is sent to the console. The toggle either adds or deletes the hook. Since creating the graph
224
+ can take a while we also create a thread so we don't hold the console hostage. A new graph is created each time a puppet evaluation occurs.
225
+
226
+ ```ruby
227
+ def run(args = [])
228
+ toggle_status
229
+ end
230
+
231
+ def toggle_status
232
+ status = !status
233
+ if status
234
+ add_hook(:after_eval, :create_graph) do |code, debugger|
235
+ # ensure we only start a single thread, otherwise they could stack up
236
+ # and try to write to the same file.
237
+ Thread.kill(@graph_thread) if @graph_thread
238
+ @graph_thread = Thread.new { create_html(create_graph_content) }
239
+ end
240
+ out = "Graph mode enabled at #{get_url}"
241
+ else
242
+ delete_hook(:after_output, :create_graph_content)
243
+ out = "Graph mode disabled"
244
+ end
245
+ out
246
+ end
247
+ ```
248
+
249
+ ## Calling other plugins
250
+ There are two ways to call other plugins.
251
+
252
+ ### Indirectly
253
+ You can call another plugin via the handle_input method ie. `debugger.handle_input('help')`. Just use the plugin command word
254
+ and any arguments that it takes to call the plugin.
255
+
256
+ This makes the debugger handle the loading of the plugin and returns formatted output which is most of the time what you want.
257
+ This does not send any output to the console so it is up to you to decide what to do next.
258
+
259
+ ### Directly
260
+ Should you want to call the plugin directly you can bypass the `handle_input` method and use the `plugin_from_command`
261
+ to return the plugin instance.
262
+
263
+ ```
264
+ # get a plugin instance
265
+ play_plugin = PuppetDebugger::InputResponders::Commands.plugin_from_command('play')
266
+
267
+ # execute the plugin
268
+ args = ['https://gists.github.com/sdalfsdfadsfds.txt']
269
+ # pass an instance of the debugger (always do this)
270
+ output = plugin.execute(args, debugger)
271
+
272
+ ```
273
+
274
+ If the command used to find the plugin is incorrect a `PuppetDebugger::Exception::InvalidCommand` error will be raised.
275
+
276
+ ## Testing your plugin code
277
+ 1. Create a new rspec test file as `spec/input_responders/plugin_name_spec.rb`
278
+
279
+ At a minimum you will need the following test code. By including the shared examples `plugin_tests' you will automatially
280
+ inherit some basic tests for your plugin. However, you will need to further test your code by creating additional
281
+ tests.
282
+
283
+ Replace `:plugin_name ` with the name of your plugin command word.
284
+
285
+ ```ruby
286
+ require 'spec_helper'
287
+ require 'puppet-debugger'
288
+ require 'puppet-debugger/plugin_test_helper'
289
+
290
+ describe :plugin_name do
291
+ include_examples "plugin_tests"
292
+ let(:args) { [] }
293
+
294
+ # you must test your run implementation similar to this, if you have args please set them in the args let blocks
295
+ it 'works' do
296
+ expect(plugin.run(args)).to eq('????')
297
+ end
298
+ end
299
+
300
+ ```
301
+
302
+ ## Examples
303
+ There are plenty of examples of plugins that are in the core code base. See lib/plugins/puppet-debugger/input_responders
304
+ for examples.