hammer_cli 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/bin/hammer +1 -0
  3. data/doc/release_notes.md +5 -0
  4. data/lib/hammer_cli.rb +1 -0
  5. data/lib/hammer_cli/apipie/command.rb +8 -0
  6. data/lib/hammer_cli/apipie/option_builder.rb +4 -4
  7. data/lib/hammer_cli/main.rb +7 -0
  8. data/lib/hammer_cli/output/adapter/abstract.rb +5 -0
  9. data/lib/hammer_cli/output/adapter/base.rb +2 -2
  10. data/lib/hammer_cli/output/adapter/csv.rb +1 -1
  11. data/lib/hammer_cli/output/adapter/json.rb +2 -2
  12. data/lib/hammer_cli/output/adapter/table.rb +5 -5
  13. data/lib/hammer_cli/output/adapter/yaml.rb +2 -2
  14. data/lib/hammer_cli/version.rb +1 -1
  15. data/locale/ca/LC_MESSAGES/hammer-cli.mo +0 -0
  16. data/locale/de/LC_MESSAGES/hammer-cli.mo +0 -0
  17. data/locale/en/LC_MESSAGES/hammer-cli.mo +0 -0
  18. data/locale/en_GB/LC_MESSAGES/hammer-cli.mo +0 -0
  19. data/locale/es/LC_MESSAGES/hammer-cli.mo +0 -0
  20. data/locale/fr/LC_MESSAGES/hammer-cli.mo +0 -0
  21. data/locale/it/LC_MESSAGES/hammer-cli.mo +0 -0
  22. data/locale/ja/LC_MESSAGES/hammer-cli.mo +0 -0
  23. data/locale/ko/LC_MESSAGES/hammer-cli.mo +0 -0
  24. data/locale/pt_BR/LC_MESSAGES/hammer-cli.mo +0 -0
  25. data/locale/ru/LC_MESSAGES/hammer-cli.mo +0 -0
  26. data/locale/zh_CN/LC_MESSAGES/hammer-cli.mo +0 -0
  27. data/locale/zh_TW/LC_MESSAGES/hammer-cli.mo +0 -0
  28. data/test/unit/apipie/command_test.rb +13 -0
  29. data/test/unit/apipie/option_builder_test.rb +6 -1
  30. data/test/unit/fixtures/apipie/documented.json +10 -1
  31. data/test/unit/output/adapter/base_test.rb +25 -0
  32. data/test/unit/output/adapter/csv_test.rb +24 -0
  33. data/test/unit/output/adapter/json_test.rb +25 -0
  34. data/test/unit/output/adapter/table_test.rb +31 -0
  35. data/test/unit/output/adapter/yaml_test.rb +25 -0
  36. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0aa589ebe2589ead222c05b6b8a1de324f3efdb5
4
- data.tar.gz: 1068b381dbe8685c2a1d7bc0168513f5e48ccce9
3
+ metadata.gz: 4a07530fca2559a9ab75f4e287a46ede2a38d3cd
4
+ data.tar.gz: '0088bd037fda97450755a19d7479e6994549dc96'
5
5
  SHA512:
6
- metadata.gz: c7153a9ebaab813ef8ea1061461efd60c1e357f5445187762203aed5055bb1e38eac86d787f4bec013e5cc78e84afd40fbb3ac81cef8a3b1844732356a7f864f
7
- data.tar.gz: ff4d24d0067d7e500ee573bfb82531637c67f557d1ef9745d4b2587ed31e9edbac0aa6d47eb79778e97658627495f3327b5cac0626d56ea04dfd8a27c7c1b8ba
6
+ metadata.gz: 1b0853ed83f5ceb835fed41d833de7d2abbb789a31ed5b3fff8d35a96c82327bc5d3b2746088d3eb895a61f93ac7da22fc254cf4dfc934455fd3b533a60c62c1
7
+ data.tar.gz: 5c87348a2eebc66ccd5207c0c5aeaa43dbb3c6277a0d977a5e3c8f043e798cee71f2a3a81f57a3af77c6a408fcbe75e63335121402c5de65dd610a76c188f03a
data/bin/hammer CHANGED
@@ -30,6 +30,7 @@ class PreParser < Clamp::Command
30
30
  option ["--csv"], :flag, "Output as CSV (same as --output=csv)"
31
31
  option ["--output"], "ADAPTER", "Set output format"
