haveapi-client 0.19.3 → 0.21.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/Rakefile +0 -1
  4. data/haveapi-client.gemspec +7 -10
  5. data/lib/haveapi/cli/action_state.rb +50 -51
  6. data/lib/haveapi/cli/authentication/base.rb +4 -9
  7. data/lib/haveapi/cli/authentication/basic.rb +3 -1
  8. data/lib/haveapi/cli/authentication/token.rb +7 -8
  9. data/lib/haveapi/cli/cli.rb +115 -127
  10. data/lib/haveapi/cli/command.rb +2 -4
  11. data/lib/haveapi/cli/commands/action_state_wait.rb +9 -9
  12. data/lib/haveapi/cli/example_formatter.rb +8 -8
  13. data/lib/haveapi/cli/output_formatter.rb +39 -36
  14. data/lib/haveapi/cli/utils.rb +5 -5
  15. data/lib/haveapi/cli.rb +1 -1
  16. data/lib/haveapi/client/action.rb +17 -20
  17. data/lib/haveapi/client/action_state.rb +3 -7
  18. data/lib/haveapi/client/authentication/base.rb +4 -7
  19. data/lib/haveapi/client/authentication/basic.rb +2 -2
  20. data/lib/haveapi/client/authentication/noauth.rb +0 -1
  21. data/lib/haveapi/client/authentication/token.rb +28 -27
  22. data/lib/haveapi/client/client.rb +12 -6
  23. data/lib/haveapi/client/communicator.rb +33 -35
  24. data/lib/haveapi/client/exceptions.rb +5 -9
  25. data/lib/haveapi/client/parameters/resource.rb +1 -0
  26. data/lib/haveapi/client/parameters/typed.rb +3 -5
  27. data/lib/haveapi/client/params.rb +8 -8
  28. data/lib/haveapi/client/resource.rb +12 -13
  29. data/lib/haveapi/client/resource_instance.rb +71 -72
  30. data/lib/haveapi/client/resource_instance_list.rb +2 -1
  31. data/lib/haveapi/client/response.rb +8 -8
  32. data/lib/haveapi/client/validator.rb +7 -8
  33. data/lib/haveapi/client/validators/confirmation.rb +1 -0
  34. data/lib/haveapi/client/validators/length.rb +1 -0
  35. data/lib/haveapi/client/validators/numericality.rb +2 -1
  36. data/lib/haveapi/client/validators/presence.rb +1 -0
  37. data/lib/haveapi/client/version.rb +2 -2
  38. data/lib/haveapi/client.rb +2 -2
  39. data/lib/restclient_ext/resource.rb +5 -5
  40. data/shell.nix +1 -1
  41. metadata +15 -43
@@ -12,9 +12,8 @@ module HaveAPI::CLI
12
12
 
13
13
  def run
14
14
  c = new
15
-
16
15
  rescue Interrupt
17
- warn "Interrupted"
16
+ warn 'Interrupted'
18
17
  exit(false)
19
18
  end
20
19
 
@@ -38,7 +37,7 @@ module HaveAPI::CLI
38
37
  connect_api unless @api
39
38
 
40
39
  if @action
41
- method(@action.first).call( * @action[1..-1] )
40
+ method(@action.first).call(* @action[1..])
42
41
  exit
43
42
  end
44
43
 
@@ -51,7 +50,7 @@ module HaveAPI::CLI
51
50
 
52
51
  resources = args[0].split('.')
53
52
 
54
- if cmd = find_command(resources, args[1])
53
+ if (cmd = find_command(resources, args[1]))
55
54
  authenticate if @auth
56
55
  c = cmd.new(@opts, HaveAPI::Client::Client.new(nil, communicator: @api))
57
56
 
@@ -72,21 +71,21 @@ module HaveAPI::CLI
72
71
  end
73
72
  end
74
73
 
75
- if sep = ARGV.index('--')
76
- cmd_opt.parse!(ARGV[sep+1..-1])
74
+ if (sep = ARGV.index('--'))
75
+ cmd_opt.parse!(ARGV[sep + 1..])
77
76
  end
78
77
 
79
- c.exec(args[2..-1] || [])
78
+ c.exec(args[2..] || [])
80
79
 
81
80
  exit
