ey_cloud_awareness 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,12 @@
1
1
  = ey_cloud_awareness
2
2
 
3
- Make your EngineYard cloud instances aware of each other.
3
+ This gem makes it a little easier to live on the EngineYard cloud:
4
4
 
5
- Never download a new <tt>deploy.rb</tt> again.
5
+ * automatically run cap tasks on all your instances
6
+ * automatically update your ssh aliases
7
+ * allow your app to get information about the cluster (aka "environment") it's running in
8
+
9
+ We use it over at http://brighterplanet.com.
6
10
 
7
11
  == Quick start
8
12
 
@@ -10,22 +14,23 @@ Put this in <tt>config/environment.rb</tt>:
10
14
 
11
15
  config.gem 'ey_cloud_awareness', :version => '[WHATEVER THE CURRENT GEM VERSION IS]', :lib => false, :source => 'http://gemcutter.org'
12
16
 
13
- Put this in your <tt>config/deploy.rb</tt> (or wherever your deploy-related Capfile is):
17
+ Put this in your <tt>config/deploy.rb</tt> (or whereever your Capfile is):
14
18
 
19
+ # don't miss this line just because it's at the top
15
20
  load "#{Gem.searcher.find('ey_cloud_awareness').full_gem_path}/lib/tasks/capistrano_tasks.rb"
16
21
 
17
- task :my_app_production do
22
+ task :my_production do
18
23
  role :app_master, 'my_app.com' # or you can use its Elastic IP
19
24
  set :rails_env, 'production' # required
20
25
  set :deploy_to, '/data/my_app' # required
21
- find_and_execute_task 'eyc_setup' # note that we don't use eyc: namespace
26
+ find_and_execute_task 'eyc_setup' # required
22
27
  end
23
28
 
24
- task :my_app_staging do
29
+ task :my_staging do
25
30
  role :app_master, 'staging.my_app.com' # or you can use its Elastic IP
26
31
  set :rails_env, 'production' # required
27
32
  set :deploy_to, '/data/my_app' # required
28
- find_and_execute_task 'eyc_setup' # note that we don't use eyc: namespace
33
+ find_and_execute_task 'eyc_setup' # required
29
34
  end
30
35
 
31
36
  # add more tasks if you have more cloud environments
@@ -34,48 +39,90 @@ That should be all.
34
39
 
35
40
  == Running capistrano tasks on your instances
36
41
 
37
- Now you should be able to eycap stuff like:
42
+ Run <tt>monit:status</tt> on all the slices in the environment <tt>my_production</tt>:
43
+
44
+ cap my_production monit:status
38
45
 
39
- cap my_app_production monit:status
46
+ Or you could run <tt>nginx:restart</tt> for <tt>my_staging</tt>:
40
47
 
41
- ...and <b>capistrano will always have a fresh list of your environment's instances</b>. Roles like <tt>:app</tt>, <tt>:db</tt>, and <tt>:utility</tt> are set properly.
48
+ cap my_staging nginx:restart
49
+
50
+ Your capistrano tasks will always have a fresh list of your environment's instances. Roles like <tt>:app</tt> and <tt>:db</tt> are set (so are <tt>:app_master</tt>, <tt>:db_master</tt>, and <tt>:utility</tt>, but you probably don't need those).
42
51
 
43
52
  == SSH into your instances
44
53
 
45
- If you want to update your <tt>~/.ssh/config</tt> with hosts from a particular environment, run
54
+ Let's say you want to ssh into...
46
55
 
47
- cap my_app_production eyc:ssh
56
+ ssh my_production-app_master
48
57
 
49
- and it will magically add or update a block like
58
+ Well, you need to keep your <tt>~/.ssh/config</tt> up-to-date. Easy!
50
59
 
51
- # START StringReplacer my_app_production -- DO NOT MODIFY
60
+ cap my_production eyc:ssh
52
61
 
