morpheus-cli 3.3.2.2 → 3.3.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/morpheus/cli.rb +16 -0
- data/lib/morpheus/cli/alias_command.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +3 -0
- data/lib/morpheus/cli/edit_profile_command.rb +46 -0
- data/lib/morpheus/cli/edit_rc_command.rb +61 -0
- data/lib/morpheus/cli/instances.rb +34 -32
- data/lib/morpheus/cli/library_container_scripts_command.rb +4 -4
- data/lib/morpheus/cli/library_container_templates_command.rb +2 -2
- data/lib/morpheus/cli/login.rb +1 -1
- data/lib/morpheus/cli/logout.rb +1 -1
- data/lib/morpheus/cli/man_command.rb +2 -7
- data/lib/morpheus/cli/option_parser.rb +28 -2
- data/lib/morpheus/cli/power_scheduling_command.rb +12 -13
- data/lib/morpheus/cli/remote.rb +3 -3
- data/lib/morpheus/cli/shell.rb +146 -52
- data/lib/morpheus/cli/tasks.rb +124 -36
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/workflows.rb +79 -45
- data/lib/morpheus/formatters.rb +2 -2
- data/lib/morpheus/terminal.rb +18 -5
- metadata +4 -2
data/lib/morpheus/cli/tasks.rb
CHANGED
@@ -27,33 +27,45 @@ class Morpheus::Cli::Tasks
|
|
27
27
|
options = {}
|
28
28
|
optparse = OptionParser.new do|opts|
|
29
29
|
opts.banner = subcommand_usage()
|
30
|
-
build_common_options(opts, options, [:list, :json, :dry_run, :remote])
|
30
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
31
31
|
end
|
32
32
|
optparse.parse!(args)
|
33
33
|
connect(options)
|
34
34
|
begin
|
35
35
|
params = {}
|
36
|
-
|
37
|
-
params[k] = options[k] unless options[k].nil?
|
38
|
-
end
|
36
|
+
params.merge!(parse_list_options(options))
|
39
37
|
if options[:dry_run]
|
40
38
|
print_dry_run @tasks_interface.dry.get(params)
|
41
39
|
return
|
42
40
|
end
|
43
41
|
json_response = @tasks_interface.get(params)
|
42
|
+
# print result and return output
|
44
43
|
if options[:json]
|
45
|
-
|
44
|
+
if options[:include_fields]
|
45
|
+
json_response = {"tasks" => filter_data(json_response["tasks"], options[:include_fields]) }
|
46
|
+
end
|
47
|
+
puts as_json(json_response, options)
|
48
|
+
return 0
|
49
|
+
elsif options[:csv]
|
50
|
+
puts records_as_csv(json_response['tasks'], options)
|
51
|
+
return 0
|
52
|
+
elsif options[:yaml]
|
53
|
+
if options[:include_fields]
|
54
|
+
json_response = {"tasks" => filter_data(json_response["tasks"], options[:include_fields]) }
|
55
|
+
end
|
56
|
+
puts as_yaml(json_response, options)
|
57
|
+
return 0
|
46
58
|
else
|
59
|
+
title = "Morpheus Tasks"
|
60
|
+
subtitles = []
|
61
|
+
subtitles += parse_list_subtitles(options)
|
62
|
+
print_h1 title, subtitles
|
47
63
|
tasks = json_response['tasks']
|
48
|
-
print_h1 "Morpheus Tasks"
|
49
64
|
if tasks.empty?
|
50
|
-
|
65
|
+
print cyan,"No tasks found.",reset,"\n"
|
51
66
|
else
|
52
67
|
print cyan
|
53
|
-
|
54
|
-
{name: task['name'], id: task['id'], type: task['taskType']['name']}
|
55
|
-
end
|
56
|
-
tp tasks_table_data, :id, :name, :type
|
68
|
+
print_tasks_table(tasks, options)
|
57
69
|
print_results_pagination(json_response)
|
58
70
|
end
|
59
71
|
print reset,"\n"
|
@@ -66,17 +78,24 @@ class Morpheus::Cli::Tasks
|
|
66
78
|
|
67
79
|
def get(args)
|
68
80
|
options = {}
|
69
|
-
optparse = OptionParser.new do|opts|
|
70
|
-
opts.banner = subcommand_usage("[
|
71
|
-
build_common_options(opts, options, [:json, :dry_run, :remote])
|
81
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
82
|
+
opts.banner = subcommand_usage("[workflow]")
|
83
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
72
84
|
end
|
73
85
|
optparse.parse!(args)
|
74
86
|
if args.count < 1
|
75
87
|
puts optparse
|
76
|
-
|
88
|
+
return 1
|
77
89
|
end
|
78
|
-
task_name = args[0]
|
79
90
|
connect(options)
|
91
|
+
id_list = parse_id_list(args)
|
92
|
+
return run_command_for_each_arg(id_list) do |arg|
|
93
|
+
_get(arg, options)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def _get(id, options)
|
98
|
+
task_name = id
|
80
99
|
begin
|
81
100
|
if options[:dry_run]
|
82
101
|
if task_name.to_s =~ /\A\d{1,}\Z/
|
@@ -88,11 +107,25 @@ class Morpheus::Cli::Tasks
|
|
88
107
|
end
|
89
108
|
task = find_task_by_name_or_id(task_name)
|
90
109
|
exit 1 if task.nil?
|
91
|
-
|
110
|
+
# refetch it
|
111
|
+
json_response = {'task' => task}
|
112
|
+
unless task_name.to_s =~ /\A\d{1,}\Z/
|
113
|
+
json_response = @tasks_interface.get(task['id'])
|
114
|
+
end
|
92
115
|
if options[:json]
|
93
|
-
|
94
|
-
|
116
|
+
json_response = {"task" => filter_data(json_response["task"], options[:include_fields]) } if options[:include_fields]
|
117
|
+
puts as_json(json_response, options)
|
118
|
+
return 0
|
119
|
+
elsif options[:yaml]
|
120
|
+
json_response = {"task" => filter_data(json_response["task"], options[:include_fields]) } if options[:include_fields]
|
121
|
+
puts as_yaml(json_response, options)
|
122
|
+
return 0
|
123
|
+
elsif options[:csv]
|
124
|
+
puts records_as_csv([json_response['task']], options)
|
125
|
+
return 0
|
95
126
|
else
|
127
|
+
# load task type to know which options to display
|
128
|
+
task_type = task['taskType'] ? find_task_type_by_name(task['taskType']['name']) : nil
|
96
129
|
#print "\n", cyan, "Task #{task['name']} - #{task['taskType']['name']}\n\n"
|
97
130
|
print_h1 "Task Details"
|
98
131
|
print cyan
|
@@ -104,15 +137,20 @@ class Morpheus::Cli::Tasks
|
|
104
137
|
print_description_list(description_cols, task)
|
105
138
|
|
106
139
|
# JD: uhh, the api should NOT be returning passwords!!
|
107
|
-
task_type
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
140
|
+
if task_type
|
141
|
+
task_type['optionTypes'].sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i }.each do |optionType|
|
142
|
+
if optionType['fieldLabel'].to_s.downcase == 'script'
|
143
|
+
print_h2 "Script"
|
144
|
+
print reset,bright_black,"#{task['taskOptions'][optionType['fieldName']]}","\n",reset
|
145
|
+
else
|
146
|
+
print cyan,("#{optionType['fieldLabel']} : " + (optionType['type'] == 'password' ? "#{task['taskOptions'][optionType['fieldName']] ? '************' : ''}" : "#{task['taskOptions'][optionType['fieldName']] || optionType['defaultValue']}")),"\n"
|
147
|
+
end
|
113
148
|
end
|
149
|
+
else
|
150
|
+
print yellow,"Task type not found.",reset,"\n"
|
114
151
|
end
|
115
152
|
print reset,"\n"
|
153
|
+
return 0
|
116
154
|
end
|
117
155
|
rescue RestClient::Exception => e
|
118
156
|
print_rest_exception(e, options)
|
@@ -222,40 +260,75 @@ class Morpheus::Cli::Tasks
|
|
222
260
|
end
|
223
261
|
|
224
262
|
def add(args)
|
263
|
+
params = {}
|
225
264
|
options = {}
|
265
|
+
task_name = nil
|
226
266
|
task_type_name = nil
|
227
267
|
optparse = OptionParser.new do|opts|
|
228
268
|
opts.banner = subcommand_usage("[name] -t TASK_TYPE")
|
229
269
|
opts.on( '-t', '--type TASK_TYPE', "Task Type" ) do |val|
|
230
270
|
task_type_name = val
|
231
271
|
end
|
232
|
-
|
272
|
+
opts.on('--name NAME', String, "Task Name" ) do |val|
|
273
|
+
task_name = val
|
274
|
+
end
|
275
|
+
opts.on('--file FILE', "File containing the script. This can be used instead of --O taskOptions.script" ) do |filename|
|
276
|
+
full_filename = File.expand_path(filename)
|
277
|
+
if File.exists?(full_filename)
|
278
|
+
options[:options] ||= {}
|
279
|
+
options[:options]['taskOptions'] ||= {}
|
280
|
+
options[:options]['taskOptions']['script'] = File.read(full_filename)
|
281
|
+
# params['script'] = File.read(full_filename)
|
282
|
+
else
|
283
|
+
print_red_alert "File not found: #{full_filename}"
|
284
|
+
exit 1
|
285
|
+
end
|
286
|
+
# use the filename as the name by default.
|
287
|
+
if !params['name']
|
288
|
+
options[:options] ||= {}
|
289
|
+
options[:options]['taskOptions'] ||= {}
|
290
|
+
options[:options]['taskOptions']['script'] = File.read(full_filename)
|
291
|
+
params['name'] = File.basename(full_filename)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
233
295
|
end
|
234
296
|
optparse.parse!(args)
|
235
|
-
|
236
|
-
|
297
|
+
if args[0]
|
298
|
+
task_name = args[0]
|
299
|
+
end
|
300
|
+
|
301
|
+
if task_name.nil? || task_type_name.nil?
|
237
302
|
puts optparse
|
238
303
|
exit 1
|
239
304
|
end
|
240
305
|
connect(options)
|
241
306
|
begin
|
242
|
-
|
243
|
-
if
|
244
|
-
|
245
|
-
|
307
|
+
payload = nil
|
308
|
+
if options[:payload]
|
309
|
+
payload = options[:payload]
|
310
|
+
else
|
311
|
+
# construct payload
|
312
|
+
task_type = find_task_type_by_name(task_type_name)
|
313
|
+
if task_type.nil?
|
314
|
+
puts "Task Type not found by id '#{task_type_name}'!"
|
315
|
+
return 1
|
316
|
+
end
|
317
|
+
input_options = Morpheus::Cli::OptionTypes.prompt(task_type['optionTypes'],options[:options],@api_client, options[:params])
|
318
|
+
payload = {task: {name: task_name, taskOptions: input_options['taskOptions'], taskType: {code: task_type['code'], id: task_type['id']}}}
|
246
319
|
end
|
247
|
-
input_options = Morpheus::Cli::OptionTypes.prompt(task_type['optionTypes'],options[:options],@api_client, options[:params])
|
248
|
-
payload = {task: {name: task_name, taskOptions: input_options['taskOptions'], taskType: {code: task_type['code'], id: task_type['id']}}}
|
249
320
|
if options[:dry_run]
|
250
321
|
print_dry_run @tasks_interface.dry.create(payload)
|
251
322
|
return
|
252
323
|
end
|
253
324
|
json_response = @tasks_interface.create(payload)
|
325
|
+
task = json_response['task']
|
254
326
|
if options[:json]
|
255
327
|
print JSON.pretty_generate(json_response),"\n"
|
256
328
|
elsif !options[:quiet]
|
257
|
-
|
258
|
-
|
329
|
+
task = json_response['task']
|
330
|
+
print "\n", cyan, "Task #{task['name']} created successfully", reset, "\n\n"
|
331
|
+
get([task['id']])
|
259
332
|
end
|
260
333
|
rescue RestClient::Exception => e
|
261
334
|
print_rest_exception(e, options)
|
@@ -358,4 +431,19 @@ class Morpheus::Cli::Tasks
|
|
358
431
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 0}
|
359
432
|
] + task_type['optionTypes']
|
360
433
|
end
|
434
|
+
|
435
|
+
def print_tasks_table(tasks, opts={})
|
436
|
+
columns = [
|
437
|
+
{"ID" => lambda {|it| it['id'] } },
|
438
|
+
{"NAME" => lambda {|it| it['name'] } },
|
439
|
+
{"TYPE" => lambda {|it| it['taskType']['name'] ? it['taskType']['name'] : it['type'] } },
|
440
|
+
# {"CREATED" => lambda {|it| format_local_dt(it['dateCreated']) } },
|
441
|
+
# {"UPDATED" => lambda {|it| format_local_dt(it['lastUpdated']) } },
|
442
|
+
]
|
443
|
+
if opts[:include_fields]
|
444
|
+
columns = opts[:include_fields]
|
445
|
+
end
|
446
|
+
print as_pretty_table(tasks, columns, opts)
|
447
|
+
end
|
448
|
+
|
361
449
|
end
|
data/lib/morpheus/cli/version.rb
CHANGED
@@ -31,29 +31,40 @@ class Morpheus::Cli::Workflows
|
|
31
31
|
options = {}
|
32
32
|
optparse = OptionParser.new do|opts|
|
33
33
|
opts.banner = subcommand_usage()
|
34
|
-
build_common_options(opts, options, [:list, :json, :dry_run, :remote])
|
34
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
35
35
|
end
|
36
36
|
optparse.parse!(args)
|
37
37
|
connect(options)
|
38
38
|
begin
|
39
39
|
params = {}
|
40
|
-
|
41
|
-
params[k] = options[k] unless options[k].nil?
|
42
|
-
end
|
40
|
+
params.merge!(parse_list_options(options))
|
43
41
|
if options[:dry_run]
|
44
42
|
print_dry_run @task_sets_interface.dry.get(params)
|
45
43
|
return
|
46
44
|
end
|
47
45
|
json_response = @task_sets_interface.get(params)
|
46
|
+
task_sets = json_response['taskSets']
|
47
|
+
# print result and return output
|
48
48
|
if options[:json]
|
49
|
-
|
49
|
+
if options[:include_fields]
|
50
|
+
json_response = {"taskSets" => filter_data(json_response["taskSets"], options[:include_fields]) }
|
51
|
+
end
|
52
|
+
puts as_json(json_response, options)
|
53
|
+
return 0
|
54
|
+
elsif options[:csv]
|
55
|
+
puts records_as_csv(json_response['taskSets'], options)
|
56
|
+
return 0
|
57
|
+
elsif options[:yaml]
|
58
|
+
if options[:include_fields]
|
59
|
+
json_response = {"taskSets" => filter_data(json_response["taskSets"], options[:include_fields]) }
|
60
|
+
end
|
61
|
+
puts as_yaml(json_response, options)
|
62
|
+
return 0
|
50
63
|
else
|
51
64
|
task_sets = json_response['taskSets']
|
52
65
|
title = "Morpheus Workflows"
|
53
66
|
subtitles = []
|
54
|
-
|
55
|
-
subtitles << "Search: #{params[:phrase]}".strip
|
56
|
-
end
|
67
|
+
subtitles += parse_list_subtitles(options)
|
57
68
|
print_h1 title, subtitles
|
58
69
|
if task_sets.empty?
|
59
70
|
print cyan,"No workflows found.",reset,"\n"
|
@@ -77,7 +88,7 @@ class Morpheus::Cli::Workflows
|
|
77
88
|
opts.on("--tasks x,y,z", Array, "List of tasks to run in order") do |list|
|
78
89
|
options[:task_names] = list
|
79
90
|
end
|
80
|
-
build_common_options(opts, options, [:json, :dry_run, :remote])
|
91
|
+
build_common_options(opts, options, [:options, :json, :dry_run, :quiet, :remote])
|
81
92
|
end
|
82
93
|
optparse.parse!(args)
|
83
94
|
if args.count < 1 || options[:task_names].empty?
|
@@ -101,7 +112,9 @@ class Morpheus::Cli::Workflows
|
|
101
112
|
if options[:json]
|
102
113
|
print JSON.pretty_generate(json_response)
|
103
114
|
else
|
104
|
-
|
115
|
+
workflow = json_response['taskSet']
|
116
|
+
print "\n", cyan, "Workflow #{workflow['name']} created successfully", reset, "\n\n"
|
117
|
+
get([workflow['id']])
|
105
118
|
end
|
106
119
|
rescue RestClient::Exception => e
|
107
120
|
print_rest_exception(e, options)
|
@@ -111,17 +124,24 @@ class Morpheus::Cli::Workflows
|
|
111
124
|
|
112
125
|
def get(args)
|
113
126
|
options = {}
|
114
|
-
optparse = OptionParser.new do|opts|
|
115
|
-
opts.banner = subcommand_usage("[
|
116
|
-
build_common_options(opts, options, [:json, :dry_run, :remote])
|
127
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
128
|
+
opts.banner = subcommand_usage("[workflow]")
|
129
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
117
130
|
end
|
118
131
|
optparse.parse!(args)
|
119
132
|
if args.count < 1
|
120
133
|
puts optparse
|
121
|
-
|
134
|
+
return 1
|
122
135
|
end
|
123
|
-
workflow_name = args[0]
|
124
136
|
connect(options)
|
137
|
+
id_list = parse_id_list(args)
|
138
|
+
return run_command_for_each_arg(id_list) do |arg|
|
139
|
+
_get(arg, options)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def _get(id, options)
|
144
|
+
workflow_name = id
|
125
145
|
begin
|
126
146
|
if options[:dry_run]
|
127
147
|
if workflow_name.to_s =~ /\A\d{1,}\Z/
|
@@ -134,13 +154,22 @@ class Morpheus::Cli::Workflows
|
|
134
154
|
workflow = find_workflow_by_name_or_id(workflow_name)
|
135
155
|
exit 1 if workflow.nil?
|
136
156
|
# refetch it..
|
137
|
-
json_response =
|
157
|
+
json_response = {'taskSet' => workflow}
|
158
|
+
unless workflow_name.to_s =~ /\A\d{1,}\Z/
|
159
|
+
json_response = @task_sets_interface.get(workflow['id'])
|
160
|
+
end
|
138
161
|
workflow = json_response['taskSet']
|
139
|
-
|
140
162
|
if options[:json]
|
141
|
-
|
142
|
-
puts
|
143
|
-
|
163
|
+
json_response = {"taskSet" => filter_data(json_response["taskSet"], options[:include_fields]) } if options[:include_fields]
|
164
|
+
puts as_json(json_response, options)
|
165
|
+
return 0
|
166
|
+
elsif options[:yaml]
|
167
|
+
json_response = {"taskSet" => filter_data(json_response["taskSet"], options[:include_fields]) } if options[:include_fields]
|
168
|
+
puts as_yaml(json_response, options)
|
169
|
+
return 0
|
170
|
+
elsif options[:csv]
|
171
|
+
puts records_as_csv([json_response['taskSet']], options)
|
172
|
+
return 0
|
144
173
|
else
|
145
174
|
# tasks = []
|
146
175
|
# (workflow['tasks'] || []).each do |task_name|
|
@@ -153,19 +182,31 @@ class Morpheus::Cli::Workflows
|
|
153
182
|
description_cols = {
|
154
183
|
"ID" => 'id',
|
155
184
|
"Name" => 'name',
|
156
|
-
|
185
|
+
"Description" => 'description',
|
186
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
187
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
157
188
|
}
|
158
189
|
print_description_list(description_cols, workflow)
|
159
190
|
|
160
191
|
#task_names = tasks.collect {|it| it['name'] }
|
161
|
-
print_h2 "Tasks"
|
192
|
+
print_h2 "Workflow Tasks"
|
162
193
|
if tasks.empty?
|
163
194
|
print yellow,"No tasks in this workflow.",reset,"\n"
|
164
195
|
else
|
165
196
|
print cyan
|
166
|
-
tasks.each_with_index do |taskSetTask, index|
|
167
|
-
|
168
|
-
end
|
197
|
+
# tasks.each_with_index do |taskSetTask, index|
|
198
|
+
# puts "#{(index+1).to_s.rjust(3, ' ')}. #{taskSetTask['task']['name']}"
|
199
|
+
# end
|
200
|
+
task_set_task_columns = [
|
201
|
+
# this is the ID needed for the config options, by name would be nicer
|
202
|
+
{"ID" => lambda {|it| it['id'] } },
|
203
|
+
{"TASK ID" => lambda {|it| it['task']['id'] } },
|
204
|
+
{"NAME" => lambda {|it| it['task']['name'] } },
|
205
|
+
{"TYPE" => lambda {|it| it['task']['taskType'] ? it['task']['taskType']['name'] : '' } },
|
206
|
+
{"PHASE" => lambda {|it| it['taskPhase'] } }, # not returned yet?
|
207
|
+
]
|
208
|
+
print cyan
|
209
|
+
puts as_pretty_table(tasks, task_set_task_columns)
|
169
210
|
end
|
170
211
|
print reset,"\n"
|
171
212
|
end
|
@@ -337,26 +378,19 @@ class Morpheus::Cli::Workflows
|
|
337
378
|
end
|
338
379
|
|
339
380
|
def print_workflows_table(workflows, opts={})
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
tasks: task_names.join(', '),
|
350
|
-
dateCreated: format_local_dt(workflow['dateCreated'])
|
351
|
-
}
|
352
|
-
end
|
353
|
-
print table_color
|
354
|
-
tp rows, [
|
355
|
-
:id,
|
356
|
-
:name,
|
357
|
-
:tasks
|
381
|
+
columns = [
|
382
|
+
{"ID" => lambda {|workflow| workflow['id'] } },
|
383
|
+
{"NAME" => lambda {|workflow| workflow['name'] } },
|
384
|
+
{"TASKS" => lambda {|workflow|
|
385
|
+
(workflow['taskSetTasks'] || []).sort { |x,y| x['taskOrder'].to_i <=> y['taskOrder'].to_i }.collect { |taskSetTask|
|
386
|
+
taskSetTask['task']['name']
|
387
|
+
}.join(', ')
|
388
|
+
} },
|
389
|
+
{"DATE CREATED" => lambda {|workflow| format_local_dt(workflow['dateCreated']) } },
|
358
390
|
]
|
359
|
-
|
391
|
+
if opts[:include_fields]
|
392
|
+
columns = opts[:include_fields]
|
393
|
+
end
|
394
|
+
print as_pretty_table(workflows, columns, opts)
|
360
395
|
end
|
361
|
-
|
362
396
|
end
|