consolr 1.0.1 → 1.0.2
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/.gitignore +1 -0
- data/.rspec +2 -0
- data/.versions.conf +4 -0
- data/Rakefile +8 -0
- data/bin/consolr +26 -1
- data/consolr.gemspec +6 -0
- data/lib/consolr/version.rb +1 -1
- data/lib/consolr.rb +27 -49
- data/spec/configs/collins_rspec.yml +4 -0
- data/spec/configs/consolr_rspec.yml +7 -0
- data/spec/consolr_spec.rb +133 -0
- data/spec/fixtures/assets/dangerous-allocated-tag.yml +24 -0
- data/spec/fixtures/assets/dangerous-maintenance-tag.yml +24 -0
- data/spec/fixtures/assets/safe-allocated-tag.yml +24 -0
- data/spec/fixtures/assets/safe-maintenance-tag.yml +24 -0
- data/spec/mocks/collins.rb +31 -0
- data/spec/mocks/collins_auth.rb +11 -0
- data/spec/mocks/ping.rb +10 -0
- data/spec/rspec_ipmi +19 -0
- data/spec/spec_helper.rb +31 -0
- metadata +106 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c01188d47bf7c259961f8f684016128fe3475d3b
|
4
|
+
data.tar.gz: d632fe8cb4bc31f429939bd32952ed2c7b4bdd6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 955dac9d7942799846908523f60d2a30db3e481a819c6b244178b2dd9775f1688adb183657ebda15a48300191ee07bb7d8122c529e51341f228d69008fc2622b
|
7
|
+
data.tar.gz: d734a3cad1e28620af367df53f93b5358812cb2e58ec6e708594d0d3114080f93a55634c1bdcdca8b9005d8636f8256a0c5c6935be00f223d79fa91ac6870836
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
coverage/
|
data/.rspec
ADDED
data/.versions.conf
ADDED
data/Rakefile
ADDED
data/bin/consolr
CHANGED
@@ -1,6 +1,31 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'consolr'
|
4
|
+
require 'consolr/version'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
opt_parser = OptionParser.new do |opt|
|
8
|
+
opt.banner = 'Usage: consolr [OPTIONS]'
|
9
|
+
opt.separator ''
|
10
|
+
opt.separator 'Options'
|
11
|
+
|
12
|
+
opt.on('-c', '--console', 'console into node via SOL') { options[:console] = true }
|
13
|
+
opt.on('-d', '--dangerous', 'list dangerous stuff') { options[:dangerous] = true }
|
14
|
+
opt.on('-f', '--force', 'force run dangerous actions') { options[:force] = true }
|
15
|
+
opt.on('-H', '--hostname ASSET', 'asset hostname') { |hostname| options[:hostname] = hostname }
|
16
|
+
opt.on('-i', '--identify', 'turn on chassis UID') { options[:identify] = true }
|
17
|
+
opt.on('-k', '--kick', 'kick if someone is hogging the console') { options[:kick] = true }
|
18
|
+
opt.on('-l', '--log LOG', 'System Event Log (SEL) [list|clear]') { |log| options[:log] = log }
|
19
|
+
opt.on('-o', '--on', 'turn on node') { options[:on] = true }
|
20
|
+
opt.on('-r', '--reboot', 'restart node') { options[:reboot] = true }
|
21
|
+
opt.on('-s', '--sdr', 'Sensor Data Repository (SDR)') { options[:sdr] = true }
|
22
|
+
opt.on('-t', '--tag ASSET', 'asset tag') { |tag| options[:tag] = tag }
|
23
|
+
opt.on('-x', '--off', 'turn off node') { options[:off] = true }
|
24
|
+
|
25
|
+
opt.on_tail('-h', '--help', 'help') { puts opt; exit 0 }
|
26
|
+
opt.on_tail('-v', '--version', 'version') { puts Consolr::VERSION; exit 0 }
|
27
|
+
end
|
28
|
+
opt_parser.parse!
|
4
29
|
|
5
30
|
console = Consolr::Console.new
|
6
|
-
console.start
|
31
|
+
console.start options
|
data/consolr.gemspec
CHANGED
@@ -19,4 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "collins_auth", "~> 0.1.2"
|
22
|
+
spec.add_runtime_dependency "net-ping", "~> 1.7.7"
|
23
|
+
|
24
|
+
spec.add_development_dependency "rake", "~> 10.4.2"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.3.0"
|
26
|
+
spec.add_development_dependency "simplecov", "~> 0.10.0"
|
27
|
+
spec.add_development_dependency "webmock", "~> 1.21.0"
|
22
28
|
end
|
data/lib/consolr/version.rb
CHANGED
data/lib/consolr.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
$LOAD_PATH.unshift('./lib/')
|
2
2
|
|
3
|
+
require 'consolr/version'
|
3
4
|
require 'collins_auth'
|
5
|
+
require 'net/ping'
|
4
6
|
require 'optparse'
|
5
7
|
require 'yaml'
|
6
|
-
require 'consolr/version'
|
7
8
|
|
8
9
|
module Consolr
|
9
10
|
class Console
|
@@ -35,7 +36,7 @@ module Consolr
|
|
35
36
|
puts "------"
|
36
37
|
exit 1
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
begin
|
40
41
|
@ipmitool_exec = config_params['ipmitool'] # ipmitool absolute path
|
41
42
|
rescue Exception => e
|
@@ -45,7 +46,7 @@ module Consolr
|
|
45
46
|
puts "-------"
|
46
47
|
exit 1
|
47
48
|
end
|
48
|
-
|
49
|
+
|
49
50
|
# Will be ignored for dangerous actions, no matter what, even with --force
|
50
51
|
begin
|
51
52
|
@dangerous_assets = config_params['dangerous_assets']
|
@@ -72,50 +73,22 @@ module Consolr
|
|
72
73
|
end
|
73
74
|
|
74
75
|
@dangerous_actions = [:off, :reboot] # Must match the symbol in options{}
|
75
|
-
|
76
|
-
@options = {}
|
77
|
-
@opt_parser = OptionParser.new do |opt|
|
78
|
-
opt.banner = 'Usage: consolr [OPTIONS]'
|
79
|
-
opt.separator ''
|
80
|
-
opt.separator 'Options'
|
81
|
-
|
82
|
-
opt.on('-c', '--console', 'console into node via SOL') { options[:console] = true }
|
83
|
-
opt.on('-d', '--dangerous', 'list dangerous stuff') { options[:dangerous] = true }
|
84
|
-
opt.on('-f', '--force', 'force run dangerous actions') { options[:force] = true }
|
85
|
-
opt.on('-H', '--hostname ASSET', 'asset hostname') { |hostname| options[:hostname] = hostname }
|
86
|
-
opt.on('-i', '--identify', 'turn on chassis UID') { options[:identify] = true }
|
87
|
-
opt.on('-k', '--kick', 'kick if someone is hogging the console') { options[:kick] = true }
|
88
|
-
opt.on('-l', '--log LOG', 'System Event Log (SEL) [list|clear]') { |log| options[:log] = log }
|
89
|
-
opt.on('-o', '--on', 'turn on node') { options[:on] = true }
|
90
|
-
opt.on('-r', '--reboot', 'restart node') { options[:reboot] = true }
|
91
|
-
opt.on('-s', '--sdr', 'Sensor Data Repository (SDR)') { options[:sdr] = true }
|
92
|
-
opt.on('-t', '--tag ASSET', 'asset tag') { |tag| options[:tag] = tag }
|
93
|
-
opt.on('-x', '--off', 'turn off node') { options[:off] = true }
|
94
|
-
opt.on_tail('-h', '--help', 'help') { puts opt; exit 0 }
|
95
|
-
opt.on_tail('-v', '--version', 'version') { puts Consolr::VERSION; exit 0 }
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def ipmitool_cmd action
|
100
|
-
system("#{@ipmitool_exec} -I lanplus -H #{@node.ipmi.address} -U #{@node.ipmi.username} -P #{@node.ipmi.password} #{action}")
|
101
|
-
return $?.exitstatus == 0 ? "SUCCESS" : "FAILED"
|
102
76
|
end
|
103
77
|
|
104
|
-
def start
|
105
|
-
@opt_parser.parse! # extract from ARGV[]
|
78
|
+
def start options
|
106
79
|
abort("Please pass either the asset tag or hostname") if options[:tag].nil? and options[:hostname].nil?
|
107
|
-
|
80
|
+
|
108
81
|
abort("Cannot find #{@ipmitool_exec}") unless File.exist?(@ipmitool_exec)
|
109
82
|
|
110
83
|
dangerous_body = "Dangerous actions: #{dangerous_actions.join(', ')}\n"\
|
111
84
|
"Dangerous status: #{dangerous_status.join(', ')} (override with --force)\n"\
|
112
85
|
"Dangerous assets: #{dangerous_assets.join(', ')} (ignored no matter what, even with --force)"
|
113
|
-
|
86
|
+
|
114
87
|
if options[:dangerous]
|
115
88
|
puts dangerous_body
|
116
89
|
exit 1
|
117
90
|
end
|
118
|
-
|
91
|
+
|
119
92
|
begin
|
120
93
|
collins = Collins::Authenticator.setup_client
|
121
94
|
rescue Exception => e
|
@@ -125,25 +98,24 @@ module Consolr
|
|
125
98
|
puts "-------"
|
126
99
|
exit 1
|
127
100
|
end
|
128
|
-
|
101
|
+
|
129
102
|
if options[:tag] and options[:hostname]
|
130
103
|
abort("Please pass either the hostname OR the tag but not both.")
|
131
104
|
end
|
132
|
-
|
105
|
+
|
133
106
|
# match assets like vm-67f5eh, zt-*, etc.
|
134
107
|
nodes = options[:tag] ? (collins.find :tag => options[:tag]) : (collins.find :hostname => options[:hostname])
|
135
108
|
@node = nodes.length == 1 ? nodes.first : abort("Found #{nodes.length} assets, aborting.")
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
if dangerous_assets.include?(@node.tag) and
|
141
|
-
|
109
|
+
|
110
|
+
abort("Cannot ping IP #{@node.ipmi.address} (#{@node.tag})") unless Net::Ping::External.new(@node.ipmi.address).ping?
|
111
|
+
|
112
|
+
selected_dangerous_actions = dangerous_actions.select { |o| options[o] }
|
113
|
+
if dangerous_assets.include?(@node.tag) and selected_dangerous_actions.any?
|
114
|
+
abort "Asset #{@node.tag} is a crucial asset. Can't ever execute dangerous actions on this asset.\n#{dangerous_body}"
|
142
115
|
end
|
143
|
-
|
144
|
-
if options[:force].nil? and
|
145
|
-
|
146
|
-
abort dangerous_body
|
116
|
+
|
117
|
+
if options[:force].nil? and selected_dangerous_actions.any? and dangerous_status.include?(@node.status)
|
118
|
+
abort "Cannot run dangerous commands on #{@node.hostname} (#{@node.tag} - #{@node.status}) because it is in a protected status. This can be overridden with the --force flag\n#{dangerous_body}"
|
147
119
|
end
|
148
120
|
|
149
121
|
case
|
@@ -171,12 +143,18 @@ module Consolr
|
|
171
143
|
raise OptionParser::MissingArgument, "specify an action"
|
172
144
|
rescue OptionParser::MissingArgument => e
|
173
145
|
puts e
|
174
|
-
|
175
|
-
exit 0
|
146
|
+
exit 1
|
176
147
|
end
|
177
148
|
end
|
178
149
|
end
|
179
150
|
|
151
|
+
private
|
152
|
+
|
153
|
+
def ipmitool_cmd action
|
154
|
+
system("#{@ipmitool_exec} -I lanplus -H #{@node.ipmi.address} -U #{@node.ipmi.username} -P #{@node.ipmi.password} #{action}")
|
155
|
+
return $?.exitstatus == 0 ? "SUCCESS" : "FAILED"
|
156
|
+
end
|
157
|
+
|
180
158
|
end
|
181
159
|
|
182
160
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Consolr::Console do
|
4
|
+
|
5
|
+
before (:each) do
|
6
|
+
@console = Consolr::Console.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'fails if no hostname is provided' do
|
10
|
+
expect { @console.start( {:hostname => nil}) }.to raise_error(SystemExit, /asset tag or hostname/)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'fails if both tag and hostname are passed' do
|
14
|
+
expect { @console.start({:hostname => 'host.dc.net', :tag => '001234' }) }.to raise_error(SystemExit, /not both/)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'fails if tag cannot be found' do
|
18
|
+
expect { @console.start({:tag => 'bogus_tag'}) }.to raise_error(SystemExit, /Found 0 assets/)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'fails if hostname cannot be found' do
|
22
|
+
expect { @console.start({:hostname => 'bogus_hostname'}) }.to raise_error(SystemExit, /Found 0 assets/)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'fails if multiple hosts are found' do
|
26
|
+
expect { @console.start({:hostname => 'hostname-with-multiple-assets.dc.net'}) }.to raise_error(SystemExit, /Found \d+ assets/)
|
27
|
+
end
|
28
|
+
|
29
|
+
safe_boolean_actions = {:console => "--> Opening SOL session (type ~~. to quit)\nsol activate", :kick => 'sol deactivate', :identify => 'chassis identify', :sdr => 'sdr elist all', :on => 'power on'}
|
30
|
+
dangerous_boolean_actions = {:off => 'power off', :reboot => 'power cycle'}
|
31
|
+
|
32
|
+
describe 'safe allocated asset' do
|
33
|
+
safe_allocated_tag = 'safe-allocated-tag'
|
34
|
+
safe_boolean_actions.each do |action, response|
|
35
|
+
it "does #{action}" do
|
36
|
+
expect { @console.start({:tag => safe_allocated_tag, action => true}) }.to output("#{response}\nSUCCESS\n").to_stdout_from_any_process
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
dangerous_boolean_actions.each do |action, response|
|
41
|
+
it "refuses to do dangerous action #{action}" do
|
42
|
+
expect { @console.start({:tag => safe_allocated_tag, action => true}) }.to raise_error(SystemExit, /Cannot run dangerous command/)
|
43
|
+
end
|
44
|
+
it "can force dangerous action #{action}" do
|
45
|
+
expect { @console.start({:tag => safe_allocated_tag, action => true, :force => true}) }.to output("#{response}\nSUCCESS\n").to_stdout_from_any_process
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'does log list' do
|
50
|
+
expect { @console.start({:tag => safe_allocated_tag, :log => 'list'}) }.to output("sel list\nSUCCESS\n").to_stdout_from_any_process
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'does log clear' do
|
54
|
+
expect { @console.start({:tag => safe_allocated_tag, :log => 'clear'}) }.to output("sel clear\nSUCCESS\n").to_stdout_from_any_process
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'safe maintenance asset' do
|
59
|
+
safe_maintenance_tag= 'safe-maintenance-tag'
|
60
|
+
safe_boolean_actions.each do |action, response|
|
61
|
+
it "does #{action}" do
|
62
|
+
expect { @console.start({:tag => safe_maintenance_tag, action => true}) }.to output("#{response}\nSUCCESS\n").to_stdout_from_any_process
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
dangerous_boolean_actions.each do |action, response|
|
67
|
+
it "does dangerous action #{action}" do
|
68
|
+
expect { @console.start({:tag => safe_maintenance_tag, action => true, :force => true}) }.to output("#{response}\nSUCCESS\n").to_stdout_from_any_process
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'does log list' do
|
73
|
+
expect { @console.start({:tag => safe_maintenance_tag, :log => 'list'}) }.to output("sel list\nSUCCESS\n").to_stdout_from_any_process
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'does log clear' do
|
77
|
+
expect { @console.start({:tag => safe_maintenance_tag, :log => 'clear'}) }.to output("sel clear\nSUCCESS\n").to_stdout_from_any_process
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'dangerous allocated asset' do
|
82
|
+
dangerous_allocated_tag= 'dangerous-allocated-tag'
|
83
|
+
safe_boolean_actions.each do |action, response|
|
84
|
+
it "does #{action}" do
|
85
|
+
expect { @console.start({:tag => dangerous_allocated_tag, action => true}) }.to output("#{response}\nSUCCESS\n").to_stdout_from_any_process
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
dangerous_boolean_actions.each do |action, response|
|
90
|
+
it "refuses to do dangerous action #{action}" do
|
91
|
+
expect { @console.start({:tag => dangerous_allocated_tag, action => true}) }.to raise_error(SystemExit, /Asset .* is a crucial asset/)
|
92
|
+
end
|
93
|
+
it "refuses to do dangerous action #{action} with force" do
|
94
|
+
expect { @console.start({:tag => dangerous_allocated_tag, action => true, :force => true}) }.to raise_error(SystemExit, /Asset .* is a crucial asset/)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'does log list' do
|
99
|
+
expect { @console.start({:tag => dangerous_allocated_tag, :log => 'list'}) }.to output("sel list\nSUCCESS\n").to_stdout_from_any_process
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'does log clear' do
|
103
|
+
expect { @console.start({:tag => dangerous_allocated_tag, :log => 'clear'}) }.to output("sel clear\nSUCCESS\n").to_stdout_from_any_process
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'dangerous maintenance asset' do
|
108
|
+
dangerous_maintenance_tag= 'dangerous-maintenance-tag'
|
109
|
+
safe_boolean_actions.each do |action, response|
|
110
|
+
it "does #{action}" do
|
111
|
+
expect { @console.start({:tag => dangerous_maintenance_tag, action => true}) }.to output("#{response}\nSUCCESS\n").to_stdout_from_any_process
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
dangerous_boolean_actions.each do |action, response|
|
116
|
+
it "refuses to do dangerous action #{action}" do
|
117
|
+
expect { @console.start({:tag => dangerous_maintenance_tag, action => true}) }.to raise_error(SystemExit, /Asset .* is a crucial asset/)
|
118
|
+
end
|
119
|
+
it "refuses to do dangerous action #{action} with force" do
|
120
|
+
expect { @console.start({:tag => dangerous_maintenance_tag, action => true, :force=> true}) }.to raise_error(SystemExit, /Asset .* is a crucial asset/)
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'does log list' do
|
126
|
+
expect { @console.start({:tag => dangerous_maintenance_tag, :log => 'list'}) }.to output("sel list\nSUCCESS\n").to_stdout_from_any_process
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'does log clear' do
|
130
|
+
expect { @console.start({:tag => dangerous_maintenance_tag, :log => 'clear'}) }.to output("sel clear\nSUCCESS\n").to_stdout_from_any_process
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
--- !ruby/object:Collins::Asset
|
2
|
+
extras:
|
3
|
+
ATTRIBS:
|
4
|
+
'0':
|
5
|
+
HOSTNAME: web-dc0ce734.ewr01.tumblr.net
|
6
|
+
id: 1
|
7
|
+
status: Allocated
|
8
|
+
tag: dangerous-allocated-tag
|
9
|
+
type: SERVER_NODE
|
10
|
+
state: !ruby/object:Collins::AssetState
|
11
|
+
description: A service in this state is operational.
|
12
|
+
id: 3
|
13
|
+
label: Running
|
14
|
+
name: RUNNING
|
15
|
+
status: !ruby/object:OpenStruct
|
16
|
+
table: {}
|
17
|
+
ipmi: !ruby/object:Collins::Ipmi
|
18
|
+
address: 1.2.3.4
|
19
|
+
asset_id: 3812
|
20
|
+
gateway: 1.2.3.1
|
21
|
+
id: 2
|
22
|
+
netmask: 255.255.240.0
|
23
|
+
password: ipmi-test-tag-password
|
24
|
+
username: ipmi-test-tag-user
|
@@ -0,0 +1,24 @@
|
|
1
|
+
--- !ruby/object:Collins::Asset
|
2
|
+
extras:
|
3
|
+
ATTRIBS:
|
4
|
+
'0':
|
5
|
+
HOSTNAME: web-dc0ce734.ewr01.tumblr.net
|
6
|
+
id: 1
|
7
|
+
status: Maintenance
|
8
|
+
tag: dangerous-maintenance-tag
|
9
|
+
type: SERVER_NODE
|
10
|
+
state: !ruby/object:Collins::AssetState
|
11
|
+
description: A service in this state is operational.
|
12
|
+
id: 3
|
13
|
+
label: Running
|
14
|
+
name: RUNNING
|
15
|
+
status: !ruby/object:OpenStruct
|
16
|
+
table: {}
|
17
|
+
ipmi: !ruby/object:Collins::Ipmi
|
18
|
+
address: 1.2.3.4
|
19
|
+
asset_id: 3812
|
20
|
+
gateway: 1.2.3.1
|
21
|
+
id: 2
|
22
|
+
netmask: 255.255.240.0
|
23
|
+
password: ipmi-test-tag-password
|
24
|
+
username: ipmi-test-tag-user
|
@@ -0,0 +1,24 @@
|
|
1
|
+
--- !ruby/object:Collins::Asset
|
2
|
+
extras:
|
3
|
+
ATTRIBS:
|
4
|
+
'0':
|
5
|
+
HOSTNAME: web-dc0ce734.ewr01.tumblr.net
|
6
|
+
id: 1
|
7
|
+
status: Allocated
|
8
|
+
tag: safe-allocated-tag
|
9
|
+
type: SERVER_NODE
|
10
|
+
state: !ruby/object:Collins::AssetState
|
11
|
+
description: A service in this state is operational.
|
12
|
+
id: 3
|
13
|
+
label: Running
|
14
|
+
name: RUNNING
|
15
|
+
status: !ruby/object:OpenStruct
|
16
|
+
table: {}
|
17
|
+
ipmi: !ruby/object:Collins::Ipmi
|
18
|
+
address: 1.2.3.4
|
19
|
+
asset_id: 3812
|
20
|
+
gateway: 1.2.3.1
|
21
|
+
id: 2
|
22
|
+
netmask: 255.255.240.0
|
23
|
+
password: ipmi-test-tag-password
|
24
|
+
username: ipmi-test-tag-user
|
@@ -0,0 +1,24 @@
|
|
1
|
+
--- !ruby/object:Collins::Asset
|
2
|
+
extras:
|
3
|
+
ATTRIBS:
|
4
|
+
'0':
|
5
|
+
HOSTNAME: web-dc0ce734.ewr01.tumblr.net
|
6
|
+
id: 1
|
7
|
+
status: Maintenance
|
8
|
+
tag: safe-maintenance-tag
|
9
|
+
type: SERVER_NODE
|
10
|
+
state: !ruby/object:Collins::AssetState
|
11
|
+
description: A service in this state is operational.
|
12
|
+
id: 3
|
13
|
+
label: Running
|
14
|
+
name: RUNNING
|
15
|
+
status: !ruby/object:OpenStruct
|
16
|
+
table: {}
|
17
|
+
ipmi: !ruby/object:Collins::Ipmi
|
18
|
+
address: 1.2.3.4
|
19
|
+
asset_id: 3812
|
20
|
+
gateway: 1.2.3.1
|
21
|
+
id: 2
|
22
|
+
netmask: 255.255.240.0
|
23
|
+
password: ipmi-test-tag-password
|
24
|
+
username: ipmi-test-tag-user
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MockCollinsMixin
|
2
|
+
require 'collins_client'
|
3
|
+
|
4
|
+
def test_assets
|
5
|
+
Dir.glob('spec/fixtures/assets/*.yml').map do |f|
|
6
|
+
YAML.load(File.read(f))
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_test_asset tag
|
11
|
+
test_assets.select { |a| a.tag == tag }
|
12
|
+
end
|
13
|
+
|
14
|
+
def mock_collins
|
15
|
+
allow_any_instance_of(Collins::Client).to receive(:find).
|
16
|
+
with(Hash).
|
17
|
+
and_return([])
|
18
|
+
|
19
|
+
allow_any_instance_of(Collins::Client).to receive(:find).
|
20
|
+
with(hash_including(:hostname => 'hostname-with-multiple-assets.dc.net')).
|
21
|
+
and_return(['asset1', 'asset2'])
|
22
|
+
|
23
|
+
|
24
|
+
['safe-allocated-tag', 'safe-maintenance-tag', 'dangerous-allocated-tag', 'dangerous-maintenance-tag'].each do |tag|
|
25
|
+
allow_any_instance_of(Collins::Client).to receive(:find).
|
26
|
+
with(hash_including(:tag => tag)).
|
27
|
+
and_return(get_test_asset(tag))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/spec/mocks/ping.rb
ADDED
data/spec/rspec_ipmi
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# mock impitool script
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: example.rb [options]"
|
9
|
+
|
10
|
+
# compatibility arguments that are ignored
|
11
|
+
opts.on("-I", "--interface [INTERFACE]", "compatibility with real tool. Ignored")
|
12
|
+
opts.on("-H", "--hostname [HOSTNAME]", "compatibility with real tool. Ignored")
|
13
|
+
opts.on("-U", "--user [USERNAME]", "compatibility with real tool. Ignored")
|
14
|
+
opts.on("-P", "--password [PASSWORD]", "compatibility with real tool. Ignored")
|
15
|
+
end.parse!
|
16
|
+
|
17
|
+
# ARGV options is the action to take
|
18
|
+
# for testing, just return the action taken
|
19
|
+
puts ARGV.join(' ')
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter "/spec/"
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'consolr'
|
7
|
+
|
8
|
+
# require our mocks
|
9
|
+
require 'mocks/collins_auth'
|
10
|
+
require 'mocks/collins'
|
11
|
+
require 'mocks/ping'
|
12
|
+
require 'webmock/rspec'
|
13
|
+
|
14
|
+
WebMock.disable_net_connect!()
|
15
|
+
|
16
|
+
# make sure we use the rspec config file
|
17
|
+
ENV['CONSOLR_CONFIG'] = "#{File.dirname(__FILE__)}/configs/consolr_rspec.yml"
|
18
|
+
ENV['COLLINS_CLIENT_CONFIG'] = "#{File.dirname(__FILE__)}/configs/collins_rspec.yml"
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.include MockCollinsAuthMixin
|
22
|
+
config.include MockCollinsMixin
|
23
|
+
config.include MockPingMixin
|
24
|
+
|
25
|
+
config.before(:example) do |example|
|
26
|
+
mock_collins_auth
|
27
|
+
mock_collins
|
28
|
+
mock_ping
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: consolr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Richard
|
@@ -9,22 +9,92 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-08-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: collins_auth
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - ~>
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 0.1.2
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - ~>
|
25
|
+
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: 0.1.2
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: net-ping
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.7.7
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 1.7.7
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 10.4.2
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 10.4.2
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 3.3.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 3.3.0
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: simplecov
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.10.0
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 0.10.0
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: webmock
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.21.0
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 1.21.0
|
28
98
|
description: Consolr is a utility which speaks to Collins on our behalf and retrieves
|
29
99
|
the address, username and password to connect to that node over IPMI. Passing different
|
30
100
|
flags, we can performs a variety of taks on the node over IPMI. There are safeguards
|
@@ -38,13 +108,29 @@ executables:
|
|
38
108
|
extensions: []
|
39
109
|
extra_rdoc_files: []
|
40
110
|
files:
|
111
|
+
- ".gitignore"
|
112
|
+
- ".rspec"
|
113
|
+
- ".versions.conf"
|
41
114
|
- Gemfile
|
42
115
|
- LICENSE
|
43
116
|
- README.md
|
117
|
+
- Rakefile
|
44
118
|
- bin/consolr
|
45
119
|
- consolr.gemspec
|
46
120
|
- lib/consolr.rb
|
47
121
|
- lib/consolr/version.rb
|
122
|
+
- spec/configs/collins_rspec.yml
|
123
|
+
- spec/configs/consolr_rspec.yml
|
124
|
+
- spec/consolr_spec.rb
|
125
|
+
- spec/fixtures/assets/dangerous-allocated-tag.yml
|
126
|
+
- spec/fixtures/assets/dangerous-maintenance-tag.yml
|
127
|
+
- spec/fixtures/assets/safe-allocated-tag.yml
|
128
|
+
- spec/fixtures/assets/safe-maintenance-tag.yml
|
129
|
+
- spec/mocks/collins.rb
|
130
|
+
- spec/mocks/collins_auth.rb
|
131
|
+
- spec/mocks/ping.rb
|
132
|
+
- spec/rspec_ipmi
|
133
|
+
- spec/spec_helper.rb
|
48
134
|
homepage: https://github.com/tumblr/collins/tree/master/support/ruby/consolr
|
49
135
|
licenses:
|
50
136
|
- Apache 2.0
|
@@ -55,19 +141,31 @@ require_paths:
|
|
55
141
|
- lib
|
56
142
|
required_ruby_version: !ruby/object:Gem::Requirement
|
57
143
|
requirements:
|
58
|
-
- -
|
144
|
+
- - ">="
|
59
145
|
- !ruby/object:Gem::Version
|
60
146
|
version: '0'
|
61
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
148
|
requirements:
|
63
|
-
- -
|
149
|
+
- - ">="
|
64
150
|
- !ruby/object:Gem::Version
|
65
151
|
version: '0'
|
66
152
|
requirements: []
|
67
153
|
rubyforge_project:
|
68
|
-
rubygems_version: 2.
|
154
|
+
rubygems_version: 2.4.5
|
69
155
|
signing_key:
|
70
156
|
specification_version: 4
|
71
157
|
summary: consolr is a pure ruby wrapper over IPMI to allow Out of Band communiation
|
72
158
|
with nodes.
|
73
|
-
test_files:
|
159
|
+
test_files:
|
160
|
+
- spec/configs/collins_rspec.yml
|
161
|
+
- spec/configs/consolr_rspec.yml
|
162
|
+
- spec/consolr_spec.rb
|
163
|
+
- spec/fixtures/assets/dangerous-allocated-tag.yml
|
164
|
+
- spec/fixtures/assets/dangerous-maintenance-tag.yml
|
165
|
+
- spec/fixtures/assets/safe-allocated-tag.yml
|
166
|
+
- spec/fixtures/assets/safe-maintenance-tag.yml
|
167
|
+
- spec/mocks/collins.rb
|
168
|
+
- spec/mocks/collins_auth.rb
|
169
|
+
- spec/mocks/ping.rb
|
170
|
+
- spec/rspec_ipmi
|
171
|
+
- spec/spec_helper.rb
|