hammer_cli 0.0.18 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -314
  3. data/bin/hammer +45 -6
  4. data/config/cli.modules.d/module_config_template.yml +4 -0
  5. data/config/cli_config.template.yml +9 -11
  6. data/doc/developer_docs.md +1 -0
  7. data/doc/i18n.md +85 -0
  8. data/doc/installation.md +321 -0
  9. data/lib/hammer_cli.rb +3 -0
  10. data/lib/hammer_cli/abstract.rb +15 -24
  11. data/lib/hammer_cli/apipie/command.rb +13 -7
  12. data/lib/hammer_cli/apipie/options.rb +14 -16
  13. data/lib/hammer_cli/apipie/read_command.rb +6 -1
  14. data/lib/hammer_cli/apipie/resource.rb +48 -58
  15. data/lib/hammer_cli/apipie/write_command.rb +5 -1
  16. data/lib/hammer_cli/completer.rb +77 -21
  17. data/lib/hammer_cli/connection.rb +44 -0
  18. data/lib/hammer_cli/exception_handler.rb +15 -4
  19. data/lib/hammer_cli/exceptions.rb +6 -0
  20. data/lib/hammer_cli/i18n.rb +95 -0
  21. data/lib/hammer_cli/logger.rb +3 -3
  22. data/lib/hammer_cli/main.rb +12 -11
  23. data/lib/hammer_cli/modules.rb +19 -6
  24. data/lib/hammer_cli/options/normalizers.rb +42 -7
  25. data/lib/hammer_cli/options/option_definition.rb +2 -2
  26. data/lib/hammer_cli/output.rb +1 -0
  27. data/lib/hammer_cli/output/adapter/abstract.rb +20 -0
  28. data/lib/hammer_cli/output/adapter/base.rb +49 -78
  29. data/lib/hammer_cli/output/adapter/csv.rb +5 -5
  30. data/lib/hammer_cli/output/adapter/table.rb +41 -10
  31. data/lib/hammer_cli/output/dsl.rb +1 -1
  32. data/lib/hammer_cli/output/field_filter.rb +21 -0
  33. data/lib/hammer_cli/output/fields.rb +44 -78
  34. data/lib/hammer_cli/output/formatters.rb +38 -0
  35. data/lib/hammer_cli/settings.rb +28 -6
  36. data/lib/hammer_cli/shell.rb +58 -57
  37. data/lib/hammer_cli/utils.rb +14 -0
  38. data/lib/hammer_cli/validator.rb +5 -5
  39. data/lib/hammer_cli/version.rb +1 -1
  40. data/locale/Makefile +64 -0
  41. data/locale/hammer-cli.pot +203 -0
  42. data/locale/zanata.xml +29 -0
  43. data/test/unit/apipie/command_test.rb +42 -25
  44. data/test/unit/apipie/read_command_test.rb +10 -7
  45. data/test/unit/apipie/write_command_test.rb +9 -8
  46. data/test/unit/completer_test.rb +206 -21
  47. data/test/unit/connection_test.rb +68 -0
  48. data/test/unit/fixtures/apipie/architectures.json +153 -0
  49. data/test/unit/fixtures/apipie/documented.json +79 -0
  50. data/test/unit/fixtures/json_input/invalid.json +12 -0
  51. data/test/unit/fixtures/json_input/valid.json +12 -0
  52. data/test/unit/history_test.rb +71 -0
  53. data/test/unit/main_test.rb +9 -0
  54. data/test/unit/modules_test.rb +22 -6
  55. data/test/unit/options/field_filter_test.rb +27 -0
  56. data/test/unit/options/normalizers_test.rb +53 -0
  57. data/test/unit/output/adapter/base_test.rb +162 -10
  58. data/test/unit/output/adapter/csv_test.rb +16 -3
  59. data/test/unit/output/adapter/table_test.rb +97 -13
  60. data/test/unit/output/dsl_test.rb +74 -6
  61. data/test/unit/output/fields_test.rb +93 -62
  62. data/test/unit/output/formatters_test.rb +47 -0
  63. data/test/unit/settings_test.rb +35 -4
  64. data/test/unit/utils_test.rb +45 -0
  65. metadata +85 -4
  66. data/test/unit/apipie/fake_api.rb +0 -101
