morpheus-cli 5.0.0 → 5.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api/api_client.rb +12 -0
- data/lib/morpheus/api/billing_interface.rb +1 -0
- data/lib/morpheus/api/deploy_interface.rb +1 -1
- data/lib/morpheus/api/deployments_interface.rb +20 -1
- data/lib/morpheus/api/forgot_password_interface.rb +17 -0
- data/lib/morpheus/api/instances_interface.rb +7 -0
- data/lib/morpheus/api/search_interface.rb +13 -0
- data/lib/morpheus/api/servers_interface.rb +7 -0
- data/lib/morpheus/api/usage_interface.rb +18 -0
- data/lib/morpheus/cli.rb +4 -1
- data/lib/morpheus/cli/cli_command.rb +26 -9
- data/lib/morpheus/cli/commands/standard/curl_command.rb +3 -5
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
- data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
- data/lib/morpheus/cli/deploy.rb +199 -90
- data/lib/morpheus/cli/deployments.rb +341 -28
- data/lib/morpheus/cli/deploys.rb +206 -41
- data/lib/morpheus/cli/error_handler.rb +7 -0
- data/lib/morpheus/cli/forgot_password.rb +133 -0
- data/lib/morpheus/cli/health_command.rb +2 -2
- data/lib/morpheus/cli/hosts.rb +169 -32
- data/lib/morpheus/cli/instances.rb +83 -32
- data/lib/morpheus/cli/invoices_command.rb +33 -16
- data/lib/morpheus/cli/logs_command.rb +9 -6
- data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -2
- data/lib/morpheus/cli/mixins/print_helper.rb +0 -21
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +24 -4
- data/lib/morpheus/cli/option_types.rb +266 -17
- data/lib/morpheus/cli/remote.rb +35 -10
- data/lib/morpheus/cli/reports_command.rb +99 -30
- data/lib/morpheus/cli/search_command.rb +182 -0
- data/lib/morpheus/cli/setup.rb +1 -1
- data/lib/morpheus/cli/shell.rb +33 -11
- data/lib/morpheus/cli/tasks.rb +20 -21
- data/lib/morpheus/cli/usage_command.rb +64 -11
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/virtual_images.rb +280 -199
- data/lib/morpheus/cli/whoami.rb +6 -6
- data/lib/morpheus/cli/workflows.rb +33 -40
- data/lib/morpheus/formatters.rb +22 -0
- data/lib/morpheus/terminal.rb +6 -2
- metadata +7 -2
data/lib/morpheus/cli/deploys.rb
CHANGED
@@ -4,13 +4,10 @@ require 'yaml'
|
|
4
4
|
class Morpheus::Cli::Deploys
|
5
5
|
include Morpheus::Cli::CliCommand
|
6
6
|
include Morpheus::Cli::DeploymentsHelper
|
7
|
-
|
8
|
-
# hidden until api support is added
|
9
|
-
set_command_hidden
|
10
7
|
|
11
8
|
set_command_name :deploys
|
12
|
-
|
13
|
-
register_subcommands :list, :get, :add, :remove, :deploy
|
9
|
+
set_command_description "View and manage instance deploys."
|
10
|
+
register_subcommands :list, :get, :add, :update, :remove, :deploy
|
14
11
|
|
15
12
|
def connect(opts)
|
16
13
|
@api_client = establish_remote_appliance_connection(opts)
|
@@ -70,10 +67,10 @@ EOT
|
|
70
67
|
options = {}
|
71
68
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
72
69
|
opts.banner = subcommand_usage("[id]")
|
73
|
-
build_standard_get_options(opts, options)
|
70
|
+
build_standard_get_options(opts, options, [:details])
|
74
71
|
opts.footer = <<-EOT
|
75
72
|
Get details about a specific instance deploy.
|
76
|
-
[id] is required. This is the
|
73
|
+
[id] is required. This is the id of an instance deploy.
|
77
74
|
EOT
|
78
75
|
end
|
79
76
|
optparse.parse!(args)
|
@@ -93,10 +90,18 @@ EOT
|
|
93
90
|
end
|
94
91
|
json_response = @deploy_interface.get(id, params)
|
95
92
|
app_deploy = json_response[app_deploy_object_key]
|
93
|
+
deploy_config = app_deploy['config']
|
96
94
|
render_response(json_response, options, app_deploy_object_key) do
|
97
95
|
print_h1 "Deploy Details", [], options
|
98
96
|
print cyan
|
99
97
|
print_description_list(app_deploy_column_definitions, app_deploy)
|
98
|
+
|
99
|
+
if options[:details] && deploy_config && !deploy_config.empty?
|
100
|
+
print_h2 "Config", options
|
101
|
+
print cyan
|
102
|
+
print as_description_list(deploy_config, deploy_config.keys, options)
|
103
|
+
end
|
104
|
+
|
100
105
|
print reset,"\n"
|
101
106
|
end
|
102
107
|
return 0, nil
|
@@ -109,9 +114,46 @@ EOT
|
|
109
114
|
opts.banner = subcommand_usage("[instance] [deployment] [version] [options]")
|
110
115
|
build_option_type_options(opts, options, add_app_deploy_option_types)
|
111
116
|
build_option_type_options(opts, options, add_app_deploy_advanced_option_types)
|
117
|
+
opts.on(nil, "--stage", "Stage Only, do not run the deployment right away.") do |val|
|
118
|
+
params['stageOnly'] = true
|
119
|
+
end
|
120
|
+
opts.on("-c", "--config JSON", String, "Config for deployment") do |val|
|
121
|
+
parse_result = parse_json_or_yaml(val)
|
122
|
+
config_map = parse_result[:data]
|
123
|
+
if config_map.nil?
|
124
|
+
# todo: bubble up JSON.parse error message
|
125
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
126
|
+
else
|
127
|
+
params['config'] = config_map
|
128
|
+
options[:options]['config'] = params['config'] # or file_content
|
129
|
+
end
|
130
|
+
end
|
131
|
+
opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
|
132
|
+
options[:config_file] = val.to_s
|
133
|
+
file_content = nil
|
134
|
+
full_filename = File.expand_path(options[:config_file])
|
135
|
+
if File.exists?(full_filename)
|
136
|
+
file_content = File.read(full_filename)
|
137
|
+
else
|
138
|
+
print_red_alert "File not found: #{full_filename}"
|
139
|
+
return 1
|
140
|
+
end
|
141
|
+
parse_result = parse_json_or_yaml(file_content)
|
142
|
+
config_map = parse_result[:data]
|
143
|
+
if config_map.nil?
|
144
|
+
# todo: bubble up JSON.parse error message
|
145
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
146
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
147
|
+
else
|
148
|
+
params['config'] = config_map
|
149
|
+
options[:options]['config'] = params['config'] # or file_content
|
150
|
+
end
|
151
|
+
end
|
112
152
|
build_standard_add_options(opts, options)
|
113
153
|
opts.footer = <<-EOT
|
114
154
|
Create a new instance deploy.
|
155
|
+
This deploys a specific deployment version to a target instance.
|
156
|
+
By default the deployment is run right away, unless the --stage option is used.
|
115
157
|
EOT
|
116
158
|
end
|
117
159
|
optparse.parse!(args)
|
@@ -134,11 +176,110 @@ EOT
|
|
134
176
|
payload[app_deploy_object_key].deep_merge!(params)
|
135
177
|
end
|
136
178
|
@deploy_interface.setopts(options)
|
179
|
+
instance_id = payload[app_deploy_object_key]['instance']
|
137
180
|
if options[:dry_run]
|
138
|
-
print_dry_run @deploy_interface.dry.create(payload)
|
181
|
+
print_dry_run @deploy_interface.dry.create(instance_id, payload)
|
139
182
|
return 0, nil
|
140
183
|
end
|
141
|
-
|
184
|
+
# unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to deploy?")
|
185
|
+
# return 9, "aborted command"
|
186
|
+
# end
|
187
|
+
json_response = @deploy_interface.create(instance_id, payload)
|
188
|
+
app_deploy = json_response[app_deploy_object_key]
|
189
|
+
render_response(json_response, options, app_deploy_object_key) do
|
190
|
+
if app_deploy['status'] == 'staged'
|
191
|
+
begin
|
192
|
+
print_green_success "Staged Deploy #{app_deploy['deployment']['name']} version #{app_deploy['deploymentVersion']['userVersion']} to instance #{app_deploy['instance']['name']}"
|
193
|
+
rescue => ex
|
194
|
+
print_green_success "Staged Deploy"
|
195
|
+
end
|
196
|
+
else
|
197
|
+
begin
|
198
|
+
print_green_success "Deploying #{app_deploy['deployment']['name']} version #{app_deploy['deploymentVersion']['userVersion']} to instance #{app_deploy['instance']['name']}"
|
199
|
+
rescue => ex
|
200
|
+
print_green_success "Deploying"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
return _get(app_deploy["id"], {}, options)
|
204
|
+
end
|
205
|
+
return 0, nil
|
206
|
+
end
|
207
|
+
|
208
|
+
def update(args)
|
209
|
+
options = {}
|
210
|
+
params = {}
|
211
|
+
payload = {}
|
212
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
213
|
+
opts.banner = subcommand_usage("[id] [options]")
|
214
|
+
opts.on("-c", "--config JSON", String, "Config for deployment") do |val|
|
215
|
+
parse_result = parse_json_or_yaml(val)
|
216
|
+
config_map = parse_result[:data]
|
217
|
+
if config_map.nil?
|
218
|
+
# todo: bubble up JSON.parse error message
|
219
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
220
|
+
else
|
221
|
+
params['config'] = config_map
|
222
|
+
options[:options]['config'] = params['config'] # or file_content
|
223
|
+
end
|
224
|
+
end
|
225
|
+
opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
|
226
|
+
options[:config_file] = val.to_s
|
227
|
+
file_content = nil
|
228
|
+
full_filename = File.expand_path(options[:config_file])
|
229
|
+
if File.exists?(full_filename)
|
230
|
+
file_content = File.read(full_filename)
|
231
|
+
else
|
232
|
+
print_red_alert "File not found: #{full_filename}"
|
233
|
+
return 1
|
234
|
+
end
|
235
|
+
parse_result = parse_json_or_yaml(file_content)
|
236
|
+
config_map = parse_result[:data]
|
237
|
+
if config_map.nil?
|
238
|
+
# todo: bubble up JSON.parse error message
|
239
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
240
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
241
|
+
else
|
242
|
+
params['config'] = config_map
|
243
|
+
options[:options]['config'] = params['config'] # or file_content
|
244
|
+
end
|
245
|
+
end
|
246
|
+
#build_option_type_options(opts, options, update_app_deploy_option_types)
|
247
|
+
#build_option_type_options(opts, options, update_app_deploy_advanced_option_types)
|
248
|
+
build_standard_update_options(opts, options)
|
249
|
+
opts.footer = <<-EOT
|
250
|
+
Update an instance deploy.
|
251
|
+
[id] is required. This is the id of an instance deploy.
|
252
|
+
EOT
|
253
|
+
end
|
254
|
+
optparse.parse!(args)
|
255
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
256
|
+
connect(options)
|
257
|
+
app_deploy = find_app_deploy_by_id(args[0])
|
258
|
+
return 1 if app_deploy.nil?
|
259
|
+
payload = {}
|
260
|
+
if options[:payload]
|
261
|
+
payload = options[:payload]
|
262
|
+
payload.deep_merge!({app_deploy_object_key => parse_passed_options(options)})
|
263
|
+
else
|
264
|
+
payload.deep_merge!({app_deploy_object_key => parse_passed_options(options)})
|
265
|
+
# do not prompt on update
|
266
|
+
#v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_app_deploy_option_types, options[:options], @api_client, options[:params])
|
267
|
+
#v_prompt.deep_compact!
|
268
|
+
#params.deep_merge!(v_prompt)
|
269
|
+
#advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_app_deploy_advanced_option_types, options[:options], @api_client, options[:params])
|
270
|
+
#advanced_config.deep_compact!
|
271
|
+
#params.deep_merge!(advanced_config)
|
272
|
+
payload.deep_merge!({app_deploy_object_key => params})
|
273
|
+
if payload[app_deploy_object_key].empty? # || options[:no_prompt]
|
274
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
@deploy_interface.setopts(options)
|
278
|
+
if options[:dry_run]
|
279
|
+
print_dry_run @deploy_interface.dry.update(app_deploy['id'], payload)
|
280
|
+
return
|
281
|
+
end
|
282
|
+
json_response = @deploy_interface.update(app_deploy['id'], payload)
|
142
283
|
app_deploy = json_response[app_deploy_object_key]
|
143
284
|
render_response(json_response, options, app_deploy_object_key) do
|
144
285
|
print_green_success "Deploying..."
|
@@ -155,7 +296,7 @@ EOT
|
|
155
296
|
build_standard_remove_options(opts, options)
|
156
297
|
opts.footer = <<-EOT
|
157
298
|
Delete an instance deploy.
|
158
|
-
[id] is required. This is the
|
299
|
+
[id] is required. This is the id of an instance deploy.
|
159
300
|
EOT
|
160
301
|
end
|
161
302
|
optparse.parse!(args)
|
@@ -163,6 +304,9 @@ EOT
|
|
163
304
|
connect(options)
|
164
305
|
app_deploy = find_app_deploy_by_id(args[0])
|
165
306
|
return 1 if app_deploy.nil?
|
307
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the deploy #{app_deploy['id']}?")
|
308
|
+
return 9, "aborted command"
|
309
|
+
end
|
166
310
|
@deploy_interface.setopts(options)
|
167
311
|
if options[:dry_run]
|
168
312
|
print_dry_run @deploy_interface.dry.destroy(app_deploy['id'], params)
|
@@ -170,7 +314,7 @@ EOT
|
|
170
314
|
end
|
171
315
|
json_response = @deploy_interface.destroy(app_deploy['id'], params)
|
172
316
|
render_response(json_response, options) do
|
173
|
-
print_green_success "Removed deploy #{app_deploy['
|
317
|
+
print_green_success "Removed deploy #{app_deploy['id']}"
|
174
318
|
end
|
175
319
|
return 0, nil
|
176
320
|
end
|
@@ -181,12 +325,44 @@ EOT
|
|
181
325
|
payload = {}
|
182
326
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
183
327
|
opts.banner = subcommand_usage("[id] [options]")
|
184
|
-
|
185
|
-
|
186
|
-
|
328
|
+
opts.on("-c", "--config JSON", String, "Config for deployment") do |val|
|
329
|
+
parse_result = parse_json_or_yaml(val)
|
330
|
+
config_map = parse_result[:data]
|
331
|
+
if config_map.nil?
|
332
|
+
# todo: bubble up JSON.parse error message
|
333
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
334
|
+
else
|
335
|
+
params['config'] = config_map
|
336
|
+
options[:options]['config'] = params['config'] # or file_content
|
337
|
+
end
|
338
|
+
end
|
339
|
+
opts.on('--config-file FILE', String, "Config from a local JSON or YAML file") do |val|
|
340
|
+
options[:config_file] = val.to_s
|
341
|
+
file_content = nil
|
342
|
+
full_filename = File.expand_path(options[:config_file])
|
343
|
+
if File.exists?(full_filename)
|
344
|
+
file_content = File.read(full_filename)
|
345
|
+
else
|
346
|
+
print_red_alert "File not found: #{full_filename}"
|
347
|
+
return 1
|
348
|
+
end
|
349
|
+
parse_result = parse_json_or_yaml(file_content)
|
350
|
+
config_map = parse_result[:data]
|
351
|
+
if config_map.nil?
|
352
|
+
# todo: bubble up JSON.parse error message
|
353
|
+
raise_command_error "Failed to parse config as YAML or JSON. Error: #{parse_result[:err]}"
|
354
|
+
#raise_command_error "Failed to parse config as valid YAML or JSON."
|
355
|
+
else
|
356
|
+
params['config'] = config_map
|
357
|
+
options[:options]['config'] = params['config'] # or file_content
|
358
|
+
end
|
359
|
+
end
|
360
|
+
#build_option_type_options(opts, options, update_app_deploy_option_types)
|
361
|
+
#build_option_type_options(opts, options, update_app_deploy_advanced_option_types)
|
362
|
+
build_standard_update_options(opts, options, [:auto_confirm])
|
187
363
|
opts.footer = <<-EOT
|
188
|
-
|
189
|
-
[id] is required. This is the
|
364
|
+
Deploy an instance deploy.
|
365
|
+
[id] is required. This is the id of an instance deploy.
|
190
366
|
EOT
|
191
367
|
end
|
192
368
|
optparse.parse!(args)
|
@@ -201,23 +377,26 @@ EOT
|
|
201
377
|
else
|
202
378
|
payload.deep_merge!({app_deploy_object_key => parse_passed_options(options)})
|
203
379
|
# 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)
|
380
|
+
#v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_app_deploy_option_types, options[:options], @api_client, options[:params])
|
381
|
+
#v_prompt.deep_compact!
|
382
|
+
#params.deep_merge!(v_prompt)
|
383
|
+
#advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_app_deploy_advanced_option_types, options[:options], @api_client, options[:params])
|
384
|
+
#advanced_config.deep_compact!
|
385
|
+
#params.deep_merge!(advanced_config)
|
210
386
|
payload.deep_merge!({app_deploy_object_key => params})
|
211
|
-
if payload[app_deploy_object_key].empty? # || options[:no_prompt]
|
212
|
-
|
213
|
-
end
|
387
|
+
# if payload[app_deploy_object_key].empty? # || options[:no_prompt]
|
388
|
+
# raise_command_error "Specify at least one option to update.\n#{optparse}"
|
389
|
+
# end
|
390
|
+
end
|
391
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to deploy #{app_deploy['deployment']['name']} version #{app_deploy['deploymentVersion']['userVersion']} to instance #{app_deploy['instance']['name']}?")
|
392
|
+
return 9, "aborted command"
|
214
393
|
end
|
215
394
|
@deploy_interface.setopts(options)
|
216
395
|
if options[:dry_run]
|
217
396
|
print_dry_run @deploy_interface.dry.update(app_deploy['id'], payload)
|
218
397
|
return
|
219
398
|
end
|
220
|
-
json_response = @deploy_interface.
|
399
|
+
json_response = @deploy_interface.deploy(app_deploy['id'], payload)
|
221
400
|
app_deploy = json_response[app_deploy_object_key]
|
222
401
|
render_response(json_response, options, app_deploy_object_key) do
|
223
402
|
print_green_success "Deploying..."
|
@@ -225,6 +404,7 @@ EOT
|
|
225
404
|
end
|
226
405
|
return 0, nil
|
227
406
|
end
|
407
|
+
|
228
408
|
private
|
229
409
|
|
230
410
|
## Deploys (AppDeploy)
|
@@ -302,20 +482,5 @@ EOT
|
|
302
482
|
}
|
303
483
|
end
|
304
484
|
|
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}"
|
316
|
-
end
|
317
|
-
out
|
318
|
-
end
|
319
|
-
|
320
485
|
end
|
321
486
|
|
@@ -25,6 +25,13 @@ class Morpheus::Cli::ErrorHandler
|
|
25
25
|
#@stderr.puts "#{dark}Handling error #{err.class} - #{err}#{reset}"
|
26
26
|
|
27
27
|
case (err)
|
28
|
+
# when Morpheus::Cli::CommandNotFoundError
|
29
|
+
# puts_angry_error err.message
|
30
|
+
# @stderr.puts "Try help to see a list of available commands"
|
31
|
+
# do_print_stacktrace = false
|
32
|
+
# if err.exit_code
|
33
|
+
# exit_code = err.exit_code
|
34
|
+
# end
|
28
35
|
when ::OptionParser::InvalidOption, ::OptionParser::AmbiguousOption,
|
29
36
|
::OptionParser::MissingArgument, ::OptionParser::InvalidArgument,
|
30
37
|
::OptionParser::NeedlessArgument
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
|
3
|
+
class Morpheus::Cli::ForgotPassword
|
4
|
+
include Morpheus::Cli::CliCommand
|
5
|
+
|
6
|
+
set_command_name :'forgot'
|
7
|
+
set_command_description "Send a forgot password email and reset your password."
|
8
|
+
|
9
|
+
def connect(opts)
|
10
|
+
@api_client = establish_remote_appliance_connection(opts)
|
11
|
+
@forgot_interface = @api_client.forgot
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle(args)
|
15
|
+
# handle_subcommand(args)
|
16
|
+
# end
|
17
|
+
|
18
|
+
# def email(args)
|
19
|
+
options = {}
|
20
|
+
params = {}
|
21
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
22
|
+
opts.banner = "Usage: #{prog_name} #{command_name} [username]"
|
23
|
+
opts.on( '-U', '--username USERNAME', "Username of the user to be emailed." ) do |val|
|
24
|
+
options[:options]['username'] = val
|
25
|
+
end
|
26
|
+
opts.on("--email [USERNAME]", String, "Email only. Only send an email, skip the reset password.") do |val|
|
27
|
+
options[:email_only] = true
|
28
|
+
if !val.to_s.empty?
|
29
|
+
options[:options]['username'] = val
|
30
|
+
end
|
31
|
+
end
|
32
|
+
opts.on("--reset [TOKEN]", "Reset only. Only reset password, skip sending an email.") do |val|
|
33
|
+
options[:reset_only] = true
|
34
|
+
if !val.to_s.empty?
|
35
|
+
options[:options]['token'] = val
|
36
|
+
end
|
37
|
+
end
|
38
|
+
opts.on( '-T', '--token TOKEN', "Token, the secret token that was emailed to the user. Only reset password, skip sending an email." ) do |val|
|
39
|
+
options[:reset_only] = true
|
40
|
+
options[:options]['token'] = val
|
41
|
+
end
|
42
|
+
opts.on( '-P', '--password PASSWORD', "New Password, the new password for the user." ) do |val|
|
43
|
+
options[:options]['password'] = val
|
44
|
+
end
|
45
|
+
|
46
|
+
build_standard_post_options(opts, options, [], [:remote_username,:remote_password,:remote_token])
|
47
|
+
opts.footer = <<-EOT
|
48
|
+
Send a forgot password email and reset your password.
|
49
|
+
[username] is required. This is the username to be notified.
|
50
|
+
By default this command prompts to perform two actions.
|
51
|
+
First it sends a forgot password email to the specified user.
|
52
|
+
Then it attempts to reset the password with the secret token and a new password.
|
53
|
+
Use the --email and --token options to only perform one of these actions, instead of prompting to do both.
|
54
|
+
That is, only send the email or only reset the password.
|
55
|
+
|
56
|
+
EOT
|
57
|
+
end
|
58
|
+
optparse.parse!(args)
|
59
|
+
connect(options)
|
60
|
+
verify_args!(args:args, optparse:optparse, max:1)
|
61
|
+
|
62
|
+
if options[:email_only] && options[:options]['token']
|
63
|
+
raise_command_error "Invalid usage. --email cannot be used with --token or --reset, use one or the other", args, optparse
|
64
|
+
end
|
65
|
+
|
66
|
+
if args[0]
|
67
|
+
options[:options]['username'] = args[0]
|
68
|
+
end
|
69
|
+
|
70
|
+
params.merge!(parse_query_options(options))
|
71
|
+
|
72
|
+
# Step 1. Send Forgot Password Email
|
73
|
+
if options[:reset_only] != true
|
74
|
+
print_h1 "Forgot Password", [], options unless options[:quiet] || options[:json] || options[:yaml]
|
75
|
+
payload = {}
|
76
|
+
payload['username'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'username', 'fieldLabel' => 'Username', 'type' => 'text', 'description' => "Enter the username of your Morpheus User.", 'required' => true, :fmt => :natural}], options[:options],@api_client)['username']
|
77
|
+
@forgot_interface.setopts(options)
|
78
|
+
if options[:dry_run]
|
79
|
+
print_dry_run @forgot_interface.dry.send_email(payload, params)
|
80
|
+
return
|
81
|
+
end
|
82
|
+
json_response = @forgot_interface.send_email(payload, params)
|
83
|
+
if options[:email_only]
|
84
|
+
render_response(json_response, options) do
|
85
|
+
print_green_success(json_response["msg"] || "Email has been sent") unless options[:quiet]
|
86
|
+
end
|
87
|
+
return 0, nil
|
88
|
+
else
|
89
|
+
print_green_success(json_response["msg"] || "Email has been sent") unless options[:quiet]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Step 2. Reset Password
|
94
|
+
print_h1 "Reset Password", [], options unless options[:quiet] || options[:json] || options[:yaml]
|
95
|
+
payload = {}
|
96
|
+
if options[:payload]
|
97
|
+
payload = options[:payload]
|
98
|
+
payload.deep_merge!(parse_passed_options(options))
|
99
|
+
else
|
100
|
+
payload.deep_merge!(parse_passed_options(options))
|
101
|
+
# prompt for Token
|
102
|
+
payload['token'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'token', 'fieldLabel' => 'Token', 'type' => 'text', 'description' => "Enter the token that you obtained from the forgot password email.", 'required' => true, :fmt => :natural}], options[:options],@api_client)['token']
|
103
|
+
# New Password
|
104
|
+
# todo: prompt_password_with_confirmation()
|
105
|
+
password_value = options[:options]['password']
|
106
|
+
confirm_password_value = password_value
|
107
|
+
while password_value.to_s.empty?
|
108
|
+
password_value = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'password', 'fieldLabel' => 'New Password', 'type' => 'password', 'description' => "Enter your new password.", 'required' => true, :fmt => :natural}], options[:options],@api_client)['password']
|
109
|
+
confirm_password_value = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'password', 'fieldLabel' => 'Confirm New Password', 'type' => 'password', 'description' => "Enter your new password again to confirm it is what you intend.", 'required' => true, :fmt => :natural}], options[:options],@api_client)['password']
|
110
|
+
if password_value != confirm_password_value
|
111
|
+
print_red_alert("Passwords did not match. Please try again.")
|
112
|
+
password_value = nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
payload['password'] = password_value
|
116
|
+
end
|
117
|
+
|
118
|
+
@forgot_interface.setopts(options)
|
119
|
+
if options[:dry_run]
|
120
|
+
print_dry_run @forgot_interface.dry.reset_password(payload, params)
|
121
|
+
return
|
122
|
+
end
|
123
|
+
json_response = @forgot_interface.reset_password(payload, params)
|
124
|
+
render_response(json_response, options) do
|
125
|
+
print_green_success(json_response["msg"] || "Password has been updated") unless options[:quiet]
|
126
|
+
end
|
127
|
+
return 0, nil
|
128
|
+
end
|
129
|
+
|
130
|
+
protected
|
131
|
+
|
132
|
+
end
|
133
|
+
|