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.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/doc/creating_apipie_commands.md +296 -0
- data/doc/creating_commands.md +547 -0
- data/doc/developer_docs.md +5 -926
- data/doc/development_tips.md +30 -0
- data/doc/writing_a_plugin.md +90 -0
- data/lib/hammer_cli/abstract.rb +31 -11
- data/lib/hammer_cli/apipie/resource.rb +14 -6
- data/lib/hammer_cli/apipie/write_command.rb +14 -5
- data/lib/hammer_cli/exception_handler.rb +7 -4
- data/lib/hammer_cli/options/normalizers.rb +27 -0
- data/lib/hammer_cli/output/adapter/abstract.rb +8 -8
- data/lib/hammer_cli/output/adapter/csv.rb +37 -4
- data/lib/hammer_cli/output/adapter/silent.rb +2 -2
- data/lib/hammer_cli/output/dsl.rb +3 -1
- data/lib/hammer_cli/output/output.rb +24 -19
- data/lib/hammer_cli/utils.rb +18 -0
- data/lib/hammer_cli/version.rb +1 -1
- data/lib/hammer_cli.rb +1 -0
- data/test/unit/abstract_test.rb +296 -0
- data/test/unit/apipie/command_test.rb +270 -0
- data/test/unit/apipie/fake_api.rb +101 -0
- data/test/unit/apipie/read_command_test.rb +34 -0
- data/test/unit/apipie/write_command_test.rb +38 -0
- data/test/unit/exception_handler_test.rb +45 -0
- data/test/unit/main_test.rb +47 -0
- data/test/unit/options/normalizers_test.rb +148 -0
- data/test/unit/options/option_definition_test.rb +43 -0
- data/test/unit/output/adapter/abstract_test.rb +96 -0
- data/test/unit/output/adapter/base_test.rb +27 -0
- data/test/unit/output/adapter/csv_test.rb +75 -0
- data/test/unit/output/adapter/table_test.rb +58 -0
- data/test/unit/output/definition_test.rb +27 -0
- data/test/unit/output/dsl_test.rb +119 -0
- data/test/unit/output/fields_test.rb +97 -0
- data/test/unit/output/formatters_test.rb +83 -0
- data/test/unit/output/output_test.rb +104 -0
- data/test/unit/settings_test.rb +106 -0
- data/test/unit/test_helper.rb +20 -0
- data/test/unit/utils_test.rb +35 -0
- data/test/unit/validator_test.rb +142 -0
- metadata +112 -35
- data/LICENSE +0 -5
- data/hammer_cli_complete +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f3bb9d5531d8e5c2686fa69e7715c4f746c677b
|
4
|
+
data.tar.gz: 9af8fd7a349392f0c00e69df2183fe0015232639
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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-
|
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
|
+
|