morpheus-cli 5.5.2.2 → 5.5.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/Dockerfile +1 -1
  4. data/README.md +57 -4
  5. data/Rakefile +9 -0
  6. data/bin/morpheus +4 -4
  7. data/lib/morpheus/api/api_client.rb +20 -2
  8. data/lib/morpheus/api/appliance_settings_interface.rb +15 -0
  9. data/lib/morpheus/api/archive_buckets_interface.rb +1 -1
  10. data/lib/morpheus/api/archive_files_interface.rb +3 -3
  11. data/lib/morpheus/api/clients_interface.rb +2 -2
  12. data/lib/morpheus/api/clusters_interface.rb +8 -1
  13. data/lib/morpheus/api/containers_interface.rb +29 -16
  14. data/lib/morpheus/api/custom_instance_types_interface.rb +0 -2
  15. data/lib/morpheus/api/cypher_interface.rb +1 -2
  16. data/lib/morpheus/api/doc_interface.rb +8 -6
  17. data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
  18. data/lib/morpheus/api/guidance_settings_interface.rb +17 -0
  19. data/lib/morpheus/api/health_interface.rb +1 -1
  20. data/lib/morpheus/api/image_builder_interface.rb +3 -3
  21. data/lib/morpheus/api/instances_interface.rb +25 -0
  22. data/lib/morpheus/api/logs_interface.rb +2 -4
  23. data/lib/morpheus/api/monitoring_interface.rb +6 -6
  24. data/lib/morpheus/api/monitoring_settings_interface.rb +25 -0
  25. data/lib/morpheus/api/network_server_groups_interface.rb +7 -0
  26. data/lib/morpheus/api/packages_interface.rb +1 -1
  27. data/lib/morpheus/api/reports_interface.rb +1 -1
  28. data/lib/morpheus/api/servers_interface.rb +9 -1
  29. data/lib/morpheus/api/storage_providers_interface.rb +2 -2
  30. data/lib/morpheus/api/virtual_images_interface.rb +1 -1
  31. data/lib/morpheus/api.rb +2 -0
  32. data/lib/morpheus/benchmarking.rb +1 -1
  33. data/lib/morpheus/cli/cli_command.rb +79 -37
  34. data/lib/morpheus/cli/cli_registry.rb +19 -10
  35. data/lib/morpheus/cli/commands/access_token_command.rb +1 -1
  36. data/lib/morpheus/cli/commands/appliance_settings_command.rb +57 -2
  37. data/lib/morpheus/cli/commands/apps.rb +1 -1
  38. data/lib/morpheus/cli/commands/archives_command.rb +25 -33
  39. data/lib/morpheus/cli/commands/backup_settings_command.rb +1 -1
  40. data/lib/morpheus/cli/commands/blueprints_command.rb +10 -21
  41. data/lib/morpheus/cli/commands/boot_scripts_command.rb +2 -2
  42. data/lib/morpheus/cli/commands/cat_command.rb +1 -1
  43. data/lib/morpheus/cli/commands/catalog_item_types_command.rb +18 -13
  44. data/lib/morpheus/cli/commands/clouds.rb +3 -3
  45. data/lib/morpheus/cli/commands/clusters.rb +154 -3
  46. data/lib/morpheus/cli/commands/containers_command.rb +398 -253
  47. data/lib/morpheus/cli/commands/cypher_command.rb +3 -0
  48. data/lib/morpheus/cli/commands/deployments.rb +1 -1
  49. data/lib/morpheus/cli/commands/deploys.rb +9 -9
  50. data/lib/morpheus/cli/commands/doc.rb +15 -16
  51. data/lib/morpheus/cli/commands/execution_request_command.rb +2 -2
  52. data/lib/morpheus/cli/commands/file_copy_request_command.rb +5 -5
  53. data/lib/morpheus/cli/commands/groups.rb +2 -2
  54. data/lib/morpheus/cli/commands/guidance_command.rb +2 -2
  55. data/lib/morpheus/cli/commands/guidance_settings.rb +148 -0
  56. data/lib/morpheus/cli/commands/health_command.rb +4 -4
  57. data/lib/morpheus/cli/commands/hosts.rb +43 -5
  58. data/lib/morpheus/cli/commands/image_builder_command.rb +1 -1
  59. data/lib/morpheus/cli/commands/instances.rb +419 -148
  60. data/lib/morpheus/cli/commands/integrations_command.rb +22 -20
  61. data/lib/morpheus/cli/commands/key_pairs.rb +2 -2
  62. data/lib/morpheus/cli/commands/library_container_scripts_command.rb +2 -2
  63. data/lib/morpheus/cli/commands/library_container_templates_command.rb +2 -2
  64. data/lib/morpheus/cli/commands/library_instance_types_command.rb +3 -3
  65. data/lib/morpheus/cli/commands/library_spec_templates_command.rb +2 -2
  66. data/lib/morpheus/cli/commands/log_settings_command.rb +1 -1
  67. data/lib/morpheus/cli/commands/login.rb +1 -1
  68. data/lib/morpheus/cli/commands/man_command.rb +32 -18
  69. data/lib/morpheus/cli/commands/monitoring_settings.rb +228 -0
  70. data/lib/morpheus/cli/commands/network_server_groups_command.rb +222 -0
  71. data/lib/morpheus/cli/commands/packages_command.rb +11 -11
  72. data/lib/morpheus/cli/commands/plugins.rb +1 -1
  73. data/lib/morpheus/cli/commands/policies_command.rb +4 -4
  74. data/lib/morpheus/cli/commands/preseed_scripts_command.rb +2 -2
  75. data/lib/morpheus/cli/commands/provisioning_settings_command.rb +1 -1
  76. data/lib/morpheus/cli/commands/remote.rb +1 -1
  77. data/lib/morpheus/cli/commands/reports_command.rb +13 -3
  78. data/lib/morpheus/cli/commands/security_groups.rb +1 -1
  79. data/lib/morpheus/cli/commands/shell.rb +40 -62
  80. data/lib/morpheus/cli/commands/snapshots.rb +3 -5
  81. data/lib/morpheus/cli/commands/source_command.rb +8 -16
  82. data/lib/morpheus/cli/commands/storage_providers_command.rb +7 -7
  83. data/lib/morpheus/cli/commands/tasks.rb +2 -2
  84. data/lib/morpheus/cli/commands/vdi_pools_command.rb +6 -6
  85. data/lib/morpheus/cli/commands/view.rb +5 -1
  86. data/lib/morpheus/cli/commands/whitelabel_settings_command.rb +5 -5
  87. data/lib/morpheus/cli/commands/whoami.rb +2 -2
  88. data/lib/morpheus/cli/credentials.rb +30 -8
  89. data/lib/morpheus/cli/dot_file.rb +8 -15
  90. data/lib/morpheus/cli/error_handler.rb +16 -0
  91. data/lib/morpheus/cli/errors.rb +8 -1
  92. data/lib/morpheus/cli/mixins/print_helper.rb +17 -13
  93. data/lib/morpheus/cli/mixins/provisioning_helper.rb +14 -12
  94. data/lib/morpheus/cli/mixins/rest_command.rb +23 -19
  95. data/lib/morpheus/cli/mixins/secondary_rest_command.rb +47 -24
  96. data/lib/morpheus/cli/option_parser.rb +5 -1
  97. data/lib/morpheus/cli/option_types.rb +59 -12
  98. data/lib/morpheus/cli/version.rb +1 -1
  99. data/lib/morpheus/cli.rb +26 -16
  100. data/lib/morpheus/ext/rest_client.rb +3 -2
  101. data/lib/morpheus/ext/string.rb +6 -4
  102. data/lib/morpheus/formatters.rb +1 -1
  103. data/lib/morpheus/logging.rb +4 -4
  104. data/lib/morpheus/morpkg.rb +4 -4
  105. data/lib/morpheus/rest_client.rb +2 -2
  106. data/lib/morpheus/routes.rb +41 -9
  107. data/lib/morpheus/terminal.rb +65 -16
  108. data/lib/morpheus.rb +1 -1
  109. data/morpheus-cli.gemspec +1 -0
  110. data/test/api/containers_interface_test.rb +68 -0
  111. data/test/api/doc_interface_test.rb +35 -0
  112. data/test/api/instances_interface_test.rb +22 -0
  113. data/test/api/whoami_interface_test.rb +14 -0
  114. data/test/cli/access_token_test.rb +36 -0
  115. data/test/cli/auth_test.rb +82 -0
  116. data/test/cli/cli_test.rb +48 -0
  117. data/test/cli/containers_test.rb +92 -0
  118. data/test/cli/doc_test.rb +35 -0
  119. data/test/cli/help_test.rb +25 -0
  120. data/test/cli/instances_test.rb +36 -0
  121. data/test/cli/man_test.rb +14 -0
  122. data/test/cli/remote_test.rb +89 -0
  123. data/test/cli/roles_test.rb +34 -0
  124. data/test/cli/shell_test.rb +81 -0
  125. data/test/cli/version_test.rb +23 -0
  126. data/test/cli/view_test.rb +55 -0
  127. data/test/cli/whoami_test.rb +17 -0
  128. data/test/morpheus_test.rb +16 -0
  129. data/test/test_case.rb +338 -0
  130. data/test/test_config.rb +137 -0
  131. data/test/test_data_helper.rb +97 -0
  132. metadata +67 -3
