dew 0.3.0 → 0.4.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/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
|
|