ey_cloud_awareness 0.1.7 → 0.1.8

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.
@@ -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