the-maestro 0.2.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.
Files changed (60) hide show
  1. data/.document +5 -0
  2. data/.gitignore +25 -0
  3. data/LICENSE +23 -0
  4. data/README.rdoc +378 -0
  5. data/Rakefile +116 -0
  6. data/VERSION +1 -0
  7. data/lib/maestro.rb +354 -0
  8. data/lib/maestro/cloud.rb +384 -0
  9. data/lib/maestro/cloud/aws.rb +1231 -0
  10. data/lib/maestro/dsl_property.rb +15 -0
  11. data/lib/maestro/log4r/console_formatter.rb +18 -0
  12. data/lib/maestro/log4r/file_formatter.rb +24 -0
  13. data/lib/maestro/node.rb +123 -0
  14. data/lib/maestro/operating_system.rb +53 -0
  15. data/lib/maestro/operating_system/cent_os.rb +23 -0
  16. data/lib/maestro/operating_system/debian.rb +40 -0
  17. data/lib/maestro/operating_system/fedora.rb +23 -0
  18. data/lib/maestro/operating_system/ubuntu.rb +100 -0
  19. data/lib/maestro/role.rb +36 -0
  20. data/lib/maestro/tasks.rb +52 -0
  21. data/lib/maestro/validator.rb +32 -0
  22. data/rails/init.rb +1 -0
  23. data/test/integration/base_aws.rb +156 -0
  24. data/test/integration/fixtures/config/maestro/cookbooks/emacs/metadata.json +41 -0
  25. data/test/integration/fixtures/config/maestro/cookbooks/emacs/metadata.rb +3 -0
  26. data/test/integration/fixtures/config/maestro/cookbooks/emacs/recipes/default.rb +21 -0
  27. data/test/integration/fixtures/config/maestro/roles/default.json +9 -0
  28. data/test/integration/fixtures/config/maestro/roles/web.json +9 -0
  29. data/test/integration/helper.rb +8 -0
  30. data/test/integration/test_aws_cloud.rb +805 -0
  31. data/test/integration/test_cent_os.rb +104 -0
  32. data/test/integration/test_debian.rb +119 -0
  33. data/test/integration/test_fedora.rb +104 -0
  34. data/test/integration/test_ubuntu.rb +149 -0
  35. data/test/unit/fixtures/invalid-clouds-not-a-directory/config/maestro/clouds +1 -0
  36. data/test/unit/fixtures/invalid-cookbooks-not-a-directory/config/maestro/cookbooks +0 -0
  37. data/test/unit/fixtures/invalid-maestro-not-a-directory/config/maestro +0 -0
  38. data/test/unit/fixtures/invalid-missing-cookbooks/config/maestro/clouds/valid.yml +21 -0
  39. data/test/unit/fixtures/invalid-missing-roles/config/maestro/clouds/valid.yml +21 -0
  40. data/test/unit/fixtures/invalid-roles-not-a-directory/config/maestro/roles +1 -0
  41. data/test/unit/fixtures/ssh/id_rsa-maestro-test-keypair +27 -0
  42. data/test/unit/helper.rb +6 -0
  43. data/test/unit/test_aws_cloud.rb +133 -0
  44. data/test/unit/test_aws_ec2_node.rb +76 -0
  45. data/test/unit/test_aws_elb_node.rb +221 -0
  46. data/test/unit/test_aws_rds_node.rb +380 -0
  47. data/test/unit/test_cent_os.rb +28 -0
  48. data/test/unit/test_cloud.rb +142 -0
  49. data/test/unit/test_debian.rb +62 -0
  50. data/test/unit/test_fedora.rb +28 -0
  51. data/test/unit/test_invalid_mode.rb +11 -0
  52. data/test/unit/test_maestro.rb +140 -0
  53. data/test/unit/test_node.rb +50 -0
  54. data/test/unit/test_operating_system.rb +19 -0
  55. data/test/unit/test_rails_mode.rb +77 -0
  56. data/test/unit/test_role.rb +59 -0
  57. data/test/unit/test_standalone_mode.rb +75 -0
  58. data/test/unit/test_ubuntu.rb +95 -0
  59. data/the-maestro.gemspec +150 -0
  60. metadata +228 -0
