morpheus-cli 5.4.0 → 5.4.1
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/Dockerfile +1 -1
- data/lib/morpheus/api/account_users_interface.rb +68 -0
- data/lib/morpheus/api/api_client.rb +51 -9
- data/lib/morpheus/api/audit_interface.rb +9 -0
- data/lib/morpheus/api/instances_interface.rb +21 -0
- data/lib/morpheus/api/load_balancer_monitors_interface.rb +9 -0
- data/lib/morpheus/api/load_balancer_pools_interface.rb +4 -4
- data/lib/morpheus/api/load_balancer_profiles_interface.rb +4 -5
- data/lib/morpheus/api/load_balancer_virtual_servers_interface.rb +13 -4
- data/lib/morpheus/api/load_balancers_interface.rb +5 -0
- data/lib/morpheus/api/network_routers_interface.rb +9 -0
- data/lib/morpheus/api/network_static_routes_interface.rb +36 -0
- data/lib/morpheus/api/read_interface.rb +4 -3
- data/lib/morpheus/api/rest_interface.rb +3 -3
- data/lib/morpheus/api/secondary_read_interface.rb +1 -1
- data/lib/morpheus/api/secondary_rest_interface.rb +19 -19
- data/lib/morpheus/api/storage_server_types_interface.rb +14 -0
- data/lib/morpheus/api/storage_servers_interface.rb +9 -0
- data/lib/morpheus/api/storage_volume_types_interface.rb +9 -0
- data/lib/morpheus/api/storage_volumes_interface.rb +9 -0
- data/lib/morpheus/api/users_interface.rb +16 -63
- data/lib/morpheus/cli/cli_command.rb +253 -5
- data/lib/morpheus/cli/cli_registry.rb +1 -1
- data/lib/morpheus/cli/commands/alias_command.rb +1 -1
- data/lib/morpheus/cli/commands/apps.rb +14 -78
- data/lib/morpheus/cli/commands/audit.rb +188 -0
- data/lib/morpheus/cli/commands/blueprints_command.rb +1 -1
- data/lib/morpheus/cli/commands/change_password_command.rb +4 -4
- data/lib/morpheus/cli/commands/clusters.rb +37 -12
- data/lib/morpheus/cli/commands/hosts.rb +15 -15
- data/lib/morpheus/cli/commands/instances.rb +109 -2
- data/lib/morpheus/cli/commands/load_balancer_monitors.rb +71 -0
- data/lib/morpheus/cli/commands/load_balancer_pools.rb +30 -50
- data/lib/morpheus/cli/commands/load_balancer_profiles.rb +65 -0
- data/lib/morpheus/cli/commands/load_balancer_types.rb +9 -4
- data/lib/morpheus/cli/commands/load_balancer_virtual_servers.rb +77 -57
- data/lib/morpheus/cli/commands/load_balancers.rb +93 -6
- data/lib/morpheus/cli/commands/network_firewalls_command.rb +22 -5
- data/lib/morpheus/cli/commands/network_routers_command.rb +96 -45
- data/lib/morpheus/cli/commands/network_static_routes_command.rb +446 -0
- data/lib/morpheus/cli/commands/network_transport_zones_command.rb +4 -4
- data/lib/morpheus/cli/commands/open_command.rb +30 -0
- data/lib/morpheus/cli/commands/options.rb +98 -0
- data/lib/morpheus/cli/commands/policies_command.rb +1 -1
- data/lib/morpheus/cli/commands/prices_command.rb +7 -7
- data/lib/morpheus/cli/commands/remote.rb +4 -2
- data/lib/morpheus/cli/commands/roles.rb +1 -1
- data/lib/morpheus/cli/commands/shell.rb +2 -2
- data/lib/morpheus/cli/commands/storage_server_types.rb +50 -0
- data/lib/morpheus/cli/commands/storage_servers.rb +122 -0
- data/lib/morpheus/cli/commands/storage_volume_types.rb +50 -0
- data/lib/morpheus/cli/commands/storage_volumes.rb +103 -0
- data/lib/morpheus/cli/commands/tenants_command.rb +1 -1
- data/lib/morpheus/cli/commands/user_groups_command.rb +1 -1
- data/lib/morpheus/cli/commands/user_settings_command.rb +2 -1
- data/lib/morpheus/cli/commands/user_sources_command.rb +1 -1
- data/lib/morpheus/cli/commands/users.rb +28 -28
- data/lib/morpheus/cli/commands/view.rb +102 -0
- data/lib/morpheus/cli/mixins/accounts_helper.rb +5 -5
- data/lib/morpheus/cli/mixins/load_balancers_helper.rb +24 -4
- data/lib/morpheus/cli/mixins/print_helper.rb +50 -18
- data/lib/morpheus/cli/mixins/processes_helper.rb +1 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +15 -5
- data/lib/morpheus/cli/mixins/rest_command.rb +145 -73
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +174 -81
- data/lib/morpheus/cli/mixins/storage_servers_helper.rb +156 -0
- data/lib/morpheus/cli/mixins/storage_volumes_helper.rb +119 -0
- data/lib/morpheus/cli/option_types.rb +45 -24
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/ext/string.rb +29 -6
- data/lib/morpheus/routes.rb +238 -0
- data/lib/morpheus/util.rb +6 -1
- metadata +29 -8
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
# require 'morpheus/routes'
|
3
|
+
|
4
|
+
class Morpheus::Cli::View
|
5
|
+
include Morpheus::Cli::CliCommand
|
6
|
+
|
7
|
+
set_command_description "Open the remote appliance in a web browser"
|
8
|
+
set_command_name :'view'
|
9
|
+
|
10
|
+
def connect(opts)
|
11
|
+
@api_client = establish_remote_appliance_connection(opts)
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle(args)
|
15
|
+
params = {}
|
16
|
+
options = {}
|
17
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
18
|
+
opts.banner = subcommand_usage("[path] [id]")
|
19
|
+
# debate: should login using /login/ouath-redirect
|
20
|
+
opts.on('-L', '--login', "Login with the CLI access token before loading the path." ) do
|
21
|
+
options[:login] = true
|
22
|
+
end
|
23
|
+
opts.on('--absolute', "Absolute path, do not search for a matching route to use") do
|
24
|
+
options[:absolute_path] = true
|
25
|
+
end
|
26
|
+
build_common_options(opts, options, [:dry_run, :remote])
|
27
|
+
opts.footer = <<-EOT
|
28
|
+
View the remote appliance in a web browser.
|
29
|
+
[path] is optional. This the path or resource type to load. The default is the index page "/".
|
30
|
+
[id] is optional. This is the resource name or id to be append to the path to load details of a specific object.
|
31
|
+
The [path] is matched against the #{prog_name} UI site map to find the best matching route.
|
32
|
+
Route matching is skipped if the path begins with a "/" or --absolute is used.
|
33
|
+
By default no authentication is not done and the existing web browser session used.
|
34
|
+
The --login option will authenticate via the CLI access token and create a new browser session.
|
35
|
+
|
36
|
+
Examples:
|
37
|
+
view --login
|
38
|
+
view monitoring
|
39
|
+
view user 1
|
40
|
+
view user administrator
|
41
|
+
view /infrastructure/clouds/2
|
42
|
+
EOT
|
43
|
+
end
|
44
|
+
optparse.parse!(args)
|
45
|
+
# verify_args!(args:args, optparse:optparse, min: 0, max: 2)
|
46
|
+
connect(options)
|
47
|
+
# todo: it would actually be cool to use the params and include them on the path..
|
48
|
+
# params.merge!(parse_query_options(options))
|
49
|
+
path, *ids = args
|
50
|
+
# default to index page "/"
|
51
|
+
path = path || "/"
|
52
|
+
if options[:absolute_path] != true
|
53
|
+
if path.start_with?("/")
|
54
|
+
# treat like absolute path, no lookup
|
55
|
+
else
|
56
|
+
# lookup best matching route from sitemap
|
57
|
+
# lookup plural routes first, so 'app' finds apps and not approvals
|
58
|
+
found_route = Morpheus::Routes.lookup(path)
|
59
|
+
if found_route
|
60
|
+
# Morpheus::Logging::DarkPrinter.puts "Found matching route: '#{path}' => '#{found_route}'" if Morpheus::Logging.debug?
|
61
|
+
path = found_route
|
62
|
+
else
|
63
|
+
# just use specified path
|
64
|
+
end
|
65
|
+
end
|
66
|
+
# always add a leading slash
|
67
|
+
path = path.start_with?("/") ? path : "/#{path}"
|
68
|
+
# append id(s) to path if passed
|
69
|
+
if ids.size > 0
|
70
|
+
# convert names to ids
|
71
|
+
# assume the last part of path is the type and use generic finder
|
72
|
+
# only lookup names, and allow any id
|
73
|
+
ids = ids.collect do |id|
|
74
|
+
if id.to_s !~ /\A\d{1,}\Z/
|
75
|
+
# assume the last part of path is the type
|
76
|
+
record_type = path.split("/").last
|
77
|
+
record = find_by_name(record_type, id)
|
78
|
+
if record.nil?
|
79
|
+
raise_command_error("[id] is invalid. No #{record_type} found for '#{id}'", args, optparse)
|
80
|
+
end
|
81
|
+
record['id'].to_s
|
82
|
+
else
|
83
|
+
id
|
84
|
+
end
|
85
|
+
end
|
86
|
+
path = "#{path}/" + ids.join("/")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
# build the link to use, either our path or oauth-redirect to that path
|
90
|
+
link = "#{@appliance_url}#{path}"
|
91
|
+
if options[:login]
|
92
|
+
# uh, this should need CGI::escape(path)
|
93
|
+
link = "#{@appliance_url}/login/oauth-redirect?access_token=#{@access_token}\\&redirectUri=#{path}"
|
94
|
+
end
|
95
|
+
if options[:dry_run]
|
96
|
+
print_system_command_dry_run(Morpheus::Util.open_url_command(link), options)
|
97
|
+
return 0, nil
|
98
|
+
end
|
99
|
+
return Morpheus::Util.open_url(link)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -15,10 +15,10 @@ module Morpheus::Cli::AccountsHelper
|
|
15
15
|
@accounts_interface
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def account_users_interface
|
19
19
|
# @api_client.users
|
20
|
-
raise "#{self.class} has not defined @
|
21
|
-
@
|
20
|
+
raise "#{self.class} has not defined @account_users_interface" if @account_users_interface.nil?
|
21
|
+
@account_users_interface
|
22
22
|
end
|
23
23
|
|
24
24
|
def user_groups_interface
|
@@ -244,7 +244,7 @@ module Morpheus::Cli::AccountsHelper
|
|
244
244
|
|
245
245
|
def find_user_by_id(account_id, id, params={})
|
246
246
|
begin
|
247
|
-
json_response =
|
247
|
+
json_response = account_users_interface.get(account_id, id.to_i, params)
|
248
248
|
return json_response['user']
|
249
249
|
rescue RestClient::Exception => e
|
250
250
|
if e.response && e.response.code == 404
|
@@ -256,7 +256,7 @@ module Morpheus::Cli::AccountsHelper
|
|
256
256
|
end
|
257
257
|
|
258
258
|
def find_user_by_username(account_id, username, params={})
|
259
|
-
users =
|
259
|
+
users = account_users_interface.list(account_id, params.merge({username: username.to_s}))['users']
|
260
260
|
if users.empty?
|
261
261
|
print_red_alert "User not found by username #{username}"
|
262
262
|
return nil
|
@@ -105,12 +105,32 @@ module Morpheus::Cli::LoadBalancersHelper
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
-
def load_balancer_type_for_id(
|
109
|
-
|
108
|
+
def load_balancer_type_for_id(val)
|
109
|
+
record = get_available_load_balancer_types().find { |z| z['id'].to_i == val.to_i}
|
110
|
+
label = "Load Balancer Type"
|
111
|
+
if record.nil?
|
112
|
+
print_red_alert "#{label.downcase} not found by id #{val}"
|
113
|
+
return nil
|
114
|
+
end
|
115
|
+
return record
|
110
116
|
end
|
111
117
|
|
112
|
-
def load_balancer_type_for_name(
|
113
|
-
|
118
|
+
def load_balancer_type_for_name(val)
|
119
|
+
records = get_available_load_balancer_types().select { |z| z['name'].downcase == val.downcase || z['code'].downcase == val.downcase}
|
120
|
+
label = "Load Balancer Type"
|
121
|
+
if records.empty?
|
122
|
+
print_red_alert "#{label} not found by name '#{val}'"
|
123
|
+
return nil
|
124
|
+
elsif records.size > 1
|
125
|
+
print_red_alert "More than one #{label.downcase} found by name '#{val}'"
|
126
|
+
print_error "\n"
|
127
|
+
puts_error as_pretty_table(records, [:id, :name], {color:red})
|
128
|
+
print_red_alert "Try using ID instead"
|
129
|
+
print_error reset,"\n"
|
130
|
+
return nil
|
131
|
+
else
|
132
|
+
return records[0]
|
133
|
+
end
|
114
134
|
end
|
115
135
|
|
116
136
|
def find_load_balancer_type_by_name_or_id(val)
|
@@ -202,7 +202,7 @@ module Morpheus::Cli::PrintHelper
|
|
202
202
|
if options[:outfile]
|
203
203
|
print_result = print_to_file(output, options[:outfile], options[:overwrite])
|
204
204
|
# with_stdout_to_file(options[:outfile], options[:overwrite]) { print output }
|
205
|
-
print "#{cyan}Wrote output to file #{options[:outfile]} (#{format_bytes
|
205
|
+
print "#{cyan}Wrote output to file #{options[:outfile]} (#{format_bytes(File.size(options[:outfile]))})\n" unless options[:quiet]
|
206
206
|
#return print_result
|
207
207
|
return
|
208
208
|
end
|
@@ -220,6 +220,14 @@ module Morpheus::Cli::PrintHelper
|
|
220
220
|
return
|
221
221
|
end
|
222
222
|
|
223
|
+
def print_system_command_dry_run(cmd, options={})
|
224
|
+
print "\n"
|
225
|
+
print "#{cyan}#{bold}#{dark}SYSTEM COMMAND#{reset}\n"
|
226
|
+
print cmd
|
227
|
+
print reset, "\n"
|
228
|
+
return
|
229
|
+
end
|
230
|
+
|
223
231
|
def format_api_request(http_method, url, headers, payload=nil, options={})
|
224
232
|
out = ""
|
225
233
|
# out << "\n"
|
@@ -385,33 +393,57 @@ module Morpheus::Cli::PrintHelper
|
|
385
393
|
if json_response.nil? || json_response.empty?
|
386
394
|
return ""
|
387
395
|
end
|
388
|
-
|
389
|
-
# options = OpenStruct.new(options) # laff, let's do this instead
|
390
396
|
color = options.key?(:color) ? options[:color] : cyan
|
391
397
|
label = options[:label]
|
392
|
-
n_label = options[:n_label]
|
393
|
-
# label = n_label if !label && n_label
|
398
|
+
n_label = options[:n_label] || (label ? label.to_s.pluralize : nil)
|
394
399
|
message = options[:message] || "Viewing %{start_index}-%{end_index} of %{total} %{label}"
|
395
400
|
blank_message = options[:blank_message] || nil # "No %{label} found"
|
396
401
|
|
397
|
-
# support lazy passing of common json_response {"meta": {"size":
|
398
|
-
#
|
399
|
-
meta
|
400
|
-
if
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
#
|
405
|
-
|
406
|
-
|
407
|
-
|
402
|
+
# support lazy passing of common list json_response {"meta": {"size": 25, "total": 56} }
|
403
|
+
# priority is:
|
404
|
+
# 1. "meta" that api response contains for list endpoints
|
405
|
+
# 2. "total" and "size" values if passed explicitely by the cli (pretty sure symbols are no longer used)
|
406
|
+
# 3. examine the first array found in the response
|
407
|
+
meta = nil
|
408
|
+
records = nil
|
409
|
+
# assume records is the first array in the response
|
410
|
+
records_key = json_response.keys.find { |k| json_response[k].is_a?(Array) }
|
411
|
+
if records_key
|
412
|
+
records = json_response[records_key]
|
413
|
+
meta = {'offset' => 0, 'size' => records.size, 'total' => records.size}
|
414
|
+
end
|
415
|
+
if json_response[:meta] || json_response["meta"]
|
416
|
+
meta = json_response[:meta] || json_response["meta"]
|
417
|
+
elsif json_response.key?('size') || json_response.key?('total')
|
418
|
+
meta = json_response
|
419
|
+
elsif json_response.key?(:size) || json_response.key?(:total)
|
420
|
+
meta = {'size' => json_response[:size], 'total' => json_response[:total], 'offset' => json_response[:offset]}
|
421
|
+
elsif records
|
422
|
+
# just use the first key in the response
|
423
|
+
meta = {'size' => records.size, 'total' => records.size}
|
424
|
+
end
|
425
|
+
# did not find pagination meta info?
|
426
|
+
if meta.nil?
|
427
|
+
return ""
|
428
|
+
end
|
429
|
+
# api should not need to return the size, just use records.size
|
430
|
+
if meta["size"].nil? && records
|
431
|
+
meta["size"] = records.size
|
432
|
+
end
|
433
|
+
offset = meta['offset'].to_i
|
434
|
+
size = meta['size'].to_i
|
435
|
+
total = meta['total'].to_i
|
436
|
+
# perhaps no total count returned, let total be equal to size of list
|
437
|
+
if total == 0 && size > 0
|
408
438
|
total = size
|
409
439
|
end
|
440
|
+
# plural label?
|
410
441
|
if total != 1
|
411
|
-
label = n_label
|
442
|
+
label = n_label
|
412
443
|
end
|
413
444
|
out_str = ""
|
414
|
-
string_key_values = {start_index: format_number(offset + 1), end_index: format_number(offset + size),
|
445
|
+
string_key_values = {start_index: format_number(offset + 1), end_index: format_number(offset + size),
|
446
|
+
total: format_number(total), size: format_number(size), offset: format_number(offset), label: label}
|
415
447
|
if size > 0
|
416
448
|
if message
|
417
449
|
out_str << message % string_key_values
|
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'morpheus/cli/mixins/print_helper'
|
2
2
|
|
3
3
|
# Mixin for Morpheus::Cli command classes
|
4
|
-
# Provides common methods for
|
5
|
-
# The including class must establish @accounts_interface, @roles_interface, @users_interface
|
4
|
+
# Provides common methods for viewing process history
|
6
5
|
module Morpheus::Cli::ProcessesHelper
|
7
6
|
|
8
7
|
def self.included(klass)
|
@@ -57,9 +57,9 @@ module Morpheus::Cli::ProvisioningHelper
|
|
57
57
|
@api_client.accounts
|
58
58
|
end
|
59
59
|
|
60
|
-
def get_available_groups(refresh=false)
|
60
|
+
def get_available_groups(params = {}, refresh=false)
|
61
61
|
if !@available_groups || refresh
|
62
|
-
option_results = options_interface.options_for_source('groups',
|
62
|
+
option_results = options_interface.options_for_source('groups', params)
|
63
63
|
@available_groups = option_results['data'].collect {|it|
|
64
64
|
{"id" => it["value"], "name" => it["name"], "value" => it["value"]}
|
65
65
|
}
|
@@ -68,9 +68,9 @@ module Morpheus::Cli::ProvisioningHelper
|
|
68
68
|
return @available_groups
|
69
69
|
end
|
70
70
|
|
71
|
-
def get_available_clouds(group_id, refresh=false)
|
71
|
+
def get_available_clouds(group_id, params = {}, refresh=false)
|
72
72
|
if !group_id
|
73
|
-
option_results = options_interface.options_for_source('clouds', {'default' => 'false'})
|
73
|
+
option_results = options_interface.options_for_source('clouds', params.merge({'default' => 'false'}))
|
74
74
|
return option_results['data'].collect {|it|
|
75
75
|
{"id" => it["value"], "name" => it["name"], "value" => it["value"], "zoneTypeId" => it["zoneTypeId"]}
|
76
76
|
}
|
@@ -80,7 +80,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
80
80
|
return []
|
81
81
|
end
|
82
82
|
if !group["clouds"] || refresh
|
83
|
-
option_results = options_interface.options_for_source('clouds', {groupId: group_id})
|
83
|
+
option_results = options_interface.options_for_source('clouds', params.merge({groupId: group_id}))
|
84
84
|
group["clouds"] = option_results['data'].collect {|it|
|
85
85
|
{"id" => it["value"], "name" => it["name"], "value" => it["value"], "zoneTypeId" => it["zoneTypeId"]}
|
86
86
|
}
|
@@ -942,6 +942,7 @@ module Morpheus::Cli::ProvisioningHelper
|
|
942
942
|
# prompt for option types
|
943
943
|
api_params['config'] = payload['config'] if payload['config']
|
944
944
|
api_params['poolId'] = payload['config']['resourcePoolId'] if payload['config'] && payload['config']['resourcePoolId']
|
945
|
+
api_params['resourcePoolId'] = api_params['poolId']
|
945
946
|
|
946
947
|
# set option type defaults from config
|
947
948
|
if options[:default_config]
|
@@ -2093,6 +2094,15 @@ module Morpheus::Cli::ProvisioningHelper
|
|
2093
2094
|
permissions
|
2094
2095
|
end
|
2095
2096
|
|
2097
|
+
def prompt_permissions_v2(options, excludes = [])
|
2098
|
+
perms = prompt_permissions(options, excludes)
|
2099
|
+
rtn = {}
|
2100
|
+
|
2101
|
+
rtn['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil?
|
2102
|
+
rtn['tenants'] = ((perms['tenantPermissions'] || {})['accounts'] || []).collect {|it| {'id' => it}}
|
2103
|
+
rtn
|
2104
|
+
end
|
2105
|
+
|
2096
2106
|
def print_permissions(permissions, excludes = [])
|
2097
2107
|
if permissions.nil?
|
2098
2108
|
print_h2 "Permissions"
|