32
32
  option ["--no-headers"], :flag, "Hide headers from output"
33
+ option ["--output-file"], "OUTPUT_FILE", "Path to custom output file"
33
34
  option ["--csv-separator"], "SEPARATOR", "Character to separate the values"
34
35
  option ["--autocomplete"], "LINE", "Get list of possible endings"
35
36
  option ["--verify-ssl"], "VERIFY_SSL", "Configure SSL verification of remote system" do |value|
@@ -1,5 +1,10 @@
1
1
  Release notes
2
2
  =============
3
+ ### 0.13.0 (2018-05-09)
4
+ * Hammer CSV output saved as a file ([PR #254](https://github.com/theforeman/hammer-cli/pull/254)) ([#11586](http://projects.theforeman.org/issues/11586))
5
+ * correct parsing of enum types ([PR #272](https://github.com/theforeman/hammer-cli/pull/272)) ([#22752](http://projects.theforeman.org/issues/22752))
6
+ * require logger ([PR #273](https://github.com/theforeman/hammer-cli/pull/273)) ([#22906](http://projects.theforeman.org/issues/22906))
7
+ * Better help for unsupported hammer commands ([PR #257](https://github.com/theforeman/hammer-cli/pull/257)) ([#18532](http://projects.theforeman.org/issues/18532))
3
8
 
4
9
  ### 0.12.0 (2018-02-19)
5
10
  * Tests for message formats ([PR #266](https://github.com/theforeman/hammer-cli/pull/266)) ([#7451](http://projects.theforeman.org/issues/7451))
@@ -5,6 +5,7 @@ require 'hammer_cli/version'
5
5
  require 'hammer_cli/modules'
6
6
  require 'hammer_cli/exit_codes'
7
7
  require 'hammer_cli/settings'
8
+ require 'hammer_cli/logger'
8
9
  require 'hammer_cli/ca_cert_manager'
9
10
  require 'hammer_cli/connection'
10
11
  require 'hammer_cli/validator'
@@ -36,6 +36,14 @@ module HammerCLI::Apipie
36
36
  return HammerCLI::EX_OK
37
37
  end
38
38
 
39
+ def help
40
+ help_str = super
41
+ if !resource || (!action.nil? && !resource.has_action?(action))
42
+ help_str << "\n" + _("Unfortunately the server does not support such operation.") + "\n"
43
+ end
44
+ help_str
45
+ end
46
+
39
47
  protected
40
48
 
41
49
  def send_request
@@ -64,14 +64,14 @@ module HammerCLI::Apipie
64
64
  def option_opts(param)
65
65
  opts = {}
66
66
  opts[:required] = true if (param.required? and require_options?)
67
- if param.expected_type.to_s == 'array' || param.validator =~ /Array/i
67
+ if param.expected_type.to_s == 'array'
68
68
  opts[:format] = HammerCLI::Options::Normalizers::List.new
69
- elsif param.expected_type.to_s == 'boolean' || param.validator =~ /Boolean/i
69
+ elsif param.expected_type.to_s == 'boolean' || param.validator.to_s == 'boolean'
70
70
  opts[:format] = HammerCLI::Options::Normalizers::Bool.new
71
- elsif param.validator =~ /Must be one of: (.*)\./
71
+ elsif param.expected_type.to_s == 'string' && param.validator =~ /Must be one of: (.*)\./
72
72
  allowed = $1.split(/,\ ?/).map { |val| val.gsub(/<[^>]*>/i,'') }
73
73
  opts[:format] = HammerCLI::Options::Normalizers::Enum.new(allowed)
74
- elsif param.expected_type.to_s == 'numeric' || param.validator =~ /Number/i || param.validator =~ /Integer/i
74
+ elsif param.expected_type.to_s == 'numeric'
75
75
  opts[:format] = HammerCLI::Options::Normalizers::Number.new
76
76
  end
77
77
  opts[:attribute_name] = HammerCLI.option_accessor_name(param.name)
@@ -44,6 +44,13 @@ module HammerCLI
44
44
  option ["--output"], "ADAPTER", _("Set output format. One of [%s]") %
45
45
  HammerCLI::Output::Output.adapters.keys.join(', '),
46
46
  :context_target => :adapter
47
+ option ["--output-file"], "OUTPUT_FILE", _("Path to custom output file") do |filename|
48
+ begin
49
+ context[:output_file] = File.new(filename, 'w')
50
+ rescue SystemCallError, IOError => e
51
+ raise ArgumentError, e
52
+ end
53
+ end
47
54
  option ["--csv-separator"], "SEPARATOR", _("Character to separate the values"),
48
55
  :context_target => :csv_separator
49
56
 
@@ -64,6 +64,11 @@ module HammerCLI::Output::Adapter
64
64
  Abstract.data_for_field(field, record)
65
65
  end
66
66
 
67
+ def output_stream
68
+ return @context[:output_file] if @context.has_key?(:output_file)
69
+ $stdout
70
+ end
71
+
67
72
  private
68
73
 
69
74
  def filter_formatters(formatters_map)
@@ -14,8 +14,8 @@ module HammerCLI::Output::Adapter
14
14
 
15
15
  def print_collection(fields, collection)
16
16
  collection.each do |data|
17
- puts render_fields(fields, data)
18
- puts
17
+ output_stream.puts render_fields(fields, data)
18
+ output_stream.puts
19
19
  end
20
20
  end
21
21
 
@@ -168,7 +168,7 @@ module HammerCLI::Output::Adapter
168
168
  csv << Cell.values(headers, row)
169
169
  end
170
170
  end
171
- puts csv_string
171
+ output_stream.puts csv_string
172
172
  end
173
173
 
174
174
  def print_message(msg, msg_params={})
@@ -3,12 +3,12 @@ module HammerCLI::Output::Adapter
3
3
 
4
4
  def print_record(fields, record)
5
5
  result = prepare_collection(fields, [record].flatten(1))
6
- puts JSON.pretty_generate(result.first)
6
+ output_stream.puts JSON.pretty_generate(result.first)
7
7
  end
8
8
 
9
9
  def print_collection(fields, collection)
10
10
  result = prepare_collection(fields, collection)
11
- puts JSON.pretty_generate(result)
11
+ output_stream.puts JSON.pretty_generate(result)
12
12
  end
13
13
 
14
14
  def print_message(msg, msg_params={})
@@ -36,21 +36,21 @@ module HammerCLI::Output::Adapter
36
36
 
37
37
  line = hline_bits.join(LINE_SEPARATOR)
38
38
  unless @context[:no_headers]
39
- puts line
40
- puts header_bits.join(COLUMN_SEPARATOR)
41
- puts line
39
+ output_stream.puts line
40
+ output_stream.puts header_bits.join(COLUMN_SEPARATOR)
41
+ output_stream.puts line
42
42
  end
43
43
 
44
44
  formatted_collection.collect do |row|
45
45
  row_bits = fields.map do |f|
46
46
  normalize_column(widths[f.label], row[f.label] || "")
47
47
  end
48
- puts row_bits.join(COLUMN_SEPARATOR)
48
+ output_stream.puts row_bits.join(COLUMN_SEPARATOR)
49
49
  end
50
50
 
51
51
  # print closing line only when the table isn't empty
52
52
  # and there is no --no-headers option
53
- puts line unless formatted_collection.empty? || @context[:no_headers]
53
+ output_stream.puts line unless formatted_collection.empty? || @context[:no_headers]
54
54
 
55
55
  if collection.meta.pagination_set? && collection.count < collection.meta.subtotal
56
56
  pages = (collection.meta.subtotal.to_f/collection.meta.per_page).ceil
@@ -3,12 +3,12 @@ module HammerCLI::Output::Adapter
3
3
 
4
4
  def print_record(fields, record)
5
5
  result = prepare_collection(fields, [record].flatten(1))
6
- puts YAML.dump(result.first)
6
+ output_stream.puts YAML.dump(result.first)
7
7
  end
8
8
 
9
9
  def print_collection(fields, collection)
10
10
  result = prepare_collection(fields, collection)
11
- puts YAML.dump(result)
11
+ output_stream.puts YAML.dump(result)
12
12
  end
13
13
 
14
14
  def print_message(msg, msg_params={})
@@ -1,5 +1,5 @@
1
1
  module HammerCLI
2
2
  def self.version
3
- @version ||= Gem::Version.new '0.12.0'
3
+ @version ||= Gem::Version.new '0.13.0'
4
4
  end
5
5
  end
@@ -29,11 +29,24 @@ describe HammerCLI::Apipie::Command do
29
29
  class CommandC < CommandA
30
30
  end
31
31
 
32
+ class CommandUnsupp < HammerCLI::Apipie::Command
33
+ resource :architectures, :unsupptest
34
+ end
35
+
32
36
  let(:ctx) { { :adapter => :silent, :interactive => false } }
33
37
  let(:cmd_class) { HammerCLI::Apipie::Command.dup }
34
38
  let(:cmd) { cmd_class.new("", ctx) }
35
39
  let(:cmd_run) { cmd.run([]) }
36
40
 
41
+ context "unsupported commands" do
42
+ let(:cmd_class) { CommandUnsupp.dup }
43
+ let(:cmd) { cmd_class.new("unsupported", ctx) }
44
+ it "should print help for unsupported command" do
45
+ assert_match /.*Unfortunately the server does not support such operation.*/, cmd.help
46
+ end
47
+
48
+ end
49
+
37
50
  context "setting resources" do
38
51
 
39
52
  it "should set resource and action together" do
@@ -90,7 +90,12 @@ describe HammerCLI::Apipie::OptionBuilder do
90
90
  it "should set enum normalizer and handle coded values" do
91
91
  enum_option = options.find {|o| o.attribute_name == HammerCLI.option_accessor_name("coded_enum_param") }
92
92
  enum_option.value_formatter.class.must_equal HammerCLI::Options::Normalizers::Enum
93
- enum_option.value_formatter.allowed_values.sort.must_equal ["tomas", "tereza"].sort
93
+ enum_option.value_formatter.allowed_values.sort.must_equal ["array", "boolean", "hash", "integer", "json", "real", "string", "yaml"].sort
94
+ end
95
+
96
+ it "should set list normalizer for array of nested elements" do
97
+ array_option = options.find {|o| o.attribute_name == HammerCLI.option_accessor_name("nested_elements_param") }
98
+ array_option.value_formatter.class.must_equal HammerCLI::Options::Normalizers::List
94
99
  end
95
100
 
96
101
  it "should set number normalizer" do
@@ -148,11 +148,20 @@
148
148
  "description": "",
149
149
  "required": false
150
150
  },
151
+ {
152
+ "name": "nested_elements_param",
153
+ "full_name": "documented[nested_elements_param]",
154
+ "allow_nil": true,
155
+ "validator": "Must be an Array of nested elements",
156
+ "expected_type": "array",
157
+ "description": "",
158
+ "required": false
159
+ },
151
160
  {
152
161
  "name": "coded_enum_param",
153
162
  "full_name": "documented[coded_enum_param]",
154
163
  "allow_nil": true,
155
- "validator": "Must be one of: <code>tomas</code>, <code>tereza</code>.",
164
+ "validator": "Must be one of: <code>string</code>, <code>boolean</code>, <code>integer</code>, <code>real</code>, <code>array</code>, <code>hash</code>, <code>yaml</code>, <code>json</code>.",
156
165
  "expected_type": "string",
157
166
  "description": "",
158
167
  "required": false
@@ -195,6 +195,31 @@ describe HammerCLI::Output::Adapter::Base do
195
195
 
196
196
  end
197
197
 
198
+ context "output_stream" do
199
+
200
+ let(:tempfile) { Tempfile.new("output_stream_base_test_temp") }
201
+ let(:context) { {:output_file => tempfile} }
202
+
203
+ it "should not print to stdout when --output-file is set" do
204
+ fields = [name]
205
+
206
+ proc { adapter.print_collection(fields, data) }.must_output("")
207
+ end
208
+
209
+ it "should print to file if --output-file is set" do
210
+ fields = [name]
211
+ expected_output = [
212
+ "Name: John",
213
+ "\n"
214
+ ].join("\n")
215
+
216
+ adapter.print_collection(fields, data)
217
+ tempfile.close
218
+ IO.read(tempfile.path).must_equal(expected_output)
219
+ end
220
+
221
+ end
222
+
198
223
  end
199
224
 
200
225
  end
@@ -203,6 +203,30 @@ describe HammerCLI::Output::Adapter::CSValues do
203
203
  out.must_match(/.*NIL.*/)
204
204
  end
205
205
  end
206
+
207
+ context "output_stream" do
208
+
209
+ let(:tempfile) { Tempfile.new("output_stream_csv_test_temp") }
210
+ let(:context) { {:output_file => tempfile} }
211
+ let(:adapter) { HammerCLI::Output::Adapter::CSValues.new(context, HammerCLI::Output::Output.formatters) }
212
+
213
+ it "should not print to stdout when --output-file is set" do
214
+ fields = [field_name]
215
+
216
+ proc { adapter.print_collection(fields, data) }.must_output("")
217
+ end
218
+
219
+ it "should print to file if --output-file is set" do
220
+ fields = [field_name]
221
+ expected_output = "Name\nJohn Doe\n"
222
+
223
+ adapter.print_collection(fields, data)
224
+ tempfile.close
225
+ IO.read(tempfile.path).must_equal(expected_output)
226
+ end
227
+
228
+ end
229
+
206
230
  end
207
231
 
208
232
  context "print message" do
@@ -243,6 +243,31 @@ describe HammerCLI::Output::Adapter::Json do
243
243
 
244
244
  end
245
245
 
246
+ context "output_stream" do
247
+
248
+ let(:tempfile) { Tempfile.new("output_stream_json_test_temp") }
249
+ let(:context) { {:output_file => tempfile} }
250
+
251
+ it "should not print to stdout when --output-file is set" do
252
+ fields = [name]
253
+
254
+ proc { adapter.print_collection(fields, data) }.must_output("")
255
+ end
256
+
257
+ it "should print to file if --output-file is set" do
258
+ fields = [name]
259
+ hash = [{
260
+ 'Name' => 'John'
261
+ }]
262
+ expected_output = JSON.pretty_generate(hash) + "\n"
263
+
264
+ adapter.print_collection(fields, data)
265
+ tempfile.close
266
+ IO.read(tempfile.path).must_equal(expected_output)
267
+ end
268
+
269
+ end
270
+
246
271
  end
247
272
 
248
273
  end
@@ -349,6 +349,37 @@ describe HammerCLI::Output::Adapter::Table do
349
349
  end
350
350
 
351
351
  end
352
+
353
+ context "output_stream" do
354
+
355
+ let(:tempfile) { Tempfile.new("output_stream_table_test_temp") }
356
+ let(:context) { {:output_file => tempfile} }
357
+ let(:adapter) { HammerCLI::Output::Adapter::Table.new(context, HammerCLI::Output::Output.formatters) }
358
+
359
+ it "should not print to stdout when --output-file is set" do
360
+ fields = [field_firstname]
361
+
362
+ proc { adapter.print_collection(fields, data) }.must_output("")
363
+ end
364
+
365
+ it "should print to file if --output-file is set" do
366
+ fields = [field_firstname]
367
+ expected_output = [
368
+ "---------",
369
+ "FIRSTNAME",
370
+ "---------",
371
+ "John ",
372
+ "---------",
373
+ ""
374
+ ].join("\n")
375
+
376
+ adapter.print_collection(fields, data)
377
+ tempfile.close
378
+ IO.read(tempfile.path).must_equal(expected_output)
379
+ end
380
+
381
+ end
382
+
352
383
  end
353
384
 
354
385
  end
@@ -240,6 +240,31 @@ describe HammerCLI::Output::Adapter::Yaml do
240
240
 
241
241
  end
242
242
 
243
+ context "output_stream" do
244
+
245
+ let(:tempfile) { Tempfile.new("output_stream_yaml_test_temp") }
246
+ let(:context) { {:output_file => tempfile} }
247
+
248
+ it "should not print to stdout when --output-file is set" do
249
+ fields = [name]
250
+
251
+ proc { adapter.print_collection(fields, data) }.must_output("")
252
+ end
253
+
254
+ it "should print to file if --output-file is set" do
255
+ fields = [name]
256
+ hash = [{
257
+ 'Name' => 'John'
258
+ }]
259
+ expected_output = YAML.dump(hash)
260
+
261
+ adapter.print_collection(fields, data)
262
+ tempfile.close
263
+ IO.read(tempfile.path).must_equal(expected_output)
264
+ end
265
+
266
+ end
267
+
243
268
  end
244
269
 
245
270
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hammer_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Bačovský
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-02-19 00:00:00.000000000 Z
12
+ date: 2018-05-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: clamp
@@ -488,7 +488,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
488
488
  version: '0'
489
489
  requirements: []
490
490
  rubyforge_project:
491
- rubygems_version: 2.6.14
491
+ rubygems_version: 2.6.14.1
492
492
  signing_key:
493
493
  specification_version: 4
494
494
  summary: Universal command-line interface