53
- Host my_app_production0
54
- Hostname ec2-67-202-43-40.compute-1.amazonaws.com
55
- User my_user
56
- StrictHostKeyChecking no
57
-
58
- Host my_app_production1
59
- Hostname ec2-222-222-22-22.compute-1.amazonaws.com
60
- User my_user
61
- StrictHostKeyChecking no
62
+ That will magically add or update a block like
63
+
64
+ # START StringReplacer my_production -- DO NOT MODIFY
65
+
66
+ # db_master
67
+ Host my_production-db_master
68
+ Hostname ec2-222-222-222-59.compute-1.amazonaws.com
69
+ User my_user
70
+ StrictHostKeyChecking no
71
+
72
+ # utility (1)
73
+ Host my_production-utility1
74
+ Hostname ec2-222-222-53-222.compute-1.amazonaws.com
75
+ User my_user
76
+ StrictHostKeyChecking no
77
+
78
+ # app_master
79
+ Host my_production-app_master
80
+ Hostname ec2-222-222-23-222.compute-1.amazonaws.com
81
+ User my_user
82
+ StrictHostKeyChecking no
83
+
84
+ # END StringReplacer my_production -- DO NOT MODIFY
85
+
86
+ Run that again as
87
+
88
+ cap my_staging eyc:ssh
89
+
90
+ ... and it adds
91
+
92
+ # START StringReplacer my_staging -- DO NOT MODIFY
93
+
94
+ # app_master
95
+ Host my_staging-app_master
96
+ Hostname ec2-222-222-7-210.compute-1.amazonaws.com
97
+ User my_user
98
+ StrictHostKeyChecking no
99
+
100
+ # db_master
101
+ Host my_staging-db_master
102
+ Hostname ec2-222-222-52-8.compute-1.amazonaws.com
103
+ User my_user
104
+ StrictHostKeyChecking no
62
105
 
63
- # END StringReplacer my_app_production -- DO NOT MODIFY
106
+ # END StringReplacer my_staging -- DO NOT MODIFY
64
107
 
65
- Now you can just ssh like this:
108
+ This leaves you with lots of useful aliases:
66
109
 
67
- ssh my_app_production0
110
+ ssh my_production-db_master
111
+ ssh my_production-app_master
112
+ ssh my_production-utility1
113
+ ssh my_staging-app_master
114
+ ssh my_staging-db_master
68
115
 
69
- Note that you can run it for different environments (my_app_production, my_app_staging, etc.) and they won't overwrite each other.
116
+ Note that the numbers after app [slaves], db [slaves], and utility [slaves] may change every time you run the task.
70
117
 
71
118
  == Just dumping information about your instances
72
119
 
73
120
  Once you've done the quickstart, try:
74
121
 
75
- cap my_app_production eyc:app # gets a list of your app instances, including app_master
76
- cap my_app_production eyc:utility # ditto for utility instances
77
- cap my_app_production eyc:db # gets your master db instance (FIXME: I don't think it will find slaves)
78
- cap my_app_production eyc:all # gets a list of all your instances
122
+ cap my_production eyc:app # gets a list of your app instances, including app_master
123
+ cap my_production eyc:utility # ditto for utility instances
124
+ cap my_production eyc:db # ditto for db instances
125
+ cap my_production eyc:all # gets a list of all your instances
79
126
 
80
127
  == Using the EngineYardCloudInstance class inside Rails
81
128
 
@@ -96,7 +143,7 @@ Or whatever you want:
96
143
  >> pp all_app_instances.first.to_hash
97
144
  {:dns_name=>"ec2-67-202-43-40.compute-1.amazonaws.com",
98
145
  :instance_role=>"app",
99
- :aws_groups=>["ey-my_app_production-1256085955-3205-13340"],
146
+ :aws_groups=>["ey-my_production-1256085955-3205-13340"],
100
147
  :aws_instance_id=>"i-50cf5838",
101
148
  :private_dns_name=>"domU-12-31-39-01-99-D3.compute-1.internal",
102
149
  :aws_state=>"running"}
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.7
1
+ 0.1.8
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ey_cloud_awareness}
8
- s.version = "0.1.7"
8
+ s.version = "0.1.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Seamus Abshere"]
@@ -34,6 +34,10 @@ class EngineYardCloudInstance
34
34
  end
35
35
  end
36
36
 
37
+ def ==(other)
38
+ self.instance_id == other.instance_id
39
+ end
40
+
37
41
  class_inheritable_accessor :proxy
38
42
 
39
43
  class << self
@@ -48,12 +52,24 @@ class EngineYardCloudInstance
48
52
  self
49
53
  end
50
54
 
55
+ def environment
56
+ @_environment ||= first.environment
57
+ end
58
+
59
+ def app_master
60
+ find_all_by_instance_roles(:app_master).first
61
+ end
62
+
63
+ def db_master
64
+ find_all_by_instance_roles(:db_master).first
65
+ end
66
+
51
67
  def app
52
68
  find_all_by_instance_roles :app, :app_master
53
69
  end
54
70
 
55
71
  def db
56
- find_all_by_instance_roles :db
72
+ find_all_by_instance_roles :db_master, :db_slave
57
73
  end
58
74
 
59
75
  def utility
