morpheus-cli 4.2.16 → 4.2.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) 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 +43 -54
  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 +3 -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/boot_scripts_command.rb +1 -1
  22. data/lib/morpheus/cli/cli_command.rb +92 -41
  23. data/lib/morpheus/cli/clusters.rb +0 -18
  24. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +7 -7
  25. data/lib/morpheus/cli/commands/standard/man_command.rb +1 -1
  26. data/lib/morpheus/cli/credentials.rb +13 -9
  27. data/lib/morpheus/cli/deploy.rb +374 -0
  28. data/lib/morpheus/cli/deployments.rb +521 -197
  29. data/lib/morpheus/cli/deploys.rb +271 -126
  30. data/lib/morpheus/cli/doc.rb +182 -0
  31. data/lib/morpheus/cli/error_handler.rb +23 -8
  32. data/lib/morpheus/cli/errors.rb +3 -2
  33. data/lib/morpheus/cli/image_builder_command.rb +2 -2
  34. data/lib/morpheus/cli/instances.rb +136 -17
  35. data/lib/morpheus/cli/invoices_command.rb +51 -38
  36. data/lib/morpheus/cli/library_layouts_command.rb +1 -1
  37. data/lib/morpheus/cli/login.rb +9 -3
  38. data/lib/morpheus/cli/mixins/accounts_helper.rb +158 -100
  39. data/lib/morpheus/cli/mixins/backups_helper.rb +115 -0
  40. data/lib/morpheus/cli/mixins/deployments_helper.rb +135 -0
  41. data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
  42. data/lib/morpheus/cli/mixins/print_helper.rb +110 -74
  43. data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -2
  44. data/lib/morpheus/cli/mixins/whoami_helper.rb +19 -6
  45. data/lib/morpheus/cli/network_routers_command.rb +1 -1
  46. data/lib/morpheus/cli/option_parser.rb +48 -5
  47. data/lib/morpheus/cli/option_types.rb +1 -1
  48. data/lib/morpheus/cli/remote.rb +3 -2
  49. data/lib/morpheus/cli/roles.rb +49 -92
  50. data/lib/morpheus/cli/security_groups.rb +7 -1
  51. data/lib/morpheus/cli/service_plans_command.rb +10 -10
  52. data/lib/morpheus/cli/setup.rb +1 -1
  53. data/lib/morpheus/cli/shell.rb +7 -6
  54. data/lib/morpheus/cli/subnets_command.rb +1 -1
  55. data/lib/morpheus/cli/tenants_command.rb +133 -163
  56. data/lib/morpheus/cli/user_groups_command.rb +20 -65
  57. data/lib/morpheus/cli/user_settings_command.rb +115 -13
  58. data/lib/morpheus/cli/user_sources_command.rb +57 -24
  59. data/lib/morpheus/cli/users.rb +210 -186
  60. data/lib/morpheus/cli/version.rb +1 -1
  61. data/lib/morpheus/cli/whitelabel_settings_command.rb +29 -5
  62. data/lib/morpheus/cli/whoami.rb +113 -6
  63. data/lib/morpheus/cli/workflows.rb +1 -1
  64. data/lib/morpheus/ext/hash.rb +21 -0
  65. data/lib/morpheus/terminal.rb +1 -0
  66. metadata +12 -3
  67. 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