82
81
  end
83
82
 
84
83
  if args.count == 1
85
84
  describe_resource(resources)
86
- exit(true)
85
+ exit
87
86
  end
88
87
 
89
- action = @api.get_action(resources, args[1].to_sym, args[2..-1])
88
+ action = @api.get_action(resources, args[1].to_sym, args[2..])
90
89
 
91
90
  unless action
92
91
  warn "Resource or action '#{args[0]} #{args[1]}' not found"
@@ -97,24 +96,23 @@ module HaveAPI::CLI
97
96
  if authenticate(action) && !action.unresolved_args?
98
97
  begin
99
98
  action.update_description(@api.describe_action(action))
100
-
101
99
  rescue RestClient::ResourceNotFound => e
102
100
  format_errors(action, 'Object not found', {})
103
101
  exit(false)
104
102
  end
105
103
  end
106
104
 
107
- @selected_params = @opts[:output] ? @opts[:output].split(',').uniq
108
- : nil
105
+ @selected_params = if @opts[:output]
106
+ @opts[:output].split(',').uniq
107
+ end
109
108
 
110
109
  @input_params = parameters(action)
111
110
 
112
111
  includes = build_includes(action) if @selected_params
113
- @input_params[:meta] = { includes: includes } if includes
112
+ @input_params[:meta] = { includes: } if includes
114
113
 
115
114
  begin
116
115
  ret = action.execute(@input_params, raw: @opts[:raw])
117
-
118
116
  rescue HaveAPI::Client::ValidationError => e
119
117
  format_errors(action, 'input parameters not valid', e.errors)
120
118
  exit(false)
@@ -128,30 +126,30 @@ module HaveAPI::CLI
128
126
  exit(false)
129
127
  end
130
128
 
131
- if action.blocking?
132
- res = HaveAPI::Client::Response.new(action, ret)
129
+ return unless action.blocking?
133
130
 
134
- if res.meta[:action_state_id]
135
- state = ActionState.new(
136
- @opts,
137
- HaveAPI::Client::Client.new(@api.url, communicator: @api, block: false),
138
- res.meta[:action_state_id]
139
- )
131
+ res = HaveAPI::Client::Response.new(action, ret)
140
132
 
141
- if @opts[:block]
142
- puts
143
- action_ret = state.wait_for_completion(timeout: @opts[:timeout])
133
+ return unless res.meta[:action_state_id]
144
134
 
145
- if action_ret.nil?
146
- warn "Timeout"
147
- exit(false)
148
- end
135
+ state = ActionState.new(
136
+ @opts,
137
+ HaveAPI::Client::Client.new(@api.url, communicator: @api, block: false),
138
+ res.meta[:action_state_id]
139
+ )
149
140
 
150
- else
151
- puts
152
- state.print_help
153
- end
141
+ puts
142
+
143
+ if @opts[:block]
144
+ action_ret = state.wait_for_completion(timeout: @opts[:timeout])
145
+
146
+ if action_ret.nil?
147
+ warn 'Timeout'
148
+ exit(false)
154
149
  end
150
+
151
+ else
152
+ state.print_help
155
153
  end
156
154
  end
157
155
 
@@ -163,7 +161,7 @@ module HaveAPI::CLI
163
161
  options = {
164
162
  client: default_url,
165
163
  block: true,
166
- verbose: false,
164
+ verbose: false
167
165
  }
168
166
 
169
167
  @global_opt = OptionParser.new do |opts|
@@ -211,11 +209,11 @@ module HaveAPI::CLI
211
209
  options[:layout] = :columns
212
210
  end
213
211
 
214
- opts.on('-H', '--no-header', 'Hide header row') do |h|
212
+ opts.on('-H', '--no-header', 'Hide header row') do |_h|
215
213
  options[:header] = false
216
214
  end
217
215
 
218
- opts.on('-L', '--list-parameters', 'List output parameters') do |l|
216
+ opts.on('-L', '--list-parameters', 'List output parameters') do |_l|
219
217
  options[:list_output] = true
220
218
  end
221
219
 
@@ -260,9 +258,9 @@ module HaveAPI::CLI
260
258
  end
261
259
 
