dew 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.md +38 -0
- data/Rakefile +26 -0
- data/bin/dew +87 -0
- data/config/cucumber.yaml +4 -0
- data/features/create-ami.feature +16 -0
- data/features/create-environments.feature +46 -0
- data/features/deploy-puge.feature +16 -0
- data/features/step_definitions/aws-steps.rb +101 -0
- data/features/step_definitions/deploy-puge-steps.rb +27 -0
- data/features/support/env.rb +38 -0
- data/features/support/hooks.rb +10 -0
- data/lib/dew.rb +7 -0
- data/lib/dew/aws_resources.yaml +122 -0
- data/lib/dew/base_command.rb +24 -0
- data/lib/dew/cloud.rb +79 -0
- data/lib/dew/commands.rb +6 -0
- data/lib/dew/commands/ami.rb +67 -0
- data/lib/dew/commands/console.rb +17 -0
- data/lib/dew/commands/console/irb_override.rb +24 -0
- data/lib/dew/commands/deploy.rb +114 -0
- data/lib/dew/commands/deploy/templates/apache.conf.erb +28 -0
- data/lib/dew/commands/deploy/templates/known_hosts +2 -0
- data/lib/dew/commands/deploy/templates/rvmrc +2 -0
- data/lib/dew/commands/environments.rb +110 -0
- data/lib/dew/commands/tidy.rb +35 -0
- data/lib/dew/controllers.rb +3 -0
- data/lib/dew/controllers/amis_controller.rb +82 -0
- data/lib/dew/controllers/deploy_controller.rb +10 -0
- data/lib/dew/controllers/environments_controller.rb +48 -0
- data/lib/dew/models.rb +7 -0
- data/lib/dew/models/account.rb +30 -0
- data/lib/dew/models/database.rb +32 -0
- data/lib/dew/models/deploy.rb +2 -0
- data/lib/dew/models/deploy/puge.rb +61 -0
- data/lib/dew/models/deploy/run.rb +19 -0
- data/lib/dew/models/environment.rb +199 -0
- data/lib/dew/models/fog_model.rb +23 -0
- data/lib/dew/models/profile.rb +60 -0
- data/lib/dew/models/server.rb +134 -0
- data/lib/dew/password.rb +7 -0
- data/lib/dew/tasks/spec.rake +14 -0
- data/lib/dew/validations.rb +8 -0
- data/lib/dew/version.rb +3 -0
- data/lib/dew/view.rb +39 -0
- data/lib/tasks/spec.rake +14 -0
- data/spec/dew/cloud_spec.rb +90 -0
- data/spec/dew/controllers/amis_controller_spec.rb +137 -0
- data/spec/dew/controllers/deploy_controller_spec.rb +38 -0
- data/spec/dew/controllers/environments_controller_spec.rb +133 -0
- data/spec/dew/models/account_spec.rb +47 -0
- data/spec/dew/models/database_spec.rb +58 -0
- data/spec/dew/models/deploy/puge_spec.rb +72 -0
- data/spec/dew/models/deploy/run_spec.rb +38 -0
- data/spec/dew/models/environment_spec.rb +374 -0
- data/spec/dew/models/fog_model_spec.rb +24 -0
- data/spec/dew/models/profile_spec.rb +85 -0
- data/spec/dew/models/server_spec.rb +190 -0
- data/spec/dew/password_spec.rb +11 -0
- data/spec/dew/spec_helper.rb +22 -0
- data/spec/dew/view_spec.rb +38 -0
- metadata +284 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
|
2
|
+
|
3
|
+
describe Account do
|
4
|
+
|
5
|
+
describe :initialize do
|
6
|
+
it "should look for the named account file in the ~/.dew/accounts dir" do
|
7
|
+
name = 'a_development_name'
|
8
|
+
File.should_receive(:read).with("#{ENV['HOME']}/.dew/accounts/#{name}.yaml").and_return("---")
|
9
|
+
Account.read(name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "parsing yaml" do
|
14
|
+
before :each do
|
15
|
+
yaml =
|
16
|
+
"aws:
|
17
|
+
user_id: 9999-3333-2222
|
18
|
+
access_key_id: foo
|
19
|
+
secret_access_key: bar"
|
20
|
+
|
21
|
+
File.stub(:read).and_return(yaml)
|
22
|
+
@account = Account.read('foo')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have a user_id stripped of dashes" do
|
26
|
+
@account.aws_user_id.should == '999933332222'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have an aws access key id" do
|
30
|
+
@account.aws_access_key_id.should == 'foo'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have an aws secret access key" do
|
34
|
+
@account.aws_secret_access_key.should == 'bar'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".user_ids" do
|
39
|
+
it "should return the user_ids of each account file in config/accounts" do
|
40
|
+
Dir.should_receive(:[]).with("#{ENV['HOME']}/.dew/accounts/*.yaml").and_return(["accounts/file1.yaml", "accounts/file2.yaml"])
|
41
|
+
Account.should_receive(:read).with("file1").and_return(double('account', :aws_user_id => 'id1'))
|
42
|
+
Account.should_receive(:read).with("file2").and_return(double('account', :aws_user_id => 'id2'))
|
43
|
+
Account.user_ids.sort.should == ['id1', 'id2']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
|
2
|
+
|
3
|
+
describe Database do
|
4
|
+
|
5
|
+
let (:rds) { double('RDS', :servers => double('RDSServers')) }
|
6
|
+
let (:id) { 'mydatabase' }
|
7
|
+
let (:fog_database) { double('FogDatabase', :id => id) }
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
Cloud.stub(:rds => rds)
|
11
|
+
rds.servers.stub(:create => fog_database)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".create!" do
|
15
|
+
it "should ask Fog to create a new RDS with the provided name, size, username and password" do
|
16
|
+
rds.servers.should_receive(:create).with(hash_including(:id => id, :flavor_id => 'db.m1.small', :master_username => 'root', :password => 'password'))
|
17
|
+
Database.create!(id, 'db.m1.small', 'password')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return a new Database object with an ID" do
|
21
|
+
database = Database.create!(id, 'b', 'd')
|
22
|
+
database.id.should == id
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".get" do
|
27
|
+
it "should return nil if the database doesn't exist" do
|
28
|
+
rds.servers.should_receive(:get).with(id).and_return nil
|
29
|
+
Database.get(id).should == nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return a Database object if the database does exist" do
|
33
|
+
rds.servers.should_receive(:get).with(id).and_return fog_database
|
34
|
+
Database.get(id).id.should == id
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with a database created" do
|
40
|
+
before :each do
|
41
|
+
@database = Database.create!(id, 'db.m1.small', 'password')
|
42
|
+
fog_database.stub(:endpoint => {'Address' => '127.0.0.1'}, :master_username => 'root')
|
43
|
+
end
|
44
|
+
describe "db_environment_file" do
|
45
|
+
it "should return the contents of a file to use as /etc/environment that can be used to connct to this database" do
|
46
|
+
data = @database.db_environment_file('password')
|
47
|
+
data.should =~ /PUGE_DB_NAME=#{id}/
|
48
|
+
data.should =~ /PUGE_DB_USERNAME=root/
|
49
|
+
data.should =~ /PUGE_DB_PASSWORD=password/
|
50
|
+
data.should =~ /PUGE_DB_HOST=127.0.0.1/
|
51
|
+
end
|
52
|
+
end
|
53
|
+
describe :public_address do
|
54
|
+
it {@database.public_address.should == '127.0.0.1'}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../../spec_helper'))
|
2
|
+
|
3
|
+
describe Deploy::Puge do
|
4
|
+
|
5
|
+
let (:tag) { 'puge-1.16.1' }
|
6
|
+
let (:rails_env) { 'development' }
|
7
|
+
let (:gofer) { double('Gofer').as_null_object }
|
8
|
+
let (:servers) { (0..1).map { |i| double("Server #{i}").as_null_object} }
|
9
|
+
let (:environment) {double('Environment', :servers => servers, :database => database)}
|
10
|
+
let (:opts) { { 'tag' => tag, 'rails_env' => rails_env } }
|
11
|
+
let (:run_on_servers) { servers }
|
12
|
+
let (:base_path) { [ ENV['HOME'], '.dew', 'deploy', 'puge' ]}
|
13
|
+
|
14
|
+
shared_examples_for "script runner" do
|
15
|
+
it "should upload the script to the EC2 instance" do
|
16
|
+
run_on_servers.each do |server|
|
17
|
+
server.ssh.should_receive(:upload).with(File.join(base_path, script), File.join('.'))
|
18
|
+
end
|
19
|
+
Deploy::Puge.new(servers, opts).deploy
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should run the script" do
|
23
|
+
run_on_servers.each do |server|
|
24
|
+
server.ssh.should_receive(:run).with(['./' + script, arguments.map { |a| "'#{a}'"}].flatten.join(" "))
|
25
|
+
end
|
26
|
+
Deploy::Puge.new(servers, opts).deploy
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe :run do
|
31
|
+
|
32
|
+
describe "Discrete actions" do
|
33
|
+
|
34
|
+
describe "Clone PUGE" do
|
35
|
+
let (:script) { 'clone_puge.sh' }
|
36
|
+
let (:arguments) { [tag] }
|
37
|
+
it_should_behave_like "script runner"
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "Bundle install" do
|
41
|
+
let (:script) { 'bundle_install.sh' }
|
42
|
+
let (:arguments) { [] }
|
43
|
+
it_should_behave_like "script runner"
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "Setup Rails database" do
|
47
|
+
let (:run_on_servers) { servers.first }
|
48
|
+
let (:script) { 'setup_rails_database.sh' }
|
49
|
+
let (:arguments) { [rails_env] }
|
50
|
+
it_should_behave_like "script runner"
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "Generate PUGE WAR" do
|
54
|
+
let (:script) { 'generate_puge_war.sh' }
|
55
|
+
let (:arguments) { [rails_env] }
|
56
|
+
it_should_behave_like "script runner"
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "Copy PUGE WAR into Tomcat directory" do
|
60
|
+
let (:script) { 'copy_puge_war_into_tomcat.sh' }
|
61
|
+
let (:arguments) { [] }
|
62
|
+
it_should_behave_like "script runner"
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "Restart Tomcat" do
|
66
|
+
let (:script) { 'restart_tomcat.sh' }
|
67
|
+
let (:arguments) { [] }
|
68
|
+
it_should_behave_like "script runner"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
2
|
+
|
3
|
+
describe Deploy::Run do
|
4
|
+
|
5
|
+
let (:deploy_type) { 'puge' }
|
6
|
+
let (:tag) { 'puge-1.16.1' }
|
7
|
+
let (:rails_env) { 'development' }
|
8
|
+
let (:servers) { (0..1).map { |i| double("Server #{i}").as_null_object} }
|
9
|
+
let (:database) { double('Database')}
|
10
|
+
let (:environment) {double('Environment', :servers => servers, :database => database)}
|
11
|
+
let (:opts) { { 'tag' => tag, 'rails_env' => rails_env } }
|
12
|
+
|
13
|
+
before :each do
|
14
|
+
@deploy_run = Deploy::Run.new(deploy_type, environment, opts)
|
15
|
+
Cloud.stub(:region => 'ap-southeast-1', :account_name => 'myaccount', :profile_name => 'development')
|
16
|
+
end
|
17
|
+
|
18
|
+
it { @deploy_run.deploy_type.should == deploy_type }
|
19
|
+
it { @deploy_run.environment.should == environment }
|
20
|
+
it { @deploy_run.opts['tag'].should == tag }
|
21
|
+
it { @deploy_run.opts['rails_env'].should == rails_env }
|
22
|
+
|
23
|
+
describe :deploy do
|
24
|
+
before :each do
|
25
|
+
Deploy::Puge.stub(:run => nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should perform a deploy run for each associated server" do
|
29
|
+
deloy_puge_class_name = 'Deploy::Puge'
|
30
|
+
deploy_puge = double(deloy_puge_class_name)
|
31
|
+
|
32
|
+
Deploy.should_receive(:const_get).with(deploy_type.capitalize).and_return(deloy_puge_class_name)
|
33
|
+
deloy_puge_class_name.should_receive(:new).with(servers, opts).and_return(deploy_puge)
|
34
|
+
deploy_puge.should_receive(:deploy)
|
35
|
+
@deploy_run.deploy
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,374 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
|
2
|
+
|
3
|
+
describe Environment do
|
4
|
+
|
5
|
+
let (:name) { 'my-environment' }
|
6
|
+
let (:bad_name) { 'my_environment' }
|
7
|
+
let (:server) { double('Server', :id => 'i-12345', :add_tag => nil, :wait_until_ready => nil, :availability_zone => 'ap-southeast-1') }
|
8
|
+
let(:groups) { %w(non_default) }
|
9
|
+
let (:server) { double('Server', :id => 'i-12345', :add_tag => nil, :wait_until_ready => nil, :availability_zone => 'ap-southeast-1', :groups => groups) }
|
10
|
+
let (:servers) { [] }
|
11
|
+
let(:an_elb) { double('elb1', :id => 'my-environment') }
|
12
|
+
let (:elb) { double('ELB', :load_balancers => [an_elb]) }
|
13
|
+
let (:database) { double('Database') }
|
14
|
+
let(:keypair_available_in_aws) { true }
|
15
|
+
let(:profile_count) { 2 }
|
16
|
+
let (:profile) do
|
17
|
+
double('Profile',
|
18
|
+
:ami => 'ami-12345', :size => 'm1.large',
|
19
|
+
:keypair => 'devops', :count => profile_count,
|
20
|
+
:has_rds? => false, :has_elb? => false
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
before :each do
|
25
|
+
@environment = Environment.new(name, servers)
|
26
|
+
Cloud.connect(name, 'development')
|
27
|
+
Cloud.stub(:elb => elb, :keypair_exists? => keypair_available_in_aws)
|
28
|
+
end
|
29
|
+
|
30
|
+
it { @environment.name.should == name }
|
31
|
+
it { @environment.servers.should == [] }
|
32
|
+
it { @environment.database.should == nil }
|
33
|
+
|
34
|
+
describe ".get" do
|
35
|
+
before :each do
|
36
|
+
Server.stub(:find => [])
|
37
|
+
Database.stub(:get => nil)
|
38
|
+
end
|
39
|
+
it "should discover servers belonging to this environment" do
|
40
|
+
Server.should_receive(:find).with('Environment', name).and_return [server]
|
41
|
+
Environment.get(name).servers.should == [server]
|
42
|
+
end
|
43
|
+
it "should discover a database belonging to this environment" do
|
44
|
+
Database.should_receive(:get).with(name).and_return 'database'
|
45
|
+
Environment.get(name).database.should == 'database'
|
46
|
+
end
|
47
|
+
it "should return nil if no servers nor database is discovered for this environment" do
|
48
|
+
Environment.get(name).should == nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ".create" do
|
53
|
+
let (:security_groups) { %w(non_default) }
|
54
|
+
let(:profile) { double(:profile, :keypair => 'default', :security_groups => security_groups, :ami => 'i-1234', :has_rds? => false, :has_elb? => false, :count => 2, :size => 'small' ) }
|
55
|
+
|
56
|
+
context "when environment name is invalid" do
|
57
|
+
it "should raise an error" do
|
58
|
+
lambda { Environment.create(bad_name, profile) }.should raise_error /does not match/
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when profile keypair is not available in AWS" do
|
63
|
+
let(:keypair_available_in_aws) { false }
|
64
|
+
|
65
|
+
it "should raise an error" do
|
66
|
+
lambda { Environment.create(name, profile) }.should raise_error /is not available/
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when profile keypair is available in AWS" do
|
71
|
+
|
72
|
+
before {
|
73
|
+
@env = double(:environment, :name => name, :add_database => true, :wait_until_ready => true, :add_server => true)
|
74
|
+
Environment.should_receive(:new).with(name).and_return(@env)
|
75
|
+
}
|
76
|
+
|
77
|
+
after { Environment.create(name, profile) }
|
78
|
+
|
79
|
+
context "with a profile count of 2" do
|
80
|
+
let(:profile_count) { 2 }
|
81
|
+
|
82
|
+
it "should add two instances to that environment with the chosen AMI, size and keypair" do
|
83
|
+
@env.should_receive(:add_server).with(profile.ami, profile.size, profile.keypair, profile.security_groups).twice
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should wait for our environment to become ready" do
|
88
|
+
@env.should_receive(:wait_until_ready)
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "with an ELB specified in the profile" do
|
92
|
+
before :each do
|
93
|
+
profile.stub(:has_elb? => true, :elb_listener_ports => [80])
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should add an ELB to the environment with the required ports" do
|
97
|
+
@env.should_receive(:add_elb).with([80])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "with an RDS specified in the profile" do
|
102
|
+
before :each do
|
103
|
+
profile.stub(:has_rds? => true, :rds_size => 'db.m1.small')
|
104
|
+
@env.stub(:add_database => nil, :configure_servers_for_database => nil)
|
105
|
+
Password.stub(:random => 'abcdef')
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should add an RDS to the environment with the required size and a random password" do
|
109
|
+
@env.should_receive(:add_database).with('db.m1.small', 'abcdef')
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should ask the environment to update the database configuration on the servers" do
|
113
|
+
@env.should_receive(:configure_servers_for_database).with('abcdef')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe ".names" do
|
121
|
+
before {
|
122
|
+
Cloud.should_receive(:valid_servers).at_least(1).and_return( [
|
123
|
+
double(:server, :tags => {"Environment" => "test-1", "Creator" => "chris" }),
|
124
|
+
double(:server, :tags => {"Environment" => "test-2", "Creator" => "ash" })
|
125
|
+
])
|
126
|
+
}
|
127
|
+
|
128
|
+
it { Environment.owners.should == [{:name=>"test-1", :owner=>"chris"}, {:name=>"test-2", :owner=>"ash"}] }
|
129
|
+
end
|
130
|
+
|
131
|
+
describe ".index" do
|
132
|
+
before {
|
133
|
+
Cloud.should_receive(:valid_servers).at_least(1).and_return( [
|
134
|
+
double(:server, :tags => {"Environment" => "test-1", "Creator" => "chris" }),
|
135
|
+
double(:server, :tags => {"Environment" => "test-2", "Creator" => "ash" })
|
136
|
+
])
|
137
|
+
}
|
138
|
+
after { Environment.index }
|
139
|
+
|
140
|
+
# TODO: Have the model return what is to be displayed rather than display it itself.
|
141
|
+
it "should index the environments" do
|
142
|
+
Inform.should_receive(:info).at_least(1).with( <<EOF
|
143
|
+
Environments:
|
144
|
+
+----------+---------+
|
145
|
+
| name | owner |
|
146
|
+
+----------+---------+
|
147
|
+
| "test-1" | "chris" |
|
148
|
+
| "test-2" | "ash" |
|
149
|
+
+----------+---------+
|
150
|
+
EOF
|
151
|
+
)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe :show do
|
156
|
+
before {
|
157
|
+
Cloud.stub_chain(:account, :aws_user_id).and_return('12345')
|
158
|
+
}
|
159
|
+
after { @environment.show }
|
160
|
+
|
161
|
+
context "with servers" do
|
162
|
+
let(:servers) { [server] }
|
163
|
+
|
164
|
+
before { @environment.stub(:elb => nil) }
|
165
|
+
it "should show the servers" do
|
166
|
+
View.should_receive(:new).with(
|
167
|
+
"SERVERS", [server], %w(id flavor_id public_ip_address state created_at groups key_name availability_zone creator)
|
168
|
+
).and_return(double(:servers_view, :index => 'servers'))
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "with an elb" do
|
173
|
+
it "should show the elb" do
|
174
|
+
elb_view = double(:elb_view)
|
175
|
+
View.should_receive(:new).with(
|
176
|
+
"ELB", [an_elb], %w(created_at dns_name instances availability_zones)
|
177
|
+
).and_return(elb_view)
|
178
|
+
elb_view.should_receive(:show).and_return('stuff')
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "with a database" do
|
183
|
+
before {
|
184
|
+
@environment.stub(:database => database)
|
185
|
+
@environment.stub(:elb => nil)
|
186
|
+
}
|
187
|
+
|
188
|
+
it "should show the database" do
|
189
|
+
View.should_receive(:new).with(
|
190
|
+
"DATABASE", [database], %w(flavor_id state created_at availability_zone db_security_groups)
|
191
|
+
).and_return(double(:database_view, :index => 'database', :show => "some_ stuff"))
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
describe :destroy do
|
198
|
+
before :each do
|
199
|
+
@environment.stub(:has_elb? => false)
|
200
|
+
end
|
201
|
+
it "should destroy the database if there is one" do
|
202
|
+
@environment.stub(:database => database)
|
203
|
+
database.should_receive(:destroy)
|
204
|
+
@environment.destroy
|
205
|
+
end
|
206
|
+
it "should destroy the servers if there are any" do
|
207
|
+
@environment.stub(:servers => [server])
|
208
|
+
server.should_receive(:destroy)
|
209
|
+
@environment.destroy
|
210
|
+
end
|
211
|
+
it "should destroy the ELB if there is one" do
|
212
|
+
@environment.stub(:has_elb? => true)
|
213
|
+
elb.should_receive(:delete_load_balancer).with(name)
|
214
|
+
@environment.destroy
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe :add_server do
|
219
|
+
before :each do
|
220
|
+
@args = 'ami', 'size', 'keypair', %w(non_default)
|
221
|
+
Server.stub(:create!).and_return(server)
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should create a Server from the provided ami, size and keypair" do
|
225
|
+
Server.should_receive(:create!).with(*@args)
|
226
|
+
@environment.add_server(*@args)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should add the Server to its servers array" do
|
230
|
+
@environment.add_server(*@args)
|
231
|
+
@environment.add_server(*@args)
|
232
|
+
@environment.servers.should == [server, server]
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should tag the server with the environment name and creator" do
|
236
|
+
server.should_receive(:add_tag).with('Environment', name)
|
237
|
+
server.should_receive(:add_tag).with('Creator', ENV['USER'])
|
238
|
+
@environment.add_server(*@args)
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should tag the server with an indexed name" do
|
242
|
+
server.should_receive(:add_tag).with('Name', "#{name} 1")
|
243
|
+
@environment.add_server(*@args)
|
244
|
+
|
245
|
+
server.should_receive(:add_tag).with('Name', "#{name} 2")
|
246
|
+
@environment.add_server(*@args)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe :remove_server_from_elb do
|
251
|
+
it "should remove the server from the ELB" do
|
252
|
+
elb.should_receive(:deregister_instances_from_load_balancer).with([server.id], name)
|
253
|
+
@environment.remove_server_from_elb(server)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe :add_server_to_elb do
|
258
|
+
it "should add the server to the ELB" do
|
259
|
+
elb.should_receive(:register_instances_with_load_balancer).with([server.id], name)
|
260
|
+
@environment.add_server_to_elb(server)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context "with one server" do
|
265
|
+
before :each do
|
266
|
+
@environment.stub(:servers => [server])
|
267
|
+
end
|
268
|
+
|
269
|
+
describe :add_elb do
|
270
|
+
before :each do
|
271
|
+
server.stub(:availability_zone => 'ap-southeast-1a')
|
272
|
+
elb.stub(:create_load_balancer => nil, :register_instances_with_load_balancer => nil)
|
273
|
+
end
|
274
|
+
it "should create the ELB using the provided listeners, environment name and the availability zones of the current servers" do
|
275
|
+
server.should_receive(:availability_zone).and_return('ap-southeast-1a')
|
276
|
+
|
277
|
+
elb.should_receive(:create_load_balancer).with(
|
278
|
+
['ap-southeast-1a'], name,
|
279
|
+
[{'Protocol' => 'TCP', 'LoadBalancerPort' => 80, 'InstancePort' => 80}]
|
280
|
+
)
|
281
|
+
@environment.add_elb [80]
|
282
|
+
end
|
283
|
+
it "should add the servers to the elb" do
|
284
|
+
elb.should_receive(:register_instances_with_load_balancer).with([server.id], name)
|
285
|
+
@environment.add_elb [80]
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
describe :add_database do
|
291
|
+
before :each do
|
292
|
+
Database.stub(:create! => database)
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should create an RDS of the requested size, using the environment name and a random password" do
|
296
|
+
Database.should_receive(:create!).with(name, 'db.m1.small', 'password')
|
297
|
+
@environment.add_database 'db.m1.small', 'password'
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should make the database available on the 'database' accessor" do
|
301
|
+
@environment.add_database 'db.m1.small', 'password'
|
302
|
+
@environment.database.should == database
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
describe :wait_until_ready do
|
307
|
+
before {
|
308
|
+
Cloud.stub(:security_groups => { 'non_default' => double(:group, :ip_permissions => ip_permissions) } )
|
309
|
+
}
|
310
|
+
after { @environment.wait_until_ready }
|
311
|
+
|
312
|
+
context "with no ip_permissions" do
|
313
|
+
let(:ip_permissions) { [:some_ip_permissions] }
|
314
|
+
|
315
|
+
it "should wait for each server to be ready" do
|
316
|
+
server.should_receive(:wait_until_ready)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
context "with ip_permissions" do
|
321
|
+
let(:ip_permissions) { [] }
|
322
|
+
|
323
|
+
it "should not wait for each server to be ready" do
|
324
|
+
server.should_not_receive(:wait_until_ready)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
context "with an RDS" do
|
330
|
+
before :each do
|
331
|
+
Cloud.stub(:security_groups => { 'non_default' => double(:group, :ip_permissions => true) } )
|
332
|
+
@environment.stub(:database => database)
|
333
|
+
end
|
334
|
+
|
335
|
+
describe :wait_until_ready do
|
336
|
+
it "should wait for the database to be ready" do
|
337
|
+
database.should_receive(:wait_until_ready)
|
338
|
+
@environment.wait_until_ready
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
describe :configure_servers_for_database do
|
343
|
+
it "should ask each server to apply credentials from our database" do
|
344
|
+
server.should_receive(:configure_for_database).with(database, 'password')
|
345
|
+
@environment.configure_servers_for_database 'password'
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def mock_describe_load_balancers load_balancers, name=nil
|
353
|
+
response = double('ELB Response', :body => { 'DescribeLoadBalancersResult' => { 'LoadBalancerDescriptions' => load_balancers }})
|
354
|
+
if name
|
355
|
+
elb.should_receive(:describe_load_balancers).with(name).and_return(response)
|
356
|
+
else
|
357
|
+
elb.should_receive(:describe_load_balancers).and_return(response)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
describe :has_elb? do
|
362
|
+
it "return true if we have a load balancer" do
|
363
|
+
mock_describe_load_balancers([{'LoadBalancerName' => name}])
|
364
|
+
@environment.has_elb?.should be_true
|
365
|
+
end
|
366
|
+
|
367
|
+
it "return false if we don't" do
|
368
|
+
mock_describe_load_balancers([{'LoadBalancerName' => "XXXX"}])
|
369
|
+
@environment.has_elb?.should be_false
|
370
|
+
end
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|