@@ -11,3 +11,4 @@ Contents:
11
11
  - [Creating ApiPie commands](creating_apipie_commands.md#creating-commands-for-restful-api-with-apipie)
12
12
  - [Development tips](development_tips.md#development-tips)
13
13
  - [Option normalizers](option_normalizers.md#option-normalizers)
14
+ - [Internacionalization](i18n.md#internacionalization)
@@ -0,0 +1,85 @@
1
+ Internacionalization
2
+ --------------------
3
+
4
+ Hammer uses [fast gettext](https://github.com/grosser/fast_gettext) for string translations. Most of the localization magic
5
+ is done for you in hammer already. If you want your plugin to support i18n it needs to register it's translation domain
6
+ at hammer's i18n module:
7
+ ```ruby
8
+ require 'hammer_cli/i18n'
9
+
10
+ # namespace your i18n module
11
+ module HammerCLIAwesome
12
+ module I18n
13
+
14
+ # create a locale domain for your plugin
15
+ class LocaleDomain < HammerCLI::I18n::LocaleDomain
16
+
17
+ # lists all your source files that use _()
18
+ def translated_files
19
+ Dir.glob(File.join(File.dirname(__FILE__), '../**/*.rb'))
20
+ end
21
+
22
+ # returns path to your locale directory
23
+ # it's typically "locale" in the root of your plugin
24
+ def locale_dir
25
+ File.join(File.dirname(__FILE__), '../../locale')
26
+ end
27
+
28
+ # name for your language domain
29
+ def domain_name
30
+ 'hammer-cli-awesome'
31
+ end
32
+
33
+ # type of the translation files, 'mo' files are default
34
+ # you can also use 'po' and 'yaml' files for testing purposes
35
+ def type
36
+ :mo
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ # register the domain
45
+ HammerCLI::I18n.add_domain(HammerCLIAwesomePlugin::I18n::LocaleDomain.new)
46
+ ```
47
+
48
+ Then you have to export strings, translate them and place the files in a directory structure.
49
+ Inspiration on how to export the translations can be found in the hammer's [Rakefile](../Rakefile).
50
+
51
+ Typical directory structure for translation files look like this:
52
+ ```
53
+ locale
54
+ ├── de
55
+ │   ├── hammer-cli-awesome.po
56
+ │   └── LC_MESSAGES
57
+ │   └── hammer-cli-awesome.mo
58
+ ├── en
59
+ │   ├── hammer-cli-awesome.po
60
+ │   └── LC_MESSAGES
61
+ │   └── hammer-cli-awesome.mo
62
+ └── hammer-cli-awesome.pot
63
+ ```
64
+
65
+
66
+ ### Translation tips
67
+
68
+ When writing a code with translations make sure you keep two following rules:
69
+
70
+ 1) Don't use variables directly in the strings and make formatting substitutions outside the gettext function `_("...")`.
71
+ ```ruby
72
+ # WRONG
73
+ puts _("Hello #{name}")
74
+ puts _("Hello %s" % name)
75
+ # CORRECT
76
+ puts _("Hello %s") % name
77
+ ```
78
+
79
+ 2) Use named placeholders when there is more than one replacement. Languages differ in their word order.
80
+ ```ruby
81
+ # WRONG
82
+ puts _("Hello %s, it is %s" % [name, day])
83
+ # CORRECT
84
+ puts _("Hello %{name}, it is %{day}") % {:name => name, :day => day}
85
+ ```
@@ -0,0 +1,321 @@
1
+ Installation
2
+ ------------
3
+
4
+ Hammer CLI is packaged for the following RPM based distributions:
5
+
6
+ - RHEL and derivatives, version 6
7
+ - Fedora 18, 19
8
+ - Debian Wheezy, Squeezy
9
+ - Ubuntu Precise
10
+
11
+ ### Installation from RPMs
12
+
13
+ #### Step 1: setup yum repositories
14
+
15
+ For Foreman 1.3 stable the hammer packages are part of your installation repo and you can skip this step.
16
+
17
+ You can choose from stable or nightly repo. Nightly has more recent version of hammer packages, but it was subject to less testing so there is a higher risk of issues.
18
+ Add the Foreman yum repository to your yum repo files. For Fedora installations replace 'el6' with 'f18' or 'f19' as appropriate.
19
+
20
+
21
+ Using stable
22
+
23
+ ```bash
24
+ yum -y install http://yum.theforeman.org/releases/1.3/el6/x86_64/foreman-release.rpm
25
+ ```
26
+
27
+ or nightly
28
+
29
+ ```bash
30
+ cat > /etc/yum.repos.d/foreman.repo << EOF
31
+ [foreman]
32
+ name=Foreman Nightly
33
+ baseurl=http://yum.theforeman.org/nightly/el6/x86_64
34
+ gpgcheck=0
35
+ enabled=1
36
+ EOF
37
+ ```
38
+
39
+ On RHEL systems you will also have to add [EPEL repository](https://fedoraproject.org/wiki/EPEL) as it contains some of the required dependencies.
40
+
41
+
42
+ #### Step 2: install hammer core
43
+
44
+ ```bash
45
+ yum install rubygem-hammer_cli
46
+ ```
47
+
48
+ #### Step 3: install plugins
49
+ Currently, there are two plugins, both available as rpm packages.
50
+
51
+ - commands for managing foreman
52
+
53
+ ```bash
54
+ yum install rubygem-hammer_cli_foreman
55
+ ```
56
+
57
+ - commands for katello [katello cli](https://github.com/Katello/katello)
58
+
59
+ ```bash
60
+ yum install rubygem-hammer_cli_katello
61
+ ```
62
+
63
+ To install any other hammer plugin just make sure the appropriate gem is installed and follow with the configuration.
64
+
65
+
66
+ ### Installation from DEBs
67
+
68
+ #### Step 1: setup apt repositories
69
+
70
+ For Foreman 1.3 stable the hammer packages are part of your installation repo and you can skip this step.
71
+
72
+ You can choose from stable or nightly repo. Nightly has more recent version of hammer packages, but it was subject to less testing so there is a highr risk of issues.
73
+
74
+ Choose stable (don't forget to replace "squeeze" with version name of your system)
75
+
76
+ ```bash
77
+ echo "deb http://deb.theforeman.org/ squeeze stable" > /etc/apt/sources.list.d/foreman.list
78
+ ```
79
+
80
+ or nightly
81
+
82
+ ```bash
83
+ echo "deb http://deb.theforeman.org/ squeeze nightly" > /etc/apt/sources.list.d/foreman.list
84
+ ```
85
+
86
+ and update the keys
87
+
88
+ ```bash
89
+ wget -q http://deb.theforeman.org/foreman.asc -O- | apt-key add -
90
+ ```
91
+
92
+ #### Step 2: install hammer core
93
+
94
+ ```bash
95
+ apt-get update && apt-get install ruby-hammer-cli
96
+ ```
97
+
98
+ #### Step 3: install plugins
99
+ Currently, there are two plugins, both available as deb packages.
100
+
101
+ - commands for managing foreman
102
+
103
+ ```bash
104
+ $ apt-get install ruby-hammer-cli-foreman
105
+ ```
106
+
107
+ - 1:1 bridge to [katello cli](https://github.com/Katello/katello)
108
+
109
+ ```bash
110
+ $ apt-get install ruby-hammer-cli-katello
111
+ ```
112
+
113
+ To install any other hammer plugin just make sure the appropriate gem is installed and follow with the configuration.
114
+
115
+
116
+ ### Installation from GEMs
117
+
118
+ Make sure you have ```gem``` command installed on your system
119
+
120
+ #### Step 1: install hammer core
121
+
122
+ ```bash
123
+ $ gem install hammer_cli
124
+ ```
125
+
126
+ #### Step 2: install plugins
127
+ Currently, there are two plugins, both available on rubygems.org
128
+
129
+ - commands for managing foreman
130
+
131
+ ```bash
132
+ $ gem install hammer_cli_foreman
133
+ ```
134
+
135
+ - 1:1 bridge to [katello cli](https://github.com/Katello/katello)
136
+
137
+ ```bash
138
+ $ gem install hammer_cli_katello
139
+ ```
140
+
141
+ To install any other hammer plugin just install the appropriate gem and follow with the configuration.
142
+
143
+
144
+ ### Installation from SOURCE
145
+
146
+ If you can install hammer from git checkouts, you will just need ```rake``` installed on your system.
147
+ Clone and install CLI core
148
+
149
+ ```bash
150
+ $ git clone https://github.com/theforeman/hammer-cli.git
151
+ $ cd hammer-cli
152
+ $ rake install
153
+ $ cd ..
154
+ ```
155
+
156
+ clone plugin with foreman commands
157
+
158
+ ```bash
159
+ $ git clone https://github.com/theforeman/hammer-cli-foreman.git
160
+ $ cd hammer-cli-foreman
161
+ $ rake install
162
+ $ cd ..
163
+ ```
164
+
165
+ and optionally other plugins via any of the methods mentioned above.
166
+
167
+
168
+ Configuration
169
+ -------------
170
+
171
+ ### Locations
172
+
173
+ Configuration is by default looked for in the following directories, loaded in this order:
174
+
175
+ - ```RbConfig::CONFIG['sysconfdir']/hammer/``` (The actual value depends on your operatingsystem and ruby defaults.)
176
+ - ```/etc/hammer/```
177
+ - ```~/.hammer/```
178
+ - ```./config/``` (config dir in CWD)
179
+ - custom location (file or directory) specified on command line - ```-c CONF_FILE_PATH```
180
+
181
+ In each of these directories hammer is trying to load ```cli_config.yml``` and anything in
182
+ the ```cli.modules.d``` subdirectory which is place for specific configuration of hammer modules.
183
+
184
+ Later directories and files have precedence if they redefine the same option. Files from ```cli.modules.d```
185
+ are loaded in alphabetical order.
186
+
187
+ ### Format
188
+
189
+ Hammer uses yaml formatting for its configuration. The configuration templates are contained in the hammer_cli gem
190
+
191
+ ```bash
192
+ gem contents hammer_cli|grep template.yml
193
+ ```
194
+ and can be copied to one of the locations above and changed as needed. The packaged version of hammer copies the template to /etc for you.
195
+
196
+
197
+ ### Options
198
+
199
+ - ```:log_dir: <path>``` - directory where the logs are stored. The default is ```/var/log/hammer/``` and the log file is named ```hammer.log```
200
+ - ```:log_level: <level>``` - logging level. One of ```debug```, ```info```, ```warning```, ```error```, ```fatal```
201
+ - ```:log_owner: <owner>``` - logfile owner
202
+ - ```:log_group: <group>``` - logfile group
203
+ - ```:log_size: 1048576``` - size in bytes, when exceeded the log rotates. Default is 1MB
204
+ - ```:watch_plain: <bool>``` - turn on/off syntax highlighting of data being logged in debug mode
205
+ - ```:log_api_calls: <bool>``` - turn on logging of the communication with API (data sent and received)
206
+
207
+ In the ```:ui``` section there is
208
+
209
+ - ```:interactive: <bool>``` - whether to ask user for input (pagination, passwords)
210
+ - ```:per_page: <records>``` - number of records per page if server sends paginated data
211
+ - ```:history_file: <path>``` - file where the hammer shell store its history (default is ```~/.hammer_history```)
212
+
213
+
214
+ #### Sample config
215
+
216
+ ```yaml
217
+ :ui:
218
+ :interactive: true
219
+ :per_page: 20
220
+ :history_file: '~/.hammer/history'
221
+
222
+ :watch_plain: false
223
+
224
+ :log_dir: '~/.hammer/log'
225
+ :log_level: 'error'
226
+ :log_api_calls: false
227
+ ```
228
+
229
+ ### Plugins
230
+
231
+ Plugins are disabled by default. To enable plugin create configuration file in ```cli.modules.d``` and add```:enable_plugin: true``` in it. Plugin specific configuration should be nested under plugin's name (without the ```hammer_cli_``` prefix).
232
+
233
+ In the example we assume the gem ```hammer_cli_foreman``` with the Foreman plugin is installed. Then the plugin configuration
234
+ in ```~/.hammer/cli.plugins.d/foreman.yml``` should look as follows:
235
+
236
+ ```yaml
237
+ :foreman:
238
+ :enable_module: true
239
+ :host: 'https://localhost/'
240
+ :username: 'admin'
241
+ :password: 'changeme'
242
+ ```
243
+
244
+ Use the hammer
245
+ --------------
246
+
247
+ Confirm your setup by running ```$ hammer -h``` and check that the desired commands are listed.
248
+
249
+ ```
250
+ $ hammer -h
251
+ Usage:
252
+ hammer [OPTIONS] SUBCOMMAND [ARG] ...
253
+
254
+ Parameters:
255
+ SUBCOMMAND subcommand
256
+ [ARG] ... subcommand arguments
257
+
258
+ Subcommands:
259
+ activation-key Manipulate activation keys.
260
+ architecture Manipulate architectures.
261
+ compute_resource Manipulate compute resources.
262
+ domain Manipulate domains.
263
+ environment Manipulate environments.
264
+ fact Search facts.
265
+ global_parameter Manipulate global parameters.
266
+ gpg manipulate GPG Key actions on the server
267
+ host Manipulate hosts.
268
+ hostgroup Manipulate hostgroups.
269
+ lifecycle-environment manipulate lifecycle_environments on the server
270
+ location Manipulate locations.
271
+ medium Manipulate installation media.
272
+ model Manipulate hardware models.
273
+ organization Manipulate organizations
274
+ os Manipulate operating system.
275
+ partition_table Manipulate partition tables.
276
+ ping get the status of the server
277
+ product Manipulate products.
278
+ provider Manipulate providers
279
+ proxy Manipulate smart proxies.
280
+ puppet_class Search puppet modules.
281
+ report Browse and read reports.
282
+ repository Manipulate repositories
283
+ repository-set manipulate repository sets on the server
284
+ sc_param Manipulate smart class parameters.
285
+ shell Interactive shell
286
+ subnet Manipulate subnets.
287
+ subscription Manipulate subscriptions.
288
+ system manipulate systems on the server
289
+ systemgroup Manipulate system groups
290
+ task Tasks related actions.
291
+ template Manipulate config templates.
292
+ user Manipulate users.
293
+
294
+ Options:
295
+ --autocomplete LINE Get list of possible endings
296
+ --csv Output as CSV (same as --output=csv)
297
+ --csv-separator SEPARATOR Character to separate the values
298
+ --interactive INTERACTIVE Explicitly turn interactive mode on/off
299
+ One of true/false, yes/no, 1/0.
300
+ --output ADAPTER Set output format. One of [base, table, silent, csv]
301
+ --show-ids Show ids of associated resources
302
+ --version show version
303
+ -c, --config CFG_FILE path to custom config file
304
+ -h, --help print help
305
+ -p, --password PASSWORD password to access the remote system
306
+ -u, --username USERNAME username to access the remote system
307
+ -v, --verbose be verbose
308
+ ```
309
+
310
+
311
+ And you are Done. Your hammer client is configured and ready to use.
312
+
313
+
314
+ Autocompletion
315
+ --------------
316
+
317
+ It is necessary to copy the hammer_cli_complete script to the bash_completion.d directory.
318
+
319
+ $ sudo cp hammer-cli/hammer_cli_complete /etc/bash_completion.d/
320
+
321
+ Then after starting a new shell the completion should work.
@@ -1,8 +1,11 @@
1
+ require 'hammer_cli/i18n'
2
+ require 'hammer_cli/exceptions'
1
3
  require 'hammer_cli/utils'
2
4
  require 'hammer_cli/version'
3
5
  require 'hammer_cli/modules'
4
6
  require 'hammer_cli/exit_codes'
5
7
  require 'hammer_cli/settings'
8
+ require 'hammer_cli/connection'
6
9
  require 'hammer_cli/validator'
7
10
  require 'hammer_cli/output'
8
11
  require 'hammer_cli/options/normalizers'
@@ -87,6 +87,19 @@ module HammerCLI
87
87
  super
88
88
  end
89
89
 
90
+ class SortedBuilder < Clamp::Help::Builder
91
+ def add_list(heading, items)
92
+ items.sort! do |a, b|
93
+ a.help[0] <=> b.help[0]
94
+ end
95
+ super(heading, items)
96
+ end
97
+ end
98
+
99
+ def help
100
+ self.class.help(invocation_path, SortedBuilder.new)
101
+ end
102
+
90
103
  def self.output(definition=nil, &block)
91
104
  dsl = HammerCLI::Output::Dsl.new
92
105
  dsl.build &block if block_given?
@@ -116,35 +129,13 @@ module HammerCLI
116
129
  @output_definition
117
130
  end
118
131
 
119
- protected
120
132
 
121
133
  def interactive?
122
- if context[:interactive].nil?
123
- return STDOUT.tty? && (HammerCLI::Settings.get(:ui, :interactive) != false)
124
- else
125
- return context[:interactive]
126
- end
134
+ HammerCLI.interactive?
127
135
  end
128
136
 
129
- def ask_username
130
- ask("Username: ") if interactive?
131
- end
132
-
133
- def ask_password
134
- ask("Password for '%s': " % username) {|q| q.echo = false} if interactive?
135
- end
136
137
 
137
- def username(ask_interactively=true)
138
- context[:username] ||= ENV['FOREMAN_USERNAME'] || HammerCLI::Settings.get(:foreman, :username)
139
- context[:username] ||= ask_username if ask_interactively
140
- context[:username]
141
- end
142
-
143
- def password(ask_interactively=true)
144
- context[:password] ||= ENV['FOREMAN_PASSWORD'] || HammerCLI::Settings.get(:foreman, :password)
145
- context[:password] ||= ask_password if ask_interactively
146
- context[:password]
147
- end
138
+ protected
148
139
 
149
140
  def print_record(definition, record)
150
141
  output.print_record(definition, record)