@@ -23,6 +23,7 @@ class Morpheus::Cli::Clusters
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
+ register_subcommands :apply_template
26
27
 
27
28
  def connect(opts)
28
29
  @api_client = establish_remote_appliance_connection(opts)
@@ -42,6 +43,7 @@ class Morpheus::Cli::Clusters
42
43
  @user_groups_interface = @api_client.user_groups
43
44
  @accounts_interface = @api_client.accounts
44
45
  @logs_interface = @api_client.logs
46
+ @execution_request_interface = @api_client.execution_request
45
47
  #@active_security_group = ::Morpheus::Cli::SecurityGroups.load_security_group_file
46
48
  end
47
49
 
@@ -3242,7 +3244,7 @@ class Morpheus::Cli::Clusters
3242
3244
  build_option_type_options(opts, options, update_wiki_page_option_types)
3243
3245
  opts.on('--file FILE', "File containing the wiki content. This can be used instead of --content") do |filename|
3244
3246
  full_filename = File.expand_path(filename)
3245
- if File.exists?(full_filename)
3247
+ if File.exist?(full_filename)
3246
3248
  params['content'] = File.read(full_filename)
3247
3249
  else
3248
3250
  print_red_alert "File not found: #{full_filename}"
@@ -3562,6 +3564,125 @@ class Morpheus::Cli::Clusters
3562
3564
  end
