morpheus-cli 3.3.2.2 → 3.3.2.3
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.
- 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
|