morpheus-cli 5.5.2.1 → 5.5.3
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 +2 -1
- data/Dockerfile +1 -1
- data/README.md +57 -4
- data/Rakefile +9 -0
- data/bin/morpheus +4 -4
- data/lib/morpheus/api/api_client.rb +8 -2
- data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
- data/lib/morpheus/api/archive_files_interface.rb +3 -3
- data/lib/morpheus/api/clients_interface.rb +2 -2
- data/lib/morpheus/api/clusters_interface.rb +8 -1
- data/lib/morpheus/api/containers_interface.rb +29 -16
- data/lib/morpheus/api/custom_instance_types_interface.rb +0 -2
- data/lib/morpheus/api/doc_interface.rb +8 -6
- data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
- data/lib/morpheus/api/health_interface.rb +1 -1
- data/lib/morpheus/api/image_builder_interface.rb +3 -3
- data/lib/morpheus/api/instances_interface.rb +25 -0
- data/lib/morpheus/api/logs_interface.rb +2 -4
- data/lib/morpheus/api/monitoring_interface.rb +6 -6
- data/lib/morpheus/api/packages_interface.rb +1 -1
- data/lib/morpheus/api/reports_interface.rb +1 -1
- data/lib/morpheus/api/servers_interface.rb +9 -1
- data/lib/morpheus/api/storage_providers_interface.rb +2 -2
- data/lib/morpheus/api/virtual_images_interface.rb +1 -1
- data/lib/morpheus/api.rb +2 -0
- data/lib/morpheus/benchmarking.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +69 -36
- data/lib/morpheus/cli/cli_registry.rb +19 -10
- data/lib/morpheus/cli/commands/access_token_command.rb +1 -1
- data/lib/morpheus/cli/commands/apps.rb +1 -1
- data/lib/morpheus/cli/commands/archives_command.rb +25 -33
- data/lib/morpheus/cli/commands/blueprints_command.rb +10 -21
- data/lib/morpheus/cli/commands/boot_scripts_command.rb +2 -2
- data/lib/morpheus/cli/commands/cat_command.rb +1 -1
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +12 -12
- data/lib/morpheus/cli/commands/clouds.rb +3 -3
- data/lib/morpheus/cli/commands/clusters.rb +154 -3
- data/lib/morpheus/cli/commands/containers_command.rb +398 -253
- data/lib/morpheus/cli/commands/deployments.rb +1 -1
- data/lib/morpheus/cli/commands/deploys.rb +9 -9
- data/lib/morpheus/cli/commands/doc.rb +15 -16
- data/lib/morpheus/cli/commands/execution_request_command.rb +2 -2
- data/lib/morpheus/cli/commands/file_copy_request_command.rb +5 -5
- data/lib/morpheus/cli/commands/groups.rb +2 -2
- data/lib/morpheus/cli/commands/health_command.rb +4 -4
- data/lib/morpheus/cli/commands/hosts.rb +43 -5
- data/lib/morpheus/cli/commands/image_builder_command.rb +1 -1
- data/lib/morpheus/cli/commands/instances.rb +419 -148
- data/lib/morpheus/cli/commands/integrations_command.rb +22 -20
- data/lib/morpheus/cli/commands/key_pairs.rb +2 -2
- data/lib/morpheus/cli/commands/library_container_scripts_command.rb +2 -2
- data/lib/morpheus/cli/commands/library_container_templates_command.rb +2 -2
- data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -3
- data/lib/morpheus/cli/commands/library_spec_templates_command.rb +2 -2
- data/lib/morpheus/cli/commands/login.rb +1 -1
- data/lib/morpheus/cli/commands/man_command.rb +32 -18
- data/lib/morpheus/cli/commands/packages_command.rb +11 -11
- data/lib/morpheus/cli/commands/plugins.rb +1 -1
- data/lib/morpheus/cli/commands/policies_command.rb +4 -4
- data/lib/morpheus/cli/commands/preseed_scripts_command.rb +2 -2
- data/lib/morpheus/cli/commands/remote.rb +1 -1
- data/lib/morpheus/cli/commands/reports_command.rb +3 -3
- data/lib/morpheus/cli/commands/roles.rb +6 -3
- data/lib/morpheus/cli/commands/security_groups.rb +1 -1
- data/lib/morpheus/cli/commands/shell.rb +40 -62
- data/lib/morpheus/cli/commands/snapshots.rb +3 -5
- data/lib/morpheus/cli/commands/source_command.rb +8 -16
- data/lib/morpheus/cli/commands/storage_providers_command.rb +7 -7
- data/lib/morpheus/cli/commands/tasks.rb +2 -2
- data/lib/morpheus/cli/commands/vdi_pools_command.rb +6 -6
- data/lib/morpheus/cli/commands/view.rb +5 -1
- data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +4 -4
- data/lib/morpheus/cli/commands/whoami.rb +2 -2
- data/lib/morpheus/cli/credentials.rb +30 -8
- data/lib/morpheus/cli/dot_file.rb +8 -15
- data/lib/morpheus/cli/error_handler.rb +16 -0
- data/lib/morpheus/cli/errors.rb +8 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +17 -13
- data/lib/morpheus/cli/mixins/rest_command.rb +18 -18
- data/lib/morpheus/cli/mixins/secondary_rest_command.rb +12 -12
- data/lib/morpheus/cli/option_parser.rb +5 -1
- data/lib/morpheus/cli/option_types.rb +59 -12
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli.rb +26 -16
- data/lib/morpheus/ext/rest_client.rb +3 -2
- data/lib/morpheus/formatters.rb +1 -1
- data/lib/morpheus/logging.rb +4 -4
- data/lib/morpheus/morpkg.rb +4 -4
- data/lib/morpheus/rest_client.rb +2 -2
- data/lib/morpheus/routes.rb +2 -2
- data/lib/morpheus/terminal.rb +65 -16
- data/lib/morpheus.rb +1 -1
- data/morpheus-cli.gemspec +1 -0
- data/test/api/containers_interface_test.rb +68 -0
- data/test/api/doc_interface_test.rb +35 -0
- data/test/api/instances_interface_test.rb +22 -0
- data/test/api/whoami_interface_test.rb +14 -0
- data/test/cli/access_token_test.rb +36 -0
- data/test/cli/auth_test.rb +82 -0
- data/test/cli/cli_test.rb +48 -0
- data/test/cli/containers_test.rb +92 -0
- data/test/cli/doc_test.rb +35 -0
- data/test/cli/help_test.rb +25 -0
- data/test/cli/instances_test.rb +36 -0
- data/test/cli/man_test.rb +14 -0
- data/test/cli/remote_test.rb +89 -0
- data/test/cli/roles_test.rb +34 -0
- data/test/cli/shell_test.rb +81 -0
- data/test/cli/version_test.rb +23 -0
- data/test/cli/view_test.rb +55 -0
- data/test/cli/whoami_test.rb +17 -0
- data/test/morpheus_test.rb +16 -0
- data/test/test_case.rb +338 -0
- data/test/test_config.rb +137 -0
- data/test/test_data_helper.rb +97 -0
- metadata +61 -3
|
@@ -6,13 +6,15 @@ class Morpheus::Cli::ContainersCommand
|
|
|
6
6
|
include Morpheus::Cli::LogsHelper
|
|
7
7
|
|
|
8
8
|
set_command_name :containers
|
|
9
|
-
|
|
10
|
-
register_subcommands :get, :stop, :start, :restart, :suspend, :eject, :action, :actions, :logs
|
|
11
|
-
|
|
9
|
+
set_command_description "View and manage containers (nodes)."
|
|
10
|
+
register_subcommands :get, :stop, :start, :restart, :suspend, :eject, :action, :actions, :logs,
|
|
11
|
+
{:exec => :execution_request}, :clone_image, :import
|
|
12
12
|
|
|
13
13
|
def connect(opts)
|
|
14
14
|
@api_client = establish_remote_appliance_connection(opts)
|
|
15
15
|
@containers_interface = @api_client.containers
|
|
16
|
+
@instances_interface = @api_client.instances
|
|
17
|
+
@provision_types_interface = @api_client.provision_types
|
|
16
18
|
@logs_interface = @api_client.logs
|
|
17
19
|
@execution_request_interface = @api_client.execution_request
|
|
18
20
|
end
|
|
@@ -40,44 +42,40 @@ class Morpheus::Cli::ContainersCommand
|
|
|
40
42
|
opts.on('--refresh-until STATUS', String, "Refresh until a specified status is reached.") do |val|
|
|
41
43
|
options[:refresh_until_status] = val.to_s.downcase
|
|
42
44
|
end
|
|
43
|
-
|
|
45
|
+
build_standard_get_options(opts, options)
|
|
46
|
+
opts.footer = <<-EOT
|
|
47
|
+
Get details about a container.
|
|
48
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
49
|
+
If more than one [id] is given, the command will execute for each one sequentially.
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
containers get 42
|
|
53
|
+
containers get 1 2 3
|
|
54
|
+
containers get 42 --refresh
|
|
55
|
+
containers get 42 --refresh 10 --refresh-until stopped
|
|
56
|
+
EOT
|
|
44
57
|
end
|
|
45
58
|
optparse.parse!(args)
|
|
46
|
-
|
|
47
|
-
puts_error "[id] argument is required"
|
|
48
|
-
puts_error optparse
|
|
49
|
-
return 1
|
|
50
|
-
end
|
|
59
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
51
60
|
connect(options)
|
|
52
61
|
id_list = parse_id_list(args)
|
|
62
|
+
validate_container_ids!(id_list)
|
|
53
63
|
return run_command_for_each_arg(id_list) do |arg|
|
|
54
64
|
_get(arg, options)
|
|
55
65
|
end
|
|
56
66
|
end
|
|
57
67
|
|
|
58
68
|
def _get(arg, options)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
puts as_json(json_response, options, "container")
|
|
70
|
-
return 0
|
|
71
|
-
elsif options[:yaml]
|
|
72
|
-
puts as_yaml(json_response, options, "container")
|
|
73
|
-
return 0
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
if options[:csv]
|
|
77
|
-
puts records_as_csv([json_response['container']], options)
|
|
78
|
-
return 0
|
|
79
|
-
end
|
|
80
|
-
container = json_response['container']
|
|
69
|
+
@containers_interface.setopts(options)
|
|
70
|
+
if options[:dry_run]
|
|
71
|
+
print_dry_run @containers_interface.dry.get(arg.to_i)
|
|
72
|
+
return
|
|
73
|
+
end
|
|
74
|
+
#container = find_container_by_id(arg)
|
|
75
|
+
#return 1 if container.nil?
|
|
76
|
+
json_response = @containers_interface.get(arg.to_i)
|
|
77
|
+
container = json_response['container']
|
|
78
|
+
render_response(json_response, options, "container") do
|
|
81
79
|
# stats = json_response['stats'] || {}
|
|
82
80
|
stats = container['stats'] || {}
|
|
83
81
|
|
|
@@ -139,49 +137,47 @@ class Morpheus::Cli::ContainersCommand
|
|
|
139
137
|
}
|
|
140
138
|
print_description_list(cost_columns, container)
|
|
141
139
|
end
|
|
142
|
-
|
|
143
140
|
print reset, "\n"
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
end
|
|
141
|
+
end
|
|
142
|
+
# refresh until a status is reached
|
|
143
|
+
if options[:refresh_until_status]
|
|
144
|
+
if options[:refresh_interval].nil? || options[:refresh_interval].to_f < 0
|
|
145
|
+
options[:refresh_interval] = default_refresh_interval
|
|
146
|
+
end
|
|
147
|
+
statuses = options[:refresh_until_status].to_s.downcase.split(",").collect {|s| s.strip }.select {|s| !s.to_s.empty? }
|
|
148
|
+
if !statuses.include?(container['status'])
|
|
149
|
+
print cyan
|
|
150
|
+
print cyan, "Refreshing in #{options[:refresh_interval] > 1 ? options[:refresh_interval].to_i : options[:refresh_interval]} seconds"
|
|
151
|
+
sleep_with_dots(options[:refresh_interval])
|
|
152
|
+
print "\n"
|
|
153
|
+
_get(arg, options)
|
|
158
154
|
end
|
|
159
|
-
|
|
160
|
-
return 0
|
|
161
|
-
rescue RestClient::Exception => e
|
|
162
|
-
print_rest_exception(e, options)
|
|
163
|
-
return 1 # , e
|
|
164
155
|
end
|
|
156
|
+
return 0, nil
|
|
165
157
|
end
|
|
166
158
|
|
|
167
159
|
|
|
168
160
|
def stop(args)
|
|
169
161
|
options = {}
|
|
170
162
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
171
|
-
opts.banner = subcommand_usage("[id
|
|
172
|
-
|
|
163
|
+
opts.banner = subcommand_usage("[id]")
|
|
164
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
165
|
+
opts.footer = <<-EOT
|
|
166
|
+
Stop a container.
|
|
167
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
168
|
+
If more than one [id] is given, the command will execute for each one sequentially.
|
|
169
|
+
|
|
170
|
+
Examples:
|
|
171
|
+
containers stop 42
|
|
172
|
+
containers stop 1 2 3 -y
|
|
173
|
+
EOT
|
|
173
174
|
end
|
|
174
175
|
optparse.parse!(args)
|
|
175
|
-
|
|
176
|
-
puts_error "[id] argument is required"
|
|
177
|
-
puts_error optparse
|
|
178
|
-
return 1
|
|
179
|
-
end
|
|
176
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
180
177
|
connect(options)
|
|
181
178
|
id_list = parse_id_list(args)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
end
|
|
179
|
+
validate_container_ids!(id_list)
|
|
180
|
+
confirm!("Are you sure you would like to stop #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options)
|
|
185
181
|
return run_command_for_each_arg(id_list) do |arg|
|
|
186
182
|
_stop(arg, options)
|
|
187
183
|
end
|
|
@@ -196,32 +192,33 @@ class Morpheus::Cli::ContainersCommand
|
|
|
196
192
|
return 0
|
|
197
193
|
end
|
|
198
194
|
json_response = @containers_interface.stop(container['id'])
|
|
199
|
-
|
|
200
|
-
if options[:json]
|
|
201
|
-
puts as_json(json_response, options)
|
|
202
|
-
elsif !options[:quiet]
|
|
195
|
+
render_response(json_response, options) do
|
|
203
196
|
print green, "Stopping container #{container['id']}", reset, "\n"
|
|
204
197
|
end
|
|
205
|
-
return 0
|
|
198
|
+
return 0, nil
|
|
206
199
|
end
|
|
207
200
|
|
|
208
201
|
def start(args)
|
|
209
202
|
options = {}
|
|
210
203
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
211
|
-
opts.banner = subcommand_usage("[id
|
|
212
|
-
|
|
204
|
+
opts.banner = subcommand_usage("[id]")
|
|
205
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
206
|
+
opts.footer = <<-EOT
|
|
207
|
+
Start a container.
|
|
208
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
209
|
+
If more than one [id] is given, the command will execute for each one sequentially.
|
|
210
|
+
|
|
211
|
+
Examples:
|
|
212
|
+
containers start 42
|
|
213
|
+
containers start 1 2 3 -y
|
|
214
|
+
EOT
|
|
213
215
|
end
|
|
214
216
|
optparse.parse!(args)
|
|
215
|
-
|
|
216
|
-
puts_error "[id] argument is required"
|
|
217
|
-
puts_error optparse
|
|
218
|
-
return 1
|
|
219
|
-
end
|
|
217
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
220
218
|
connect(options)
|
|
221
219
|
id_list = parse_id_list(args)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
end
|
|
220
|
+
validate_container_ids!(id_list)
|
|
221
|
+
confirm!("Are you sure you would like to start #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options)
|
|
225
222
|
return run_command_for_each_arg(id_list) do |arg|
|
|
226
223
|
_start(arg, options)
|
|
227
224
|
end
|
|
@@ -236,32 +233,33 @@ class Morpheus::Cli::ContainersCommand
|
|
|
236
233
|
return 0
|
|
237
234
|
end
|
|
238
235
|
json_response = @containers_interface.start(container['id'])
|
|
239
|
-
|
|
240
|
-
if options[:json]
|
|
241
|
-
puts as_json(json_response, options)
|
|
242
|
-
elsif !options[:quiet]
|
|
236
|
+
render_response(json_response, options) do
|
|
243
237
|
print green, "Starting container #{container['id']}", reset, "\n"
|
|
244
238
|
end
|
|
245
|
-
return 0
|
|
239
|
+
return 0, nil
|
|
246
240
|
end
|
|
247
241
|
|
|
248
242
|
def restart(args)
|
|
249
243
|
options = {}
|
|
250
244
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
251
|
-
opts.banner = subcommand_usage("[id
|
|
252
|
-
|
|
245
|
+
opts.banner = subcommand_usage("[id]")
|
|
246
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
247
|
+
opts.footer = <<-EOT
|
|
248
|
+
Restart a container.
|
|
249
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
250
|
+
If more than one [id] is given, the command will execute for each one sequentially.
|
|
251
|
+
|
|
252
|
+
Examples:
|
|
253
|
+
containers restart 42
|
|
254
|
+
containers restart 1 2 3 -y
|
|
255
|
+
EOT
|
|
253
256
|
end
|
|
254
257
|
optparse.parse!(args)
|
|
255
|
-
|
|
256
|
-
puts_error "[id] argument is required"
|
|
257
|
-
puts_error optparse
|
|
258
|
-
return 1
|
|
259
|
-
end
|
|
258
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
260
259
|
connect(options)
|
|
261
260
|
id_list = parse_id_list(args)
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
end
|
|
261
|
+
validate_container_ids!(id_list)
|
|
262
|
+
confirm!("Are you sure you would like to restart #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options)
|
|
265
263
|
return run_command_for_each_arg(id_list) do |arg|
|
|
266
264
|
_restart(arg, options)
|
|
267
265
|
end
|
|
@@ -276,32 +274,33 @@ class Morpheus::Cli::ContainersCommand
|
|
|
276
274
|
return 0
|
|
277
275
|
end
|
|
278
276
|
json_response = @containers_interface.restart(container['id'])
|
|
279
|
-
|
|
280
|
-
if options[:json]
|
|
281
|
-
puts as_json(json_response, options)
|
|
282
|
-
elsif !options[:quiet]
|
|
277
|
+
render_response(json_response, options) do
|
|
283
278
|
print green, "Restarting container #{container['id']}", reset, "\n"
|
|
284
279
|
end
|
|
285
|
-
return 0
|
|
280
|
+
return 0, nil
|
|
286
281
|
end
|
|
287
282
|
|
|
288
283
|
def suspend(args)
|
|
289
284
|
options = {}
|
|
290
285
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
291
|
-
opts.banner = subcommand_usage("[id
|
|
292
|
-
|
|
286
|
+
opts.banner = subcommand_usage("[id]")
|
|
287
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
288
|
+
opts.footer = <<-EOT
|
|
289
|
+
Suspend a container.
|
|
290
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
291
|
+
If more than one [id] is given, the command will execute for each one sequentially.
|
|
292
|
+
|
|
293
|
+
Examples:
|
|
294
|
+
containers suspend 42
|
|
295
|
+
containers suspend 1 2 3 -y
|
|
296
|
+
EOT
|
|
293
297
|
end
|
|
294
298
|
optparse.parse!(args)
|
|
295
|
-
|
|
296
|
-
puts_error "[id] argument is required"
|
|
297
|
-
puts_error optparse
|
|
298
|
-
return 1
|
|
299
|
-
end
|
|
299
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
300
300
|
connect(options)
|
|
301
301
|
id_list = parse_id_list(args)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
end
|
|
302
|
+
validate_container_ids!(id_list)
|
|
303
|
+
confirm!("Are you sure you would like to suspend #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options)
|
|
305
304
|
return run_command_for_each_arg(id_list) do |arg|
|
|
306
305
|
_suspend(arg, options)
|
|
307
306
|
end
|
|
@@ -316,32 +315,33 @@ class Morpheus::Cli::ContainersCommand
|
|
|
316
315
|
return 0
|
|
317
316
|
end
|
|
318
317
|
json_response = @containers_interface.suspend(container['id'])
|
|
319
|
-
|
|
320
|
-
if options[:json]
|
|
321
|
-
puts as_json(json_response, options)
|
|
322
|
-
elsif !options[:quiet]
|
|
318
|
+
render_response(json_response, options) do
|
|
323
319
|
print green, "Suspending container #{container['id']}", reset, "\n"
|
|
324
320
|
end
|
|
325
|
-
return 0
|
|
321
|
+
return 0, nil
|
|
326
322
|
end
|
|
327
323
|
|
|
328
324
|
def eject(args)
|
|
329
325
|
options = {}
|
|
330
326
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
331
|
-
opts.banner = subcommand_usage("[id
|
|
332
|
-
|
|
327
|
+
opts.banner = subcommand_usage("[id]")
|
|
328
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
329
|
+
opts.footer = <<-EOT
|
|
330
|
+
Eject a container.
|
|
331
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
332
|
+
If more than one [id] is given, the command will execute for each one sequentially.
|
|
333
|
+
|
|
334
|
+
Examples:
|
|
335
|
+
containers eject 42
|
|
336
|
+
containers eject 1 2 3 -y
|
|
337
|
+
EOT
|
|
333
338
|
end
|
|
334
339
|
optparse.parse!(args)
|
|
335
|
-
|
|
336
|
-
puts_error "[id] argument is required"
|
|
337
|
-
puts_error optparse
|
|
338
|
-
return 1
|
|
339
|
-
end
|
|
340
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
340
341
|
connect(options)
|
|
341
342
|
id_list = parse_id_list(args)
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
end
|
|
343
|
+
validate_container_ids!(id_list)
|
|
344
|
+
confirm!("Are you sure you would like to eject #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options)
|
|
345
345
|
return run_command_for_each_arg(id_list) do |arg|
|
|
346
346
|
_eject(arg, options)
|
|
347
347
|
end
|
|
@@ -356,29 +356,31 @@ class Morpheus::Cli::ContainersCommand
|
|
|
356
356
|
return 0
|
|
357
357
|
end
|
|
358
358
|
json_response = @containers_interface.eject(container['id'])
|
|
359
|
-
|
|
360
|
-
if options[:json]
|
|
361
|
-
puts as_json(json_response, options)
|
|
362
|
-
elsif !options[:quiet]
|
|
359
|
+
render_response(json_response, options) do
|
|
363
360
|
print green, "Ejecting container #{container['id']}", reset, "\n"
|
|
364
361
|
end
|
|
365
|
-
return 0
|
|
362
|
+
return 0, nil
|
|
366
363
|
end
|
|
367
364
|
|
|
368
365
|
def actions(args)
|
|
369
366
|
options = {}
|
|
370
367
|
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
|
371
|
-
opts.banner = subcommand_usage("[id
|
|
372
|
-
opts
|
|
373
|
-
|
|
368
|
+
opts.banner = subcommand_usage("[id]")
|
|
369
|
+
build_standard_get_options(opts, options)
|
|
370
|
+
opts.footer = <<-EOT
|
|
371
|
+
List the actions available to specified container(s).
|
|
372
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
373
|
+
|
|
374
|
+
Examples:
|
|
375
|
+
containers actions 42
|
|
376
|
+
containers actions 1 2 3
|
|
377
|
+
EOT
|
|
374
378
|
end
|
|
375
379
|
optparse.parse!(args)
|
|
376
|
-
|
|
377
|
-
puts optparse
|
|
378
|
-
exit 1
|
|
379
|
-
end
|
|
380
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
380
381
|
connect(options)
|
|
381
382
|
id_list = parse_id_list(args)
|
|
383
|
+
validate_container_ids!(id_list)
|
|
382
384
|
containers = []
|
|
383
385
|
id_list.each do |container_id|
|
|
384
386
|
container = find_container_by_id(container_id)
|
|
@@ -393,58 +395,53 @@ class Morpheus::Cli::ContainersCommand
|
|
|
393
395
|
return 1
|
|
394
396
|
end
|
|
395
397
|
container_ids = containers.collect {|container| container["id"] }
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
398
|
+
# container = find_container_by_name_or_id(args[0])
|
|
399
|
+
@containers_interface.setopts(options)
|
|
400
|
+
if options[:dry_run]
|
|
401
|
+
print_dry_run @containers_interface.dry.available_actions(container_ids.size == 1 ? container_ids[0] : container_ids)
|
|
402
|
+
return 0
|
|
403
|
+
end
|
|
404
|
+
json_response = @containers_interface.available_actions(container_ids.size == 1 ? container_ids[0] : container_ids)
|
|
405
|
+
render_response(json_response, options) do
|
|
406
|
+
title = "Container Actions: #{anded_list(id_list)}"
|
|
407
|
+
print_h1 title
|
|
408
|
+
available_actions = json_response["actions"]
|
|
409
|
+
if (available_actions && available_actions.size > 0)
|
|
410
|
+
print as_pretty_table(available_actions, [:name, :code])
|
|
411
|
+
print reset, "\n"
|
|
406
412
|
else
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
available_actions = json_response["actions"]
|
|
410
|
-
if (available_actions && available_actions.size > 0)
|
|
411
|
-
print as_pretty_table(available_actions, [:name, :code])
|
|
412
|
-
print reset, "\n"
|
|
413
|
+
if container_ids.size > 1
|
|
414
|
+
print "#{yellow}The specified containers have no available actions in common.#{reset}\n\n"
|
|
413
415
|
else
|
|
414
|
-
|
|
415
|
-
print "#{yellow}The specified containers have no available actions in common.#{reset}\n\n"
|
|
416
|
-
else
|
|
417
|
-
print "#{yellow}No available actions#{reset}\n\n"
|
|
418
|
-
end
|
|
416
|
+
print "#{yellow}No available actions#{reset}\n\n"
|
|
419
417
|
end
|
|
420
418
|
end
|
|
421
|
-
return 0
|
|
422
|
-
rescue RestClient::Exception => e
|
|
423
|
-
print_rest_exception(e, options)
|
|
424
|
-
exit 1
|
|
425
419
|
end
|
|
420
|
+
return 0, nil
|
|
426
421
|
end
|
|
427
422
|
|
|
428
423
|
def action(args)
|
|
429
424
|
options = {}
|
|
430
425
|
action_id = nil
|
|
431
426
|
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
|
432
|
-
opts.banner = subcommand_usage("[id
|
|
427
|
+
opts.banner = subcommand_usage("[id] -a CODE")
|
|
433
428
|
opts.on('-a', '--action CODE', "Container Action CODE to execute") do |val|
|
|
434
429
|
action_id = val.to_s
|
|
435
430
|
end
|
|
436
|
-
|
|
437
|
-
opts.footer =
|
|
431
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
432
|
+
opts.footer = <<-EOT
|
|
433
|
+
Execute an action for a container or containers
|
|
434
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
435
|
+
|
|
436
|
+
Examples:
|
|
437
|
+
containers action 42 -a docker-remove-node
|
|
438
|
+
EOT
|
|
438
439
|
end
|
|
439
440
|
optparse.parse!(args)
|
|
440
|
-
|
|
441
|
-
print_error Morpheus::Terminal.angry_prompt
|
|
442
|
-
puts_error "[id list] argument is required"
|
|
443
|
-
puts_error optparse
|
|
444
|
-
return 1
|
|
445
|
-
end
|
|
441
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
446
442
|
connect(options)
|
|
447
443
|
id_list = parse_id_list(args)
|
|
444
|
+
validate_container_ids!(id_list)
|
|
448
445
|
containers = []
|
|
449
446
|
id_list.each do |container_id|
|
|
450
447
|
container = find_container_by_id(container_id)
|
|
@@ -489,29 +486,21 @@ class Morpheus::Cli::ContainersCommand
|
|
|
489
486
|
end
|
|
490
487
|
|
|
491
488
|
action_display_name = "#{container_action['name']} [#{container_action['code']}]"
|
|
492
|
-
|
|
493
|
-
return 9, "aborted command"
|
|
494
|
-
end
|
|
489
|
+
confirm!("Are you sure you would like to perform action #{action_display_name} on #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}?", options)
|
|
495
490
|
|
|
496
491
|
# return run_command_for_each_arg(containers) do |arg|
|
|
497
492
|
# _action(arg, action_id, options)
|
|
498
493
|
# end
|
|
499
494
|
@containers_interface.setopts(options)
|
|
500
495
|
if options[:dry_run]
|
|
501
|
-
print_dry_run @containers_interface.dry.action(container_ids, action_id)
|
|
496
|
+
print_dry_run @containers_interface.dry.action(container_ids.size == 1 ? container_ids[0] : container_ids, action_id)
|
|
502
497
|
return 0
|
|
503
498
|
end
|
|
504
|
-
json_response = @containers_interface.action(container_ids, action_id)
|
|
505
|
-
|
|
506
|
-
if options[:json]
|
|
507
|
-
puts as_json(json_response, options)
|
|
508
|
-
elsif !options[:quiet]
|
|
509
|
-
# containers.each do |container|
|
|
510
|
-
# print green, "Action #{action_display_name} performed on container #{container['id']}", reset, "\n"
|
|
511
|
-
# end
|
|
499
|
+
json_response = @containers_interface.action(container_ids.size == 1 ? container_ids[0] : container_ids, action_id)
|
|
500
|
+
render_response(json_response, options) do
|
|
512
501
|
print green, "Action #{action_display_name} performed on #{id_list.size == 1 ? 'container' : 'containers'} #{anded_list(id_list)}", reset, "\n"
|
|
513
502
|
end
|
|
514
|
-
return 0
|
|
503
|
+
return 0, nil
|
|
515
504
|
end
|
|
516
505
|
|
|
517
506
|
def logs(args)
|
|
@@ -534,35 +523,35 @@ class Morpheus::Cli::ContainersCommand
|
|
|
534
523
|
opts.on('-a', '--all', "Display all details: entire message." ) do
|
|
535
524
|
options[:details] = true
|
|
536
525
|
end
|
|
537
|
-
|
|
538
|
-
opts.footer =
|
|
539
|
-
|
|
526
|
+
build_standard_list_options(opts, options)
|
|
527
|
+
opts.footer = <<-EOT
|
|
528
|
+
List logs for a container.
|
|
529
|
+
[id] is required. This is the id of a container. Supports multiple [id] arguments.
|
|
530
|
+
|
|
531
|
+
Examples:
|
|
532
|
+
containers logs 42 --level ERROR
|
|
533
|
+
EOT
|
|
540
534
|
end
|
|
541
535
|
optparse.parse!(args)
|
|
542
|
-
|
|
543
|
-
puts_error "[id] argument is required"
|
|
544
|
-
puts_error optparse
|
|
545
|
-
return 1
|
|
546
|
-
end
|
|
536
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
|
547
537
|
connect(options)
|
|
548
538
|
id_list = parse_id_list(args)
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
539
|
+
validate_container_ids!(id_list)
|
|
540
|
+
|
|
541
|
+
containers = id_list # heh
|
|
542
|
+
params['level'] = params['level'].collect {|it| it.to_s.upcase }.join('|') if params['level'] # api works with INFO|WARN
|
|
543
|
+
params.merge!(parse_list_options(options))
|
|
544
|
+
params['query'] = params.delete('phrase') if params['phrase']
|
|
545
|
+
params[:order] = params[:direction] unless params[:direction].nil? # old api version expects order instead of direction
|
|
546
|
+
params['startMs'] = (options[:start].to_i * 1000) if options[:start]
|
|
547
|
+
params['endMs'] = (options[:end].to_i * 1000) if options[:end]
|
|
548
|
+
@logs_interface.setopts(options)
|
|
549
|
+
if options[:dry_run]
|
|
550
|
+
print_dry_run @logs_interface.dry.container_logs(containers, params)
|
|
551
|
+
return
|
|
552
|
+
end
|
|
553
|
+
json_response = @logs_interface.container_logs(containers, params)
|
|
554
|
+
render_response(json_response, options, "logs") do
|
|
566
555
|
logs = json_response
|
|
567
556
|
title = "Container Logs: #{containers.join(', ')}"
|
|
568
557
|
subtitles = parse_list_subtitles(options)
|
|
@@ -587,11 +576,8 @@ class Morpheus::Cli::ContainersCommand
|
|
|
587
576
|
print_results_pagination({'meta'=>{'total'=>(json_response['total']['value'] rescue json_response['total']),'size'=>logs.size,'max'=>(json_response['max'] || options[:max]),'offset'=>(json_response['offset'] || options[:offset] || 0)}})
|
|
588
577
|
end
|
|
589
578
|
print reset,"\n"
|
|
590
|
-
return 0
|
|
591
|
-
rescue RestClient::Exception => e
|
|
592
|
-
print_rest_exception(e, options)
|
|
593
|
-
exit 1
|
|
594
579
|
end
|
|
580
|
+
return 0, nil
|
|
595
581
|
end
|
|
596
582
|
|
|
597
583
|
def execution_request(args)
|
|
@@ -606,7 +592,7 @@ class Morpheus::Cli::ContainersCommand
|
|
|
606
592
|
end
|
|
607
593
|
opts.on('--file FILE', "File containing the script. This can be used instead of --script" ) do |filename|
|
|
608
594
|
full_filename = File.expand_path(filename)
|
|
609
|
-
if File.
|
|
595
|
+
if File.exist?(full_filename)
|
|
610
596
|
script_content = File.read(full_filename)
|
|
611
597
|
else
|
|
612
598
|
print_red_alert "File not found: #{full_filename}"
|
|
@@ -617,51 +603,46 @@ class Morpheus::Cli::ContainersCommand
|
|
|
617
603
|
do_refresh = false
|
|
618
604
|
end
|
|
619
605
|
#build_option_type_options(opts, options, add_user_source_option_types())
|
|
620
|
-
|
|
621
|
-
opts.footer =
|
|
622
|
-
|
|
623
|
-
|
|
606
|
+
build_standard_update_options(opts, options)
|
|
607
|
+
opts.footer = <<-EOT
|
|
608
|
+
Execute an arbitrary command or script on a container.
|
|
609
|
+
[id] is required. This is the id of a container.
|
|
610
|
+
[script] is required and can be passed as --script of --file instead. This is the script that is to be executed.
|
|
611
|
+
|
|
612
|
+
Examples:
|
|
613
|
+
containers exec 42 "uname -a"
|
|
614
|
+
EOT
|
|
624
615
|
end
|
|
625
616
|
optparse.parse!(args)
|
|
626
617
|
connect(options)
|
|
627
|
-
|
|
628
|
-
print_error Morpheus::Terminal.angry_prompt
|
|
629
|
-
puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
|
|
630
|
-
return 1
|
|
631
|
-
end
|
|
618
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
632
619
|
|
|
633
620
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
script_content = v_prompt['script']
|
|
648
|
-
end
|
|
649
|
-
payload['script'] = script_content
|
|
650
|
-
end
|
|
651
|
-
@execution_request_interface.setopts(options)
|
|
652
|
-
if options[:dry_run]
|
|
653
|
-
print_dry_run @execution_request_interface.dry.create(params, payload)
|
|
654
|
-
return 0
|
|
655
|
-
end
|
|
656
|
-
# do it
|
|
657
|
-
json_response = @execution_request_interface.create(params, payload)
|
|
658
|
-
# print and return result
|
|
659
|
-
if options[:quiet]
|
|
660
|
-
return 0
|
|
661
|
-
elsif options[:json]
|
|
662
|
-
puts as_json(json_response, options)
|
|
663
|
-
return 0
|
|
621
|
+
container = find_container_by_id(args[0])
|
|
622
|
+
return 1 if container.nil?
|
|
623
|
+
params['containerId'] = container['id']
|
|
624
|
+
# construct payload
|
|
625
|
+
payload = {}
|
|
626
|
+
if options[:payload]
|
|
627
|
+
payload = options[:payload]
|
|
628
|
+
else
|
|
629
|
+
payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
|
630
|
+
# prompt for Script
|
|
631
|
+
if script_content.nil?
|
|
632
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'script', 'type' => 'code-editor', 'fieldLabel' => 'Script', 'required' => true, 'description' => 'The script content'}], options[:options])
|
|
633
|
+
script_content = v_prompt['script']
|
|
664
634
|
end
|
|
635
|
+
payload['script'] = script_content
|
|
636
|
+
end
|
|
637
|
+
@execution_request_interface.setopts(options)
|
|
638
|
+
if options[:dry_run]
|
|
639
|
+
print_dry_run @execution_request_interface.dry.create(params, payload)
|
|
640
|
+
return 0
|
|
641
|
+
end
|
|
642
|
+
# do it
|
|
643
|
+
json_response = @execution_request_interface.create(params, payload)
|
|
644
|
+
# print and return result
|
|
645
|
+
render_response(json_response, options) do
|
|
665
646
|
execution_request = json_response['executionRequest']
|
|
666
647
|
print_green_success "Executing request #{execution_request['uniqueId']}"
|
|
667
648
|
if do_refresh
|
|
@@ -669,11 +650,127 @@ class Morpheus::Cli::ContainersCommand
|
|
|
669
650
|
else
|
|
670
651
|
Morpheus::Cli::ExecutionRequestCommand.new.handle(["get", execution_request['uniqueId']]+ (options[:remote] ? ["-r",options[:remote]] : []))
|
|
671
652
|
end
|
|
672
|
-
return 0
|
|
673
|
-
rescue RestClient::Exception => e
|
|
674
|
-
print_rest_exception(e, options)
|
|
675
|
-
exit 1
|
|
676
653
|
end
|
|
654
|
+
return 0, nil
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
def import(args)
|
|
658
|
+
options = {}
|
|
659
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
660
|
+
opts.banner = subcommand_usage("[id] [image]")
|
|
661
|
+
opts.on( '--storage-provider VALUE', String, "Optional storage provider to use" ) do |val|
|
|
662
|
+
options[:options]['storageProviderId'] = val
|
|
663
|
+
end
|
|
664
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
665
|
+
opts.footer = <<-EOT
|
|
666
|
+
Import image template for a container.
|
|
667
|
+
[id] is required. This is the id of a container.
|
|
668
|
+
EOT
|
|
669
|
+
end
|
|
670
|
+
optparse.parse!(args)
|
|
671
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
672
|
+
connect(options)
|
|
673
|
+
container = find_container_by_id(args[0])
|
|
674
|
+
return 1 if container.nil?
|
|
675
|
+
instance = find_instance_by_name_or_id(container['instance']['id'])
|
|
676
|
+
return 1 if instance.nil?
|
|
677
|
+
# need to GET provision type for exportServer == true
|
|
678
|
+
provision_type = load_container_provision_type(container, instance)
|
|
679
|
+
# todo: add this exportServer to the api too obviously (oh it is there.. but clone-image is not)
|
|
680
|
+
# if provision_type['exportServer'] != true
|
|
681
|
+
# raise_command_error "import is not supported by provision type #{provision_type['name']}"
|
|
682
|
+
# end
|
|
683
|
+
payload = parse_payload(options)
|
|
684
|
+
if payload.nil?
|
|
685
|
+
payload = parse_passed_options(options)
|
|
686
|
+
container_import_option_types = [
|
|
687
|
+
{'fieldName' => 'storageProviderId', 'type' => 'select', 'fieldLabel' => 'Storage Provider', 'optionSource' => 'storageProviders', 'required' => false, 'description' => 'Select Storage Provider.'}
|
|
688
|
+
]
|
|
689
|
+
payload.deep_merge! Morpheus::Cli::OptionTypes.prompt(container_import_option_types, options[:options], @api_client, {})
|
|
690
|
+
end
|
|
691
|
+
confirm!("Are you sure you would like to import container #{container['id']}?", options)
|
|
692
|
+
@containers_interface.setopts(options)
|
|
693
|
+
if options[:dry_run]
|
|
694
|
+
print_dry_run @containers_interface.dry.import(container['id'], payload)
|
|
695
|
+
return
|
|
696
|
+
end
|
|
697
|
+
json_response = @containers_interface.import(container['id'], payload)
|
|
698
|
+
render_response(json_response, options) do
|
|
699
|
+
print_green_success "Import initiated for container [#{container['id']}] #{container['name']}"
|
|
700
|
+
end
|
|
701
|
+
return 0, nil
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
def clone_image(args)
|
|
705
|
+
options = {}
|
|
706
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
707
|
+
opts.banner = subcommand_usage("[id]")
|
|
708
|
+
opts.on( '--name VALUE', String, "Image Name (Template Name). Default is server name + timestamp" ) do |val|
|
|
709
|
+
options[:options]['templateName'] = val
|
|
710
|
+
end
|
|
711
|
+
opts.on( '--folder VALUE', String, "Folder externalId or '/' to use the root folder" ) do |val|
|
|
712
|
+
options[:options]['zoneFolder'] = val
|
|
713
|
+
end
|
|
714
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
|
715
|
+
opts.footer = <<-EOT
|
|
716
|
+
Clone to image (template) for a container.
|
|
717
|
+
[id] is required. This is the id of a container.
|
|
718
|
+
EOT
|
|
719
|
+
end
|
|
720
|
+
optparse.parse!(args)
|
|
721
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
|
722
|
+
connect(options)
|
|
723
|
+
container = find_container_by_id(args[0])
|
|
724
|
+
return 1 if container.nil?
|
|
725
|
+
# need to GET provision type for hasFolders == true and cloneTemplte == true
|
|
726
|
+
instance = find_instance_by_name_or_id(container['instance']['id'])
|
|
727
|
+
return 1 if instance.nil?
|
|
728
|
+
provision_type = load_container_provision_type(container, instance)
|
|
729
|
+
# todo: add this cloneTemplate check to the api too obviously
|
|
730
|
+
# if provision_type['cloneTemplate'] != true
|
|
731
|
+
# raise_command_error "clone-image is not supported by provision type #{provision_type['name']}"
|
|
732
|
+
# end
|
|
733
|
+
payload = parse_payload(options)
|
|
734
|
+
if payload.nil?
|
|
735
|
+
payload = parse_passed_options(options)
|
|
736
|
+
if payload['templateName'].nil?
|
|
737
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'templateName', 'type' => 'text', 'fieldLabel' => 'Image Name', 'description' => 'Choose a name for the new image template. Default is the server name + timestamp'}], options[:options])
|
|
738
|
+
if v_prompt['templateName'].to_s != ''
|
|
739
|
+
payload['templateName'] = v_prompt['templateName']
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
#if provision_type['code'] == 'vmware'
|
|
743
|
+
if provision_type && provision_type["hasFolders"]
|
|
744
|
+
if payload['zoneFolder'].nil?
|
|
745
|
+
# vmwareFolders moved from /api/options/vmwareFolders to /api/options/vmware/vmwareFolders
|
|
746
|
+
folder_prompt = nil
|
|
747
|
+
begin
|
|
748
|
+
folder_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneFolder', 'type' => 'select', 'optionSource' => 'vmwareFolders', 'optionSourceType' => 'vmware', 'fieldLabel' => 'Folder', 'description' => "Folder externalId or '/' to use the root folder", 'required' => true}], options[:options], @api_client, {siteId: instance['group']['id'], zoneId: instance['cloud']['id']})
|
|
749
|
+
rescue RestClient::Exception => e
|
|
750
|
+
Morpheus::Logging::DarkPrinter.puts "Failed to load folder options" if Morpheus::Logging.debug?
|
|
751
|
+
begin
|
|
752
|
+
folder_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'zoneFolder', 'type' => 'select', 'optionSource' => 'vmwareFolders', 'fieldLabel' => 'Folder', 'description' => "Folder externalId or '/' to use the root folder", 'required' => true}], options[:options], @api_client, {siteId: instance['group']['id'], zoneId: instance['cloud']['id']})
|
|
753
|
+
rescue RestClient::Exception => e2
|
|
754
|
+
Morpheus::Logging::DarkPrinter.puts "Failed to load folder options from alternative endpoint too" if Morpheus::Logging.debug?
|
|
755
|
+
end
|
|
756
|
+
end
|
|
757
|
+
if folder_prompt && folder_prompt['zoneFolder'].to_s != ''
|
|
758
|
+
payload['zoneFolder'] = folder_prompt['zoneFolder']
|
|
759
|
+
end
|
|
760
|
+
end
|
|
761
|
+
end
|
|
762
|
+
end
|
|
763
|
+
confirm!("Are you sure you would like to clone as image container #{container['id']}?", options)
|
|
764
|
+
@containers_interface.setopts(options)
|
|
765
|
+
if options[:dry_run]
|
|
766
|
+
print_dry_run @containers_interface.dry.clone_image(container['id'], payload)
|
|
767
|
+
return
|
|
768
|
+
end
|
|
769
|
+
json_response = @containers_interface.clone_image(container['id'], payload)
|
|
770
|
+
render_response(json_response, options) do
|
|
771
|
+
print_green_success "Clone Image initiated for container [#{container['id']}] #{container['name']}"
|
|
772
|
+
end
|
|
773
|
+
return 0, nil
|
|
677
774
|
end
|
|
678
775
|
|
|
679
776
|
private
|
|
@@ -692,4 +789,52 @@ private
|
|
|
692
789
|
end
|
|
693
790
|
end
|
|
694
791
|
|
|
792
|
+
def validate_container_ids!(id_list)
|
|
793
|
+
id_list.each { |id| validate_container_id!(id) }
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
def validate_container_id!(id)
|
|
797
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
|
798
|
+
true
|
|
799
|
+
else
|
|
800
|
+
raise_command_error "[id] argument is invalid, expected a number and got '#{id}'" #, args, optparse
|
|
801
|
+
end
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
def load_container_provision_type(container, instance=nil)
|
|
805
|
+
if instance.nil?
|
|
806
|
+
instance = find_instance_by_name_or_id(container['instance']['id'])
|
|
807
|
+
return 1 if instance.nil?
|
|
808
|
+
end
|
|
809
|
+
# todo: should be returned by containers api too, get from instance for old api versions
|
|
810
|
+
provision_type_code = container['containerType']['provisionTypeCode'] rescue nil
|
|
811
|
+
provision_type_code = provision_type_code || container['provisionType']['code'] rescue nil
|
|
812
|
+
if provision_type_code.nil?
|
|
813
|
+
return load_instance_provision_type(instance)
|
|
814
|
+
end
|
|
815
|
+
provision_type = nil
|
|
816
|
+
if provision_type_code
|
|
817
|
+
provision_type = provision_types_interface.list({code:provision_type_code})['provisionTypes'][0]
|
|
818
|
+
if provision_type.nil?
|
|
819
|
+
raise_command_error "Provision Type not found by code #{provision_type_code}"
|
|
820
|
+
end
|
|
821
|
+
else
|
|
822
|
+
raise_command_error "Unable to determine provision type for container #{container['id']}"
|
|
823
|
+
end
|
|
824
|
+
return provision_type
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
def load_instance_provision_type(instance)
|
|
828
|
+
provision_type_code = instance['layout']['provisionTypeCode'] rescue nil
|
|
829
|
+
provision_type = nil
|
|
830
|
+
if provision_type_code
|
|
831
|
+
provision_type = provision_types_interface.list({code:provision_type_code})['provisionTypes'][0]
|
|
832
|
+
if provision_type.nil?
|
|
833
|
+
raise_command_error "Provision Type not found by code #{provision_type_code}"
|
|
834
|
+
end
|
|
835
|
+
else
|
|
836
|
+
raise_command_error "Unable to determine provision type for instance #{instance['id']}"
|
|
837
|
+
end
|
|
838
|
+
return provision_type
|
|
839
|
+
end
|
|
695
840
|
end
|