262
260
  opts.on(
263
- '--timeout SEC',
264
- Float,
265
- 'Fail when the action does not finish within the timeout'
261
+ '--timeout SEC',
262
+ Float,
263
+ 'Fail when the action does not finish within the timeout'
266
264
  ) do |v|
267
265
  options[:timeout] = v.to_f
268
266
  end
@@ -291,11 +289,9 @@ module HaveAPI::CLI
291
289
  args = []
292
290
 
293
291
  ARGV.each do |arg|
294
- if arg == '--'
295
- break
296
- else
297
- args << arg
298
- end
292
+ break if arg == '--'
293
+
294
+ args << arg
299
295
  end
300
296
 
301
297
  @global_opt.parse!(args)
@@ -304,11 +300,11 @@ module HaveAPI::CLI
304
300
  cfg = server_config(options[:client])
305
301
  connect_api(url: options[:client], version: options[:version]) unless @api
306
302
 
307
- if m = cfg[:last_auth]
303
+ if (m = cfg[:last_auth])
308
304
  @auth = Cli.auth_methods[m].new(
309
305
  @api,
310
306
  @api.describe_api(options[:version])[:authentication][m],
311
- cfg[:auth][m],
307
+ cfg[:auth][m]
312
308
  )
313
309
  end
314
310
  end
@@ -328,12 +324,12 @@ module HaveAPI::CLI
328
324
  opts.on(param_option(name, p), p[:description] || p[:label] || ' ') do |*args|
329
325
  arg = args.first
330
326
 
331
- if arg.nil?
332
- options[name] = read_param(name, p)
327
+ options[name] = if arg.nil?
328
+ read_param(name, p)
333
329
 
334
- else
335
- options[name] = args.first
336
- end
330
+ else
331
+ args.first
332
+ end
337
333
  end
338
334
  end
339
335
  end
@@ -353,7 +349,7 @@ module HaveAPI::CLI
353
349
  puts 'Output parameters:'
354
350
 
355
351
  action.params.each do |name, param|
356
- puts sprintf(" %-32s %s", name, param[:description])
352
+ puts format(' %-32s %s', name, param[:description])
357
353
  end
358
354
 
359
355
  print_examples(action)
@@ -367,7 +363,7 @@ module HaveAPI::CLI
367
363
 
368
364
  return {} unless sep
369
365
 
370
- @action_opt.parse!(ARGV[sep+1..-1])
366
+ @action_opt.parse!(ARGV[sep + 1..])
371
367
 
372
368
  options
373
369
  end
@@ -375,7 +371,7 @@ module HaveAPI::CLI
375
371
  def list_versions
376
372
  desc = @api.available_versions
377
373
 
378
- desc[:versions].each do |v, _|
374
+ desc[:versions].each_key do |v|
379
375
  next if v == :default
380
376
 
381
377
  v_int = v.to_s.to_i
@@ -384,7 +380,7 @@ module HaveAPI::CLI
384
380
  end
385
381
  end
386
382
 
387
- def list_auth(v=nil)
383
+ def list_auth(v = nil)
388
384
  desc = @api.describe_api(v)
389
385
 
390
386
  desc[:authentication].each_key do |auth|
@@ -392,7 +388,7 @@ module HaveAPI::CLI
392
388
  end
393
389
  end
394
390
 
395
- def list_resources(v=nil)
391
+ def list_resources(v = nil)
396
392
  desc = @api.describe_api(v)
397
393
 
398
394
  sort_by_key(desc[:resources]).each do |resource, children|
@@ -400,7 +396,7 @@ module HaveAPI::CLI
400
396
  end
401
397
  end
402
398
 
403
- def list_actions(v=nil)
399
+ def list_actions(v = nil)
404
400
  desc = @api.describe_api(v)
405
401
 
406
402
  sort_by_key(desc[:resources]).each do |resource, children|
@@ -450,16 +446,16 @@ module HaveAPI::CLI
450
446
 
451
447
  puts '' if !desc[:resources].empty? && !desc[:actions].empty?
452
448
 
453
- unless desc[:actions].empty?
454
- puts 'Actions:'
449
+ return if desc[:actions].empty?
455
450
 
