morpheus-cli 8.1.1.1 → 9.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8ad3fb5b81a6d6a3cfa1798e0db8c2a40c5b839aa424e6b247dde4e90c69a2f
4
- data.tar.gz: 1916b5e1f52ed9a7d8035c314e03806cffc7a33a3ac9e9a3834221e2a266a45b
3
+ metadata.gz: 1b224b836c51abacb14e3e75c0cc9d88a59b84932c1550f708ffbae41ea08ad3
4
+ data.tar.gz: ee787f62e945490b8537dc9bbbf3a027dadbb7dde1272a57492c92b1111d5f39
5
5
  SHA512:
6
- metadata.gz: 3b8782866788837ceaae8c347d1ecec2df87b0abf019fc5ff27296a69b31ef9f2954fcee1cb48e0458df26b1a3b6827e96ab532c08bf233fe220634c9958e7a8
7
- data.tar.gz: 80e3d6c638f5048d60e9d60ff481acf9b1a6ccfaf5f002b2b60295577acf695c8fbf92a18521dadacdc2ef2f1723bb9acaf0b775eb6ad616155d8546fb87b49a
6
+ metadata.gz: cbe5cf5150058a44b1441ff60de0473af2814390bede4750195bae54973918a828ee5b9a747e4470d1cc084eee45c0d62eff5cad647535a6ccef1d8765335005
7
+ data.tar.gz: 2edbb553a70619a8e8ac47f14aa7f920949add47dd92beaaea0c8cdc1761e7b8aeafcde6e29a2ad0c1b16c31f37728f47d1f941d9af3f189e238233aa3bac59b
data/Dockerfile CHANGED
@@ -1,5 +1,5 @@
1
1
  FROM ruby:2.7.5
2
2
 
3
- RUN gem install morpheus-cli -v 8.1.1.1
3
+ RUN gem install morpheus-cli -v 9.0.0
4
4
 
5
- ENTRYPOINT ["morpheus"]
5
+ ENTRYPOINT ["morpheus"]
@@ -1034,6 +1034,10 @@ class Morpheus::APIClient
1034
1034
  Morpheus::MigrationsInterface.new(common_interface_options).setopts(@options)
1035
1035
  end
1036
1036
 
1037
+ def tokens
1038
+ Morpheus::TokensInterface.new(common_interface_options).setopts(@options)
1039
+ end
1040
+
1037
1041
  def rest(endpoint)
1038
1042
  Morpheus::RestInterface.new(common_interface_options).setopts(@options.merge({base_path: "#{@base_url}/api/#{endpoint}"}))
1039
1043
  end
@@ -1048,6 +1052,10 @@ class Morpheus::APIClient
1048
1052
  end
1049
1053
  alias :get_interface :interface
1050
1054
 
1055
+ def support_bundles
1056
+ Morpheus::SupportBundlesInterface.new(common_interface_options).setopts(@options)
1057
+ end
1058
+
1051
1059
  # add new interfaces here
1052
1060
 
1053
1061
  protected
@@ -9,7 +9,7 @@ class Morpheus::GroupsInterface < Morpheus::APIClient
9
9
  execute(opts)
10
10
  end
11
11
 
12
- def get(options=nil)
12
+ def get(options=nil, params={})
13
13
  url = "#{@base_url}/api/groups"
14
14
  headers = { params: {}, authorization: "Bearer #{@access_token}" }
15
15
 
@@ -17,6 +17,7 @@ class Morpheus::GroupsInterface < Morpheus::APIClient
17
17
  headers[:params].merge!(options)
18
18
  elsif options.is_a?(Numeric)
19
19
  url = "#{@base_url}/api/groups/#{options}"
20
+ headers[:params] = params
20
21
  elsif options.is_a?(String)
21
22
  headers[:params]['name'] = options
22
23
  end
@@ -219,5 +219,4 @@ class Morpheus::ServersInterface < Morpheus::APIClient
219
219
  execute(opts)
220
220
  end
221
221
 
222
-
223
222
  end
