collins_shell 0.2.14
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.
- data/.pryrc +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +59 -0
- data/README.md +335 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/bin/collins-shell +36 -0
- data/collins_shell.gemspec +95 -0
- data/lib/collins_shell.rb +3 -0
- data/lib/collins_shell/asset.rb +198 -0
- data/lib/collins_shell/cli.rb +185 -0
- data/lib/collins_shell/console.rb +129 -0
- data/lib/collins_shell/console/asset.rb +127 -0
- data/lib/collins_shell/console/cache.rb +17 -0
- data/lib/collins_shell/console/command_helpers.rb +131 -0
- data/lib/collins_shell/console/commands.rb +28 -0
- data/lib/collins_shell/console/commands/cat.rb +123 -0
- data/lib/collins_shell/console/commands/cd.rb +61 -0
- data/lib/collins_shell/console/commands/io.rb +26 -0
- data/lib/collins_shell/console/commands/iterators.rb +190 -0
- data/lib/collins_shell/console/commands/tail.rb +178 -0
- data/lib/collins_shell/console/commands/versions.rb +42 -0
- data/lib/collins_shell/console/filesystem.rb +121 -0
- data/lib/collins_shell/console/options_helpers.rb +8 -0
- data/lib/collins_shell/errors.rb +7 -0
- data/lib/collins_shell/ip_address.rb +144 -0
- data/lib/collins_shell/ipmi.rb +67 -0
- data/lib/collins_shell/monkeypatch.rb +60 -0
- data/lib/collins_shell/provision.rb +152 -0
- data/lib/collins_shell/state.rb +98 -0
- data/lib/collins_shell/tag.rb +41 -0
- data/lib/collins_shell/thor.rb +209 -0
- data/lib/collins_shell/util.rb +120 -0
- data/lib/collins_shell/util/asset_printer.rb +265 -0
- data/lib/collins_shell/util/asset_stache.rb +32 -0
- data/lib/collins_shell/util/log_printer.rb +187 -0
- data/lib/collins_shell/util/printer_util.rb +28 -0
- metadata +200 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'collins_shell/thor'
|
2
|
+
require 'collins_shell/util'
|
3
|
+
require 'thor'
|
4
|
+
require 'thor/group'
|
5
|
+
require 'terminal-table'
|
6
|
+
|
7
|
+
module CollinsShell
|
8
|
+
|
9
|
+
class Provision < Thor
|
10
|
+
include ThorHelper
|
11
|
+
include CollinsShell::Util
|
12
|
+
|
13
|
+
desc 'list', 'list available provisioning profiles'
|
14
|
+
use_collins_options
|
15
|
+
def list
|
16
|
+
table = Terminal::Table.new
|
17
|
+
table.title = set_color("Provisioning Profiles", :bold, :magenta)
|
18
|
+
table << [
|
19
|
+
"Profile", "Label", "Prefix", "Pool", split("Primary Role"), split("Secondary Role"),
|
20
|
+
split("Suffix Allowed?"), split("Requires Primary Role?"),
|
21
|
+
split("Requires Secondary Role?"), split("Requires Pool?")
|
22
|
+
]
|
23
|
+
table << :separator
|
24
|
+
data = call_collins get_collins_client, '/api/provision/profiles' do |client|
|
25
|
+
profs = client.provisioning_profiles
|
26
|
+
last = profs.size - 1
|
27
|
+
profs.each_with_index do |profile, idx|
|
28
|
+
table << [
|
29
|
+
profile.profile, split(profile.label), profile.prefix, optional_string(profile.pool),
|
30
|
+
optional_string(profile.primary_role), optional_string(profile.secondary_role),
|
31
|
+
centered(profile.suffix_allowed?), centered(profile.requires_primary_role?),
|
32
|
+
centered(profile.requires_secondary_role?), centered(profile.requires_pool?)
|
33
|
+
]
|
34
|
+
if idx != last && too_wide? then
|
35
|
+
table << :separator
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
puts table
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'host TAG PROFILE CONTACT', 'provision host with asset tag TAG as PROFILE, and then contact CONTACT'
|
43
|
+
long_desc <<-D
|
44
|
+
Provision the host specified by the TAG argument as a PROFILE.
|
45
|
+
|
46
|
+
PROFILE must be one of the profiles found by doing a `collins-shell provision list`
|
47
|
+
|
48
|
+
CONTACT should be your hipchat username, or the username part of your email address.
|
49
|
+
|
50
|
+
This task may take up to 90 seconds to return.
|
51
|
+
D
|
52
|
+
use_collins_options
|
53
|
+
method_option :activate, :type => :boolean, :desc => 'Activate a server', :hide => true
|
54
|
+
method_option :confirm, :type => :boolean, :default => :true, :desc => 'Require confirmation. Defaults to true'
|
55
|
+
method_option :exec, :type => :string, :desc => 'Execute a command using the data from this asset. Use {{hostname}}, {{ipmi.password}}, etc for substitution'
|
56
|
+
method_option :pool, :type => :string, :desc => 'Pool for host'
|
57
|
+
method_option :primary_role, :type => :string, :desc => 'Primary role for host'
|
58
|
+
method_option :secondary_role, :type => :string, :desc => 'Secondary role for host'
|
59
|
+
method_option :suffix, :type => :string, :desc => 'Suffix to use for hostname'
|
60
|
+
method_option :verify, :type => :boolean, :default => :true, :desc => 'Verify arguments locally first'
|
61
|
+
def host tag, profile, contact
|
62
|
+
verify_profile(profile) if options.verify
|
63
|
+
config = get_collins_config
|
64
|
+
if config[:timeout] < 180 then
|
65
|
+
cclient = get_collins_client :timeout => 180
|
66
|
+
else
|
67
|
+
cclient = get_collins_client
|
68
|
+
end
|
69
|
+
asset = asset_get tag, options
|
70
|
+
if options.confirm then
|
71
|
+
printer = CollinsShell::AssetPrinter.new asset, self, :detailed => false
|
72
|
+
puts printer
|
73
|
+
require_yes "You are about to provision asset #{tag} as a #{profile}. ARE YOU SURE?", :red
|
74
|
+
end
|
75
|
+
progress_printer = Thread.new {
|
76
|
+
loop {
|
77
|
+
print "."
|
78
|
+
sleep(1)
|
79
|
+
}
|
80
|
+
}
|
81
|
+
status = call_collins cclient, "provision host" do |client|
|
82
|
+
say_status("starting", "Provisioning has started", :white)
|
83
|
+
client.provision tag, profile, contact, :activate => options.activate,
|
84
|
+
:pool => options.pool,
|
85
|
+
:primary_role => options.primary_role,
|
86
|
+
:secondary_role => options.secondary_role,
|
87
|
+
:suffix => options.suffix
|
88
|
+
end
|
89
|
+
progress_printer.terminate
|
90
|
+
puts()
|
91
|
+
if status then
|
92
|
+
say_success("Successfully provisioned asset")
|
93
|
+
asset = asset_get tag, options
|
94
|
+
printer = CollinsShell::AssetPrinter.new asset, self, :detailed => false
|
95
|
+
puts printer
|
96
|
+
asset_exec asset, options.exec, options.confirm
|
97
|
+
else
|
98
|
+
say_error("Failed to provision asset")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
no_tasks do
|
103
|
+
def too_wide?
|
104
|
+
terminal_width < 150
|
105
|
+
end
|
106
|
+
|
107
|
+
def split value
|
108
|
+
if too_wide? then
|
109
|
+
value.split(' ').join("\n")
|
110
|
+
else
|
111
|
+
value
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def verify_value pname, name, user_specified, profile_exists, profile_requires, profile_provides
|
116
|
+
if user_specified then
|
117
|
+
require_that(!profile_exists, "#{name} is not user configurable for '#{pname}'")
|
118
|
+
else
|
119
|
+
require_that(!profile_requires || profile_provides, "#{name} is required for '#{pname}'")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def verify_profile pname
|
124
|
+
profiles = call_collins get_collins_client, '/api/provision/profiles' do |client|
|
125
|
+
client.provisioning_profiles
|
126
|
+
end
|
127
|
+
profile = profiles.select{|p| p.profile.downcase == pname.to_s.downcase}.first
|
128
|
+
require_non_empty(profile, "No such profile '#{pname}', try collins-shell provision list")
|
129
|
+
if options.suffix? then
|
130
|
+
require_that(profile.suffix_allowed?, "Suffix not allowed for '#{pname}'")
|
131
|
+
end
|
132
|
+
verify_value pname, "Pool", options.pool?, profile.pool?, profile.requires_pool?, profile.pool
|
133
|
+
verify_value pname, "Secondary role", options.secondary_role?, profile.secondary_role?, profile.requires_secondary_role?, profile.secondary_role
|
134
|
+
verify_value pname, "Primary role", options.primary_role?, profile.primary_role?, profile.requires_primary_role?, profile.primary_role
|
135
|
+
end
|
136
|
+
|
137
|
+
def centered value
|
138
|
+
{:alignment => :center, :value => value}
|
139
|
+
end
|
140
|
+
|
141
|
+
def optional_string value, default = 'Configurable'
|
142
|
+
if value.nil? || value.empty? then
|
143
|
+
default
|
144
|
+
else
|
145
|
+
value
|
146
|
+
end
|
147
|
+
end # optional_string
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'collins_shell/thor'
|
2
|
+
require 'collins_shell/util'
|
3
|
+
require 'thor'
|
4
|
+
require 'thor/group'
|
5
|
+
|
6
|
+
module CollinsShell
|
7
|
+
|
8
|
+
class State < Thor
|
9
|
+
include ThorHelper
|
10
|
+
include CollinsShell::Util
|
11
|
+
namespace :state
|
12
|
+
|
13
|
+
def self.banner task, namespace = true, subcommand = false
|
14
|
+
"#{basename} #{task.formatted_usage(self, true, subcommand).gsub(':',' ')}"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'create', 'Create a new state'
|
18
|
+
use_collins_options
|
19
|
+
method_option :name, :type => :string, :required => true, :desc => 'Name of state. Must be all caps and unique. Can contain numbers, letters and underscores.'
|
20
|
+
method_option :label, :type => :string, :required => true, :desc => 'A friendly (short) description of the state to use in visual labels. Usually just a camel case version of the name, possibly with spaces.'
|
21
|
+
method_option :description, :type => :string, :required => true, :desc => 'A longer description of the state'
|
22
|
+
method_option :status, :type => :string, :required => false, :desc => 'Optional status to bind the state to'
|
23
|
+
def create
|
24
|
+
name = options.name.upcase
|
25
|
+
label = options.label
|
26
|
+
desc = options.description
|
27
|
+
status = options.status
|
28
|
+
call_collins get_collins_client, "state_create!" do |client|
|
29
|
+
if client.state_create!(name, label, desc, status) then
|
30
|
+
say_success "Successfully created state '#{name}'"
|
31
|
+
else
|
32
|
+
say_error "Failed creating state '#{name}'"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'delete STATE', 'Delete a state'
|
38
|
+
use_collins_options
|
39
|
+
def delete state
|
40
|
+
call_collins get_collins_client, "state_delete!" do |client|
|
41
|
+
if client.state_delete!(state) then
|
42
|
+
say_success "Successfully deleted state '#{state}'"
|
43
|
+
else
|
44
|
+
say_error "Failed deleting state '#{state}'"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'get STATE', 'Get a state by name'
|
50
|
+
use_collins_options
|
51
|
+
def get state
|
52
|
+
call_collins get_collins_client, "state_get" do |client|
|
53
|
+
header = [["Name", "Label", "Status", "Description"]]
|
54
|
+
state = client.state_get(state)
|
55
|
+
table = header + [[state.name, state.label, (state.status.name || ""), state.description]]
|
56
|
+
print_table table
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc 'list', 'list states that are available'
|
61
|
+
use_collins_options
|
62
|
+
def list
|
63
|
+
call_collins get_collins_client, "state_get_all" do |client|
|
64
|
+
header = [["Name", "Label", "Status", "Description"]]
|
65
|
+
states = header + client.state_get_all.map do |state|
|
66
|
+
[state.name, state.label, (state.status.name || ""), state.description]
|
67
|
+
end
|
68
|
+
print_table states
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
desc 'update STATE', 'Update the name, label, description or status binding of a state'
|
73
|
+
use_collins_options
|
74
|
+
method_option :name, :type => :string, :required => false, :desc => 'New name of state. Must be all caps and unique. Can contains numbers, letters, and underscores.'
|
75
|
+
method_option :label, :type => :string, :required => false, :desc => 'A friendly (short) description of the state to use in visual labels. Usually just a camel case version of the name, possibly with spaces.'
|
76
|
+
method_option :description, :type => :string, :required => false, :desc => 'A longer description of the state'
|
77
|
+
method_option :status, :type => :string, :required => false, :desc => 'Optional status to bind the state to'
|
78
|
+
def update state
|
79
|
+
name = options.name.upcase if options.name?
|
80
|
+
label = options.label if options.label?
|
81
|
+
desc = options.description if options.description?
|
82
|
+
status = options.status if options.status?
|
83
|
+
call_collins get_collins_client, "state_update!" do |client|
|
84
|
+
opts = {
|
85
|
+
:name => name, :label => label, :status => status,
|
86
|
+
:description => desc
|
87
|
+
}
|
88
|
+
if client.state_update!(state, opts) then
|
89
|
+
say_success "Successfully updated state '#{state}'"
|
90
|
+
else
|
91
|
+
say_error "Failed creating state '#{state}'"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'collins_shell/thor'
|
2
|
+
require 'collins_shell/util'
|
3
|
+
require 'thor'
|
4
|
+
require 'thor/group'
|
5
|
+
|
6
|
+
module CollinsShell
|
7
|
+
|
8
|
+
class Tag < Thor
|
9
|
+
|
10
|
+
include ThorHelper
|
11
|
+
include CollinsShell::Util
|
12
|
+
namespace :tag
|
13
|
+
|
14
|
+
def self.banner task, namespace = true, subcommand = false
|
15
|
+
"#{basename} #{task.formatted_usage(self, true, subcommand).gsub(':',' ')}"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'list', 'list tags that are in use'
|
19
|
+
use_collins_options
|
20
|
+
def list
|
21
|
+
call_collins get_collins_client, "list" do |client|
|
22
|
+
header = [["Name", "Label", "Description"]]
|
23
|
+
tags = header + client.get_all_tags.map do |tag|
|
24
|
+
[tag.name, tag.label, tag.description]
|
25
|
+
end
|
26
|
+
print_table tags
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'values TAG', 'list all values for the specified tag'
|
31
|
+
use_collins_options
|
32
|
+
def values tag
|
33
|
+
call_collins get_collins_client, "values" do |client|
|
34
|
+
client.get_tag_values(tag).sort.each do |value|
|
35
|
+
puts(value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'collins_client'
|
2
|
+
require 'highline'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module CollinsShell
|
6
|
+
module ThorHelper
|
7
|
+
|
8
|
+
include Collins::Util
|
9
|
+
|
10
|
+
COLLINS_OPTIONS = {
|
11
|
+
:config => {:type => :string, :desc => 'YAML configuration file'},
|
12
|
+
:debug => {:type => :boolean, :default => false, :desc => 'Debug output'},
|
13
|
+
:host => {:type => :string, :desc => 'Collins host (e.g. http://host:port)'},
|
14
|
+
:password => {:type => :string, :desc => 'Collins password'},
|
15
|
+
:quiet => {:type => :boolean, :default => false, :desc => 'Be quiet when appropriate'},
|
16
|
+
:timeout => {:type => :numeric, :default => 30, :desc => 'Collins client timeout'},
|
17
|
+
:username => {:type => :string, :desc => 'Collins username'}
|
18
|
+
}
|
19
|
+
|
20
|
+
PAGE_OPTIONS = {
|
21
|
+
:page => {:type => :numeric, :default => 0, :desc => 'Page of results set.'},
|
22
|
+
:size => {:type => :numeric, :default => 20, :desc => 'Number of results to return.'},
|
23
|
+
:sort => {:type => :string, :default => 'DESC', :desc => 'Sort direction. ASC or DESC'}
|
24
|
+
}
|
25
|
+
|
26
|
+
def self.included(base)
|
27
|
+
base.extend(ThorHelper)
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
attr_accessor :password
|
32
|
+
end
|
33
|
+
|
34
|
+
def use_collins_options
|
35
|
+
COLLINS_OPTIONS.each do |name, options|
|
36
|
+
method_option name, options
|
37
|
+
end
|
38
|
+
end
|
39
|
+
def use_page_options default_size = 20
|
40
|
+
PAGE_OPTIONS.each do |name, options|
|
41
|
+
options.update(:default => default_size) if name == :size
|
42
|
+
method_option name, options
|
43
|
+
end
|
44
|
+
end
|
45
|
+
def use_tag_option required = false
|
46
|
+
method_option :tag, :type => :string, :required => required, :desc => 'Tag for asset'
|
47
|
+
end
|
48
|
+
def use_selector_option required = false
|
49
|
+
method_option :selector, :type => :hash, :required => required, :desc => 'Selector to query collins. Takes the form of --selector=key1:val1 key2:val2 etc'
|
50
|
+
method_option :remote, :type => :boolean, :default => false, :desc => 'Search all collins instances, including remote ones'
|
51
|
+
end
|
52
|
+
|
53
|
+
def selector_or_tag
|
54
|
+
if options.selector? then
|
55
|
+
options.selector
|
56
|
+
elsif options.tag? then
|
57
|
+
{:tag => options.tag}
|
58
|
+
else
|
59
|
+
say_error "Either tag or selector must be specified", :exit => true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def require_yes message, color = nil, should_exit = true
|
64
|
+
highline = HighLine.new
|
65
|
+
colored_message = set_color(message, color)
|
66
|
+
answer = ask(colored_message)
|
67
|
+
if answer.downcase.strip !~ /^yes$/ then
|
68
|
+
if should_exit then
|
69
|
+
exit(0)
|
70
|
+
else
|
71
|
+
false
|
72
|
+
end
|
73
|
+
else
|
74
|
+
true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def batch_selector_operation options = {}, &block
|
79
|
+
confirmation_message = options[:confirmation_message]
|
80
|
+
success_message = options[:success_message]
|
81
|
+
error_message = options[:error_message]
|
82
|
+
operation = options[:operation]
|
83
|
+
require_non_empty(confirmation_message, "confirmation_message option not set")
|
84
|
+
require_non_empty(success_message, "success_message not set")
|
85
|
+
require_non_empty(error_message, "error_message not set")
|
86
|
+
require_non_empty(operation, "operation not set")
|
87
|
+
selector = get_selector selector_or_tag, [], nil, options[:remote]
|
88
|
+
call_collins get_collins_client, operation do |client|
|
89
|
+
assets = client.find selector
|
90
|
+
if assets.length > 1 then
|
91
|
+
require_yes confirmation_message.call(assets), :red
|
92
|
+
end
|
93
|
+
assets.each do |asset|
|
94
|
+
if block.call(client, asset) then
|
95
|
+
say_success success_message.call(asset)
|
96
|
+
else
|
97
|
+
say_error error_message.call(asset)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def say_error message, options = {}
|
104
|
+
if options[:exception] then
|
105
|
+
say_status("error", "#{message} - #{options[:exception]}", :red)
|
106
|
+
if options[:debug] && options[:debug] then
|
107
|
+
pp options[:exception].backtrace
|
108
|
+
end
|
109
|
+
else
|
110
|
+
say_status("error", message, :red)
|
111
|
+
end
|
112
|
+
if options[:exit].is_a?(TrueClass) then
|
113
|
+
exit(1)
|
114
|
+
elsif not options[:exit].nil? then
|
115
|
+
exit(options[:exit])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def say_success message
|
120
|
+
say_status("success", message, :green)
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_collins_client opts = {}
|
124
|
+
config = get_collins_config.merge(opts).merge(:strict => true)
|
125
|
+
config = ensure_password opts
|
126
|
+
require_valid_collins_config config
|
127
|
+
config[:logger] = get_logger :trace => options.debug, :progname => 'collins-shell'
|
128
|
+
Collins::Client.new config
|
129
|
+
end
|
130
|
+
|
131
|
+
def ensure_password opts = {}
|
132
|
+
me = CollinsShell::ThorHelper
|
133
|
+
if me.password.nil? then
|
134
|
+
me.password = get_password(get_collins_config.merge(opts).merge(:strict => true))
|
135
|
+
end
|
136
|
+
me.password
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_password config
|
140
|
+
if
|
141
|
+
config[:password] and not
|
142
|
+
config[:password].empty? and
|
143
|
+
config[:password] != "password" then
|
144
|
+
return config
|
145
|
+
end
|
146
|
+
highline = HighLine.new
|
147
|
+
password = highline.ask("Enter your password: ") { |q| q.echo = "x" }
|
148
|
+
config.update(:password => password)
|
149
|
+
end
|
150
|
+
|
151
|
+
# --username --password --host is highest priority
|
152
|
+
# --config= second highest
|
153
|
+
# ~/.collins.yaml is lowest
|
154
|
+
def get_collins_config
|
155
|
+
def try_config_merge filename, config
|
156
|
+
file_config = collins_config_from_file filename
|
157
|
+
if file_config[:collins] then
|
158
|
+
file_config = file_config[:collins]
|
159
|
+
end
|
160
|
+
config.update(:host => file_config[:host]) unless options.host?
|
161
|
+
config.update(:username => file_config[:username]) unless options.username?
|
162
|
+
config.update(:password => file_config[:password]) unless options.password?
|
163
|
+
if options.timeout == 30 and file_config[:timeout] then
|
164
|
+
config.update(:timeout => file_config[:timeout].to_i)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
config = Hash[
|
168
|
+
:host => options.host,
|
169
|
+
:username => options.username,
|
170
|
+
:password => options.password,
|
171
|
+
:timeout => options.timeout
|
172
|
+
]
|
173
|
+
if ENV['COLLINS'] then
|
174
|
+
try_config_merge ENV['COLLINS'], config
|
175
|
+
end
|
176
|
+
if options.config? then
|
177
|
+
try_config_merge options.config, config
|
178
|
+
end
|
179
|
+
if File.exists?(File.expand_path("~/.collins.yaml")) then
|
180
|
+
user_config = collins_config_from_file "~/.collins.yaml"
|
181
|
+
if user_config[:collins] then
|
182
|
+
user_config = user_config[:collins]
|
183
|
+
end
|
184
|
+
config.update(:host => user_config[:host]) if config[:host].nil?
|
185
|
+
config.update(:username => user_config[:username]) if config[:username].nil?
|
186
|
+
config.update(:password => user_config[:password]) if config[:password].nil?
|
187
|
+
if config[:timeout] == 30 and user_config[:timeout] then
|
188
|
+
config.update(:timeout => user_config[:timeout].to_i)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
config
|
192
|
+
end
|
193
|
+
|
194
|
+
def collins_config_from_file file
|
195
|
+
symbolize_hash(YAML::load(File.open(File.expand_path(file))))
|
196
|
+
end
|
197
|
+
|
198
|
+
def require_valid_collins_config config
|
199
|
+
begin
|
200
|
+
require_non_empty(config[:host], "collins.host is required")
|
201
|
+
require_non_empty(config[:username], "collins.username is required")
|
202
|
+
require_non_empty(config[:password], "collins.password is required")
|
203
|
+
rescue Exception => e
|
204
|
+
raise CollinsShell::ConfigurationError.new(e.message)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|