morpheus-cli 7.0.7 → 8.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 +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +11 -0
- data/lib/morpheus/api/clusters_interface.rb +25 -0
- data/lib/morpheus/api/datastores_interface.rb +6 -0
- data/lib/morpheus/api/library_operating_systems_interface.rb +63 -0
- data/lib/morpheus/api/processes_interface.rb +17 -5
- data/lib/morpheus/cli/commands/backup_jobs_command.rb +50 -17
- data/lib/morpheus/cli/commands/backups_command.rb +36 -9
- data/lib/morpheus/cli/commands/clusters.rb +380 -6
- data/lib/morpheus/cli/commands/hosts.rb +3 -0
- data/lib/morpheus/cli/commands/instances.rb +33 -4
- data/lib/morpheus/cli/commands/library_container_types_command.rb +6 -0
- data/lib/morpheus/cli/commands/library_operating_systems_command.rb +671 -0
- data/lib/morpheus/cli/commands/license.rb +11 -1
- data/lib/morpheus/cli/commands/processes_command.rb +71 -1
- data/lib/morpheus/cli/commands/setup.rb +32 -18
- data/lib/morpheus/cli/commands/virtual_images.rb +10 -2
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +28 -2
- data/lib/morpheus/cli/option_types.rb +3 -0
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/formatters.rb +12 -0
- metadata +5 -3
@@ -13,18 +13,20 @@ class Morpheus::Cli::Clusters
|
|
13
13
|
register_subcommands :upgrade_cluster
|
14
14
|
register_subcommands :list_volumes, :remove_volume
|
15
15
|
register_subcommands :list_namespaces, :get_namespace, :add_namespace, :update_namespace, :remove_namespace
|
16
|
-
register_subcommands :list_containers, :remove_container, :restart_container
|
16
|
+
register_subcommands :list_containers, :remove_container, :restart_container, :get_container
|
17
17
|
register_subcommands :list_deployments, :remove_deployment, :restart_deployment
|
18
18
|
register_subcommands :list_stateful_sets, :remove_stateful_set, :restart_stateful_set
|
19
19
|
register_subcommands :list_pods, :remove_pod, :restart_pod
|
20
20
|
register_subcommands :list_jobs, :remove_job
|
21
21
|
register_subcommands :list_services, :remove_service
|
22
|
-
register_subcommands :list_datastores, :get_datastore, :update_datastore
|
22
|
+
register_subcommands :list_datastores, :get_datastore, :update_datastore, :add_datastore, :remove_datastore
|
23
23
|
register_subcommands :update_permissions
|
24
24
|
register_subcommands :api_config, :view_api_token, :view_kube_config
|
25
25
|
register_subcommands :wiki, :update_wiki
|
26
26
|
register_subcommands :apply_template
|
27
27
|
register_subcommands :refresh
|
28
|
+
register_subcommands :list_replicasets, :list_daemonsets, :list_endpoints, :list_ingresses, :list_policies, :list_volumes, :list_volume_claims, :list_config_maps, :list_secrets
|
29
|
+
register_subcommands :get_pod, :get_deployment, :get_replicaset, :get_daemonset, :get_endpoint, :get_ingress, :get_policy, :get_volume_claim, :get_volume, :get_config_map, :get_secret, :get_stateful_set, :get_job, :get_service
|
28
30
|
|
29
31
|
def connect(opts)
|
30
32
|
@api_client = establish_remote_appliance_connection(opts)
|
@@ -32,6 +34,7 @@ class Morpheus::Cli::Clusters
|
|
32
34
|
@groups_interface = @api_client.groups
|
33
35
|
@cluster_layouts_interface = @api_client.library_cluster_layouts
|
34
36
|
@security_groups_interface = @api_client.security_groups
|
37
|
+
@datastores_interface = @api_client.datastores
|
35
38
|
#@security_group_rules_interface = @api_client.security_group_rules
|
36
39
|
@cloud_resource_pools_interface = @api_client.cloud_resource_pools
|
37
40
|
@resource_pool_groups_interface = @api_client.resource_pool_groups
|
@@ -220,6 +223,7 @@ class Morpheus::Cli::Clusters
|
|
220
223
|
"Cloud" => lambda { |it| it['zone']['name'] },
|
221
224
|
"Location" => lambda { |it| it['location'] },
|
222
225
|
"Layout" => lambda { |it| it['layout'] ? it['layout']['name'] : ''},
|
226
|
+
"Integrations" => lambda {|it| format_name_and_id(it['integrations']) },
|
223
227
|
"API Url" => 'serviceUrl',
|
224
228
|
"Visibility" => lambda { |it| it['visibility'].to_s.capitalize },
|
225
229
|
#"Groups" => lambda {|it| it['groups'].collect {|g| g.instance_of?(Hash) ? g['name'] : g.to_s }.join(', ') },
|
@@ -228,6 +232,8 @@ class Morpheus::Cli::Clusters
|
|
228
232
|
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
229
233
|
"Created By" => lambda {|it| it['createdBy'] ? it['createdBy']['username'] : '' },
|
230
234
|
"Enabled" => lambda { |it| format_boolean(it['enabled']) },
|
235
|
+
"Managed" => lambda { |it| format_boolean(it['managed']) },
|
236
|
+
"Auto Power On VMs" => lambda { |it| format_boolean(it['autoRecoverPowerState']) },
|
231
237
|
"Status" => lambda { |it| format_cluster_status(it) }
|
232
238
|
}
|
233
239
|
print_description_list(description_cols, cluster)
|
@@ -796,12 +802,18 @@ class Morpheus::Cli::Clusters
|
|
796
802
|
opts.on('--managed [on|off]', String, "Can be used to enable / disable managed cluster. Default is on") do |val|
|
797
803
|
options[:managed] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
798
804
|
end
|
805
|
+
opts.on('--autoRecoverPowerState [on|off]', String, "Automatically Power On VMs") do |val|
|
806
|
+
options[:autoRecoverPowerState] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
|
807
|
+
end
|
799
808
|
opts.on( nil, '--refresh', "Refresh cluster" ) do
|
800
809
|
options[:refresh] = true
|
801
810
|
end
|
802
811
|
opts.on("--tenant ACCOUNT", String, "Account ID or Name" ) do |val|
|
803
812
|
options[:tenant] = val
|
804
813
|
end
|
814
|
+
opts.on('--integrations [LIST]', Array, "Updates Cluster Integration(s), comma separated list of integration IDs") do |list|
|
815
|
+
options[:integrations] = list ? list.collect {|it| it.to_s.strip.to_i } : []
|
816
|
+
end
|
805
817
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
806
818
|
opts.footer = "Update a cluster.\n" +
|
807
819
|
"[cluster] is required. This is the name or id of an existing cluster."
|
@@ -831,15 +843,18 @@ class Morpheus::Cli::Clusters
|
|
831
843
|
else
|
832
844
|
cluster = find_cluster_by_name_or_id(args[0])
|
833
845
|
cluster_payload = {}
|
846
|
+
cluster_payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
|
834
847
|
cluster_payload['name'] = options[:name] if !options[:name].empty?
|
835
848
|
cluster_payload['description'] = options[:description] if !options[:description].empty?
|
836
849
|
cluster_payload['labels'] = options[:labels] if !options[:labels].nil?
|
837
850
|
cluster_payload['enabled'] = options[:active] if !options[:active].nil?
|
838
851
|
cluster_payload['managed'] = options[:managed] if !options[:managed].nil?
|
852
|
+
cluster_payload['autoRecoverPowerState'] = options[:autoRecoverPowerState] if !options[:autoRecoverPowerState].nil?
|
839
853
|
cluster_payload['serviceUrl'] = options[:apiUrl] if !options[:apiUrl].nil?
|
840
854
|
cluster_payload['serviceToken'] = options[:apiToken] if !options[:apiToken].nil?
|
841
855
|
cluster_payload['refresh'] = options[:refresh] if options[:refresh] == true
|
842
856
|
cluster_payload['tenant'] = options[:tenant] if !options[:tenant].nil?
|
857
|
+
cluster_payload['integrations'] = options[:integrations] if !options[:integrations].nil?
|
843
858
|
payload = {"cluster" => cluster_payload}
|
844
859
|
end
|
845
860
|
|
@@ -847,10 +862,9 @@ class Morpheus::Cli::Clusters
|
|
847
862
|
print_red_alert "No clusters available for update"
|
848
863
|
exit 1
|
849
864
|
end
|
850
|
-
|
851
|
-
if
|
852
|
-
|
853
|
-
exit 1
|
865
|
+
|
866
|
+
if payload['cluster'].empty?
|
867
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
854
868
|
end
|
855
869
|
|
856
870
|
@clusters_interface.setopts(options)
|
@@ -2205,6 +2219,7 @@ class Morpheus::Cli::Clusters
|
|
2205
2219
|
:id, :status, :name, :cpu, :memory, :storage
|
2206
2220
|
]
|
2207
2221
|
print as_pretty_table(rows, columns, options)
|
2222
|
+
print_results_pagination(json_response)
|
2208
2223
|
end
|
2209
2224
|
print reset,"\n"
|
2210
2225
|
return 0
|
@@ -2214,6 +2229,43 @@ class Morpheus::Cli::Clusters
|
|
2214
2229
|
end
|
2215
2230
|
end
|
2216
2231
|
|
2232
|
+
def _get_container_group(args, options, resource_type)
|
2233
|
+
begin
|
2234
|
+
cluster = find_cluster_by_name_or_id(args[0])
|
2235
|
+
id = args[1]
|
2236
|
+
return 1 if cluster.nil?
|
2237
|
+
|
2238
|
+
params = {}
|
2239
|
+
params.merge!(parse_list_options(options))
|
2240
|
+
params['resourceLevel'] = options[:resourceLevel] if !options[:resourceLevel].nil?
|
2241
|
+
@clusters_interface.setopts(options)
|
2242
|
+
if options[:dry_run]
|
2243
|
+
print_dry_run @clusters_interface.dry.get_container_group(cluster['id'], resource_type, id, params)
|
2244
|
+
return
|
2245
|
+
end
|
2246
|
+
container_group = @clusters_interface.get_container_group(cluster['id'], resource_type, id, params)['resource']
|
2247
|
+
|
2248
|
+
render_result = render_with_format(container_group, options, 'containers')
|
2249
|
+
return 0 if render_result
|
2250
|
+
resource_is = options['title'] ? options['title'].capitalize : resource_type.capitalize
|
2251
|
+
title = "Morpheus Cluster #{cluster['name']}: #{resource_is}"
|
2252
|
+
print_h1 title
|
2253
|
+
print cyan
|
2254
|
+
description_cols = {
|
2255
|
+
"ID" => 'id',
|
2256
|
+
"Name" => 'name',
|
2257
|
+
"Status" => 'status',
|
2258
|
+
"metadata" => lambda { |it| as_json(it['metadata']) }
|
2259
|
+
}
|
2260
|
+
print_description_list(description_cols, container_group)
|
2261
|
+
print reset,"\n"
|
2262
|
+
return 0
|
2263
|
+
rescue RestClient::Exception => e
|
2264
|
+
print_rest_exception(e, options)
|
2265
|
+
exit 1
|
2266
|
+
end
|
2267
|
+
end
|
2268
|
+
|
2217
2269
|
def _remove_container_group(args, options, resource_type)
|
2218
2270
|
begin
|
2219
2271
|
cluster = find_cluster_by_name_or_id(args[0])
|
@@ -2321,6 +2373,26 @@ class Morpheus::Cli::Clusters
|
|
2321
2373
|
_list_container_groups(args, options,resource_type)
|
2322
2374
|
end
|
2323
2375
|
|
2376
|
+
def get_deployment(args)
|
2377
|
+
resource_type = 'deployment'
|
2378
|
+
options = {}
|
2379
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
2380
|
+
opts.banner = subcommand_usage( "[cluster]")
|
2381
|
+
opts.on("--resource-level LEVEL", String, "Resource Level") do |val|
|
2382
|
+
options[:resourceLevel] = val.to_s
|
2383
|
+
end
|
2384
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
2385
|
+
opts.footer = "get #{resource_type} for a cluster.\n" +
|
2386
|
+
"[cluster] and [#{resource_type}] is required. This is the name or id of an existing cluster, and the id of the #{resource_type}"
|
2387
|
+
end
|
2388
|
+
optparse.parse!(args)
|
2389
|
+
if args.count != 2
|
2390
|
+
raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
2391
|
+
end
|
2392
|
+
connect(options)
|
2393
|
+
_get_container_group(args, options, resource_type)
|
2394
|
+
end
|
2395
|
+
|
2324
2396
|
def remove_deployment(args)
|
2325
2397
|
resource_type = 'deployment'
|
2326
2398
|
options = {}
|
@@ -2439,6 +2511,26 @@ class Morpheus::Cli::Clusters
|
|
2439
2511
|
_list_container_groups(args, options, resource_type)
|
2440
2512
|
end
|
2441
2513
|
|
2514
|
+
def get_pod(args)
|
2515
|
+
resource_type = 'pod'
|
2516
|
+
options = {}
|
2517
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
2518
|
+
opts.banner = subcommand_usage( "[cluster]")
|
2519
|
+
opts.on("--resource-level LEVEL", String, "Resource Level") do |val|
|
2520
|
+
options[:resourceLevel] = val.to_s
|
2521
|
+
end
|
2522
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
2523
|
+
opts.footer = "get #{resource_type} for a cluster.\n" +
|
2524
|
+
"[cluster] and [#{resource_type}] is required. This is the name or id of an existing cluster, and the id of the #{resource_type}"
|
2525
|
+
end
|
2526
|
+
optparse.parse!(args)
|
2527
|
+
if args.count != 2
|
2528
|
+
raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
2529
|
+
end
|
2530
|
+
connect(options)
|
2531
|
+
_get_container_group(args, options, resource_type)
|
2532
|
+
end
|
2533
|
+
|
2442
2534
|
def remove_pod(args)
|
2443
2535
|
resource_type = 'pod'
|
2444
2536
|
options = {}
|
@@ -2908,6 +3000,130 @@ class Morpheus::Cli::Clusters
|
|
2908
3000
|
end
|
2909
3001
|
end
|
2910
3002
|
|
3003
|
+
def add_datastore(args)
|
3004
|
+
options = {}
|
3005
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
3006
|
+
opts.banner = subcommand_usage( "[cluster] [options]")
|
3007
|
+
build_option_type_options(opts, options, add_datastore_option_types)
|
3008
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
3009
|
+
opts.footer = "Add datastore to a cluster.\n" +
|
3010
|
+
"[cluster] is required. This is the name or id of an existing cluster.\n" +
|
3011
|
+
"[name] is required. This is the name of the new datastore."
|
3012
|
+
end
|
3013
|
+
|
3014
|
+
optparse.parse!(args)
|
3015
|
+
if args.count != 1 and args.count != 2
|
3016
|
+
raise_command_error "wrong number of arguments, expected 1-2 and got (#{args.count}) #{args}\n#{optparse}"
|
3017
|
+
end
|
3018
|
+
connect(options)
|
3019
|
+
|
3020
|
+
begin
|
3021
|
+
cluster = find_cluster_by_name_or_id(args[0])
|
3022
|
+
return 1 if cluster.nil?
|
3023
|
+
if options[:payload]
|
3024
|
+
payload = options[:payload]
|
3025
|
+
# support -O OPTION switch on top of --payload
|
3026
|
+
if options[:options]
|
3027
|
+
payload ||= {}
|
3028
|
+
payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
|
3029
|
+
end
|
3030
|
+
else
|
3031
|
+
options[:params] ||= {}
|
3032
|
+
options[:params].merge!({:serverGroupId => cluster['id']})
|
3033
|
+
|
3034
|
+
datastore = Morpheus::Cli::OptionTypes.prompt(add_datastore_option_types, options[:options], @api_client, options[:params])
|
3035
|
+
|
3036
|
+
datastore_type = find_datastore_type_by_code(datastore['datastoreType'])
|
3037
|
+
datastore['datastoreType'] = {id:datastore_type['id']}
|
3038
|
+
|
3039
|
+
# datastore type options
|
3040
|
+
unless datastore_type['optionTypes'].empty?
|
3041
|
+
datastore.merge!(Morpheus::Cli::OptionTypes.prompt(datastore_type['optionTypes'], options[:options].deep_merge({:context_map => {'domain' => ''}, :checkbox_as_boolean => true}), @api_client, options[:params]))
|
3042
|
+
end
|
3043
|
+
|
3044
|
+
# perms
|
3045
|
+
perms = prompt_permissions(options.merge({:for_datastore => true}), ['plans', 'groupDefaults'])
|
3046
|
+
|
3047
|
+
datastore['resourcePermissions'] = perms['resourcePermissions'] unless perms['resourcePermissions'].nil?
|
3048
|
+
datastore['tenants'] = perms['tenantPermissions'] unless perms['tenantPermissions'].nil?
|
3049
|
+
datastore['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
3050
|
+
|
3051
|
+
payload = {datastore:datastore}
|
3052
|
+
end
|
3053
|
+
|
3054
|
+
@clusters_interface.setopts(options)
|
3055
|
+
if options[:dry_run]
|
3056
|
+
print_dry_run @clusters_interface.dry.create_datastore(cluster['id'], payload)
|
3057
|
+
return
|
3058
|
+
end
|
3059
|
+
json_response = @clusters_interface.create_datastore(cluster['id'], payload)
|
3060
|
+
if options[:json]
|
3061
|
+
puts as_json(json_response)
|
3062
|
+
elsif json_response['success']
|
3063
|
+
if json_response['msg'] == nil
|
3064
|
+
print_green_success "Added datastore to cluster #{cluster['name']}"
|
3065
|
+
else
|
3066
|
+
print_green_success json_response['msg']
|
3067
|
+
end
|
3068
|
+
end
|
3069
|
+
return 0
|
3070
|
+
rescue RestClient::Exception => e
|
3071
|
+
print_rest_exception(e, options)
|
3072
|
+
exit 1
|
3073
|
+
end
|
3074
|
+
end
|
3075
|
+
|
3076
|
+
def remove_datastore(args)
|
3077
|
+
params = {}
|
3078
|
+
options = {}
|
3079
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
3080
|
+
opts.banner = subcommand_usage("[cluster] [datastore]")
|
3081
|
+
opts.on( '-f', '--force', "Force Delete" ) do
|
3082
|
+
params[:force] = 'on'
|
3083
|
+
end
|
3084
|
+
build_standard_remove_options(opts, options)
|
3085
|
+
opts.footer = "Delete a datastore from a cluster.\n" +
|
3086
|
+
"[cluster] is required. This is the name or id of an existing cluster.\n" +
|
3087
|
+
"[datastore] is required. This is the name or id of an existing datastore."
|
3088
|
+
end
|
3089
|
+
optparse.parse!(args)
|
3090
|
+
verify_args!(args:args, optparse:optparse, count:2)
|
3091
|
+
connect(options)
|
3092
|
+
params.merge!(parse_query_options(options))
|
3093
|
+
|
3094
|
+
cluster = find_cluster_by_name_or_id(args[0])
|
3095
|
+
return 1 if cluster.nil?
|
3096
|
+
|
3097
|
+
datastore_id = args[1]
|
3098
|
+
if datastore_id.empty?
|
3099
|
+
raise_command_error "missing required worker parameter"
|
3100
|
+
end
|
3101
|
+
|
3102
|
+
datastore = find_datastore_by_name_or_id(cluster['id'], datastore_id)
|
3103
|
+
if datastore.nil?
|
3104
|
+
print_red_alert "Datastore not found for '#{datastore_id}'"
|
3105
|
+
return 1
|
3106
|
+
end
|
3107
|
+
unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove the cluster datastore '#{datastore['name'] || datastore['id']}'?", options)
|
3108
|
+
return 9, "aborted command"
|
3109
|
+
end
|
3110
|
+
|
3111
|
+
@clusters_interface.setopts(options)
|
3112
|
+
if options[:dry_run]
|
3113
|
+
print_dry_run @clusters_interface.dry.destroy_datastore(cluster['id'], datastore['id'], params)
|
3114
|
+
return
|
3115
|
+
end
|
3116
|
+
json_response = @clusters_interface.destroy_datastore(cluster['id'], datastore['id'], params)
|
3117
|
+
render_response(json_response, options) do
|
3118
|
+
msg = "Datastore #{datastore['name']} is being removed from cluster #{cluster['name']}..."
|
3119
|
+
if json_response['msg']
|
3120
|
+
msg = json_response['msg']
|
3121
|
+
end
|
3122
|
+
print_green_success msg
|
3123
|
+
end
|
3124
|
+
return 0, nil
|
3125
|
+
end
|
3126
|
+
|
2911
3127
|
def update_datastore(args)
|
2912
3128
|
options = {}
|
2913
3129
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
@@ -3970,6 +4186,25 @@ class Morpheus::Cli::Clusters
|
|
3970
4186
|
json_results['datastores'].empty? ? nil : json_results['datastores'][0]
|
3971
4187
|
end
|
3972
4188
|
|
4189
|
+
def find_datastore_type_by_code_or_id(val)
|
4190
|
+
(val.to_s =~ /\A\d{1,}\Z/) ? find_datastore_type_by_id(val) : find_datastore_type_by_code(val)
|
4191
|
+
end
|
4192
|
+
|
4193
|
+
def find_datastore_type_by_id(id)
|
4194
|
+
get_datastore_types.find { |it| it['id'] == id }
|
4195
|
+
end
|
4196
|
+
|
4197
|
+
def find_datastore_type_by_code(code)
|
4198
|
+
get_datastore_types.find { |it| it['code'].downcase == code.downcase }
|
4199
|
+
end
|
4200
|
+
|
4201
|
+
def get_datastore_types(refresh=false)
|
4202
|
+
if !@datastore_types || refresh
|
4203
|
+
@datastore_types = @datastores_interface.types()['datastoreTypes']
|
4204
|
+
end
|
4205
|
+
@datastore_types
|
4206
|
+
end
|
4207
|
+
|
3973
4208
|
def find_job_by_name_or_id(cluster_id, val)
|
3974
4209
|
if val.to_s =~ /\A\d{1,}\Z/
|
3975
4210
|
params = {jobId: val.to_i}
|
@@ -4275,6 +4510,14 @@ class Morpheus::Cli::Clusters
|
|
4275
4510
|
end
|
4276
4511
|
end
|
4277
4512
|
|
4513
|
+
def add_datastore_option_types
|
4514
|
+
[
|
4515
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
4516
|
+
{'fieldName' => 'datastoreType', 'fieldLabel' => 'Type', 'type' => 'select', 'optionSource' => 'datastoreTypes', 'description' => 'Choose a datastore type.', 'required' => true, 'displayOrder' => 2},
|
4517
|
+
{'fieldName' => 'active', 'fieldLabel' => 'Active', 'type' => 'checkbox', 'required' => true, 'displayOrder' => 3, 'defaultValue' => true},
|
4518
|
+
]
|
4519
|
+
end
|
4520
|
+
|
4278
4521
|
def prompt_resource_pool(group, cloud, service_plan, provision_type, options)
|
4279
4522
|
resource_pool = nil
|
4280
4523
|
|
@@ -4451,4 +4694,135 @@ class Morpheus::Cli::Clusters
|
|
4451
4694
|
exit 1
|
4452
4695
|
end
|
4453
4696
|
end
|
4697
|
+
|
4698
|
+
def list_replicasets(args)
|
4699
|
+
_list_resources(args, 'replicaset')
|
4700
|
+
end
|
4701
|
+
|
4702
|
+
def get_replicaset(args)
|
4703
|
+
_get_resource(args, 'replicaset')
|
4704
|
+
end
|
4705
|
+
|
4706
|
+
def list_daemonsets(args)
|
4707
|
+
_list_resources(args, 'daemonset')
|
4708
|
+
end
|
4709
|
+
|
4710
|
+
def get_daemonset(args)
|
4711
|
+
_get_resource(args, 'daemonset')
|
4712
|
+
end
|
4713
|
+
|
4714
|
+
|
4715
|
+
def list_endpoints(args)
|
4716
|
+
_list_resources(args, 'endpoint')
|
4717
|
+
end
|
4718
|
+
|
4719
|
+
def get_endpoint(args)
|
4720
|
+
_get_resource(args, 'endpoint')
|
4721
|
+
end
|
4722
|
+
|
4723
|
+
def list_ingresses(args)
|
4724
|
+
_list_resources(args, 'ingresse')
|
4725
|
+
end
|
4726
|
+
|
4727
|
+
def get_ingress(args)
|
4728
|
+
_get_resource(args, 'ingresse', {'title' => 'ingress'})
|
4729
|
+
end
|
4730
|
+
|
4731
|
+
def list_policies(args)
|
4732
|
+
_list_resources(args, 'policie')
|
4733
|
+
end
|
4734
|
+
|
4735
|
+
def get_policy(args)
|
4736
|
+
_get_resource(args, 'policie', {'title' => 'policy'})
|
4737
|
+
end
|
4738
|
+
|
4739
|
+
def list_volume_claims(args)
|
4740
|
+
_list_resources(args, 'volumeclaim')
|
4741
|
+
end
|
4742
|
+
|
4743
|
+
def get_volume_claim(args)
|
4744
|
+
_get_resource(args, 'volumeclaim')
|
4745
|
+
end
|
4746
|
+
|
4747
|
+
def list_volumes(args)
|
4748
|
+
_list_resources(args, 'volume')
|
4749
|
+
end
|
4750
|
+
|
4751
|
+
def get_volume(args)
|
4752
|
+
_get_resource(args, 'volume')
|
4753
|
+
end
|
4754
|
+
|
4755
|
+
|
4756
|
+
def list_config_maps(args)
|
4757
|
+
_list_resources(args, 'configmap')
|
4758
|
+
end
|
4759
|
+
|
4760
|
+
def get_config_map(args)
|
4761
|
+
_get_resource(args, 'configmap')
|
4762
|
+
end
|
4763
|
+
|
4764
|
+
def list_secrets(args)
|
4765
|
+
_list_resources(args, 'secret')
|
4766
|
+
end
|
4767
|
+
|
4768
|
+
def get_secret(args)
|
4769
|
+
_get_resource(args, 'secret')
|
4770
|
+
end
|
4771
|
+
|
4772
|
+
def get_container(args)
|
4773
|
+
_get_resource(args, 'container')
|
4774
|
+
end
|
4775
|
+
|
4776
|
+
def get_stateful_set(args)
|
4777
|
+
_get_resource(args, 'statefulset')
|
4778
|
+
|
4779
|
+
end
|
4780
|
+
|
4781
|
+
def get_job(args)
|
4782
|
+
_get_resource(args, 'job')
|
4783
|
+
end
|
4784
|
+
|
4785
|
+
def get_service(args)
|
4786
|
+
_get_resource(args, 'service')
|
4787
|
+
end
|
4788
|
+
|
4789
|
+
private
|
4790
|
+
|
4791
|
+
def _get_resource(args, resource_type, options = {})
|
4792
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
4793
|
+
opts.banner = subcommand_usage("[cluster] [id]")
|
4794
|
+
opts.on("--resource-level LEVEL", String, "Resource Level") do |val|
|
4795
|
+
options[:resourceLevel] = val.to_s
|
4796
|
+
end
|
4797
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
4798
|
+
opts.footer = "get #{resource_type} for a cluster.\n" +
|
4799
|
+
"[cluster] and [#{resource_type}] is required. This is the name or id of an existing cluster, and the id of the #{resource_type}"
|
4800
|
+
end
|
4801
|
+
optparse.parse!(args)
|
4802
|
+
|
4803
|
+
if args.count != 2
|
4804
|
+
raise_command_error "wrong number of arguments, expected 2 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
4805
|
+
end
|
4806
|
+
|
4807
|
+
connect(options)
|
4808
|
+
_get_container_group(args, options, resource_type)
|
4809
|
+
end
|
4810
|
+
|
4811
|
+
def _list_resources(args, resource_type, options = {})
|
4812
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
4813
|
+
opts.banner = subcommand_usage( "[cluster]")
|
4814
|
+
opts.on("--resource-level LEVEL", String, "Resource Level") do |val|
|
4815
|
+
options[:resourceLevel] = val.to_s
|
4816
|
+
end
|
4817
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
4818
|
+
opts.footer = "List #{resource_type}s for a cluster.\n" +
|
4819
|
+
"[cluster] is required. This is the name or id of an existing cluster."
|
4820
|
+
end
|
4821
|
+
optparse.parse!(args)
|
4822
|
+
if args.count != 1
|
4823
|
+
raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
|
4824
|
+
end
|
4825
|
+
connect(options)
|
4826
|
+
_list_container_groups(args, options, resource_type)
|
4827
|
+
end
|
4454
4828
|
end
|
@@ -1009,6 +1009,9 @@ class Morpheus::Cli::Hosts
|
|
1009
1009
|
opts.on('--ssh-password VALUE', String, "SSH Password") do |val|
|
1010
1010
|
params['sshPassword'] = val == "null" ? nil : val
|
1011
1011
|
end
|
1012
|
+
opts.on('--ssh-key-pair ID', String, "SSH Key Pair ID") do |val|
|
1013
|
+
params['sshKeyPair'] = val == "null" ? nil : {"id" => val.to_i}
|
1014
|
+
end
|
1012
1015
|
opts.on('--power-schedule-type ID', String, "Power Schedule Type ID") do |val|
|
1013
1016
|
params['powerScheduleType'] = val == "null" ? nil : val
|
1014
1017
|
end
|
@@ -2746,6 +2746,9 @@ class Morpheus::Cli::Instances
|
|
2746
2746
|
options = {}
|
2747
2747
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
2748
2748
|
opts.banner = subcommand_usage("[instance]")
|
2749
|
+
opts.on('--include-network-interfaces','--include-network-interfaces', "Populate payload networkInterfaces with current interfaces") do
|
2750
|
+
options[:include_nics] = true
|
2751
|
+
end
|
2749
2752
|
build_standard_update_options(opts, options)
|
2750
2753
|
end
|
2751
2754
|
optparse.parse!(args)
|
@@ -2775,11 +2778,17 @@ class Morpheus::Cli::Instances
|
|
2775
2778
|
plan_id = instance['plan']['id']
|
2776
2779
|
resource_pool_id = instance['config']['resourcePoolId'] if instance['config']
|
2777
2780
|
current_plan_name = instance['plan']['name']
|
2778
|
-
current_interfaces = get_instance_interfaces(instance)
|
2779
|
-
if current_interfaces != false
|
2780
|
-
payload['networkInterfaces'] = current_interfaces
|
2781
|
-
end
|
2782
2781
|
|
2782
|
+
# JD: networkInterfaces should not be needed but pre 7.0.8/8.0.0 the API does expect it to be passed
|
2783
|
+
# However if the instance has more than one server this creates duplicate nics and breaks things
|
2784
|
+
# so only continue to do it if the instance has just one server and remote version is pre 7.0.8
|
2785
|
+
# should also only do this if remote version < 7.0.8
|
2786
|
+
if options[:include_nics] || (!remote_version_gte("7.0.8") && instance['servers'] && instance['servers'].size == 1)
|
2787
|
+
current_interfaces = get_instance_interfaces(instance)
|
2788
|
+
if current_interfaces != false
|
2789
|
+
payload['networkInterfaces'] = current_interfaces
|
2790
|
+
end
|
2791
|
+
end
|
2783
2792
|
|
2784
2793
|
# need to GET provision type for some settings...
|
2785
2794
|
provision_type = @provision_types_interface.get(instance['layout']['provisionTypeId'])['provisionType']
|
@@ -5576,6 +5585,8 @@ private
|
|
5576
5585
|
details['interfaces'].each do |inter|
|
5577
5586
|
interfaces.push(inter)
|
5578
5587
|
end
|
5588
|
+
# only include the first one or it will create duplicates
|
5589
|
+
break
|
5579
5590
|
end
|
5580
5591
|
return interfaces
|
5581
5592
|
rescue
|
@@ -5583,4 +5594,22 @@ private
|
|
5583
5594
|
end
|
5584
5595
|
end
|
5585
5596
|
|
5597
|
+
def remote_version_gte(required_version)
|
5598
|
+
version = @remote_appliance[:build_version]
|
5599
|
+
return false if version.nil?
|
5600
|
+
version_numbers = version.split(".")
|
5601
|
+
required_version_numbers = required_version.split(".")
|
5602
|
+
result = true
|
5603
|
+
required_version_numbers.each_with_index do |v, i|
|
5604
|
+
if version_numbers[i].to_i > v.to_i
|
5605
|
+
break
|
5606
|
+
elsif version_numbers[i].to_i < v.to_i
|
5607
|
+
result = false
|
5608
|
+
break
|
5609
|
+
else
|
5610
|
+
# keep going
|
5611
|
+
end
|
5612
|
+
end
|
5613
|
+
return result
|
5614
|
+
end
|
5586
5615
|
end
|
@@ -163,6 +163,9 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
163
163
|
"Virtual Image" => lambda {|it|
|
164
164
|
it['virtualImage'] ? it['virtualImage']['name'] : ''
|
165
165
|
},
|
166
|
+
"OsType" => lambda {|it|
|
167
|
+
it['osType'] ? it['osType']['name'] : ''
|
168
|
+
},
|
166
169
|
# "Category" => lambda {|it| it['category'].to_s.capitalize },
|
167
170
|
# # "Logo" => lambda {|it| it['logo'].to_s },
|
168
171
|
# "Visiblity" => lambda {|it| it['visibility'].to_s.capitalize },
|
@@ -474,6 +477,9 @@ class Morpheus::Cli::LibraryContainerTypesCommand
|
|
474
477
|
opts.on('--version VALUE', String, "Version") do |val|
|
475
478
|
params['containerVersion'] = val
|
476
479
|
end
|
480
|
+
opts.on('--osType VALUE', Integer, "OsType") do |val|
|
481
|
+
params['osTypeId'] = val
|
482
|
+
end
|
477
483
|
# opts.on('--technology CODE', String, "Technology") do |val|
|
478
484
|
# params['provisionTypeCode'] = val
|
479
485
|
# end
|