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.
- data/.document +5 -0
- data/.gitignore +25 -0
- data/LICENSE +23 -0
- data/README.rdoc +378 -0
- data/Rakefile +116 -0
- data/VERSION +1 -0
- data/lib/maestro.rb +354 -0
- data/lib/maestro/cloud.rb +384 -0
- data/lib/maestro/cloud/aws.rb +1231 -0
- data/lib/maestro/dsl_property.rb +15 -0
- data/lib/maestro/log4r/console_formatter.rb +18 -0
- data/lib/maestro/log4r/file_formatter.rb +24 -0
- data/lib/maestro/node.rb +123 -0
- data/lib/maestro/operating_system.rb +53 -0
- data/lib/maestro/operating_system/cent_os.rb +23 -0
- data/lib/maestro/operating_system/debian.rb +40 -0
- data/lib/maestro/operating_system/fedora.rb +23 -0
- data/lib/maestro/operating_system/ubuntu.rb +100 -0
- data/lib/maestro/role.rb +36 -0
- data/lib/maestro/tasks.rb +52 -0
- data/lib/maestro/validator.rb +32 -0
- data/rails/init.rb +1 -0
- data/test/integration/base_aws.rb +156 -0
- data/test/integration/fixtures/config/maestro/cookbooks/emacs/metadata.json +41 -0
- data/test/integration/fixtures/config/maestro/cookbooks/emacs/metadata.rb +3 -0
- data/test/integration/fixtures/config/maestro/cookbooks/emacs/recipes/default.rb +21 -0
- data/test/integration/fixtures/config/maestro/roles/default.json +9 -0
- data/test/integration/fixtures/config/maestro/roles/web.json +9 -0
- data/test/integration/helper.rb +8 -0
- data/test/integration/test_aws_cloud.rb +805 -0
- data/test/integration/test_cent_os.rb +104 -0
- data/test/integration/test_debian.rb +119 -0
- data/test/integration/test_fedora.rb +104 -0
- data/test/integration/test_ubuntu.rb +149 -0
- data/test/unit/fixtures/invalid-clouds-not-a-directory/config/maestro/clouds +1 -0
- data/test/unit/fixtures/invalid-cookbooks-not-a-directory/config/maestro/cookbooks +0 -0
- data/test/unit/fixtures/invalid-maestro-not-a-directory/config/maestro +0 -0
- data/test/unit/fixtures/invalid-missing-cookbooks/config/maestro/clouds/valid.yml +21 -0
- data/test/unit/fixtures/invalid-missing-roles/config/maestro/clouds/valid.yml +21 -0
- data/test/unit/fixtures/invalid-roles-not-a-directory/config/maestro/roles +1 -0
- data/test/unit/fixtures/ssh/id_rsa-maestro-test-keypair +27 -0
- data/test/unit/helper.rb +6 -0
- data/test/unit/test_aws_cloud.rb +133 -0
- data/test/unit/test_aws_ec2_node.rb +76 -0
- data/test/unit/test_aws_elb_node.rb +221 -0
- data/test/unit/test_aws_rds_node.rb +380 -0
- data/test/unit/test_cent_os.rb +28 -0
- data/test/unit/test_cloud.rb +142 -0
- data/test/unit/test_debian.rb +62 -0
- data/test/unit/test_fedora.rb +28 -0
- data/test/unit/test_invalid_mode.rb +11 -0
- data/test/unit/test_maestro.rb +140 -0
- data/test/unit/test_node.rb +50 -0
- data/test/unit/test_operating_system.rb +19 -0
- data/test/unit/test_rails_mode.rb +77 -0
- data/test/unit/test_role.rb +59 -0
- data/test/unit/test_standalone_mode.rb +75 -0
- data/test/unit/test_ubuntu.rb +95 -0
- data/the-maestro.gemspec +150 -0
- 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,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
|