toft-puppet 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +62 -0
- data/Rakefile +121 -0
- data/features/checker.feature +14 -0
- data/features/chef.feature +70 -0
- data/features/command.feature +20 -0
- data/features/node.feature +41 -0
- data/features/puppet.feature +40 -0
- data/features/step_definitions/centos/checks.rb +9 -0
- data/features/step_definitions/checker.rb +15 -0
- data/features/step_definitions/chef.rb +43 -0
- data/features/step_definitions/command.rb +28 -0
- data/features/step_definitions/node.rb +65 -0
- data/features/step_definitions/puppet.rb +7 -0
- data/features/support/env.rb +25 -0
- data/fixtures/chef/attributes.json +9 -0
- data/fixtures/chef/cookbooks/test/attributes/default.rb +4 -0
- data/fixtures/chef/cookbooks/test/recipes/attribute.rb +19 -0
- data/fixtures/chef/cookbooks/test/recipes/default.rb +4 -0
- data/fixtures/chef/cookbooks/test/recipes/role.rb +4 -0
- data/fixtures/chef/roles/test.rb +3 -0
- data/fixtures/puppet/conf/fileserver.conf +3 -0
- data/fixtures/puppet/conf/puppet.conf +15 -0
- data/fixtures/puppet/conf/puppet_exec.conf +9 -0
- data/fixtures/puppet/conf/puppet_fileserver.conf +8 -0
- data/fixtures/puppet/conf/puppet_modules.conf +7 -0
- data/fixtures/puppet/conf/puppet_template.conf +8 -0
- data/fixtures/puppet/manifests/fileserver/conf/test_fileserver +1 -0
- data/fixtures/puppet/manifests/nodes/test_node.pp +26 -0
- data/fixtures/puppet/manifests/site.pp +1 -0
- data/fixtures/puppet/manifests/templates/template_test +2 -0
- data/fixtures/puppet/manifests/test.pp +8 -0
- data/fixtures/puppet/manifests/test_fileserver.pp +14 -0
- data/fixtures/puppet/manifests/test_install.pp +5 -0
- data/fixtures/puppet/manifests/test_module.pp +5 -0
- data/fixtures/puppet/manifests/test_service.pp +11 -0
- data/fixtures/puppet/manifests/test_template.pp +12 -0
- data/fixtures/puppet/modules/test_module/manifests/init.pp +8 -0
- data/lib/toft.rb +39 -0
- data/lib/toft/chef/chef_attributes.rb +29 -0
- data/lib/toft/chef/chef_runner.rb +77 -0
- data/lib/toft/command_executor.rb +16 -0
- data/lib/toft/file_checker.rb +47 -0
- data/lib/toft/node.rb +243 -0
- data/lib/toft/node_controller.rb +32 -0
- data/lib/toft/puppet/puppet_runner.rb +38 -0
- data/lib/toft/version.rb +3 -0
- data/scripts/bin/centos/lxc-prepare-host +172 -0
- data/scripts/bin/centos/provision_vagrant +11 -0
- data/scripts/bin/share/install-chef-ubuntu.sh +19 -0
- data/scripts/bin/share/lxc-create-centos-image +60 -0
- data/scripts/bin/ubuntu/lxc-create-ubuntu-image +77 -0
- data/scripts/bin/ubuntu/lxc-prepare-host +199 -0
- data/scripts/bin/ubuntu/provision_vagrant +9 -0
- data/scripts/lxc-templates/files/rc.local +38 -0
- data/scripts/lxc-templates/lxc-centos-6 +279 -0
- data/scripts/lxc-templates/lxc-lenny +255 -0
- data/scripts/lxc-templates/lxc-lucid +313 -0
- data/scripts/lxc-templates/lxc-natty +237 -0
- data/spec/fixtures/illegal_syntax.json +1 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/toft/chef/chef_attributes_spec.rb +39 -0
- data/spec/toft/chef/chef_runner_spec.rb +34 -0
- data/spec/toft/node_spec.rb +18 -0
- data/spec/toft/puppet/puppet_runner_spec.rb +26 -0
- metadata +234 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
Then /^Running ssh command "([^"]*)" on "([^"]*)" should succeed$/ do |cmd, node|
|
2
|
+
lambda { find(node).run_ssh(cmd) }.should_not raise_error
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^Running ssh command "([^"]*)" on "([^"]*)" should fail$/ do |cmd, node|
|
6
|
+
lambda { find(node).run_ssh(cmd) }.should raise_error
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^Rm "([^"]*)" on "([^"]*)" should fail$/ do |dir, node|
|
10
|
+
lambda { find(node).rm(dir) }.should raise_error
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^Rm "([^"]*)" on "([^"]*)" should succeed$/ do |dir, node|
|
14
|
+
lambda { find(node).rm(dir) }.should_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
Then /^the result of running ssh command "([^"]*)" on "([^"]*)" should contain "([^"]*)"$/ do |cmd, node, s|
|
18
|
+
r = find(node).run_ssh(cmd)
|
19
|
+
r.stdout.should include(s)
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^the result of running ssh command "([^"]*)" on "([^"]*)" should fail because of "([^"]*)"$/ do |cmd, node, s|
|
23
|
+
begin
|
24
|
+
r = find(node).run_ssh(cmd)
|
25
|
+
rescue CommandExecutionError => e
|
26
|
+
e.stdout.should include(s)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
Given /^I have a clean running node n1$/ do
|
2
|
+
@n1.start
|
3
|
+
@n1.rm "/tmp/stub"
|
4
|
+
end
|
5
|
+
|
6
|
+
When /^I add another node "([^"]*)" with ip "([^"]*)"$/ do |node, ip|
|
7
|
+
create_node node, {:ip => ip, :type => CONTAINER_TYPE}
|
8
|
+
end
|
9
|
+
|
10
|
+
When /^I add another node "([^"]*)"$/ do |node|
|
11
|
+
n = create_node node, {:type => CONTAINER_TYPE}
|
12
|
+
n.start
|
13
|
+
end
|
14
|
+
|
15
|
+
When /^I destroy node "([^"]*)"$/ do |node|
|
16
|
+
destroy_node node
|
17
|
+
end
|
18
|
+
|
19
|
+
When /^Node "([^"]*)" is destroyed$/ do |node|
|
20
|
+
find(node).destroy
|
21
|
+
end
|
22
|
+
|
23
|
+
Then /^There should be ([^"]*) nodes in the environment$/ do |count|
|
24
|
+
find(:all).size.should == count.to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
Then /^the node "([^"]*)" should be stopped$/ do |node|
|
28
|
+
find(node).should_not be_running
|
29
|
+
end
|
30
|
+
|
31
|
+
When /^I start node "([^"]*)"$/ do |node|
|
32
|
+
find(node).start
|
33
|
+
end
|
34
|
+
|
35
|
+
When /^I stop node "([^"]*)"$/ do |node|
|
36
|
+
find(node).stop
|
37
|
+
end
|
38
|
+
|
39
|
+
Then /^the node "([^"]*)" should be running$/ do |node|
|
40
|
+
find(node).should be_running
|
41
|
+
end
|
42
|
+
|
43
|
+
Then /^Node "([^"]*)" should have ip address same with that obtained from inside it through ssh$/ do |node|
|
44
|
+
n = find(node)
|
45
|
+
n.run_ssh("ifconfig eth0 | grep 'inet addr:'").stdout.should include(n.ip)
|
46
|
+
end
|
47
|
+
|
48
|
+
When /^I add cname "([^"]*)" to "([^"]*)"$/ do |cname, node|
|
49
|
+
find(node).add_cname cname
|
50
|
+
end
|
51
|
+
|
52
|
+
When /^I remove cname "([^"]*)" from "([^"]*)"$/ do |cname, node|
|
53
|
+
find(node).remove_cname cname
|
54
|
+
end
|
55
|
+
|
56
|
+
When /^I change the internal hostname for "([^"]*)" to "([^"]*)"$/ do |node_hostname, internal_hostname|
|
57
|
+
r = find(node_hostname)
|
58
|
+
r.run_ssh("hostname #{internal_hostname}")
|
59
|
+
r.run_ssh("echo 127.0.0.1 #{internal_hostname} >> /etc/hosts")
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
Then /^Hostname of Node "([^"]*)" should match its name$/ do |node|
|
64
|
+
find(node).hostname.should == node
|
65
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
When /^I run puppet manifest "([^"]*)" on node "([^"]*)"$/ do |run_list, node|
|
2
|
+
find(node).run_puppet run_list
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I run puppet manifest "([^"]*)" with config file "([^"]*)" on node "([^"]*)"$/ do |run_list, conf_file, node|
|
6
|
+
find(node).run_puppet(run_list, :conf_file => conf_file)
|
7
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
2
|
+
require 'rspec/expectations'
|
3
|
+
require 'toft'
|
4
|
+
|
5
|
+
CHEF_FIXTURE_PATH = File.dirname(__FILE__) + '/../../fixtures/chef'
|
6
|
+
PUPPET_FIXTURE_PATH = File.dirname(__FILE__) + '/../../fixtures/puppet'
|
7
|
+
|
8
|
+
CONTAINER_TYPE = "centos-6"
|
9
|
+
|
10
|
+
World(Toft)
|
11
|
+
|
12
|
+
include Toft
|
13
|
+
n1 = create_node "n1", {:ip => "192.168.20.2", :type => CONTAINER_TYPE}
|
14
|
+
|
15
|
+
Before do
|
16
|
+
Toft.cookbook_path = CHEF_FIXTURE_PATH + '/cookbooks'
|
17
|
+
Toft.role_path = CHEF_FIXTURE_PATH + '/roles'
|
18
|
+
Toft.manifest_path = PUPPET_FIXTURE_PATH
|
19
|
+
|
20
|
+
@n1 = n1
|
21
|
+
end
|
22
|
+
|
23
|
+
at_exit do
|
24
|
+
n1.destroy
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
directory "/tmp/stub/#{node.one}" do
|
2
|
+
action :create
|
3
|
+
recursive true
|
4
|
+
end
|
5
|
+
|
6
|
+
directory "/tmp/stub/#{node.two.two}" do
|
7
|
+
action :create
|
8
|
+
recursive true
|
9
|
+
end
|
10
|
+
|
11
|
+
directory "/tmp/stub/#{node.two.one}" do
|
12
|
+
action :create
|
13
|
+
recursive true
|
14
|
+
end
|
15
|
+
|
16
|
+
directory "/tmp/stub/#{node.three}" do
|
17
|
+
action :create
|
18
|
+
recursive true
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
[main]
|
2
|
+
modulepath = /tmp/puppet/modules
|
3
|
+
templatedir = /tmp/puppet/manifests/templates
|
4
|
+
node_terminus = exec
|
5
|
+
external_nodes = /tmp/puppet/tools/extnode.pl
|
6
|
+
fileserverconfig = /tmp/puppet/conf/fileserver.conf
|
7
|
+
logdir = /var/log/puppet
|
8
|
+
vardir = /var/lib/puppet
|
9
|
+
ssldir = /var/lib/puppet/ssl
|
10
|
+
rundir = /var/run/puppet
|
11
|
+
report = true
|
12
|
+
server = puppet.dev.int.realestate.com.au
|
13
|
+
reportserver = puppet.dev.int.realestate.com.au
|
14
|
+
diff = diff
|
15
|
+
diff_args = -u
|
@@ -0,0 +1 @@
|
|
1
|
+
This is a test for the fileserver config
|
@@ -0,0 +1,26 @@
|
|
1
|
+
node /^correct.*/ inherits default_node {
|
2
|
+
|
3
|
+
file { "/tmp/puppet_test_correct":
|
4
|
+
ensure => present,
|
5
|
+
mode => '0666',
|
6
|
+
}
|
7
|
+
|
8
|
+
}
|
9
|
+
|
10
|
+
node /^incorrect.*/ inherits default_node {
|
11
|
+
|
12
|
+
file { "/tmp/puppet_test_incorrect":
|
13
|
+
ensure => present,
|
14
|
+
mode => '0666',
|
15
|
+
}
|
16
|
+
|
17
|
+
}
|
18
|
+
|
19
|
+
node default_node {
|
20
|
+
|
21
|
+
file { "/tmp/puppet_test_default":
|
22
|
+
ensure => present,
|
23
|
+
mode => '0666',
|
24
|
+
}
|
25
|
+
|
26
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
import "nodes/*.pp"
|
data/lib/toft.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'toft/node_controller'
|
2
|
+
require 'toft/file_checker'
|
3
|
+
require 'toft/chef/chef_attributes'
|
4
|
+
require 'toft/chef/chef_runner'
|
5
|
+
require 'toft/puppet/puppet_runner'
|
6
|
+
|
7
|
+
module Toft
|
8
|
+
DYNAMIC_IP = "0.0.0.0"
|
9
|
+
DOMAIN = "foo"
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :manifest_path, :cookbook_path, :role_path
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_node(hostname, options = {})
|
16
|
+
NodeController.instance.create_node(hostname, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(name)
|
20
|
+
return NodeController.instance.nodes if name === :all
|
21
|
+
NodeController.instance.nodes[name] if name.is_a? String
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy_node(hostname)
|
25
|
+
NodeController.instance.destroy_node(hostname)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class NilClass
|
30
|
+
def blank?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class String
|
36
|
+
def blank?
|
37
|
+
empty?
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Toft
|
4
|
+
class ChefAttributes
|
5
|
+
attr_reader :attributes
|
6
|
+
|
7
|
+
def initialize(cuke_ast_table = nil)
|
8
|
+
@attributes = {}
|
9
|
+
cuke_ast_table.hashes.each do |row|
|
10
|
+
add_attribute row[:key], row[:value]
|
11
|
+
end unless cuke_ast_table.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_attribute(key, value)
|
15
|
+
stat = "attributes"
|
16
|
+
head = attributes
|
17
|
+
key.split(".").each do |k|
|
18
|
+
head[k] ||= Hash.new
|
19
|
+
head = head[k]
|
20
|
+
stat += "[\"#{k}\"]"
|
21
|
+
end
|
22
|
+
eval "#{stat}=\"#{value}\""
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_json
|
26
|
+
attributes.to_json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'toft/chef/chef_attributes'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Toft
|
5
|
+
module Chef
|
6
|
+
class ChefRunner
|
7
|
+
include FileUtils
|
8
|
+
|
9
|
+
DEST_CHEF_TMP = "/tmp/toft-chef-tmp"
|
10
|
+
DEST_COOKBOOK_PATH = "#{DEST_CHEF_TMP}/cookbooks"
|
11
|
+
DEST_ROLE_PATH = "#{DEST_CHEF_TMP}/roles"
|
12
|
+
DEST_CHEF_SOLO_PATH = "#{DEST_CHEF_TMP}/solo.rb"
|
13
|
+
DEST_CHEF_JSON_PATH = "#{DEST_CHEF_TMP}/solo.json"
|
14
|
+
|
15
|
+
def initialize(root_dir, &command_runner)
|
16
|
+
@root_dir = root_dir
|
17
|
+
@command_runner = command_runner
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(run_list, params = {})
|
21
|
+
override_attributes_hash = parse_attributes params[:json], params[:attributes]
|
22
|
+
copy_chef_material
|
23
|
+
generate_solo_rb
|
24
|
+
generate_json ([] << run_list).flatten, override_attributes_hash
|
25
|
+
@command_runner.call "chef-solo -c #{DEST_CHEF_SOLO_PATH} -j #{DEST_CHEF_JSON_PATH}"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def parse_attributes(json_file_path, chef_attributes)
|
30
|
+
chef_attributes = chef_attributes || ChefAttributes.new
|
31
|
+
chef_attributes_from_json ||= {}
|
32
|
+
chef_attributes_from_json = read_json_file json_file_path unless json_file_path.blank?
|
33
|
+
chef_attributes_from_json.merge chef_attributes.attributes
|
34
|
+
end
|
35
|
+
|
36
|
+
def read_json_file(json_file_path)
|
37
|
+
JSON.parse(File.read(json_file_path))
|
38
|
+
end
|
39
|
+
|
40
|
+
def copy_chef_material
|
41
|
+
raise ArgumentError, "Toft.cookbook_path can not be empty!" if Toft.cookbook_path.blank?
|
42
|
+
rm_rf "#{@root_dir}#{DEST_CHEF_TMP}"
|
43
|
+
mkdir_p "#{@root_dir}#{DEST_CHEF_TMP}"
|
44
|
+
cp_r Toft.cookbook_path, "#{@root_dir}#{DEST_COOKBOOK_PATH}"
|
45
|
+
cp_r Toft.role_path, "#{@root_dir}#{DEST_ROLE_PATH}" unless roles_missing?
|
46
|
+
end
|
47
|
+
|
48
|
+
def roles_missing?
|
49
|
+
Toft.role_path.blank?
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate_solo_rb
|
53
|
+
solo = <<-EOF
|
54
|
+
file_cache_path "/tmp/chef-file-cache"
|
55
|
+
cookbook_path ["#{DEST_COOKBOOK_PATH}"]
|
56
|
+
EOF
|
57
|
+
solo += "role_path [\"#{DEST_ROLE_PATH}\"]" unless roles_missing?
|
58
|
+
|
59
|
+
File.open("#{@root_dir}#{DEST_CHEF_SOLO_PATH}", 'w') do |f|
|
60
|
+
f.write(solo);
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def generate_json(run_list, override_attributes_hash)
|
65
|
+
run_list = {"run_list" => run_list}
|
66
|
+
run_list.merge!(override_attributes_hash)
|
67
|
+
File.open("#{@root_dir}#{DEST_CHEF_JSON_PATH}", 'w') do |f|
|
68
|
+
f.write(run_list.to_json);
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def cmd(cmd)
|
73
|
+
raise "Command execution failed: [#{cmd}]" unless system cmd
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|