morpheus-cli 2.10.2 → 2.10.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/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
|