zool 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.md +96 -0
- data/Rakefile +57 -0
- data/Readme.md +96 -0
- data/bin/zool +156 -0
- data/features/config_parser.feature +67 -0
- data/features/fetching_ssh_keys.feature +72 -0
- data/features/step_definitions/ssh_keys_steps.rb +136 -0
- data/features/store_ssh_keys.feature +62 -0
- data/features/support/env.rb +39 -0
- data/lib/py_config_parser/py_config_parser.tt +85 -0
- data/lib/zool.rb +24 -0
- data/lib/zool/configuration.rb +151 -0
- data/lib/zool/key_file_writer.rb +48 -0
- data/lib/zool/server.rb +116 -0
- data/lib/zool/server_pool.rb +74 -0
- data/spec/py_config_parser_spec.rb +55 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/zool.rb +4 -0
- data/spec/zool/configuration_spec.rb +170 -0
- data/spec/zool/key_file_writer_spec.rb +82 -0
- data/spec/zool/server_pool_spec.rb +133 -0
- data/spec/zool/server_spec.rb +178 -0
- metadata +266 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
Feature: Fetching SSH Keys
|
2
|
+
In order to see a list of all used ssh servers
|
3
|
+
As a xing techie
|
4
|
+
I want to be able to fetch all authorized keys from remote servers
|
5
|
+
|
6
|
+
Scenario: Fetching all keys from a server
|
7
|
+
Given the following keys are on the servers
|
8
|
+
| server | key |
|
9
|
+
| preview_server | ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
10
|
+
When I run the fetch_keys command for the server "preview_server"
|
11
|
+
Then It should fetch the following keys
|
12
|
+
| key |
|
13
|
+
| ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
14
|
+
|
15
|
+
Scenario: Fetching all keys from all servers
|
16
|
+
Given the following hosts
|
17
|
+
"""
|
18
|
+
13.9.1.41 preview_server
|
19
|
+
13.9.1.42 edge_server
|
20
|
+
10.53.1.41 production_server
|
21
|
+
"""
|
22
|
+
And the following keys are on the servers
|
23
|
+
| server | key |
|
24
|
+
| 13.9.1.41 | ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
25
|
+
| 13.9.1.41 | ssh-rsa key4== abel.fernandez@nb-afernandez.local |
|
26
|
+
| 13.9.1.41 | ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
27
|
+
| 13.9.1.42 | ssh-rsa key3== lee.hambley@xing.com |
|
28
|
+
| 10.53.1.41 | ssh-rsa key4== abel.fernandez@nb-afernandez.local |
|
29
|
+
| 10.53.1.41 | ssh-rsa key5== pascal.friederich@nb-pfriederich.local |
|
30
|
+
When I run the fetch_keys command
|
31
|
+
Then It should fetch the following keys
|
32
|
+
| key |
|
33
|
+
| ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
34
|
+
| ssh-rsa key4== abel.fernandez@nb-afernandez.local |
|
35
|
+
| ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
36
|
+
| ssh-rsa key3== lee.hambley@xing.com |
|
37
|
+
| ssh-rsa key5== pascal.friederich@nb-pfriederich.local |
|
38
|
+
|
39
|
+
Scenario: Dumping a single servers keys to files
|
40
|
+
Given the following keys have been fetched
|
41
|
+
| key |
|
42
|
+
| ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
43
|
+
| ssh-rsa key4== abelfernandez@nb-afernandez.local |
|
44
|
+
| ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
45
|
+
| ssh-rsa key3== lee.hambley@xing.com |
|
46
|
+
| ssh-rsa key5== lee.hambley@private |
|
47
|
+
When I run the dump_keyfiles command
|
48
|
+
Then It should generate the following files
|
49
|
+
| name | key |
|
50
|
+
| abelfernandez.pub | ssh-rsa key4== abelfernandez@nb-afernandez.local |
|
51
|
+
| adem_deliceoglu.pub | ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
52
|
+
| christian_kvalheim.pub | ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
53
|
+
| lee_hambley.pub | ssh-rsa key3== lee.hambley@xing.com |
|
54
|
+
| lee_hambley_2.pub | ssh-rsa key5== lee.hambley@private |
|
55
|
+
|
56
|
+
Scenario: Dumping all servers keys to files
|
57
|
+
Given the following hosts
|
58
|
+
"""
|
59
|
+
13.9.1.41 preview_server
|
60
|
+
10.53.1.42 production_server
|
61
|
+
"""
|
62
|
+
And the following keys are on the servers
|
63
|
+
| server | key |
|
64
|
+
| 13.9.1.41 | ssh-rsa key4== abel.fernandez@nb-afernandez.local |
|
65
|
+
| 13.9.1.41 | ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
66
|
+
| 10.53.1.42 | ssh-rsa key4== abel.fernandez@nb-afernandez.local |
|
67
|
+
When I run the fetch_keys command
|
68
|
+
And I run the dump_keyfiles command
|
69
|
+
Then It should generate the following files
|
70
|
+
| name | key |
|
71
|
+
| abel_fernandez.pub | ssh-rsa key4== abel.fernandez@nb-afernandez.local |
|
72
|
+
| christian_kvalheim.pub | ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'ruby-debug'
|
3
|
+
Debugger.start
|
4
|
+
|
5
|
+
#########
|
6
|
+
# GIVEN
|
7
|
+
#########
|
8
|
+
|
9
|
+
Given /^the local keyfiles$/ do |table|
|
10
|
+
writer = Zool::KeyfileWriter.new
|
11
|
+
table.hashes.each {|keyfile| writer.write(keyfile['key'], keyfile['name'])}
|
12
|
+
end
|
13
|
+
|
14
|
+
Given /^the config$/ do |string|
|
15
|
+
@config = string
|
16
|
+
end
|
17
|
+
|
18
|
+
Given /^the following hosts$/ do |string|
|
19
|
+
hosts = StringIO.new(string)
|
20
|
+
@zool = Zool::ServerPool.from_hostfile(hosts)
|
21
|
+
end
|
22
|
+
|
23
|
+
Given /^the following keys are on the servers$/ do |table|
|
24
|
+
keys = server_with_keys_from_table(table)
|
25
|
+
|
26
|
+
keys.each do |host, keys|
|
27
|
+
File.open(fake_server_dir!(host) + '/authorized_keys', 'w+') do |file|
|
28
|
+
file.write(keys.join("\n"))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Given /^the following keys have been fetched$/ do |table|
|
34
|
+
Given 'the server "localhost"'
|
35
|
+
@zool.keys = table.rows.flatten
|
36
|
+
end
|
37
|
+
|
38
|
+
Given /^the server "([^\"]*)" without a key file$/ do |servername|
|
39
|
+
Given "the server \"localhost\""
|
40
|
+
end
|
41
|
+
|
42
|
+
Given /^the server "([^\"]*)"$/ do |servername|
|
43
|
+
@zool = Zool::Server.new(servername)
|
44
|
+
end
|
45
|
+
|
46
|
+
#########
|
47
|
+
# WHEN
|
48
|
+
#########
|
49
|
+
|
50
|
+
When /^I parse the config and run the upload_keys command$/ do
|
51
|
+
@zool = Zool::Configuration.parse(@config)
|
52
|
+
@zool.upload_keys
|
53
|
+
end
|
54
|
+
|
55
|
+
When /^I build the config from scratch$/ do
|
56
|
+
@generated_config = Zool::Configuration.build(@zool)
|
57
|
+
end
|
58
|
+
|
59
|
+
When /^I run the fetch_keys command for the server "([^\"]*)"$/ do |hostname|
|
60
|
+
@zool = Zool::Server.new(hostname)
|
61
|
+
@zool.fetch_keys
|
62
|
+
end
|
63
|
+
|
64
|
+
When /^I add the key "([^\"]*)"$/ do |key|
|
65
|
+
@zool.keys << key
|
66
|
+
end
|
67
|
+
|
68
|
+
When /^I run the (.*) command$/ do |command|
|
69
|
+
@zool.send(command)
|
70
|
+
end
|
71
|
+
|
72
|
+
When /^I upload the keys to the server "([^\"]*)"$/ do |servername, table|
|
73
|
+
@zool = Zool::Server.new(servername)
|
74
|
+
@zool.keys = table.rows
|
75
|
+
@zool.upload_keys
|
76
|
+
end
|
77
|
+
|
78
|
+
#########
|
79
|
+
# THEN
|
80
|
+
#########
|
81
|
+
|
82
|
+
Then /^It should fetch the following keys$/ do |table|
|
83
|
+
actual_keys = [['key']] | @zool.keys.map {|key| [key] }
|
84
|
+
table.diff!(actual_keys)
|
85
|
+
end
|
86
|
+
|
87
|
+
Then /^It should generate the following files$/ do |keyfiles|
|
88
|
+
actual_keyfiles = [['name', 'key']]
|
89
|
+
Dir[TEST_TMP_PATH + '/keys/*.pub'].each do |keyfile|
|
90
|
+
File.open(keyfile) do |file|
|
91
|
+
actual_keyfiles << [File.basename(keyfile), file.read.strip]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
keyfiles.diff!(actual_keyfiles)
|
96
|
+
end
|
97
|
+
|
98
|
+
Then /^the server "([^\"]*)" should have the authorized_keys file with the content$/ do |server, expected_content|
|
99
|
+
File.read(TEST_TMP_PATH + "/servers/#{server}/authorized_keys").should == expected_content
|
100
|
+
end
|
101
|
+
|
102
|
+
Then /^the following keys should be on the servers$/ do |table|
|
103
|
+
actual_keys_from_server = [['server', 'key']]
|
104
|
+
server_with_keys_from_table(table).each do |server, keys|
|
105
|
+
entries = File.read(TEST_TMP_PATH + "/servers/#{server}/authorized_keys").split("\n").map {|key| [server, key]}
|
106
|
+
actual_keys_from_server += entries
|
107
|
+
end
|
108
|
+
table.diff!(actual_keys_from_server)
|
109
|
+
end
|
110
|
+
|
111
|
+
Then /^I should have the following config$/ do |string|
|
112
|
+
@generated_config.should == string
|
113
|
+
end
|
114
|
+
|
115
|
+
#########
|
116
|
+
# HELPER
|
117
|
+
#########
|
118
|
+
def fake_server_dir!(server)
|
119
|
+
path = fake_server_dir(server)
|
120
|
+
return path if File.directory?(path)
|
121
|
+
FileUtils.mkdir_p path
|
122
|
+
path
|
123
|
+
end
|
124
|
+
|
125
|
+
def fake_server_dir(host)
|
126
|
+
TEST_TMP_PATH + "/servers/#{host}"
|
127
|
+
end
|
128
|
+
|
129
|
+
def server_with_keys_from_table(table)
|
130
|
+
keys = {}
|
131
|
+
table.hashes.each do |values|
|
132
|
+
keys[values["server"]] ||= []
|
133
|
+
keys[values["server"]] << values["key"]
|
134
|
+
end
|
135
|
+
keys
|
136
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
Feature: Store ssh keys on servers
|
2
|
+
In order to simplify uploading of keys to servers
|
3
|
+
As a xing techie
|
4
|
+
I want to be able to compose key lists and upload them to servers
|
5
|
+
|
6
|
+
Scenario: uploading keys to a server
|
7
|
+
Given the server "preview_server" without a key file
|
8
|
+
When I upload the keys to the server "preview_server"
|
9
|
+
| key |
|
10
|
+
| ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
11
|
+
| ssh-rsa key4== abel.fernandez@nb-afernandez.local |
|
12
|
+
| ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
13
|
+
| ssh-rsa key3== lee.hambley@xing.com |
|
14
|
+
| ssh-rsa key5== pascal.friederich@nb-pfriederich.local |
|
15
|
+
|
16
|
+
Then the server "preview_server" should have the authorized_keys file with the content
|
17
|
+
"""
|
18
|
+
ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO
|
19
|
+
ssh-rsa key4== abel.fernandez@nb-afernandez.local
|
20
|
+
ssh-dss key2== christian.kvalheim@nb-ckvalheim.local
|
21
|
+
ssh-rsa key3== lee.hambley@xing.com
|
22
|
+
ssh-rsa key5== pascal.friederich@nb-pfriederich.local
|
23
|
+
"""
|
24
|
+
|
25
|
+
Scenario: adding a single key to a servers keyfile
|
26
|
+
Given the server "13.9.1.41"
|
27
|
+
And the following keys are on the servers
|
28
|
+
| server | key |
|
29
|
+
| 13.9.1.41 | ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO |
|
30
|
+
| 13.9.1.41 | ssh-dss key2== christian.kvalheim@nb-ckvalheim.local |
|
31
|
+
When I add the key "ssh-rsa key4== abel.fernandez@nb-afernandez.local"
|
32
|
+
And I run the upload_keys command
|
33
|
+
Then the server "13.9.1.41" should have the authorized_keys file with the content
|
34
|
+
"""
|
35
|
+
ssh-rsa key1== Adem.Deliceoglu@PC-ADELICEO
|
36
|
+
ssh-dss key2== christian.kvalheim@nb-ckvalheim.local
|
37
|
+
ssh-rsa key4== abel.fernandez@nb-afernandez.local
|
38
|
+
"""
|
39
|
+
|
40
|
+
Scenario: adding a single key to a serverpools keyfiles
|
41
|
+
Given the following hosts
|
42
|
+
"""
|
43
|
+
13.9.1.41 preview_server
|
44
|
+
13.9.1.42 edge_server
|
45
|
+
"""
|
46
|
+
And the following keys are on the servers
|
47
|
+
| server | key |
|
48
|
+
| 13.9.1.41 | ssh-rsa key1== some.key@somehost |
|
49
|
+
| 13.9.1.41 | ssh-rsa key4== anotherkey@ahost.local |
|
50
|
+
| 13.9.1.41 | ssh-dss key2== thiskey@thishost.local |
|
51
|
+
| 13.9.1.42 | ssh-rsa key3== snafu@bar.com |
|
52
|
+
When I add the key "ssh-rsa key5== additionalkey@host"
|
53
|
+
And I run the upload_keys command
|
54
|
+
Then the following keys should be on the servers
|
55
|
+
| server | key |
|
56
|
+
| 13.9.1.41 | ssh-rsa key1== some.key@somehost |
|
57
|
+
| 13.9.1.41 | ssh-rsa key4== anotherkey@ahost.local |
|
58
|
+
| 13.9.1.41 | ssh-dss key2== thiskey@thishost.local |
|
59
|
+
| 13.9.1.41 | ssh-rsa key5== additionalkey@host |
|
60
|
+
| 13.9.1.42 | ssh-rsa key3== snafu@bar.com |
|
61
|
+
| 13.9.1.42 | ssh-rsa key5== additionalkey@host |
|
62
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../..'))
|
2
|
+
|
3
|
+
require 'spec'
|
4
|
+
require 'lib/zool'
|
5
|
+
|
6
|
+
TEST_TMP_PATH = File.expand_path(File.dirname(__FILE__) + "/../tmp")
|
7
|
+
|
8
|
+
class Zool::Server
|
9
|
+
def initialize(host, options = {})
|
10
|
+
@options = {
|
11
|
+
:password => '',
|
12
|
+
:user => `whoami`.chomp
|
13
|
+
}
|
14
|
+
@hostname = 'localhost'
|
15
|
+
@fake_hostname = host
|
16
|
+
|
17
|
+
temp_server_path = TEST_TMP_PATH + "/servers/#{host}"
|
18
|
+
@keyfile_location = temp_server_path + '/authorized_keys'
|
19
|
+
FileUtils.mkdir_p temp_server_path unless File.directory? temp_server_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def hostname
|
23
|
+
@fake_hostname
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Zool::KeyfileWriter
|
28
|
+
def initialize(out_directory = 'keys')
|
29
|
+
@out_directory = TEST_TMP_PATH + "/#{out_directory}"
|
30
|
+
FileUtils.mkdir_p @out_directory unless File.directory? @out_directory
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Before do
|
35
|
+
FileUtils.rm_r TEST_TMP_PATH if File.directory? TEST_TMP_PATH
|
36
|
+
@zool = nil
|
37
|
+
@servers = nil
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
grammar PyConfig
|
2
|
+
rule main
|
3
|
+
section*
|
4
|
+
{
|
5
|
+
def build
|
6
|
+
@config = {}
|
7
|
+
elements.each do |section|
|
8
|
+
@config[section.name] = section.build
|
9
|
+
end
|
10
|
+
@config
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
rule section
|
16
|
+
space* '[' sectionname ']' eol
|
17
|
+
pairs:(sectionvalue eol?)+
|
18
|
+
white*
|
19
|
+
{
|
20
|
+
def name
|
21
|
+
sectionname.text_value
|
22
|
+
end
|
23
|
+
|
24
|
+
def build
|
25
|
+
return pairs.elements.inject({}) do |pairs, elt|
|
26
|
+
pairs.merge!(elt.sectionvalue.build)
|
27
|
+
pairs
|
28
|
+
end
|
29
|
+
end
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
rule sectionname
|
34
|
+
(string / space / '.')+
|
35
|
+
end
|
36
|
+
|
37
|
+
rule sectionvalue
|
38
|
+
space* key separator value
|
39
|
+
{
|
40
|
+
def build
|
41
|
+
separator.build(key, value)
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
rule separator
|
47
|
+
space* ':' space*
|
48
|
+
{
|
49
|
+
def build(key, value)
|
50
|
+
{key.text_value => value.text_value.strip}
|
51
|
+
end
|
52
|
+
}
|
53
|
+
/
|
54
|
+
space* '=' space*
|
55
|
+
{
|
56
|
+
def build(key, value)
|
57
|
+
{key.text_value => value.text_value.split(',').map {|val| val.strip }}
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
rule key
|
63
|
+
string
|
64
|
+
end
|
65
|
+
|
66
|
+
rule value
|
67
|
+
[^\n]*
|
68
|
+
end
|
69
|
+
|
70
|
+
rule string
|
71
|
+
[a-zA-Z_0-9]+
|
72
|
+
end
|
73
|
+
|
74
|
+
rule white
|
75
|
+
(space / eol)
|
76
|
+
end
|
77
|
+
|
78
|
+
rule space
|
79
|
+
[ \t]
|
80
|
+
end
|
81
|
+
|
82
|
+
rule eol
|
83
|
+
"\n" / ("\r" "\n"?)
|
84
|
+
end
|
85
|
+
end
|
data/lib/zool.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
begin
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../vendor/gems/environment')
|
4
|
+
rescue LoadError
|
5
|
+
# seems to be the gem version
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'treetop'
|
9
|
+
require 'py_config_parser/py_config_parser'
|
10
|
+
require 'zool/server'
|
11
|
+
require 'zool/server_pool'
|
12
|
+
require 'zool/key_file_writer'
|
13
|
+
require 'zool/configuration'
|
14
|
+
|
15
|
+
module Zool
|
16
|
+
DEFAULT_LOGGER = begin
|
17
|
+
if defined?(Spec)
|
18
|
+
# we are in test environment
|
19
|
+
Logger.new('test.log')
|
20
|
+
else
|
21
|
+
Logger.new('zool.log')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module Zool
|
2
|
+
class Configuration
|
3
|
+
class ParseError < Exception; end
|
4
|
+
attr_reader :servers, :roles, :groups
|
5
|
+
|
6
|
+
def self.parse(configuration)
|
7
|
+
parser = PyConfigParser.new
|
8
|
+
if raw_config = parser.parse(configuration)
|
9
|
+
self.new(raw_config.build)
|
10
|
+
else
|
11
|
+
raise ParseError.new(parser.failure_reason)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.build(pool)
|
16
|
+
conf = ""
|
17
|
+
pool.servers.each do |server|
|
18
|
+
next if server.keys == []
|
19
|
+
conf << "\n" unless conf == ""
|
20
|
+
conf << "[server #{server.hostname}]\n"
|
21
|
+
keynames = server.keys.map {|key| KeyfileWriter.keyname_for_key(key)}
|
22
|
+
conf << " keys = #{keynames.join(', ')}\n"
|
23
|
+
end
|
24
|
+
conf
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(raw_config)
|
28
|
+
@raw_config = raw_config
|
29
|
+
parse
|
30
|
+
end
|
31
|
+
|
32
|
+
def keys
|
33
|
+
@keys ||= read_keys
|
34
|
+
end
|
35
|
+
|
36
|
+
def upload_keys
|
37
|
+
@servers.each { |servername, server| server.upload_keys }
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def parse
|
42
|
+
@roles = {}
|
43
|
+
@servers = {}
|
44
|
+
@groups = {}
|
45
|
+
|
46
|
+
parse_groups
|
47
|
+
parse_servers
|
48
|
+
parse_roles
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_groups
|
52
|
+
raw_groups.each do |raw_group|
|
53
|
+
@groups[raw_group[/^group\s(.*)/, 1]] = @raw_config[raw_group]['members']
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_servers
|
58
|
+
raw_servers.each do |raw_server|
|
59
|
+
server = server(raw_server[/^server\s(.*)/, 1], @raw_config[raw_server])
|
60
|
+
@raw_config[raw_server]['keys'].each do |key|
|
61
|
+
server.keys << fetch_key(key)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def raw_servers
|
67
|
+
raw(:server)
|
68
|
+
end
|
69
|
+
|
70
|
+
def raw_groups
|
71
|
+
raw(:group)
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_roles
|
75
|
+
raw_roles.each do |raw_role|
|
76
|
+
@roles[raw_role[/^role\s(.*)/, 1]] = server_pool(raw_role)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def raw_roles
|
81
|
+
raw(:role)
|
82
|
+
end
|
83
|
+
|
84
|
+
def raw(raw_type)
|
85
|
+
@raw_config.select {|k, v| k =~ /^#{raw_type}/}.map {|role_arrey| role_arrey[0]}
|
86
|
+
end
|
87
|
+
|
88
|
+
def server(hostname, raw_object)
|
89
|
+
return @servers[hostname] if @servers[hostname]
|
90
|
+
options = server_options_from_configuration(raw_object)
|
91
|
+
|
92
|
+
new_server = Server.new(hostname, options)
|
93
|
+
new_server.keys = []
|
94
|
+
@servers[hostname] = new_server
|
95
|
+
new_server
|
96
|
+
end
|
97
|
+
|
98
|
+
def server_options_from_configuration(raw_object)
|
99
|
+
user = raw_object['user']
|
100
|
+
password = raw_object['password']
|
101
|
+
options = {}
|
102
|
+
options.update({:user => user}) if user
|
103
|
+
options.update({:password => password}) if password
|
104
|
+
options
|
105
|
+
end
|
106
|
+
|
107
|
+
def read_keys
|
108
|
+
hash = {}
|
109
|
+
key_directory = KeyfileWriter.new.out_directory # FIXME: terrible and lazy hack!
|
110
|
+
keyfiles = Dir["#{key_directory}/*.pub"]
|
111
|
+
keyfiles.each do |keyfile|
|
112
|
+
keyname = File.basename(keyfile)[/(.*)\.pub/, 1]
|
113
|
+
hash[keyname] = File.read(keyfile).chomp
|
114
|
+
end
|
115
|
+
hash
|
116
|
+
end
|
117
|
+
|
118
|
+
def server_pool(raw_role)
|
119
|
+
pool = ServerPool.new()
|
120
|
+
|
121
|
+
@raw_config[raw_role]['servers'].each do |hostname|
|
122
|
+
pool << server(hostname, @raw_config[raw_role])
|
123
|
+
end
|
124
|
+
|
125
|
+
@raw_config[raw_role]['keys'].each do |key|
|
126
|
+
if key =~ /^&/
|
127
|
+
add_group_keys(key[1..-1], pool)
|
128
|
+
else
|
129
|
+
pool.keys << fetch_key(key)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
pool
|
134
|
+
end
|
135
|
+
|
136
|
+
def fetch_key(key)
|
137
|
+
return keys[key] unless keys[key].nil?
|
138
|
+
raise ParseError.new("missing ssh key '#{key}'")
|
139
|
+
end
|
140
|
+
|
141
|
+
def add_group_keys(group, pool)
|
142
|
+
begin
|
143
|
+
@groups[group].each do |key|
|
144
|
+
pool.keys << fetch_key(key)
|
145
|
+
end
|
146
|
+
rescue NoMethodError => e
|
147
|
+
raise ParseError.new("missing referenced group '#{group}'")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|