nex_client 0.15.0 → 0.16.0.pre1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3cf9ee63f05c80c764ea3e0007a4933f40b62542
4
- data.tar.gz: 1a0da520b96e8f0e29400bce6abc6c506091d63e
3
+ metadata.gz: 65ff74c01669c2d62ffd1ff2f86d968636376ff9
4
+ data.tar.gz: bc06abd22d617d961eadcaa2bb79c28a6244b5e2
5
5
  SHA512:
6
- metadata.gz: 2e15e0f441bd717a8684f8a466223d79717feca4ac2cb4ad097f38c3b0db02382a64730ee2fa16d5110cb5e3c189fc420fba5a7ea598364af1ebf17e0b6389dc
7
- data.tar.gz: 20f12b7be4e354f786939d0a639f717ad394ed197225429bb7d4e96fa7bf8ba137ee6d6a518922df5985ecf96258d9a7c89fd457121898226d3020abc173cc70
6
+ metadata.gz: 4f985e4a4926104ee1d5e3dbb7ca66a1b13c1ad3aeea7e9928a39766eb63ef3b44df13e763d1af8bf4150f1d126fa408960f5fc37a4561ee1ed624508ac640d7
7
+ data.tar.gz: 685bd46320361767df2d89cbc7faf30ec4e4eadd02cdcfa0f772fd0cc1bee48eed5270b156a973061516c4e9b98c4a4da2536129d331e899ff3b8c3494269f7f
@@ -2,6 +2,7 @@
2
2
  require 'json_api_client'
3
3
  require 'active_support/all'
4
4
  require 'nex_client/version'
5
+ require 'launchy'
5
6
 
6
7
  module NexClient
7
8
  autoload :Addon, 'nex_client/addon'
@@ -23,5 +23,14 @@ module NexClient
23
23
 
24
24
  # GET <api_root>/apps/:id/logs
25
25
  custom_endpoint :logs, on: :member, request_method: :get
26
+
27
+ def preferred_url
28
+ domain = self.domains.first rescue NexClient::Domain.find('origin.name' => self.name).first
29
+ if domain
30
+ "#{domain.ssl_available ? 'https':'http'}://#{domain.cname}"
31
+ else
32
+ "#{self.ssl_enabled ? 'https' : 'http'}://#{self.url}"
33
+ end
34
+ end
26
35
  end
27
36
  end
@@ -294,9 +294,10 @@ module NexClient
294
294
  c.summary = 'Update apps settings'
295
295
  c.description = 'Update application settings'
296
296
  c.example 'change container size to 4', 'nex-cli apps:update myapp --size 4'
297
- c.option '--size SIZE', Integer, 'change container size (default: 2, min: 1, max: 20). Container will have N shares of CPU and N*128M of memory. [restart required]'
298
- c.option '--http-log-drain DRAIN_URL', String, 'specify the URL of a remote log drain. [restart required]'
299
297
  c.option '--desc DESCRIPTION', String, 'update the application description'
298
+ c.option '--http-log-drain DRAIN_URL', String, 'specify the URL of a remote log drain. [restart required]'
299
+ c.option '--image-tag IMAGE_TAG', String, 'update the docker image tag [restart required]'
300
+ c.option '--size SIZE', Integer, 'change container size (default: 2, min: 1, max: 20). Container will have N shares of CPU and N*128M of memory. [restart required]'
300
301
  c.option '--tags TAG_LIST', String, 'comma separated list of tags to use to describe the app'
301
302
  c.action do |args, options|
302
303
  NexClient::Commands::Apps.update(args,options)
@@ -323,6 +324,16 @@ module NexClient
323
324
  end
324
325
  end
325
326
 
327
+ command :'apps:open' do |c|
328
+ c.syntax = 'nex-cli apps:open APP_NAME'
329
+ c.summary = 'Open app url'
330
+ c.description = 'Open app in your browser'
331
+ c.example 'open app for myapp', 'nex-cli apps:open myapp'
332
+ c.action do |args, options|
333
+ NexClient::Commands::Apps.open(args,options)
334
+ end
335
+ end
336
+
326
337
  command :certs do |c|
327
338
  c.syntax = 'nex-cli certs [APP_OR_ORG_NAME] [options]'
328
339
  c.summary = 'Manage certs'
@@ -382,8 +393,18 @@ module NexClient
382
393
  end
383
394
  end
384
395
 
