hammer_cli 0.0.9 → 0.0.10

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  3. data/doc/creating_apipie_commands.md +296 -0
  4. data/doc/creating_commands.md +547 -0
  5. data/doc/developer_docs.md +5 -926
  6. data/doc/development_tips.md +30 -0
  7. data/doc/writing_a_plugin.md +90 -0
  8. data/lib/hammer_cli/abstract.rb +31 -11
  9. data/lib/hammer_cli/apipie/resource.rb +14 -6
  10. data/lib/hammer_cli/apipie/write_command.rb +14 -5
  11. data/lib/hammer_cli/exception_handler.rb +7 -4
  12. data/lib/hammer_cli/options/normalizers.rb +27 -0
  13. data/lib/hammer_cli/output/adapter/abstract.rb +8 -8
  14. data/lib/hammer_cli/output/adapter/csv.rb +37 -4
  15. data/lib/hammer_cli/output/adapter/silent.rb +2 -2
  16. data/lib/hammer_cli/output/dsl.rb +3 -1
  17. data/lib/hammer_cli/output/output.rb +24 -19
  18. data/lib/hammer_cli/utils.rb +18 -0
  19. data/lib/hammer_cli/version.rb +1 -1
  20. data/lib/hammer_cli.rb +1 -0
  21. data/test/unit/abstract_test.rb +296 -0
  22. data/test/unit/apipie/command_test.rb +270 -0
  23. data/test/unit/apipie/fake_api.rb +101 -0
  24. data/test/unit/apipie/read_command_test.rb +34 -0
  25. data/test/unit/apipie/write_command_test.rb +38 -0
  26. data/test/unit/exception_handler_test.rb +45 -0
  27. data/test/unit/main_test.rb +47 -0
  28. data/test/unit/options/normalizers_test.rb +148 -0
  29. data/test/unit/options/option_definition_test.rb +43 -0
  30. data/test/unit/output/adapter/abstract_test.rb +96 -0
  31. data/test/unit/output/adapter/base_test.rb +27 -0
  32. data/test/unit/output/adapter/csv_test.rb +75 -0
  33. data/test/unit/output/adapter/table_test.rb +58 -0
  34. data/test/unit/output/definition_test.rb +27 -0
  35. data/test/unit/output/dsl_test.rb +119 -0
  36. data/test/unit/output/fields_test.rb +97 -0
  37. data/test/unit/output/formatters_test.rb +83 -0
  38. data/test/unit/output/output_test.rb +104 -0
  39. data/test/unit/settings_test.rb +106 -0
  40. data/test/unit/test_helper.rb +20 -0
  41. data/test/unit/utils_test.rb +35 -0
  42. data/test/unit/validator_test.rb +142 -0
  43. metadata +112 -35
  44. data/LICENSE +0 -5
  45. data/hammer_cli_complete +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f94cb081ad874612f32639ed07cdf5626fb69ba4
4
- data.tar.gz: 479cf176ac7bb522702489eb0205286ea0a98bf4
3
+ metadata.gz: 8f3bb9d5531d8e5c2686fa69e7715c4f746c677b
4
+ data.tar.gz: 9af8fd7a349392f0c00e69df2183fe0015232639
5
5
  SHA512:
6
- metadata.gz: 5a52be94f2ad2519e8eff5737b4f1fafbefb247db4fc49a6be931f0129f4a12fae8641e086ab4f0b9cca8bef691db8a5a6035c43e94afb7cb1c6ef0da7504403
7
- data.tar.gz: b97b952d02e88eb7541ea041d61b32cfe5374200a1d59ba6d24a38f8f3e58289b598606a075863ba58501f038c61547ce0b669e42befa81ea1b074d914c2ceec
6
+ metadata.gz: 220f699b4bdd24f5ad223a9b9d310361de3da6ebf5fa222425f1efcade8fc81d7d66392794bb6f5cac5f5311f20f646187a819b4f63955cde1a44ea96300b36d
7
+ data.tar.gz: 7bfee673681c83321ce82f73981f7c5f90be6d6e4ed78fbd6fae73ebc98cbbe319d37e3c084f2c742d84b2e395d3c434e296d442fb980b94b938b1ba45b9ea9b
data/README.md CHANGED
@@ -2,7 +2,7 @@ Hammer - the CLI tool (not only) for Foreman
2
2
  ============================================
