morpheus-cli 2.10.2 → 2.10.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/morpheus +6 -1
- data/lib/morpheus/cli/alias_command.rb +2 -2
- data/lib/morpheus/cli/credentials.rb +3 -0
- data/lib/morpheus/cli/groups.rb +7 -2
- data/lib/morpheus/cli/login.rb +7 -3
- data/lib/morpheus/cli/mixins/print_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +34 -36
- data/lib/morpheus/cli/option_types.rb +45 -18
- data/lib/morpheus/cli/remote.rb +6 -2
- data/lib/morpheus/cli/shell.rb +19 -13
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/ext/hash.rb +42 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63a320542a8d185d0e96a8ca526ff4ff23b21868
|
4
|
+
data.tar.gz: aeccbd35966dd37101a032acd9346804767ae627
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c825db622aed4d8d571d97bf13a250333f04543834b7749f57a33555fc17e89a0190797e6c0ec6b06dfdf246f623329c4fd7b3b9aef097ac0160e196f1d80712
|
7
|
+
data.tar.gz: fe005b26254bbc9fcf41cde841a5ad40715583d0b637a763e8d0612bdc23341f98df11e9385b98a4d8588fc15c6e53a517d040f9463935be7b2e139141500c84
|
data/bin/morpheus
CHANGED
@@ -81,7 +81,12 @@ end
|
|
81
81
|
|
82
82
|
# ok, execute the command (or alias)
|
83
83
|
begin
|
84
|
-
|
84
|
+
# shell is a Singleton command class
|
85
|
+
if args[0] == "shell"
|
86
|
+
cmd_result = Morpheus::Cli::Shell.instance.handle(args[1..-1])
|
87
|
+
else
|
88
|
+
cmd_result = Morpheus::Cli::CliRegistry.exec(args[0], args[1..-1])
|
89
|
+
end
|
85
90
|
if cmd_result == false
|
86
91
|
exit 1
|
87
92
|
else
|
@@ -27,7 +27,7 @@ class Morpheus::Cli::AliasCommand
|
|
27
27
|
exit 127
|
28
28
|
elsif self.class.has_subcommand?(args[0])
|
29
29
|
handle_subcommand(args)
|
30
|
-
elsif args.count == 1
|
30
|
+
elsif args.count == 1 || (args.count == 2 && args.include?('-e'))
|
31
31
|
add(args)
|
32
32
|
else
|
33
33
|
handle_subcommand(args)
|
@@ -80,7 +80,7 @@ class Morpheus::Cli::AliasCommand
|
|
80
80
|
Morpheus::Cli::CliRegistry.instance.add_alias(alias_name, command_string)
|
81
81
|
#print "registered alias #{alias_name}", "\n"
|
82
82
|
if do_export
|
83
|
-
puts "exporting alias '#{alias_name}' now..."
|
83
|
+
# puts "exporting alias '#{alias_name}' now..."
|
84
84
|
morpheus_profile = Morpheus::Cli::DotFile.new(Morpheus::Cli::DotFile.morpheus_profile_filename)
|
85
85
|
morpheus_profile.export_aliases({(alias_name) => command_string})
|
86
86
|
end
|
@@ -146,6 +146,9 @@ module Morpheus
|
|
146
146
|
credential_map[app_name] = token
|
147
147
|
begin
|
148
148
|
fn = credentials_file_path
|
149
|
+
if !Dir.exists?(File.dirname(fn))
|
150
|
+
FileUtils.mkdir_p(File.dirname(fn))
|
151
|
+
end
|
149
152
|
print "#{dark} #=> adding credentials to #{fn}#{reset}\n" if Morpheus::Logging.debug?
|
150
153
|
File.open(fn, 'w') {|f| f.write credential_map.to_yaml } #Store
|
151
154
|
FileUtils.chmod(0600, fn)
|
data/lib/morpheus/cli/groups.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'fileutils'
|
1
2
|
require 'yaml'
|
2
3
|
require 'io/console'
|
3
4
|
require 'rest_client'
|
@@ -550,8 +551,12 @@ public
|
|
550
551
|
end
|
551
552
|
|
552
553
|
def save_groups(groups_map)
|
553
|
-
|
554
|
-
|
554
|
+
fn = groups_file_path
|
555
|
+
if !Dir.exists?(File.dirname(fn))
|
556
|
+
FileUtils.mkdir_p(File.dirname(fn))
|
557
|
+
end
|
558
|
+
File.open(fn, 'w') {|f| f.write groups_map.to_yaml } #Store
|
559
|
+
FileUtils.chmod(0600, fn)
|
555
560
|
@@groups = groups_map
|
556
561
|
end
|
557
562
|
|
data/lib/morpheus/cli/login.rb
CHANGED
@@ -48,15 +48,19 @@ class Morpheus::Cli::Login
|
|
48
48
|
else
|
49
49
|
@appliance_name, @appliance_url = nil, nil
|
50
50
|
end
|
51
|
+
if !@appliance_name
|
52
|
+
print_red_alert "You have no appliance named '#{options[:remote]}' configured. See the `remote add` command."
|
53
|
+
return false
|
54
|
+
end
|
51
55
|
else
|
52
56
|
@appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
53
|
-
end
|
54
|
-
|
55
|
-
begin
|
56
57
|
if !@appliance_name
|
57
58
|
print yellow,"Please specify a remote appliance with -r or see the command `remote use`#{reset}\n"
|
58
59
|
return false
|
59
60
|
end
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
60
64
|
if options[:quiet]
|
61
65
|
if username.empty? || password.empty?
|
62
66
|
print yellow,"You have not specified username and password\n"
|
@@ -162,7 +162,7 @@ module Morpheus::Cli::PrintHelper
|
|
162
162
|
|
163
163
|
def print_results_pagination(json_response)
|
164
164
|
if json_response && json_response["meta"]
|
165
|
-
print cyan,"\nViewing #{json_response['meta']['offset'].to_i + 1}-#{json_response['meta']['offset'].to_i + json_response['meta']['size'].to_i} of #{json_response['meta']['total']}\n"
|
165
|
+
print cyan,"\nViewing #{json_response['meta']['offset'].to_i + 1}-#{json_response['meta']['offset'].to_i + json_response['meta']['size'].to_i} of #{json_response['meta']['total']}\n", reset
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
@@ -217,29 +217,29 @@ module Morpheus::Cli::ProvisioningHelper
|
|
217
217
|
end
|
218
218
|
|
219
219
|
payload = {
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
220
|
+
'zoneId' => cloud_id,
|
221
|
+
'instance' => {
|
222
|
+
'name' => instance_name,
|
223
|
+
'site' => {
|
224
|
+
'id' => group_id
|
225
225
|
},
|
226
|
-
|
227
|
-
|
226
|
+
'instanceType' => {
|
227
|
+
'code' => instance_type_code
|
228
228
|
}
|
229
229
|
}
|
230
230
|
}
|
231
231
|
|
232
232
|
# Description
|
233
233
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false}], options[:options])
|
234
|
-
payload[
|
234
|
+
payload['instance']['description'] = v_prompt['description'] if !v_prompt['description'].empty?
|
235
235
|
|
236
236
|
# Environment
|
237
237
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'instanceContext', 'fieldLabel' => 'Environment', 'type' => 'select', 'required' => false, 'selectOptions' => instance_context_options()}], options[:options])
|
238
|
-
payload[
|
238
|
+
payload['instance']['instanceContext'] = v_prompt['instanceContext'] if !v_prompt['instanceContext'].empty?
|
239
239
|
|
240
240
|
# Tags
|
241
241
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'tags', 'fieldLabel' => 'Tags', 'type' => 'text', 'required' => false}], options[:options])
|
242
|
-
payload[
|
242
|
+
payload['instance']['tags'] = v_prompt['tags'].split(',').collect {|it| it.to_s.strip }.compact.uniq if !v_prompt['tags'].empty?
|
243
243
|
|
244
244
|
# Version and Layout
|
245
245
|
|
@@ -247,7 +247,11 @@ module Morpheus::Cli::ProvisioningHelper
|
|
247
247
|
layout_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'select', 'fieldLabel' => 'Layout', 'optionSource' => 'layoutsForCloud', 'required' => true, 'description' => 'Select which configuration of the instance type to be provisioned.'}],options[:options],api_client,{groupId: group_id, cloudId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
|
248
248
|
layout_id = layout_prompt['layout']
|
249
249
|
layout = instance_type['instanceTypeLayouts'].find{ |lt| lt['id'] == layout_id.to_i}
|
250
|
-
|
250
|
+
if !layout
|
251
|
+
print_red_alert "Layout not found by id #{layout_id}"
|
252
|
+
exit 1
|
253
|
+
end
|
254
|
+
payload['instance']['layout'] = {'id' => layout['id']}
|
251
255
|
|
252
256
|
# prompt for service plan
|
253
257
|
service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout_id})
|
@@ -255,14 +259,12 @@ module Morpheus::Cli::ProvisioningHelper
|
|
255
259
|
service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
|
256
260
|
plan_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'servicePlan', 'type' => 'select', 'fieldLabel' => 'Plan', 'selectOptions' => service_plans_dropdown, 'required' => true, 'description' => 'Choose the appropriately sized plan for this instance'}],options[:options])
|
257
261
|
service_plan = service_plans.find {|sp| sp["id"] == plan_prompt['servicePlan'].to_i }
|
258
|
-
|
259
|
-
#payload[:servicePlan] = service_plan["id"] # pre-2.10 appliances
|
260
|
-
payload[:instance][:plan] = {id: service_plan["id"]}
|
262
|
+
payload['instance']['plan'] = {'id' => service_plan["id"]}
|
261
263
|
|
262
264
|
# prompt for volumes
|
263
265
|
volumes = prompt_volumes(service_plan, options, api_client, {})
|
264
266
|
if !volumes.empty?
|
265
|
-
payload[
|
267
|
+
payload['volumes'] = volumes
|
266
268
|
end
|
267
269
|
|
268
270
|
if layout["provisionType"] && layout["provisionType"]["id"] && layout["provisionType"]["hasNetworks"]
|
@@ -270,46 +272,42 @@ module Morpheus::Cli::ProvisioningHelper
|
|
270
272
|
begin
|
271
273
|
network_interfaces = prompt_network_interfaces(cloud_id, layout["provisionType"]["id"], options)
|
272
274
|
if !network_interfaces.empty?
|
273
|
-
payload[
|
275
|
+
payload['networkInterfaces'] = network_interfaces
|
274
276
|
end
|
275
277
|
rescue RestClient::Exception => e
|
276
278
|
print_yellow_warning "Unable to load network options. Proceeding..."
|
277
279
|
print_rest_exception(e, options) if Morpheus::Logging.debug?
|
278
280
|
end
|
279
281
|
end
|
280
|
-
|
282
|
+
|
283
|
+
|
281
284
|
if !layout['optionTypes'].nil? && !layout['optionTypes'].empty?
|
282
|
-
type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options]
|
285
|
+
type_payload = Morpheus::Cli::OptionTypes.prompt(layout['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
|
286
|
+
payload.deep_merge!(type_payload)
|
283
287
|
elsif !instance_type['optionTypes'].nil? && !instance_type['optionTypes'].empty?
|
284
|
-
type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options]
|
288
|
+
type_payload = Morpheus::Cli::OptionTypes.prompt(instance_type['optionTypes'],options[:options],@api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
|
289
|
+
payload.deep_merge!(type_payload)
|
285
290
|
end
|
286
|
-
|
287
|
-
payload.merge!(type_payload['config'])
|
288
|
-
end
|
289
|
-
|
290
|
-
provision_payload = {}
|
291
|
+
|
291
292
|
if !layout['provisionType'].nil? && !layout['provisionType']['optionTypes'].nil? && !layout['provisionType']['optionTypes'].empty?
|
292
293
|
instance_type_option_types = layout['provisionType']['optionTypes']
|
293
294
|
# remove volume options if volumes were configured
|
294
|
-
if !payload[
|
295
|
+
if !payload['volumes'].empty?
|
295
296
|
instance_type_option_types = reject_volume_option_types(instance_type_option_types)
|
296
297
|
end
|
297
298
|
# remove networkId option if networks were configured above
|
298
|
-
if !payload[
|
299
|
+
if !payload['networkInterfaces'].empty?
|
299
300
|
instance_type_option_types = reject_networking_option_types(instance_type_option_types)
|
300
301
|
end
|
302
|
+
#print "#{dark} #=> gathering instance type option types for layout provision type...#{reset}\n" if Morpheus::Logging.debug?
|
301
303
|
provision_payload = Morpheus::Cli::OptionTypes.prompt(instance_type_option_types,options[:options],api_client,{groupId: group_id, cloudId: cloud_id, zoneId: cloud_id, instanceTypeId: instance_type['id'], version: version_prompt['version']})
|
302
|
-
|
303
|
-
|
304
|
-
payload[:config] = provision_payload['config'] || {}
|
305
|
-
if provision_payload['server']
|
306
|
-
payload[:server] = provision_payload['server'] || {}
|
304
|
+
payload.deep_merge!(provision_payload)
|
307
305
|
end
|
308
306
|
|
309
307
|
# prompt for environment variables
|
310
308
|
evars = prompt_evars(options)
|
311
309
|
if !evars.empty?
|
312
|
-
payload[
|
310
|
+
payload['evars'] = evars
|
313
311
|
end
|
314
312
|
|
315
313
|
return payload
|
@@ -844,10 +842,10 @@ module Morpheus::Cli::ProvisioningHelper
|
|
844
842
|
network_interface['network']['id'] = v_prompt[field_context]['networkId'].to_i
|
845
843
|
selected_network = networks.find {|it| it["id"] == network_interface['network']['id'] }
|
846
844
|
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
845
|
+
if !selected_network
|
846
|
+
print_red_alert "Network not found by id #{network_interface['network']['id']}!"
|
847
|
+
exit 1
|
848
|
+
end
|
851
849
|
|
852
850
|
# choose network interface type
|
853
851
|
if enable_network_type_selection && !network_interface_type_options.empty?
|
@@ -41,23 +41,35 @@ module Morpheus
|
|
41
41
|
value = nil
|
42
42
|
value_found=false
|
43
43
|
if option_type['fieldContext']
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
cur_namespace = options
|
45
|
+
namespaces = option_type['fieldContext'].split(".")
|
46
|
+
namespaces.each do |ns|
|
47
|
+
next if ns.empty?
|
48
|
+
cur_namespace[ns.to_s] ||= {}
|
49
|
+
cur_namespace = cur_namespace[ns.to_s]
|
50
|
+
context_map[ns.to_s] ||= {}
|
51
|
+
context_map = context_map[ns.to_s]
|
52
|
+
end
|
53
|
+
# use the value passed in the options map
|
54
|
+
if cur_namespace.key?(option_type['fieldName'])
|
55
|
+
value = cur_namespace[option_type['fieldName']]
|
48
56
|
if option_type['type'] == 'number'
|
49
57
|
value = value.to_i
|
58
|
+
elsif option_type['type'] == 'select'
|
59
|
+
# this should just fall down through below, with the extra params no_prompt, use_value
|
60
|
+
value = select_prompt(option_type, api_client, api_params, true, value)
|
50
61
|
end
|
51
62
|
value_found = true
|
52
63
|
end
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
64
|
+
else
|
65
|
+
# no fieldContext
|
66
|
+
if value_found == false && options.key?(option_type['fieldName'])
|
67
|
+
value = options[option_type['fieldName']]
|
68
|
+
if option_type['type'] == 'number'
|
69
|
+
value = value.to_i
|
70
|
+
end
|
71
|
+
value_found = true
|
59
72
|
end
|
60
|
-
value_found = true
|
61
73
|
end
|
62
74
|
|
63
75
|
# no_prompt means skip prompting and instead
|
@@ -78,8 +90,8 @@ module Morpheus
|
|
78
90
|
end
|
79
91
|
if !value_found
|
80
92
|
if option_type['required']
|
81
|
-
print Term::ANSIColor.red, "\nMissing Required Option\n\n"
|
82
|
-
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] -
|
93
|
+
print Term::ANSIColor.red, "\nMissing Required Option\n\n", Term::ANSIColor.reset
|
94
|
+
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
|
83
95
|
print "\n"
|
84
96
|
exit 1
|
85
97
|
else
|
@@ -190,25 +202,41 @@ module Morpheus
|
|
190
202
|
return value
|
191
203
|
end
|
192
204
|
|
193
|
-
def self.select_prompt(option_type,api_client, api_params={}, no_prompt=false)
|
205
|
+
def self.select_prompt(option_type,api_client, api_params={}, no_prompt=false, use_value=nil)
|
194
206
|
value_found = false
|
195
207
|
value = nil
|
208
|
+
# local array of options
|
196
209
|
if option_type['selectOptions']
|
197
210
|
select_options = option_type['selectOptions']
|
211
|
+
# remote optionSource aka /api/options/$optionSource?
|
198
212
|
elsif option_type['optionSource']
|
199
213
|
select_options = load_source_options(option_type['optionSource'],api_client,api_params)
|
200
214
|
else
|
201
215
|
raise "select_prompt() requires selectOptions or optionSource!"
|
202
216
|
end
|
203
|
-
|
217
|
+
# ensure the preselected value (passed as an option) is in the dropdown
|
218
|
+
if !use_value.nil?
|
219
|
+
matched_value = select_options.find {|opt| opt['value'].to_s == use_value.to_s }
|
220
|
+
if !matched_value.nil?
|
221
|
+
value = use_value
|
222
|
+
value_found = true
|
223
|
+
else
|
224
|
+
print Term::ANSIColor.red, "\nInvalid Option #{option_type['fieldLabel']}: [#{use_value}]\n\n", Term::ANSIColor.reset
|
225
|
+
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
|
226
|
+
display_select_options(select_options)
|
227
|
+
print "\n"
|
228
|
+
exit 1
|
229
|
+
end
|
230
|
+
elsif !select_options.nil? && select_options.count == 1 && option_type['skipSingleOption'] == true
|
204
231
|
value_found = true
|
205
232
|
value = select_options[0]['value']
|
206
233
|
end
|
234
|
+
|
207
235
|
if no_prompt
|
208
236
|
if !value_found
|
209
237
|
if option_type['required']
|
210
|
-
print Term::ANSIColor.red, "\nMissing Required Option\n\n"
|
211
|
-
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] -
|
238
|
+
print Term::ANSIColor.red, "\nMissing Required Option\n\n", Term::ANSIColor.reset
|
239
|
+
print Term::ANSIColor.red, " * #{option_type['fieldLabel']} [-O #{option_type['fieldContext'] ? (option_type['fieldContext']+'.') : ''}#{option_type['fieldName']}=] - #{option_type['description']}\n", Term::ANSIColor.reset
|
212
240
|
display_select_options(select_options)
|
213
241
|
print "\n"
|
214
242
|
exit 1
|
@@ -369,7 +397,6 @@ module Morpheus
|
|
369
397
|
select_options.each do |option|
|
370
398
|
puts " * #{option['name']} [#{option['value']}]"
|
371
399
|
end
|
372
|
-
puts "\n\n"
|
373
400
|
end
|
374
401
|
|
375
402
|
def self.format_option_types_help(option_types)
|
data/lib/morpheus/cli/remote.rb
CHANGED
@@ -475,8 +475,12 @@ class Morpheus::Cli::Remote
|
|
475
475
|
end
|
476
476
|
|
477
477
|
def save_appliances(new_config)
|
478
|
-
|
479
|
-
|
478
|
+
fn = appliances_file_path
|
479
|
+
if !Dir.exists?(File.dirname(fn))
|
480
|
+
FileUtils.mkdir_p(File.dirname(fn))
|
481
|
+
end
|
482
|
+
File.open(fn, 'w') {|f| f.write new_config.to_yaml } #Store
|
483
|
+
FileUtils.chmod(0600, fn)
|
480
484
|
#@@appliance_config = load_appliance_file
|
481
485
|
@@appliance_config = new_config
|
482
486
|
end
|
data/lib/morpheus/cli/shell.rb
CHANGED
@@ -119,14 +119,14 @@ class Morpheus::Cli::Shell
|
|
119
119
|
execute_command(cmd)
|
120
120
|
end
|
121
121
|
# skip logging of exit and !cmd
|
122
|
-
unless input.strip.empty? || (["exit"].include?(input.strip)) || input.strip[0].to_s.chr == "!"
|
122
|
+
unless input.strip.empty? || (["exit", "history"].include?(input.strip)) || input.strip[0].to_s.chr == "!"
|
123
123
|
log_history_command(input.strip)
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
127
|
def execute_command(input)
|
128
128
|
#puts "shell execute_command(#{input})"
|
129
|
-
@command_options
|
129
|
+
@command_options ||= {}
|
130
130
|
|
131
131
|
input = input.to_s.strip
|
132
132
|
|
@@ -213,29 +213,35 @@ class Morpheus::Cli::Shell
|
|
213
213
|
elsif input =~ /^\!.+/
|
214
214
|
cmd_number = input.sub("!", "").to_i
|
215
215
|
if cmd_number != 0
|
216
|
-
|
217
|
-
if !
|
216
|
+
old_input = @history[cmd_number]
|
217
|
+
if !old_input
|
218
218
|
puts "Command not found by number #{cmd_number}"
|
219
219
|
return 0
|
220
220
|
end
|
221
|
-
#puts "executing history command: (#{cmd_number}) #{
|
222
|
-
|
223
|
-
|
221
|
+
#puts "executing history command: (#{cmd_number}) #{old_input}"
|
222
|
+
# log_history_command(old_input)
|
223
|
+
# remove this from readline, and replace it with the old command
|
224
|
+
Readline::HISTORY.pop
|
225
|
+
Readline::HISTORY << old_input
|
226
|
+
return execute_commands(old_input)
|
224
227
|
end
|
225
228
|
|
226
229
|
elsif input == "insecure"
|
227
230
|
Morpheus::RestClient.enable_ssl_verification = false
|
228
231
|
return 0
|
232
|
+
|
229
233
|
# use log-level [debug|info]
|
230
234
|
# elsif input =~ /^log_level/ # hidden for now
|
231
235
|
# log_level = input.sub(/^log_level\s*/, '').strip
|
232
236
|
# if log_level == ""
|
233
237
|
# puts "#{Morpheus::Logging.log_level}"
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
238
|
+
elsif input == "debug"
|
239
|
+
log_history_command(input)
|
240
|
+
Morpheus::Cli::LogLevelCommand.new.handle(["debug"])
|
241
|
+
@command_options[:debug] = true
|
242
|
+
return 0
|
243
|
+
# Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
|
244
|
+
# ::RestClient.log = Morpheus::Logging.debug? ? STDOUT : nil
|
239
245
|
# elsif log_level == "info"
|
240
246
|
# #log_history_command(input)
|
241
247
|
# @command_options.delete(:debug)
|
@@ -258,7 +264,7 @@ class Morpheus::Cli::Shell
|
|
258
264
|
# return 0
|
259
265
|
elsif ["hello","hi","hey","hola"].include?(input.strip.downcase)
|
260
266
|
print "#{input.capitalize}, how may I #{cyan}help#{reset} you?\n"
|
261
|
-
return
|
267
|
+
return 0
|
262
268
|
# use morpheus coloring [on|off]
|
263
269
|
# elsif input == "colorize"
|
264
270
|
# Term::ANSIColor::coloring = true
|
data/lib/morpheus/cli/version.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Provide deep_merge.
|
2
|
+
# Borrowed from rails active_support
|
3
|
+
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
|
4
|
+
#
|
5
|
+
class Hash
|
6
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
7
|
+
#
|
8
|
+
# h1 = { a: true, b: { c: [1, 2, 3] } }
|
9
|
+
# h2 = { a: false, b: { x: [3, 4, 5] } }
|
10
|
+
#
|
11
|
+
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
12
|
+
#
|
13
|
+
# Like with Hash#merge in the standard library, a block can be provided
|
14
|
+
# to merge values:
|
15
|
+
#
|
16
|
+
# h1 = { a: 100, b: 200, c: { c1: 100 } }
|
17
|
+
# h2 = { b: 250, c: { c1: 200 } }
|
18
|
+
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
|
19
|
+
# # => { a: 100, b: 450, c: { c1: 300 } }
|
20
|
+
def deep_merge(other_hash, &block)
|
21
|
+
dup.deep_merge!(other_hash, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Same as +deep_merge+, but modifies +self+.
|
25
|
+
def deep_merge!(other_hash, &block)
|
26
|
+
other_hash.each_pair do |current_key, other_value|
|
27
|
+
this_value = self[current_key]
|
28
|
+
|
29
|
+
self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
|
30
|
+
this_value.deep_merge(other_value, &block)
|
31
|
+
else
|
32
|
+
if block_given? && key?(current_key)
|
33
|
+
block.call(current_key, this_value, other_value)
|
34
|
+
else
|
35
|
+
other_value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
end
|
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: 2.10.
|
4
|
+
version: 2.10.3
|
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: 2017-03-
|
14
|
+
date: 2017-03-14 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -218,6 +218,7 @@ files:
|
|
218
218
|
- lib/morpheus/cli/virtual_images.rb
|
219
219
|
- lib/morpheus/cli/whoami.rb
|
220
220
|
- lib/morpheus/cli/workflows.rb
|
221
|
+
- lib/morpheus/ext/hash.rb
|
221
222
|
- lib/morpheus/ext/nil_class.rb
|
222
223
|
- lib/morpheus/formatters.rb
|
223
224
|
- lib/morpheus/logging.rb
|