396
+ command :'cubes:download' do |c|
397
+ c.syntax = 'nex-cli cubes:download CUBE_ID REMOTE_SRC_PATH [DST_LOCAL_PATH]'
398
+ c.summary = 'Download a file from a container'
399
+ c.description = 'Download a file from a container'
400
+ c.example 'download file /tmp/foo.txt locally', 'nex-cli cubes:download mycube /tmp/foo.txt'
401
+ c.action do |args, options|
402
+ NexClient::Commands::CubeInstances.download(args,options)
403
+ end
404
+ end
405
+
385
406
  command :'cubes:events' do |c|
386
- c.syntax = 'nex-cli cubes:events APP_NAME [options]'
407
+ c.syntax = 'nex-cli cubes:events ID [options]'
387
408
  c.summary = 'Gather system events'
388
409
  c.description = 'Gather system events for a given cube'
389
410
  c.example 'display events for mycube', 'nex-cli cubes:events mycube'
@@ -395,6 +416,16 @@ module NexClient
395
416
  end
396
417
  end
397
418
 
419
+ command :'cubes:info' do |c|
420
+ c.syntax = 'nex-cli cubes:info ID [options]'
421
+ c.summary = 'Display information on a cube'
422
+ c.description = 'Display information about a given cube'
423
+ c.example 'display info for mycube', 'nex-cli cubes:info mycube'
424
+ c.action do |args, options|
425
+ NexClient::Commands::CubeInstances.info(args,options)
426
+ end
427
+ end
428
+
398
429
  command :'cubes:logs' do |c|
399
430
  c.syntax = 'nex-cli cubes:logs APP_NAME [options]'
400
431
  c.summary = 'Gather cube logs'
@@ -447,6 +478,17 @@ module NexClient
447
478
  end
448
479
  end
449
480
 
481
+ command :'cubes:upload' do |c|
482
+ c.syntax = 'nex-cli cubes:upload CUBE_ID LOCAL_SRC_PATH [DEST_PATH]'
483
+ c.summary = 'Upload a file to a container'
484
+ c.description = 'Upload a file to a container. If no DEST_PATH is specified then file will be created in /tmp.'
485
+ c.example 'upload file foo.txt to remote /tmp directory', 'nex-cli cubes:upload mycube ./foo.txt'
486
+ c.example 'upload file foo.txt to remote data directory', 'nex-cli cubes:upload mycube ./foo.txt /data/'
487
+ c.action do |args, options|
488
+ NexClient::Commands::CubeInstances.upload(args,options)
489
+ end
490
+ end
491
+
450
492
  command :cube_templates do |c|
451
493
  c.syntax = 'nex-cli cube_templates [options]'
452
494
  c.summary = 'Manage cube_templates [platform admin][legacy]'
@@ -523,6 +565,27 @@ module NexClient
523
565
  end
524
566
  end
525
567
 
568
+ command :'racks:download' do |c|
569
+ c.syntax = 'nex-cli racks:download IP_ADDRESS REMOTE_SRC_PATH [DST_LOCAL_PATH]'
570
+ c.summary = 'Download a file from a rack'
571
+ c.description = 'Download a file from a rack'
572
+ c.example 'download file /tmp/foo.txt locally', 'nex-cli racks:download 10.0.1.1 /tmp/foo.txt'
573
+ c.action do |args, options|
574
+ NexClient::Commands::Racks.download(args,options)
575
+ end
576
+ end
577
+
578
+ command :'racks:upload' do |c|
579
+ c.syntax = 'nex-cli racks:upload IP_ADDRESS LOCAL_SRC_PATH [DEST_PATH]'
580
+ c.summary = 'Upload a file to a rack'
581
+ c.description = 'Upload a file to a rack. If no DEST_PATH is specified then file will be created in /tmp.'
582
+ c.example 'upload file foo.txt to remote /tmp directory', 'nex-cli racks:upload 10.0.1.1 foo.txt'
583
+ c.example 'upload file foo.txt to remote data directory', 'nex-cli racks:upload 10.0.1.1 foo.txt /data/'
584
+ c.action do |args, options|
585
+ NexClient::Commands::Racks.upload(args,options)
586
+ end
587
+ end
588
+
526
589
  command :'racks:ssh' do |c|
527
590
  c.syntax = 'nex-cli racks:ssh IP_ADDRESS [options]'
528
591
  c.summary = 'SSH to racks [platform admin]'
