toft-puppet 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +62 -0
  3. data/Rakefile +121 -0
  4. data/features/checker.feature +14 -0
  5. data/features/chef.feature +70 -0
  6. data/features/command.feature +20 -0
  7. data/features/node.feature +41 -0
  8. data/features/puppet.feature +40 -0
  9. data/features/step_definitions/centos/checks.rb +9 -0
  10. data/features/step_definitions/checker.rb +15 -0
  11. data/features/step_definitions/chef.rb +43 -0
  12. data/features/step_definitions/command.rb +28 -0
  13. data/features/step_definitions/node.rb +65 -0
  14. data/features/step_definitions/puppet.rb +7 -0
  15. data/features/support/env.rb +25 -0
  16. data/fixtures/chef/attributes.json +9 -0
  17. data/fixtures/chef/cookbooks/test/attributes/default.rb +4 -0
  18. data/fixtures/chef/cookbooks/test/recipes/attribute.rb +19 -0
  19. data/fixtures/chef/cookbooks/test/recipes/default.rb +4 -0
  20. data/fixtures/chef/cookbooks/test/recipes/role.rb +4 -0
  21. data/fixtures/chef/roles/test.rb +3 -0
  22. data/fixtures/puppet/conf/fileserver.conf +3 -0
  23. data/fixtures/puppet/conf/puppet.conf +15 -0
  24. data/fixtures/puppet/conf/puppet_exec.conf +9 -0
  25. data/fixtures/puppet/conf/puppet_fileserver.conf +8 -0
  26. data/fixtures/puppet/conf/puppet_modules.conf +7 -0
  27. data/fixtures/puppet/conf/puppet_template.conf +8 -0
  28. data/fixtures/puppet/manifests/fileserver/conf/test_fileserver +1 -0
  29. data/fixtures/puppet/manifests/nodes/test_node.pp +26 -0
  30. data/fixtures/puppet/manifests/site.pp +1 -0
  31. data/fixtures/puppet/manifests/templates/template_test +2 -0
  32. data/fixtures/puppet/manifests/test.pp +8 -0
  33. data/fixtures/puppet/manifests/test_fileserver.pp +14 -0
  34. data/fixtures/puppet/manifests/test_install.pp +5 -0
  35. data/fixtures/puppet/manifests/test_module.pp +5 -0
  36. data/fixtures/puppet/manifests/test_service.pp +11 -0
  37. data/fixtures/puppet/manifests/test_template.pp +12 -0
  38. data/fixtures/puppet/modules/test_module/manifests/init.pp +8 -0
  39. data/lib/toft.rb +39 -0
  40. data/lib/toft/chef/chef_attributes.rb +29 -0
  41. data/lib/toft/chef/chef_runner.rb +77 -0
  42. data/lib/toft/command_executor.rb +16 -0
  43. data/lib/toft/file_checker.rb +47 -0
  44. data/lib/toft/node.rb +243 -0
  45. data/lib/toft/node_controller.rb +32 -0
  46. data/lib/toft/puppet/puppet_runner.rb +38 -0
  47. data/lib/toft/version.rb +3 -0
  48. data/scripts/bin/centos/lxc-prepare-host +172 -0
  49. data/scripts/bin/centos/provision_vagrant +11 -0
  50. data/scripts/bin/share/install-chef-ubuntu.sh +19 -0
  51. data/scripts/bin/share/lxc-create-centos-image +60 -0
  52. data/scripts/bin/ubuntu/lxc-create-ubuntu-image +77 -0
  53. data/scripts/bin/ubuntu/lxc-prepare-host +199 -0
  54. data/scripts/bin/ubuntu/provision_vagrant +9 -0
  55. data/scripts/lxc-templates/files/rc.local +38 -0
  56. data/scripts/lxc-templates/lxc-centos-6 +279 -0
  57. data/scripts/lxc-templates/lxc-lenny +255 -0
  58. data/scripts/lxc-templates/lxc-lucid +313 -0
  59. data/scripts/lxc-templates/lxc-natty +237 -0
  60. data/spec/fixtures/illegal_syntax.json +1 -0
  61. data/spec/spec_helper.rb +6 -0
  62. data/spec/toft/chef/chef_attributes_spec.rb +39 -0
  63. data/spec/toft/chef/chef_runner_spec.rb +34 -0
  64. data/spec/toft/node_spec.rb +18 -0
  65. data/spec/toft/puppet/puppet_runner_spec.rb +26 -0
  66. 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,9 @@
