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 +4 -4
- data/lib/nex_client.rb +1 -0
- data/lib/nex_client/app.rb +9 -0
- data/lib/nex_client/cli.rb +66 -3
- data/lib/nex_client/commands/addons.rb +0 -13
- data/lib/nex_client/commands/apps.rb +16 -26
- data/lib/nex_client/commands/cube_instances.rb +100 -0
- data/lib/nex_client/commands/helpers.rb +67 -10
- data/lib/nex_client/commands/racks.rb +75 -10
- data/lib/nex_client/version.rb +1 -1
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65ff74c01669c2d62ffd1ff2f86d968636376ff9
|
4
|
+
data.tar.gz: bc06abd22d617d961eadcaa2bb79c28a6244b5e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f985e4a4926104ee1d5e3dbb7ca66a1b13c1ad3aeea7e9928a39766eb63ef3b44df13e763d1af8bf4150f1d126fa408960f5fc37a4561ee1ed624508ac640d7
|
7
|
+
data.tar.gz: 685bd46320361767df2d89cbc7faf30ec4e4eadd02cdcfa0f772fd0cc1bee48eed5270b156a973061516c4e9b98c4a4da2536129d331e899ff3b8c3494269f7f
|
data/lib/nex_client.rb
CHANGED
data/lib/nex_client/app.rb
CHANGED
@@ -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
|
data/lib/nex_client/cli.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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(
|
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
|
-
|
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 =
|
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|
|
data/lib/nex_client/version.rb
CHANGED
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.
|
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:
|
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:
|
186
|
+
version: 1.3.1
|
173
187
|
requirements: []
|
174
188
|
rubyforge_project:
|
175
|
-
rubygems_version: 2.
|
189
|
+
rubygems_version: 2.6.8
|
176
190
|
signing_key:
|
177
191
|
specification_version: 4
|
178
192
|
summary: Maestrano Nex!™ Client
|