3563
3565
  end
3564
3566
 
3567
+ def apply_template(args)
3568
+ options = {}
3569
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
3570
+ opts.banner = subcommand_usage( "[cluster] --specTemplate --serviceUrl")
3571
+ opts.on("--specTemplate [TEXT]", String, "Name or ID of desired Spec Template to apply to cluster") do |val|
3572
+ options[:specTemplate] = val.to_s
3573
+ end
3574
+ opts.on("--serviceUrl [TEXT]", String, "Url of template to apply to Cluster") do |val|
3575
+ options[:serviceUrl] = val.to_s
3576
+ end
3577
+ opts.on("--specYaml [TEXT]", String, "Yaml to apply to Cluster") do |val|
3578
+ options[:specYaml] = val.to_s
3579
+ end
3580
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
3581
+ opts.footer = "Apply a Template to a Cluster.\n" +
3582
+ "[cluster] is required. This is the name or id of an existing cluster."
3583
+ end
3584
+
3585
+ optparse.parse!(args)
3586
+ if args.count != 1
3587
+ raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args}\n#{optparse}"
3588
+ end
3589
+ connect(options)
3590
+
3591
+ begin
3592
+ payload = nil
3593
+ cluster = nil
3594
+
3595
+ if options[:payload]
3596
+ payload = options[:payload]
3597
+ # support -O OPTION switch on top of --payload
3598
+ if options[:options]
3599
+ payload['cluster'] ||= {}
3600
+ payload['cluster'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
3601
+ end
3602
+
3603
+ if !payload['cluster'].empty?
3604
+ cluster = find_cluster_by_name_or_id(payload['cluster']['id'] || payload['cluster']['name'])
3605
+ end
3606
+ else
3607
+ cluster = find_cluster_by_name_or_id(args[0])
3608
+ cluster_payload = {}
3609
+ cluster_payload['specTemplate'] = options[:specTemplate] if !options[:specTemplate].empty?
3610
+ cluster_payload['serviceUrl'] = options[:serviceUrl] if !options[:serviceUrl].empty?
3611
+ cluster_payload['specYaml'] = options[:specYaml] if !options[:specYaml].empty?
3612
+ payload = cluster_payload
3613
+ end
3614
+
3615
+ if !cluster
3616
+ print_red_alert "No clusters available for update"
3617
+ exit 1
3618
+ end
3619
+
3620
+ if cluster_payload.empty?
3621
+ type = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'select', 'fieldLabel' => "Type", 'selectOptions' => apply_temp_options, 'required' => true, 'description' => 'Choose type of template being used.'}])['type']
3622
+ if type == 'specTemplate'
3623
+ cluster_payload['specTemplate'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'specTemplate', 'type' => 'select', 'fieldLabel' => "Spec Template", 'selectOptions' => available_kube_templates, 'required' => true, 'description' => 'Choose a template.'}], options[:options])['specTemplate']
3624
+ elsif type == 'yaml'
3625
+ file_params = Morpheus::Cli::OptionTypes.file_content_prompt({'fieldName' => 'source', 'fieldLabel' => 'File Content', 'type' => 'file-content', 'required' => true}, {'source' => {'source' => 'local'}}, nil, {})
3626
+ cluster_payload['specYaml'] = file_params['content']
3627
+ else
3628
+ cluster_payload['specUrl'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'specUrl', 'type' => 'text', 'fieldLabel' => 'Spec Url', 'required' => true, 'description' => 'Url of template.'}])['specUrl']
3629
+ end
3630
+ end
3631
+
3632
+ if options[:dry_run]
3633
+ print_dry_run @clusters_interface.dry.apply_template(cluster['id'], cluster_payload)
3634
+ return
3635
+ end
3636
+
3637
+ json_response = @clusters_interface.apply_template(cluster['id'], cluster_payload)
3638
+ if options[:json]
3639
+ print JSON.pretty_generate(json_response)
3640
+ print "\n"
3641
+ elsif json_response['msg'] != nil
3642
+ print_red_alert "There was an error #{json_response['msg']}"
3643
+ else
3644
+ print_green_success 'Template applied to Cluster. Check Execution Request for results'
3645
+ json_response = @execution_request_interface.get(json_response['executionId'], {})
3646
+
3647
+ if json_response['executionRequest'] && json_response['executionRequest']['errorMessage']
3648
+ print_red_alert "There was an error: #{json_response['executionRequest']['errorMessage']}"
3649
+ print_red_alert "execution request id: #{json_response['executionRequest']['uniqueId']}"
3650
+ else
3651
+ execution_request = json_response['executionRequest']
3652
+ print_h1 "Execution Request Details"
3653
+ print cyan
3654
+ description_cols = {
3655
+ #"ID" => lambda {|it| it['id'] },
3656
+ "Unique ID" => lambda {|it| it['uniqueId'] },
3657
+ "Server ID" => lambda {|it| it['serverId'] },
3658
+ "Instance ID" => lambda {|it| it['instanceId'] },
3659
+ "Container ID" => lambda {|it| it['containerId'] },
3660
+ "Expires At" => lambda {|it| format_local_dt it['expiresAt'] },
3661
+ "Exit Code" => lambda {|it| it['exitCode'] },
3662
+ "Status" => lambda {|it| format_execution_request_status(it) },
3663
+ #"Created By" => lambda {|it| it['createdById'] },
3664
+ #"Subdomain" => lambda {|it| it['subdomain'] },
3665
+ }
3666
+ description_cols.delete("Server ID") if execution_request['serverId'].nil?
3667
+ description_cols.delete("Instance ID") if execution_request['instanceId'].nil?
3668
+ description_cols.delete("Container ID") if execution_request['containerId'].nil?
3669
+ description_cols.delete("Exit Code") if execution_request['exitCode'].nil?
3670
+ print_description_list(description_cols, execution_request)
3671
+
3672
+ if execution_request['stdErr'].to_s.strip != '' && execution_request['stdErr'] != "stdin: is not a tty\n"
3673
+ print_h2 "Error"
3674
+ puts execution_request['stdErr'].to_s.strip
3675
+ end
3676
+ if execution_request['stdOut']
3677
+ print_h2 "Output"
3678
+ puts execution_request['stdOut'].to_s.strip
3679
+ end
3680
+ print reset, "\n"
3681
+ end
3682
+ end
3683
+ end
3684
+ end
3685
+
3565
3686
  def history_event_details(args)
