dnapi 1.1.74.jruby192.c

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/lib/dnapi.rb +54 -0
  2. data/lib/dnapi/app.rb +130 -0
  3. data/lib/dnapi/component.rb +50 -0
  4. data/lib/dnapi/component_possessor.rb +49 -0
  5. data/lib/dnapi/components/addons.rb +26 -0
  6. data/lib/dnapi/components/apache.rb +13 -0
  7. data/lib/dnapi/components/cloudkick.rb +13 -0
  8. data/lib/dnapi/components/encrypted_backup.rb +12 -0
  9. data/lib/dnapi/components/exim.rb +10 -0
  10. data/lib/dnapi/components/monitor.rb +12 -0
  11. data/lib/dnapi/components/nagios.rb +28 -0
  12. data/lib/dnapi/components/newrelic.rb +12 -0
  13. data/lib/dnapi/components/passenger3.rb +13 -0
  14. data/lib/dnapi/components/ruby.rb +234 -0
  15. data/lib/dnapi/components/ssmtp.rb +10 -0
  16. data/lib/dnapi/components/stunneled.rb +13 -0
  17. data/lib/dnapi/components/volume.rb +32 -0
  18. data/lib/dnapi/cron.rb +5 -0
  19. data/lib/dnapi/db_stack.rb +92 -0
  20. data/lib/dnapi/ebuild_dep.rb +5 -0
  21. data/lib/dnapi/environment.rb +327 -0
  22. data/lib/dnapi/extensions.rb +32 -0
  23. data/lib/dnapi/gem_dep.rb +9 -0
  24. data/lib/dnapi/instance.rb +69 -0
  25. data/lib/dnapi/monitoring.rb +22 -0
  26. data/lib/dnapi/recipe.rb +27 -0
  27. data/lib/dnapi/ssl_cert.rb +13 -0
  28. data/lib/dnapi/stack.rb +111 -0
  29. data/lib/dnapi/struct.rb +149 -0
  30. data/lib/dnapi/test.rb +114 -0
  31. data/lib/dnapi/test/ext.rb +32 -0
  32. data/lib/dnapi/test/sweatshop.rb +148 -0
  33. data/lib/dnapi/version.rb +3 -0
  34. data/lib/dnapi/vhost.rb +24 -0
  35. data/spec/app_spec.rb +68 -0
  36. data/spec/component_spec.rb +66 -0
  37. data/spec/components/addons_spec.rb +33 -0
  38. data/spec/components/cloudkick_spec.rb +17 -0
  39. data/spec/components/nagios_spec.rb +42 -0
  40. data/spec/components/nodejs_spec.rb +27 -0
  41. data/spec/components/passenger3_spec.rb +12 -0
  42. data/spec/components/ruby_spec.rb +321 -0
  43. data/spec/components/stunneled.rb +15 -0
  44. data/spec/components/volume_spec.rb +21 -0
  45. data/spec/db_stack_spec.rb +111 -0
  46. data/spec/environment_spec.rb +227 -0
  47. data/spec/instance_spec.rb +52 -0
  48. data/spec/proxies.rb +143 -0
  49. data/spec/proxies_spec.rb +76 -0
  50. data/spec/spec_helper.rb +2 -0
  51. data/spec/stack_spec.rb +105 -0
  52. data/spec/struct_spec.rb +100 -0
  53. metadata +181 -0