@@ -64,6 +80,10 @@ class EngineYardCloudInstance
64
80
  data.map { |k, _| new k }
65
81
  end
66
82
 
83
+ def with_roles
84
+ all.reject { |i| i.instance_role == 'unknown' }
85
+ end
86
+
67
87
  def current
68
88
  new cached_current_instance_id
69
89
  end
@@ -99,7 +119,7 @@ class EngineYardCloudInstance
99
119
  current = hash[instance_description[:aws_instance_id]]
100
120
  # using current as a pointer
101
121
  if dna[:db_host] == instance_description[:dns_name] or dna[:db_host] == instance_description[:private_dns_name]
102
- current[:instance_role] = 'db'
122
+ current[:instance_role] = 'db_master'
103
123
  elsif Array.wrap(dna[:db_slaves]).include? instance_description[:private_dns_name]
104
124
  current[:instance_role] = 'db_slave'
105
125
  elsif Array.wrap(dna[:utility_instances]).include? instance_description[:private_dns_name]
@@ -108,6 +128,8 @@ class EngineYardCloudInstance
108
128
  current[:instance_role] = 'app_master'
109
129
  elsif instance_description[:aws_state] == 'running'
110
130
  current[:instance_role] = 'app'
131
+ else
132
+ current[:instance_role] = 'unknown'
111
133
  end
112
134
  current[:private_dns_name] = instance_description[:private_dns_name]
113
135
  current[:dns_name] = instance_description[:dns_name]
@@ -116,6 +138,7 @@ class EngineYardCloudInstance
116
138
  current[:aws_instance_id] = instance_description[:aws_instance_id]
117
139
  current[:users] = dna[:users]
118
140
  current[:environment] = dna[:environment]
141
+ @_environment ||= dna[:environment]
119
142
  end
120
143
  @_data = hash.recursive_symbolize_keys!
121
144
  end
@@ -26,6 +26,7 @@ task :eyc_setup, :roles => :app_master do
26
26
  $stderr.puts output
27
27
  raise
28
28
  end
29
+ role :db_master, eyc_proxy.db_master.dns_name
29
30
  eyc_proxy.app.each { |i| role :app, i.dns_name }
30
31
  eyc_proxy.db.each { |i| role :db, i.dns_name }
31
32
  end
@@ -38,6 +39,7 @@ namespace :eyc do
38
39
  end
39
40
  end
40
41
 
42
+ # Used by the eyc:ssh cap task to insert host information into ~/.ssh/config
41
43
  class StringReplacer
42
44
  NEWLINE = "AijQA6tD1wkWqgvLzXD"
43
45
  START_MARKER = '# START StringReplacer %s -- DO NOT MODIFY'
@@ -70,18 +72,32 @@ end
70
72
  namespace :eyc do
71
73
  task :ssh, :roles => :app_master do
72
74
  replacement = []
73
- environment_name = ''
74
- eyc_proxy.app.each_with_index do |instance, index|
75
- environment_name = instance.environment[:name]
75
+ eyc_proxy.with_roles.each_with_index do |instance, index|
76
+ case instance.instance_role
77
+ when 'db_master'
78
+ explanation = ''
79
+ shorthand = 'db_master'
80
+ when 'app_master'
81
+ explanation = ''
82
+ shorthand = 'app_master'
83
+ else
84
+ explanation = " (#{index})"
85
+ shorthand = "#{instance.instance_role}#{index}"
86
+ end
76
87
  replacement << %{
77
- Host #{environment_name}#{index}
78
- Hostname #{instance.dns_name}
79
- User #{instance.users.first[:username]}
80
- StrictHostKeyChecking no
88
+ # #{instance.instance_role}#{explanation}
89
+ Host #{eyc_proxy.environment[:name]}-#{shorthand}
90
+ Hostname #{instance.dns_name}
91
+ User #{instance.users.first[:username]}
92
+ StrictHostKeyChecking no
81
93
  }
82
94
  end
83
95
  replacement = replacement.join
84
- r = StringReplacer.new File.expand_path("~/.ssh/config")
85
- r.replace! replacement, environment_name
96
+ ssh_config_path = File.expand_path("~/.ssh/config")
97
+ r = StringReplacer.new ssh_config_path
98
+ r.replace! replacement, eyc_proxy.environment[:name]
99
+
100
+ $stderr.puts "[EY CLOUD AWARENESS GEM] Added this to #{ssh_config_path}"
101
+ $stderr.puts replacement
86
102
  end
87
103
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ey_cloud_awareness
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seamus Abshere