conan 0.2.1 → 0.3.5

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/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
-