hammer_cli 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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
+