@@ -0,0 +1,46 @@
1
+ require 'morpheus/api/rest_interface'
2
+
3
+ class Morpheus::SupportBundlesInterface < Morpheus::RestInterface
4
+
5
+ def base_path
6
+ "/api/support-bundles"
7
+ end
8
+
9
+ # Download uses chunked streaming to write directly to a file.
10
+ # Follows the same pattern as file_copy_request_interface.rb#download_file_chunked.
11
+ def download(id, outfile, params={})
12
+ raise "#{self.class}.download() passed a blank id!" if id.to_s == ''
13
+ url = "#{base_path}/#{CGI::escape(id.to_s)}/download"
14
+ headers = { params: params }
15
+ opts = {method: :get, url: url, headers: headers, parse_json: false}
16
+ if Dir.exist?(outfile)
17
+ raise "outfile is invalid. It is the name of an existing directory: #{outfile}"
18
+ end
19
+ if @dry_run
20
+ return execute(opts)
21
+ end
22
+ http_response = nil
23
+ begin
24
+ File.open(outfile, 'w') {|f|
25
+ block = proc { |response|
26
+ response.read_body do |chunk|
27
+ f.write chunk
28
+ end
29
+ }
30
+ opts[:block_response] = block
31
+ http_response = execute(opts)
32
+ }
33
+ rescue
34
+ if File.exist?(outfile) && File.file?(outfile)
35
+ File.delete(outfile)
36
+ end
37
+ raise
38
+ end
39
+ return http_response
40
+ end
41
+
42
+ def cancel(id, payload={}, params={}, headers={})
43
+ execute(method: :post, url: "#{base_path}/#{CGI::escape(id.to_s)}/cancel", params: params, payload: payload, headers: headers)
44
+ end
45
+
46
+ end
@@ -20,4 +20,36 @@ class Morpheus::SystemsInterface < Morpheus::RestInterface
20
20
  execute(method: :get, url: "#{base_path}/#{CGI::escape(id.to_s)}/validate", params: params, headers: headers)
21
21
  end
22
22
 
