dnapi 1.1.74.jruby192.c

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