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.
- data/lib/dnapi.rb +54 -0
- data/lib/dnapi/app.rb +130 -0
- data/lib/dnapi/component.rb +50 -0
- data/lib/dnapi/component_possessor.rb +49 -0
- data/lib/dnapi/components/addons.rb +26 -0
- data/lib/dnapi/components/apache.rb +13 -0
- data/lib/dnapi/components/cloudkick.rb +13 -0
- data/lib/dnapi/components/encrypted_backup.rb +12 -0
- data/lib/dnapi/components/exim.rb +10 -0
- data/lib/dnapi/components/monitor.rb +12 -0
- data/lib/dnapi/components/nagios.rb +28 -0
- data/lib/dnapi/components/newrelic.rb +12 -0
- data/lib/dnapi/components/passenger3.rb +13 -0
- data/lib/dnapi/components/ruby.rb +234 -0
- data/lib/dnapi/components/ssmtp.rb +10 -0
- data/lib/dnapi/components/stunneled.rb +13 -0
- data/lib/dnapi/components/volume.rb +32 -0
- data/lib/dnapi/cron.rb +5 -0
- data/lib/dnapi/db_stack.rb +92 -0
- data/lib/dnapi/ebuild_dep.rb +5 -0
- data/lib/dnapi/environment.rb +327 -0
- data/lib/dnapi/extensions.rb +32 -0
- data/lib/dnapi/gem_dep.rb +9 -0
- data/lib/dnapi/instance.rb +69 -0
- data/lib/dnapi/monitoring.rb +22 -0
- data/lib/dnapi/recipe.rb +27 -0
- data/lib/dnapi/ssl_cert.rb +13 -0
- data/lib/dnapi/stack.rb +111 -0
- data/lib/dnapi/struct.rb +149 -0
- data/lib/dnapi/test.rb +114 -0
- data/lib/dnapi/test/ext.rb +32 -0
- data/lib/dnapi/test/sweatshop.rb +148 -0
- data/lib/dnapi/version.rb +3 -0
- data/lib/dnapi/vhost.rb +24 -0
- data/spec/app_spec.rb +68 -0
- data/spec/component_spec.rb +66 -0
- data/spec/components/addons_spec.rb +33 -0
- data/spec/components/cloudkick_spec.rb +17 -0
- data/spec/components/nagios_spec.rb +42 -0
- data/spec/components/nodejs_spec.rb +27 -0
- data/spec/components/passenger3_spec.rb +12 -0
- data/spec/components/ruby_spec.rb +321 -0
- data/spec/components/stunneled.rb +15 -0
- data/spec/components/volume_spec.rb +21 -0
- data/spec/db_stack_spec.rb +111 -0
- data/spec/environment_spec.rb +227 -0
- data/spec/instance_spec.rb +52 -0
- data/spec/proxies.rb +143 -0
- data/spec/proxies_spec.rb +76 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/stack_spec.rb +105 -0
- data/spec/struct_spec.rb +100 -0
- metadata +181 -0
@@ -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,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,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
|