conan 0.2.1 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -104,6 +104,7 @@ In this scenario, the configuration for the staging server will be produced by m
104
104
  * `db.json`
105
105
  * `staging.json`
106
106
 
107
+
107
108
  Furthermore, this server will have the `app` and `db` roles in Capistrano, with
108
109
  the usual meanings: the application will be deployed on this server, and the
109
110
  database migrations will be run.
@@ -0,0 +1,74 @@
1
+ {
2
+ "ubuntu 10.04": {
3
+ "ap-northeast-1": {
4
+ "64-bit": {
5
+ "ebs": "ami-36e65037",
6
+ "instance-store": "ami-baf94fbb"
7
+ },
8
+ "32-bit": {
9
+ "ebs": "ami-1ae6501b",
10
+ "instance-store": "ami-46f94f47"
11
+ }
12
+ },
13
+ "ap-southeast-1": {
14
+ "64-bit": {
15
+ "ebs": "ami-c0c98c92",
16
+ "instance-store": "ami-3cc98c6e"
17
+ },
18
+ "32-bit": {
19
+ "ebs": "ami-d8c98c8a",
20
+ "instance-store": "ami-76c98c24"
21
+ }
22
+ },
23
+ "eu-west-1": {
24
+ "64-bit": {
25
+ "ebs": "ami-81dde2f5",
26
+ "instance-store": "ami-3fdde24b"
27
+ },
28
+ "32-bit": {
29
+ "ebs": "ami-95dde2e1",
30
+ "instance-store": "ami-fddee189"
31
+ }
32
+ },
33
+ "sa-east-1": {
34
+ "64-bit": {
35
+ "ebs": "ami-645f8079",
36
+ "instance-store": "ami-7a5f8067"
37
+ },
38
+ "32-bit": {
39
+ "ebs": "ami-6a5f8077",
40
+ "instance-store": "ami-4a5f8057"
41
+ }
42
+ },
43
+ "us-east-1": {
44
+ "64-bit": {
45
+ "ebs": "ami-55dc0b3c",
46
+ "instance-store": "ami-35de095c"
47
+ },
48
+ "32-bit": {
49
+ "ebs": "ami-71dc0b18",
50
+ "instance-store": "ami-4fd00726"
51
+ }
52
+ },
53
+ "us-west-1": {
54
+ "64-bit": {
55
+ "ebs": "ami-a191cfe4",
56
+ "instance-store": "ami-3991cf7c"
57
+ },
58
+ "32-bit": {
59
+ "ebs": "ami-9991cfdc",
60
+ "instance-store": "ami-b390cef6"
61
+ }
62
+ },
63
+ "us-west-2": {
64
+ "64-bit": {
65
+ "ebs": "ami-8eb33ebe",
66
+ "instance-store": "ami-94b33ea4"
67
+ },
68
+ "32-bit": {
69
+ "ebs": "ami-8cb33ebc",
70
+ "instance-store": "ami-bcb33e8c"
71
+ }
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,343 @@
1
+ require "fileutils"
2
+ require "fog"
3
+ require "json"
4
+
5
+ module AWS
6
+ class Provision
7
+
8
+ def initialize(aws_config = {}, stage = 'production')
9
+ @aws_config = aws_config
10
+ @stage = stage
11
+ end
12
+
13
+ def describe_env_to_json(file_path)
14
+ servers_json = {}
15
+ servers = []
16
+ ["us-east-1", "us-west-1", "eu-west-1", "ap-southeast-1", "ap-northeast-1"].each do |region|
17
+ compute = Fog::Compute.new(:provider => :aws, :region => region)
18
+ compute.servers.all.each { |s| servers << s if s.state == 'running' }
19
+ end
20
+ stages = servers.map {|s| s.tags["stage"] }.uniq
21
+
22
+ stages.each do | stage|
23
+ servers_json[stage] = {}
24
+ servers.each do |server|
25
+ if server.tags["stage"] == stage
26
+ server_json = {}
27
+ server_json[:roles] = server.tags["roles"].split(", ") unless server.tags["roles"].nil?
28
+ server_json[:alias] = server.tags["name"]
29
+ servers_json[stage][server.dns_name] = server_json
30
+ end
31
+ end
32
+ end
33
+
34
+ File.open(file_path, "w") do |io|
35
+ io << JSON.pretty_generate(servers_json)
36
+ end
37
+ end
38
+
39
+ def build_env()
40
+
41
+ #we need to check the existance of ~/.fog
42
+
43
+ #first key_pairs
44
+ key_pairs = @aws_config["key_pairs"]
45
+
46
+ key_pairs.each do |name, conf|
47
+ create_key_pair(name, conf)
48
+ end unless key_pairs.nil?
49
+
50
+ security_groups = @aws_config["security"]
51
+
52
+ if security_groups.nil? or security_groups.size == 0
53
+ create_default_security_groups()
54
+ else
55
+ security_groups["ec2"].each do |name, conf|
56
+ create_ec2_security_group(name, conf)
57
+ end unless security_groups["ec2"].nil?
58
+
59
+ security_groups["rds"].each do |name, conf|
60
+ create_rds_security_group(name, conf)
61
+ end unless security_groups["rds"].nil?
62
+ end
63
+
64
+ @aws_config.each do |type, resources|
65
+ case type
66
+ when "ec2"
67
+ resources.each do |name, conf|
68
+ create_ec2_server(name, conf)
69
+ end
70
+ when "rds"
71
+ resources.each do |name, conf|
72
+ create_rds_server(name, conf)
73
+ end
74
+ when "s3"
75
+ resources.each do |name, conf|
76
+ create_s3_bucket(name, conf)
77
+ end
78
+ when "elb"
79
+ resources.each do |name,conf|
80
+ create_elb(name, conf)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ def create_key_pair(name, config = {})
87
+ new_conf = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
88
+ region = new_conf[:region] || "us-east-1"
89
+ compute = Fog::Compute.new(:provider => :aws, :region => region)
90
+
91
+ kp = compute.key_pairs.get(name)
92
+ if kp.nil?
93
+ #no key pair create and write it out
94
+ puts "Creating key-pair #{name}"
95
+ kp = compute.key_pairs.create(:name => name)
96
+
97
+ puts "Writing key into your .ssh directory and adding it to ssh agent"
98
+ File.open("#{ENV['HOME']}/.ssh/#{kp.name}.pem", "w") do |io|
99
+ io << kp.private_key
100
+ end
101
+ system("chmod 600 #{ENV['HOME']}/.ssh/#{kp.name}.pem")
102
+ system("ssh-add #{ENV['HOME']}/.ssh/#{kp.name}.pem")
103
+ else
104
+ puts "Key-pair #{name} already exists. Skipping"
105
+ end
106
+ end
107
+
108
+ def create_default_security_groups()
109
+ create_ec2_security_group('default', {:ports => ["22", "80"]})
110
+ create_rds_security_group('default', {:ec2_security_groups => ["default"]})
111
+ end
112
+
113
+ def create_ec2_security_group(name, config = {})
114
+ new_conf = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
115
+ region = new_conf[:region] || "us-east-1"
116
+
117
+ compute = Fog::Compute.new(:provider => :aws, :region => region)
118
+
119
+ sg_name = "#{@stage}-#{name}"
120
+
121
+ sg = compute.security_groups.get(sg_name)
122
+ if sg.nil?
123
+ puts "Creating EC2 Secruity Group #{sg_name}"
124
+ sg = compute.security_groups.create(:name => sg_name, :description => "#{name} Security Group for #{@stage}")
125
+ new_conf[:ports].each do |port|
126
+ sg.authorize_port_range(Range.new(port.to_i,port.to_i))
127
+ end unless new_conf[:ports].nil?
128
+ else
129
+ puts "EC2 Security Group #{sg_name} already exists. Skipping"
130
+ end
131
+
132
+ end
133
+
134
+ def create_rds_security_group(name, config = {})
135
+ unless Fog.mocking?
136
+ new_conf = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
137
+ region = new_conf[:region] || "us-east-1"
138
+ rds = Fog::AWS::RDS.new(:region => region)
139
+
140
+ rdssg_name = "#{@stage}-db-#{name}"
141
+
142
+ rdssg = rds.security_groups.get(rdssg_name)
143
+
144
+ if rdssg.nil?
145
+ puts "Creating RDS Security Group #{rdssg_name}"
146
+ rdssg = rds.security_groups.create(:id => rdssg_name, :description => "#{name} DB Security Group For #{@stage}")
147
+ new_conf[:ec2_security_groups].each do |ec2_group|
148
+ rdssg.authorize_ec2_security_group("#{@stage}-#{ec2_group}")
149
+ end
150
+ else
151
+ puts "RDS Security Group #{rdssg_name} already exists. Skipping"
152
+ end
153
+
154
+ end
155
+ end
156
+
157
+ def create_s3_bucket(name, config = {})
158
+ new_conf = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
159
+ region = new_conf[:region] || "us-east-1"
160
+
161
+ storage = Fog::Storage.new(:provider => :aws, :region => region)
162
+
163
+ begin
164
+ bucket = storage.get_bucket(name)
165
+ puts "S3 Bucket #{name} already exists. Skipping"
166
+ rescue Excon::Errors::NotFound
167
+ puts "Creating S3 Bucket #{name}"
168
+ storage.put_bucket(name)
169
+
170
+ acl = new_conf[:acl] || 'public-read'
171
+
172
+ storage.put_bucket_acl(name, acl)
173
+ end
174
+ end
175
+
176
+ def create_elb(name, config = {})
177
+ new_conf = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
178
+ region = new_conf[:region] || "us-east-1"
179
+
180
+ elb = Fog::AWS::ELB.new(:region => region)
181
+
182
+ zones = new_conf[:availability_zones] || all_availability_zones(region)
183
+
184
+ elb_name = "#{@stage}-#{name}"
185
+
186
+ lb = elb.load_balancers.get(elb_name)
187
+ if lb.nil?
188
+ puts "Creating Elastic Load Balancer #{elb_name}"
189
+
190
+ lb = elb.load_balancers.create(:id => elb_name, :availability_zones => zones)
191
+
192
+ #need to do listeners but for now stick with the default
193
+
194
+ compute = Fog::Compute.new(:provider => :aws, :region => region)
195
+
196
+ inst_servers = new_conf[:servers].map { |s| "#{@stage}-#{s}" } unless new_conf[:servers].nil?
197
+
198
+ compute.servers.all.each do |server|
199
+ #the mocking seems wrong
200
+ unless Fog.mocking?
201
+ name = server.tags["name"]
202
+ lb.register_instances(server.id) if (inst_servers.nil? or inst_servers.include?(name))
203
+ end
204
+ end
205
+ else
206
+ puts "Elastic Load Balancer #{elb_name} already exists. Skipping"
207
+ end
208
+
209
+ end
210
+
211
+ def create_ec2_server(name, config = {})
212
+ new_conf = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
213
+ region = new_conf[:region] || "us-east-1"
214
+
215
+ compute = Fog::Compute.new(:provider => :aws, :region => region)
216
+
217
+ default_key_name = compute.key_pairs.all.first.name
218
+
219
+ default_params = { :availability_zone => default_availability_zone(region),
220
+ :flavor_id => "m1.small",
221
+ :monitoring => true,
222
+ :key_name => default_key_name,
223
+ :root_device_type => "instance-store"
224
+ }
225
+
226
+ params = default_params.merge(new_conf)
227
+ params[:image_id] = default_image_id(region, params[:flavor_id], params[:root_device_type]) if params[:image_id].nil?
228
+
229
+ tags = {}
230
+
231
+ #need to bork if no name in config file
232
+ ec2_name = "#{@stage}-#{name}"
233
+
234
+ #need to parse all servers to see if this one exists
235
+ servers = compute.servers.all
236
+ server_exists = false
237
+ servers.each { |server| server_exists = true if server.tags["name"] == ec2_name and server.state == 'running' }
238
+
239
+ unless server_exists
240
+ puts "Creating EC2 Server named #{ec2_name}"
241
+ tags[:name] = ec2_name
242
+ tags[:stage] = @stage
243
+
244
+ if new_conf[:roles]
245
+ new_conf[:roles] << @stage unless new_conf[:roles].include? @stage
246
+ tags[:roles] = new_conf[:roles].join(', ')
247
+ else
248
+ tags[:roles] = "app, db, #{@stage}"
249
+ end
250
+
251
+ params[:tags] = tags
252
+
253
+ if new_conf[:groups] and new_conf[:groups].size > 0
254
+ params[:groups] = new_conf[:groups].collect { |g| "#{@stage}-#{g}" }
255
+ else
256
+ params[:groups] = ["#{@stage}-default"]
257
+ end
258
+
259
+ server = compute.servers.create(params)
260
+ server.wait_for { ready? }
261
+ else
262
+ puts "EC2 Server named #{ec2_name} already exists. Skipping"
263
+ end
264
+
265
+ end
266
+
267
+ def create_rds_server(name, config = {})
268
+ unless Fog.mocking?
269
+ new_conf = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
270
+ region = new_conf[:region] || "us-east-1"
271
+ rds = Fog::AWS::RDS.new(:region => region)
272
+ default_params = { :allocated_storage => 20,
273
+ :engine => 'mysql',
274
+ :master_username => 'root',
275
+ :password => 'password',
276
+ :backup_retention_period => 8,
277
+ :multi_az => false,
278
+ :db_name =>"production",
279
+ :availability_zone => default_availability_zone(region),
280
+ :flavor_id => 'db.m1.small'
281
+ }
282
+ params = default_params.merge(new_conf)
283
+
284
+ params[:id] = "#{@stage}-#{name}"
285
+
286
+ if new_conf[:db_security_groups] and new_conf[:db_security_groups].size > 0
287
+ params[:db_security_groups] = new_conf[:db_security_groups].collect { |g| "#{@stage}-db-#{g}" }
288
+ else
289
+ params[:db_security_groups] = ["#{@stage}-db-default"]
290
+ end
291
+
292
+ server = rds.servers.get(params[:id])
293
+
294
+ if server.nil?
295
+ puts "Creating RDS Server #{params[:id]}"
296
+ server = rds.servers.create(params)
297
+ else
298
+ puts "RDS Server #{params[:id]} aready exists. Skipping"
299
+ end
300
+ else
301
+ puts "Fog is mocking. Can't test with RDS Servers. Skipping"
302
+ end
303
+ end
304
+
305
+ private
306
+
307
+ def default_availability_zone(region)
308
+ #using availability zone b by default as a is often unavailable in us-east-1
309
+ "#{region}b"
310
+ end
311
+
312
+ def all_availability_zones(region)
313
+ case region
314
+ when "us-east-1"
315
+ #not using availability zone us-east-1a as it often fails
316
+ ["us-east-1b", "us-east-1c"]
317
+ when "us-west-1"
318
+ ["us-west-1a", "us-west-1b", "us-west-1c"]
319
+ when "eu-west-1"
320
+ ["eu-west-1a", "eu-west-1b"]
321
+ when "ap-northeast-1"
322
+ ["ap-northeast-1a", "ap-northeast-1a"]
323
+ when "ap-southeast-1"
324
+ ["ap-southeast-1a", "ap-southeast-1b"]
325
+ end
326
+ end
327
+
328
+ def default_image_id(region, flavor_id, root_device_type)
329
+ arch = ["m1.small", "t1.micro", "c1.medium"].include?(flavor_id) ? "32-bit" : "64-bit"
330
+
331
+ defaults = JSON.parse(File.read(File.expand_path(File.join(File.dirname(__FILE__), 'default_amis.json'))))
332
+
333
+ region_defaults = defaults["ubuntu 10.04"][region]
334
+ raise "Invalid Region" if region_defaults.nil?
335
+ default_ami = region_defaults[arch][root_device_type]
336
+
337
+ raise "Default AMI not found for #{region} #{flavor_id} #{root_device_type}" if default_ami.nil?
338
+ default_ami
339
+
340
+ end
341
+ end
342
+ end
343
+
@@ -0,0 +1,16 @@
1
+ require "fileutils"
2
+ require "json"
3
+ require File.expand_path(File.join(File.dirname(__FILE__), 'aws/provision'))
4
+
5
+ namespace :aws do
6
+
7
+ task :provision do
8
+ aws_config = JSON.parse(File.read("config/aws.json"))[stage] || {}
9
+ AWS::Provision.new(aws_config, stage).build_env
10
+ end
11
+
12
+ task :write_config do
13
+ AWS::Provision.new.describe_env_to_json("config/servers.json")
14
+ end
15
+ end
16
+
@@ -0,0 +1,5 @@
1
+ def _cset(name, *args, &block)
2
+ unless exists?(name)
3
+ set(name, *args, &block)
4
+ end
5
+ end
@@ -1,6 +1,12 @@
1
1
  module Conan
2
2
  class Deployment
3
3
  module Helpers
4
+ def _cset(name, *args, &block)
5
+ unless exists?(name)
6
+ set(name, *args, &block)
7
+ end
8
+ end
9
+
4
10
  def with_user(new_user, &blk)
5
11
  old_user = user
6
12
  return if old_user == new_user
@@ -43,13 +49,27 @@ module Conan
43
49
 
44
50
  class <<self
45
51
  def define_tasks(context)
46
- load_script(context, "deploy")
47
- load_script(context, "chef")
48
- load_script(context, "git")
52
+ load_script(context, "deployment/deploy")
53
+ load_script(context, "deployment/chef")
54
+
55
+ load_script(context, "deployment/git")
56
+
57
+ load_script(context, "cloud/tasks")
58
+
59
+ #need to change to only compile for rails 3.1
60
+ begin
61
+ rails_v = `bundle exec rails -v`.chomp.split(' ').last
62
+ if Gem::Version.new(rails_v) > Gem::Version.new('3.1.0')
63
+ load_script(context, "deployment/assets")
64
+ end
65
+ rescue
66
+ #not a rails or 3.1 app or bundle failed
67
+ end
68
+
49
69
  end
50
70
 
51
71
  def load_script(context, fragment)
52
- path = File.expand_path("../deployment/#{fragment}.rb", __FILE__)
72
+ path = File.expand_path("../#{fragment}.rb", __FILE__)
53
73
  code = File.read(path)
54
74
  context.instance_eval(code, path)
55
75
  end
@@ -0,0 +1,61 @@
1
+ def _cset(name, *args, &block)
2
+ unless exists?(name)
3
+ set(name, *args, &block)
4
+ end
5
+ end
6
+
7
+ _cset :asset_env, "RAILS_GROUPS=assets"
8
+ _cset :assets_prefix, "assets"
9
+
10
+ before 'deploy:finalize_update', 'deploy:assets:symlink'
11
+ after 'deploy:update_code', 'deploy:assets:precompile'
12
+
13
+ namespace :deploy do
14
+ namespace :assets do
15
+ desc <<-DESC
16
+ [internal] This task will set up a symlink to the shared directory \
17
+ for the assets directory. Assets are shared across deploys to avoid \
18
+ mid-deploy mismatches between old application html asking for assets \
19
+ and getting a 404 file not found error. The assets cache is shared \
20
+ for efficiency. If you cutomize the assets path prefix, override the \
21
+ :assets_prefix variable to match.
22
+ DESC
23
+ task :symlink, :roles => :app, :except => { :no_release => true } do
24
+ run <<-CMD
25
+ rm -rf #{latest_release}/public/#{assets_prefix} &&
26
+ mkdir -p #{latest_release}/public &&
27
+ mkdir -p #{shared_path}/assets &&
28
+ ln -s #{shared_path}/assets #{latest_release}/public/#{assets_prefix}
29
+ CMD
30
+ end
31
+
32
+ desc <<-DESC
33
+ Run the asset precompilation rake task. You can specify the full path \
34
+ to the rake executable by setting the rake variable. You can also \
35
+ specify additional environment variables to pass to rake via the \
36
+ asset_env variable. The defaults are:
37
+
38
+ set :rake, "rake"
39
+ set :rails_env, "production"
40
+ set :asset_env, "RAILS_GROUPS=assets"
41
+ DESC
42
+ task :precompile, :roles => :app, :except => { :no_release => true } do
43
+ run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile"
44
+ end
45
+
46
+ desc <<-DESC
47
+ Run the asset clean rake task. Use with caution, this will delete \
48
+ all of your compiled assets. You can specify the full path \
49
+ to the rake executable by setting the rake variable. You can also \
50
+ specify additional environment variables to pass to rake via the \
51
+ asset_env variable. The defaults are:
52
+
53
+ set :rake, "rake"
54
+ set :rails_env, "production"
55
+ set :asset_env, "RAILS_GROUPS=assets"
56
+ DESC
57
+ task :clean, :roles => :app, :except => { :no_release => true } do
58
+ run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:clean"
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  namespace :git do
2
- before "deploy:update_code", "git:tag_attempted_deploy"
2
+ before "deploy:update_code", "git:tag_attempted_deploy" unless deploy_via == :copy
3
3
  task :tag_attempted_deploy do
4
4
  git_tag branch, "#{stage}.last-deploy"
5
5
  end
@@ -7,5 +7,5 @@ namespace :git do
7
7
  task :tag_successful_deploy do
8
8
  git_tag branch, "#{stage}.last-successful-deploy"
9
9
  end
10
- after "deploy:smoke_test", "git:tag_successful_deploy"
10
+ after "deploy:smoke_test", "git:tag_successful_deploy" unless deploy_via == :copy
11
11
  end
@@ -1,4 +1,6 @@
1
1
  require "fileutils"
2
+ require "rubygems"
3
+ require "bundler/setup"
2
4
 
3
5
  module Conan
4
6
  class Initializer
@@ -11,7 +13,7 @@ module Conan
11
13
 
12
14
  def initialize(where, settings)
13
15
  @destination = File.expand_path(where)
14
- @settings = settings
16
+ @settings = Conan::Settings.new(settings)
15
17
  end
16
18
 
17
19
  def run
@@ -32,7 +34,8 @@ module Conan
32
34
 
33
35
  def add_git_submodule
34
36
  return unless File.directory?(".git")
35
- sh "git submodule add git://github.com/madebymany/cookbooks.git deploy/chef/recipes/cookbooks >/dev/null 2>&1"
37
+ return if File.directory?("deploy/chef/recipes/cookbooks")
38
+ sh "git submodule add #{@settings["COOKBOOK_REPOSITORY"]} deploy/chef/recipes/cookbooks #{@settings["COOKBOOK_BRANCH"]} >/dev/null 2>&1"
36
39
  end
37
40
 
38
41
  def copy_template
@@ -2,8 +2,8 @@ require "conan/version"
2
2
 
3
3
  module Conan
4
4
  class Settings
5
- def initialize
6
- @settings = defaults
5
+ def initialize(settings = {})
6
+ @settings = defaults.merge(settings)
7
7
  end
8
8
 
9
9
  def []=(k, v)
@@ -19,7 +19,7 @@ module Conan
19
19
  {
20
20
  "APPLICATION" => application_from_git_remote,
21
21
  "COOKBOOK_REPOSITORY" => "git://github.com/madebymany/cookbooks.git",
22
- "COOKBOOK_BRANCH" => "minimal",
22
+ "COOKBOOK_BRANCH" => "master",
23
23
  "VERSION" => Conan::VERSION,
24
24
  }
25
25
  end
@@ -1,6 +1,24 @@
1
1
  Conan the Deployer has set up your project.
2
2
 
3
- Next, set up your deployment:
3
+ Optional: if you are use AWS you can provision instances from a json file
4
+
5
+ * Add or edit ~/.fog to include your AWS access and secret key: It should look something like:
6
+ :default:
7
+ :aws_access_key_id: AithisismykeyYxDr
8
+ :aws_secret_access_key: PeT/thisismysecretaccesskey9HyE
9
+
10
+ * Edit config/aws.json to describe your AWS environments
11
+
12
+ Now you can use capistrano to provision your environment
13
+
14
+ * cap staging aws:provision
15
+
16
+ Then you can write out the config/servers.json which will be used in the next steps
17
+
18
+ * cap staging aws:write_config
19
+ (this will actually write out all environments so you may need to re-run it if you provision a new environment)
20
+
21
+ Next, set up your deployment or if you are not using AWS start her:
4
22
 
5
23
  * Edit config/servers.json to specify your stages, servers, and roles
6
24
 
@@ -0,0 +1,110 @@
1
+ {
2
+ "staging": {
3
+ "key_pairs": {
4
+ "keypair-name": {
5
+ "region": "us-east-1"
6
+ }
7
+ },
8
+ "ec2": {
9
+ "app1": {
10
+ "region": "us-east-1",
11
+ "monitoring": false,
12
+ "roles": ["app", "db", "staging"],
13
+ "flavor_id": "m1.small",
14
+ "availability_zone": "us-east-1b",
15
+ "groups": ["default"]
16
+ }
17
+ },
18
+ "rds": {
19
+ "db1": {
20
+ "region": "us-east-1",
21
+ "flavor_id": "db.m1.small",
22
+ "backup_retention_period": "1",
23
+ "multi_az": false,
24
+ "availability_zone": "us-east-1b",
25
+ "db_security_groups": ["default"],
26
+ "db_name": "app_production",
27
+ "master_username": "root",
28
+ "password": "TODO"
29
+ }
30
+ },
31
+ "security": {
32
+ "ec2": {
33
+ "default": {
34
+ "region": "us-east-1",
35
+ "ports": ["22", "80"]
36
+ }
37
+ },
38
+ "rds": {
39
+ "default": {
40
+ "region": "us-east-1",
41
+ "ec2_security_groups": ["default"]
42
+ }
43
+ }
44
+ },
45
+ "s3": {
46
+ "bucket-name": {
47
+ "region": "us-east-1"
48
+ }
49
+ }
50
+ },
51
+ "production": {
52
+ "ec2": {
53
+ "app1": {
54
+ "region": "us-east-1",
55
+ "monitoring": true,
56
+ "roles": ["app", "db", "production"],
57
+ "flavor_id": "m1.small",
58
+ "availability_zone": "us-east-1b",
59
+ "groups": ["default"]
60
+ },
61
+ "app2": {
62
+ "region": "us-east-1",
63
+ "roles": ["app", "db", "production"],
64
+ "flavor_id": "m1.small",
65
+ "availability_zone": "us-east-1b",
66
+ "groups": ["default"]
67
+ }
68
+ },
69
+ "rds": {
70
+ "db1": {
71
+ "region": "us-east-1",
72
+ "multi_az": true,
73
+ "flavor_id": "db.m1.small",
74
+ "allocated_storage": 100,
75
+ "availability_zone": "us-east-1b",
76
+ "db_security_groups": ["default"],
77
+ "backup_retention_period": "8",
78
+ "db_name": "app_production",
79
+ "master_username": "root",
80
+ "password": "TODO"
81
+ }
82
+ },
83
+ "elb": {
84
+ "lb1": {
85
+ "region": "us-east-1",
86
+ "servers": ["app1", "app2"],
87
+ "https": "false"
88
+ }
89
+ },
90
+ "security": {
91
+ "ec2": {
92
+ "default": {
93
+ "region": "us-east-1",
94
+ "ports": ["22", "80"]
95
+ }
96
+ },
97
+ "rds": {
98
+ "default": {
99
+ "region": "us-east-1",
100
+ "ec2_security_groups": ["default"]
101
+ }
102
+ }
103
+ },
104
+ "s3": {
105
+ "test": {
106
+ "region": "us-east-1"
107
+ }
108
+ }
109
+ }
110
+ }
@@ -42,6 +42,8 @@ set :user, "rails"
42
42
  set :deploy_to, "/mnt/#{application}"
43
43
  set :ruby_version, "1.9.2"
44
44
 
45
+ ssh_options[:forward_agent] = true
46
+
45
47
  # Let Conan take over
46
48
  require "conan/version"
47
49
  unless Conan::VERSION == "{{VERSION}}"
@@ -29,7 +29,7 @@
29
29
  "listen_ports": ["80"]
30
30
  },
31
31
  "passenger": {
32
- "version": "2.2.14"
32
+ "version": "3.0.11"
33
33
  },
34
34
  "recipes": [
35
35
  "hosts"
@@ -1,3 +1,3 @@
1
1
  module Conan
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.5"
3
3
  end
metadata CHANGED
@@ -1,49 +1,66 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: conan
3
- version: !ruby/object:Gem::Version
4
- hash: 21
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.5
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 2
9
- - 1
10
- version: 0.2.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Paul Battley
9
+ - Stuart Eccles
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
-
18
- date: 2011-09-29 00:00:00 +01:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2012-02-15 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: json
17
+ requirement: &70097716738400 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 1.6.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70097716738400
26
+ - !ruby/object:Gem::Dependency
27
+ name: capistrano
28
+ requirement: &70097716737480 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
23
35
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
36
+ version_requirements: *70097716737480
37
+ - !ruby/object:Gem::Dependency
38
+ name: fog
39
+ requirement: &70097716735820 !ruby/object:Gem::Requirement
25
40
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
33
45
  type: :runtime
34
- version_requirements: *id001
35
- description: Set up a project to enable the configuration of servers using Chef via Capistrano.
36
- email:
37
- - pbattley@gmail.com
38
- executables:
46
+ prerelease: false
47
+ version_requirements: *70097716735820
48
+ description: Set up a project to enable the provision of infrastructure through AWS
49
+ and the configuration of servers using Chef via Capistrano.
50
+ email:
51
+ - stuart@madebymany.co.uk
52
+ executables:
39
53
  - conan
40
54
  extensions: []
41
-
42
55
  extra_rdoc_files: []
43
-
44
- files:
56
+ files:
45
57
  - bin/conan
46
58
  - lib/conan/capistrano.rb
59
+ - lib/conan/cloud/aws/default_amis.json
60
+ - lib/conan/cloud/aws/provision.rb
61
+ - lib/conan/cloud/tasks.rb
62
+ - lib/conan/common.rb
63
+ - lib/conan/deployment/assets.rb
47
64
  - lib/conan/deployment/chef.rb
48
65
  - lib/conan/deployment/deploy.rb
49
66
  - lib/conan/deployment/git.rb
@@ -53,6 +70,7 @@ files:
53
70
  - lib/conan/smart_hash_merge.rb
54
71
  - lib/conan/template/Capfile
55
72
  - lib/conan/template/CONAN_TODO
73
+ - lib/conan/template/config/aws.json
56
74
  - lib/conan/template/config/deploy.rb
57
75
  - lib/conan/template/config/servers.json
58
76
  - lib/conan/template/deploy/chef/dna/app.json
@@ -69,39 +87,28 @@ files:
69
87
  - lib/conan/template/deploy/chef/solo.rb
70
88
  - lib/conan/version.rb
71
89
  - README.md
72
- has_rdoc: true
73
90
  homepage: http://github.com/madebymany/conan
74
91
  licenses: []
75
-
76
92
  post_install_message:
77
93
  rdoc_options: []
78
-
79
- require_paths:
94
+ require_paths:
80
95
  - lib
81
- required_ruby_version: !ruby/object:Gem::Requirement
96
+ required_ruby_version: !ruby/object:Gem::Requirement
82
97
  none: false
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- hash: 3
87
- segments:
88
- - 0
89
- version: "0"
90
- required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
103
  none: false
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- hash: 3
96
- segments:
97
- - 0
98
- version: "0"
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
99
108
  requirements: []
100
-
101
109
  rubyforge_project:
102
- rubygems_version: 1.5.3
110
+ rubygems_version: 1.8.10
103
111
  signing_key:
104
112
  specification_version: 3
105
113
  summary: Conan The Deployer
106
114
  test_files: []
107
-