hammer_cli 0.15.1 → 0.16.0
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/doc/commands_modification.md +82 -0
- data/doc/creating_commands.md +78 -38
- data/doc/developer_docs.md +2 -0
- data/doc/help_modification.md +119 -0
- data/doc/i18n.md +2 -2
- data/doc/installation_rpm.md +3 -3
- data/doc/release_notes.md +9 -1
- data/lib/hammer_cli.rb +0 -1
- data/lib/hammer_cli/abstract.rb +44 -13
- data/lib/hammer_cli/exception_handler.rb +1 -1
- data/lib/hammer_cli/help/definition.rb +55 -0
- data/lib/hammer_cli/help/definition/abstract_item.rb +38 -0
- data/lib/hammer_cli/help/definition/list.rb +53 -0
- data/lib/hammer_cli/help/definition/section.rb +36 -0
- data/lib/hammer_cli/help/definition/text.rb +21 -0
- data/lib/hammer_cli/help/text_builder.rb +26 -49
- data/lib/hammer_cli/i18n.rb +0 -1
- data/lib/hammer_cli/options/option_collector.rb +12 -9
- data/lib/hammer_cli/options/option_processor.rb +17 -0
- data/lib/hammer_cli/options/processor_list.rb +37 -0
- data/lib/hammer_cli/options/sources/base.rb +17 -0
- data/lib/hammer_cli/options/sources/command_line.rb +3 -1
- data/lib/hammer_cli/options/sources/saved_defaults.rb +3 -1
- data/lib/hammer_cli/options/validators/base.rb +20 -0
- data/lib/hammer_cli/options/validators/dsl.rb +160 -0
- data/lib/hammer_cli/options/validators/dsl_block_validator.rb +19 -0
- data/lib/hammer_cli/output/adapter/csv.rb +11 -11
- data/lib/hammer_cli/output/adapter/tree_structure.rb +5 -3
- data/lib/hammer_cli/output/definition.rb +42 -4
- data/lib/hammer_cli/output/dsl.rb +4 -2
- data/lib/hammer_cli/output/fields.rb +9 -2
- data/lib/hammer_cli/testing/messages.rb +6 -6
- data/lib/hammer_cli/utils.rb +15 -0
- data/lib/hammer_cli/version.rb +1 -1
- data/locale/ca/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/de/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/en/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/en_GB/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/es/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/fr/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/it/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ja/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ko/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/pt_BR/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ru/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/zh_CN/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/zh_TW/LC_MESSAGES/hammer-cli.mo +0 -0
- data/test/unit/abstract_test.rb +70 -5
- data/test/unit/exception_handler_test.rb +1 -1
- data/test/unit/help/definition/abstract_item_test.rb +33 -0
- data/test/unit/help/definition/list_test.rb +17 -0
- data/test/unit/help/definition/section_test.rb +25 -0
- data/test/unit/help/definition/text_test.rb +11 -0
- data/test/unit/help/definition_test.rb +236 -0
- data/test/unit/help/text_builder_test.rb +170 -1
- data/test/unit/options/option_collector_test.rb +18 -9
- data/test/unit/options/processor_list_test.rb +70 -0
- data/test/unit/{validator_test.rb → options/validators/dsl_test.rb} +57 -93
- data/test/unit/output/adapter/abstract_test.rb +3 -0
- data/test/unit/output/adapter/base_test.rb +5 -0
- data/test/unit/output/adapter/csv_test.rb +3 -0
- data/test/unit/output/adapter/json_test.rb +12 -0
- data/test/unit/output/adapter/table_test.rb +5 -0
- data/test/unit/output/adapter/yaml_test.rb +11 -0
- data/test/unit/output/definition_test.rb +221 -1
- data/test/unit/utils_test.rb +23 -0
- metadata +31 -5
- data/lib/hammer_cli/validator.rb +0 -172
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 836795c65ef362f852b3eed29126508d0bf23927
|
4
|
+
data.tar.gz: 8300578ae0b731724817506ee20bda1ea458b71b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 848a8e9636cb5c8e8dea817de554d943f73db10399d897d770d71a7df5cfc66d5c843b351c64587781dd93ae5be81ecd17afe0e2ffa4e0ce7192d55e4d5fd732
|
7
|
+
data.tar.gz: aa6bbeb277ae28f0d1c1626f78773dcfbd64a4b81de89609a5fa64eff4a7a607e582f464fb2b58bc7df30b3770c877b2188b62ed14030992630a21932e0b9cf8
|
@@ -0,0 +1,82 @@
|
|
1
|
+
Modify an existing command
|
2
|
+
-------------------------
|
3
|
+
|
4
|
+
### Modification of output fields
|
5
|
+
|
6
|
+
Each command (as well as each field) might have its own
|
7
|
+
output definition. You can modify the output definition of existing
|
8
|
+
command or a specific field of that command by following output
|
9
|
+
definition interface:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
|
13
|
+
# Appends fields to the end.
|
14
|
+
# Where:
|
15
|
+
# fields is one or more existing fields
|
16
|
+
# block is block of code with new fields
|
17
|
+
definition.append(fields) do
|
18
|
+
label
|
19
|
+
field
|
20
|
+
collection
|
21
|
+
end
|
22
|
+
# Inserts one or more fields.
|
23
|
+
# Where:
|
24
|
+
# :mode is one of [:before, :after, :replace]
|
25
|
+
# :id is field's id or key. Field's label can be used if field does not
|
26
|
+
# have id
|
27
|
+
# fields is one or more existing fields
|
28
|
+
# block is block of code with new fields
|
29
|
+
definition.insert(:mode, :id, fields) do
|
30
|
+
label
|
31
|
+
field
|
32
|
+
collection
|
33
|
+
end
|
34
|
+
# Returns output definition of the command or field specified with path.
|
35
|
+
# Where:
|
36
|
+
# path = Array of :key or/and :id or/and 'label']
|
37
|
+
definition.at(path)
|
38
|
+
# Returns field from current output definition.
|
39
|
+
definition.find_field(:id)
|
40
|
+
# Deletes all fields from current output definition.
|
41
|
+
definition.clear
|
42
|
+
end
|
43
|
+
```
|
44
|
+
#### Examples
|
45
|
+
```ruby
|
46
|
+
# Append some fields to the end
|
47
|
+
HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
|
48
|
+
definition.at(_('Collection Field Label'))
|
49
|
+
.append do
|
50
|
+
field :value3, _('Value 3')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
# Change field's label
|
54
|
+
HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
|
55
|
+
definition.at(:path)
|
56
|
+
.find_field(:id).label = _('New label')
|
57
|
+
end
|
58
|
+
# Expand a field with new definition
|
59
|
+
HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
|
60
|
+
definition.at([_('some'), :path])
|
61
|
+
.insert(:replace, :not_container_field_id) do
|
62
|
+
field nil, _('Label with new fields'), Fields::Label, id: :now_container_field_id do
|
63
|
+
field :new_field1, _('New field 1')
|
64
|
+
field :new_field2, _('New field 2')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# Insert a new field after specific field
|
69
|
+
HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
|
70
|
+
definition.at([_('some'), :path])
|
71
|
+
.insert(:after, :other_field_id, [Fields::Field.new(label: _('My field'), id: :my_field_id)])
|
72
|
+
end
|
73
|
+
# Insert a new field before specific field
|
74
|
+
HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
|
75
|
+
definition.insert(:before, :other_field_id,
|
76
|
+
Fields::Field.new(label: _('My field'), id: :my_field_id))
|
77
|
+
end
|
78
|
+
# Remove field
|
79
|
+
HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
|
80
|
+
definition.insert(:replace, :field_id) do; end
|
81
|
+
end
|
82
|
+
```
|
data/doc/creating_commands.md
CHANGED
@@ -169,33 +169,7 @@ In cases when you want to deprecate just one of more possible switches use the e
|
|
169
169
|
Hammer commands offer option builders that can be used for automatic option generation.
|
170
170
|
See [documentation page](option_builders.md#option-builders) dedicated to this topic for more details.
|
171
171
|
|
172
|
-
### Option
|
173
|
-
Hammer provides extended functionality for validating options.
|
174
|
-
|
175
|
-
#### DSL
|
176
|
-
First of all there is a dsl for validating combinations of options:
|
177
|
-
```ruby
|
178
|
-
validate_options do
|
179
|
-
all(:option_name, :option_surname).required # requires all the options
|
180
|
-
option(:option_age).required # requires a single option,
|
181
|
-
# equivalent of :required => true in option declaration
|
182
|
-
any(:option_email, :option_phone).required # requires at least one of the options
|
183
|
-
|
184
|
-
# It is possible to create more complicated constructs.
|
185
|
-
# This example requires either the full address or nothing
|
186
|
-
if any(:option_street, :option_city, :option_zip).exist?
|
187
|
-
all(:option_street, :option_city, :option_zip).required
|
188
|
-
end
|
189
|
-
|
190
|
-
# Here you can reject all address related option when --no-address is passed
|
191
|
-
if option(:option_no_address).exist?
|
192
|
-
all(:option_street, :option_city, :option_zip).rejected
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
```
|
197
|
-
|
198
|
-
#### Option normalizers
|
172
|
+
### Option normalizers
|
199
173
|
Another option-related feature is a set of normalizers for specific option types. They validate and preprocess
|
200
174
|
option values. Each normalizer has a description of the format it accepts. This description is printed
|
201
175
|
in commands' help.
|
@@ -244,24 +218,90 @@ option "--attributes", "ATTRIBUTES", "Values of various attributes",
|
|
244
218
|
|
245
219
|
### Advanced option evaluation
|
246
220
|
|
247
|
-
Sometimes it is necessary to tune the option values based on other parameters given on CLI.
|
221
|
+
Sometimes it is necessary to tune or validate the option values based on other parameters given on CLI.
|
248
222
|
An example could be setting default values based on other options, values lookup in a DB, etc.
|
249
|
-
The right place for this are
|
250
|
-
|
223
|
+
The right place for this are option processors. There are two basic kinds of option processors in hammer:
|
224
|
+
- *option sources* - they provide values for the options, descendants of `HammerCLI::Options::Sources::Base`
|
225
|
+
- *option validators* - they check if the options values are valid, descendants of `HammerCLI::Options::Validators::Base`
|
226
|
+
|
227
|
+
Option sources and validators can be mixed together. For example it's possible to collect options from the command line,
|
228
|
+
do some validation on them and then continue with collecting options from a different source.
|
229
|
+
The whole set of processors is invoked only once per command call. The processing is triggered by a first call
|
230
|
+
to the `options` or `all_options` method, but at latest right after the option validation
|
231
|
+
(before the command's `execute` method is invoked). The order is as follows:
|
232
|
+
1. option parsing
|
233
|
+
1. option normalization
|
234
|
+
1. option processors execution (sources and validators)
|
235
|
+
1. `execute` invocation
|
236
|
+
|
237
|
+
#### Default option sources
|
238
|
+
|
239
|
+
Abstract Hammer command uses two default option sources -
|
240
|
+
`HammerCLI::Options::Sources::CommandLine` responsible for intial population of the options and
|
251
241
|
`HammerCLI::Options::Sources::SavedDefaults` adding defaults managed by the `defaults` command.
|
252
242
|
|
243
|
+
The default option sources are wrapped in `DefaultInputs` processor list so that it's possible to easily place
|
244
|
+
custom sources before or behind all the default ones.
|
245
|
+
The full default hierarchy is:
|
246
|
+
|
247
|
+
```
|
248
|
+
- DefaultInputs
|
249
|
+
- CommandLine
|
250
|
+
- SavedDefaults (present only when defaults are enabled)
|
251
|
+
```
|
252
|
+
|
253
253
|
By overriding `option_sources` method in a command it is possible to add custom option sources
|
254
254
|
for various tasks to the list. The option sources are evaluated one by one each being given output
|
255
255
|
of the previous one as its input so the order in which the sources are listed matters.
|
256
256
|
|
257
|
-
Option
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
257
|
+
#### Option validation
|
258
|
+
Hammer provides extended functionality for validating options.
|
259
|
+
|
260
|
+
First of all there is a DSL for validating combinations of options:
|
261
|
+
```ruby
|
262
|
+
validate_options do
|
263
|
+
all(:option_name, :option_surname).required # requires all the options
|
264
|
+
option(:option_age).required # requires a single option,
|
265
|
+
# equivalent of :required => true in option declaration
|
266
|
+
any(:option_email, :option_phone).required # requires at least one of the options
|
267
|
+
|
268
|
+
# It is possible to create more complicated constructs.
|
269
|
+
# This example requires either the full address or nothing
|
270
|
+
if any(:option_street, :option_city, :option_zip).exist?
|
271
|
+
all(:option_street, :option_city, :option_zip).required
|
272
|
+
end
|
273
|
+
|
274
|
+
# Here you can reject all address related option when --no-address is passed
|
275
|
+
if option(:option_no_address).exist?
|
276
|
+
all(:option_street, :option_city, :option_zip).rejected
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
```
|
281
|
+
|
282
|
+
It's possible to insert a validation block on a certain place in the option processor chain:
|
283
|
+
```ruby
|
284
|
+
validate_options(:after, 'DefaultInputs') do
|
285
|
+
# ...inserts the validation block after DefaultInputs option source
|
286
|
+
end
|
287
|
+
|
288
|
+
validate_options(:prepend) do
|
289
|
+
# ...adds validation to the first place in the queue
|
290
|
+
end
|
291
|
+
|
292
|
+
# Following insert modes can be used:
|
293
|
+
# before, after, append, prepend (the default behavior)
|
294
|
+
```
|
295
|
+
|
296
|
+
Alternatively the functionality can be extracted in a validator object that can be shared by multiple commands:
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
validate_options(:after, 'DefaultInputs', validator: Custom::Validator.new)
|
300
|
+
|
301
|
+
```
|
302
|
+
|
303
|
+
`validate_options` adds validators into a specific command class and they aren't inherited with subclasses.
|
304
|
+
Inheritable validators can be created command's `add_validators` method.
|
265
305
|
|
266
306
|
|
267
307
|
### Adding subcommands
|
data/doc/developer_docs.md
CHANGED
@@ -8,6 +8,8 @@ before creating hammer specific plugins.
|
|
8
8
|
Contents:
|
9
9
|
- [Writing a plugin](writing_a_plugin.md#writing-your-own-hammer-plugin)
|
10
10
|
- [Creating commands](creating_commands.md#create-your-first-command)
|
11
|
+
- [Help modification](help_modification.md#modify-an-existing-help)
|
12
|
+
- [Commands modification](commands_modification.md#modify-an-existing-command)
|
11
13
|
- [Option builders](option_builders.md#option-builders)
|
12
14
|
- [Creating ApiPie commands](creating_apipie_commands.md#creating-commands-for-restful-api-with-apipie)
|
13
15
|
- [Development tips](development_tips.md#development-tips)
|
@@ -0,0 +1,119 @@
|
|
1
|
+
Modify an existing help
|
2
|
+
-------------------------
|
3
|
+
Each command might have its own help definition. This definition is composed of various _help items_, which might contain their own definitions.
|
4
|
+
|
5
|
+
Let's say `hammer host create -h` help string has the following structure:
|
6
|
+
```
|
7
|
+
hammer host create -h
|
8
|
+
+-- Usage
|
9
|
+
+-- Options
|
10
|
+
+-- Additional info
|
11
|
+
| +-- Section(Available keys for --interface:)
|
12
|
+
| | +-- List
|
13
|
+
| | +-- Section
|
14
|
+
| | | +-- List
|
15
|
+
| | +-- Section
|
16
|
+
| | | +-- List
|
17
|
+
| | +-- Section
|
18
|
+
| | | +-- List
|
19
|
+
| +-- Section(Provider specific options:)
|
20
|
+
| | +-- Section
|
21
|
+
| | | +-- Section
|
22
|
+
| | | | +-- List
|
23
|
+
...
|
24
|
+
| | +-- Section(Libvirt:)
|
25
|
+
| | | +-- Section(--compute-attributes:)
|
26
|
+
| | | | +-- List[
|
27
|
+
cpus Number of CPUs
|
28
|
+
memory String, amount of memory, value in bytes
|
29
|
+
start Boolean (expressed as 0 or 1), whether to start the machine or not
|
30
|
+
]
|
31
|
+
...
|
32
|
+
| | | +-- Section
|
33
|
+
| | | | +-- List
|
34
|
+
```
|
35
|
+
Every `Section`, `List` and simple `Text` is _help item_ defined as `HammerCLI::Help::AbstractItem`, so everything might have its own ID now for easier addressing.
|
36
|
+
|
37
|
+
To modify the structure above, you might use the following:
|
38
|
+
```ruby
|
39
|
+
HammerCLIForeman::Host::CreateCommand.extend_help do |h|
|
40
|
+
# Simple addition to the end.
|
41
|
+
h.section
|
42
|
+
h.list
|
43
|
+
h.text
|
44
|
+
|
45
|
+
# Inserts one or more help items.
|
46
|
+
# Where:
|
47
|
+
# :mode is one of [:before, :after, :replace]
|
48
|
+
# :item_id is item's id or label. Item's label can be used if it does not
|
49
|
+
# have an id, e.g. any Section
|
50
|
+
# block is block of code with new items
|
51
|
+
h.insert(:mode, :item_id) do |h|
|
52
|
+
h.section
|
53
|
+
h.list
|
54
|
+
h.text
|
55
|
+
end
|
56
|
+
# Addition to custom path.
|
57
|
+
# Where:
|
58
|
+
# path is Array of :item_id or/and 'item_label'
|
59
|
+
# block is the code block with new help items.
|
60
|
+
h.at(path) do |h|
|
61
|
+
...
|
62
|
+
h.section
|
63
|
+
h.list
|
64
|
+
h.text
|
65
|
+
...
|
66
|
+
end
|
67
|
+
# Returns help item from current definition.
|
68
|
+
h.find_item(:item_id)
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
#### Examples
|
73
|
+
```ruby
|
74
|
+
# Add a new section with list to the end of the Libvirt section.
|
75
|
+
HammerCLIForeman::Host::CreateCommand.extend_help do |h|
|
76
|
+
h.at(['Provider specific options', 'Libvirt']) do |h|
|
77
|
+
h.section('--new-section-with-list', id: :section_with_list) do |h|
|
78
|
+
h.list([
|
79
|
+
['item1', _('Desc1')],
|
80
|
+
['item2'],
|
81
|
+
['item3', _('Desc3')]
|
82
|
+
], id: :list_with_id)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Add important information
|
88
|
+
HammerCLIForeman::Host::CreateCommand.extend_help do |h|
|
89
|
+
h.at(['Provider specific options']) do |h|
|
90
|
+
h.insert(:before, 'EC2') do |h|
|
91
|
+
h.text('Something important for all providers')
|
92
|
+
end
|
93
|
+
h.at(['EC2']) do |h|
|
94
|
+
h.insert(:before, '--compute-attributes') do |h|
|
95
|
+
h.text('Something important for EC2 only')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Delete the Libvirt section from Provider specific options section.
|
102
|
+
HammerCLIForeman::Host::CreateCommand.extend_help do |h|
|
103
|
+
h.at('Provider specific options') do |h|
|
104
|
+
h.insert(:replace, 'Libvirt') do |h|; end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Add more text
|
109
|
+
HammerCLIForeman::Host::CreateCommand.extend_help do |h|
|
110
|
+
h.at('Provider specific options') do |h|
|
111
|
+
h.insert(:before, 'EC2') do |h|
|
112
|
+
h.text('Imagine it already was here', id: :old_text_id)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
h.at(['Provider specific options', :old_text_id]) do |h|
|
116
|
+
h.text('Additional information', id: :additional_text)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
data/doc/i18n.md
CHANGED
@@ -73,8 +73,8 @@ HammerCLI::I18n::FindTask.define(HammerCLIAwesome::I18n::LocaleDomain.new, Hamme
|
|
73
73
|
and create `locale/Makefile` with following content:
|
74
74
|
```make
|
75
75
|
DOMAIN = hammer-cli-awesome
|
76
|
-
VERSION = $(shell bundle exec ruby -e 'require "rubygems"; spec = Gem::Specification::load("../hammer_cli_awesome.gemspec"); puts spec.version')
|
77
|
-
MAIN_MAKEFILE = $(shell bundle exec ruby -e 'require "hammer_cli"; puts HammerCLI::I18n.main_makefile')
|
76
|
+
VERSION = $(shell bundle exec ruby -C ../ -e 'require "rubygems"; spec = Gem::Specification::load("../hammer_cli_awesome.gemspec"); puts spec.version')
|
77
|
+
MAIN_MAKEFILE = $(shell bundle exec ruby -C ../ -e 'require "hammer_cli"; puts HammerCLI::I18n.main_makefile')
|
78
78
|
|
79
79
|
include $(MAIN_MAKEFILE)
|
80
80
|
```
|
data/doc/installation_rpm.md
CHANGED
@@ -32,7 +32,7 @@ On RHEL systems you will also have to add [EPEL repository](https://fedoraprojec
|
|
32
32
|
#### Step 2: install hammer core
|
33
33
|
|
34
34
|
```bash
|
35
|
-
yum install rubygem-hammer_cli
|
35
|
+
yum install tfm-rubygem-hammer_cli
|
36
36
|
```
|
37
37
|
|
38
38
|
#### Step 3: install plugins
|
@@ -41,13 +41,13 @@ Currently, there are two plugins, both available as rpm packages.
|
|
41
41
|
- commands for managing foreman
|
42
42
|
|
43
43
|
```bash
|
44
|
-
yum install rubygem-hammer_cli_foreman
|
44
|
+
yum install tfm-rubygem-hammer_cli_foreman
|
45
45
|
```
|
46
46
|
|
47
47
|
- commands for managing [katello](https://github.com/Katello/katello)
|
48
48
|
|
49
49
|
```bash
|
50
|
-
yum install rubygem-hammer_cli_katello
|
50
|
+
yum install tfm-rubygem-hammer_cli_katello
|
51
51
|
```
|
52
52
|
|
53
53
|
To install any other hammer plugin just make sure the appropriate gem is installed and follow with the [configuration](installation.md#configuration).
|
data/doc/release_notes.md
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
Release notes
|
2
2
|
=============
|
3
|
-
### 0.
|
3
|
+
### 0.16.0 (2019-01-16)
|
4
|
+
* Fixed instructions in i18n docs ([#25724](http://projects.theforeman.org/issues/25724))
|
5
|
+
* Option validators can be mixed with sources ([#22253](http://projects.theforeman.org/issues/22253))
|
6
|
+
* Validator uses options from option collector ([#19574](http://projects.theforeman.org/issues/19574))
|
7
|
+
* Hammer -h does work with --output json, csv, yaml ([#25438](http://projects.theforeman.org/issues/25438))
|
8
|
+
* Update rpm names to use tfm ([PR #296](https://github.com/theforeman/hammer-cli/pull/296))
|
9
|
+
* Allows modification of output fields ([PR #275](https://github.com/theforeman/hammer-cli/pull/275)) ([#21634](http://projects.theforeman.org/issues/21634))
|
10
|
+
* Allow skipping message tests ([PR #292](https://github.com/theforeman/hammer-cli/pull/292)) ([#7451](http://projects.theforeman.org/issues/7451))
|
4
11
|
* Helper for editing text in editor ([PR #294](https://github.com/theforeman/hammer-cli/pull/294)) ([#24489](http://projects.theforeman.org/issues/24489))
|
5
12
|
* Add ability to disable defaults ([PR #293](https://github.com/theforeman/hammer-cli/pull/293)) ([#25307](http://projects.theforeman.org/issues/25307))
|
13
|
+
* Allow modification of additional help texts ([PR #277](https://github.com/theforeman/hammer-cli/pull/277)) ([#21633](http://projects.theforeman.org/issues/21633))
|
6
14
|
|
7
15
|
### 0.15.0 (2018-10-24)
|
8
16
|
* Correct the gemspec ([PR #286](https://github.com/theforeman/hammer-cli/pull/286))
|
data/lib/hammer_cli.rb
CHANGED
@@ -9,7 +9,6 @@ require 'hammer_cli/settings'
|
|
9
9
|
require 'hammer_cli/logger'
|
10
10
|
require 'hammer_cli/ca_cert_manager'
|
11
11
|
require 'hammer_cli/connection'
|
12
|
-
require 'hammer_cli/validator'
|
13
12
|
require 'hammer_cli/output'
|
14
13
|
require 'hammer_cli/options/normalizers'
|
15
14
|
require 'hammer_cli/completer'
|
data/lib/hammer_cli/abstract.rb
CHANGED
@@ -2,14 +2,17 @@ require 'hammer_cli/exception_handler'
|
|
2
2
|
require 'hammer_cli/logger_watch'
|
3
3
|
require 'hammer_cli/options/option_definition'
|
4
4
|
require 'hammer_cli/options/option_collector'
|
5
|
+
require 'hammer_cli/options/processor_list'
|
5
6
|
require 'hammer_cli/options/sources/command_line'
|
6
7
|
require 'hammer_cli/options/sources/saved_defaults'
|
8
|
+
require 'hammer_cli/options/validators/dsl_block_validator'
|
7
9
|
require 'hammer_cli/clamp'
|
8
10
|
require 'hammer_cli/subcommand'
|
9
11
|
require 'hammer_cli/options/matcher'
|
10
12
|
require 'hammer_cli/help/builder'
|
11
13
|
require 'hammer_cli/help/text_builder'
|
12
14
|
require 'logging'
|
15
|
+
|
13
16
|
module HammerCLI
|
14
17
|
|
15
18
|
class AbstractCommand < Clamp::Command
|
@@ -17,6 +20,10 @@ module HammerCLI
|
|
17
20
|
|
18
21
|
class << self
|
19
22
|
attr_accessor :validation_blocks
|
23
|
+
|
24
|
+
def help_extension_blocks
|
25
|
+
@help_extension_blocks ||= []
|
26
|
+
end
|
20
27
|
end
|
21
28
|
|
22
29
|
def adapter
|
@@ -40,7 +47,7 @@ module HammerCLI
|
|
40
47
|
super
|
41
48
|
validate_options
|
42
49
|
logger.info "Called with options: %s" % options.inspect
|
43
|
-
rescue HammerCLI::
|
50
|
+
rescue HammerCLI::Options::Validators::ValidationError => e
|
44
51
|
signal_usage_error e.message
|
45
52
|
end
|
46
53
|
|
@@ -48,15 +55,14 @@ module HammerCLI
|
|
48
55
|
HammerCLI::EX_OK
|
49
56
|
end
|
50
57
|
|
51
|
-
def self.validate_options(&block)
|
58
|
+
def self.validate_options(mode=:append, target_name=nil, validator: nil, &block)
|
59
|
+
validator ||= HammerCLI::Options::Validators::DSLBlockValidator.new(&block)
|
52
60
|
self.validation_blocks ||= []
|
53
|
-
self.validation_blocks <<
|
61
|
+
self.validation_blocks << [mode, target_name, validator]
|
54
62
|
end
|
55
63
|
|
56
64
|
def validate_options
|
57
|
-
|
58
|
-
self.class.validation_blocks.each { |validation_block| validator.run(&validation_block) }
|
59
|
-
end
|
65
|
+
# keep the method for legacy reasons
|
60
66
|
end
|
61
67
|
|
62
68
|
def exception_handler
|
@@ -80,9 +86,16 @@ module HammerCLI
|
|
80
86
|
def self.help(invocation_path, builder = HammerCLI::Help::Builder.new)
|
81
87
|
super(invocation_path, builder)
|
82
88
|
|
83
|
-
|
89
|
+
unless help_extension_blocks.empty?
|
84
90
|
help_extension = HammerCLI::Help::TextBuilder.new(builder.richtext)
|
85
|
-
|
91
|
+
help_extension_blocks.each do |extension_block|
|
92
|
+
begin
|
93
|
+
extension_block.call(help_extension)
|
94
|
+
rescue ArgumentError => e
|
95
|
+
handler = HammerCLI::ExceptionHandler.new
|
96
|
+
handler.handle_exception(e)
|
97
|
+
end
|
98
|
+
end
|
86
99
|
builder.add_text(help_extension.string)
|
87
100
|
end
|
88
101
|
builder.string
|
@@ -90,7 +103,14 @@ module HammerCLI
|
|
90
103
|
|
91
104
|
def self.extend_help(&block)
|
92
105
|
# We save the block for execution on object level, where we can access command's context and check :is_tty? flag
|
93
|
-
|
106
|
+
self.help_extension_blocks << block
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.extend_output_definition(&block)
|
110
|
+
block.call(output_definition)
|
111
|
+
rescue ArgumentError => e
|
112
|
+
handler = HammerCLI::ExceptionHandler.new
|
113
|
+
handler.handle_exception(e)
|
94
114
|
end
|
95
115
|
|
96
116
|
def self.output(definition=nil, &block)
|
@@ -180,8 +200,8 @@ module HammerCLI
|
|
180
200
|
end
|
181
201
|
|
182
202
|
def validator
|
183
|
-
|
184
|
-
@validator ||= HammerCLI::
|
203
|
+
# keep the method for legacy reasons, it's used by validate_options
|
204
|
+
@validator ||= HammerCLI::Options::Validators::DSL.new(self.class.recognised_options, all_options)
|
185
205
|
end
|
186
206
|
|
187
207
|
def handle_exception(e)
|
@@ -240,13 +260,24 @@ module HammerCLI
|
|
240
260
|
end
|
241
261
|
|
242
262
|
def option_collector
|
243
|
-
@option_collector ||= HammerCLI::Options::OptionCollector.new(self.class.recognised_options, option_sources)
|
263
|
+
@option_collector ||= HammerCLI::Options::OptionCollector.new(self.class.recognised_options, add_validators(option_sources))
|
244
264
|
end
|
245
265
|
|
246
266
|
|
247
267
|
def option_sources
|
248
|
-
sources =
|
268
|
+
sources = HammerCLI::Options::ProcessorList.new(name: 'DefaultInputs')
|
269
|
+
sources << HammerCLI::Options::Sources::CommandLine.new(self)
|
249
270
|
sources << HammerCLI::Options::Sources::SavedDefaults.new(context[:defaults], logger) if context[:use_defaults]
|
271
|
+
|
272
|
+
HammerCLI::Options::ProcessorList.new([sources])
|
273
|
+
end
|
274
|
+
|
275
|
+
def add_validators(sources)
|
276
|
+
if self.class.validation_blocks
|
277
|
+
self.class.validation_blocks.each do |validation_block|
|
278
|
+
sources.insert_relative(*validation_block)
|
279
|
+
end
|
280
|
+
end
|
250
281
|
sources
|
251
282
|
end
|
252
283
|
|