3566
3687
  options = {}
3567
3688
  process_event_id = nil
@@ -4057,7 +4178,7 @@ class Morpheus::Cli::Clusters
4057
4178
  end
4058
4179
  opts.on('--volumes-file FILE', String, "Volumes Config from a local JSON or YAML file") do |val|
4059
4180
  config_file = File.expand_path(val)
4060
- if !File.exists?(config_file) || !File.file?(config_file)
4181
+ if !File.exist?(config_file) || !File.file?(config_file)
4061
4182
  print_red_alert "Specified volumes file not found: #{config_file}"
4062
4183
  exit 1
4063
4184
  end
@@ -4093,7 +4214,7 @@ class Morpheus::Cli::Clusters
4093
4214
  end
4094
4215
  opts.on('--network-interfaces-file FILE', String, "Network Interfaces Config from a local JSON or YAML file") do |val|
4095
4216
  config_file = File.expand_path(val)
4096
- if !File.exists?(config_file) || !File.file?(config_file)
4217
+ if !File.exist?(config_file) || !File.file?(config_file)
4097
4218
  print_red_alert "Specified network interfaces file not found: #{config_file}"
4098
4219
  exit 1
4099
4220
  end
@@ -4235,4 +4356,34 @@ class Morpheus::Cli::Clusters
4235
4356
  it
