morpheus-cli 3.3.2.4 → 3.3.2.5
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/clouds.rb +170 -100
- data/lib/morpheus/cli/mixins/print_helper.rb +39 -27
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43f88e813f909c4b50f7b18219e0a3a4b298cc44
|
4
|
+
data.tar.gz: c5f23f5767cb4d60bae998e21f82abf78d452239
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a012937d6dc02d54e8b204b34b1ae98297017c66c70df6c114be7ccd98e49282202ca379ad7b6c2e4efa677a051dfe4a3fbd62d744d19e38ff5ed385b365f479
|
7
|
+
data.tar.gz: ca965fcec4b654400a983975e6905275f12c2ef973932d0ec1ce76bb9126868f4970f3beac3a503c369c735746cf80c154e18ef7bb6ef1f0b06d33b6d6b90e69
|
data/lib/morpheus/cli/clouds.rb
CHANGED
@@ -10,7 +10,7 @@ class Morpheus::Cli::Clouds
|
|
10
10
|
include Morpheus::Cli::CliCommand
|
11
11
|
include Morpheus::Cli::InfrastructureHelper
|
12
12
|
|
13
|
-
register_subcommands :list, :get, :add, :update, :remove, :firewall_disable, :firewall_enable, :security_groups, :apply_security_groups, :types => :list_cloud_types
|
13
|
+
register_subcommands :list, :count, :get, :add, :update, :remove, :firewall_disable, :firewall_enable, :security_groups, :apply_security_groups, :types => :list_cloud_types
|
14
14
|
alias_subcommand :details, :get
|
15
15
|
set_default_subcommand :list
|
16
16
|
|
@@ -34,7 +34,7 @@ class Morpheus::Cli::Clouds
|
|
34
34
|
def list(args)
|
35
35
|
options={}
|
36
36
|
params = {}
|
37
|
-
optparse = OptionParser.new do|opts|
|
37
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
38
38
|
opts.banner = subcommand_usage()
|
39
39
|
opts.on( '-g', '--group GROUP', "Group Name" ) do |group|
|
40
40
|
options[:group] = group
|
@@ -42,14 +42,12 @@ class Morpheus::Cli::Clouds
|
|
42
42
|
opts.on( '-t', '--type TYPE', "Cloud Type" ) do |val|
|
43
43
|
options[:zone_type] = val
|
44
44
|
end
|
45
|
-
build_common_options(opts, options, [:list, :json, :dry_run, :remote])
|
45
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
|
46
|
+
opts.footer = "List clouds."
|
46
47
|
end
|
47
48
|
optparse.parse!(args)
|
48
49
|
connect(options)
|
49
50
|
begin
|
50
|
-
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
51
|
-
params[k] = options[k] unless options[k].nil?
|
52
|
-
end
|
53
51
|
if options[:zone_type]
|
54
52
|
cloud_type = cloud_type_for_name(options[:zone_type])
|
55
53
|
params[:type] = cloud_type['code']
|
@@ -61,6 +59,8 @@ class Morpheus::Cli::Clouds
|
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
62
|
+
params.merge!(parse_list_options(options))
|
63
|
+
|
64
64
|
if options[:dry_run]
|
65
65
|
print_dry_run @clouds_interface.dry.get(params)
|
66
66
|
return
|
@@ -68,8 +68,13 @@ class Morpheus::Cli::Clouds
|
|
68
68
|
|
69
69
|
json_response = @clouds_interface.get(params)
|
70
70
|
if options[:json]
|
71
|
-
|
72
|
-
|
71
|
+
puts as_json(json_response, options, "zones")
|
72
|
+
return 0
|
73
|
+
elsif options[:yaml]
|
74
|
+
puts as_yaml(json_response, options, "zones")
|
75
|
+
return 0
|
76
|
+
elsif options[:csv]
|
77
|
+
puts records_as_csv(json_response['zones'], options)
|
73
78
|
else
|
74
79
|
clouds = json_response['zones']
|
75
80
|
title = "Morpheus Clouds"
|
@@ -80,9 +85,7 @@ class Morpheus::Cli::Clouds
|
|
80
85
|
if cloud_type
|
81
86
|
subtitles << "Type: #{cloud_type['name']}".strip
|
82
87
|
end
|
83
|
-
|
84
|
-
subtitles << "Search: #{params[:phrase]}".strip
|
85
|
-
end
|
88
|
+
subtitles += parse_list_subtitles(options)
|
86
89
|
print_h1 title, subtitles
|
87
90
|
if clouds.empty?
|
88
91
|
print cyan,"No clouds found.",reset,"\n"
|
@@ -98,25 +101,71 @@ class Morpheus::Cli::Clouds
|
|
98
101
|
end
|
99
102
|
end
|
100
103
|
|
104
|
+
def count(args)
|
105
|
+
options = {}
|
106
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
107
|
+
opts.banner = subcommand_usage("[options]")
|
108
|
+
build_common_options(opts, options, [:query, :remote, :dry_run])
|
109
|
+
opts.footer = "Get the number of clouds."
|
110
|
+
end
|
111
|
+
optparse.parse!(args)
|
112
|
+
connect(options)
|
113
|
+
begin
|
114
|
+
params = {}
|
115
|
+
params.merge!(parse_list_options(options))
|
116
|
+
if options[:dry_run]
|
117
|
+
print_dry_run @clouds_interface.dry.get(params)
|
118
|
+
return
|
119
|
+
end
|
120
|
+
json_response = @clouds_interface.get(params)
|
121
|
+
# print number only
|
122
|
+
if json_response['meta'] && json_response['meta']['total']
|
123
|
+
print cyan, json_response['meta']['total'], reset, "\n"
|
124
|
+
else
|
125
|
+
print yellow, "unknown", reset, "\n"
|
126
|
+
end
|
127
|
+
rescue RestClient::Exception => e
|
128
|
+
print_rest_exception(e, options)
|
129
|
+
exit 1
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
101
133
|
def get(args)
|
102
134
|
options = {}
|
103
|
-
optparse = OptionParser.new do|opts|
|
135
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
104
136
|
opts.banner = subcommand_usage("[name]")
|
105
|
-
build_common_options(opts, options, [:json, :dry_run, :remote])
|
137
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
138
|
+
opts.footer = "Get details about a cloud.\n" +
|
139
|
+
"[name] is required. This is the name or id of a cloud."
|
106
140
|
end
|
107
141
|
optparse.parse!(args)
|
108
142
|
if args.count < 1
|
109
|
-
puts optparse
|
143
|
+
puts optparse
|
110
144
|
exit 1
|
111
145
|
end
|
112
146
|
connect(options)
|
147
|
+
id_list = parse_id_list(args)
|
148
|
+
return run_command_for_each_arg(id_list) do |arg|
|
149
|
+
_get(arg, options)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def _get(arg, options={})
|
113
154
|
begin
|
114
|
-
cloud = find_cloud_by_name_or_id(args[0])
|
115
|
-
#json_response = {'zone' => cloud}
|
116
155
|
if options[:dry_run]
|
117
|
-
|
156
|
+
if arg.to_s =~ /\A\d{1,}\Z/
|
157
|
+
print_dry_run @clouds_interface.dry.get(arg.to_i)
|
158
|
+
else
|
159
|
+
print_dry_run @clouds_interface.dry.get({name:arg})
|
160
|
+
end
|
118
161
|
return
|
119
162
|
end
|
163
|
+
cloud = find_cloud_by_name_or_id(arg)
|
164
|
+
#json_response = {'zone' => cloud}
|
165
|
+
# if options[:dry_run]
|
166
|
+
# print_dry_run @clouds_interface.dry.get(cloud['id'])
|
167
|
+
# return
|
168
|
+
# end
|
120
169
|
json_response = @clouds_interface.get(cloud['id'])
|
121
170
|
cloud = json_response['zone']
|
122
171
|
cloud_stats = cloud['stats']
|
@@ -145,15 +194,7 @@ class Morpheus::Cli::Clouds
|
|
145
194
|
"Status" => lambda {|it| format_cloud_status(it) }
|
146
195
|
}
|
147
196
|
print_description_list(description_cols, cloud)
|
148
|
-
|
149
|
-
# puts "Name: #{cloud['name']}"
|
150
|
-
# puts "Type: #{cloud_type ? cloud_type['name'] : ''}"
|
151
|
-
# puts "Code: #{cloud['code']}"
|
152
|
-
# puts "Location: #{cloud['location']}"
|
153
|
-
# puts "Visibility: #{cloud['visibility'].to_s.capitalize}"
|
154
|
-
# puts "Groups: #{cloud['groups'].collect {|it| it.instance_of?(Hash) ? it['name'] : it.to_s }.join(', ')}"
|
155
|
-
# puts "Status: #{format_cloud_status(cloud)}"
|
156
|
-
|
197
|
+
|
157
198
|
print_h2 "Cloud Servers"
|
158
199
|
print cyan
|
159
200
|
if server_counts
|
@@ -188,7 +229,10 @@ class Morpheus::Cli::Clouds
|
|
188
229
|
opts.on( '-d', '--description DESCRIPTION', "Description (optional)" ) do |desc|
|
189
230
|
params[:description] = desc
|
190
231
|
end
|
191
|
-
|
232
|
+
opts.on( '--certificate-provider CODE', String, "Certificate Provider. Default is 'internal'" ) do |val|
|
233
|
+
params[:certificate_provider] = val
|
234
|
+
end
|
235
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
192
236
|
end
|
193
237
|
optparse.parse!(args)
|
194
238
|
# if args.count < 1
|
@@ -197,65 +241,80 @@ class Morpheus::Cli::Clouds
|
|
197
241
|
# end
|
198
242
|
connect(options)
|
199
243
|
|
200
|
-
cloud_payload = {name: args[0], description: params[:description]}
|
201
|
-
|
202
244
|
begin
|
245
|
+
payload = nil
|
246
|
+
if options[:payload]
|
247
|
+
payload = options[:payload]
|
248
|
+
# support -O OPTION switch on top of --payload
|
249
|
+
if options[:options]
|
250
|
+
payload['zone'] ||= {}
|
251
|
+
payload['zone'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
|
252
|
+
end
|
253
|
+
else
|
254
|
+
cloud_payload = {name: args[0], description: params[:description]}
|
255
|
+
# use active group by default
|
256
|
+
params[:group] ||= @active_group_id
|
257
|
+
|
258
|
+
# Group
|
259
|
+
group_id = nil
|
260
|
+
group = params[:group] ? find_group_by_name_or_id(params[:group]) : nil
|
261
|
+
if group
|
262
|
+
group_id = group["id"]
|
263
|
+
else
|
264
|
+
# print_red_alert "Group not found or specified!"
|
265
|
+
# exit 1
|
266
|
+
groups_dropdown = @groups_interface.get({})['groups'].collect {|it| {'name' => it["name"], 'value' => it["id"]} }
|
267
|
+
group_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'group', 'type' => 'select', 'fieldLabel' => 'Group', 'selectOptions' => groups_dropdown, 'required' => true, 'description' => 'Select Group.'}],options[:options],@api_client,{})
|
268
|
+
group_id = group_prompt['group']
|
269
|
+
end
|
270
|
+
cloud_payload['groupId'] = group_id
|
271
|
+
# todo: pass groups as an array instead
|
203
272
|
|
204
|
-
|
205
|
-
params[:group] ||= @active_group_id
|
273
|
+
# Cloud Name
|
206
274
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
all_option_types = add_cloud_option_types(cloud_type)
|
252
|
-
params = Morpheus::Cli::OptionTypes.prompt(all_option_types, options[:options], @api_client, {zoneTypeId: cloud_type['id']})
|
253
|
-
# some optionTypes have fieldContext='zone', so move those to the root level of the zone payload
|
254
|
-
if params['zone'].is_a?(Hash)
|
255
|
-
cloud_payload.merge!(params.delete('zone'))
|
256
|
-
end
|
257
|
-
cloud_payload.merge!(params)
|
258
|
-
payload = {zone: cloud_payload}
|
275
|
+
if args[0]
|
276
|
+
cloud_payload[:name] = args[0]
|
277
|
+
options[:options]['name'] = args[0] # to skip prompt
|
278
|
+
elsif !options[:no_prompt]
|
279
|
+
# name_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true}], options[:options])
|
280
|
+
# cloud_payload[:name] = name_prompt['name']
|
281
|
+
end
|
282
|
+
|
283
|
+
# Cloud Type
|
284
|
+
|
285
|
+
cloud_type = nil
|
286
|
+
if params[:zone_type]
|
287
|
+
cloud_type = cloud_type_for_name(params[:zone_type])
|
288
|
+
elsif !options[:no_prompt]
|
289
|
+
# print_red_alert "Cloud Type not found or specified!"
|
290
|
+
# exit 1
|
291
|
+
cloud_types_dropdown = cloud_types_for_dropdown
|
292
|
+
cloud_type_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'select', 'fieldLabel' => 'Cloud Type', 'selectOptions' => cloud_types_dropdown, 'required' => true, 'description' => 'Select Cloud Type.'}],options[:options],@api_client,{})
|
293
|
+
cloud_type_code = cloud_type_prompt['type']
|
294
|
+
cloud_type = cloud_type_for_name(cloud_type_code) # this does work
|
295
|
+
end
|
296
|
+
if !cloud_type
|
297
|
+
print_red_alert "A cloud type is required."
|
298
|
+
exit 1
|
299
|
+
end
|
300
|
+
cloud_payload[:zoneType] = {code: cloud_type['code']}
|
301
|
+
|
302
|
+
cloud_payload['config'] ||= {}
|
303
|
+
if params[:certificate_provider]
|
304
|
+
cloud_payload['config']['certificateProvider'] = params[:certificate_provider]
|
305
|
+
else
|
306
|
+
cloud_payload['config']['certificateProvider'] = 'internal'
|
307
|
+
end
|
308
|
+
|
309
|
+
all_option_types = add_cloud_option_types(cloud_type)
|
310
|
+
params = Morpheus::Cli::OptionTypes.prompt(all_option_types, options[:options], @api_client, {zoneTypeId: cloud_type['id']})
|
311
|
+
# some optionTypes have fieldContext='zone', so move those to the root level of the zone payload
|
312
|
+
if params['zone'].is_a?(Hash)
|
313
|
+
cloud_payload.deep_merge!(params.delete('zone'))
|
314
|
+
end
|
315
|
+
cloud_payload.deep_merge!(params)
|
316
|
+
payload = {zone: cloud_payload}
|
317
|
+
end
|
259
318
|
if options[:dry_run]
|
260
319
|
print_dry_run @clouds_interface.dry.create(payload)
|
261
320
|
return
|
@@ -289,7 +348,7 @@ class Morpheus::Cli::Clouds
|
|
289
348
|
# opts.on( '-d', '--description DESCRIPTION', "Description (optional)" ) do |desc|
|
290
349
|
# params[:description] = desc
|
291
350
|
# end
|
292
|
-
build_common_options(opts, options, [:options, :json, :dry_run, :remote])
|
351
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
293
352
|
end
|
294
353
|
optparse.parse!(args)
|
295
354
|
if args.count < 1
|
@@ -299,22 +358,33 @@ class Morpheus::Cli::Clouds
|
|
299
358
|
connect(options)
|
300
359
|
begin
|
301
360
|
cloud = find_cloud_by_name_or_id(args[0])
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
361
|
+
return 1 if cloud.nil?
|
362
|
+
payload = nil
|
363
|
+
if options[:payload]
|
364
|
+
payload = options[:payload]
|
365
|
+
# support -O OPTION switch on top of --payload
|
366
|
+
if options[:options]
|
367
|
+
payload['zone'] ||= {}
|
368
|
+
payload['zone'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
|
369
|
+
end
|
370
|
+
else
|
371
|
+
cloud_type = cloud_type_for_id(cloud['zoneTypeId'])
|
372
|
+
cloud_payload = {id: cloud['id']}
|
373
|
+
all_option_types = update_cloud_option_types(cloud_type)
|
374
|
+
#params = Morpheus::Cli::OptionTypes.prompt(all_option_types, options[:options], @api_client, {zoneTypeId: cloud_type['id']})
|
375
|
+
params = options[:options] || {}
|
376
|
+
if params.empty?
|
377
|
+
puts_error optparse.banner
|
378
|
+
puts_error format_available_options(all_option_types)
|
379
|
+
exit 1
|
380
|
+
end
|
381
|
+
# some optionTypes have fieldContext='zone', so move those to the root level of the zone payload
|
382
|
+
if params['zone'].is_a?(Hash)
|
383
|
+
cloud_payload.merge!(params.delete('zone'))
|
384
|
+
end
|
385
|
+
cloud_payload.merge!(params)
|
386
|
+
payload = {zone: cloud_payload}
|
387
|
+
end
|
318
388
|
|
319
389
|
if options[:dry_run]
|
320
390
|
print_dry_run @clouds_interface.dry.update(cloud['id'], payload)
|
@@ -298,9 +298,9 @@ module Morpheus::Cli::PrintHelper
|
|
298
298
|
print out
|
299
299
|
end
|
300
300
|
|
301
|
-
def
|
301
|
+
def format_available_options(option_types)
|
302
302
|
option_lines = option_types.collect {|it| "\t-O #{it['fieldContext'] ? it['fieldContext'] + '.' : ''}#{it['fieldName']}=\"value\"" }.join("\n")
|
303
|
-
|
303
|
+
return "Available Options:\n#{option_lines}\n\n"
|
304
304
|
end
|
305
305
|
|
306
306
|
def format_dt_dd(label, value, label_width=10, justify="right", do_wrap=true)
|
@@ -685,12 +685,12 @@ module Morpheus::Cli::PrintHelper
|
|
685
685
|
'"' + v.to_s.gsub('"', '""') + '"'
|
686
686
|
end
|
687
687
|
|
688
|
-
def as_csv(data, columns,
|
688
|
+
def as_csv(data, columns, options={})
|
689
689
|
out = ""
|
690
|
-
delim =
|
691
|
-
newline =
|
692
|
-
include_header =
|
693
|
-
do_quotes =
|
690
|
+
delim = options[:csv_delim] || options[:delim] || ","
|
691
|
+
newline = options[:csv_newline] || options[:newline] || "\n"
|
692
|
+
include_header = options[:csv_no_header] ? false : true
|
693
|
+
do_quotes = options[:csv_quotes] || options[:quotes]
|
694
694
|
|
695
695
|
column_defs = build_column_definitions(columns)
|
696
696
|
#columns = columns.flatten.compact
|
@@ -728,7 +728,7 @@ module Morpheus::Cli::PrintHelper
|
|
728
728
|
|
729
729
|
end
|
730
730
|
|
731
|
-
def records_as_csv(records,
|
731
|
+
def records_as_csv(records, options={}, default_columns=nil)
|
732
732
|
out = ""
|
733
733
|
if !records
|
734
734
|
#raise "records_as_csv expects records as an Array of objects to render"
|
@@ -736,27 +736,35 @@ module Morpheus::Cli::PrintHelper
|
|
736
736
|
end
|
737
737
|
cols = []
|
738
738
|
all_fields = records.first ? records.first.keys : []
|
739
|
-
if
|
740
|
-
if
|
739
|
+
if options[:include_fields]
|
740
|
+
if options[:include_fields] == 'all' || options[:include_fields].include?('all')
|
741
741
|
cols = all_fields
|
742
742
|
else
|
743
|
-
cols =
|
743
|
+
cols = options[:include_fields]
|
744
744
|
end
|
745
745
|
elsif default_columns
|
746
746
|
cols = default_columns
|
747
747
|
else
|
748
748
|
cols = all_fields
|
749
749
|
end
|
750
|
-
out << as_csv(records, cols,
|
750
|
+
out << as_csv(records, cols, options)
|
751
751
|
out
|
752
752
|
end
|
753
753
|
|
754
|
-
def as_json(data, options={})
|
754
|
+
def as_json(data, options={}, object_key=nil)
|
755
755
|
out = ""
|
756
756
|
if !data
|
757
757
|
return "null" # "No data"
|
758
758
|
end
|
759
759
|
|
760
|
+
if options[:include_fields]
|
761
|
+
if object_key
|
762
|
+
data[object_key] = filter_data(data[object_key], options[:include_fields])
|
763
|
+
else
|
764
|
+
data = filter_data(data, options[:include_fields])
|
765
|
+
end
|
766
|
+
end
|
767
|
+
|
760
768
|
do_pretty = options.key?(:pretty_json) ? options[:pretty_json] : true
|
761
769
|
if do_pretty
|
762
770
|
out << JSON.pretty_generate(data)
|
@@ -767,24 +775,18 @@ module Morpheus::Cli::PrintHelper
|
|
767
775
|
out
|
768
776
|
end
|
769
777
|
|
770
|
-
def
|
771
|
-
items = items ? items.clone : []
|
772
|
-
last_item = items.pop
|
773
|
-
if items.empty?
|
774
|
-
return "#{last_item}"
|
775
|
-
else
|
776
|
-
return items.join(", ") + " and #{last_item}"
|
777
|
-
end
|
778
|
-
end
|
779
|
-
|
780
|
-
def as_yaml(data, options={})
|
778
|
+
def as_yaml(data, options={}, object_key=nil)
|
781
779
|
out = ""
|
782
780
|
if !data
|
783
781
|
return "null" # "No data"
|
784
782
|
end
|
785
|
-
|
786
|
-
|
787
|
-
|
783
|
+
if options[:include_fields]
|
784
|
+
if object_key
|
785
|
+
data[object_key] = filter_data(data[object_key], options[:include_fields])
|
786
|
+
else
|
787
|
+
data = filter_data(data, options[:include_fields])
|
788
|
+
end
|
789
|
+
end
|
788
790
|
begin
|
789
791
|
out << data.to_yaml
|
790
792
|
rescue => err
|
@@ -795,4 +797,14 @@ module Morpheus::Cli::PrintHelper
|
|
795
797
|
out
|
796
798
|
end
|
797
799
|
|
800
|
+
def anded_list(items)
|
801
|
+
items = items ? items.clone : []
|
802
|
+
last_item = items.pop
|
803
|
+
if items.empty?
|
804
|
+
return "#{last_item}"
|
805
|
+
else
|
806
|
+
return items.join(", ") + " and #{last_item}"
|
807
|
+
end
|
808
|
+
end
|
809
|
+
|
798
810
|
end
|
data/lib/morpheus/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morpheus-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.3.2.
|
4
|
+
version: 3.3.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Estes
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2018-05-
|
14
|
+
date: 2018-05-31 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|