morpheus-cli 4.2.16 → 4.2.21

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +8 -6
  4. data/lib/morpheus/api/api_client.rb +32 -14
  5. data/lib/morpheus/api/auth_interface.rb +4 -2
  6. data/lib/morpheus/api/backup_jobs_interface.rb +9 -0
  7. data/lib/morpheus/api/backups_interface.rb +16 -0
  8. data/lib/morpheus/api/deploy_interface.rb +25 -56
  9. data/lib/morpheus/api/deployments_interface.rb +44 -55
  10. data/lib/morpheus/api/doc_interface.rb +57 -0
  11. data/lib/morpheus/api/instances_interface.rb +5 -0
  12. data/lib/morpheus/api/rest_interface.rb +40 -0
  13. data/lib/morpheus/api/user_sources_interface.rb +0 -15
  14. data/lib/morpheus/api/users_interface.rb +2 -3
  15. data/lib/morpheus/benchmarking.rb +2 -2
  16. data/lib/morpheus/cli.rb +4 -1
  17. data/lib/morpheus/cli/access_token_command.rb +27 -10
  18. data/lib/morpheus/cli/apps.rb +21 -15
  19. data/lib/morpheus/cli/backup_jobs_command.rb +276 -0
  20. data/lib/morpheus/cli/backups_command.rb +271 -0
  21. data/lib/morpheus/cli/blueprints_command.rb +27 -61
  22. data/lib/morpheus/cli/boot_scripts_command.rb +1 -1
  23. data/lib/morpheus/cli/budgets_command.rb +4 -4
  24. data/lib/morpheus/cli/cli_command.rb +99 -41
  25. data/lib/morpheus/cli/cloud_resource_pools_command.rb +16 -0
  26. data/lib/morpheus/cli/clouds.rb +7 -10
  27. data/lib/morpheus/cli/clusters.rb +0 -18
  28. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +7 -7
  29. data/lib/morpheus/cli/commands/standard/man_command.rb +1 -1
  30. data/lib/morpheus/cli/credentials.rb +13 -9
  31. data/lib/morpheus/cli/deploy.rb +374 -0
  32. data/lib/morpheus/cli/deployments.rb +521 -197
  33. data/lib/morpheus/cli/deploys.rb +271 -126
  34. data/lib/morpheus/cli/doc.rb +182 -0
  35. data/lib/morpheus/cli/error_handler.rb +23 -8
  36. data/lib/morpheus/cli/errors.rb +3 -2
  37. data/lib/morpheus/cli/image_builder_command.rb +2 -2
  38. data/lib/morpheus/cli/instances.rb +136 -17
  39. data/lib/morpheus/cli/invoices_command.rb +59 -47
  40. data/lib/morpheus/cli/jobs_command.rb +2 -2
  41. data/lib/morpheus/cli/library_instance_types_command.rb +17 -3
  42. data/lib/morpheus/cli/library_layouts_command.rb +1 -1
  43. data/lib/morpheus/cli/login.rb +9 -3
  44. data/lib/morpheus/cli/mixins/accounts_helper.rb +158 -100
  45. data/lib/morpheus/cli/mixins/backups_helper.rb +115 -0
  46. data/lib/morpheus/cli/mixins/deployments_helper.rb +135 -0
  47. data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
  48. data/lib/morpheus/cli/mixins/print_helper.rb +110 -74
  49. data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -2
  50. data/lib/morpheus/cli/mixins/whoami_helper.rb +19 -6
  51. data/lib/morpheus/cli/network_routers_command.rb +1 -1
  52. data/lib/morpheus/cli/option_parser.rb +48 -5
  53. data/lib/morpheus/cli/option_types.rb +1 -1
  54. data/lib/morpheus/cli/projects_command.rb +7 -7
  55. data/lib/morpheus/cli/provisioning_licenses_command.rb +2 -2
  56. data/lib/morpheus/cli/remote.rb +3 -2
  57. data/lib/morpheus/cli/roles.rb +49 -92
  58. data/lib/morpheus/cli/security_groups.rb +7 -1
  59. data/lib/morpheus/cli/service_plans_command.rb +10 -10
  60. data/lib/morpheus/cli/setup.rb +1 -1
  61. data/lib/morpheus/cli/shell.rb +7 -6
  62. data/lib/morpheus/cli/subnets_command.rb +1 -1
  63. data/lib/morpheus/cli/tasks.rb +24 -10
  64. data/lib/morpheus/cli/tenants_command.rb +133 -163
  65. data/lib/morpheus/cli/user_groups_command.rb +20 -65
  66. data/lib/morpheus/cli/user_settings_command.rb +115 -13
  67. data/lib/morpheus/cli/user_sources_command.rb +57 -24
  68. data/lib/morpheus/cli/users.rb +210 -186
  69. data/lib/morpheus/cli/version.rb +1 -1
  70. data/lib/morpheus/cli/whitelabel_settings_command.rb +29 -5
  71. data/lib/morpheus/cli/whoami.rb +113 -6
  72. data/lib/morpheus/cli/workflows.rb +11 -8
  73. data/lib/morpheus/ext/hash.rb +21 -0
  74. data/lib/morpheus/terminal.rb +1 -0
  75. metadata +12 -3
  76. data/lib/morpheus/cli/auth_command.rb +0 -105
