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
data/lib/dnapi.rb ADDED
@@ -0,0 +1,54 @@
1
+ require 'forwardable'
2
+ require 'extlib'
3
+ require 'json'
4
+
5
+ module DNApi
6
+ def self.build(attributes = {})
7
+ Environment.new(attributes)
8
+ end
9
+
10
+ def self.from(json)
11
+ jexp = (String === json) ? JSON.parse(json) : json
12
+
13
+ engineyard = jexp["engineyard"]
14
+ environment = Environment.from(engineyard["environment"])
15
+ environment.instance_for(engineyard["this"])
16
+ end
17
+
18
+ def self.components
19
+ @components ||= []
20
+ end
21
+
22
+ def self.component(name, &block)
23
+ klass = Class.new(Component, &block)
24
+ klass.name = name
25
+
26
+ self.components << klass
27
+
28
+ klass
29
+ end
30
+
31
+ class InstanceNotFound < StandardError; end
32
+ end
33
+
34
+ require 'dnapi/component'
35
+ require 'dnapi/extensions'
36
+ require 'dnapi/struct'
37
+ require 'dnapi/component_possessor'
38
+ require 'dnapi/recipe'
39
+ require 'dnapi/db_stack'
40
+ require 'dnapi/monitoring'
41
+ require 'dnapi/instance'
42
+ require 'dnapi/environment'
43
+ require 'dnapi/app'
44
+ require 'dnapi/ebuild_dep'
45
+ require 'dnapi/gem_dep'
46
+ require 'dnapi/cron'
47
+ require 'dnapi/ssl_cert'
48
+ require 'dnapi/vhost'
49
+
50
+ require 'dnapi/components/versioned_component'
51
+ Dir[File.join(File.dirname(__FILE__), 'dnapi', 'components', '*')].each do |component_file|
52
+ require component_file
53
+ end
54
+ require 'dnapi/stack'
data/lib/dnapi/app.rb ADDED
@@ -0,0 +1,130 @@
1
+ module DNApi
2
+ class App < Struct.new(:deploy_key, :repository_name, :type, :branch,
3
+ :deploy_action, :migration_command, :revision,
4
+ :run_deploy, :run_migrations, :name, :bundled,
5
+ :newrelic, :database_name)
6
+
7
+ include ComponentPossessor
8
+
9
+ belongs_to :environment
10
+ many :gems, :ebuilds, :vhosts
11
+
12
+ def initialize(attributes = {})
13
+ gem_attributes = attributes.delete(:gems)
14
+ ebuild_names = attributes.delete(:ebuilds)
15
+
16
+ super(attributes)
17
+
18
+ gem_attributes.each {|attrs| build_gem(attrs) } if gem_attributes
19
+ ebuild_names.each {|name| build_ebuild(:name => name) } if ebuild_names
20
+ vhosts.each {|vhost| vhost.app = self } if vhosts
21
+ end
22
+
23
+ def build_vhost(attributes = {})
24
+ vhost = VHost.new(attributes)
25
+ vhost.app = self
26
+ vhosts << vhost
27
+ vhost
28
+ end
29
+
30
+ def domain_name
31
+ vhosts.map {|vhost| vhost.domain_name }.compact.first
32
+ end
33
+
34
+ def domain_name=(value)
35
+ if vhosts.empty?
36
+ build_vhost(:domain_name => value)
37
+ else
38
+ vhosts.first.domain_name = value
39
+ end
40
+ end
41
+
42
+ def ssl_cert
43
+ vhosts.map {|vhost| vhost.ssl_cert }.compact.first
44
+ end
45
+
46
+ def ssl_cert=(attributes = {})
47
+ if vhosts.empty?
48
+ build_vhost.build_ssl_cert(attributes || {})
49
+ else
50
+ vhosts.first.build_ssl_cert(attributes || {})
51
+ end
52
+ end
53
+
54
+ def https?
55
+ vhosts.any? {|vhost| vhost.https? }
56
+ end
57
+
58
+ def bundled?
59
+ !! bundled
60
+ end
61
+
62
+ def newrelic?
63
+ !! newrelic
64
+ end
65
+
66
+ def to_legacy_hash
67
+ shared = %w( deploy_key repository_name type branch
68
+ deploy_action migration_command revision
69
+ run_deploy run_migrations )
70
+ data = to_hash.select {|k,v| shared.include?(k.to_s)}
71
+ Hash[*data.flatten].merge(
72
+ :newrelic => newrelic?,
73
+ :vhosts => vhost_legacy_array,
74
+ :recipes => recipe_names,
75
+ :http_bind_port => 80,
76
+ :https_bind_port => 443,
77
+ :auth => {:active => false},
78
+ :services => [{
79
+ :resource => :mongrel,
80
+ :mongrel_base_port => 5000,
81
+ :mongrel_mem_limit => 150,
82
+ :mongrel_instance_count => 3
83
+ },
84
+ {
85
+ :resource => :memcached,
86
+ :base_port => 11211,
87
+ :mem_limit => 128
88
+ }]
89
+ )
90
+ end
91
+
92
+ def vhost_legacy_array
93
+ array = vhosts.map {|vhost| vhost.to_legacy_hash }
94
+ vhosts.select {|vhost| vhost.https? }.inject(array) {|a,vhost| a.push(vhost.to_legacy_hash(true)) } if https? # legacy shit has 2 entries for an https vhost
95
+ array
96
+ end
97
+
98
+ def gems_hash
99
+ gems.map do |gem|
100
+ gem.to_legacy_hash
101
+ end
102
+ end
103
+
104
+ def recipes
105
+ Recipe.defaults + environment.stack.recipes
106
+ end
107
+
108
+ def jruby?
109
+ environment.ruby_component.is_a?(DNApi::Components::JRuby)
110
+ end
111
+
112
+ def recipe_names
113
+ recipes.map {|r| r.name }
114
+ end
115
+
116
+ def build_gem(attributes = {})
117
+ gem = GemDep.new(attributes)
118
+ gem.app = self
119
+ gems << gem
120
+ gem
121
+ end
122
+
123
+ def build_ebuild(attributes = {})
124
+ ebuild = EbuildDep.new(attributes)
125
+ ebuild.app = self
126
+ ebuilds << ebuild
127
+ ebuild
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,50 @@
1
+ module DNApi
2
+ module Component
3
+ class NoSuchComponent < StandardError; end
4
+
5
+ module ClassExt
6
+ attr_accessor :description, :key_id, :parent, :stack_versions
7
+ alias_method :key, :key_id=
8
+ alias_method :desc, :description=
9
+ alias_method :versions, :stack_versions=
10
+
11
+ def belongs_to(klass)
12
+ name = klass.name.split(/::/).last.downcase
13
+ self.send :alias_method, name, :parent
14
+ self.send :alias_method, "#{name}=", :parent=
15
+ @parent = klass
16
+ end
17
+ end
18
+
19
+ def self.included(receiver)
20
+ components << receiver
21
+ receiver.send(:attr_accessor, :parent)
22
+ receiver.extend ClassExt
23
+ end
24
+
25
+ def self.components
26
+ @components ||= []
27
+ end
28
+
29
+ def self.[](key)
30
+ components.detect {|c| c.key_id == key } or raise NoSuchComponent, "unknown component #{key.inspect}"
31
+ end
32
+
33
+ def self.from(values)
34
+ self[values.delete('key').to_sym].new(values)
35
+ end
36
+
37
+ def key
38
+ self::class.key_id
39
+ end
40
+
41
+ def to_hash
42
+ super.merge('key' => key)
43
+ end
44
+
45
+ def can_belong_to?(model)
46
+ self.class.parent === model
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ module DNApi
2
+ module ComponentPossessor
3
+
4
+ class ComponentAttachmentError < StandardError; end
5
+
6
+ module Ext
7
+ def component_group_map
8
+ @component_group_map ||= {}
9
+ end
10
+
11
+ def component_group(name, *keys)
12
+ define_method(name.to_sym) do
13
+ component_group(name)
14
+ end
15
+ component_group_map[name.to_sym] = keys
16
+ end
17
+ end
18
+
19
+ def has_component?(key)
20
+ components.any? {|c| c.key == key }
21
+ end
22
+
23
+ alias_method :component?, :has_component?
24
+
25
+ def component(key)
26
+ components.detect {|c| c.key == key }
27
+ end
28
+
29
+ def component_group(group_key)
30
+ component_keys = self::class.component_group_map[group_key.to_sym] || []
31
+ component_keys.map {|key| components.select {|c| c.key == key } }.flatten
32
+ end
33
+
34
+ def self.included(receiver)
35
+ receiver.extend(Ext)
36
+ receiver.send :many, :components
37
+ end
38
+
39
+ def add_component(key, component_options={})
40
+ c = Component[key.to_sym].new(component_options.merge(:parent => self))
41
+ unless c.can_belong_to?(self)
42
+ raise ComponentAttachmentError, "Can't attach #{key.inspect} to a #{self.class}"
43
+ end
44
+
45
+ components << c
46
+ c
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,26 @@
1
+ module DNApi
2
+ module Components
3
+ class Addons < Struct.new(:collection)
4
+ include Component
5
+
6
+ desc "Configuration for simple heroku-style third party addons"
7
+
8
+ key :addons
9
+
10
+ belongs_to App
11
+
12
+ def initialize(attrs = {})
13
+ attrs[:collection] = (attrs['collection'] || attrs[:collection]).collect{ |v| Addon.new(v) }
14
+ super attrs
15
+ end
16
+
17
+ def each(&block)
18
+ collection.each(&block)
19
+ end
20
+ include Enumerable
21
+
22
+ class Addon < Struct.new(:name, :config)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module DNApi
2
+ module Components
3
+ class Apache < Struct.new(:key)
4
+ include Component
5
+
6
+ desc "Use Apache instead of Nginx for the frontend server."
7
+
8
+ key :apache
9
+
10
+ belongs_to Environment
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module DNApi
2
+ module Components
3
+ class Cloudkick < Struct.new(:name, :oauth_key, :oauth_secret, :tags)
4
+ include Component
5
+
6
+ desc "A 3rd party service for instance monitoring."
7
+
8
+ key :cloudkick
9
+
10
+ belongs_to Instance
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module DNApi
2
+ module Components
3
+ class EncryptedBackup < Struct.new(:public_key)
4
+ include Component
5
+ desc "Enable encrypted backup support (so your customer's boss's boss will STFU)."
6
+
7
+ key :encrypted_backup
8
+
9
+ belongs_to App
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module DNApi
2
+ module Components
3
+ class Exim < Struct.new(:user, :password, :host, :outbound_host)
4
+ include Component
5
+
6
+ key :exim
7
+ belongs_to Instance
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module DNApi
2
+ module Components
3
+ class GodMonitor < Struct.new(:key)
4
+ include Component
5
+ desc "Monitor services with god."
6
+
7
+ key :god
8
+
9
+ belongs_to Environment
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ module DNApi
2
+ module Components
3
+ class Nagios < Struct.new(:master_key, :endpoint)
4
+ include Component
5
+ desc "Monitor the instances with nagios."
6
+
7
+ key :nagios
8
+
9
+ belongs_to Instance
10
+
11
+ def master_instance
12
+ instance.environment.instances.detect {|i| i.id == master_key }
13
+ end
14
+
15
+ def master?
16
+ master_instance == instance
17
+ end
18
+
19
+ def monitored_instances
20
+ if master?
21
+ instance.environment.instances
22
+ else
23
+ [master_instance]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ module DNApi
2
+ module Components
3
+ class Newrelic < Struct.new(:token, :seed)
4
+ include Component
5
+ desc "Enable newrelic support."
6
+
7
+ key :newrelic
8
+
9
+ belongs_to Instance
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module DNApi
2
+ module Components
3
+ class Passenger3 < Struct.new(:key)
4
+ include Component
5
+
6
+ desc "The latest stable version of the passenger web stack."
7
+
8
+ key :passenger3
9
+
10
+ belongs_to Environment
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,234 @@
1
+ module DNApi
2
+ module Components
3
+ class RubyVersion < VersionedComponent.new(:key)
4
+ def self.all
5
+ [ DNApi::Components::Ruby186,
6
+ DNApi::Components::Ruby187,
7
+ DNApi::Components::REE,
8
+ DNApi::Components::JRuby187,
9
+ DNApi::Components::JRuby192,
10
+ DNApi::Components::Rubinius,
11
+ DNApi::Components::Ruby193,
12
+ DNApi::Components::Ruby192 ]
13
+ end
14
+
15
+ def self.encoding_aware
16
+ [DNApi::Components::Ruby192, DNApi::Components::Ruby193, DNApi::Components::Rubinius]
17
+ end
18
+
19
+ NAME = 'Ruby'.freeze
20
+ RUBYGEMS_VERSION = '1.5.2'.freeze
21
+
22
+ def rubygems_version
23
+ self.class::RUBYGEMS_VERSION
24
+ end
25
+
26
+ def ruby_version
27
+ "#{version}_p#{patch_level}"
28
+ end
29
+
30
+ def ruby_flavor
31
+ 'dev-lang/ruby'
32
+ end
33
+
34
+ def ruby_module
35
+ 'ruby18'
36
+ end
37
+
38
+ # This shit is used by old versions of cloud_cookbooks and
39
+ # we can't remove it without breaking the ones that didn't upgrade.
40
+ #
41
+ # The latest versions of the cookbooks won't use this anymore.
42
+ # To know how to specify a database adapter see DNApi::DbStack#adapter_for
43
+ #
44
+ def mysql_adapter
45
+ 'mysql'
46
+ end
47
+ end
48
+
49
+ class Ruby186 < RubyVersion
50
+ include Component
51
+
52
+ desc "Legacy version of Ruby 1.8"
53
+
54
+ key :ruby_186
55
+
56
+ belongs_to Environment
57
+
58
+ VERSION = '1.8.6'.freeze
59
+ PATCH_LEVEL = '420'.freeze
60
+ RUBYGEMS_VERSION = '1.4.2'.freeze
61
+ end
62
+
63
+ class Ruby187 < RubyVersion
64
+ include Component
65
+
66
+ desc "Modern version of Ruby 1.8"
67
+
68
+ key :ruby_187
69
+
70
+ belongs_to Environment
71
+
72
+ VERSION = '1.8.7'.freeze
73
+ PATCH_LEVEL = '352'.freeze
74
+ end
75
+
76
+ class REE < RubyVersion
77
+ include Component
78
+
79
+ desc "Ruby Enterprise Edition"
80
+
81
+ key :ree
82
+
83
+ belongs_to Environment
84
+
85
+ NAME = 'REE'.freeze
86
+ VERSION = '1.8.7'.freeze
87
+ PATCH_LEVEL = '2011.03'.freeze
88
+
89
+ def self.label
90
+ "#{self::NAME} #{self::PATCH_LEVEL}"
91
+ end
92
+
93
+ def ruby_version
94
+ "#{version}.#{patch_level}"
95
+ end
96
+
97
+ def ruby_flavor
98
+ 'dev-lang/ruby-enterprise'
99
+ end
100
+
101
+ def ruby_module
102
+ 'rubyee'
103
+ end
104
+ end
105
+
106
+ class Ruby192 < RubyVersion
107
+ include Component
108
+
109
+ desc "Latest stable version of Ruby 1.9"
110
+
111
+ key :ruby_192
112
+
113
+ belongs_to Environment
114
+
115
+ VERSION = '1.9.2'.freeze
116
+ PATCH_LEVEL = '290-r1'.freeze
117
+
118
+ def ruby_module
119
+ 'ruby19'
120
+ end
121
+
122
+ def mysql_adapter
123
+ 'mysql2'
124
+ end
125
+ end
126
+
127
+ class Ruby193 < RubyVersion
128
+ include Component
129
+
130
+ desc "Latest development release of Ruby 1.9"
131
+
132
+ key :ruby_193
133
+
134
+ belongs_to Environment
135
+
136
+ VERSION = '1.9.3'.freeze
137
+ PATCH_LEVEL = 'p0'.freeze
138
+ RUBYGEMS_VERSION = '1.8.11'.freeze
139
+
140
+ def ruby_version
141
+ "#{version}_#{patch_level}"
142
+ end
143
+
144
+ def ruby_module
145
+ 'ruby19'
146
+ end
147
+
148
+ def mysql_adapter
149
+ 'mysql2'
150
+ end
151
+ end
152
+
153
+ class JRuby < RubyVersion
154
+ NAME = 'JRuby'.freeze
155
+ VERSION = '1.6.5'.freeze
156
+ PATCH_LEVEL = nil
157
+ RUBYGEMS_VERSION = '1.5.1'.freeze
158
+
159
+ def self.label
160
+ "#{super} #{compat_version}"
161
+ end
162
+
163
+ def ruby_version
164
+ version
165
+ end
166
+
167
+ def ruby_flavor
168
+ 'dev-java/jruby-bin'
169
+ end
170
+
171
+ def ruby_module
172
+ 'rubyjruby16'
173
+ end
174
+ end
175
+
176
+ class JRuby187 < JRuby
177
+ include Component
178
+
179
+ desc "A Ruby runtime built on the JVM"
180
+
181
+ belongs_to Environment
182
+
183
+ key :jruby_187
184
+
185
+ def self.compat_version
186
+ '(ruby-1.8.7-p330)'
187
+ end
188
+ end
189
+
190
+ class JRuby192 < JRuby
191
+ include Component
192
+
193
+ desc "A Ruby runtime built on the JVM"
194
+
195
+ belongs_to Environment
196
+
197
+ key :jruby_192
198
+
199
+ def self.compat_version
200
+ '(ruby-1.9.2-p136)'
201
+ end
202
+ end
203
+
204
+ class Rubinius < RubyVersion
205
+ include Component
206
+
207
+ desc "A Ruby runtime written mostly in Ruby"
208
+
209
+ key :rubinius
210
+
211
+ belongs_to Environment
212
+
213
+ NAME = 'Rubinius'.freeze
214
+ VERSION = '1.2.4'.freeze
215
+ PATCH_LEVEL = nil
216
+
217
+ def ruby_version
218
+ version
219
+ end
220
+
221
+ def ruby_flavor
222
+ 'dev-lang/rubinius'
223
+ end
224
+
225
+ def ruby_module
226
+ 'rubyrbx12'
227
+ end
228
+
229
+ def mysql_adapter
230
+ 'mysql2'
231
+ end
232
+ end
233
+ end
234
+ end