456
- desc[:actions].keys.sort.each do |a|
457
- puts " #{a}"
458
- end
451
+ puts 'Actions:'
452
+
453
+ desc[:actions].keys.sort.each do |a|
454
+ puts " #{a}"
459
455
  end
460
456
  end
461
457
 
462
- def nested_resource(prefix, children, actions=false)
458
+ def nested_resource(prefix, children, actions = false)
463
459
  if actions
464
460
  children[:actions].keys.sort.each do |action|
465
461
  puts "#{prefix}##{action}"
@@ -468,8 +464,8 @@ module HaveAPI::CLI
468
464
  puts prefix
469
465
  end
470
466
 
471
- sort_by_key(children[:resources]).each do |resource, children|
472
- nested_resource("#{prefix}.#{resource}", children, actions)
467
+ sort_by_key(children[:resources]).each do |resource, grandchildren|
468
+ nested_resource("#{prefix}.#{resource}", grandchildren, actions)
473
469
  end
474
470
  end
475
471
 
@@ -480,10 +476,10 @@ module HaveAPI::CLI
480
476
  puts
481
477
  puts 'Commands:'
482
478
  Cli.commands.each do |cmd|
483
- puts sprintf(
484
- '%-36s %s',
485
- "#{cmd.resource.join('.')} #{cmd.action} #{cmd.args}",
486
- cmd.desc
479
+ puts format(
480
+ '%-36s %s',
481
+ "#{cmd.resource.join('.')} #{cmd.action} #{cmd.args}",
482
+ cmd.desc
487
483
  )
488
484
  end
489
485
  end
@@ -493,10 +489,10 @@ module HaveAPI::CLI
493
489
  end
494
490
 
495
491
  def print_examples(action)
496
- unless action.examples.empty?
497
- puts "\nExamples:\n"
498
- ExampleFormatter.format_examples(self, action)
499
- end
492
+ return if action.examples.empty?
493
+
494
+ puts "\nExamples:\n"
495
+ ExampleFormatter.format_examples(self, action)
500
496
  end
501
497
 
502
498
  def format_output(action, response, out = $>)
@@ -510,7 +506,7 @@ module HaveAPI::CLI
510
506
  namespace = action.namespace(:output).to_sym
511
507
 
512
508
  if action.output_layout.to_sym == :custom
513
- return PP.pp(response[namespace], out)
509
+ return PP.pp(response[namespace], out)
514
510
  end
515
511
 
516
512
  cols = []
@@ -522,37 +518,35 @@ module HaveAPI::CLI
522
518
 
523
519
  # Fetching an associated attribute
524
520
  if raw_name.to_s.index('.')
525
- parts = raw_name.to_s.split('.').map! { |v| v.to_sym }
521
+ parts = raw_name.to_s.split('.').map!(&:to_sym)
526
522
  name = parts.first.to_sym
527
523
 
528
524
  top = action.params
529
525
 
530
526
  parts.each do |part|
531
- fail "'#{part}' not found" unless top.has_key?(part)
527
+ raise "'#{part}' not found" unless top.has_key?(part)
532
528
 
533
- if top[part][:type] == 'Resource'
534
- param = top[part]
535
- top = @api.get_action(top[part][:resource], :show, []).params
529
+ param = top[part]
536
530
 
537
- else
538
- param = top[part]
539
- break
540
- end
531
+ break if param[:type] != 'Resource'
532
+
533
+ top = @api.get_action(param[:resource], :show, []).params
541
534
  end
542
535
 
543
- col[:display] = Proc.new do |r|
536
+ col[:display] = proc do |r|
544
537
  next '' unless r
545
538
 
546
539
  top = r
547
- parts[1..-1].each do |part|
548
- fail "'#{part}' not found" unless top.has_key?(part)
540
+ parts[1..].each do |part|
541
+ raise "'#{part}' not found" unless top.has_key?(part)
549
542
  break if top[part].nil?
543
+
550
544
  top = top[part]
551
545
  end
552
546
 
553
547
  case param[:type]
554
548
  when 'Resource'
555
- "#{top[ param[:value_label].to_sym ]} (##{top[ param[:value_id].to_sym ]})"
549
+ "#{top[param[:value_label].to_sym]} (##{top[param[:value_id].to_sym]})"
556
550
 
557
551
  when 'Datetime'
558
552
  format_date(top)
@@ -567,12 +561,13 @@ module HaveAPI::CLI
567
561
  else # directly accessible parameter
568
562
  name = raw_name.to_sym
569
563
  param = action.params[name]
570
- fail "parameter '#{name}' does not exist" if param.nil?
564
+ raise "parameter '#{name}' does not exist" if param.nil?
571
565
 
572
566
  if param[:type] == 'Resource'
573
- col[:display] = Proc.new do |r|
567
+ col[:display] = proc do |r|
574
568
  next '' unless r
575
- "#{r[ param[:value_label].to_sym ]} (##{r[ param[:value_id].to_sym ]})"
569
+
570
+ "#{r[param[:value_label].to_sym]} (##{r[param[:value_id].to_sym]})"
576
571
  end
577
572
 
578
573
  elsif param[:type] == 'Datetime'
@@ -581,8 +576,8 @@ module HaveAPI::CLI
581
576
  end
582
577
 
583
578
  col.update({
584
- name: name,
585
- align: %w(Integer Float).include?(param[:type]) ? 'right' : 'left',
579
+ name:,
580
+ align: %w[Integer Float].include?(param[:type]) ? 'right' : 'left'
586
581
  })
587
582
 
588
583
  col[:label] ||= param[:label] && !param[:label].empty? ? param[:label] : name.upcase
@@ -591,11 +586,11 @@ module HaveAPI::CLI
591
586
  end
592
587
 
593
588
  OutputFormatter.print(
594
- response[namespace],
595
- cols,
596
- header: @opts[:header].nil?,
597
- sort: @opts[:sort] && @opts[:sort].to_sym,
598
- layout: @opts[:layout]
589
+ response[namespace],
590
+ cols,
591
+ header: @opts[:header].nil?,
592
+ sort: @opts[:sort] && @opts[:sort].to_sym,
593
+ layout: @opts[:layout]
599
594
  )
600
595
  end
601
596
 
@@ -610,25 +605,23 @@ module HaveAPI::CLI
610
605
  end
611
606
 
612
607
  def authenticate(action = nil)
613
- if @auth
614
- @auth.validate
615
- @auth.authenticate
608
+ raise 'auth is needed and has not been selected' unless @auth
616
609
 
617
- if @opts[:save]
618
- cfg = server_config(api_url)
619
- cfg[:auth][@opts[:auth]] = @auth.save
620
- cfg[:last_auth] = @opts[:auth]
621
- write_config
622
- end
610
+ @auth.validate
611
+ @auth.authenticate
623
612
 
624
- else
625
- # FIXME: exit as auth is needed and has not been selected
613
+ if @opts[:save]
614
+ cfg = server_config(api_url)
615
+ cfg[:auth][@opts[:auth]] = @auth.save
616
+ cfg[:last_auth] = @opts[:auth]
617
+ write_config
626
618
  end
627
619
 
628
- return true
620
+ true
629
621
  end
630
622
 
631
623
  protected
624
+
632
625
  def default_url
633
626
  'http://localhost:4567'
634
627
  end
@@ -638,18 +631,16 @@ module HaveAPI::CLI
638
631
  end
639
632
 
640
633
  def write_config
641
- File.open(config_path, 'w') do |f|
642
- f.write(YAML.dump(@config))
643
- end
634
+ File.write(config_path, YAML.dump(@config))
644
635
  end
645
636
 
646
637
  def read_config
647
- @config = YAML.load_file(config_path) if File.exists?(config_path)
638
+ @config = YAML.load_file(config_path) if File.exist?(config_path)
648
639
  end
649
640
 
650
641
  def server_config(url)
651
642
  unless @config[:servers]
652
- @config[:servers] = [{url: url, auth: {}}]
643
+ @config[:servers] = [{ url:, auth: {} }]
653
644
  return @config[:servers].first
654
645
  end
655
646
 
@@ -657,7 +648,7 @@ module HaveAPI::CLI
657
648
  return s if s[:url] == url
658
649
  end
659
650
 
660
- @config[:servers] << {url: url, auth: {}}
651
+ @config[:servers] << { url:, auth: {} }
661
652
  @config[:servers].last
662
653
  end
663
654
 
@@ -708,7 +699,7 @@ module HaveAPI::CLI
708
699
  includes = []
709
700
  top = action.params
710
701
 
711
- param.split('.').map! { |v| v.to_sym }.each do |part|
702
+ param.split('.').map!(&:to_sym).each do |part|
712
703
  next unless top.has_key?(part)
713
704
  next if top[part][:type] != 'Resource'
714
705
 
@@ -728,25 +719,22 @@ module HaveAPI::CLI
728
719
 
729
720
  t = DateTime.iso8601(date).to_time
730
721
  ret = case @opts[:datetime]
731
- when :timestamp
732
- t.to_i
733
-
734
- when :utc
735
- t.utc
722
+ when :timestamp
723
+ t.to_i
736
724
 
737
- when :local
738
- t.localtime
725
+ when :utc
726
+ t.utc
739
727
 
740
- else
741
- t.localtime
742
- end
728
+ else
729
+ t.localtime
730
+ end
743
731
 
744
732
  @opts[:date_format] ? ret.strftime(@opts[:date_format]) : ret
745
733
  end
746
734
 
747
735
  def sort_by_key(hash)
748
736
  hash.sort do |a, b|
749
- a[0]<=> b[0]
737
+ a[0] <=> b[0]
750
738
  end
751
739
  end
752
740
  end
@@ -5,7 +5,7 @@ module HaveAPI::CLI
5
5
 
6
6
  def cmd(resource, action = nil)
7
7
  @resource = resource.is_a?(::Array) ? resource : [resource]
8
- @resource.map! { |v| v.to_s }
8
+ @resource.map!(&:to_s)
9
9
  @action = action && action.to_s
10
10
 
11
11
  Cli.register_command(self)
@@ -41,9 +41,7 @@ module HaveAPI::CLI
41
41
  @api = client
42
42
  end
43
43
 
44
- def options(opts)
45
-
46
- end
44
+ def options(opts); end
47
45
 
48
46
  def exec(args)
49
47
  raise NotImplementedError
@@ -7,24 +7,24 @@ module HaveAPI::CLI::Commands
7
7
  desc 'Block until the action is finished'
8
8
 
9
9
  def exec(args)
10
- if args.size < 1
11
- warn "Provide argument STATE ID"
10
+ if args.empty?
11
+ warn 'Provide argument STATE ID'
12
12
  exit(false)
13
13
  end
14
14
 
15
15
  @api.set_opts(block: false)
16
16
 
17
17
  state = HaveAPI::CLI::ActionState.new(
18
- @global_opts,
19
- @api,
20
- args.first.to_i
18
+ @global_opts,
19
+ @api,
20
+ args.first.to_i
21
21
  )
22
22
  ret = state.wait_for_completion(timeout: @global_opts[:timeout])
23
23
 
24
- if ret.nil?
25
- warn "Timeout"
26
- exit(false)
27
- end
24
+ return unless ret.nil?
25
+
26
+ warn 'Timeout'
27
+ exit(false)
28
28
  end
29
29
  end
30
30
  end
@@ -24,9 +24,9 @@ module HaveAPI::CLI
24
24
 
25
25
  # response
26
26
  cli.format_output(
27
- action,
28
- {action.namespace(:output).to_sym => example[:response]},
29
- out
27
+ action,
28
+ { action.namespace(:output).to_sym => example[:response] },
29
+ out
30
30
  )
31
31
  end
32
32
  end
@@ -35,16 +35,16 @@ module HaveAPI::CLI
35
35
  option = name.to_s.dasherize
36
36
 
37
37
  case desc[:type]
38
- when 'Boolean'
39
- value ? "--#{option}" : "--no-#{option}"
38
+ when 'Boolean'
39
+ value ? "--#{option}" : "--no-#{option}"
40
40
 
41
- else
42
- "--#{option} #{example_value(value)}"
41
+ else
42
+ "--#{option} #{example_value(value)}"
43
43
  end
44
44
  end
45
45
 
46
46
  def self.example_value(v)
47
- (v.is_a?(String) && (v.empty? || v.index(' '))) ? "\"#{v}\"" : v
47
+ v.is_a?(String) && (v.empty? || v.index(' ')) ? "\"#{v}\"" : v
48
48
  end
49
49
  end
50
50
  end