@@ -1,176 +1,321 @@
1
- # require 'yaml'
2
- require 'io/console'
3
- require 'rest_client'
4
- require 'filesize'
5
1
  require 'morpheus/cli/cli_command'
2
+ require 'yaml'
6
3
 
7
4
  class Morpheus::Cli::Deploys
8
5
  include Morpheus::Cli::CliCommand
6
+ include Morpheus::Cli::DeploymentsHelper
9
7
 
10
- set_command_name :deploy
8
+ # hidden until api support is added
9
+ set_command_hidden
10
+
11
+ set_command_name :deploys
11
12
 
12
- def initialize()
13
- # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
14
- end
13
+ register_subcommands :list, :get, :add, :remove, :deploy
15
14
 
16
15
  def connect(opts)
17
16
  @api_client = establish_remote_appliance_connection(opts)
18
- @instances_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).instances
19
- @deploy_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).deploy
17
+ @instances_interface = @api_client.instances
18
+ @deploy_interface = @api_client.deploy
19
+ @deployments_interface = @api_client.deployments
20
20
  end
21
21
 
22
22
  def handle(args)
23
- deploy(args)
23
+ handle_subcommand(args)
24
24
  end
25
25
 
26
- def deploy(args)
27
- options={}
28
- optparse = Morpheus::Cli::OptionParser.new do|opts|
29
- opts.banner = "Usage: morpheus deploy [environment]"
30
- build_common_options(opts, options, [:remote, :dry_run])
31
- opts.footer = "Deploy to an environment using the morpheus.yml file, located in the working directory."
32
- # "todo: document me better!"
26
+ def list(args)
27
+ options = {}
28
+ params = {}
29
+ ref_ids = []
30
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
31
+ opts.banner = subcommand_usage("[search]")
32
+ build_standard_list_options(opts, options)
33
+ opts.footer = <<-EOT
34
+ List deploys.
35
+ EOT
33
36
  end
34
37
  optparse.parse!(args)
35
38
  connect(options)
36
- environment = 'production' # yikes!
39
+ # verify_args!(args:args, optparse:optparse, count:0)
37
40
  if args.count > 0
38
- environment = args[0]
41
+ options[:phrase] = args.join(" ")
39
42
  end
40
- if load_deploy_file().nil?
41
- puts "Morpheus Deploy File `morpheus.yml` not detected. Please create one and try again."
43
+ params.merge!(parse_list_options(options))
44
+ @deploy_interface.setopts(options)
45
+ if options[:dry_run]
46
+ print_dry_run @deploy_interface.dry.list(params)
42
47
  return