@@ -0,0 +1,10 @@
1
+ module DNApi
2
+ module Components
3
+ class Ssmtp < Struct.new(:key)
4
+ include Component
5
+
6
+ key :ssmtp
7
+ belongs_to Instance
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module DNApi
2
+ module Components
3
+ class Stunneled < Struct.new(:key)
4
+ include Component
5
+
6
+ desc "A way to tunnel SSL traffic so that x-forwarded-for headers make their way to the app"
7
+
8
+ key :stunneled
9
+
10
+ belongs_to Environment
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ module DNApi
2
+ module Components
3
+ class Volume < Struct.new(:mountpoint, :size, :warn_at_percent, :fail_at_percent)
4
+ def warn_at
5
+ (self.size * (self.warn_at_percent.to_f / 100)).to_i
6
+ end
7
+
8
+ def fail_at
9
+ (self.size * (self.fail_at_percent.to_f / 100)).to_i
10
+ end
11
+ end
12
+
13
+ class EphemeralVolume < Volume
14
+ include Component
15
+ desc "The local, non persistant volumes for EC2."
16
+
17
+ key :ephemeral_volume
18
+
19
+ belongs_to Instance
20
+ end
21
+
22
+ class EBSVolume < Volume
23
+ include Component
24
+ desc "Snapshotable, persistant volumes for EC2."
25
+
26
+ key :ebs_volume
27
+
28
+ belongs_to Instance
29
+ end
30
+
31
+ end
32
+ end
data/lib/dnapi/cron.rb ADDED
@@ -0,0 +1,5 @@
1
+ module DNApi
2
+ class Cron < Struct.new(:command, :day, :hour, :minute, :month, :name, :user, :weekday)
3
+ attr_accessor :environment
4
+ end
5
+ end
@@ -0,0 +1,92 @@
1
+ module DNApi
2
+ class DbStack < Struct.new(:name, :label, :supports_replication, :backup_command, :adapter)
3
+ Mysql = new(
4
+ :name => 'mysql',
5
+ :label => 'MySQL 5.0.x',
6
+ :supports_replication => true,
7
+ :backup_command => 'eybackup --quiet',
8
+ :adapter => 'mysql'
9
+ )
10
+ Mysql5_1 = new(
11
+ :name => 'mysql5_1',
12
+ :label => 'MySQL 5.1.x',
13
+ :supports_replication => true,
14
+ :backup_command => 'eybackup -e mysql --quiet',
15
+ :adapter => 'mysql'
16
+ )
17
+ Mysql5_5 = new(
18
+ :name => 'mysql5_5',
19
+ :label => 'MySQL 5.5.x',
20
+ :supports_replication => true,
21
+ :backup_command => 'eybackup -e mysql --quiet',
22
+ :adapter => 'mysql'
23
+ )
24
+ Postgres = new(
25
+ :name => 'postgres',
26
+ :label => 'PostgreSQL 8.3.x',
27
+ :supports_replication => false,
28
+ :backup_command => 'eybackup -e postgresql --quiet',
29
+ :adapter => 'postgresql'
30
+ )
31
+
32
+ Postgres9 = new(
33
+ :name => 'postgres9',
34
+ :label => 'PostgreSQL 9.0.x',
35
+ :supports_replication => true,
36
+ :backup_command => 'eybackup -e postgresql --quiet',
37
+ :adapter => 'postgresql'
38
+ )
39
+
40
+ Postgres91 = new(
41
+ :name => 'postgres9_1',
42
+ :label => 'PostgreSQL 9.1.x',
43
+ :supports_replication => true,
44
+ :backup_command => 'eybackup -e postgresql --quiet',
45
+ :adapter => 'postgersql'
46
+ )
47
+
48
+ def self.all
49
+ [Mysql, Mysql5_1, Mysql5_5, Postgres, Postgres9,Postgres91]
50
+ end
51
+
52
+ def self.get(name)
53
+ all.detect {|s| s.name == name }
54
+ end
55
+
56
+ def supports_replication?
57
+ supports_replication
58
+ end
59
+
60
+ def postgres?
61
+ name == 'postgres'
62
+ end
63
+
64
+ def postgres9?
65
+ name == 'postgres9'
66
+ end
67
+
68
+ def postgres9_1?
69
+ name == 'postgres9_1'
70
+ end
71
+
72
+ def mysql5_1?
73
+ name == 'mysql5_1'
74
+ end
75
+
76
+ def mysql5_5?
77
+ name == 'mysql5_5'
78
+ end
79
+
80
+ def mysql?
81
+ name == 'mysql'
82
+ end
83
+
84
+ def adapter_for(component)
85
+ if adapter == 'mysql' && DNApi::Components::RubyVersion.encoding_aware.include?(component.class)
86
+ 'mysql2'
87
+ else
88
+ adapter
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,5 @@
1
+ module DNApi
2
+ class EbuildDep < Struct.new(:name)
3
+ belongs_to :app
4
+ end
5
+ end
@@ -0,0 +1,327 @@
1
+ module DNApi
2
+ class Environment < Struct.new(:alert_email,
3
+ :aws_secret_key, :aws_secret_id,
4
+ :backup_interval, :backup_window,
5
+ :admin_ssh_key, :mailserver, :stonith_endpoint,
6
+ :internal_ssh_public_key,
7
+ :internal_ssh_private_key,
8
+ :newrelic_key,
9
+ :ruby_version,
10
+ :stack_name, :name, :framework_env,
11
+ :stats_password, :ssh_username, :ssh_password,
12
+ :ssh_keys, :db_stack_name,
13
+ :monitoring, :region, :backup_bucket)
14
+
15
+ include ComponentPossessor
16
+
17
+ many :instances, :apps, :crons
18
+
19
+ def initialize(attributes = {})
20
+ if stack = attributes[:stack]
21
+ attributes[:stack_name] = stack.name
22
+ end
23
+
24
+ super(attributes)
25
+
26
+ self.backup_window ||= 14
27
+ self.monitoring ||= "monit"
28
+ end
29
+
30
+
31
+ def stack=(stack)
32
+ self.stack_name = stack.name
33
+ end
34
+
35
+ def monitoring
36
+ Monitoring.get(super)
37
+ end
38
+
39
+ def ruby_component
40
+ component(:ruby_186) || component(:ruby_187) ||
41
+ component(:ree) || component(:ruby_192) ||
42
+ component(:jruby_187) || component(:jruby_192) ||
43
+ component(:rubinius) || component(:ruby_193) ||
44
+ component(:nodejs)
45
+ end
46
+
47
+ def stack
48
+ Stack.get(stack_name)
49
+ end
50
+
51
+ def db_stack=(db_stack)
52
+ self.db_stack_name = db_stack.name
53
+ end
54
+
55
+ def db_stack
56
+ DbStack.get(db_stack_name)
57
+ end
58
+
59
+ def build_app(attributes = {})
60
+ app = App.new(attributes)
61
+ app.environment = self
62
+ apps << app
63
+ app
64
+ end
65
+
66
+ def build_instance(attributes = {})
67
+ instance = Instance.new(attributes)
68
+ instance.environment = self
69
+ instances << instance
70
+ instance
71
+ end
72
+
73
+ alias_method :_instances=, :instances=
74
+
75
+ def instances=(array)
76
+ array.each do |item|
77
+ item.environment = self
78
+ end
79
+ self._instances = array
80
+ end
81
+
82
+ def build_cron(attributes = {})
83
+ cron = Cron.new(attributes)
84
+ cron.environment = self
85
+ crons << cron
86
+ cron
87
+ end
88
+
89
+ alias_method :_apps=, :apps=
90
+
91
+ def apps=(array)
92
+ array.each do |item|
93
+ item.environment = self
94
+ end
95
+ self._apps = array
96
+ end
97
+
98
+ def db_host
99
+ if db_master
100
+ db_master.public_hostname
101
+ else
102
+ solo.public_hostname
103
+ end
104
+ end
105
+
106
+ def solo?
107
+ instances.any? {|i| i.role.to_s == 'solo' }
108
+ end
109
+
110
+ def solo
111
+ instances.detect {|i| i.role.to_s == 'solo' }
112
+ end
113
+
114
+ def db_slaves
115
+ instances.select {|i| i.role.to_s == 'db_slave' }
116
+ end
117
+
118
+ def app_slaves
119
+ instances.select {|i| i.role.to_s == 'app' }
120
+ end
121
+
122
+ def db_master
123
+ instances.detect {|i| i.role.to_s == 'db_master' }
124
+ end
125
+
126
+ def app_master
127
+ instances.detect {|i| i.role.to_s == 'app_master' }
128
+ end
129
+
130
+ def app_servers
131
+ (app_slaves << app_master).compact
132
+ end
133
+
134
+ def utility_instances
135
+ instances.select {|i| i.role.to_s == 'util' }
136
+ end
137
+
138
+ def solo_cluster?
139
+ instances.size == 1 && instances.first.role.to_s == 'solo'
140
+ end
141
+
142
+ def environment_hash
143
+ {:name => name, :framework_env => framework_env, :stack => stack.name}
144
+ end
145
+
146
+ def haproxy_hash
147
+ {:username => ssh_username, :password => stats_password}
148
+ end
149
+
150
+ def app_master_hash
151
+ if app_master
152
+ {:master_app_server => {
153
+ :public_ip => app_master.public_hostname,
154
+ :private_dns_name => app_master.private_hostname
155
+ }}
156
+ else
157
+ {}
158
+ end
159
+ end
160
+
161
+ def enabled_app_servers_hash
162
+ unless app_servers.empty?
163
+ {:members => enabled_app_servers_hostnames}
164
+ else
165
+ {}
166
+ end
167
+ end
168
+
169
+ def db_slaves_hostnames
170
+ db_slaves.map {|i| i.private_hostname }
171
+ end
172
+
173
+ def utility_instances_hostnames
174
+ utility_instances.map {|i| {:hostname => i.private_hostname, :name => i.name } }
175
+ end
176
+
177
+ def app_slaves_hostnames
178
+ unless app_slaves.empty?
179
+ app_slaves.map {|i| i.private_hostname }
180
+ end
181
+ end
182
+
183
+ def enabled_app_servers
184
+ app_servers.select {|i| i.enabled?}
185
+ end
186
+
187
+ def enabled_app_servers_hostnames
188
+ enabled_app_servers.map {|i| i.private_hostname }
189
+ end
190
+
191
+ def users
192
+ [{
193
+ :username => ssh_username,
194
+ :password => ssh_password,
195
+ :gid => '1000',
196
+ :uid => '1000',
197
+ :comment => ''
198
+ }]
199
+ end
200
+
201
+ def applications
202
+ apps.inject({}) do |h, app|
203
+ h.update(app.name => app.to_legacy_hash)
204
+ end
205
+ end
206
+
207
+ def ebuilds
208
+ apps.map {|app| app.ebuilds }.flatten
209
+ end
210
+
211
+ def gems
212
+ apps.map {|app| app.gems_hash }.flatten
213
+ end
214
+
215
+ def applications_hash
216
+ apps.inject({}) do |h, app|
217
+ h.update(app.name => app.to_legacy_hash)
218
+ end
219
+ end
220
+
221
+ def to_legacy_hash
222
+ shared = %w( alert_email aws_secret_key aws_secret_id
223
+ backup_interval backup_window
224
+ admin_ssh_key mailserver
225
+ internal_ssh_public_key
226
+ internal_ssh_private_key
227
+ ruby_version
228
+ newrelic_key)
229
+ data = to_hash.select {|k,v| shared.include?(k.to_s)}
230
+ Hash[*data.flatten].merge(
231
+ :db_host => db_host,
232
+ :db_slaves => db_slaves_hostnames,
233
+ :user_ssh_key => ssh_keys,
234
+ :utility_instances => utility_instances_hostnames,
235
+ :environment => environment_hash,
236
+ :haproxy => haproxy_hash,
237
+ :users => users,
238
+ :packages_to_install => ebuilds,
239
+ :gems_to_install => gems,
240
+ :applications => applications_hash,
241
+ :crons => crons,
242
+ :ruby_version => ruby_version
243
+ ).merge(app_master_hash).
244
+ merge(enabled_app_servers_hash).reject {|k,v| v.nil? }
245
+ end
246
+
247
+ def dna_for_instance(instance)
248
+ dna_for_instance_id(instance.id)
249
+ end
250
+
251
+ def dna_for_instance_id(amazon_id)
252
+ if instance = instance_for(amazon_id)
253
+ instance.to_legacy_hash
254
+ else
255
+ raise InstanceNotFound, "Unknown instance #{amazon_id.inspect} in environment #{name.inspect}"
256
+ end
257
+ end
258
+
259
+ def instance_ids
260
+ instances.map {|instance| instance.id}
261
+ end
262
+
263
+ def instance_for(instance_id)
264
+ instances.find { |instance| instance.id == instance_id }
265
+ end
266
+
267
+ def backups?
268
+ backup_window && backup_window.to_s != '0'
269
+ end
270
+
271
+ def snapshot_cron
272
+ if backups?
273
+ cron = backup_cron
274
+ cron.name = 'ey-snapshots'
275
+ cron.command = 'ey-snapshots --snapshot --quiet'
276
+ cron.minute = "0/#{rand(30) + 30}"
277
+ cron
278
+ end
279
+ end
280
+
281
+ def mysql_backup_cron
282
+ if backups?
283
+ cron = backup_cron
284
+ cron.name = 'eybackup'
285
+ cron.command = db_stack.backup_command
286
+ cron.minute = '10'
287
+ cron
288
+ end
289
+ end
290
+
291
+ def postgres_backup_cron
292
+ if backups? && (db_stack == DbStack::Postgres || db_stack == DbStack::Postgres9 || db_stack == DbStack::Postgres91)
293
+ cron = backup_cron
294
+ cron.name = 'eybackup postgres'
295
+ cron.command = db_stack.backup_command
296
+ cron.minute = '20'
297
+ cron
298
+ end
299
+ end
300
+
301
+ def backup_cron
302
+ Cron.new(
303
+ :hour => backup_hour,
304
+ :day => '*',
305
+ :month => '*',
306
+ :weekday => '*',
307
+ :user => 'root'
308
+ ) if backups?
309
+ end
310
+
311
+ def backup_hour
312
+ backup_interval.to_s == '24' ? '1' : "*/#{backup_interval}"
313
+ end
314
+
315
+ ## chef-ey selectors
316
+ def recipes
317
+ apps.map {|a| a.recipes }.flatten.uniq
318
+ end
319
+
320
+ private
321
+
322
+ def ruby_version
323
+ rc = ruby_component
324
+ rc && rc.label
325
+ end
326
+ end
327
+ end