the-maestro 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|