1
+ {
2
+ "one" : "one",
3
+ "two" :
4
+ {
5
+ "one" : "two_one",
6
+ "two" : "two_two"
7
+ },
8
+ "three" : "three"
9
+ }
@@ -0,0 +1,4 @@
1
+ default[:one] = "test"
2
+ default[:three] = "test"
3
+ default[:two][:one] = "test"
4
+ default[:two][:two] = "test"
@@ -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,4 @@
1
+ directory "/tmp/stub/dir" do
2
+ action :create
3
+ recursive true
4
+ end
@@ -0,0 +1,4 @@
1
+ directory "/tmp/stub/role" do
2
+ action :create
3
+ recursive true
4
+ end
@@ -0,0 +1,3 @@
1
+ name 'test'
2
+ description 'Test!'
3
+ run_list "recipe[test::role]"
@@ -0,0 +1,3 @@
1
+ [conf]
2
+ path /tmp/toft-puppet-tmp/manifests/fileserver/conf
3
+ allow *
@@ -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,9 @@
1
+ [main]
2
+ node_terminus = exec
3
+ external_nodes = /tmp/puppet/tools/extnode.pl
4
+
5
+ logdir = /var/log/puppet
6
+ vardir = /var/lib/puppet
7
+ ssldir = /var/lib/puppet/ssl
8
+ rundir = /var/run/puppet
9
+ report = true
@@ -0,0 +1,8 @@
1
+ [main]
2
+ fileserverconfig = /tmp/toft-puppet-tmp/conf/fileserver.conf
3
+
4
+ logdir = /var/log/puppet
5
+ vardir = /var/lib/puppet
6
+ ssldir = /var/lib/puppet/ssl
7
+ rundir = /var/run/puppet
8
+ report = true
@@ -0,0 +1,7 @@
1
+ [main]
2
+ modulepath = /tmp/toft-puppet-tmp/modules
3
+
4
+ logdir = /var/log/puppet
5
+ vardir = /var/lib/puppet
6
+ ssldir = /var/lib/puppet/ssl
7
+ rundir = /var/run/puppet
@@ -0,0 +1,8 @@
1
+ [main]
2
+ templatedir = /tmp/toft-puppet-tmp/manifests/templates
3
+
4
+ logdir = /var/log/puppet
5
+ vardir = /var/lib/puppet
6
+ ssldir = /var/lib/puppet/ssl
7
+ rundir = /var/run/puppet
8
+ report = true
@@ -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"
@@ -0,0 +1,2 @@
1
+ This is a test for the template config
2
+ Here is the variable <%= variable %>
@@ -0,0 +1,8 @@
1
+ class { 'test': }
2
+
3
+ class test {
4
+ file { "/tmp/puppet_test":
5
+ ensure => present,
6
+ mode => '0666',
7
+ }
8
+ }
@@ -0,0 +1,14 @@
1
+ class { 'test': }
2
+
3
+ class test {
4
+ file { "test_fileserver":
5
+ path => "/tmp/puppet_test_fileserver",
6
+ owner => "root",
7
+ group => "root",
8
+ mode => 0440,
9
+ source => "puppet:///conf/test_fileserver",
10
+ }
11
+ }
12
+
13
+
14
+
@@ -0,0 +1,5 @@
1
+ class { 'test': }
2
+
3
+ class test {
4
+ package { "zip": ensure => installed }
5
+ }
@@ -0,0 +1,5 @@
1
+ class { 'test': }
2
+
3
+ class test {
4
+ include test_module
5
+ }
@@ -0,0 +1,11 @@
1
+ class { 'test': }
2
+
3
+ class test {
4
+ package { "bind": ensure => installed }
5
+
6
+ service { "named":
7
+ enable => true,
8
+ ensure => running,
9
+ require => Package["bind"],
10
+ }
11
+ }
@@ -0,0 +1,12 @@
1
+ class { 'test': }
2
+
3
+ class test {
4
+
5
+ $variable = "BLAH"
6
+
7
+ file { "/tmp/puppet_test_template":
8
+ ensure => present,
9
+ mode => '0666',
10
+ content => template(template_test)
11
+ }
12
+ }
@@ -0,0 +1,8 @@
1
+ class test_module {
2
+
3
+ file { "/tmp/puppet_test_module":
4
+ ensure => present,
5
+ mode => '0666',
6
+ }
7
+
8
+ }
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