@@ -8,9 +8,6 @@ module NexClient
8
8
  ADDONS_TITLE = "Addons".colorize(:red)
9
9
  ADDONS_HEADERS = ['name','status','service','size','nodes','app'].map(&:upcase)
10
10
 
11
- VARS_TITLE = "Environment Variables".colorize(:blue)
12
- VARS_HEADERS = ['key','value'].map(&:upcase)
13
-
14
11
  OPTS_TITLE = "Options".colorize(:blue)
15
12
  OPTS_HEADERS = ['key','value'].map(&:upcase)
16
13
 
@@ -223,16 +220,6 @@ module NexClient
223
220
  puts "\n"
224
221
  end
225
222
 
226
- def self.display_vars(list)
227
- table = Terminal::Table.new title: VARS_TITLE, headings: VARS_HEADERS do |t|
228
- [list].flatten.compact.each do |e|
229
- e.sort_by { |k, v| k }.each { |k,v| t.add_row([k,v]) }
230
- end
231
- end
232
- puts table
233
- puts "\n"
234
- end
235
-
236
223
  def self.display_options(list)
237
224
  table = Terminal::Table.new title: OPTS_TITLE, headings: OPTS_HEADERS do |t|
238
225
  [list].flatten.compact.each do |e|
@@ -10,9 +10,6 @@ module NexClient
10
10
  APPS_TITLE = "App Details".colorize(:green)
11
11
  APPS_HEADERS = ['name','status','image','ssl','storage','preferred region','size','nodes','owner','description','tags'].map(&:upcase)
12
12
 
13
- VARS_TITLE = "Environment Variables".colorize(:blue)
14
- VARS_HEADERS = ['key','value'].map(&:upcase)
15
-
16
13
  OPTS_TITLE = "Options".colorize(:blue)
17
14
  OPTS_HEADERS = ['key','value'].map(&:upcase)
18
15
 
@@ -81,6 +78,20 @@ module NexClient
81
78
  CubeInstances.display_cubes(e.cube_instances)
82
79
  end
83
80
 
81
+ # Open application in Browser
82
+ def self.open(args,opts)
83
+ name = args.first
84
+ app = NexClient::App.includes(:domains).find(name: name).first
85
+ # Display error
86
+ unless app
87
+ error("Error! Could not find app: #{name}")
88
+ return false
89
+ end
90
+ url = app.preferred_url
91
+ success "Opening #{url}"
92
+ Launchy.open(url)
93
+ end
94
+
84
95
  # Retrieve application logs from all containers
85
96
  def self.logs(args,opts)
86
97
  name = args.first
@@ -187,6 +198,7 @@ module NexClient
187
198
  attrs[:container_size] = opts.size if opts.size.present?
188
199
  attrs[:description] = opts.desc if opts.desc.present?
189
200
  attrs[:tag_list] = opts.tags if opts.tags.present?
201
+ attrs[:image_tag] = opts.image_tag if opts.image_tag.present?
190
202
 
191
203
  # Option: HTTP Log Drain
192
204
  if opts.http_log_drain.present?
@@ -400,27 +412,6 @@ module NexClient
400
412
  puts "\n"
401
413
  end
402
414
 
403
- def self.display_raw_vars(list)
404
- table = [list].flatten.compact.map do |e|
405
- e.sort_by { |k, v| k }.map { |k,v| "#{k}=#{v}" }
406
- end.flatten
407
- puts table
408
- puts "\n"
409
- end
410
-
411
- def self.display_vars(list,truncate = true)
412
- table = Terminal::Table.new title: VARS_TITLE, headings: VARS_HEADERS do |t|
413
- [list].flatten.compact.each do |e|
414
- e.sort_by { |k, v| k }.each do |k,v|
415
- val = truncate ? v.to_s.truncate(100) : v
416
- t.add_row([k,val])
417
- end
418
- end
419
- end
420
- puts table
421
- puts "\n"
422
- end
423
-
424
415
  def self.display_options(list)
425
416
  table = Terminal::Table.new title: OPTS_TITLE, headings: OPTS_HEADERS do |t|
426
417
  [list].flatten.compact.each do |e|
@@ -441,14 +432,13 @@ module NexClient
441
432
  puts "\n"
442
433
  end
443
434
 
444
-
445
435
  def self.format_record(record)
446
436
  owner = self.format_owner(record)
447
437
  node_count = self.format_node_count(record)