43
48
  end
49
+ json_response = @deploy_interface.list(params)
50
+ app_deploys = json_response[app_deploy_list_key]
51
+ render_response(json_response, options, app_deploy_list_key) do
52
+ print_h1 "Morpheus Deploys", parse_list_subtitles(options), options
53
+ if app_deploys.empty?
54
+ print cyan,"No deploys found.",reset,"\n"
55
+ else
56
+ print as_pretty_table(app_deploys, app_deploy_column_definitions.upcase_keys!, options)
57
+ print_results_pagination(json_response)
58
+ end
59
+ print reset,"\n"
60
+ end
61
+ if app_deploys.empty?
62
+ return 1, "no deploys found"
63
+ else
64
+ return 0, nil
65
+ end
66
+ end
44
67
 
45
- deploy_args = merged_deploy_args(environment)
46
- if deploy_args['name'].nil?
47
- puts "Instance not specified. Please specify the instance name and try again."
48
- return
68
+ def get(args)
69
+ params = {}
70
+ options = {}
71
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
72
+ opts.banner = subcommand_usage("[id]")
73
+ build_standard_get_options(opts, options)
74
+ opts.footer = <<-EOT
75
+ Get details about a specific instance deploy.
76
+ [id] is required. This is the name or id of a deployment.
77
+ EOT
49
78
  end
79
+ optparse.parse!(args)
80
+ verify_args!(args:args, optparse:optparse, min:1)
81
+ connect(options)
82
+ id_list = parse_id_list(args)
83
+ return run_command_for_each_arg(id_list) do |arg|
84
+ _get(arg, params, options)
85
+ end
86
+ end
50
87
 
51
- instance_results = @instances_interface.get(name: deploy_args['name'])
52
- if instance_results['instances'].empty?
53
- puts "Instance not found by name #{args[0]}"
54
- return
88
+ def _get(id, params, options)
89
+ @deploy_interface.setopts(options)
90
+ if options[:dry_run]
91
+ print_dry_run @deploy_interface.dry.get(id, params)
92
+ return 0
93
+ end
94
+ json_response = @deploy_interface.get(id, params)
95
+ app_deploy = json_response[app_deploy_object_key]
96
+ render_response(json_response, options, app_deploy_object_key) do
97
+ print_h1 "Deploy Details", [], options
98
+ print cyan
99
+ print_description_list(app_deploy_column_definitions, app_deploy)
100
+ print reset,"\n"
55
101
  end
56
- instance = instance_results['instances'][0]
57
- instance_id = instance['id']
58
- print_h1 "Morpheus Deployment"
59
- if !deploy_args['script'].nil?
60
- print cyan, bold, " - Executing Pre Deploy Script...", reset, "\n"
102
+ return 0, nil
103
+ end
61
104
 
62
- if !system(deploy_args['script'])
63
- puts "Error executing pre script..."
64
- return
65
- end
105
+ def add(args)
106
+ options = {}
107
+ params = {}
108
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
109
+ opts.banner = subcommand_usage("[instance] [deployment] [version] [options]")
110
+ build_option_type_options(opts, options, add_app_deploy_option_types)
111
+ build_option_type_options(opts, options, add_app_deploy_advanced_option_types)
112
+ build_standard_add_options(opts, options)
113
+ opts.footer = <<-EOT
114
+ Create a new instance deploy.
115
+ EOT
116
+ end
117
+ optparse.parse!(args)
118
+ verify_args!(args:args, optparse:optparse, min:0, max:3)
119
+ options[:options]['instance'] = args[0] if args[0]
120
+ options[:options]['deployment'] = args[1] if args[1]
121
+ options[:options]['version'] = args[2] if args[2]
122
+ connect(options)
123
+ payload = {}
124
+ if options[:payload]
125
+ payload = options[:payload]
126
+ payload.deep_merge!({app_deploy_object_key => parse_passed_options(options)})
127
+ else
128
+ payload.deep_merge!({app_deploy_object_key => parse_passed_options(options)})
129
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(add_app_deploy_option_types, options[:options], @api_client, options[:params])
130
+ params.deep_merge!(v_prompt)
131
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_app_deploy_advanced_option_types, options[:options], @api_client, options[:params])
132
+ advanced_config.deep_compact!
133
+ params.deep_merge!(advanced_config)
134
+ payload[app_deploy_object_key].deep_merge!(params)
66
135
  end