23
+ def list_compute_server_update_definitions(system_id, server_id, params={}, headers={})
24
+ execute(method: :get, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/servers/#{CGI::escape(server_id.to_s)}/update-definitions", params: params, headers: headers)
25
+ end
26
+
27
+ def apply_compute_server_update_definition(system_id, server_id, update_definition_id, payload={}, params={}, headers={})
28
+ execute(method: :post, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/servers/#{CGI::escape(server_id.to_s)}/update-definitions/#{CGI::escape(update_definition_id.to_s)}", params: params, payload: payload, headers: headers)
29
+ end
30
+
31
+ def list_storage_server_update_definitions(system_id, server_id, params={}, headers={})
32
+ execute(method: :get, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/storage-servers/#{CGI::escape(server_id.to_s)}/update-definitions", params: params, headers: headers)
33
+ end
34
+
35
+ def apply_storage_server_update_definition(system_id, server_id, update_definition_id, payload={}, params={}, headers={})
36
+ execute(method: :post, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/storage-servers/#{CGI::escape(server_id.to_s)}/update-definitions/#{CGI::escape(update_definition_id.to_s)}", params: params, payload: payload, headers: headers)
37
+ end
38
+
39
+ def list_network_server_update_definitions(system_id, server_id, params={}, headers={})
40
+ execute(method: :get, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/network-servers/#{CGI::escape(server_id.to_s)}/update-definitions", params: params, headers: headers)
41
+ end
42
+
43
+ def apply_network_server_update_definition(system_id, server_id, update_definition_id, payload={}, params={}, headers={})
44
+ execute(method: :post, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/network-servers/#{CGI::escape(server_id.to_s)}/update-definitions/#{CGI::escape(update_definition_id.to_s)}", params: params, payload: payload, headers: headers)
45
+ end
46
+
47
+ def list_cluster_update_definitions(system_id, cluster_id, params={}, headers={})
48
+ execute(method: :get, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/clusters/#{CGI::escape(cluster_id.to_s)}/update-definitions", params: params, headers: headers)
49
+ end
50
+
51
+ def apply_cluster_update_definition(system_id, cluster_id, update_definition_id, payload={}, params={}, headers={})
52
+ execute(method: :post, url: "#{base_path}/#{CGI::escape(system_id.to_s)}/clusters/#{CGI::escape(cluster_id.to_s)}/update-definitions/#{CGI::escape(update_definition_id.to_s)}", params: params, payload: payload, headers: headers)
53
+ end
54
+
23
55
  end
@@ -0,0 +1,39 @@
1
+ require 'morpheus/api/api_client'
2
+
3
+ class Morpheus::TokensInterface < Morpheus::APIClient
4
+
5
+ def base_path
6
+ "/api/tokens"
7
+ end
8
+
9
+ def list(params={}, headers={})
10
+ execute(method: :get, url: "#{base_path}", params: params, headers: headers)
11
+ end
12
+
13
+ def get(id, params={}, headers={})
14
+ validate_id!(id)
15
+ execute(method: :get, url: "#{base_path}/#{id}", params: params, headers: headers)
16
+ end
17
+
18
+ def create(payload, params={})
19
+ execute(method: :post, url: "#{base_path}", payload: payload, params: params)
20
+ end
21
+
22
+ # def update(id, payload, params={})
23
+ # execute(method: :put, url: "#{base_path}/#{id}", params: params, headers: headers)
24
+ # end
25
+
26
+ def destroy(id, params={})
27
+ validate_id!(id)
28
+ execute(method: :delete, url: "#{base_path}/#{id}", params: params)
29
+ end
30
+
31
+ def destroy_all(params={})
32
+ execute(method: :delete, url: "#{base_path}", params: params)
33
+ end
34
+
35
+ def available_clients(params={})
36
+ execute(method: :get, url: "#{base_path}/api-clients", params: params)
37
+ end
38
+
39
+ end
@@ -1485,7 +1485,12 @@ module Morpheus
1485
1485
  # returns Array of subtitles as strings in the format ["Phrase: blah", "Max: 100"]
1486
1486
  def parse_list_subtitles(options={})
1487
1487
  subtitles = []
1488
- list_params = {}
1488
+ if options[:tenant]
1489
+ subtitles << "Tenant: #{options[:tenant]}".strip
1490
+ end
1491
+ if options[:include_tenants]
1492
+ subtitles << "Include Tenants: true".strip
1493
+ end
1489
1494
  [:phrase, :offset, :max, :sort, :direction, :lastUpdated].each do |k|
1490
1495
  if options.key?(k)
1491
1496
  subtitles << "#{k.to_s}: #{options[k]}"
@@ -30,41 +30,29 @@ class Morpheus::Cli::ClientsCommand
30
30
  end
31
31
  optparse.parse!(args)
32
32
  connect(options)
33
-
33
+ # verify_args!(args:args, optparse:optparse, count:0)
34
+ if args.count > 0
35
+ options[:phrase] = args.join(" ")
36
+ end
34
37
  params.merge!(parse_list_options(options))
35
38
  @clients_interface.setopts(options)
36
39
  if options[:dry_run]
37
40
  print_dry_run @clients_interface.dry.list(params)
38
41
  return 0
39
42
  end
40
-
41
43
  json_response = @clients_interface.list(params)
42
44
  render_response(json_response, options, "clients") do
43
- clients = json_response["clients"]
44
- if clients.empty?
45
- print cyan,"No clients found",reset,"\n"
46
- else
47
- rows = clients.collect {|client|
48
- row = {
49
- id: client['id'],
50
- client_id: client['clientId'],
51
- access_token_seconds: client['accessTokenValiditySeconds'],
52
- refresh_token_seconds: client['refreshTokenValiditySeconds']
53
- }
54
- row
55
- }
56
- columns = [:id, {:client_id => {:max_width => 50}}, :access_token_seconds, :refresh_token_seconds]
57
- print_h1 "Morpheus Clients", [], options
58
- print as_pretty_table(rows, columns, options)
59
- print reset
60
- print_results_pagination(json_response)
61
- end
45
+ clients = json_response['clients']
46
+ print_h1 "Morpheus Clients", [], options
47
+ print as_pretty_table(clients, client_columns.upcase_keys!, options)
48
+ print reset
49
+ print_results_pagination(json_response)
62
50
  print reset,"\n"
63
51
  end
64
- return 0, nil
65
52
  end
66
53
 
67
54
  def get(args)
55
+ params = {}
68
56
  options = {}
69
57
  optparse = Morpheus::Cli::OptionParser.new do |opts|
70
58
  opts.banner = subcommand_usage("[client]")
@@ -74,47 +62,28 @@ class Morpheus::Cli::ClientsCommand
74
62
 
75
63
  end
76
64
  optparse.parse!(args)
77
- if args.count < 1
78
- puts optparse
79
- exit 1
80
- end
65
+ verify_args!(args:args, optparse:optparse, count:1)
81
66
  connect(options)
82
- begin
83
- @clients_interface.setopts(options)
84
- if options[:dry_run]
85
- if args[0].to_s =~ /\A\d{1,}\Z/
86
- print_dry_run @clients_interface.dry.get(args[0])
87
- else
88
- print_dry_run @clients_interface.dry.list({name: args[0].to_s})
89
- end
90
- return 0
91
- end
92
- client = find_client_by_name_or_id(args[0])
67
+ id = args[0]
68
+ if id.to_s !~ /\A\d{1,}\Z/
69
+ client = find_client_by_client_id(id)
93
70
  return 1 if client.nil?
94
- json_response = {'client' => client}
95
- render_result = render_with_format(json_response, options, 'client')
96
- return 0 if render_result
97
-
98
- unless options[:quiet]
99
- print_h1 "Client Details"
100
- print cyan
101
- client_columns = {
102
- "ID" => 'id',
103
- "Client ID" => 'clientId',
104
- "Access Token Validity Seconds" => 'accessTokenValiditySeconds',
105
- "Refresh Token Validity Seconds" => 'refreshTokenValiditySeconds',
106
- # "Scopes" => lambda {|client| client['scopes'].join(", ")},
107
- "Redirect URI" => lambda {|client| client['redirectUris'].join(", ")}
108
- }
109
- print_description_list(client_columns, client)
110
- print reset,"\n"
111
-
112
- end
71
+ id = client['id']
72
+ else
73
+ id = id.to_i
74
+ end
75
+ @clients_interface.setopts(options)
76
+ if options[:dry_run]
77
+ print_dry_run @clients_interface.dry.get(id, params)
78
+ return
79
+ end
80
+ json_response = @clients_interface.get(id, params)
81
+ render_response(json_response, options, 'client') do
82
+ client = json_response['client']
83
+ print_h1 "Client Details", [], options
84
+ print cyan
85
+ print_description_list(client_columns, client)
113
86
  print reset,"\n"
114
- return 0
115
- rescue RestClient::Exception => e
116
- print_rest_exception(e, options)
117
- exit 1
118
87
  end
119
88
  end
120
89
 
@@ -151,6 +120,7 @@ class Morpheus::Cli::ClientsCommand
151
120
  payload.deep_merge!({'client' => passed_options}) unless passed_options.empty?
152
121
  # prompt for options
153
122
  params = Morpheus::Cli::OptionTypes.prompt(add_client_option_types, options[:options], @api_client, options[:params])
123
+ params.booleanize!
154
124
  if params['redirectUris'] && params['redirectUris'].is_a?(String)
155
125
  params['redirectUris'] = params['redirectUris'].split(',').collect {|it| it.strip}.reject {|it| it.empty?}
156
126
  end
@@ -182,7 +152,7 @@ class Morpheus::Cli::ClientsCommand
182
152
  options = {}
183
153
  optparse = Morpheus::Cli::OptionParser.new do |opts|
184
154
  opts.banner = subcommand_usage("[clientId] [options]")
185
- build_option_type_options(opts, options, client_option_types)
155
+ build_option_type_options(opts, options, update_client_option_types)
186
156
  build_standard_update_options(opts, options)
187
157
  opts.footer = "Update Oauth Client Record."
188
158
  end
@@ -212,8 +182,9 @@ class Morpheus::Cli::ClientsCommand
212
182
  # allow arbitrary -O options
213
183
  payload.deep_merge!({'client' => passed_options}) unless passed_options.empty?
214
184
  # prompt for options
215
- #params = Morpheus::Cli::OptionTypes.prompt(update_wiki_page_option_types, options[:options], @api_client, options[:params])
185
+ #params = Morpheus::Cli::OptionTypes.no_prompt(update_client_option_types, options[:options], @api_client, options[:params])
216
186
  params = passed_options
187
+ params.booleanize!
217
188
  if params['redirectUris'] && params['redirectUris'].is_a?(String)
218
189
  params['redirectUris'] = params['redirectUris'].split(',').collect {|it| it.strip}.reject {|it| it.empty?}
219
190
  end
@@ -325,21 +296,36 @@ class Morpheus::Cli::ClientsCommand
325
296
  end
326
297
  end
327
298
 
328
- def client_option_types
329
- [
330
- {'fieldName' => 'clientId', 'fieldLabel' => 'Client Id', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
331
- {'fieldName' => 'accessTokenValiditySeconds', 'fieldLabel' => 'Access Token Validity Length (Seconds)', 'type' => 'number', 'required' => true, 'defaultValue' => 43200,'displayOrder' => 2},
332
- {'fieldName' => 'refreshTokenValiditySeconds', 'fieldLabel' => 'Refresh Token Validity Length (Seconds)', 'type' => 'number', 'required' => true, 'defaultValue' => 43200,'displayOrder' => 3}
333
- ]
299
+ def client_columns
300
+ {
301
+ "ID" => lambda {|it| it['id'] },
302
+ "Client ID" => lambda {|it| it['clientId'] },
303
+ "TTL" => lambda {|it| it['accessTokenValiditySeconds'] },
304
+ "Refresh TTL" => lambda {|it| it['refreshTokenValiditySeconds'] },
305
+ "Redirect URI" => lambda {|client| client['redirectUris'].join(", ")},
306
+ "Requires Consent" => lambda {|it| format_boolean it['requireConsent']}
307
+ }
334
308
  end
335
309
 
336
- def add_client_option_types
310
+
311
+ def add_client_option_types
337
312
  [
338
- {'fieldName' => 'clientId', 'fieldLabel' => 'Client Id', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
339
- {'fieldName' => 'clientSecret', 'fieldLabel' => 'Client Secret', 'type' => 'text', 'displayOrder' => 2},
340
- {'fieldName' => 'accessTokenValiditySeconds', 'fieldLabel' => 'Access Token Validity Length (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'displayOrder' => 3},
341
- {'fieldName' => 'refreshTokenValiditySeconds', 'fieldLabel' => 'Refresh Token Validity Length (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'displayOrder' => 4},
342
- {'fieldName' => 'redirectUris', 'fieldLabel' => 'Redirect URI', 'type' => 'text', 'displayOrder' => 5}
313
+ {'fieldName' => 'clientId', 'fieldLabel' => 'Client Id', 'type' => 'text', 'required' => true},
314
+ {'fieldName' => 'clientSecret', 'fieldLabel' => 'Client Secret', 'type' => 'text'},
315
+ {'switch' => 'ttl', 'fieldName' => 'accessTokenValiditySeconds', 'fieldLabel' => 'TTL (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'description' => 'Access Token Validity Seconds'},
316
+ {'switch' => 'refresh-ttl', 'fieldName' => 'refreshTokenValiditySeconds', 'fieldLabel' => 'Refresh TTL (Seconds)', 'type' => 'number', 'required' => true,'defaultValue' => 43200, 'description' => 'Refresh Token Validity Seconds'},
317
+ {'fieldName' => 'redirectUris', 'fieldLabel' => 'Redirect URI', 'type' => 'text', 'description' => 'Redirect URI(s), use commas to delimit values.'},
318
+ {'fieldName' => 'requireConsent', 'fieldLabel' => 'Requires Consent', 'type' => 'checkbox', 'defaultValue' => false}
343
319
  ]
344
320
  end
321
+
322
+ def update_client_option_types
323
+ option_types = add_client_option_types #.select {|it| ['clientId', 'clientSecret', 'accessTokenValiditySeconds'].include?(it['fieldName']) }
324
+ option_types.each {|it|
325
+ it.delete('required')
326
+ it.delete('defaultValue')
327
+ it.delete('skipSingleOption')
328
+ }
329
+ option_types
330
+ end
345
331
  end
@@ -2,6 +2,7 @@ require 'morpheus/cli/cli_command'
2
2
 
3
3
  class Morpheus::Cli::Clouds
4
4
  include Morpheus::Cli::CliCommand
5
+ include Morpheus::Cli::AccountsHelper
5
6
  include Morpheus::Cli::InfrastructureHelper
6
7
  include Morpheus::Cli::ProvisioningHelper
7
8
  include Morpheus::Cli::WhoamiHelper
@@ -25,6 +26,8 @@ class Morpheus::Cli::Clouds
25
26
  @api_client = establish_remote_appliance_connection(opts)
26
27
  @clouds_interface = @api_client.clouds
27
28
  @groups_interface = @api_client.groups
29
+ @accounts_interface = @api_client.accounts
30
+ @account_users_interface = @api_client.account_users
28
31
  @active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
29
32
  end
30
33
 
@@ -49,6 +52,13 @@ class Morpheus::Cli::Clouds
49
52
  opts.on('--all-labels LABEL', String, "Filter by labels, must match all of the values") do |val|
50
53
  add_query_parameter(params, 'allLabels', parse_labels(val))
51
54
  end
55
+ opts.on('--include-tenants','--include-tenants', "Include sub tenant clouds") do
56
+ options[:include_tenants] = true
57
+ params['includeTenants'] = true
58
+ end
59
+ opts.on('--tenant TENANT', String, "Tenant Name or ID" ) do |val|
60
+ options[:tenant] = val
61
+ end
52
62
  build_standard_list_options(opts, options)
53
63
  opts.footer = "List clouds."
54
64
  end
@@ -69,7 +79,18 @@ class Morpheus::Cli::Clouds
69
79
  params['groupId'] = group['id']
70
80
  end
71
81
  end
72
-
82
+ if options[:tenant]
83
+ if options[:tenant].to_s !~ /\A\d{1,}\Z/
84
+ account = find_account_by_name_or_id(options[:tenant])
85
+ if account.nil?
86
+ return 1, "Tenant not found by name: #{options[:tenant]}"
87
+ else
88
+ params['tenantId'] = account['id']
89
+ end
90
+ else
91
+ params['tenantId'] = options[:tenant]
92
+ end
93
+ end
73
94
  params.merge!(parse_list_options(options))
74
95
  @clouds_interface.setopts(options)
75
96
  if options[:dry_run]
@@ -94,6 +115,9 @@ class Morpheus::Cli::Clouds
94
115
  print cyan,"No clouds found.",reset,"\n"
95
116
  else
96
117
  columns = cloud_list_column_definitions(options).upcase_keys!
118
+ if !options[:include_tenants] && !options[:tenant]
119
+ columns.delete("Tenant")
120
+ end
97
121
  print as_pretty_table(clouds, columns, options)
98
122
  print_results_pagination(json_response)
99
123
  end
@@ -141,6 +165,9 @@ class Morpheus::Cli::Clouds
141
165
  params = {}
142
166
  optparse = Morpheus::Cli::OptionParser.new do |opts|
143
167
  opts.banner = subcommand_usage("[name]")
168
+ opts.on('--include-tenants','--include-tenants', "Include sub tenant clouds when finding cloud by name") do
169
+ options[:include_tenants] = true
170
+ end
144
171
  build_standard_list_options(opts, options)
145
172
  opts.footer = "Get details about a cloud.\n" +
146
173
  "[name] is required. This is the name or id of a cloud."
@@ -158,7 +185,7 @@ class Morpheus::Cli::Clouds
158
185
  def _get(id, params, options={})
159
186
  cloud = nil
160
187
  if id.to_s !~ /\A\d{1,}\Z/
161
- cloud = find_cloud_by_name_or_id(id)
188
+ cloud = find_cloud_by_name_or_id(id, options[:include_tenants])
162
189
  id = cloud['id']
163
190
  end
164
191
  @clouds_interface.setopts(options)
@@ -1481,6 +1508,7 @@ EOT
1481
1508
  {
1482
1509
  "ID" => 'id',
1483
1510
  "Name" => 'name',
1511
+ "Tenant" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
1484
1512
  "Type" => lambda {|it| it['zoneType'] ? it['zoneType']['name'] : '' },
1485
1513
  "Labels" => lambda {|it| format_list(it['labels'], '', 3) rescue '' },
1486
1514
  "Location" => 'location',
@@ -3064,6 +3064,7 @@ class Morpheus::Cli::Clusters
3064
3064
  "Active" => lambda { |it| format_boolean(it['active']) },
3065
3065
  "Visibility" => lambda { |it| it['visibility'].nil? ? '' : it['visibility'].to_s.capitalize },
3066
3066
  "Tenants" => lambda { |it| it['tenants'].nil? ? '' : it['tenants'].collect {|it| it['name']}.join(', ') },
3067
+ "Supports VM Secure Metadata" => lambda { |it| format_boolean(it['supportsVmSecureMetadata']) },
3067
3068
  "Cluster" => lambda { |it| cluster['name'] }
3068
3069
  }
3069
3070
  print_description_list(description_cols, datastore)
@@ -3233,6 +3234,9 @@ class Morpheus::Cli::Clusters
3233
3234
  opts.on('--active [on|off]', String, "Enable datastore") do |val|
3234
3235
  options[:active] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
3235
3236
  end
3237
+ opts.on('--supports-vm-secure-metadata [on|off]', String, "Enable VM Secure Metadata support") do |val|
3238
+ options[:supportsVmSecureMetadata] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == ''
3239
+ end
3236
3240
  add_perms_options(opts, options, ['plans', 'groupDefaults'])
3237
3241
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
3238
3242
  opts.footer = "Update a cluster datastore.\n" +
@@ -3264,6 +3268,7 @@ class Morpheus::Cli::Clusters
3264
3268
  else
3265
3269
  payload = {'datastore' => {}}
3266
3270
  payload['datastore']['active'] = options[:active].nil? ? (Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox', 'description' => 'Datastore Active', 'defaultValue' => true}], options[:options], @api_client))['active'] == 'on' : options[:active]
3271
+ payload['datastore']['supportsVmSecureMetadata'] = options[:supportsVmSecureMetadata] unless options[:supportsVmSecureMetadata].nil?
3267
3272
 
3268
3273
  perms = prompt_permissions(options.merge({:available_plans => namespace_service_plans}), datastore['owner']['id'] == current_user['accountId'] ? ['plans', 'groupDefaults'] : ['plans', 'groupDefaults', 'visibility', 'tenants'])
3269
3274
  perms_payload = {}
@@ -83,13 +83,13 @@ class Morpheus::Cli::ExecutionRequestCommand
83
83
  if options[:refresh_interval].nil? || options[:refresh_interval].to_f < 0
84
84
  options[:refresh_interval] = default_refresh_interval
85
85
  end
86
- if !(execution_request['status'] == 'pending' || execution_request['status'] == 'new')
86
+ if is_finished(execution_request)
87
87
  # it is finished
88
88
  else
89
89
  print cyan
90
90
  refresh_display_seconds = options[:refresh_interval] % 1.0 == 0 ? options[:refresh_interval].to_i : options[:refresh_interval]
91
91
  print "Execution request has not yet finished. Refreshing every #{refresh_display_seconds} seconds"
92
- while execution_request['status'] == 'pending' || execution_request['status'] == 'new' do
92
+ while !is_finished(execution_request) do
93
93
  sleep(options[:refresh_interval])
94
94
  print cyan,".",reset
95
95
  json_response = @execution_request_interface.get(execution_request_id, params)
@@ -326,4 +326,8 @@ class Morpheus::Cli::ExecutionRequestCommand
326
326
  out
327
327
  end
328
328
 
329
+ def is_finished(execution_request)
330
+ ['executing', 'pending', 'new'].include?(execution_request['status']) ? false : true
331
+ end
332
+
329
333
  end