3
3
 
4
4
 
5
- Hammer is a generic [clamp-based](https://github.com/mdub/clamp) CLI framework.
5
+ Hammer is a generic [clamp-based](https://github.com/mdub/clamp) CLI framework.
6
6
  Hammer-cli provides just the core functionality. The core is extensible using plugins that contain application-specific commands.
7
7
 
8
8
  This architecture allows for easy customization according to your application. Nearly any Ruby script can be turned into a Hammer command, so the possibilities are endless.
@@ -244,7 +244,7 @@ Use the hammer
244
244
  Confirm your setup by running ```$ hammer -h``` and check that the desired commands are listed.
245
245
 
246
246
  ```
247
- $ hammer -h
247
+ $ hammer -h
248
248
  Usage:
249
249
  hammer [OPTIONS] SUBCOMMAND [ARG] ...
250
250
 
@@ -332,9 +332,9 @@ Then after starting a new shell the completion should work.
332
332
 
333
333
  Further reading
334
334
  ---------------
335
- If you're interested in hammer and want to develop some plugins for Foreman
336
- or use it as a base for your own cli, read
337
- [the developer docs](doc/developer_docs.md#hammer-developer-docs).
335
+ If you're interested in hammer and want to develop some plugins for Foreman
336
+ or use it as a base for your own cli, read
337
+ [the developer docs](doc/developer_docs.md#hammer-development-docs).
338
338
 
339
339
  License
340
340
  -------
@@ -0,0 +1,296 @@
1
+ Creating commands for RESTful API with ApiPie
2
+ ---------------------------------------------
3
+
4
+ CLIs binded to a rest api do simillar things for most of the resources. Typically it's
5
+ CRUD actions that appear for nearly every resource. Actions differ with parameters
6
+ accross resources but the operations remain the same.
7
+
8
+ Hammer is optimised for usage with [ApiPie](https://github.com/Pajk/apipie-rails)
9
+ and generated api bindings and tries to reduce the effort neccessary for a command creation.
10
+
11
+
12
+ ### ApiPie and bindings
13
+
14
+ [ApiPie](https://github.com/Pajk/apipie-rails) is a documentation library for RESTful APIs.
15
+ Unlike traditional tools ApiPie uses DSL for api description. This brings many advantages. See its
16
+ documentation for details.
17
+
18
+ Foreman comes with [ruby bindings](https://github.com/theforeman/foreman_api) automatically generated
19
+ from the information provided by ApiPie. Every resource (eg. Architecture, User) has it's own
20
+ class with methods for each available action (eg. create, show, index, destroy).
21
+ Apart from that it contains also full api documentation with parameters for the actions.
22
+ This enables to reuse the documentation on client side for automatic option definition
23
+ and reduce the amount of custom code per CLI action.
24
+
25
+
26
+ ### ApiPie commands in Hammer
27
+
28
+ Hammer identifies two basic types of ApiPie commands:
29
+
30
+ - __ReadCommand__
31
+ - should be used for actions that print records
32
+ - retrieves the data and prints them in given format (uses output definition)
33
+ - typical actions in rails terminology: _index, show_
34
+
35
+ - __WriteCommand__
36
+ - should used for actions that modify records
37
+ - sends modifying request and prints the result
38
+ - typical actions in rails terminology: _create, update, destroy_
39
+
40
+ Both command classes are single resource related and expect the resource and an action to be defined.
41
+ There's a simple DSL for that:
42
+
43
+ ```ruby
44
+ class ListCommand < HammerCLI::Apipie::ReadCommand
45
+ # define resource and the action together
46
+ resource ForemanApi::Resources::Architecture, :index
47
+ end
48
+
49
+ # or
50
+
51
+ class ListCommand2 < HammerCLI::Apipie::ReadCommand
52
+ # define them separately
53
+ resource ForemanApi::Resources::Architecture
54
+ action :index
55
+ end
56
+ ```
57
+
58
+ #### Options definition
59
+
60
+ When the resource-action pair is defined we can take the advantage of automatic option definition.
61
+ There's a class method `apipie_options` for this purpose.
62
+
63
+ ```ruby
64
+ class ListCommand < HammerCLI::Apipie::ReadCommand
65
+ resource ForemanApi::Resources::Architecture, :index
66
+
67
+ apipie_options
68
+ end
69
+ ```
70
+
71
+ If we plug the command into an existing command tree and check the help we will see there
72
+ are four parameters defined from the ApiPie docs. Compare the result with
73
+ [online api documentation](http://www.theforeman.org/api/apidoc/architectures/index.html).
74
+ ```
75
+ $ hammer architecture list -h
76
+ Usage:
77
+ hammer architecture list [OPTIONS]
78
+
79
+ Options:
80
+ --search SEARCH filter results
81
+ --order ORDER sort results
82
+ --page PAGE paginate results
83
+ --per-page PER_PAGE number of entries per request
84
+ -h, --help print help
85
+ ```
86
+
87
+ It is possible to combine apipie options with custom ones. If the generated options
88
+ doesn't suit your needs for any reason, you can always skip and redefine them by hand.
89
+ See following example.
90
+ ```ruby
91
+ class ListCommand < HammerCLI::Apipie::ReadCommand
92
+ resource ForemanApi::Resources::Architecture, :index
93
+
94
+ apipie_options :without => [:search, :order]
95
+ option '--search', 'QUERY', "search query"
96
+ end
97
+ ```
98
+
99
+ ```
100
+ hammer architecture list -h
101
+ Usage:
102
+ hammer architecture list [OPTIONS]
103
+
104
+ Options:
105
+ --page PAGE paginate results
106
+ --per-page PER_PAGE number of entries per request
107
+ --search QUERY search query
108
+ -h, --help print help
109
+ ```
110
+ Note that the `--search` description has changed and `--order` disappeared.
111
+
112
+ Automatic options reflect:
113
+ - parameter names and descriptions
114
+ - required parameters
115
+ - parameter types - the only supported type is array, which is translated to option normalizer `List`
116
+
117
+ #### Write commands
118
+
119
+ Write commands are expected to print result of the api action. There are
120
+ two class methods for setting success and failure messages. Messages are
121
+ printed according to the http status code the api returned.
122
+
123
+ ```ruby
124
+ success_message "The user has been created"
125
+ failure_message "Could not create the user"
126
+ ```
127
+
128
+
129
+ #### Example 1: Create an architecture
130
+
131
+ ```ruby
132
+ class CreateCommand < HammerCLI::Apipie::WriteCommand
133
+ command_name "create"
134
+ resource ForemanApi::Resources::Architecture, :create
135
+
136
+ success_message "Architecture created"
137
+ failure_message "Could not create the architecture"
138
+
139
+ apipie_options
140
+ end
141
+ ```
142
+
143
+ ```
144
+ $ hammer architecture create -h
145
+ Usage:
146
+ hammer architecture create [OPTIONS]
147
+
148
+ Options:
149
+ --name NAME
150
+ --operatingsystem-ids OPERATINGSYSTEM_IDS Operatingsystem ID’s
151
+ Comma separated list of values.
152
+ -h, --help print help
153
+ ```
154
+
155
+ ```
156
+ $ hammer architecture create
157
+ ERROR: option '--name' is required
158
+
159
+ See: 'hammer architecture create --help'
160
+ ```
161
+
162
+ ```
163
+ $ hammer architecture create --name test --operatingsystem-ids=1,2
164
+ Architecture created
165
+ ```
166
+
167
+ ```
168
+ $ hammer architecture create --name test
169
+ Could not create the architecture:
170
+ Name has already been taken
171
+ ```
172
+
173
+
174
+ #### Example 2: Show an architecture
175
+
176
+ ```ruby
177
+ class InfoCommand < HammerCLI::Apipie::ReadCommand
178
+ command_name "info"
179
+ resource ForemanApi::Resources::Architecture, :show
180
+
181
+ # It's a good practice to reuse output definition from list commands
182
+ # and add more details. It helps avoiding duplicities.
183
+ output ListCommand.output_definition do
184
+ from "architecture" do
185
+ field :operatingsystem_ids, "OS ids", Fields::List
186
+ field :created_at, "Created at", Fields::Date
187
+ field :updated_at, "Updated at", Fields::Date
188
+ end
189
+ end
190
+
191
+ apipie_options
192
+ end
193
+ ```
194
+
195
+ ```
196
+ $ hammer architecture info -h
197
+ Usage:
198
+ hammer architecture info [OPTIONS]
199
+
200
+ Options:
201
+ --id ID
202
+ -h, --help print help
203
+ ```
204
+
205
+ ```
206
+ $ hammer architecture info --id 1
207
+ Id: 1
208
+ Name: x86_64
209
+ OS ids: 1, 3
210
+ Created at: 2013/06/08 18:53:56
211
+ Updated at: 2013/06/08 19:17:43
212
+ ```
213
+
214
+
215
+ #### Tips
216
+
217
+ When you define more command like we've shown above you find yourself repeating
218
+ `resource ...` in every one of them. As the commands are usually grouped by
219
+ the resource it is handy to extract the resource definition one level up to
220
+ the encapsulating command.
221
+
222
+ ```ruby
223
+ class Architecture < HammerCLI::Apipie::Command
224
+
225
+ resource ForemanApi::Resources::Architecture
226
+
227
+ class ListCommand < HammerCLI::Apipie::ReadCommand
228
+ action :index
229
+ # ...
230
+ end
231
+
232
+
233
+ class InfoCommand < HammerCLI::Apipie::ReadCommand
234
+ action :show
235
+ # ...
236
+ end
237
+
238
+ # ...
239
+ end
240
+ ```
241
+
242
+ ApiPie resources are being looked up in the encapsulating classes and modules
243
+ when the definition is missing in the command class. If they are not found even there
244
+ the resource of the parent command is used at runtime. This is useful for context-aware
245
+ shared commands.
246
+
247
+ The following example shows a common subcommand that can be attached to
248
+ any parent of which resource implements method `add_tag`. Please note that this example
249
+ is fictitious. There's no tags in Foreman's architectures and users.
250
+ ```ruby
251
+ module Tags
252
+ class AddTag < HammerCLI::Apipie::WriteCommand
253
+ option '--id', 'ID', 'ID of the resource'
254
+ option '--tag', 'TAG', 'Name of the tag to add'
255
+ action :add_tag
256
+ command_name 'add_tag'
257
+ end
258
+ end
259
+
260
+ class Architecture < HammerCLI::Apipie::Command
261
+ resource ForemanApi::Resources::Architecture
262
+ # ...
263
+ include Tags
264
+ autoload_subcommands
265
+ end
266
+
267
+ class User < HammerCLI::Apipie::Command
268
+ resource ForemanApi::Resources::User
269
+ # ...
270
+ include Tags
271
+ autoload_subcommands
272
+ end
273
+ ```
274
+
275
+ ```
276
+ $ hammer architecture add_tag -h
277
+ Usage:
278
+ hammer architecture add_tag [OPTIONS]
279
+
280
+ Options:
281
+ --id ID ID of the resource
282
+ --tag TAG Name of the tag to add
283
+ -h, --help print help
284
+ ```
285
+
286
+ ```
287
+ $ hammer user add_tag -h
288
+ Usage:
289
+ hammer user add_tag [OPTIONS]
290
+
291
+ Options:
292
+ --id ID ID of the resource
293
+ --tag TAG Name of the tag to add
294
+ -h, --help print help
295
+ ```
296
+