zool 0.1.0
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/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
|