4236
4357
  end
4237
4358
  end
4359
+
4360
+ def available_kube_templates
4361
+ option_results = options_interface.options_for_source('availableKubeTemplates')
4362
+ available_templates = option_results['data'].collect {|it|
4363
+ {"id" => it["value"], "name" => it["name"], "value" => it["value"]}
4364
+ }
4365
+
4366
+ return available_templates
4367
+ end
4368
+
4369
+ def apply_temp_options
4370
+ [
4371
+ {"id" => "specYaml", "name" => "YAML", "value" => "yaml"},
4372
+ {"id" => 'specTemplate', "name" => "Spec Template", "value" => 'specTemplate'},
4373
+ {"id" => 'url', "name" => 'Url of Template', "value" => 'url'}
4374
+ ]
4375
+ end
4376
+
4377
+ def format_execution_request_status(execution_request, return_color=cyan)
4378
+ out = ""
4379
+ status_str = execution_request['status']
4380
+ if status_str == 'complete'
4381
+ out << "#{green}#{status_str.upcase}#{return_color}"
4382
+ elsif status_str == 'failed' || status_str == 'expired'
4383
+ out << "#{red}#{status_str.upcase}#{return_color}"
4384
+ else
4385
+ out << "#{cyan}#{status_str.upcase}#{return_color}"
4386
+ end
4387
+ out
4388
+ end
4238
4389
  end