nex_client 0.1.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.
- checksums.yaml +7 -0
- data/LICENSE +202 -0
- data/README.md +28 -0
- data/bin/nex-cli +7 -0
- data/lib/nex_client.rb +20 -0
- data/lib/nex_client/addon.rb +7 -0
- data/lib/nex_client/app.rb +24 -0
- data/lib/nex_client/base_resource.rb +19 -0
- data/lib/nex_client/cli.rb +348 -0
- data/lib/nex_client/commands.rb +17 -0
- data/lib/nex_client/commands/addons.rb +98 -0
- data/lib/nex_client/commands/apps.rb +301 -0
- data/lib/nex_client/commands/cube_instances.rb +89 -0
- data/lib/nex_client/commands/cube_templates.rb +44 -0
- data/lib/nex_client/commands/domains.rb +90 -0
- data/lib/nex_client/commands/helpers.rb +22 -0
- data/lib/nex_client/commands/organizations.rb +27 -0
- data/lib/nex_client/commands/racks.rb +90 -0
- data/lib/nex_client/commands/ssl_certificates.rb +100 -0
- data/lib/nex_client/commands/users.rb +49 -0
- data/lib/nex_client/compute_rack.rb +10 -0
- data/lib/nex_client/cube_instance.rb +21 -0
- data/lib/nex_client/cube_template.rb +8 -0
- data/lib/nex_client/domain.rb +7 -0
- data/lib/nex_client/gateway_rack.rb +7 -0
- data/lib/nex_client/organization.rb +5 -0
- data/lib/nex_client/resource_workflow.rb +17 -0
- data/lib/nex_client/routing_rack.rb +7 -0
- data/lib/nex_client/ssl_certificate.rb +7 -0
- data/lib/nex_client/storage_rack.rb +10 -0
- data/lib/nex_client/user.rb +5 -0
- data/lib/nex_client/version.rb +3 -0
- metadata +146 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
module Commands
|
4
|
+
module CubeTemplates
|
5
|
+
extend Helpers
|
6
|
+
|
7
|
+
TEMPLATES_TITLE = "Cube Templates".colorize(:red)
|
8
|
+
TEMPLATES_HEADERS = ['id','name','image','tag','layer','min_pu','stack'].map(&:upcase)
|
9
|
+
|
10
|
+
def self.list(args,opts)
|
11
|
+
filters = {}
|
12
|
+
filters[:human_id] = opts.name if opts.name.present?
|
13
|
+
filters[:stack] = opts.stack if opts.stack.present?
|
14
|
+
filters[:image] = opts.image if opts.image.present?
|
15
|
+
|
16
|
+
# Create table
|
17
|
+
list = NexClient::CubeTemplate.where(filters).order('human_id')
|
18
|
+
self.display_templates(list)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.display_templates(list)
|
22
|
+
table = Terminal::Table.new title: TEMPLATES_TITLE, headings: TEMPLATES_HEADERS do |t|
|
23
|
+
[list].flatten.compact.each do |e|
|
24
|
+
t.add_row(self.format_record(e))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
puts table
|
28
|
+
puts "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.format_record(record)
|
32
|
+
[
|
33
|
+
record.id,
|
34
|
+
record.human_id,
|
35
|
+
record.image,
|
36
|
+
record.tag,
|
37
|
+
record.layer,
|
38
|
+
record.min_pu,
|
39
|
+
record.stack
|
40
|
+
]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
module Commands
|
4
|
+
module Domains
|
5
|
+
extend Helpers
|
6
|
+
|
7
|
+
DOMAINS_TITLE = "Domains".colorize(:magenta)
|
8
|
+
DOMAINS_HEADERS = ['id','cname','origin'].map(&:upcase)
|
9
|
+
|
10
|
+
def self.list(args,opts)
|
11
|
+
filters = {}
|
12
|
+
filters[:'origin.name'] = args.first if args.first.present?
|
13
|
+
|
14
|
+
# Create table
|
15
|
+
list = NexClient::Domain.includes(:origin).where(filters).order('cname')
|
16
|
+
self.display_domains(list)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.create(args,opts)
|
20
|
+
domain_name,app_name = args
|
21
|
+
app = NexClient::App.find(name: app_name).first
|
22
|
+
app ||= NexClient::CubeInstance.find(name: app_name).first
|
23
|
+
|
24
|
+
# Display error
|
25
|
+
unless app
|
26
|
+
error("Error! Could not find app: #{app_name}")
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
domain = NexClient::Domain.new(cname: domain_name)
|
31
|
+
domain.relationships.attributes = { origin: { data: { type: app.type, id: app.id } } }
|
32
|
+
domain.save
|
33
|
+
|
34
|
+
# Display errors if any
|
35
|
+
if domain.errors.any?
|
36
|
+
display_record_errors(domain)
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
|
40
|
+
# Display domains
|
41
|
+
self.display_domains(NexClient::Domain.includes(:origin).find(domain.id).first)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.destroy(args,opts)
|
45
|
+
name = args.first
|
46
|
+
e = NexClient::Domain.find(cname: name).first
|
47
|
+
|
48
|
+
# Display error
|
49
|
+
unless e
|
50
|
+
error("Error! Could not find domain: #{name}")
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
|
54
|
+
# Ask confirmation
|
55
|
+
answer = ask("Enter the name of this domain to confirm: ")
|
56
|
+
unless answer == e.cname
|
57
|
+
error("Aborting deletion...")
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
|
61
|
+
e.destroy
|
62
|
+
success("Successfully destroyed domain: #{name}")
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.display_domains(list)
|
66
|
+
table = Terminal::Table.new title: DOMAINS_TITLE, headings: DOMAINS_HEADERS do |t|
|
67
|
+
[list].flatten.compact.each do |e|
|
68
|
+
t.add_row(self.format_record(e))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
puts table
|
72
|
+
puts "\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.format_record(record)
|
76
|
+
origin = self.format_origin(record)
|
77
|
+
[
|
78
|
+
record.id,
|
79
|
+
record.cname,
|
80
|
+
origin
|
81
|
+
]
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.format_origin(record)
|
85
|
+
return "-" unless record.origin
|
86
|
+
record.origin.name
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NexClient
|
4
|
+
module Commands
|
5
|
+
module Helpers
|
6
|
+
|
7
|
+
def display_record_errors(record)
|
8
|
+
record.errors.messages.each do |k,v|
|
9
|
+
v.each { |m| puts "#{k} #{m}" }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def success(msg)
|
14
|
+
puts msg.colorize(:green)
|
15
|
+
end
|
16
|
+
|
17
|
+
def error(msg)
|
18
|
+
puts msg.colorize(:red)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
module Commands
|
4
|
+
module Organizations
|
5
|
+
extend Helpers
|
6
|
+
|
7
|
+
ORGS_TITLE = "Organizations".colorize(:green)
|
8
|
+
ORGS_HEADERS = ['id','name','handle'].map(&:upcase)
|
9
|
+
|
10
|
+
def self.list(args,opts)
|
11
|
+
# Create table
|
12
|
+
self.display_organizations(NexClient::Organization.order('handle'))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.display_organizations(list)
|
16
|
+
table = Terminal::Table.new title: ORGS_TITLE, headings: ORGS_HEADERS do |t|
|
17
|
+
[list].flatten.compact.each do |e|
|
18
|
+
t.add_row([e.id,e.name,e.handle])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
puts table
|
22
|
+
puts "\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
module Commands
|
4
|
+
module Racks
|
5
|
+
extend Helpers
|
6
|
+
|
7
|
+
COMPUTE_RACKS_TITLE = "Compute Racks".colorize(:cyan)
|
8
|
+
STORAGE_RACKS_TITLE = "Storage Racks".colorize(:blue)
|
9
|
+
ROUTING_RACKS_TITLE = "Routing Racks".colorize(:green)
|
10
|
+
GATEWAY_RACKS_TITLE = "Gateway Racks".colorize(:yellow)
|
11
|
+
RACKS_HEADERS = ['type','id','region','stack','status','iip','eip','capacity'].map(&:upcase)
|
12
|
+
|
13
|
+
def self.list(args,opts)
|
14
|
+
filters = {}
|
15
|
+
|
16
|
+
# Type filter
|
17
|
+
only_type = opts.type
|
18
|
+
only_type = 'compute' if opts.stack.present?
|
19
|
+
|
20
|
+
# Status filter
|
21
|
+
filters[:status] = opts.status || 'running'
|
22
|
+
|
23
|
+
# Stack filter
|
24
|
+
if opts.stack.present?
|
25
|
+
filters[:stack] = opts.stack
|
26
|
+
end
|
27
|
+
|
28
|
+
# All option
|
29
|
+
filters = {} if opts.all
|
30
|
+
|
31
|
+
# Create table
|
32
|
+
if !only_type || only_type == 'compute'
|
33
|
+
self.display_compute_racks(NexClient::ComputeRack.where(filters).order('aws_region,status'))
|
34
|
+
end
|
35
|
+
|
36
|
+
if !only_type || only_type == 'storage'
|
37
|
+
self.display_storage_racks(NexClient::StorageRack.where(filters).order('aws_region,status'))
|
38
|
+
end
|
39
|
+
|
40
|
+
if !only_type || only_type == 'routing'
|
41
|
+
self.display_routing_racks(NexClient::RoutingRack.where(filters).order('aws_region,status'))
|
42
|
+
end
|
43
|
+
|
44
|
+
if !only_type || only_type == 'gateway'
|
45
|
+
self.display_gateway_racks(NexClient::GatewayRack.where(filters).order('aws_region,status'))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.display_compute_racks(list)
|
50
|
+
table = Terminal::Table.new title: COMPUTE_RACKS_TITLE, headings: RACKS_HEADERS do |t|
|
51
|
+
[list].flatten.compact.each do |e|
|
52
|
+
t.add_row(['compute',e.id,e.aws_region,e.stack,e.status,e.aws_local_ip_address,'-',"#{e.used_pu}/#{e.total_pu}"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
puts table
|
56
|
+
puts "\n"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.display_storage_racks(list)
|
60
|
+
table = Terminal::Table.new title: STORAGE_RACKS_TITLE, headings: RACKS_HEADERS do |t|
|
61
|
+
[list].flatten.compact.each do |e|
|
62
|
+
t.add_row(['storage',e.id,e.aws_region,'-',e.status,e.aws_local_ip_address,'-',"#{e.used_su}/#{e.total_su}"])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
puts table
|
66
|
+
puts "\n"
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.display_routing_racks(list)
|
70
|
+
table = Terminal::Table.new title: ROUTING_RACKS_TITLE, headings: RACKS_HEADERS do |t|
|
71
|
+
[list].flatten.compact.each do |e|
|
72
|
+
t.add_row(['routing',e.id,e.aws_region,'-',e.status,e.aws_local_ip_address,'-','-'])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
puts table
|
76
|
+
puts "\n"
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.display_gateway_racks(list)
|
80
|
+
table = Terminal::Table.new title: GATEWAY_RACKS_TITLE, headings: RACKS_HEADERS do |t|
|
81
|
+
[list].flatten.compact.each do |e|
|
82
|
+
t.add_row(['gateway',e.id,e.aws_region,'-',e.status,e.aws_local_ip_address,e.ip_address,'-'])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
puts table
|
86
|
+
puts "\n"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
module Commands
|
4
|
+
module SslCertificates
|
5
|
+
extend Helpers
|
6
|
+
|
7
|
+
DOMAINS_TITLE = "SSL Certificates".colorize(:light_yellow)
|
8
|
+
DOMAINS_HEADERS = ['id','cname','origin'].map(&:upcase)
|
9
|
+
|
10
|
+
def self.list(args,opts)
|
11
|
+
filters = {}
|
12
|
+
filters[:'origin.name'] = args.first if args.first.present?
|
13
|
+
|
14
|
+
# Create table
|
15
|
+
list = NexClient::SslCertificate.includes(:origin).where(filters).order('cname')
|
16
|
+
self.display_certs(list)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.create(args,opts)
|
20
|
+
cert_name,app_name = args
|
21
|
+
app = NexClient::App.find(name: app_name).first
|
22
|
+
app ||= NexClient::CubeInstance.find(name: app_name).first
|
23
|
+
|
24
|
+
# Display error
|
25
|
+
unless app
|
26
|
+
error("Error! Could not find app: #{app_name}")
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
# Load or ask certificate content from specified files
|
31
|
+
pubcert = opts.cert.present? ? File.read(opts.cert) : ask("Copy/paste your certificate below:") { |q| q.gather = "" }
|
32
|
+
bundle = opts.bundle.present? ? File.read(opts.bundle) : ask("Copy/paste your cert bundle below:") { |q| q.gather = "" }
|
33
|
+
privkey = opts.privkey.present? ? File.read(opts.privkey) : ask("Copy/paste your cert private key below:") { |q| q.gather = "" }
|
34
|
+
|
35
|
+
cert = NexClient::SslCertificate.new(
|
36
|
+
cname: cert_name,
|
37
|
+
public_cert: pubcert,
|
38
|
+
cert_bundle: bundle,
|
39
|
+
private_key: privkey
|
40
|
+
)
|
41
|
+
cert.relationships.attributes = { origin: { data: { type: app.type, id: app.id } } }
|
42
|
+
cert.save
|
43
|
+
|
44
|
+
# Display errors if any
|
45
|
+
if cert.errors.any?
|
46
|
+
display_record_errors(cert)
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
# Display certs
|
51
|
+
self.display_certs(NexClient::SslCertificate.includes(:origin).find(cert.id).first)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.destroy(args,opts)
|
55
|
+
name = args.first
|
56
|
+
e = NexClient::SslCertificate.find(cname: name).first
|
57
|
+
|
58
|
+
# Display error
|
59
|
+
unless e
|
60
|
+
error("Error! Could not find cert: #{name}")
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
|
64
|
+
# Ask confirmation
|
65
|
+
answer = ask("Enter the name of this cert to confirm: ")
|
66
|
+
unless answer == e.cname
|
67
|
+
error("Aborting deletion...")
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
|
71
|
+
e.destroy
|
72
|
+
success("Successfully destroyed cert: #{name}")
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.display_certs(list)
|
76
|
+
table = Terminal::Table.new title: DOMAINS_TITLE, headings: DOMAINS_HEADERS do |t|
|
77
|
+
[list].flatten.compact.each do |e|
|
78
|
+
t.add_row(self.format_record(e))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
puts table
|
82
|
+
puts "\n"
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.format_record(record)
|
86
|
+
origin = self.format_origin(record)
|
87
|
+
[
|
88
|
+
record.id,
|
89
|
+
record.cname,
|
90
|
+
origin
|
91
|
+
]
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.format_origin(record)
|
95
|
+
return "-" unless record.origin
|
96
|
+
record.origin.name
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
module Commands
|
4
|
+
module Users
|
5
|
+
extend Helpers
|
6
|
+
|
7
|
+
USERS_TITLE = "Users".colorize(:blue)
|
8
|
+
USERS_HEADERS = ['id','name','email','handle','orgs'].map(&:upcase)
|
9
|
+
|
10
|
+
def self.list(args,opts)
|
11
|
+
filters = {}
|
12
|
+
|
13
|
+
# Stack filter
|
14
|
+
if opts.organization.present?
|
15
|
+
filters[:'organization.handle'] = opts.organization
|
16
|
+
end
|
17
|
+
|
18
|
+
# Create table
|
19
|
+
self.display_users(NexClient::User.includes(:organizations).where(filters).order('handle'))
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.display_users(list)
|
23
|
+
table = Terminal::Table.new title: USERS_TITLE, headings: USERS_HEADERS do |t|
|
24
|
+
[list].flatten.compact.each do |e|
|
25
|
+
t.add_row(self.format_record(e))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
puts table
|
29
|
+
puts "\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.format_record(record)
|
33
|
+
orgs = self.format_orgs(record)
|
34
|
+
[
|
35
|
+
record.id,
|
36
|
+
record.first_name,
|
37
|
+
record.email,
|
38
|
+
record.handle,
|
39
|
+
orgs
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.format_orgs(record)
|
44
|
+
return "-" unless record.organizations.present?
|
45
|
+
record.organizations.map(&:name).join(',')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
class ComputeRack < BaseResource
|
4
|
+
property :created_at, type: :time
|
5
|
+
property :updated_at, type: :time
|
6
|
+
property :total_pu, type: :int
|
7
|
+
property :available_pu, type: :int
|
8
|
+
property :used_pu, type: :int
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module NexClient
|
3
|
+
class CubeInstance < BaseResource
|
4
|
+
property :created_at, type: :time
|
5
|
+
property :updated_at, type: :time
|
6
|
+
property :pu, type: :int
|
7
|
+
property :soa_enabled, type: :boolean
|
8
|
+
property :ssl_enabled, type: :boolean
|
9
|
+
property :persistent_storage, type: :boolean
|
10
|
+
property :port, type: :int
|
11
|
+
|
12
|
+
# PATCH <api_root>/apps/:id/restart
|
13
|
+
custom_endpoint :restart, on: :member, request_method: :patch
|
14
|
+
|
15
|
+
# PATCH <api_root>/apps/:id/start
|
16
|
+
custom_endpoint :start, on: :member, request_method: :patch
|
17
|
+
|
18
|
+
# PATCH <api_root>/apps/:id/stop
|
19
|
+
custom_endpoint :stop, on: :member, request_method: :patch
|
20
|
+
end
|
21
|
+
end
|