morpheus-cli 4.2.22 → 5.2.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/.gitignore +1 -0
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +30 -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 +16 -2
- 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 +14 -0
- data/lib/morpheus/api/service_catalog_interface.rb +89 -0
- data/lib/morpheus/api/usage_interface.rb +18 -0
- data/lib/morpheus/cli.rb +7 -3
- data/lib/morpheus/cli/apps.rb +6 -27
- data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
- data/lib/morpheus/cli/backups_command.rb +3 -0
- data/lib/morpheus/cli/catalog_item_types_command.rb +622 -0
- data/lib/morpheus/cli/cli_command.rb +70 -21
- data/lib/morpheus/cli/commands/standard/curl_command.rb +3 -5
- 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 -24
- data/lib/morpheus/cli/cypher_command.rb +6 -2
- data/lib/morpheus/cli/deploy.rb +199 -90
- data/lib/morpheus/cli/deployments.rb +341 -28
- 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 +59 -2
- data/lib/morpheus/cli/hosts.rb +295 -35
- data/lib/morpheus/cli/instances.rb +247 -130
- data/lib/morpheus/cli/invoices_command.rb +37 -19
- data/lib/morpheus/cli/library_option_lists_command.rb +15 -7
- data/lib/morpheus/cli/library_option_types_command.rb +5 -2
- data/lib/morpheus/cli/logs_command.rb +9 -6
- data/lib/morpheus/cli/mixins/accounts_helper.rb +12 -7
- data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
- 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 +108 -5
- data/lib/morpheus/cli/option_types.rb +271 -22
- data/lib/morpheus/cli/ping.rb +0 -1
- data/lib/morpheus/cli/remote.rb +35 -12
- data/lib/morpheus/cli/reports_command.rb +99 -30
- data/lib/morpheus/cli/roles.rb +453 -113
- data/lib/morpheus/cli/search_command.rb +182 -0
- data/lib/morpheus/cli/service_catalog_command.rb +1474 -0
- 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 +29 -32
- 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 +429 -254
- data/lib/morpheus/cli/whoami.rb +6 -6
- data/lib/morpheus/cli/workflows.rb +33 -40
- data/lib/morpheus/formatters.rb +75 -7
- data/lib/morpheus/terminal.rb +6 -2
- metadata +14 -2
@@ -25,16 +25,19 @@ class Morpheus::Cli::InvoicesCommand
|
|
25
25
|
options = {}
|
26
26
|
params = {}
|
27
27
|
ref_ids = []
|
28
|
-
query_tags = {}
|
29
28
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
30
29
|
opts.banner = subcommand_usage()
|
31
30
|
opts.on('-a', '--all', "Display all details, costs and prices." ) do
|
32
31
|
options[:show_all] = true
|
32
|
+
options[:show_dates] = true
|
33
33
|
options[:show_estimates] = true
|
34
34
|
# options[:show_costs] = true
|
35
35
|
options[:show_prices] = true
|
36
36
|
# options[:show_raw_data] = true
|
37
37
|
end
|
38
|
+
opts.on('--dates', "Display Ref Start, Ref End, etc.") do |val|
|
39
|
+
options[:show_dates] = true
|
40
|
+
end
|
38
41
|
opts.on('--estimates', '--estimates', "Display all estimated costs, from usage info: Compute, Storage, Network, Extra" ) do
|
39
42
|
options[:show_estimates] = true
|
40
43
|
end
|
@@ -107,9 +110,12 @@ class Morpheus::Cli::InvoicesCommand
|
|
107
110
|
params['accountId'] = val
|
108
111
|
end
|
109
112
|
opts.on('--tags Name=Value',String, "Filter by tags.") do |val|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
+
val.split(",").each do |value_pair|
|
114
|
+
k,v = value_pair.strip.split("=")
|
115
|
+
options[:tags] ||= {}
|
116
|
+
options[:tags][k] ||= []
|
117
|
+
options[:tags][k] << (v || '')
|
118
|
+
end
|
113
119
|
end
|
114
120
|
opts.on('--raw-data', '--raw-data', "Display Raw Data, the cost data from the cloud provider's API.") do |val|
|
115
121
|
options[:show_raw_data] = true
|
@@ -169,8 +175,8 @@ class Morpheus::Cli::InvoicesCommand
|
|
169
175
|
end
|
170
176
|
params['rawData'] = true if options[:show_raw_data]
|
171
177
|
params['refId'] = ref_ids unless ref_ids.empty?
|
172
|
-
if
|
173
|
-
|
178
|
+
if options[:tags] && !options[:tags].empty?
|
179
|
+
options[:tags].each do |k,v|
|
174
180
|
params['tags.' + k] = v
|
175
181
|
end
|
176
182
|
end
|
@@ -203,6 +209,7 @@ class Morpheus::Cli::InvoicesCommand
|
|
203
209
|
{"INVOICE ID" => lambda {|it| it['id'] } },
|
204
210
|
{"TYPE" => lambda {|it| format_invoice_ref_type(it) } },
|
205
211
|
{"REF ID" => lambda {|it| it['refId'] } },
|
212
|
+
{"REF UUID" => lambda {|it| it['refUuid'] } },
|
206
213
|
{"REF NAME" => lambda {|it|
|
207
214
|
if options[:show_all]
|
208
215
|
it['refName']
|
@@ -218,9 +225,11 @@ class Morpheus::Cli::InvoicesCommand
|
|
218
225
|
{"PERIOD" => lambda {|it| format_invoice_period(it) } },
|
219
226
|
{"START" => lambda {|it| format_date(it['startDate']) } },
|
220
227
|
{"END" => lambda {|it| format_date(it['endDate']) } },
|
221
|
-
] + (options[:show_all] ? [
|
228
|
+
] + ((options[:show_dates] || options[:show_all]) ? [
|
222
229
|
{"REF START" => lambda {|it| format_dt(it['refStart']) } },
|
223
230
|
{"REF END" => lambda {|it| format_dt(it['refEnd']) } },
|
231
|
+
# {"LAST COST DATE" => lambda {|it| format_local_dt(it['lastCostDate']) } },
|
232
|
+
# {"LAST ACTUAL DATE" => lambda {|it| format_local_dt(it['lastActualDate']) } },
|
224
233
|
] : []) + [
|
225
234
|
{"COMPUTE" => lambda {|it| format_money(it['computeCost'], 'usd', {sigdig:options[:sigdig]}) } },
|
226
235
|
# {"MEMORY" => lambda {|it| format_money(it['memoryCost']) } },
|
@@ -263,7 +272,7 @@ class Morpheus::Cli::InvoicesCommand
|
|
263
272
|
{"ESTIMATE" => lambda {|it| format_boolean(it['estimate']) } },
|
264
273
|
{"ACTIVE" => lambda {|it| format_boolean(it['active']) } },
|
265
274
|
{"ITEMS" => lambda {|it| it['lineItems'].size rescue '' } },
|
266
|
-
{"TAGS" => lambda {|it| it['metadata'] ? it['metadata'].collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' } },
|
275
|
+
{"TAGS" => lambda {|it| (it['metadata'] || it['tags']) ? (it['metadata'] || it['tags']).collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' } },
|
267
276
|
]
|
268
277
|
if show_projects
|
269
278
|
columns += [
|
@@ -272,9 +281,15 @@ class Morpheus::Cli::InvoicesCommand
|
|
272
281
|
{"PROJECT TAGS" => lambda {|it| it['project'] ? truncate_string(format_metadata(it['project']['tags']), 50) : '' } },
|
273
282
|
]
|
274
283
|
end
|
284
|
+
if options[:show_dates]
|
285
|
+
columns += [
|
286
|
+
{"LAST COST DATE" => lambda {|it| format_local_dt(it['lastCostDate']) } },
|
287
|
+
{"LAST ACTUAL DATE" => lambda {|it| format_local_dt(it['lastActualDate']) } },
|
288
|
+
]
|
289
|
+
end
|
275
290
|
columns += [
|
276
291
|
{"CREATED" => lambda {|it| format_local_dt(it['dateCreated']) } },
|
277
|
-
{"UPDATED" => lambda {|it| format_local_dt(it['lastUpdated']) } }
|
292
|
+
{"UPDATED" => lambda {|it| format_local_dt(it['lastUpdated']) } },
|
278
293
|
]
|
279
294
|
if options[:show_raw_data]
|
280
295
|
columns += [{"RAW DATA" => lambda {|it| truncate_string(it['rawData'].to_s, 10) } }]
|
@@ -423,7 +438,7 @@ EOT
|
|
423
438
|
"Ref Start" => lambda {|it| format_dt(it['refStart']) },
|
424
439
|
"Ref End" => lambda {|it| format_dt(it['refEnd']) },
|
425
440
|
"Items" => lambda {|it| it['lineItems'].size rescue '' },
|
426
|
-
"Tags" => lambda {|it| it['metadata'] ? it['metadata'].collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
|
441
|
+
"Tags" => lambda {|it| (it['metadata'] || it['tags']) ? (it['metadata'] || it['tags']).collect {|m| "#{m['name']}: #{m['value']}" }.join(', ') : '' },
|
427
442
|
"Project ID" => lambda {|it| it['project'] ? it['project']['id'] : '' },
|
428
443
|
"Project Name" => lambda {|it| it['project'] ? it['project']['name'] : '' },
|
429
444
|
"Project Tags" => lambda {|it| it['project'] ? format_metadata(it['project']['tags']) : '' },
|
@@ -439,7 +454,8 @@ EOT
|
|
439
454
|
description_cols.delete("Project Name")
|
440
455
|
description_cols.delete("Project Tags")
|
441
456
|
end
|
442
|
-
|
457
|
+
tags = (invoice['metadata'] || invoice['tags'])
|
458
|
+
if tags.nil? || tags.empty?
|
443
459
|
description_cols.delete("Tags")
|
444
460
|
end
|
445
461
|
if !['ComputeServer','Instance','Container'].include?(invoice['refType'])
|
@@ -656,7 +672,6 @@ EOT
|
|
656
672
|
options = {}
|
657
673
|
params = {}
|
658
674
|
ref_ids = []
|
659
|
-
query_tags = {}
|
660
675
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
661
676
|
opts.banner = subcommand_usage()
|
662
677
|
opts.on('-a', '--all', "Display all details, costs and prices." ) do
|
@@ -744,11 +759,14 @@ EOT
|
|
744
759
|
opts.on('--tenant ID', String, "View invoice line items for a tenant. Default is your own account.") do |val|
|
745
760
|
params['accountId'] = val
|
746
761
|
end
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
762
|
+
opts.on('--tags Name=Value',String, "Filter by tags.") do |val|
|
763
|
+
val.split(",").each do |value_pair|
|
764
|
+
k,v = value_pair.strip.split("=")
|
765
|
+
options[:tags] ||= {}
|
766
|
+
options[:tags][k] ||= []
|
767
|
+
options[:tags][k] << (v || '')
|
768
|
+
end
|
769
|
+
end
|
752
770
|
opts.on('--raw-data', '--raw-data', "Display Raw Data, the cost data from the cloud provider's API.") do |val|
|
753
771
|
options[:show_raw_data] = true
|
754
772
|
end
|
@@ -808,8 +826,8 @@ EOT
|
|
808
826
|
end
|
809
827
|
params['rawData'] = true if options[:show_raw_data]
|
810
828
|
params['refId'] = ref_ids unless ref_ids.empty?
|
811
|
-
if
|
812
|
-
|
829
|
+
if options[:tags] && !options[:tags].empty?
|
830
|
+
options[:tags].each do |k,v|
|
813
831
|
params['tags.' + k] = v
|
814
832
|
end
|
815
833
|
end
|
@@ -90,6 +90,9 @@ class Morpheus::Cli::LibraryOptionListsCommand
|
|
90
90
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
91
91
|
opts.banner = subcommand_usage("[name]")
|
92
92
|
build_standard_get_options(opts, options)
|
93
|
+
opts.on(nil,'--no-items', "Do not display List Items") do |val|
|
94
|
+
options[:no_list_items] = true
|
95
|
+
end
|
93
96
|
opts.footer = "Get details about an option list.\n" +
|
94
97
|
"[name] is required. This is the name or id of an option list. Supports 1-N [name] arguments."
|
95
98
|
end
|
@@ -166,15 +169,20 @@ class Morpheus::Cli::LibraryOptionListsCommand
|
|
166
169
|
print_h2 "Translation Script"
|
167
170
|
print reset,"#{option_type_list['translationScript']}","\n",reset
|
168
171
|
end
|
172
|
+
if !option_type_list['requestScript'].empty?
|
173
|
+
print_h2 "Request Script"
|
174
|
+
print reset,"#{option_type_list['requestScript']}","\n",reset
|
175
|
+
end
|
169
176
|
end
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
177
|
+
if options[:no_list_items] != true
|
178
|
+
list_items = option_type_list['listItems']
|
179
|
+
if list_items && list_items.size > 0
|
180
|
+
print_h2 "List Items"
|
181
|
+
print as_pretty_table(list_items, [:name, :value], options)
|
182
|
+
print_results_pagination({size: list_items.size, total: list_items.size})
|
183
|
+
end
|
175
184
|
end
|
176
185
|
print reset,"\n"
|
177
|
-
|
178
186
|
rescue RestClient::Exception => e
|
179
187
|
print_rest_exception(e, options)
|
180
188
|
exit 1
|
@@ -262,7 +270,7 @@ class Morpheus::Cli::LibraryOptionListsCommand
|
|
262
270
|
else
|
263
271
|
payload = {}
|
264
272
|
payload.deep_merge!({'optionTypeList' => parse_passed_options(options)})
|
265
|
-
list_payload = Morpheus::Cli::OptionTypes.no_prompt(
|
273
|
+
list_payload = Morpheus::Cli::OptionTypes.no_prompt(update_option_type_list_option_types(), options[:options], @api_client)
|
266
274
|
if list_payload['type'] == 'rest'
|
267
275
|
# parse Source Headers
|
268
276
|
if !(payload['optionTypeList']['config'] && payload['optionTypeList']['config']['sourceHeaders'])
|
@@ -129,7 +129,7 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
129
129
|
|
130
130
|
print_h1 "Option Type Details"
|
131
131
|
print cyan
|
132
|
-
|
132
|
+
columns = {
|
133
133
|
"ID" => 'id',
|
134
134
|
"Name" => 'name',
|
135
135
|
"Description" => 'description',
|
@@ -138,11 +138,14 @@ class Morpheus::Cli::LibraryOptionTypesCommand
|
|
138
138
|
# "Field Name" => 'fieldName',
|
139
139
|
"Full Field Name" => lambda {|it| [it['fieldContext'], it['fieldName']].select {|it| !it.to_s.empty? }.join('.') },
|
140
140
|
"Type" => lambda {|it| it['type'].to_s.capitalize },
|
141
|
+
"Option List" => lambda {|it| it['optionList'] ? it['optionList']['name'] : nil },
|
141
142
|
"Placeholder" => 'placeHolder',
|
142
143
|
"Default Value" => 'defaultValue',
|
143
144
|
"Required" => lambda {|it| format_boolean(it['required']) },
|
144
145
|
"Export As Tag" => lambda {|it| it['exportMeta'].nil? ? '' : format_boolean(it['exportMeta']) },
|
145
|
-
}
|
146
|
+
}
|
147
|
+
columns.delete("Option List") if option_type['optionList'].nil?
|
148
|
+
print as_description_list(option_type, columns, options)
|
146
149
|
print reset,"\n"
|
147
150
|
return 0
|
148
151
|
rescue RestClient::Exception => e
|
@@ -34,7 +34,7 @@ class Morpheus::Cli::LogsCommand
|
|
34
34
|
options = {}
|
35
35
|
params = {}
|
36
36
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
37
|
-
opts.banner = subcommand_usage("[
|
37
|
+
opts.banner = subcommand_usage("[search]")
|
38
38
|
opts.on('--hosts HOSTS', String, "Filter logs to specific Host ID(s)") do |val|
|
39
39
|
params['servers'] = val.to_s.split(",").collect {|it| it.to_s.strip }.select {|it| it }.compact
|
40
40
|
end
|
@@ -72,18 +72,21 @@ class Morpheus::Cli::LogsCommand
|
|
72
72
|
options[:details] = true
|
73
73
|
end
|
74
74
|
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
75
|
-
opts.footer = "List logs for
|
76
|
-
"[id] is required. This is the id of a container."
|
75
|
+
opts.footer = "List logs for all hosts and containers."
|
77
76
|
end
|
78
77
|
optparse.parse!(args)
|
79
|
-
if args.count
|
80
|
-
|
78
|
+
if args.count > 0
|
79
|
+
options[:phrase] = args.join(" ")
|
81
80
|
end
|
82
81
|
connect(options)
|
83
82
|
begin
|
84
83
|
params['level'] = params['level'].collect {|it| it.to_s.upcase }.join('|') if params['level'] # api works with INFO|WARN
|
85
84
|
params.merge!(parse_list_options(options))
|
86
|
-
|
85
|
+
if params['phrase']
|
86
|
+
options.delete(:phrase)
|
87
|
+
search_phrase = params.delete('phrase')
|
88
|
+
params['query'] = search_phrase
|
89
|
+
end
|
87
90
|
params['order'] = params['direction'] unless params['direction'].nil? # old api version expects order instead of direction
|
88
91
|
params['startMs'] = (options[:start].to_i * 1000) if options[:start]
|
89
92
|
params['endMs'] = (options[:end].to_i * 1000) if options[:end]
|
@@ -136,6 +136,7 @@ module Morpheus::Cli::AccountsHelper
|
|
136
136
|
"Multitenant" => lambda {|it|
|
137
137
|
format_boolean(it['multitenant']).to_s + (it['multitenantLocked'] ? " (LOCKED)" : "")
|
138
138
|
},
|
139
|
+
"Default Persona" => lambda {|it| it['defaultPersona'] ? it['defaultPersona']['name'] : '(standard)' },
|
139
140
|
"Owner" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
|
140
141
|
#"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
141
142
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
@@ -196,7 +197,7 @@ module Morpheus::Cli::AccountsHelper
|
|
196
197
|
|
197
198
|
## Users
|
198
199
|
|
199
|
-
def user_column_definitions()
|
200
|
+
def user_column_definitions(opts={})
|
200
201
|
{
|
201
202
|
"ID" => 'id',
|
202
203
|
"Tenant" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
@@ -206,15 +207,15 @@ module Morpheus::Cli::AccountsHelper
|
|
206
207
|
"Email" => 'email',
|
207
208
|
"Role" => lambda {|it| format_user_role_names(it) },
|
208
209
|
"Notifications" => lambda {|it| it['receiveNotifications'].nil? ? '' : format_boolean(it['receiveNotifications']) },
|
209
|
-
"Status" => lambda {|it| format_user_status(it) },
|
210
|
+
"Status" => lambda {|it| format_user_status(it, opts[:color] || cyan) },
|
210
211
|
"Last Login" => lambda {|it| format_duration_ago(it['lastLoginDate']) },
|
211
212
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
212
213
|
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
213
214
|
}
|
214
215
|
end
|
215
216
|
|
216
|
-
def list_user_column_definitions()
|
217
|
-
columns = user_column_definitions
|
217
|
+
def list_user_column_definitions(opts={})
|
218
|
+
columns = user_column_definitions(opts)
|
218
219
|
columns.delete("Notifications")
|
219
220
|
return columns.upcase_keys!
|
220
221
|
end
|
@@ -261,8 +262,8 @@ module Morpheus::Cli::AccountsHelper
|
|
261
262
|
return nil
|
262
263
|
elsif users.size > 1
|
263
264
|
print_red_alert "Found #{users.size} users by username '#{username}'. Try using ID instead: #{format_list(users.collect {|it| it['id']}, 'or', 3)}"
|
264
|
-
|
265
|
-
|
265
|
+
print_error "\n"
|
266
|
+
print_error as_pretty_table(users, list_user_column_definitions({color: red}), {color: red, thin: true})
|
266
267
|
print reset,"\n"
|
267
268
|
return nil
|
268
269
|
else
|
@@ -400,7 +401,7 @@ module Morpheus::Cli::AccountsHelper
|
|
400
401
|
end
|
401
402
|
|
402
403
|
def get_access_string(access, return_color=cyan)
|
403
|
-
get_access_color(access) + access + return_color
|
404
|
+
get_access_color(access) + access.to_s + return_color.to_s
|
404
405
|
# access ||= 'none'
|
405
406
|
# if access == 'none'
|
406
407
|
# "#{white}#{access.to_s}#{return_color}"
|
@@ -425,10 +426,14 @@ module Morpheus::Cli::AccountsHelper
|
|
425
426
|
# Examples: format_permission_access("read")
|
426
427
|
# format_permission_access("custom", "full,custom,none")
|
427
428
|
def format_access_string(access, access_levels=nil, return_color=cyan)
|
429
|
+
# nevermind all this, just colorized access level
|
430
|
+
return get_access_string(access, return_color)
|
431
|
+
|
428
432
|
access = access.to_s.downcase.strip
|
429
433
|
if access.empty?
|
430
434
|
access = "none"
|
431
435
|
end
|
436
|
+
|
432
437
|
if access_levels.nil?
|
433
438
|
access_levels = ["none","read","user","full"]
|
434
439
|
elsif access_levels.is_a?(Array)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'morpheus/cli/mixins/print_helper'
|
2
2
|
# Mixin for Morpheus::Cli command classes
|
3
|
-
# Provides common methods for
|
3
|
+
# Provides common methods for backups management
|
4
4
|
module Morpheus::Cli::BackupsHelper
|
5
5
|
|
6
6
|
def self.included(klass)
|
@@ -8,13 +8,11 @@ module Morpheus::Cli::BackupsHelper
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def backups_interface
|
11
|
-
# @api_client.groups
|
12
11
|
raise "#{self.class} has not defined @backups_interface" if @backups_interface.nil?
|
13
12
|
@backups_interface
|
14
13
|
end
|
15
14
|
|
16
|
-
def
|
17
|
-
# @api_client.groups
|
15
|
+
def backup_jobs_interfaces
|
18
16
|
raise "#{self.class} has not defined @backup_jobs_interface" if @backup_jobs_interface.nil?
|
19
17
|
@backup_jobs_interface
|
20
18
|
end
|
@@ -10,7 +10,6 @@ module Morpheus::Cli::DeploymentsHelper
|
|
10
10
|
## Deployments
|
11
11
|
|
12
12
|
def deployments_interface
|
13
|
-
# @api_client.groups
|
14
13
|
raise "#{self.class} has not defined @deployments_interface" if @deployments_interface.nil?
|
15
14
|
@deployments_interface
|
16
15
|
end
|
@@ -52,9 +51,10 @@ module Morpheus::Cli::DeploymentsHelper
|
|
52
51
|
return nil
|
53
52
|
elsif deployments.size > 1
|
54
53
|
print_red_alert "#{deployments.size} deployments found by name '#{name}'"
|
54
|
+
print_error "\n"
|
55
55
|
puts_error as_pretty_table(deployments, [:id, :name], {color:red})
|
56
56
|
print_red_alert "Try using ID instead"
|
57
|
-
|
57
|
+
print_error reset,"\n"
|
58
58
|
return nil
|
59
59
|
else
|
60
60
|
return deployments[0]
|
@@ -123,13 +123,41 @@ module Morpheus::Cli::DeploymentsHelper
|
|
123
123
|
return nil
|
124
124
|
elsif deployment_versions.size > 1
|
125
125
|
print_red_alert "#{deployment_versions.size} deployment versions found by version '#{name}'"
|
126
|
+
print_error "\n"
|
126
127
|
puts_error as_pretty_table(deployment_versions, {"ID" => 'id', "VERSION" => 'userVersion'}, {color:red})
|
127
128
|
print_red_alert "Try using ID instead"
|
128
|
-
|
129
|
+
print_error reset,"\n"
|
129
130
|
return nil
|
130
131
|
else
|
131
132
|
return deployment_versions[0]
|
132
133
|
end
|
133
134
|
end
|
134
135
|
|
136
|
+
def format_deployment_version_number(deployment_version)
|
137
|
+
if deployment_version
|
138
|
+
deployment_version['userVersion'] || deployment_version['version'] || ''
|
139
|
+
else
|
140
|
+
''
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def format_app_deploy_status(status, return_color=cyan)
|
145
|
+
out = ""
|
146
|
+
s = status.to_s.downcase
|
147
|
+
if s == 'deployed' || s == 'committed'
|
148
|
+
out << "#{green}#{s.upcase}#{return_color}"
|
149
|
+
elsif s == 'open' || s == 'archived'
|
150
|
+
out << "#{cyan}#{s.upcase}#{return_color}"
|
151
|
+
elsif s == 'failed'
|
152
|
+
out << "#{red}#{s.upcase}#{return_color}"
|
153
|
+
else
|
154
|
+
out << "#{yellow}#{s.upcase}#{return_color}"
|
155
|
+
end
|
156
|
+
out
|
157
|
+
end
|
158
|
+
|
159
|
+
def format_deploy_type(val)
|
160
|
+
return val
|
161
|
+
end
|
162
|
+
|
135
163
|
end
|
@@ -75,7 +75,7 @@ module Morpheus::Cli::OptionSourceHelper
|
|
75
75
|
|
76
76
|
def get_cloud_options(refresh=false, api_params={})
|
77
77
|
if !@available_cloud_options || refresh
|
78
|
-
option_results = options_interface.options_for_source('clouds', api_params.
|
78
|
+
option_results = options_interface.options_for_source('clouds', api_params.merge({'default' => 'false'}))
|
79
79
|
@available_cloud_options = option_results['data'].collect {|it|
|
80
80
|
{"name" => it["name"], "value" => it["value"], "id" => it["value"]}
|
81
81
|
}
|
@@ -1151,27 +1151,6 @@ module Morpheus::Cli::PrintHelper
|
|
1151
1151
|
out
|
1152
1152
|
end
|
1153
1153
|
|
1154
|
-
def format_list(items, conjunction="and", limit=nil)
|
1155
|
-
items = items ? items.clone : []
|
1156
|
-
if limit
|
1157
|
-
items = items.first(limit)
|
1158
|
-
end
|
1159
|
-
last_item = items.pop
|
1160
|
-
if items.empty?
|
1161
|
-
return "#{last_item}"
|
1162
|
-
else
|
1163
|
-
return items.join(", ") + (conjunction.to_s.empty? ? ", " : " #{conjunction} ") + "#{last_item}" + ((limit && limit < (items.size+1)) ? " ..." : "")
|
1164
|
-
end
|
1165
|
-
end
|
1166
|
-
|
1167
|
-
def anded_list(items, limit=nil)
|
1168
|
-
format_list(items, "and", limit)
|
1169
|
-
end
|
1170
|
-
|
1171
|
-
def ored_list(items, limit=nil)
|
1172
|
-
format_list(items, "or", limit)
|
1173
|
-
end
|
1174
|
-
|
1175
1154
|
def sleep_with_dots(sleep_seconds, dots=3, dot_chr=".")
|
1176
1155
|
dot_interval = (sleep_seconds.to_f / dots.to_i)
|
1177
1156
|
dots.to_i.times do |dot_index|
|
@@ -1285,4 +1264,50 @@ module Morpheus::Cli::PrintHelper
|
|
1285
1264
|
end
|
1286
1265
|
end
|
1287
1266
|
|
1267
|
+
# convert JSON or YAML string to a map
|
1268
|
+
def parse_json_or_yaml(config, parsers = [:json, :yaml])
|
1269
|
+
rtn = {success: false, data: nil, err: nil}
|
1270
|
+
err = nil
|
1271
|
+
config = config.strip
|
1272
|
+
if config[0..2] == "---"
|
1273
|
+
parsers = [:yaml]
|
1274
|
+
end
|
1275
|
+
# ok only parse json for strings that start with {, consolidated yaml can look like json and cause issues}
|
1276
|
+
if config[0] && config[0].chr == "{" && config[-1] && config[-1].chr == "}"
|
1277
|
+
parsers = [:json]
|
1278
|
+
end
|
1279
|
+
parsers.each do |parser|
|
1280
|
+
if parser == :yaml
|
1281
|
+
begin
|
1282
|
+
# todo: one method to parse and return Hash
|
1283
|
+
# load does not raise an exception, it just returns the bad string
|
1284
|
+
#YAML.parse(config)
|
1285
|
+
config_map = YAML.load(config)
|
1286
|
+
if !config_map.is_a?(Hash)
|
1287
|
+
raise "Failed to parse config as YAML"
|
1288
|
+
end
|
1289
|
+
rtn[:data] = config_map
|
1290
|
+
rtn[:success] = true
|
1291
|
+
break
|
1292
|
+
rescue => ex
|
1293
|
+
rtn[:err] = ex if rtn[:err].nil?
|
1294
|
+
end
|
1295
|
+
elsif parser == :json
|
1296
|
+
begin
|
1297
|
+
config_map = JSON.parse(config)
|
1298
|
+
rtn[:data] = config_map
|
1299
|
+
rtn[:success] = true
|
1300
|
+
break
|
1301
|
+
rescue => ex
|
1302
|
+
rtn[:err] = ex if rtn[:err].nil?
|
1303
|
+
end
|
1304
|
+
end
|
1305
|
+
end
|
1306
|
+
return rtn
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
def parse_yaml_or_json(config, parsers = [:yaml, :json])
|
1310
|
+
parse_json_or_yaml(config, parsers)
|
1311
|
+
end
|
1312
|
+
|
1288
1313
|
end
|