448
438
  [
449
439
  record.name,
450
440
  record.status,
451
- record.image,
441
+ [record.image,record.image_tag].compact.join(':'),
452
442
  record.ssl_enabled,
453
443
  record.persistent_storage,
454
444
  record.preferred_region,
@@ -31,6 +31,14 @@ module NexClient
31
31
  end
32
32
  end
33
33
 
34
+ def self.info(args,opts)
35
+ id = args.first
36
+ e = NexClient::CubeInstance.includes(:cluster).find(uuid: id).first
37
+
38
+ # Display cube information
39
+ self.display_cubes(e)
40
+ end
41
+
34
42
  # Retrieve application logs from all containers
35
43
  def self.logs(args,opts)
36
44
  name = args.first
@@ -84,6 +92,98 @@ module NexClient
84
92
  perform_ssh_cmd(e.ssh_cmd_template)
85
93
  end
86
94
 
95
+ # Download a file from a container
96
+ def self.download(args,opts)
97
+ id = args.first
98
+ remote_path = args[1]
99
+ local_path = args[2] || './'
100
+ e = NexClient::CubeInstance.includes(:compute_rack).find(uuid: id).first
101
+
102
+ # Display error
103
+ unless e
104
+ error("Error! Could not find cube: #{id}")
105
+ return false
106
+ end
107
+
108
+ # Get rack and file details
109
+ rack = e.compute_rack
110
+ filename = File.basename(remote_path)
111
+
112
+ # Copy and download file
113
+ with_cert_identity do |username,pv_key_path|
114
+ cmds = []
115
+ tmp_folder = "/home/#{username}/tmp"
116
+ tmp_path = "#{tmp_folder}/#{filename}"
117
+ ssh_cmd = format_cmd(rack.ssh_cmd_template, username: username, certfile: pv_key_path)
118
+
119
+ # Format tmp folder creation command
120
+ cmds << "#{ssh_cmd} mkdir -p #{tmp_folder}"
121
+
122
+ # Format container copy command
123
+ cmds << "#{ssh_cmd} sudo docker cp #{e.container}:#{remote_path} #{tmp_folder}/"
124
+
125
+ # Format server copy command
126
+ cmds << format_cmd(rack.scp_cmd_template,
127
+ username: username,
128
+ certfile: pv_key_path,
129
+ remote_path: tmp_path,
130
+ dst_local_file: local_path
131
+ )
132
+
133
+ # Cleanup
134
+ cmds << "#{ssh_cmd} rm -f #{tmp_path}"
135
+
136
+ # Execute commands
137
+ cmds.each { |cmd| system(cmd) }
138
+ end
139
+ end
140
+
141
+ # Upload a file to the container
142
+ def self.upload(args,opts)
143
+ id = args.first
144
+ local_path = args[1]
145
+ remote_path = args[2] || "/tmp/"
146
+ e = NexClient::CubeInstance.includes(:compute_rack).find(uuid: id).first
147
+
148
+ # Display error
149
+ unless e
150
+ error("Error! Could not find cube: #{id}")
151
+ return false
152
+ end
153
+
154
+ # Get rack and file details
155
+ rack = e.compute_rack
156
+ filename = File.basename(local_path)
157
+
158
+ # Upload and copy file
159
+ with_cert_identity do |username,pv_key_path|
160
+ cmds = []
161
+ tmp_folder = "/home/#{username}/tmp"
162
+ tmp_path = "#{tmp_folder}/#{filename}"
163
+ ssh_cmd = format_cmd(rack.ssh_cmd_template, username: username, certfile: pv_key_path)
164
+
165
+ # Format tmp folder creation command
166
+ cmds << "#{ssh_cmd} mkdir -p #{tmp_folder}"
167
+
168
+ # Format server copy command
169
+ cmds << format_cmd(rack.scp_cmd_template,
170
+ username: username,
171
+ certfile: pv_key_path,
172
+ src_local_file: local_path,
173
+ remote_path: tmp_path
174
+ )
175
+
176
+ # Format container copy command
177
+ cmds << "#{ssh_cmd} sudo docker cp #{tmp_path} #{e.container}:#{remote_path}"
178
+
179
+ # Cleanup
180
+ cmds << "#{ssh_cmd} rm -f #{tmp_path}"
181
+
182
+ # Execute commands
183
+ cmds.each { |cmd| system(cmd) }
184
+ end
185
+ end
186
+
87
187
  def self.display_cubes(list)
88
188
  table = Terminal::Table.new title: CUBES_TITLE, headings: CUBES_HEADERS do |t|
89
189
  [list].flatten.compact.each do |e|
@@ -4,6 +4,8 @@ module NexClient
4
4
  module Commands
5
5
  module Helpers
6
6
  LOG_COLORS = [:cyan,:green,:red,:yellow,:magenta]
7
+ VARS_TITLE = "Environment Variables".colorize(:blue)
8
+ VARS_HEADERS = ['key','value'].map(&:upcase)
7
9
 
8
10
  def display_record_errors(record)
9
11
  record.errors.messages.each do |k,v|
@@ -52,19 +54,27 @@ module NexClient
52
54
 
53
55
  # Display a list of events
54
56
  def display_events(events)
57
+ # Content
55
58
  events.sort_by { |e| e.id.to_i }.each do |e|
56
- puts [e.created_at,e.event.ljust(12,' '),e.level.ljust(6,' '),e.message].join(" | ")
59
+ username = e&.username || 'system'
60
+ session_id = e&.session_id || '-'
61
+ puts [
62
+ e.created_at,
63
+ e.event.ljust(12,' '),
64
+ username.ljust(15,' '),
65
+ session_id.ljust(6,' '),
66
+ e.level.ljust(6,' '),
67
+ e.message
68
+ ].join(" | ")
57
69
  end
58
70
  puts "\n"
59
71
  end
60
72
 
61
- # Perform an SSH command based on a template
62
- # Fetch current user key and username
63
- def perform_ssh_cmd(ssh_cmd_template)
73
+ def with_cert_identity
64
74
  # Fetch user
65
75
  me = NexClient::Me.find.first
66
76
  if me.api_only
67
- error("Error! Cannot SSH with an api-only user")
77
+ error('Error! Cannot SSH with an api-only user')
68
78
  return false
69
79
  end
70
80
 
@@ -77,17 +87,43 @@ module NexClient
77
87
  pv_key_file.write(pv_key)
78
88
  pv_key_file.close
79
89
 
80
- # Format command
81
- ssh_cmd = ssh_cmd_template.gsub("{{certfile}}",pv_key_file.path).gsub("{{username}}",username)
82
-
83
- # Launch SSH session
84
90
  begin
85
- system(ssh_cmd)
91
+ yield(username,pv_key_file.path)
86
92
  ensure
87
93
  pv_key_file.unlink # delete tmp file
88
94
  end
89
95
  end
90
96
 
97
+ def format_cmd(cmd,values = {})
98
+ formatted = cmd
99
+
100
+ # Replace declared values
101
+ values.each do |k,v|
102
+ formatted = formatted.gsub("{{#{k}}}",v)
103
+ end
104
+
105
+ # Remove remaining template values
106
+ formatted.gsub(/{{[^{}]+}}/,'')
107
+ end
108
+
109
+ # Perform an SSH command based on a template
110
+ # Fetch current user key and username
111
+ def perform_ssh_cmd(ssh_cmd_template, exec_cmd = nil)
112
+ unless ssh_cmd_template
113
+ error('Error! Cannot perform SSH. Command Template was empty. Are you sure the app is running ?')
114
+ return false
115
+ end
116
+
117
+ with_cert_identity do |username,pv_key_path|
118
+ # Format command
119
+ ssh_cmd = format_cmd(ssh_cmd_template, username: username, certfile: pv_key_path)
120
+ ssh_cmd += " #{exec_cmd}" if exec_cmd
121
+
122
+ # Run command
123
+ system(ssh_cmd)
124
+ end
125
+ end
126
+
91
127
  # Parse plain or yaml file
92
128
  def vars_from_file(file,prefix = nil,&block)
93
129
  # YAML file
@@ -122,6 +158,27 @@ module NexClient
122
158
  yield(key,val)
123
159
  end
124
160
  end
161
+
162
+ def display_raw_vars(list)
163
+ table = [list].flatten.compact.map do |e|
164
+ e.sort_by { |k, v| k }.map { |k,v| "#{k}=#{v}" }
165
+ end.flatten
166
+ puts table
167
+ puts "\n"
168
+ end
169
+
170
+ def display_vars(list,truncate = true)
171
+ table = Terminal::Table.new title: VARS_TITLE, headings: VARS_HEADERS do |t|
172
+ [list].flatten.compact.each do |e|
173
+ e.sort_by { |k, v| k }.each do |k,v|
174
+ val = truncate ? v.to_s.truncate(100) : v
175
+ t.add_row([k,val])
176
+ end
177
+ end
178
+ end
179
+ puts table
180
+ puts "\n"
181
+ end
125
182
  end
126
183
  end
127
184
  end
@@ -83,16 +83,7 @@ module NexClient
83
83
  def self.ssh(args,opts)
84
84
  # Find server
85
85
  id = args.first
86
- rack = nil
87
- [
88
- NexClient::ComputeRack,
89
- NexClient::GatewayRack,
90
- NexClient::RoutingRack,
91
- NexClient::StorageRack
92
- ].each do |server_type|
93
- rack ||= server_type.where(private_ip_address: id).first ||
94
- server_type.where(ip_address: id).first
95
- end
86
+ rack = find_rack_by_ip(id)
96
87
 
97
88
  # Display error
98
89
  unless rack
@@ -104,6 +95,80 @@ module NexClient
104
95
  perform_ssh_cmd(rack.ssh_cmd_template)
105
96
  end
106
97
 
98
+ # Download a file from a container
99
+ def self.download(args,opts)
100
+ id = args.first
101
+ remote_path = args[1]
102
+ local_path = args[2] || './'
103
+ rack = find_rack_by_ip(id)
104
+
105
+ # Display error
106
+ unless rack
107
+ error("Error! Could not find rack: #{id}")
108
+ return false
109
+ end
110
+
111
+ # Download file
112
+ with_cert_identity do |username,pv_key_path|
113
+ # Format server copy command
114
+ cmd = format_cmd(rack.scp_cmd_template,
115
+ username: username,
116
+ certfile: pv_key_path,
117
+ remote_path: remote_path,
118
+ dst_local_file: local_path
119
+ )
120
+
121
+ # Execute commands
122
+ system(cmd)
123
+ end
124
+ end
125
+
126
+ # Upload a file to the container
127
+ def self.upload(args,opts)
128
+ id = args.first
129
+ local_path = args[1]
130
+ remote_path = args[2] || "/tmp/"
131
+
132
+ # Find server
133
+ rack = find_rack_by_ip(id)
134
+
135
+ # Display error
136
+ unless rack
137
+ error("Error! Could not find rack: #{id}")
138
+ return false
139
+ end
140
+
141
+ # Upload file
142
+ with_cert_identity do |username,pv_key_path|
143
+ # Format server copy command
144
+ cmd = format_cmd(rack.scp_cmd_template,
145
+ username: username,
146
+ certfile: pv_key_path,
147
+ src_local_file: local_path,
148
+ remote_path: remote_path
149
+ )
150
+
151
+ # Execute command
152
+ system(cmd)
153
+ end
154
+ end
155
+
156
+ def self.find_rack_by_ip(ip_address)
157
+ rack = nil
158
+
159
+ [
160
+ NexClient::ComputeRack,
161
+ NexClient::GatewayRack,
162
+ NexClient::RoutingRack,
163
+ NexClient::StorageRack
164
+ ].each do |server_type|
165
+ rack ||= server_type.where(private_ip_address: ip_address).first ||
166
+ server_type.where(ip_address: ip_address).first
167
+ end
168
+
169
+ return rack
170
+ end
171
+
107
172
  def self.display_compute_racks(list)
108
173
  table = Terminal::Table.new title: COMPUTE_RACKS_TITLE, headings: RACKS_HEADERS do |t|
109
174
  [list].flatten.compact.each do |e|
@@ -1,3 +1,3 @@
1
1
  module NexClient
2
- VERSION ||= '0.15.0'
2
+ VERSION ||= '0.16.0.pre1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nex_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arnaud Lachaume
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-21 00:00:00.000000000 Z
11
+ date: 2017-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json_api_client
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: launchy
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rspec
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -167,12 +181,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
167
181
  version: '0'
168
182
  required_rubygems_version: !ruby/object:Gem::Requirement
169
183
  requirements:
170
- - - ">="
184
+ - - ">"
171
185
  - !ruby/object:Gem::Version
172
- version: '0'
186
+ version: 1.3.1
173
187
  requirements: []
174
188
  rubyforge_project:
175
- rubygems_version: 2.5.1
189
+ rubygems_version: 2.6.8
176
190
  signing_key:
177
191
  specification_version: 4
178
192
  summary: Maestrano Nex!™ Client