dew 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/dew/models/account.rb +11 -6
- data/lib/dew/models/environment.rb +29 -15
- data/lib/dew/models/profile.rb +46 -29
- data/lib/dew/models/server.rb +42 -10
- data/lib/dew/version.rb +1 -1
- data/spec/dew/cloud_spec.rb +1 -1
- data/spec/dew/controllers/amis_controller_spec.rb +1 -1
- data/spec/dew/controllers/deploy_controller_spec.rb +2 -2
- data/spec/dew/controllers/environments_controller_spec.rb +1 -1
- data/spec/dew/models/account_spec.rb +25 -20
- data/spec/dew/models/database_spec.rb +1 -1
- data/spec/dew/models/deploy/puge_spec.rb +1 -1
- data/spec/dew/models/deploy/run_spec.rb +2 -2
- data/spec/dew/models/environment_spec.rb +155 -90
- data/spec/dew/models/fog_model_spec.rb +2 -2
- data/spec/dew/models/profile_spec.rb +32 -8
- data/spec/dew/models/server_spec.rb +74 -9
- data/spec/dew/password_spec.rb +2 -2
- data/spec/dew/view_spec.rb +1 -1
- data/spec/{dew/spec_helper.rb → spec_helper.rb} +0 -0
- metadata +32 -32
data/lib/dew/models/account.rb
CHANGED
@@ -2,16 +2,24 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
class Account
|
4
4
|
|
5
|
+
def initialize(yaml)
|
6
|
+
@yaml = yaml
|
7
|
+
end
|
8
|
+
|
5
9
|
def self.read(account_name)
|
6
|
-
Account.new
|
10
|
+
Account.new(YAML.load_file(account_path(account_name)))
|
7
11
|
end
|
8
12
|
|
9
13
|
def self.user_ids
|
10
|
-
Dir[
|
11
|
-
|
14
|
+
Dir[account_path('*')].map do |filename|
|
15
|
+
read(File.basename(filename, '.yaml')).aws_user_id
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
19
|
+
def self.account_path(account_name)
|
20
|
+
File.join(ENV['HOME'], '.dew', 'accounts', "#{account_name}.yaml")
|
21
|
+
end
|
22
|
+
|
15
23
|
def aws_access_key_id
|
16
24
|
@yaml['aws']['access_key_id']
|
17
25
|
end
|
@@ -36,7 +44,4 @@ class Account
|
|
36
44
|
@yaml['dns']['domain']
|
37
45
|
end
|
38
46
|
|
39
|
-
def initialize(yaml)
|
40
|
-
@yaml = yaml
|
41
|
-
end
|
42
47
|
end
|
@@ -5,7 +5,7 @@ class Environment
|
|
5
5
|
|
6
6
|
attr_reader :name, :servers, :database
|
7
7
|
|
8
|
-
def initialize
|
8
|
+
def initialize(name, servers=[], database=nil)
|
9
9
|
@name = name
|
10
10
|
@servers = servers
|
11
11
|
@database = database
|
@@ -34,14 +34,23 @@ class Environment
|
|
34
34
|
environment.add_database(profile.rds_size, profile.rds_storage_size, password) if profile.has_rds?
|
35
35
|
|
36
36
|
(1..profile.count).each do
|
37
|
-
environment.add_server(
|
37
|
+
environment.add_server(
|
38
|
+
profile.username,
|
39
|
+
:ami => profile.ami,
|
40
|
+
:size => profile.size,
|
41
|
+
:keypair => profile.keypair,
|
42
|
+
:groups => profile.security_groups,
|
43
|
+
:disk_size => profile.instance_disk_size
|
44
|
+
)
|
38
45
|
end
|
39
46
|
|
40
47
|
environment.add_elb(profile.elb_listener_ports) if profile.has_elb?
|
41
48
|
|
42
49
|
environment.wait_until_ready
|
43
|
-
|
50
|
+
|
51
|
+
environment.resize_disks if profile.instance_disk_size?
|
44
52
|
environment.configure_servers_for_database password if profile.has_rds?
|
53
|
+
|
45
54
|
Inform.info "Environment %{name} ready!", :name => name
|
46
55
|
environment
|
47
56
|
end
|
@@ -117,18 +126,17 @@ class Environment
|
|
117
126
|
end
|
118
127
|
end
|
119
128
|
|
120
|
-
def add_server(
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
129
|
+
def add_server(username, create_options)
|
130
|
+
server_name = "#{name} #{servers.count + 1}"
|
131
|
+
|
132
|
+
server = Server.create!(create_options)
|
133
|
+
server.add_tag('Environment', name)
|
134
|
+
server.add_tag('Creator', ENV['USER'])
|
135
|
+
server.add_tag('Name', server_name)
|
136
|
+
server.add_tag('Username', username) # Needed for SSH
|
137
|
+
Inform.debug("%{name} ID: %{id} AZ: %{az}", :name => server_name, :id =>server.id, :az => server.availability_zone)
|
138
|
+
|
139
|
+
servers << server
|
132
140
|
end
|
133
141
|
|
134
142
|
def add_server_to_elb server
|
@@ -185,6 +193,12 @@ class Environment
|
|
185
193
|
end
|
186
194
|
end
|
187
195
|
|
196
|
+
def resize_disks
|
197
|
+
Inform.info "Resizing disks on servers" do
|
198
|
+
servers.each { |s| s.resize_disk }
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
188
202
|
def elb
|
189
203
|
@elb ||= Cloud.elb.load_balancers.detect { |elb| elb.id == name } # XXX - need to refactor
|
190
204
|
end
|
data/lib/dew/models/profile.rb
CHANGED
@@ -5,31 +5,22 @@ class Profile
|
|
5
5
|
attr_reader :profile_name
|
6
6
|
attr_accessor :ami, :size, :security_groups, :keypair, :count
|
7
7
|
attr_accessor :rds_size, :rds_storage_size, :elb_listener_ports, :username
|
8
|
-
|
9
|
-
|
8
|
+
attr_reader :instance_disk_size
|
9
|
+
|
10
|
+
AWS_RESOURCES = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'aws_resources.yaml'))
|
10
11
|
|
11
12
|
DEFAULT_RDS_STORAGE_SIZE = 5
|
12
|
-
|
13
|
+
DEFAULT_USERNAME = 'ubuntu'
|
14
|
+
|
13
15
|
def self.read(profile_name)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
profile.count = yaml['instances']['count'].to_i
|
23
|
-
profile.username = yaml['instances']['username'] if yaml['instances'].include?('username')
|
24
|
-
end
|
25
|
-
if yaml['elb']
|
26
|
-
profile.elb_listener_ports = yaml['elb']['listener_ports']
|
27
|
-
end
|
28
|
-
if yaml['rds']
|
29
|
-
profile.rds_size = yaml['rds']['size']
|
30
|
-
profile.rds_storage_size = yaml['rds'].fetch('storage', DEFAULT_RDS_STORAGE_SIZE)
|
31
|
-
end
|
32
|
-
profile
|
16
|
+
new(
|
17
|
+
profile_name,
|
18
|
+
YAML.load_file(profile_path(profile_name))
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.profile_path(profile_name)
|
23
|
+
File.join(ENV['HOME'], '.dew', 'profiles', "#{profile_name}.yaml")
|
33
24
|
end
|
34
25
|
|
35
26
|
def has_elb?
|
@@ -40,18 +31,40 @@ class Profile
|
|
40
31
|
rds_size != nil
|
41
32
|
end
|
42
33
|
|
43
|
-
def initialize(profile_name)
|
34
|
+
def initialize(profile_name, init_yaml = nil)
|
44
35
|
@profile_name = profile_name
|
45
|
-
|
46
|
-
|
36
|
+
populate_from_yaml(Cloud.region, init_yaml) if init_yaml
|
37
|
+
end
|
38
|
+
|
39
|
+
def populate_from_yaml(region, yaml)
|
40
|
+
@username = DEFAULT_USERNAME # do we actually need this? There are no instances...
|
41
|
+
|
42
|
+
if yaml['instances']
|
43
|
+
@ami = yaml['instances'].fetch('amis', {})[region]
|
44
|
+
@size = yaml['instances']['size']
|
45
|
+
@security_groups = yaml['instances'].fetch('security-groups', ['default']) #TODO is this fallback tested?
|
46
|
+
@keypair = yaml['instances']['keypair']
|
47
|
+
@count = yaml['instances']['count'].to_i
|
48
|
+
@username = yaml['instances'].fetch('username', DEFAULT_USERNAME) #TODO is this fallback tested?
|
49
|
+
@instance_disk_size = yaml['instances'].fetch('disk-size', nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
if yaml['elb']
|
53
|
+
@elb_listener_ports = yaml['elb']['listener_ports']
|
54
|
+
end
|
55
|
+
|
56
|
+
if yaml['rds']
|
57
|
+
@rds_size = yaml['rds']['size']
|
58
|
+
@rds_storage_size = yaml['rds'].fetch('storage', DEFAULT_RDS_STORAGE_SIZE)
|
59
|
+
end
|
47
60
|
end
|
61
|
+
|
62
|
+
TO_STRING_TEMPLATE = "%{memory} GB memory, %{processor} ECUs processor, %{storage} GB storage, %{platform}-bit platform"
|
48
63
|
|
49
64
|
def self.size_to_s(size)
|
50
|
-
#instance_str = "%{memory} memory, %{processor} processor, %{storage} storage, %{platform} platform, %{io_performance} I/O performance"
|
51
|
-
instance_str = "%{memory} GB memory, %{processor} ECUs processor, %{storage} GB storage, %{platform}-bit platform, %{io_performance} I/O performance"
|
52
65
|
flavor = Cloud.compute.flavors.detect { |f| f.id == size }
|
53
|
-
instance_hash = { :memory => flavor.ram.to_s, :processor => flavor.cores.to_s, :storage => flavor.disk.to_s, :platform => flavor.bits.to_s
|
54
|
-
instance_hash.inject(
|
66
|
+
instance_hash = { :memory => flavor.ram.to_s, :processor => flavor.cores.to_s, :storage => flavor.disk.to_s, :platform => flavor.bits.to_s }
|
67
|
+
instance_hash.inject(TO_STRING_TEMPLATE) { |res,(k,v)| res.gsub(/%\{#{k}\}/, v) }
|
55
68
|
end
|
56
69
|
|
57
70
|
def to_s
|
@@ -65,4 +78,8 @@ class Profile
|
|
65
78
|
t << ['keypair', keypair.inspect]
|
66
79
|
}.to_s
|
67
80
|
end
|
81
|
+
|
82
|
+
def instance_disk_size?
|
83
|
+
!!@instance_disk_size
|
84
|
+
end
|
68
85
|
end
|
data/lib/dew/models/server.rb
CHANGED
@@ -1,12 +1,40 @@
|
|
1
1
|
class Server < FogModel
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
TAG_CREATION_TIMEOUT = 60
|
3
|
+
AMI_RECOGNITION_TIMEOUT = 60
|
4
|
+
DEFAULT_SSH_CONNECTION_TIMEOUT = 180
|
5
|
+
|
6
6
|
RUNNING_SERVER_STATES = %w{pending running}
|
7
7
|
|
8
|
-
def self.create!
|
9
|
-
|
8
|
+
def self.create!(options)
|
9
|
+
ami = options.fetch(:ami)
|
10
|
+
size = options.fetch(:size)
|
11
|
+
keypair = options.fetch(:keypair)
|
12
|
+
groups = options.fetch(:groups)
|
13
|
+
disk_size = options.fetch(:disk_size, nil)
|
14
|
+
|
15
|
+
Inform.info "Creating server using AMI %{ami} of size %{size}, keypair %{keypair} and security groups %{groups}",
|
16
|
+
:ami => ami, :size => size, :keypair => keypair, :groups => groups.join(',') do
|
17
|
+
|
18
|
+
server_options = {
|
19
|
+
:image_id => ami,
|
20
|
+
:flavor_id => size,
|
21
|
+
:key_name => keypair,
|
22
|
+
:groups => groups
|
23
|
+
}
|
24
|
+
|
25
|
+
if disk_size
|
26
|
+
server_options.merge!(
|
27
|
+
:block_device_mapping => [
|
28
|
+
{
|
29
|
+
'DeviceName' => '/dev/sda1',
|
30
|
+
'Ebs.VolumeSize' => disk_size.to_s
|
31
|
+
}
|
32
|
+
]
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
new(Cloud.compute.servers.create(server_options))
|
37
|
+
end
|
10
38
|
end
|
11
39
|
|
12
40
|
def self.find tag_name, tag_value
|
@@ -18,15 +46,19 @@ class Server < FogModel
|
|
18
46
|
end
|
19
47
|
|
20
48
|
def add_tag key, val
|
21
|
-
try_for(
|
49
|
+
try_for(TAG_CREATION_TIMEOUT) do
|
22
50
|
Cloud.compute.tags.create(:resource_id => id, :key => key, :value => val)
|
23
|
-
|
51
|
+
end
|
24
52
|
end
|
25
53
|
|
26
54
|
def configure_for_database database, password
|
27
55
|
ssh.write(database.db_environment_file(password), '/tmp/envfile')
|
28
56
|
ssh.run('sudo mv /tmp/envfile /etc/environment')
|
29
57
|
end
|
58
|
+
|
59
|
+
def resize_disk
|
60
|
+
ssh.run('sudo resize2fs -p /dev/sda1')
|
61
|
+
end
|
30
62
|
|
31
63
|
def username
|
32
64
|
fog_object.tags['Username'] || 'ubuntu'
|
@@ -40,7 +72,7 @@ class Server < FogModel
|
|
40
72
|
Gofer::Host.new(public_ip_address, username, :port => ssh_port, :key_data => [File.read(Cloud.keyfile_path(key_name))], :paranoid => false, :quiet => true)
|
41
73
|
end
|
42
74
|
|
43
|
-
def wait_until_ready ssh_timeout=
|
75
|
+
def wait_until_ready ssh_timeout=DEFAULT_SSH_CONNECTION_TIMEOUT
|
44
76
|
super()
|
45
77
|
Inform.debug("%{id} online at %{ip}, waiting for SSH connection...", :id => id, :ip => public_ip_address)
|
46
78
|
wait_for_ssh ssh_timeout
|
@@ -52,7 +84,7 @@ class Server < FogModel
|
|
52
84
|
|
53
85
|
Inform.debug("Created image at %{id}, waiting for AWS to recognize it...", :id => image_id)
|
54
86
|
# Sometimes takes a while for AWS to realise there's a new image...
|
55
|
-
image = Timeout::timeout(
|
87
|
+
image = Timeout::timeout(AMI_RECOGNITION_TIMEOUT) do
|
56
88
|
image = nil
|
57
89
|
while image == nil
|
58
90
|
image = Cloud.compute.images.get(image_id)
|
data/lib/dew/version.rb
CHANGED
data/spec/dew/cloud_spec.rb
CHANGED
@@ -1,29 +1,32 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Account do
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe '::read' do
|
6
6
|
it "should look for the named account file in the ~/.dew/accounts dir" do
|
7
7
|
name = 'a_development_name'
|
8
|
-
|
8
|
+
YAML.should_receive(:load_file).with("#{ENV['HOME']}/.dew/accounts/#{name}.yaml").and_return({})
|
9
9
|
Account.read(name)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
describe "parsing yaml" do
|
14
14
|
before :each do
|
15
|
-
|
15
|
+
YAML.stub(:load_file).and_return(yaml)
|
16
16
|
end
|
17
17
|
|
18
18
|
subject { Account.read('foo') }
|
19
19
|
|
20
20
|
describe "with an aws section" do
|
21
|
-
let (:yaml)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
let (:yaml) do
|
22
|
+
{
|
23
|
+
'aws' => {
|
24
|
+
'user_id' => '9999-3333-2222',
|
25
|
+
'access_key_id' => 'foo',
|
26
|
+
'secret_access_key' => 'bar'
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
27
30
|
|
28
31
|
it "should have a user_id stripped of dashes" do
|
29
32
|
subject.aws_user_id.should == '999933332222'
|
@@ -35,16 +38,18 @@ describe Account do
|
|
35
38
|
end
|
36
39
|
|
37
40
|
describe "with a DNS section" do
|
38
|
-
let (:yaml)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
it { subject.
|
41
|
+
let (:yaml) do
|
42
|
+
{
|
43
|
+
'dns' => {
|
44
|
+
'domain' => 'mydomain.com',
|
45
|
+
'key' => 'a1b2c3d4e5'
|
46
|
+
}
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
it { subject.should have_dns }
|
51
|
+
its(:dns_key) { should == 'a1b2c3d4e5' }
|
52
|
+
its(:dns_domain) { should == 'mydomain.com' }
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
@@ -1,10 +1,9 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Environment do
|
4
4
|
|
5
5
|
let (:name) { 'my-environment' }
|
6
|
-
let (:
|
7
|
-
let (:server) { double('Server', :id => 'i-12345', :add_tag => nil, :wait_until_ready => nil, :availability_zone => 'ap-southeast-1') }
|
6
|
+
# let (:server) { double('Server', :id => 'i-12345', :add_tag => nil, :wait_until_ready => nil, :availability_zone => 'ap-southeast-1') }
|
8
7
|
let(:groups) { %w(non_default) }
|
9
8
|
let (:server) { double('Server', :id => 'i-12345', :add_tag => nil, :wait_until_ready => nil, :availability_zone => 'ap-southeast-1', :groups => groups) }
|
10
9
|
let (:servers) { [] }
|
@@ -13,25 +12,26 @@ describe Environment do
|
|
13
12
|
let (:database) { double('Database') }
|
14
13
|
let(:keypair_available_in_aws) { true }
|
15
14
|
let(:profile_count) { 2 }
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
)
|
22
|
-
end
|
15
|
+
|
16
|
+
let(:instance_disk_size) { rand(234) }
|
17
|
+
let(:database) { mock('Database', :destroy => true, :wait_until_ready => true) }
|
18
|
+
|
19
|
+
let(:environment) { Environment.new(name, servers, database) }
|
23
20
|
|
24
21
|
before :each do
|
25
|
-
@environment = Environment.new(name, servers)
|
26
22
|
Cloud.connect(name, 'development')
|
27
23
|
Cloud.stub(:elb => elb, :keypair_exists? => keypair_available_in_aws)
|
28
24
|
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
it { @environment.database.should == nil }
|
26
|
+
describe "initialization" do
|
27
|
+
subject { environment }
|
33
28
|
|
34
|
-
|
29
|
+
its(:name) { should == name }
|
30
|
+
its(:servers) { should == [] }
|
31
|
+
its(:database) { should == database }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "::get" do
|
35
35
|
before :each do
|
36
36
|
Server.stub(:find => [])
|
37
37
|
Database.stub(:get => nil)
|
@@ -49,13 +49,26 @@ describe Environment do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
describe "
|
53
|
-
let (:
|
54
|
-
|
55
|
-
|
52
|
+
describe "::create" do
|
53
|
+
let (:profile) do
|
54
|
+
double('Profile',
|
55
|
+
:username => 'username',
|
56
|
+
:security_groups => %w(default),
|
57
|
+
:ami => 'ami-12345', :size => 'm1.large',
|
58
|
+
:keypair => 'devops', :count => profile_count,
|
59
|
+
:has_rds? => false, :has_elb? => false,
|
60
|
+
:instance_disk_size => instance_disk_size,
|
61
|
+
:instance_disk_size? => !!instance_disk_size
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
subject { Environment.create(name, profile) }
|
66
|
+
|
56
67
|
context "when environment name is invalid" do
|
68
|
+
let(:name) { 'my_bad_name' }
|
69
|
+
|
57
70
|
it "should raise an error" do
|
58
|
-
lambda {
|
71
|
+
lambda { subject }.should raise_error(ArgumentError, /does not match/)
|
59
72
|
end
|
60
73
|
end
|
61
74
|
|
@@ -63,16 +76,31 @@ describe Environment do
|
|
63
76
|
let(:keypair_available_in_aws) { false }
|
64
77
|
|
65
78
|
it "should raise an error" do
|
66
|
-
lambda {
|
79
|
+
lambda { subject }.should raise_error /is not available/
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when no instance disk size is specified" do
|
84
|
+
let(:instance_disk_size) { nil }
|
85
|
+
let(:environment) { mock(:add_server => true, :wait_until_ready => true) }
|
86
|
+
|
87
|
+
before do
|
88
|
+
Environment.stub(:new => environment)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should not resize_disks on the environment" do
|
92
|
+
environment.should_not_receive(:resize_disks)
|
93
|
+
subject
|
67
94
|
end
|
68
95
|
end
|
69
96
|
|
70
97
|
context "when profile keypair is available in AWS" do
|
71
98
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
99
|
+
let(:environment) { double(:environment, :name => name, :add_database => true, :wait_until_ready => true, :add_server => true, :resize_disks => true) }
|
100
|
+
|
101
|
+
before do
|
102
|
+
Environment.stub(:new => environment)
|
103
|
+
end
|
76
104
|
|
77
105
|
after { Environment.create(name, profile) }
|
78
106
|
|
@@ -80,12 +108,19 @@ describe Environment do
|
|
80
108
|
let(:profile_count) { 2 }
|
81
109
|
|
82
110
|
it "should add two instances to that environment with the chosen AMI, size and keypair" do
|
83
|
-
|
111
|
+
environment.should_receive(:add_server).with(
|
112
|
+
profile.username,
|
113
|
+
:ami => profile.ami,
|
114
|
+
:size => profile.size,
|
115
|
+
:keypair => profile.keypair,
|
116
|
+
:groups => profile.security_groups,
|
117
|
+
:disk_size => profile.instance_disk_size
|
118
|
+
).twice
|
84
119
|
end
|
85
120
|
end
|
86
121
|
|
87
122
|
it "should wait for our environment to become ready" do
|
88
|
-
|
123
|
+
environment.should_receive(:wait_until_ready)
|
89
124
|
end
|
90
125
|
|
91
126
|
describe "with an ELB specified in the profile" do
|
@@ -94,41 +129,41 @@ describe Environment do
|
|
94
129
|
end
|
95
130
|
|
96
131
|
it "should add an ELB to the environment with the required ports" do
|
97
|
-
|
132
|
+
environment.should_receive(:add_elb).with([80])
|
98
133
|
end
|
99
134
|
end
|
100
135
|
|
101
136
|
describe "with an RDS specified in the profile" do
|
102
137
|
before :each do
|
103
138
|
profile.stub(:has_rds? => true, :rds_size => 'db.m1.small', :rds_storage_size => 5)
|
104
|
-
|
139
|
+
environment.stub(:add_database => nil, :configure_servers_for_database => nil)
|
105
140
|
Password.stub(:random => 'abcdef')
|
106
141
|
end
|
107
142
|
|
108
143
|
it "should add an RDS to the environment with the required size and a random password" do
|
109
|
-
|
144
|
+
environment.should_receive(:add_database).with('db.m1.small', 5, 'abcdef')
|
110
145
|
end
|
111
146
|
|
112
147
|
it "should ask the environment to update the database configuration on the servers" do
|
113
|
-
|
148
|
+
environment.should_receive(:configure_servers_for_database).with('abcdef')
|
114
149
|
end
|
115
150
|
end
|
116
151
|
|
117
152
|
end
|
118
153
|
end
|
119
154
|
|
120
|
-
describe "
|
121
|
-
before
|
155
|
+
describe "::owners" do
|
156
|
+
before do
|
122
157
|
Cloud.should_receive(:valid_servers).at_least(1).and_return( [
|
123
158
|
double(:server, :tags => {"Environment" => "test-1", "Creator" => "chris" }),
|
124
159
|
double(:server, :tags => {"Environment" => "test-2", "Creator" => "ash" })
|
125
160
|
])
|
126
|
-
|
161
|
+
end
|
127
162
|
|
128
163
|
it { Environment.owners.should == [{:name=>"test-1", :owner=>"chris"}, {:name=>"test-2", :owner=>"ash"}] }
|
129
164
|
end
|
130
165
|
|
131
|
-
describe "
|
166
|
+
describe "::index" do
|
132
167
|
before {
|
133
168
|
Cloud.should_receive(:valid_servers).at_least(1).and_return( [
|
134
169
|
double(:server, :tags => {"Environment" => "test-1", "Creator" => "chris" }),
|
@@ -152,119 +187,140 @@ EOF
|
|
152
187
|
end
|
153
188
|
end
|
154
189
|
|
155
|
-
describe
|
156
|
-
before
|
190
|
+
describe '#show' do
|
191
|
+
before do
|
157
192
|
Cloud.stub_chain(:account, :aws_user_id).and_return('12345')
|
158
|
-
|
159
|
-
|
193
|
+
end
|
194
|
+
|
195
|
+
subject { environment.show }
|
160
196
|
|
161
197
|
context "with servers" do
|
162
198
|
let(:servers) { [server] }
|
163
|
-
|
164
|
-
|
199
|
+
let(:database) { nil }
|
200
|
+
|
201
|
+
before { environment.stub(:elb => nil) }
|
165
202
|
it "should show the servers" do
|
166
203
|
View.should_receive(:new).with(
|
167
204
|
"SERVERS", [server], %w(id flavor_id public_ip_address state created_at groups key_name availability_zone creator)
|
168
205
|
).and_return(double(:servers_view, :index => 'servers'))
|
206
|
+
subject
|
169
207
|
end
|
170
208
|
end
|
171
209
|
|
172
210
|
context "with an elb" do
|
211
|
+
let(:database) { nil }
|
212
|
+
|
173
213
|
it "should show the elb" do
|
174
214
|
elb_view = double(:elb_view)
|
175
215
|
View.should_receive(:new).with(
|
176
216
|
"ELB", [an_elb], %w(created_at dns_name instances availability_zones)
|
177
217
|
).and_return(elb_view)
|
178
218
|
elb_view.should_receive(:show).and_return('stuff')
|
219
|
+
subject
|
179
220
|
end
|
180
221
|
end
|
181
222
|
|
182
223
|
context "with a database" do
|
183
|
-
before {
|
184
|
-
@environment.stub(:database => database)
|
185
|
-
@environment.stub(:elb => nil)
|
186
|
-
}
|
224
|
+
before { environment.stub(:elb => nil) }
|
187
225
|
|
188
226
|
it "should show the database" do
|
189
227
|
View.should_receive(:new).with(
|
190
228
|
"DATABASE", [database], %w(flavor_id state created_at availability_zone db_security_groups)
|
191
|
-
).and_return(
|
229
|
+
).and_return(mock('database_view', :index => 'database', :show => "some_ stuff"))
|
230
|
+
subject
|
192
231
|
end
|
193
232
|
end
|
194
233
|
|
195
234
|
end
|
196
235
|
|
197
|
-
describe
|
198
|
-
|
199
|
-
|
236
|
+
describe '#destroy' do
|
237
|
+
subject { environment.destroy }
|
238
|
+
|
239
|
+
before do
|
240
|
+
environment.stub(:has_elb? => false)
|
200
241
|
end
|
242
|
+
|
201
243
|
it "should destroy the database if there is one" do
|
202
|
-
|
244
|
+
environment.stub(:database => database)
|
203
245
|
database.should_receive(:destroy)
|
204
|
-
|
246
|
+
|
247
|
+
subject
|
205
248
|
end
|
206
249
|
it "should destroy the servers if there are any" do
|
207
|
-
|
250
|
+
environment.stub(:servers => [server])
|
208
251
|
server.should_receive(:destroy)
|
209
|
-
|
252
|
+
|
253
|
+
subject
|
210
254
|
end
|
255
|
+
|
211
256
|
it "should destroy the ELB if there is one" do
|
212
|
-
|
257
|
+
environment.stub(:has_elb? => true)
|
213
258
|
elb.should_receive(:delete_load_balancer).with(name)
|
214
|
-
|
259
|
+
|
260
|
+
subject
|
215
261
|
end
|
216
262
|
end
|
217
263
|
|
218
|
-
describe
|
264
|
+
describe '#add_server' do
|
265
|
+
let(:create_options) { mock('create options') }
|
266
|
+
let(:username) { 'username' }
|
267
|
+
|
268
|
+
subject { environment.add_server(username, create_options) }
|
269
|
+
|
219
270
|
before :each do
|
220
|
-
@args = 'ami', 'size', 'keypair', %w(non_default)
|
221
271
|
Server.stub(:create!).and_return(server)
|
222
272
|
end
|
223
273
|
|
224
274
|
it "should create a Server from the provided ami, size and keypair" do
|
225
|
-
Server.should_receive(:create!).with(
|
226
|
-
|
275
|
+
Server.should_receive(:create!).with(create_options)
|
276
|
+
subject
|
227
277
|
end
|
228
278
|
|
229
279
|
it "should add the Server to its servers array" do
|
230
|
-
|
231
|
-
|
232
|
-
|
280
|
+
# don't use subject here, is memoized
|
281
|
+
environment.add_server(username, create_options)
|
282
|
+
environment.add_server(username, create_options)
|
283
|
+
environment.servers.should == [server, server]
|
233
284
|
end
|
234
285
|
|
235
286
|
it "should tag the server with the environment name, creator and username" do
|
236
287
|
server.should_receive(:add_tag).with('Environment', name)
|
237
288
|
server.should_receive(:add_tag).with('Creator', ENV['USER'])
|
238
289
|
server.should_receive(:add_tag).with('Username', 'username')
|
239
|
-
|
290
|
+
subject
|
240
291
|
end
|
241
292
|
|
242
293
|
it "should tag the server with an indexed name" do
|
243
294
|
server.should_receive(:add_tag).with('Name', "#{name} 1")
|
244
|
-
|
295
|
+
environment.add_server('username', create_options)
|
245
296
|
|
246
297
|
server.should_receive(:add_tag).with('Name', "#{name} 2")
|
247
|
-
|
298
|
+
environment.add_server('username', create_options)
|
248
299
|
end
|
249
300
|
end
|
250
301
|
|
251
|
-
describe
|
302
|
+
describe '#remove_server_from_elb' do
|
303
|
+
subject { environment.remove_server_from_elb(server) }
|
304
|
+
|
252
305
|
it "should remove the server from the ELB" do
|
253
306
|
elb.should_receive(:deregister_instances_from_load_balancer).with([server.id], name)
|
254
|
-
|
307
|
+
subject
|
255
308
|
end
|
256
309
|
end
|
257
310
|
|
258
|
-
describe
|
311
|
+
describe '#add_server_to_elb' do
|
312
|
+
subject { environment.add_server_to_elb(server) }
|
313
|
+
|
259
314
|
it "should add the server to the ELB" do
|
260
315
|
elb.should_receive(:register_instances_with_load_balancer).with([server.id], name)
|
261
|
-
|
316
|
+
subject
|
262
317
|
end
|
263
318
|
end
|
264
319
|
|
265
320
|
context "with one server" do
|
266
|
-
|
267
|
-
|
321
|
+
|
322
|
+
before do
|
323
|
+
environment.stub(:servers => [server])
|
268
324
|
end
|
269
325
|
|
270
326
|
describe :add_elb do
|
@@ -279,17 +335,17 @@ EOF
|
|
279
335
|
['ap-southeast-1a'], name,
|
280
336
|
[{'Protocol' => 'TCP', 'LoadBalancerPort' => 80, 'InstancePort' => 80}]
|
281
337
|
)
|
282
|
-
|
338
|
+
environment.add_elb [80]
|
283
339
|
end
|
284
340
|
it "should add the servers to the elb" do
|
285
341
|
elb.should_receive(:register_instances_with_load_balancer).with([server.id], name)
|
286
|
-
|
342
|
+
environment.add_elb [80]
|
287
343
|
end
|
288
344
|
|
289
345
|
end
|
290
346
|
|
291
347
|
describe :add_database do
|
292
|
-
before
|
348
|
+
before do
|
293
349
|
Database.stub(:create! => database)
|
294
350
|
end
|
295
351
|
|
@@ -297,12 +353,12 @@ EOF
|
|
297
353
|
|
298
354
|
it "should create an RDS of the requested size, using the environment name and a random password" do
|
299
355
|
Database.should_receive(:create!).with(name, 'db.m1.small', storage_size, 'password')
|
300
|
-
|
356
|
+
environment.add_database 'db.m1.small', storage_size, 'password'
|
301
357
|
end
|
302
358
|
|
303
359
|
it "should make the database available on the 'database' accessor" do
|
304
|
-
|
305
|
-
|
360
|
+
environment.add_database 'db.m1.small', storage_size, 'password'
|
361
|
+
environment.database.should == database
|
306
362
|
end
|
307
363
|
end
|
308
364
|
|
@@ -310,7 +366,7 @@ EOF
|
|
310
366
|
before {
|
311
367
|
Cloud.stub(:security_groups => { 'non_default' => double(:group, :ip_permissions => ip_permissions) } )
|
312
368
|
}
|
313
|
-
after {
|
369
|
+
after { environment.wait_until_ready }
|
314
370
|
|
315
371
|
context "with no ip_permissions" do
|
316
372
|
let(:ip_permissions) { [:some_ip_permissions] }
|
@@ -332,20 +388,20 @@ EOF
|
|
332
388
|
context "with an RDS" do
|
333
389
|
before :each do
|
334
390
|
Cloud.stub(:security_groups => { 'non_default' => double(:group, :ip_permissions => true) } )
|
335
|
-
|
391
|
+
environment.stub(:database => database)
|
336
392
|
end
|
337
393
|
|
338
394
|
describe :wait_until_ready do
|
339
395
|
it "should wait for the database to be ready" do
|
340
396
|
database.should_receive(:wait_until_ready)
|
341
|
-
|
397
|
+
environment.wait_until_ready
|
342
398
|
end
|
343
399
|
end
|
344
400
|
|
345
401
|
describe :configure_servers_for_database do
|
346
402
|
it "should ask each server to apply credentials from our database" do
|
347
403
|
server.should_receive(:configure_for_database).with(database, 'password')
|
348
|
-
|
404
|
+
environment.configure_servers_for_database 'password'
|
349
405
|
end
|
350
406
|
end
|
351
407
|
|
@@ -361,34 +417,43 @@ EOF
|
|
361
417
|
end
|
362
418
|
end
|
363
419
|
|
364
|
-
describe
|
420
|
+
describe '#has_elb?' do
|
421
|
+
subject { environment.has_elb? }
|
422
|
+
|
365
423
|
it "return true if we have a load balancer" do
|
366
424
|
mock_describe_load_balancers([{'LoadBalancerName' => name}])
|
367
|
-
|
425
|
+
subject.should be_true
|
368
426
|
end
|
369
427
|
|
370
428
|
it "return false if we don't" do
|
371
429
|
mock_describe_load_balancers([{'LoadBalancerName' => "XXXX"}])
|
372
|
-
|
430
|
+
subject.should be_false
|
373
431
|
end
|
374
432
|
|
375
433
|
end
|
376
434
|
|
377
435
|
describe "#show_json" do
|
378
|
-
|
379
436
|
let(:servers) { [mock(:dns_name => 'fish.com', :public_ip_address => '1.2.3.4'), mock(:dns_name => 'fish2.com', :public_ip_address => '1.2.3.5')] }
|
380
437
|
let(:output) { servers.map { |s| { 'public_dns' => s.dns_name, 'public_ip' => s.public_ip_address } } }
|
381
438
|
|
382
|
-
|
383
|
-
@environment.stub(:servers => servers)
|
384
|
-
end
|
385
|
-
|
386
|
-
subject { @environment.show_json }
|
439
|
+
subject { environment.show_json }
|
387
440
|
|
388
441
|
it "should return the correct JSON" do
|
389
442
|
STDOUT.should_receive(:puts).with(JSON.pretty_generate(output))
|
390
443
|
subject
|
391
444
|
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe '#resize_disks' do
|
448
|
+
|
449
|
+
let(:servers) { [mock('server1'), mock('server2')] }
|
450
|
+
|
451
|
+
subject { environment.resize_disks }
|
452
|
+
|
453
|
+
it "should resize_disk on each server" do
|
454
|
+
servers.each { |s| s.should_receive(:resize_disk).with() }
|
455
|
+
subject
|
456
|
+
end
|
392
457
|
|
393
458
|
end
|
394
459
|
|