67
136
  @deploy_interface.setopts(options)
68
- @instances_interface.setopts(options)
69
137
  if options[:dry_run]
70
- print_dry_run @deploy_interface.create(instance_id)
71
- end
72
- # Create a new deployment record
73
- deploy_result = @deploy_interface.create(instance_id)
74
- app_deploy = deploy_result['appDeploy']
75
- deployment_id = app_deploy['id']
76
-
77
- # Upload Files
78
- print "\n",cyan, bold, "Uploading Files...", reset, "\n"
79
- current_working_dir = Dir.pwd
80
- deploy_args['files'].each do |fmap|
81
- Dir.chdir(fmap['path'] || current_working_dir)
82
- files = Dir.glob(fmap['pattern'] || '**/*')
83
- files.each do |file|
84
- if File.file?(file)
85
- print cyan,bold, " - Uploading #{file} ...", reset, "\n"
86
- destination = file.split("/")[0..-2].join("/")
87
- if options[:dry_run]
88
- print_dry_run @deploy_interface.upload_file(deployment_id,file,destination)
89
- else
90
- upload_result = @deploy_interface.upload_file(deployment_id,file,destination)
91
- end
92
- end
93
- end
138
+ print_dry_run @deploy_interface.dry.create(payload)
139
+ return 0, nil
94
140
  end
95
- print cyan, bold, "Upload Complete!", reset, "\n"
96
- Dir.chdir(current_working_dir)
141
+ json_response = @deploy_interface.create(payload)
142
+ app_deploy = json_response[app_deploy_object_key]
143
+ render_response(json_response, options, app_deploy_object_key) do
144
+ print_green_success "Deploying..."
145
+ return _get(app_deploy["id"], {}, options)
146
+ end
147
+ return 0, nil
148
+ end
97
149
 
98
- if !deploy_args['post_script'].nil?
99
- print cyan, bold, "Executing Post Script...", reset, "\n"
100
- if !system(deploy_args['post_script'])
101
- puts "Error executing post script..."
102
- return
103
- end
150
+ def remove(args)
151
+ options = {}
152
+ params = {}
153
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
154
+ opts.banner = subcommand_usage("[id] [options]")
155
+ build_standard_remove_options(opts, options)
156
+ opts.footer = <<-EOT
157
+ Delete an instance deploy.
158
+ [id] is required. This is the name or id of a deploy.
159
+ EOT
160
+ end
161
+ optparse.parse!(args)
162
+ verify_args!(args:args, optparse:optparse, count:1)
163
+ connect(options)
164
+ app_deploy = find_app_deploy_by_id(args[0])
165
+ return 1 if app_deploy.nil?
166
+ @deploy_interface.setopts(options)
167
+ if options[:dry_run]
168
+ print_dry_run @deploy_interface.dry.destroy(app_deploy['id'], params)
169
+ return
170
+ end
171
+ json_response = @deploy_interface.destroy(app_deploy['id'], params)
172
+ render_response(json_response, options) do
173
+ print_green_success "Removed deploy #{app_deploy['name']}"
104
174
  end
175
+ return 0, nil
176
+ end
105
177
 
