morpheus-cli 4.2.20 → 5.0.2
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/api_client.rb +26 -0
- data/lib/morpheus/api/billing_interface.rb +34 -0
- data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
- data/lib/morpheus/api/deploy_interface.rb +1 -1
- data/lib/morpheus/api/deployments_interface.rb +20 -1
- data/lib/morpheus/api/forgot_password_interface.rb +17 -0
- data/lib/morpheus/api/instances_interface.rb +7 -0
- data/lib/morpheus/api/rest_interface.rb +0 -6
- data/lib/morpheus/api/roles_interface.rb +14 -0
- data/lib/morpheus/api/search_interface.rb +13 -0
- data/lib/morpheus/api/servers_interface.rb +7 -0
- data/lib/morpheus/api/usage_interface.rb +18 -0
- data/lib/morpheus/cli.rb +6 -3
- data/lib/morpheus/cli/apps.rb +3 -4
- data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
- data/lib/morpheus/cli/backups_command.rb +3 -0
- data/lib/morpheus/cli/budgets_command.rb +4 -4
- data/lib/morpheus/cli/catalog_command.rb +507 -0
- data/lib/morpheus/cli/cli_command.rb +45 -20
- data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -12
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
- data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
- data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
- data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
- data/lib/morpheus/cli/containers_command.rb +14 -0
- data/lib/morpheus/cli/deploy.rb +199 -90
- data/lib/morpheus/cli/deployments.rb +342 -29
- data/lib/morpheus/cli/deploys.rb +206 -41
- data/lib/morpheus/cli/error_handler.rb +7 -0
- data/lib/morpheus/cli/forgot_password.rb +133 -0
- data/lib/morpheus/cli/groups.rb +1 -1
- data/lib/morpheus/cli/health_command.rb +2 -2
- data/lib/morpheus/cli/hosts.rb +181 -26
- data/lib/morpheus/cli/instances.rb +102 -33
- data/lib/morpheus/cli/invoices_command.rb +33 -16
- data/lib/morpheus/cli/jobs_command.rb +28 -6
- data/lib/morpheus/cli/library_option_lists_command.rb +14 -6
- data/lib/morpheus/cli/logs_command.rb +9 -6
- data/lib/morpheus/cli/mixins/accounts_helper.rb +7 -6
- data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
- data/lib/morpheus/cli/mixins/catalog_helper.rb +66 -0
- data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -3
- data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +46 -21
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +24 -4
- data/lib/morpheus/cli/network_pools_command.rb +14 -6
- data/lib/morpheus/cli/option_types.rb +266 -17
- data/lib/morpheus/cli/ping.rb +0 -1
- data/lib/morpheus/cli/provisioning_licenses_command.rb +2 -2
- data/lib/morpheus/cli/remote.rb +35 -12
- data/lib/morpheus/cli/reports_command.rb +99 -30
- data/lib/morpheus/cli/roles.rb +305 -3
- data/lib/morpheus/cli/search_command.rb +182 -0
- data/lib/morpheus/cli/service_plans_command.rb +2 -2
- data/lib/morpheus/cli/setup.rb +1 -1
- data/lib/morpheus/cli/shell.rb +33 -11
- data/lib/morpheus/cli/storage_providers_command.rb +40 -56
- data/lib/morpheus/cli/tasks.rb +20 -21
- data/lib/morpheus/cli/tenants_command.rb +1 -1
- data/lib/morpheus/cli/usage_command.rb +203 -0
- data/lib/morpheus/cli/user_settings_command.rb +1 -0
- data/lib/morpheus/cli/users.rb +12 -1
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +280 -199
- data/lib/morpheus/cli/whoami.rb +6 -6
- data/lib/morpheus/cli/workflows.rb +34 -41
- data/lib/morpheus/formatters.rb +48 -5
- data/lib/morpheus/terminal.rb +6 -2
- metadata +13 -2
@@ -295,7 +295,7 @@ EOT
|
|
295
295
|
[
|
296
296
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
297
297
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
|
298
|
-
{'fieldContext' => 'role', 'fieldName' => 'id', 'fieldLabel' => 'Base Role', 'type' => 'select', 'optionSource' => lambda {
|
298
|
+
{'fieldContext' => 'role', 'fieldName' => 'id', 'fieldLabel' => 'Base Role', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
299
299
|
@roles_interface.list(nil, {roleType:'account'})['roles'].collect {|it|
|
300
300
|
{"name" => (it["authority"] || it["name"]), "value" => it["id"]}
|
301
301
|
}
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
# CLI command usages
|
4
|
+
# UI is Costing - Usage
|
5
|
+
# API is /usage and returns usages
|
6
|
+
class Morpheus::Cli::UsageCommand
|
7
|
+
include Morpheus::Cli::CliCommand
|
8
|
+
include Morpheus::Cli::OptionSourceHelper
|
9
|
+
|
10
|
+
set_command_name :'usage'
|
11
|
+
|
12
|
+
register_subcommands :list, :get
|
13
|
+
|
14
|
+
def connect(opts)
|
15
|
+
@api_client = establish_remote_appliance_connection(opts)
|
16
|
+
@usage_interface = @api_client.usage
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle(args)
|
20
|
+
handle_subcommand(args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def list(args)
|
24
|
+
options = {}
|
25
|
+
params = {}
|
26
|
+
ref_ids = []
|
27
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
28
|
+
opts.banner = subcommand_usage("[search]")
|
29
|
+
opts.on( '-t', '--type TYPE', "Filter by type" ) do |val|
|
30
|
+
params['type'] = parse_usage_type(val)
|
31
|
+
end
|
32
|
+
opts.on( '-c', '--cloud CLOUD', "Filter by cloud" ) do |val|
|
33
|
+
options[:cloud] = val
|
34
|
+
end
|
35
|
+
opts.on('--start DATE', String, "Start date in the format YYYY-MM-DD.") do |val|
|
36
|
+
params['startDate'] = val # parse_time(val).utc.iso8601
|
37
|
+
end
|
38
|
+
opts.on('--end DATE', String, "End date in the format YYYY-MM-DD. Default is the current date.") do |val|
|
39
|
+
params['endDate'] = val # parse_time(val).utc.iso8601
|
40
|
+
end
|
41
|
+
opts.on('--sigdig DIGITS', "Significant digits when rounding cost values for display as currency. Default is 5.") do |val|
|
42
|
+
options[:sigdig] = val.to_i
|
43
|
+
end
|
44
|
+
build_standard_list_options(opts, options)
|
45
|
+
opts.footer = "List usages."
|
46
|
+
end
|
47
|
+
optparse.parse!(args)
|
48
|
+
connect(options)
|
49
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
50
|
+
if args.count > 0
|
51
|
+
options[:phrase] = args.join(" ")
|
52
|
+
end
|
53
|
+
params.merge!(parse_list_options(options))
|
54
|
+
# --cloud
|
55
|
+
if options[:cloud]
|
56
|
+
params['cloud'] = parse_id_list(options[:cloud]).collect {|cloud_id|
|
57
|
+
if cloud_id.to_s =~ /\A\d{1,}\Z/
|
58
|
+
cloud_id
|
59
|
+
else
|
60
|
+
cloud = find_cloud_option(cloud_id)
|
61
|
+
return 1 if cloud.nil?
|
62
|
+
cloud['id']
|
63
|
+
end
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
@usage_interface.setopts(options)
|
68
|
+
if options[:dry_run]
|
69
|
+
print_dry_run @usage_interface.dry.list(params)
|
70
|
+
return
|
71
|
+
end
|
72
|
+
json_response = @usage_interface.list(params)
|
73
|
+
usages = json_response[usage_list_key]
|
74
|
+
render_response(json_response, options, usage_list_key) do
|
75
|
+
print_h1 "Morpheus Usages", parse_list_subtitles(options), options
|
76
|
+
if usages.empty?
|
77
|
+
print cyan,"No usages found.",reset,"\n"
|
78
|
+
else
|
79
|
+
list_columns = {
|
80
|
+
"ID" => 'id',
|
81
|
+
"Cloud" => 'zoneName',
|
82
|
+
"Type" => lambda {|it| format_usage_type(it) },
|
83
|
+
"Name" => 'name',
|
84
|
+
"Plan" => 'planName',
|
85
|
+
"Start Date" => lambda {|it| format_local_dt(it['startDate']) },
|
86
|
+
"End Date" => lambda {|it| format_local_dt(it['endDate']) },
|
87
|
+
"Usage Status" => lambda {|it| format_usage_status(it) },
|
88
|
+
"Usage Cost" => lambda {|it| format_money(it['costDetails']['cost'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
|
89
|
+
"Usage Price" => lambda {|it| format_money(it['price'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
|
90
|
+
}
|
91
|
+
print as_pretty_table(usages, list_columns.upcase_keys!, options)
|
92
|
+
print_results_pagination(json_response)
|
93
|
+
end
|
94
|
+
print reset,"\n"
|
95
|
+
end
|
96
|
+
if usages.empty?
|
97
|
+
return 1, "no usages found"
|
98
|
+
else
|
99
|
+
return 0, nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def get(args)
|
104
|
+
params = {}
|
105
|
+
options = {}
|
106
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
107
|
+
opts.banner = subcommand_usage("[usage]")
|
108
|
+
build_standard_get_options(opts, options)
|
109
|
+
opts.footer = <<-EOT
|
110
|
+
Get details about a specific usage.
|
111
|
+
[usage] is required. This is the id of a usage record.
|
112
|
+
EOT
|
113
|
+
end
|
114
|
+
optparse.parse!(args)
|
115
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
116
|
+
connect(options)
|
117
|
+
id_list = parse_id_list(args)
|
118
|
+
return run_command_for_each_arg(id_list) do |arg|
|
119
|
+
_get(arg, params, options)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def _get(id, params, options)
|
124
|
+
usage = nil
|
125
|
+
@usage_interface.setopts(options)
|
126
|
+
if options[:dry_run]
|
127
|
+
print_dry_run @usage_interface.dry.get(id, params)
|
128
|
+
return
|
129
|
+
end
|
130
|
+
json_response = @usage_interface.get(id, params)
|
131
|
+
usage = json_response[usage_object_key]
|
132
|
+
render_response(json_response, options, usage_object_key) do
|
133
|
+
print_h1 "Usage Details", [], options
|
134
|
+
print cyan
|
135
|
+
show_columns = {
|
136
|
+
"ID" => 'id',
|
137
|
+
"Cloud" => 'zoneName',
|
138
|
+
"Type" => lambda {|it| format_usage_type(it) },
|
139
|
+
"Name" => 'name',
|
140
|
+
"Plan" => 'planName',
|
141
|
+
"Start Date" => lambda {|it| format_local_dt(it['startDate']) },
|
142
|
+
"End Date" => lambda {|it| format_local_dt(it['endDate']) },
|
143
|
+
"Usage Status" => lambda {|it| format_usage_status(it) },
|
144
|
+
"Usage Cost" => lambda {|it| format_money(it['costDetails']['cost'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
|
145
|
+
"Usage Price" => lambda {|it| format_money(it['price'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
|
146
|
+
}
|
147
|
+
print_description_list(show_columns, usage)
|
148
|
+
|
149
|
+
# print_h2 "Applicable Prices"
|
150
|
+
|
151
|
+
print reset,"\n"
|
152
|
+
end
|
153
|
+
return 0, nil
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def usage_object_key
|
159
|
+
'usage'
|
160
|
+
end
|
161
|
+
|
162
|
+
def usage_list_key
|
163
|
+
'usages'
|
164
|
+
end
|
165
|
+
|
166
|
+
def format_usage_type(usage)
|
167
|
+
#return usage['costDetails']['refType']
|
168
|
+
ref_type = usage['costDetails'] ? usage['costDetails']['refType'].to_s : ''
|
169
|
+
if ref_type == 'discoveredServer'
|
170
|
+
'Discovered'
|
171
|
+
elsif ref_type == 'computeServer'
|
172
|
+
'Host'
|
173
|
+
elsif ref_type == 'container'
|
174
|
+
'Container'
|
175
|
+
else
|
176
|
+
ref_type.to_s
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def parse_usage_type(val)
|
181
|
+
type_string = val.to_s.downcase
|
182
|
+
if type_string == 'discoveredServer'
|
183
|
+
'discoveredServer'
|
184
|
+
elsif type_string == 'host'
|
185
|
+
'computeServer'
|
186
|
+
elsif type_string == 'container'
|
187
|
+
'container'
|
188
|
+
else
|
189
|
+
val
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def format_usage_status(usage, return_color=cyan)
|
194
|
+
#return usage['status'].to_s.capitalize
|
195
|
+
status_string = usage['status'].to_s
|
196
|
+
if status_string == 'stopped'
|
197
|
+
return "#{red}#{status_string.upcase}#{return_color}"
|
198
|
+
else
|
199
|
+
return "#{green}#{status_string.upcase}#{return_color}"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
@@ -94,6 +94,7 @@ EOT
|
|
94
94
|
"Linux Key Pair" => lambda {|it| it['linuxKeyPairId'] },
|
95
95
|
"Windows Username" => lambda {|it| it['windowsUsername'] },
|
96
96
|
"Windows Password" => lambda {|it| it['windowsPassword'] },
|
97
|
+
"Default Persona" => lambda {|it| it['defaultPersona'] ? it['defaultPersona']['name'] : '' },
|
97
98
|
}
|
98
99
|
print_description_list(description_cols, user_settings)
|
99
100
|
|
data/lib/morpheus/cli/users.rb
CHANGED
@@ -161,12 +161,22 @@ class Morpheus::Cli::Users
|
|
161
161
|
options[:include_app_templates_access] = true
|
162
162
|
params['includeAccess'] = true
|
163
163
|
end
|
164
|
+
opts.on(nil,'--catalog-item-type-access', "Display Catalog Item Type Access") do
|
165
|
+
options[:include_catalog_item_types_access] = true
|
166
|
+
params['includeAccess'] = true
|
167
|
+
end
|
168
|
+
opts.on(nil,'--personas', "Display Persona Access") do
|
169
|
+
options[:include_personas_access] = true
|
170
|
+
params['includeAccess'] = true
|
171
|
+
end
|
164
172
|
opts.on(nil,'--all', "Display All Access Lists") do
|
165
173
|
options[:include_features_access] = true
|
166
174
|
options[:include_sites_access] = true
|
167
175
|
options[:include_zones_access] = true
|
168
176
|
options[:include_instance_types_access] = true
|
169
177
|
options[:include_app_templates_access] = true
|
178
|
+
options[:include_catalog_item_types_access] = true
|
179
|
+
options[:include_personas_access] = true
|
170
180
|
params['includeAccess'] = true
|
171
181
|
end
|
172
182
|
opts.on('-i', '--include-none-access', "Include Items with 'None' Access in Access List") do
|
@@ -241,7 +251,8 @@ EOT
|
|
241
251
|
puts yellow,"No permissions found.",reset
|
242
252
|
end
|
243
253
|
else
|
244
|
-
available_field_options = {'features' => 'Feature', 'sites' => 'Group', 'zones' => 'Cloud', 'instance_types' => 'Instance Type',
|
254
|
+
available_field_options = {'features' => 'Feature', 'sites' => 'Group', 'zones' => 'Cloud', 'instance_types' => 'Instance Type',
|
255
|
+
'app_templates' => 'Blueprint', 'catalog_item_types' => 'Catalog Item Types', 'personas' => 'Personas'}
|
245
256
|
available_field_options.each do |field, label|
|
246
257
|
if !(field == 'sites' && is_tenant_account) && options["include_#{field}_access".to_sym]
|
247
258
|
access = user['access'][field.split('_').enum_for(:each_with_index).collect {|word, idx| idx == 0 ? word : word.capitalize}.join]
|
data/lib/morpheus/cli/version.rb
CHANGED
@@ -27,6 +27,7 @@ class Morpheus::Cli::VirtualImages
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def list(args)
|
30
|
+
params = {}
|
30
31
|
options = {}
|
31
32
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
32
33
|
opts.banner = subcommand_usage()
|
@@ -42,42 +43,32 @@ class Morpheus::Cli::VirtualImages
|
|
42
43
|
opts.on('--system', "System Images" ) do
|
43
44
|
options[:filterType] = 'System'
|
44
45
|
end
|
45
|
-
|
46
|
+
build_standard_list_options(opts, options)
|
46
47
|
opts.footer = "List virtual images."
|
47
48
|
end
|
48
49
|
optparse.parse!(args)
|
49
50
|
connect(options)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
elsif options[:yaml]
|
70
|
-
puts as_yaml(json_response, options, "virtualImages")
|
71
|
-
return 0
|
72
|
-
elsif options[:csv]
|
73
|
-
puts records_as_csv(json_response["virtualImages"], options)
|
74
|
-
return 0
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
images = json_response['virtualImages']
|
51
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
52
|
+
if args.count > 0
|
53
|
+
options[:phrase] = args.join(" ")
|
54
|
+
end
|
55
|
+
params.merge!(parse_list_options(options))
|
56
|
+
if options[:imageType]
|
57
|
+
params[:imageType] = options[:imageType]
|
58
|
+
end
|
59
|
+
if options[:filterType]
|
60
|
+
params[:filterType] = options[:filterType]
|
61
|
+
end
|
62
|
+
@virtual_images_interface.setopts(options)
|
63
|
+
if options[:dry_run]
|
64
|
+
print_dry_run @virtual_images_interface.dry.list(params)
|
65
|
+
return
|
66
|
+
end
|
67
|
+
json_response = @virtual_images_interface.list(params)
|
68
|
+
images = json_response['virtualImages']
|
69
|
+
render_response(json_response, options, 'virtualImages') do
|
79
70
|
title = "Morpheus Virtual Images"
|
80
|
-
subtitles =
|
71
|
+
subtitles = parse_list_subtitles(options)
|
81
72
|
if options[:imageType]
|
82
73
|
subtitles << "Image Type: #{options[:imageType]}".strip
|
83
74
|
end
|
@@ -91,6 +82,7 @@ class Morpheus::Cli::VirtualImages
|
|
91
82
|
if images.empty?
|
92
83
|
print cyan,"No virtual images found.",reset,"\n"
|
93
84
|
else
|
85
|
+
# print as_pretty_table(images, virtual_image_column_definitions.upcase_keys!, options)
|
94
86
|
rows = images.collect do |image|
|
95
87
|
image_type = virtual_image_type_for_name_or_code(image['imageType'])
|
96
88
|
image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
|
@@ -103,117 +95,134 @@ class Morpheus::Cli::VirtualImages
|
|
103
95
|
print_results_pagination(json_response)
|
104
96
|
end
|
105
97
|
print reset,"\n"
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
98
|
+
end
|
99
|
+
if images.empty?
|
100
|
+
return -1, "no virtual images found"
|
101
|
+
else
|
102
|
+
return 0, nil
|
111
103
|
end
|
112
104
|
end
|
113
105
|
|
114
106
|
def get(args)
|
107
|
+
params = {}
|
115
108
|
options = {}
|
116
|
-
show_details = false
|
117
109
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
118
|
-
opts.banner = subcommand_usage("[
|
110
|
+
opts.banner = subcommand_usage("[image]")
|
119
111
|
opts.on('--details', "Show more details." ) do
|
120
|
-
|
112
|
+
options[:details] = true
|
121
113
|
end
|
122
|
-
|
123
|
-
opts.footer =
|
124
|
-
|
114
|
+
build_standard_get_options(opts, options)
|
115
|
+
opts.footer = <<-EOT
|
116
|
+
Get details about a virtual image.
|
117
|
+
[image] is required. This is the name or id of a virtual image.
|
118
|
+
EOT
|
125
119
|
end
|
126
120
|
optparse.parse!(args)
|
127
|
-
|
128
|
-
puts optparse
|
129
|
-
exit 1
|
130
|
-
end
|
131
|
-
image_name = args[0]
|
121
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
132
122
|
connect(options)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
123
|
+
id_list = parse_id_list(args)
|
124
|
+
# lookup IDs if names are given
|
125
|
+
id_list = id_list.collect do |id|
|
126
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
127
|
+
id
|
128
|
+
else
|
129
|
+
image = find_virtual_image_by_name_or_id(id)
|
130
|
+
if image
|
131
|
+
image['id']
|
138
132
|
else
|
139
|
-
|
133
|
+
raise_command_error "virtual image not found for name '#{id}'"
|
140
134
|
end
|
141
|
-
return
|
142
|
-
end
|
143
|
-
image = find_virtual_image_by_name_or_id(image_name)
|
144
|
-
return 1 if image.nil?
|
145
|
-
# refetch
|
146
|
-
json_response = @virtual_images_interface.get(image['id'])
|
147
|
-
if options[:json]
|
148
|
-
puts as_json(json_response, options, "virtualImage")
|
149
|
-
return 0
|
150
|
-
elsif options[:yaml]
|
151
|
-
puts as_yaml(json_response, options, "virtualImage")
|
152
|
-
return 0
|
153
|
-
elsif options[:csv]
|
154
|
-
puts records_as_csv([json_response["virtualImage"]], options)
|
155
|
-
return 0
|
156
135
|
end
|
136
|
+
end
|
137
|
+
return run_command_for_each_arg(id_list) do |arg|
|
138
|
+
_get(arg, params, options)
|
139
|
+
end
|
140
|
+
end
|
157
141
|
|
142
|
+
def _get(id, params, options)
|
143
|
+
@virtual_images_interface.setopts(options)
|
144
|
+
if options[:dry_run]
|
145
|
+
print_dry_run @virtual_images_interface.dry.get(id.to_i)
|
146
|
+
return
|
147
|
+
end
|
148
|
+
json_response = @virtual_images_interface.get(id.to_i)
|
158
149
|
image = json_response['virtualImage']
|
150
|
+
image_config = image['config'] || {}
|
159
151
|
image_files = json_response['cloudFiles'] || json_response['files']
|
160
|
-
|
161
|
-
|
162
152
|
image_type = virtual_image_type_for_name_or_code(image['imageType'])
|
163
153
|
image_type_display = image_type ? "#{image_type['name']}" : image['imageType']
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
"Trial Version" => lambda {|it| format_boolean it['trialVersion'] },
|
191
|
-
"Sysprep Enabled?" => lambda {|it| format_boolean it['isSysprep'] },
|
192
|
-
}
|
193
|
-
if show_details
|
194
|
-
description_cols.merge!(advanced_description_cols)
|
195
|
-
end
|
196
|
-
print_description_list(description_cols, image)
|
197
|
-
|
198
|
-
if image_files
|
199
|
-
print_h2 "Files (#{image_files.size})"
|
200
|
-
# image_files.each {|image_file|
|
201
|
-
# pretty_filesize = Filesize.from("#{image_file['size']} B").pretty
|
202
|
-
# print cyan," = #{image_file['name']} [#{pretty_filesize}]", "\n"
|
203
|
-
# }
|
204
|
-
image_file_rows = image_files.collect do |image_file|
|
205
|
-
|
206
|
-
{filename: image_file['name'], size: Filesize.from("#{image_file['size']} B").pretty}
|
154
|
+
render_response(json_response, options, 'virtualImage') do
|
155
|
+
print_h1 "Virtual Image Details", [], options
|
156
|
+
description_cols = {
|
157
|
+
"ID" => 'id',
|
158
|
+
"Name" => 'name',
|
159
|
+
"Type" => lambda {|it| image_type_display },
|
160
|
+
"Storage" => lambda {|it| !image['storageProvider'].nil? ? image['storageProvider']['name'] : 'Default' },
|
161
|
+
"Size" => lambda {|it| image['rawSize'].nil? ? 'Unknown' : "#{Filesize.from("#{image['rawSize']} B").pretty}" },
|
162
|
+
"Azure Publisher" => lambda {|it| image_config['publisher'] },
|
163
|
+
"Azure Offer" => lambda {|it| image_config['offer'] },
|
164
|
+
"Azure Sku" => lambda {|it| image_config['sku'] },
|
165
|
+
"Azure Version" => lambda {|it| image_config['version'] },
|
166
|
+
"Source" => lambda {|it| image['userUploaded'] ? "#{green}UPLOADED#{cyan}" : (image['systemImage'] ? 'SYSTEM' : "#{white}SYNCED#{cyan}") },
|
167
|
+
# "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
168
|
+
# "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
169
|
+
}
|
170
|
+
if image['imageType'] == "azure-reference" || image['imageType'] == "azure"
|
171
|
+
description_cols.delete("Size")
|
172
|
+
description_cols.delete("Storage")
|
173
|
+
description_cols["Source"] = lambda {|it| "#{bold}#{cyan}AZURE#{reset}#{cyan}" }
|
174
|
+
else
|
175
|
+
description_cols.delete("Azure Marketplace")
|
176
|
+
description_cols.delete("Azure Marketplace Publisher")
|
177
|
+
description_cols.delete("Azure Marketplace Sku")
|
178
|
+
description_cols.delete("Azure Marketplace Offer")
|
179
|
+
description_cols.delete("Azure Marketplace Version")
|
207
180
|
end
|
208
|
-
|
209
|
-
|
210
|
-
|
181
|
+
advanced_description_cols = {
|
182
|
+
"OS Type" => lambda {|it| it['osType'] ? it['osType']['name'] : "" },
|
183
|
+
"Min Memory" => lambda {|it| it['minRam'].to_i != 0 ? Filesize.from("#{it['minRam']} B").pretty : "" },
|
184
|
+
"Cloud Init?" => lambda {|it| format_boolean it['osType'] },
|
185
|
+
"Install Agent?" => lambda {|it| format_boolean it['osType'] },
|
186
|
+
"SSH Username" => lambda {|it| it['sshUsername'] },
|
187
|
+
"SSH Password" => lambda {|it| it['sshPassword'] },
|
188
|
+
"User Data" => lambda {|it| it['userData'] },
|
189
|
+
"Visibility" => lambda {|it| it['visibility'].to_s.capitalize },
|
190
|
+
"Tenants" => lambda {|it| format_tenants(it['accounts']) },
|
191
|
+
"Auto Join Domain?" => lambda {|it| format_boolean it['isAutoJoinDomain'] },
|
192
|
+
"VirtIO Drivers Loaded?" => lambda {|it| format_boolean it['virtioSupported'] },
|
193
|
+
"VM Tools Installed?" => lambda {|it| format_boolean it['vmToolsInstalled'] },
|
194
|
+
"Force Guest Customization?" => lambda {|it| format_boolean it['isForceCustomization'] },
|
195
|
+
"Trial Version" => lambda {|it| format_boolean it['trialVersion'] },
|
196
|
+
"Sysprep Enabled?" => lambda {|it| format_boolean it['isSysprep'] },
|
197
|
+
}
|
198
|
+
if options[:details]
|
199
|
+
description_cols.merge!(advanced_description_cols)
|
200
|
+
end
|
201
|
+
print_description_list(description_cols, image)
|
202
|
+
|
203
|
+
if image_files
|
204
|
+
print_h2 "Files (#{image_files.size})"
|
205
|
+
# image_files.each {|image_file|
|
206
|
+
# pretty_filesize = Filesize.from("#{image_file['size']} B").pretty
|
207
|
+
# print cyan," = #{image_file['name']} [#{pretty_filesize}]", "\n"
|
208
|
+
# }
|
209
|
+
image_file_rows = image_files.collect do |image_file|
|
210
|
+
{filename: image_file['name'], size: Filesize.from("#{image_file['size']} B").pretty}
|
211
|
+
end
|
212
|
+
print cyan
|
213
|
+
print as_pretty_table(image_file_rows, [:filename, :size])
|
214
|
+
# print reset,"\n"
|
215
|
+
end
|
216
|
+
|
217
|
+
if options[:details] && image_config && !image_config.empty?
|
218
|
+
print_h2 "Config", options
|
219
|
+
print cyan
|
220
|
+
print as_description_list(image_config, image_config.keys, options)
|
221
|
+
print "\n", reset
|
222
|
+
end
|
223
|
+
print reset,"\n"
|
211
224
|
end
|
212
|
-
|
213
|
-
rescue RestClient::Exception => e
|
214
|
-
print_rest_exception(e, options)
|
215
|
-
exit 1
|
216
|
-
end
|
225
|
+
return 0, nil
|
217
226
|
end
|
218
227
|
|
219
228
|
def update(args)
|
@@ -339,6 +348,19 @@ class Morpheus::Cli::VirtualImages
|
|
339
348
|
opts.on( '-U', '--url URL', "Image File URL. This can be used instead of uploading local files." ) do |val|
|
340
349
|
file_url = val
|
341
350
|
end
|
351
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud to scope image to, certain types require a cloud to be selected, eg. Azure Reference" ) do |val|
|
352
|
+
# options[:cloud] = val
|
353
|
+
options[:options]['cloud'] = val
|
354
|
+
end
|
355
|
+
opts.on( '--azure-offer OFFER', String, "Azure Reference offer value, only applies to Azure Reference" ) do |val|
|
356
|
+
options[:options]['offer'] = val
|
357
|
+
end
|
358
|
+
opts.on( '--azure-sku SKU', String, "Azure SKU value, only applies to Azure Reference" ) do |val|
|
359
|
+
options[:options]['sku'] = val
|
360
|
+
end
|
361
|
+
opts.on( '--azure-version VERSION', String, "Azure Version value, only applies to Azure Reference" ) do |val|
|
362
|
+
options[:options]['version'] = val
|
363
|
+
end
|
342
364
|
opts.on('--tenants LIST', Array, "Tenant Access, comma separated list of account IDs") do |list|
|
343
365
|
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
344
366
|
tenants_list = []
|
@@ -346,7 +368,10 @@ class Morpheus::Cli::VirtualImages
|
|
346
368
|
tenants_list = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
347
369
|
end
|
348
370
|
end
|
349
|
-
|
371
|
+
# build_option_type_options(opts, options, add_virtual_image_option_types)
|
372
|
+
# build_option_type_options(opts, options, add_virtual_image_advanced_option_types)
|
373
|
+
build_standard_add_options(opts, options)
|
374
|
+
|
350
375
|
opts.footer = "Create a virtual image."
|
351
376
|
end
|
352
377
|
optparse.parse!(args)
|
@@ -368,26 +393,43 @@ class Morpheus::Cli::VirtualImages
|
|
368
393
|
options[:options]['name'] ||= image_name
|
369
394
|
end
|
370
395
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
396
|
+
payload = {}
|
397
|
+
if options[:payload]
|
398
|
+
payload = options[:payload]
|
399
|
+
payload.deep_merge!({'virtualImage' => parse_passed_options(options)})
|
400
|
+
else
|
401
|
+
payload.deep_merge!({'virtualImage' => parse_passed_options(options)})
|
402
|
+
virtual_image_payload = {}
|
403
|
+
# v_prompt = Morpheus::Cli::OptionTypes.prompt(add_virtual_image_option_types, options[:options], @api_client, options[:params])
|
404
|
+
if image_type_name
|
405
|
+
image_type = virtual_image_type_for_name_or_code(image_type_name)
|
406
|
+
# fix issue with api returning imageType vmware instead of vmdk
|
407
|
+
if image_type.nil? && image_type_name == 'vmware'
|
408
|
+
image_type = virtual_image_type_for_name_or_code('vmdk')
|
409
|
+
elsif image_type.nil? && image_type_name == 'vmdk'
|
410
|
+
image_type = virtual_image_type_for_name_or_code('vmware')
|
411
|
+
end
|
412
|
+
if image_type.nil?
|
413
|
+
print_red_alert "Virtual Image Type not found by code '#{image_type_name}'"
|
414
|
+
return 1
|
415
|
+
end
|
416
|
+
# options[:options] ||= {}
|
417
|
+
# options[:options]['imageType'] ||= image_type['code']
|
418
|
+
else
|
419
|
+
image_type_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'imageType', 'fieldLabel' => 'Image Type', 'type' => 'select', 'optionSource' => 'virtualImageTypes', 'required' => true, 'description' => 'Select Virtual Image Type.', 'displayOrder' => 2}],options[:options],@api_client,{})
|
420
|
+
image_type = virtual_image_type_for_name_or_code(image_type_prompt['imageType'])
|
378
421
|
end
|
379
|
-
|
380
|
-
|
381
|
-
|
422
|
+
|
423
|
+
# azure requires us to search the marketplace to select publisher, cloud, offerm sku
|
424
|
+
if image_type['code'] == "azure-reference" || image_type['code'] == "azure"
|
425
|
+
cloud_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'cloud', 'fieldLabel' => 'Cloud', 'type' => 'select', 'optionSource' => 'clouds', 'required' => true, 'description' => 'Select Azure Cloud.', :fmt=>:natural}],options[:options],@api_client, {zoneTypeWhiteList: 'azure'})
|
426
|
+
cloud_id = cloud_prompt['cloud'].to_i
|
427
|
+
|
428
|
+
marketplace_config = prompt_azure_marketplace(cloud_id, options)
|
429
|
+
virtual_image_payload['config'] ||= {}
|
430
|
+
virtual_image_payload['config'].deep_merge!(marketplace_config)
|
382
431
|
end
|
383
|
-
# options[:options] ||= {}
|
384
|
-
# options[:options]['imageType'] ||= image_type['code']
|
385
|
-
else
|
386
|
-
image_type_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'imageType', 'fieldLabel' => 'Image Type', 'type' => 'select', 'optionSource' => 'virtualImageTypes', 'required' => true, 'description' => 'Select Virtual Image Type.', 'displayOrder' => 2}],options[:options],@api_client,{})
|
387
|
-
image_type = virtual_image_type_for_name_or_code(image_type_prompt['imageType'])
|
388
|
-
end
|
389
432
|
|
390
|
-
begin
|
391
433
|
my_option_types = add_virtual_image_option_types(image_type, !file_url)
|
392
434
|
# if options[:no_prompt]
|
393
435
|
# my_option_types.each do |it|
|
@@ -396,9 +438,9 @@ class Morpheus::Cli::VirtualImages
|
|
396
438
|
# end
|
397
439
|
# end
|
398
440
|
# end
|
399
|
-
|
400
|
-
|
401
|
-
virtual_image_payload
|
441
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(my_option_types, options[:options], @api_client, options[:params])
|
442
|
+
v_prompt.deep_compact!
|
443
|
+
virtual_image_payload.deep_merge!(v_prompt)
|
402
444
|
virtual_image_files = virtual_image_payload.delete('virtualImageFiles')
|
403
445
|
virtual_image_payload['imageType'] = image_type['code']
|
404
446
|
storage_provider_id = virtual_image_payload.delete('storageProviderId')
|
@@ -412,61 +454,62 @@ class Morpheus::Cli::VirtualImages
|
|
412
454
|
if virtual_image_payload && virtual_image_payload['imageType'] == 'vmware'
|
413
455
|
virtual_image_payload['imageType'] == 'vmdk'
|
414
456
|
end
|
415
|
-
payload = {virtualImage
|
416
|
-
|
417
|
-
|
418
|
-
print_dry_run @virtual_images_interface.dry.create(payload)
|
419
|
-
if file_url
|
420
|
-
print_dry_run @virtual_images_interface.dry.upload_by_url(":id", file_url, file_name)
|
421
|
-
elsif virtual_image_files && !virtual_image_files.empty?
|
422
|
-
virtual_image_files.each do |key, filepath|
|
423
|
-
print_dry_run @virtual_images_interface.dry.upload(":id", "(Contents of file #{filepath})")
|
424
|
-
end
|
425
|
-
end
|
426
|
-
return
|
427
|
-
end
|
428
|
-
|
429
|
-
json_response = @virtual_images_interface.create(payload)
|
430
|
-
virtual_image = json_response['virtualImage']
|
431
|
-
|
432
|
-
if options[:json]
|
433
|
-
print JSON.pretty_generate(json_response)
|
434
|
-
elsif !options[:quiet]
|
435
|
-
print "\n", cyan, "Virtual Image #{virtual_image['name']} created successfully", reset, "\n\n"
|
436
|
-
end
|
457
|
+
#payload = {'virtualImage' => virtual_image_payload}
|
458
|
+
payload.deep_merge!({'virtualImage' => virtual_image_payload})
|
459
|
+
end
|
437
460
|
|
438
|
-
|
461
|
+
@virtual_images_interface.setopts(options)
|
462
|
+
if options[:dry_run]
|
463
|
+
print_dry_run @virtual_images_interface.dry.create(payload)
|
439
464
|
if file_url
|
440
|
-
|
441
|
-
print cyan, "Uploading file by url #{file_url} ...", reset, "\n"
|
442
|
-
end
|
443
|
-
upload_json_response = @virtual_images_interface.upload_by_url(virtual_image['id'], file_url, file_name)
|
444
|
-
if options[:json]
|
445
|
-
print JSON.pretty_generate(upload_json_response)
|
446
|
-
end
|
465
|
+
print_dry_run @virtual_images_interface.dry.upload_by_url(":id", file_url, file_name)
|
447
466
|
elsif virtual_image_files && !virtual_image_files.empty?
|
448
467
|
virtual_image_files.each do |key, filepath|
|
449
|
-
|
450
|
-
print cyan, "Uploading file (#{key}) #{filepath} ...", reset, "\n"
|
451
|
-
end
|
452
|
-
image_file = File.new(filepath, 'rb')
|
453
|
-
upload_json_response = @virtual_images_interface.upload(virtual_image['id'], image_file, file_name)
|
454
|
-
if options[:json]
|
455
|
-
print JSON.pretty_generate(upload_json_response)
|
456
|
-
end
|
468
|
+
print_dry_run @virtual_images_interface.dry.upload(":id", "(Contents of file #{filepath})")
|
457
469
|
end
|
458
|
-
else
|
459
|
-
puts cyan, "No files uploaded.", reset
|
460
470
|
end
|
471
|
+
return
|
472
|
+
end
|
461
473
|
|
462
|
-
|
463
|
-
|
474
|
+
json_response = @virtual_images_interface.create(payload)
|
475
|
+
virtual_image = json_response['virtualImage']
|
476
|
+
|
477
|
+
# if options[:json]
|
478
|
+
# print JSON.pretty_generate(json_response)
|
479
|
+
# elsif !options[:quiet]
|
480
|
+
# print "\n", cyan, "Virtual Image #{virtual_image['name']} created successfully", reset, "\n\n"
|
481
|
+
# end
|
482
|
+
|
483
|
+
# now upload the file, do this in the background maybe?
|
484
|
+
if file_url
|
485
|
+
unless options[:quiet]
|
486
|
+
print cyan, "Uploading file by url #{file_url} ...", reset, "\n"
|
487
|
+
end
|
488
|
+
upload_json_response = @virtual_images_interface.upload_by_url(virtual_image['id'], file_url, file_name)
|
489
|
+
# if options[:json]
|
490
|
+
# print JSON.pretty_generate(upload_json_response)
|
491
|
+
# end
|
492
|
+
elsif virtual_image_files && !virtual_image_files.empty?
|
493
|
+
virtual_image_files.each do |key, filepath|
|
494
|
+
unless options[:quiet]
|
495
|
+
print cyan, "Uploading file (#{key}) #{filepath} ...", reset, "\n"
|
496
|
+
end
|
497
|
+
image_file = File.new(filepath, 'rb')
|
498
|
+
upload_json_response = @virtual_images_interface.upload(virtual_image['id'], image_file, file_name)
|
499
|
+
# if options[:json]
|
500
|
+
# print JSON.pretty_generate(upload_json_response)
|
501
|
+
# end
|
464
502
|
end
|
503
|
+
else
|
504
|
+
# puts cyan, "No files uploaded.", reset
|
505
|
+
end
|
465
506
|
|
466
|
-
|
467
|
-
|
468
|
-
|
507
|
+
render_response(json_response, options, 'virtualImage') do
|
508
|
+
print_green_success "Added virtual image #{virtual_image['name']}"
|
509
|
+
return _get(virtual_image["id"], {}, options)
|
469
510
|
end
|
511
|
+
return 0, nil
|
512
|
+
|
470
513
|
end
|
471
514
|
|
472
515
|
def add_file(args)
|
@@ -678,11 +721,11 @@ class Morpheus::Cli::VirtualImages
|
|
678
721
|
#{'fieldName' => 'imageType', 'fieldLabel' => 'Image Type', 'type' => 'select', 'optionSource' => 'virtualImageTypes', 'required' => true, 'description' => 'Select Virtual Image Type.', 'displayOrder' => 2},
|
679
722
|
{'fieldName' => 'osType', 'fieldLabel' => 'OS Type', 'type' => 'select', 'optionSource' => 'osTypes', 'required' => false, 'description' => 'Select OS Type.', 'displayOrder' => 3},
|
680
723
|
{'fieldName' => 'minRam', 'fieldLabel' => 'Minimum Memory (MB)', 'type' => 'number', 'required' => false, 'description' => 'Minimum Memory (MB)', 'displayOrder' => 4},
|
681
|
-
{'fieldName' => 'isCloudInit', 'fieldLabel' => 'Cloud Init Enabled?', 'type' => 'checkbox', 'required' => false, 'description' => 'Cloud Init Enabled?', 'displayOrder' =>
|
682
|
-
{'fieldName' => 'installAgent', 'fieldLabel' => 'Install Agent?', 'type' => 'checkbox', 'required' => false, 'description' => 'Install Agent?', 'displayOrder' =>
|
683
|
-
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text', 'required' => false, 'description' => 'Enter an SSH Username', 'displayOrder' =>
|
684
|
-
{'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false, 'description' => 'Enter an SSH Password', 'displayOrder' =>
|
685
|
-
{'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Storage Provider', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.', 'displayOrder' =>
|
724
|
+
{'fieldName' => 'isCloudInit', 'fieldLabel' => 'Cloud Init Enabled?', 'type' => 'checkbox', 'required' => false, 'description' => 'Cloud Init Enabled?', 'displayOrder' => 5},
|
725
|
+
{'fieldName' => 'installAgent', 'fieldLabel' => 'Install Agent?', 'type' => 'checkbox', 'required' => false, 'description' => 'Install Agent?', 'displayOrder' => 6},
|
726
|
+
{'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text', 'required' => false, 'description' => 'Enter an SSH Username', 'displayOrder' => 7},
|
727
|
+
{'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false, 'description' => 'Enter an SSH Password', 'displayOrder' => 8},
|
728
|
+
{'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Storage Provider', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.', 'displayOrder' => 9},
|
686
729
|
{'fieldName' => 'userData', 'fieldLabel' => 'Cloud-Init User Data', 'type' => 'textarea', 'required' => false, 'displayOrder' => 10},
|
687
730
|
{'fieldName' => 'visibility', 'fieldLabel' => 'Visibility', 'type' => 'select', 'selectOptions' => [{'name' => 'Private', 'value' => 'private'},{'name' => 'Public', 'value' => 'public'}], 'required' => false, 'description' => 'Visibility', 'category' => 'permissions', 'defaultValue' => 'private', 'displayOrder' => 40},
|
688
731
|
{'fieldName' => 'isAutoJoinDomain', 'fieldLabel' => 'Auto Join Domain?', 'type' => 'checkbox', 'required' => false, 'description' => 'Auto Join Domain?', 'category' => 'advanced', 'displayOrder' => 40},
|
@@ -696,22 +739,25 @@ class Morpheus::Cli::VirtualImages
|
|
696
739
|
image_type_code = image_type ? image_type['code'] : nil
|
697
740
|
if image_type_code
|
698
741
|
if image_type_code == 'ami'
|
699
|
-
tmp_option_types << {'fieldName' => 'externalId', 'fieldLabel' => 'AMI id', 'type' => 'text', 'required' => false, 'displayOrder' =>
|
742
|
+
tmp_option_types << {'fieldName' => 'externalId', 'fieldLabel' => 'AMI id', 'type' => 'text', 'required' => false, 'displayOrder' => 11}
|
700
743
|
if include_file_selection
|
701
|
-
tmp_option_types << {'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'displayOrder' =>
|
744
|
+
tmp_option_types << {'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'displayOrder' => 12}
|
702
745
|
end
|
703
746
|
elsif image_type_code == 'vmware' || image_type_code == 'vmdk'
|
704
747
|
if include_file_selection
|
705
|
-
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'OVF File', 'type' => 'file', 'required' => false, 'displayOrder' =>
|
706
|
-
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageDescriptorFile', 'fieldLabel' => 'VMDK File', 'type' => 'file', 'required' => false, 'displayOrder' =>
|
748
|
+
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'OVF File', 'type' => 'file', 'required' => false, 'displayOrder' => 11}
|
749
|
+
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageDescriptorFile', 'fieldLabel' => 'VMDK File', 'type' => 'file', 'required' => false, 'displayOrder' => 12}
|
707
750
|
end
|
708
751
|
elsif image_type_code == 'pxe'
|
709
|
-
tmp_option_types << {'fieldName' => 'config.menu', 'fieldLabel' => 'Menu', 'type' => 'text', 'required' => false, 'displayOrder' =>
|
710
|
-
tmp_option_types << {'fieldName' => 'imagePath', 'fieldLabel' => 'Image Path', 'type' => 'text', 'required' => true, 'displayOrder' =>
|
752
|
+
tmp_option_types << {'fieldName' => 'config.menu', 'fieldLabel' => 'Menu', 'type' => 'text', 'required' => false, 'displayOrder' => 11}
|
753
|
+
tmp_option_types << {'fieldName' => 'imagePath', 'fieldLabel' => 'Image Path', 'type' => 'text', 'required' => true, 'displayOrder' => 12}
|
711
754
|
tmp_option_types.reject! {|opt| ['isCloudInit', 'installAgent', 'sshUsername', 'sshPassword'].include?(opt['fieldName'])}
|
755
|
+
elsif image_type_code == 'azure' || image_type_code == 'azure-reference'
|
756
|
+
# Azure Marketplace Prompt happens elsewhere
|
757
|
+
tmp_option_types.reject! {|opt| ['storageProviderId', 'userData', 'sshUsername', 'sshPassword'].include?(opt['fieldName'])}
|
712
758
|
else
|
713
759
|
if include_file_selection
|
714
|
-
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'description' => 'Choose an image file to upload', 'displayOrder' =>
|
760
|
+
tmp_option_types << {'fieldContext' => 'virtualImageFiles', 'fieldName' => 'imageFile', 'fieldLabel' => 'Image File', 'type' => 'file', 'required' => false, 'description' => 'Choose an image file to upload', 'displayOrder' => 11}
|
715
761
|
end
|
716
762
|
end
|
717
763
|
end
|
@@ -735,5 +781,40 @@ class Morpheus::Cli::VirtualImages
|
|
735
781
|
""
|
736
782
|
end
|
737
783
|
end
|
784
|
+
|
785
|
+
def prompt_azure_marketplace(cloud_id, options)
|
786
|
+
rtn = {}
|
787
|
+
publisher_value, offer_value, sku_value, version_value = nil, nil, nil, nil
|
788
|
+
|
789
|
+
# Marketplace Publisher & Offer
|
790
|
+
marketplace_api_params = {'zoneId' => cloud_id}
|
791
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'offer', 'fieldLabel' => 'Azure Marketplace Offer', 'type' => 'typeahead', 'optionSource' => 'searchAzureMarketplace', 'required' => true, 'description' => "Select Azure Marketplace Offer."}], options[:options],@api_client, marketplace_api_params)
|
792
|
+
# offer_value = v_prompt['marketplace']
|
793
|
+
# actually need both offer and publisher of these to query correctly..sigh
|
794
|
+
marketplace_option = Morpheus::Cli::OptionTypes.get_last_select()
|
795
|
+
offer_value = marketplace_option['offer']
|
796
|
+
publisher_value = marketplace_option['publisher']
|
797
|
+
|
798
|
+
# SKU & VERSION
|
799
|
+
if options[:options] && options[:options]['sku'] && options[:options]['version']
|
800
|
+
# the value to match on is actually sku|version
|
801
|
+
options[:options]['sku'] = options[:options]['sku'] + '|' + options[:options]['version']
|
802
|
+
end
|
803
|
+
sku_api_params = {'zoneId' => cloud_id, publisher: publisher_value, offer: offer_value}
|
804
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'sku', 'fieldLabel' => 'Azure Marketplace SKU', 'type' => 'select', 'optionSource' => 'searchAzureMarketplaceSkus', 'required' => true, 'description' => "Select Azure Marketplace SKU and Version, the format is SKU|Version"}], options[:options],@api_client, sku_api_params)
|
805
|
+
# marketplace_option = Morpheus::Cli::OptionTypes.get_last_select()
|
806
|
+
# sku_value = marketplace_option['sku']
|
807
|
+
# version_value = marketplace_option['version']
|
808
|
+
sku_value = v_prompt['sku']
|
809
|
+
if sku_value && sku_value.include?("|")
|
810
|
+
sku_value, version_value = sku_value.split("|")
|
811
|
+
end
|
812
|
+
|
813
|
+
rtn['publisher'] = publisher_value
|
814
|
+
rtn['offer'] = offer_value
|
815
|
+
rtn['sku'] = sku_value
|
816
|
+
rtn['version'] = version_value
|
817
|
+
return rtn
|
818
|
+
end
|
738
819
|
|
739
820
|
end
|