@@ -0,0 +1,62 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for Maestro::OperatingSystem::Debian
4
+ class TestDebian < Test::Unit::TestCase
5
+
6
+ context "Maestro::OperatingSystem::Debian" do
7
+ setup do
8
+ end
9
+
10
+ context "Debian 6.0" do
11
+ should "create from etc/issue string" do
12
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian GNU/Linux 6.0")
13
+ assert os.instance_of? Maestro::OperatingSystem::Debian6
14
+ end
15
+
16
+ should "respond to chef_install_script" do
17
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian GNU/Linux 6.0")
18
+ assert os.respond_to? :chef_install_script
19
+ end
20
+
21
+ should "respond to etc_issue_str" do
22
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian GNU/Linux 6.0")
23
+ assert os.respond_to? :etc_issue_string
24
+ end
25
+ end
26
+
27
+ context "Debian 5.0" do
28
+ should "create from etc/issue string" do
29
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian GNU/Linux 5.0")
30
+ assert os.instance_of? Maestro::OperatingSystem::Debian5
31
+ end
32
+
33
+ should "respond to chef_install_script" do
34
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian GNU/Linux 5.0")
35
+ assert os.respond_to? :chef_install_script
36
+ end
37
+
38
+ should "respond to etc_issue_str" do
39
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian GNU/Linux 5.0")
40
+ assert os.respond_to? :etc_issue_string
41
+ end
42
+ end
43
+
44
+ context "Debian" do
45
+ should "create from etc/issue string" do
46
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian")
47
+ assert os.instance_of? Maestro::OperatingSystem::Debian
48
+ end
49
+
50
+ should "respond to chef_install_script" do
51
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian")
52
+ assert os.respond_to? :chef_install_script
53
+ end
54
+
55
+ should "respond to etc_issue_str" do
56
+ os = Maestro::OperatingSystem.create_from_etc_issue("Debian")
57
+ assert os.respond_to? :etc_issue_string
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for Maestro::OperatingSystem::Fedora
4
+ class TestFedora < Test::Unit::TestCase
5
+
6
+ context "Maestro::OperatingSystem::Fedora" do
7
+ setup do
8
+ end
9
+
10
+ context "Fedora" do
11
+ should "create from etc/issue string" do
12
+ os = Maestro::OperatingSystem.create_from_etc_issue("Fedora")
13
+ assert os.instance_of? Maestro::OperatingSystem::Fedora
14
+ end
15
+
16
+ should "respond to chef_install_script" do
17
+ os = Maestro::OperatingSystem.create_from_etc_issue("Fedora")
18
+ assert os.respond_to? :chef_install_script
19
+ end
20
+
21
+ should "respond to etc_issue_str" do
22
+ os = Maestro::OperatingSystem.create_from_etc_issue("Fedora")
23
+ assert os.respond_to? :etc_issue_string
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for no mode found
4
+ class TestInvalidMode < Test::Unit::TestCase
5
+
6
+ should "be invalid due to no rails or standalone" do
7
+ result = Maestro.validate_configs
8
+ assert !result[0], result[1]
9
+ end
10
+
11
+ end
@@ -0,0 +1,140 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for Maestro class methods
4
+ class TestMaestro < Test::Unit::TestCase
5
+
6
+ context "Maestro" do
7
+
8
+ context "Rails mode" do
9
+ setup do
10
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'rails'))
11
+ end
12
+
13
+ teardown do
14
+ Object.send(:remove_const, "RAILS_ROOT")
15
+ end
16
+
17
+ should "create config dirs" do
18
+ assert_nothing_raised do
19
+ assert_config_directories_do_not_exist("#{RAILS_ROOT}/config")
20
+ Maestro.create_config_dirs
21
+ assert_config_directories_exist("#{RAILS_ROOT}/config")
22
+ delete_config_directories("#{RAILS_ROOT}/config")
23
+ assert_config_directories_do_not_exist("#{RAILS_ROOT}/config")
24
+ end
25
+ end
26
+
27
+ should "create log dirs" do
28
+ assert_nothing_raised do
29
+ assert_log_directories_do_not_exist("#{RAILS_ROOT}/log")
30
+ Maestro.create_log_dirs
31
+ assert_log_directories_exist("#{RAILS_ROOT}/log")
32
+ delete_log_directories("#{RAILS_ROOT}/log")
33
+ assert_log_directories_do_not_exist("#{RAILS_ROOT}/log")
34
+ end
35
+ end
36
+
37
+ should "get clouds" do
38
+ assert_nothing_raised do
39
+ Maestro.clouds
40
+ end
41
+ end
42
+ end
43
+
44
+
45
+ context "Standalone mode" do
46
+ setup do
47
+ ENV[Maestro::MAESTRO_DIR_ENV_VAR] = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'standalone')
48
+ end
49
+
50
+ teardown do
51
+ ENV.delete Maestro::MAESTRO_DIR_ENV_VAR
52
+ end
53
+
54
+ should "create config dirs" do
55
+ assert_nothing_raised do
56
+ base_dir = ENV[Maestro::MAESTRO_DIR_ENV_VAR]
57
+ assert_config_directories_do_not_exist("#{base_dir}/config")
58
+ Maestro.create_config_dirs
59
+ assert_config_directories_exist("#{base_dir}/config")
60
+ delete_config_directories("#{base_dir}/config")
61
+ assert_config_directories_do_not_exist("#{base_dir}/config")
62
+ end
63
+ end
64
+
65
+ should "create log dirs" do
66
+ assert_nothing_raised do
67
+ base_dir = ENV[Maestro::MAESTRO_DIR_ENV_VAR]
68
+ assert_log_directories_do_not_exist("#{base_dir}/log")
69
+ Maestro.create_log_dirs
70
+ assert_log_directories_exist("#{base_dir}/log")
71
+ delete_log_directories("#{base_dir}/log")
72
+ assert_log_directories_do_not_exist("#{base_dir}/log")
73
+ end
74
+ end
75
+
76
+ should "get clouds" do
77
+ assert_nothing_raised do
78
+ Maestro.clouds
79
+ end
80
+ end
81
+ end
82
+
83
+ context "No mode" do
84
+ should "fail to create config dirs" do
85
+ assert_raise RuntimeError do
86
+ Maestro.create_config_dirs
87
+ end
88
+ end
89
+
90
+ should "fail to create log dirs" do
91
+ assert_raise RuntimeError do
92
+ Maestro.create_config_dirs
93
+ end
94
+ end
95
+
96
+ should "fail to get clouds" do
97
+ assert_raise RuntimeError do
98
+ Maestro.clouds
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+
105
+ def delete_config_directories(dir)
106
+ Dir.rmdir("#{dir}/maestro/roles") if File.exists?("#{dir}/maestro/roles")
107
+ Dir.rmdir("#{dir}/maestro/cookbooks") if File.exists?("#{dir}/maestro/cookbooks")
108
+ Dir.rmdir("#{dir}/maestro/clouds") if File.exists?("#{dir}/maestro/clouds")
109
+ Dir.rmdir("#{dir}/maestro") if File.exists?("#{dir}/maestro")
110
+ end
111
+
112
+ def assert_config_directories_exist(dir)
113
+ assert File.exists?("#{dir}/maestro")
114
+ assert File.exists?("#{dir}/maestro/clouds")
115
+ assert File.exists?("#{dir}/maestro/cookbooks")
116
+ assert File.exists?("#{dir}/maestro/roles")
117
+ end
118
+
119
+ def assert_config_directories_do_not_exist(dir)
120
+ assert !File.exists?("#{dir}/maestro")
121
+ assert !File.exists?("#{dir}/maestro/clouds")
122
+ assert !File.exists?("#{dir}/maestro/cookbooks")
123
+ assert !File.exists?("#{dir}/maestro/roles")
124
+ end
125
+
126
+ def delete_log_directories(dir)
127
+ Dir.rmdir("#{dir}/maestro/clouds") if File.exists?("#{dir}/maestro/clouds")
128
+ Dir.rmdir("#{dir}/maestro") if File.exists?("#{dir}/maestro")
129
+ end
130
+
131
+ def assert_log_directories_exist(dir)
132
+ assert File.exists?("#{dir}/maestro")
133
+ assert File.exists?("#{dir}/maestro/clouds")
134
+ end
135
+
136
+ def assert_log_directories_do_not_exist(dir)
137
+ assert !File.exists?("#{dir}/maestro")
138
+ assert !File.exists?("#{dir}/maestro/clouds")
139
+ end
140
+ end
@@ -0,0 +1,50 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for Maestro::Node
4
+ class TestNode < Test::Unit::TestCase
5
+
6
+ context "Maestro::Node" do
7
+ setup do
8
+ @cloud = aws_cloud :test do
9
+ keypair_name "XXXXXXX-keypair"
10
+ keypair_file "/path/to/id_rsa-XXXXXXX-keypair"
11
+
12
+ roles do
13
+ role "web" do
14
+ public_ports [80, 443]
15
+ end
16
+ end
17
+
18
+ nodes do
19
+ ec2_node "web-1" do
20
+ roles ["web"]
21
+ end
22
+ end
23
+ end
24
+ @node = @cloud.nodes["web-1"]
25
+ end
26
+
27
+
28
+ should "raise exception on space in name" do
29
+ assert_raise StandardError do
30
+ @cloud = aws_cloud :test do
31
+ keypair_name "XXXXXXX-keypair"
32
+ keypair_file "/path/to/id_rsa-XXXXXXX-keypair"
33
+ roles {}
34
+ nodes do
35
+ ec2_node "foo bar" do
36
+ roles ["web"]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ should "be invalid due to missing role map" do
44
+ @node.roles nil
45
+ @node.validate
46
+ assert !@node.valid?
47
+ assert @node.validation_errors.any? {|message| !message.index("missing roles map").nil? }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,19 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for Maestro::OperatingSystem
4
+ class TestOperatingSystem < Test::Unit::TestCase
5
+
6
+ context "Maestro::OperatingSystem" do
7
+ setup do
8
+ end
9
+
10
+ should "raise an error on invalid etc_issue_str" do
11
+ e = assert_raise(StandardError) {os = Maestro::OperatingSystem.create_from_etc_issue(nil)}
12
+ assert_match(/Invalid etc_issue_str/i, e.message)
13
+
14
+ e2 = assert_raise(StandardError) {os = Maestro::OperatingSystem.create_from_etc_issue('')}
15
+ assert_match(/Invalid etc_issue_str/i, e2.message)
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,77 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for Rails mode
4
+ class TestRailsMode < Test::Unit::TestCase
5
+
6
+ context "Rails mode" do
7
+ teardown do
8
+ Object.send(:remove_const, "RAILS_ROOT")
9
+ end
10
+
11
+ should "be invalid due to missing RAILS_ROOT" do
12
+ result = Maestro.validate_configs
13
+ assert !result[0], result[1]
14
+ assert result[1].any? {|message| !message.index("Maestro not configured correctly").nil? }
15
+ # so teardown doesn't fail
16
+ Object.const_set("RAILS_ROOT", "blah")
17
+ end
18
+
19
+ should "be invalid due to missing maestro directory" do
20
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-missing-maestro'))
21
+ result = Maestro.validate_configs
22
+ assert !result[0], result[1]
23
+ assert result[1].any? {|message| !message.index("Maestro config directory does not exist").nil? }
24
+ end
25
+
26
+ should "be invalid due to maestro not a directory" do
27
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-maestro-not-a-directory'))
28
+ result = Maestro.validate_configs
29
+ assert !result[0], result[1]
30
+ assert result[1].any? {|message| !message.index("Maestro config directory is not a directory").nil? }
31
+ end
32
+
33
+ should "be invalid due to missing clouds directory" do
34
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-missing-clouds'))
35
+ result = Maestro.validate_configs
36
+ assert !result[0], result[1]
37
+ assert result[1].any? {|message| !message.index("Maestro clouds config directory does not exist").nil? }
38
+ end
39
+
40
+ should "be invalid due to clouds not a directory" do
41
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-clouds-not-a-directory'))
42
+ result = Maestro.validate_configs
43
+ assert !result[0], result[1]
44
+ assert result[1].any? {|message| !message.index("Maestro clouds config directory is not a directory").nil? }
45
+ end
46
+
47
+ should "be invalid due to missing cookbooks directory" do
48
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-missing-cookbooks'))
49
+ result = Maestro.validate_configs
50
+ assert !result[0], result[1]
51
+ assert result[1].any? {|message| !message.index("Chef cookbooks directory does not exist").nil? }
52
+ end
53
+
54
+ should "be invalid due to cookbooks not a directory" do
55
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-cookbooks-not-a-directory'))
56
+ result = Maestro.validate_configs
57
+ assert !result[0], result[1]
58
+ assert result[1].any? {|message| !message.index("Chef cookbooks directory is not a directory").nil? }
59
+ end
60
+
61
+ should "be invalid due to missing roles directory" do
62
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-missing-roles'))
63
+ result = Maestro.validate_configs
64
+ assert !result[0], result[1]
65
+ assert result[1].any? {|message| !message.index("Chef roles directory does not exist").nil? }
66
+ end
67
+
68
+ should "be invalid due to roles not a directory" do
69
+ Object.const_set("RAILS_ROOT", File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'invalid-roles-not-a-directory'))
70
+ result = Maestro.validate_configs
71
+ assert !result[0], result[1]
72
+ assert result[1].any? {|message| !message.index("Chef roles directory is not a directory").nil? }
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,59 @@
1
+ require 'helper'
2
+
3
+ # Unit tests for Maestro::Role
4
+ class TestRole < Test::Unit::TestCase
5
+
6
+ context "Maestro::Role" do
7
+ setup do
8
+ @cloud = aws_cloud :test do
9
+ keypair_name "XXXXXXX-keypair"
10
+ keypair_file "/path/to/id_rsa-XXXXXXX-keypair"
11
+
12
+ roles do
13
+ role "web" do
14
+ public_ports [80, 443]
15
+ end
16
+ end
17
+ nodes {}
18
+ end
19
+ @role = @cloud.roles["web"]
20
+ end
21
+
22
+
23
+ should "raise exception on space in name" do
24
+ assert_raise StandardError do
25
+ @cloud = aws_cloud :test do
26
+ keypair_name "XXXXXXX-keypair"
27
+ keypair_file "/path/to/id_rsa-XXXXXXX-keypair"
28
+
29
+ roles do
30
+ role "foo bar" do
31
+ public_ports [80, 443]
32
+ end
33
+ end
34
+ nodes {}
35
+ end
36
+ end
37
+ end
38
+
39
+ should "be invalid due to public_ports not being an Array" do
40
+ @role.public_ports String.new
41
+ @role.validate
42
+ assert !@role.valid?
43
+ assert @role.validation_errors.any? {|message| !message.index("public_ports attribute must be an Array (found String)").nil? }
44
+ end
45
+
46
+ should "be invalid due to public_ports containing a non-number" do
47
+ @role.public_ports ["foo", "bar"]
48
+ @role.validate
49
+ assert !@role.valid?
50
+ assert @role.validation_errors.any? {|message| !message.index("public_ports attribute must be an Array of numbers").nil? }
51
+ end
52
+
53
+ should "be valid" do
54
+ @role.validate
55
+ assert @role.valid?
56
+ assert @role.validation_errors.empty?
57
+ end
58
+ end
59
+ end