106
- deploy_payload = {}
107
- if deploy_args['env']
108
- evars = []
109
- deploy_args['env'].each_pair do |key, value|
110
- evars << {name: key, value: value, export: false}
111
- end
112
- payload = {envs: evars}
113
- if options[:dry_run]
114
- print_dry_run @instances_interface.create_env(instance_id, payload)
115
- print_dry_run @instances_interface.restart(instance_id)
116
- else
117
- @instances_interface.create_env(instance_id, payload)
118
- @instances_interface.restart(instance_id)
119
- end
178
+ def deploy(args)
179
+ options = {}
180
+ params = {}
181
+ payload = {}
182
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
183
+ opts.banner = subcommand_usage("[id] [options]")
184
+ build_option_type_options(opts, options, update_app_deploy_option_types)
185
+ build_option_type_options(opts, options, update_app_deploy_advanced_option_types)
186
+ build_standard_update_options(opts, options)
187
+ opts.footer = <<-EOT
188
+ Update an instance deploy.
189
+ [id] is required. This is the name or id of an instance deploy.
190
+ EOT
120
191
  end
121
- if deploy_args['options']
122
- deploy_payload = {
123
- appDeploy: {
124
- config: deploy_args['options']
125
- }
126
- }
192
+ optparse.parse!(args)
193
+ verify_args!(args:args, optparse:optparse, count:1)
194
+ connect(options)
195
+ app_deploy = find_app_deploy_by_id(args[0])
196
+ return 1 if app_deploy.nil?
197
+ payload = {}
198
+ if options[:payload]
199
+ payload = options[:payload]
200
+ payload.deep_merge!({app_deploy_object_key => parse_passed_options(options)})
201
+ else
202
+ payload.deep_merge!({app_deploy_object_key => parse_passed_options(options)})
203
+ # do not prompt on update
204
+ v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_app_deploy_option_types, options[:options], @api_client, options[:params])
205
+ v_prompt.deep_compact!
206
+ params.deep_merge!(v_prompt)
207
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_app_deploy_advanced_option_types, options[:options], @api_client, options[:params])
208
+ advanced_config.deep_compact!
209
+ params.deep_merge!(advanced_config)
210
+ payload.deep_merge!({app_deploy_object_key => params})
211
+ if payload[app_deploy_object_key].empty? # || options[:no_prompt]
212
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
213
+ end
127
214
  end
215
+ @deploy_interface.setopts(options)
128
216
  if options[:dry_run]
129
- print_dry_run @deploy_interface.deploy(deployment_id,deploy_payload)
130
- else
131
- print cyan, bold, "Deploying to Servers...", reset, "\n"
132
- @deploy_interface.deploy(deployment_id,deploy_payload)
133
- print cyan, bold, "Deploy Successful!", reset, "\n"
217
+ print_dry_run @deploy_interface.dry.update(app_deploy['id'], payload)
218
+ return
219
+ end
220
+ json_response = @deploy_interface.update(app_deploy['id'], payload)
221
+ app_deploy = json_response[app_deploy_object_key]
222
+ render_response(json_response, options, app_deploy_object_key) do
223
+ print_green_success "Deploying..."
224
+ return _get(app_deploy["id"], {}, options)
134
225
  end
135
-
226
+ return 0, nil
136
227
  end
137
- def list(args)
228
+ private
229
+
230
+ ## Deploys (AppDeploy)
231
+
232
+ def app_deploy_object_key
233
+ 'appDeploy'
138
234
  end
139
235
 
140
- def rollback(args)
236
+ def app_deploy_list_key
237
+ 'appDeploys'
141
238
  end
142
239
 
143
- # Loads a morpheus.yml file from within the current working directory.
144
- # This file contains information necessary in the project to perform a deployment via the cli
145
- #
146
- # === Example File Attributes
147
- # * +script+ - The initial script to run before uploading files
148
- # * +name+ - The instance name we are deploying to (can be overridden in CLI)
149
- # * +remote+ - Optional remote appliance name we are connecting to
150
- # * +files+ - List of file patterns to use for uploading files and their target destination
151
- # * +options+ - Map of deployment options depending on deployment type
152
- # * +post_script+ - A post operation script to be run on the local machine
153
- # * +stage_deploy+ - If set to true the deploy will only be staged and not actually run
154
- #
155
- # +NOTE: + It is also possible to nest these properties in an "environments" map to override based on a passed environment deploy name
156
- #
157
- def load_deploy_file
158
- if !File.exist? "morpheus.yml"
159
- puts "No morpheus.yml file detected in the current directory. Nothing to do."
160
- return nil
240
+ def find_app_deploy_by_id(id)
241
+ begin
242
+ json_response = @deploy_interface.get(id.to_i)
243
+ return json_response[app_deploy_object_key]
244
+ rescue RestClient::Exception => e
245
+ if e.response && e.response.code == 404
246
+ print_red_alert "Deploy not found by id '#{id}'"
247
+ else
248
+ raise e
249
+ end
161
250
  end
251
+ end
162
252
 
163
- @deploy_file = YAML.load_file("morpheus.yml")
164
- return @deploy_file
253
+ def app_deploy_column_definitions
254
+ {
255
+ "ID" => 'id',
256
+ "Instance" => lambda {|it| it['instance'] ? it['instance']['name'] : it['instanceId'] },
257
+ "Deployment" => lambda {|it| it['deployment']['name'] rescue '' },
258
+ "Version" => lambda {|it| (it['deploymentVersion']['userVersion'] || it['deploymentVersion']['version']) rescue '' },
259
+ # "Version ID" => lambda {|it| (it['deploymentVersion']['id']) rescue '' },
260
+ "Deploy Date" => lambda {|it| format_local_dt(it['deployDate']) },
261
+ "Status" => lambda {|it| format_app_deploy_status(it['status']) },
262
+ }
165
263
  end
166
264
 
167
- def merged_deploy_args(environment)
168
- environment = environment || production
265
+ def add_app_deploy_option_types
266
+ [
267
+ {'fieldName' => 'instance', 'fieldLabel' => 'Instance', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
268
+ @instances_interface.list({max:10000}.merge(api_params))['instances'].collect {|it|
269
+ {'name' => it['name'], 'value' => it['id'], 'id' => it['id']}
270
+ }
271
+ }, 'required' => true, 'displayOrder' => 1},
272
+ {'fieldName' => 'deployment', 'fieldLabel' => 'Deployment', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
273
+ @deployments_interface.list({max:10000})['deployments'].collect {|it|
274
+ {'name' => it['name'], 'value' => it['id'], 'id' => it['id']}
275
+ }
276
+ }, 'required' => true, 'displayOrder' => 2},
277
+ {'fieldName' => 'version', 'fieldLabel' => 'Version', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
278
+ @deployments_interface.list_versions(api_params['deployment'], {max:10000})['versions'].collect {|it|
279
+ {'name' => (it['userVersion'] || it['version']), 'value' => it['id'], 'id' => it['id']}
280
+ }
281
+ }, 'required' => true, 'displayOrder' => 3}
282
+ ]
283
+ end
169
284
 
170
- deploy_args = @deploy_file.reject { |key,value| key == 'environment'}
171
- if !@deploy_file['environment'].nil? && !@deploy_file['environment'][environment].nil?
172
- deploy_args = deploy_args.merge(@deploy_file['environment'][environment])
285
+ def add_app_deploy_advanced_option_types
286
+ [{'fieldName' => 'stageOnly', 'fieldLabel' => 'Stage Only', 'type' => 'checkbox', 'description' => 'If set to true the deploy will only be staged and not actually run', 'displayOrder' => 10}]
287
+ end
288
+
289
+ def update_app_deploy_option_types
290
+ add_app_deploy_option_types.collect {|it|
291
+ it.delete('required')
292
+ it.delete('defaultValue')
293
+ it
294
+ }
295
+ end
296
+
297
+ def update_app_deploy_advanced_option_types
298
+ add_app_deploy_advanced_option_types.collect {|it|
299
+ it.delete('required')
300
+ it.delete('defaultValue')
301
+ it
302
+ }
303
+ end
304
+
305
+ def format_app_deploy_status(status, return_color=cyan)
306
+ out = ""
307
+ s = status.to_s.downcase
308
+ if s == 'deployed'
309
+ out << "#{green}#{s.upcase}#{return_color}"
310
+ elsif s == 'open' || s == 'archived' || s == 'committed'
311
+ out << "#{cyan}#{s.upcase}#{return_color}"
312
+ elsif s == 'failed'
313
+ out << "#{red}#{s.upcase}#{return_color}"
314
+ else
315
+ out << "#{yellow}#{s.upcase}#{return_color}"
173
316
  end
174
- return deploy_args
317
+ out
175
318
  end
319
+
176
320
  end
321
+
@@ -0,0 +1,182 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ # This provides commands for authentication
4
+ # This also includes credential management.
5
+ class Morpheus::Cli::DocCommand
6
+ include Morpheus::Cli::CliCommand
7
+
8
+ set_command_name :'doc'
9
+ #set_command_name :'access'
10
+ register_subcommands :list
11
+ register_subcommands :get => :swagger
12
+ register_subcommands :download => :download_swagger
13
+
14
+ # hidden until doc complete (or close to it)
15
+ set_command_hidden
16
+
17
+ def initialize()
18
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
19
+ end
20
+
21
+ def handle(args)
22
+ handle_subcommand(args)
23
+ end
24
+
25
+ def connect(options)
26
+ @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true, :skip_login => true}))
27
+ @doc_interface = @api_client.doc
28
+ end
29
+
30
+ def list(args)
31
+ exit_code, err = 0, nil
32
+ params, options = {}, {}
33
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
34
+ opts.banner = subcommand_usage()
35
+ build_standard_get_options(opts, options)
36
+ opts.footer = <<-EOT
37
+ List documentation links.
38
+ EOT
39
+ end
40
+ optparse.parse!(args)
41
+ verify_args!(args:args, optparse:optparse, count:0)
42
+ connect(options)
43
+ # construct the api request
44
+ params.merge!(parse_list_options(options))
45
+ # execute the api request
46
+ @doc_interface.setopts(options)
47
+ if options[:dry_run]
48
+ print_dry_run @doc_interface.dry.list(params)
49
+ return 0, nil
50
+ end
51
+ json_response = @doc_interface.list(params)
52
+ render_response(json_response, options, "links") do
53
+ title = "Morpheus Documentation"
54
+ print_h1 title, options
55
+ if json_response['links'].empty?
56
+ print yellow, "No help links found.",reset,"\n"
57
+ else
58
+ columns = {
59
+ "Link Name" => 'name',
60
+ "URL" => 'url',
61
+ "Description" => {display_method:'description', max_width: (options[:wrap] ? nil : 50)},
62
+ }
63
+ print as_pretty_table(json_response['links'], columns.upcase_keys!, options)
64
+ # print_results_pagination(json_response)
65
+ end
66
+ print reset,"\n"
67
+ end
68
+ return exit_code, err
69
+ end
70
+
71
+ def swagger(args)
72
+ exit_code, err = 0, nil
73
+ params, options = {}, {}
74
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
75
+ opts.banner = subcommand_usage()
76
+ opts.on(nil, "--refresh", "Refresh the document. By default the swagger.yml and swagger.json are cached by the server.") do
77
+ params['refresh'] = true
78
+ end
79
+ opts.on('-g', '--generate', "Alias for --refresh") do
80
+ params['refresh'] = true
81
+ end
82
+ build_standard_get_options(opts, options, [], [:csv])
83
+ opts.footer = <<-EOT
84
+ Print the Morpheus API Swagger Documentation (openapi).
85
+ The default format is JSON. Supports json or yaml.
86
+ EOT
87
+ end
88
+ optparse.parse!(args)
89
+ verify_args!(args:args, optparse:optparse, count:0)
90
+ connect(options)
91
+ # construct the api request
92
+ params.merge!(parse_list_options(options))
93
+ # for now, always use .json, and just convert to yaml for display on cli side
94
+ openapi_format = options[:yaml] ? "yaml" : "json"
95
+ # params['format'] = openapi_format
96
+ # execute the api request
97
+ @doc_interface.setopts(options)
98
+ if options[:dry_run]
99
+ params['format'] = openapi_format
100
+ print_dry_run @doc_interface.dry.swagger(params)
101
+ return 0, nil
102
+ end
103
+ json_response = @doc_interface.swagger(params)
104
+ # default format is to print header and json
105
+ render_response(json_response, options) do
106
+ title = "Morpheus API swagger.#{openapi_format}"
107
+ print_h1 title, options
108
+ print cyan
109
+ print as_json(json_response, options)
110
+ print reset,"\n"
111
+ end
112
+ return exit_code, err
113
+ end
114
+
115
+ def download_swagger(args)
116
+ exit_code, err = 0, nil
117
+ params, options = {}, {}
118
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
119
+ opts.banner = subcommand_usage("[local-file]")
120
+ # build_standard_get_options(opts, options, [], [:csv,:out])
121
+ opts.on(nil, '--yaml', "YAML Output") do
122
+ options[:yaml] = true
123
+ options[:format] = :yaml
124
+ end
125
+ opts.on(nil, "--refresh", "Refresh the document. By default the swagger.yml and swagger.json are cached by the server.") do
126
+ params['refresh'] = true
127
+ end
128
+ opts.on('-g', '--generate', "Alias for --refresh") do
129
+ params['refresh'] = true
130
+ end
131
+ opts.on( '-f', '--force', "Overwrite existing [local-file] if it exists." ) do
132
+ options[:overwrite] = true
133
+ end
134
+ opts.on( '-p', '--mkdir', "Create missing directories for [local-file] if they do not exist." ) do
135
+ options[:mkdir] = true
136
+ end
137
+ build_common_options(opts, options, [:dry_run, :quiet, :remote])
138
+ opts.footer = <<-EOT
139
+ Download the Morpheus API Swagger Documentation (openapi).
140
+ [local-file] is required. This is the full local filepath for the downloaded file.
141
+ The default format is JSON. Supports json or yaml.
142
+ EOT
143
+ end
144
+ optparse.parse!(args)
145
+ verify_args!(args:args, optparse:optparse, count:1)
146
+ connect(options)
147
+ # parse args
148
+ outfile = args[0]
149
+ if !validate_outfile(outfile, options)
150
+ return 1, "Failed to validate outfile"
151
+ end
152
+ # construct the api request
153
+ params.merge!(parse_list_options(options))
154
+ if outfile.include?(".yml") || outfile.include?(".yaml")
155
+ options[:yaml] = true
156
+ end
157
+ openapi_format = options[:yaml] ? "yaml" : "json"
158
+ params['format'] = openapi_format
159
+ # execute the api request
160
+ @doc_interface.setopts(options)
161
+ if options[:dry_run]
162
+ print_dry_run @doc_interface.dry.download_swagger(outfile, params)
163
+ return 0, nil
164
+ end
165
+ print cyan + "Downloading swagger.#{openapi_format} to #{outfile} ... " if !options[:quiet]
166
+ http_response = @doc_interface.download_swagger(outfile, params)
167
+ if http_response.code.to_i == 200
168
+ print green + "SUCCESS" + reset + "\n" if !options[:quiet]
169
+ return 0, nil
170
+ else
171
+ print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n" if !options[:quiet]
172
+ if File.exists?(outfile) && File.file?(outfile)
173
+ Morpheus::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if Morpheus::Logging.debug?
174
+ File.delete(outfile)
175
+ end
176
+ return 1, "HTTP #{http_response.code}"
177
+ end
178
+ end
179
+
180
+ protected
181
+
182
+ end