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,32 @@
1
+ module DNApi
2
+ module Test
3
+ module Ext
4
+ def fixture(name = default_fauxture_name, &blk)
5
+ Sweatshop.add(self, name, &blk)
6
+ end
7
+
8
+ alias_method :fix, :fixture
9
+
10
+ def generate(name = default_fauxture_name, attributes = {})
11
+ name, attributes = default_fauxture_name, name if name.is_a? Hash
12
+ Sweatshop.make(self, name, attributes)
13
+ end
14
+
15
+ alias_method :gen, :generate
16
+
17
+ def generate_attributes(name = default_fauxture_name)
18
+ Sweatshop.attributes(self, name)
19
+ end
20
+
21
+ alias_method :gen_attrs, :generate_attributes
22
+
23
+ def pick(name = default_fauxture_name)
24
+ Sweatshop.pick(self, name)
25
+ end
26
+
27
+ def default_fauxture_name
28
+ :default
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,148 @@
1
+ # Vendoring dm-sweatshop
2
+ # This code hasn't changed in over 2 years, and using
3
+ # dm-sweatshop means adding dm-sweatshop as a runtime dependency
4
+ module DNApi
5
+ class Sweatshop
6
+ # Raise when requested attributes hash or instance are not
7
+ # found in model and record maps, respectively.
8
+ #
9
+ # This usually happens when you forget to use +make+ or
10
+ # +generate+ method before trying ti +pick+ an object.
11
+ class NoFixtureExist < Exception
12
+ end
13
+
14
+ class << self
15
+ attr_accessor :model_map
16
+ attr_accessor :record_map
17
+ end
18
+
19
+ # Models map stores named Procs for a class.
20
+ # Each Proc must return a Hash of attributes.
21
+ self.model_map = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = []}}
22
+ # Records map stores named instances of a class.
23
+ # Those instances may or may not be new records.
24
+ self.record_map = Hash.new {|h,k| h[k] = Hash.new {|h,k| h[k] = []}}
25
+
26
+ # Adds a Proc to model map. Proc must return a Hash of attributes.
27
+ #
28
+ # @param klass [Class, DataMapper::Resource]
29
+ # @param name [Symbol]
30
+ # @param instance [DataMapper::Resource]
31
+ #
32
+ # @api private
33
+ #
34
+ # @returns [Array] model map
35
+ def self.add(klass, name, &proc)
36
+ self.model_map[klass][name.to_sym] << proc
37
+ end
38
+
39
+ # Adds an instance to records map.
40
+ #
41
+ # @param klass [Class, DataMapper::Resource]
42
+ # @param name [Symbol]
43
+ # @param instance [DataMapper::Resource]
44
+ #
45
+ # @api private
46
+ #
47
+ # @returns [DataMapper::Resource] added instance
48
+ def self.record(klass, name, instance)
49
+ self.record_map[klass][name.to_sym] << instance
50
+ instance
51
+ end
52
+
53
+ # Same as create but calls Model#create! and does save
54
+ # invalid models
55
+ #
56
+ # @param klass [Class, DataMapper::Resource]
57
+ # @param name [Symbol]
58
+ # @param attributes [Hash]
59
+ #
60
+ # @api private
61
+ #
62
+ # @returns [DataMapper::Resource] added instance
63
+ def self.create!(klass, name, attributes = {})
64
+ record(klass, name, klass.create!(attributes(klass, name).merge(attributes)))
65
+ end
66
+
67
+ # Creates an instance from given hash of attributes, saves it
68
+ # and adds it to the record map.
69
+ #
70
+ # @param klass [Class, DataMapper::Resource]
71
+ # @param name [Symbol]
72
+ # @param attributes [Hash]
73
+ #
74
+ # @api private
75
+ #
76
+ # @returns [DataMapper::Resource] added instance
77
+ def self.create(klass, name, attributes = {})
78
+ record(klass, name, klass.create(attributes(klass, name).merge(attributes)))
79
+ end
80
+
81
+ # Creates an instance from given hash of attributes
82
+ # and adds it to records map without saving.
83
+ #
84
+ # @param klass [Class, DataMapper::Resource]
85
+ # @param name [Symbol]
86
+ # @param attributes [Hash]
87
+ #
88
+ # @api private
89
+ #
90
+ # @returns [DataMapper::Resource] added instance
91
+ def self.make(klass, name, attributes = {})
92
+ record(klass, name, klass.new(attributes(klass, name).merge(attributes)))
93
+ end
94
+
95
+ # Returns a pre existing instance of a model from the record map
96
+ #
97
+ # @param klass [Class, DataMapper::Resource]
98
+ # @param name [Symbol]
99
+ #
100
+ # @returns [DataMapper::Resource] existing instance of a model from the record map
101
+ # @raises DataMapper::Sweatshop::NoFixtureExist when requested fixture does not exist in the record map
102
+ #
103
+ # @api private
104
+ def self.pick(klass, name)
105
+ self.record_map[klass][name.to_sym].pick || raise(NoFixtureExist, "no #{name} context fixtures have been generated for the #{klass} class")
106
+ end
107
+
108
+ # Returns a Hash of attributes from the model map
109
+ #
110
+ # @param klass [Class, DataMapper::Resource]
111
+ # @param name [Symbol]
112
+ #
113
+ # @returns [Hash] existing instance of a model from the model map
114
+ # @raises NoFixtureExist when requested fixture does not exist in the model map
115
+ #
116
+ # @api private
117
+ def self.attributes(klass, name)
118
+ proc = model_map[klass][name.to_sym].pick
119
+
120
+ if proc
121
+ expand_callable_values(proc.call)
122
+ elsif klass.superclass.is_a?(Struct)
123
+ attributes(klass.superclass, name)
124
+ else
125
+ raise NoFixtureExist, "#{name} fixture was not found for class #{klass}"
126
+ end
127
+ end
128
+
129
+ # Returns a Hash with callable values evaluated.
130
+ #
131
+ # @param hash [Hash]
132
+ #
133
+ # @returns [Hash] existing instance of a model from the model map
134
+ #
135
+ # @api private
136
+ def self.expand_callable_values(hash)
137
+ expanded = {}
138
+ hash.each do |key, value|
139
+ if value.respond_to?(:call)
140
+ expanded[key] = value.call
141
+ else
142
+ expanded[key] = value
143
+ end
144
+ end
145
+ expanded
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,3 @@
1
+ module DNApi
2
+ VERSION = '1.1.74.jruby192.c'
3
+ end
@@ -0,0 +1,24 @@
1
+ module DNApi
2
+ class VHost < Struct.new(:domain_name)
3
+ belongs_to :app
4
+ one :ssl_cert
5
+
6
+ def https?
7
+ !ssl_cert.nil?
8
+ end
9
+
10
+ def build_ssl_cert(attributes = {})
11
+ self.ssl_cert = SSLCert.new(attributes)
12
+ self.ssl_cert.vhost = self
13
+ self.ssl_cert
14
+ end
15
+
16
+ def to_legacy_hash(include_cert = false)
17
+ hash = {:role => app.environment.name, :name => domain_name}
18
+ if include_cert
19
+ hash.merge!(ssl_cert.to_legacy_hash)
20
+ end
21
+ hash
22
+ end
23
+ end
24
+ end
data/spec/app_spec.rb ADDED
@@ -0,0 +1,68 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe DNApi::App do
4
+ describe "#bundled" do
5
+ it 'can be unbundled' do
6
+ DNApi::App.new(:bundled => false).should_not be_bundled
7
+ end
8
+
9
+ it 'can be bundled' do
10
+ DNApi::App.new(:bundled => true).should be_bundled
11
+ end
12
+
13
+ it 'defaults to be unbundled' do
14
+ DNApi::App.new.should_not be_bundled
15
+ end
16
+ end
17
+
18
+ describe "#build_gem" do
19
+ it 'adds the gem to gems' do
20
+ app = DNApi::App.new
21
+ gem = app.build_gem(:name => 'rails', :version => 3)
22
+ app.gems.should include(gem)
23
+ end
24
+
25
+ it 'sets the app on the gem' do
26
+ app = DNApi::App.new
27
+ gem = app.build_gem(:name => 'rails', :version => 3)
28
+ gem.app.should == app
29
+ end
30
+ end
31
+
32
+ describe "#build_ebuild" do
33
+ it 'adds the ebuild to ebuilds' do
34
+ app = DNApi::App.new
35
+ ebuild = app.build_ebuild(:name => 'cowsay')
36
+ app.ebuilds.should include(ebuild)
37
+ end
38
+
39
+ it 'sets the app on the ebuild' do
40
+ app = DNApi::App.new
41
+ ebuild = app.build_ebuild(:name => 'cowsay')
42
+ ebuild.app.should == app
43
+ end
44
+ end
45
+
46
+ describe "#component" do
47
+ it 'can find and return a component' do
48
+ app = DNApi::App.new
49
+ app.add_component(:encrypted_backup, :public_key => 'foobarbaz')
50
+ app.component(:encrypted_backup).public_key.should == 'foobarbaz'
51
+ end
52
+ end
53
+ describe "nginx_nodejs environment" do
54
+ before do
55
+ @environment = DNApi::Environment.new(:stack => DNApi::Stack.get('nginxtcp'))
56
+ @app = DNApi::App.new
57
+ @environment.apps = [@app]
58
+ end
59
+ it 'has a nginx_nodejs service' do
60
+ hash = @app.to_legacy_hash
61
+ hash[:services][0][:resource].should == :mongrel
62
+ end
63
+ it 'has a memcached service' do
64
+ hash = @app.to_legacy_hash
65
+ hash[:services][1][:resource].should == :memcached
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module DNApi
4
+ class TestComponent < Struct.new(:abc, :def)
5
+ include Component
6
+
7
+ key :testing
8
+ belongs_to Instance
9
+ end
10
+
11
+ class Instance
12
+ component_group :test_components, :testing
13
+ end
14
+ end
15
+
16
+ describe DNApi::Component do
17
+
18
+ it "allows the component" do
19
+ env = DNApi::Environment.new(:stack => DNApi::Stack.get('nginx_mongrel'))
20
+ instance = env.build_instance(:id => "hax", :role => 'solo')
21
+ instance.add_component(:testing)
22
+
23
+ instance2 = DNApi.from(JSON.parse(instance.to_dna.to_json))
24
+ instance2.components.should_not be_empty
25
+ instance2.component(:testing).parent.should == instance2
26
+ end
27
+
28
+ it "Allows component groups" do
29
+ env = DNApi::Environment.new(:stack => DNApi::Stack.get('nginx_mongrel'))
30
+ instance = env.build_instance(:id => "hax")
31
+ instance.add_component(:testing)
32
+
33
+ instance.test_components.should_not be_empty
34
+ end
35
+
36
+ context "adding one to another model" do
37
+ class SpecificComponent < DNApi::Struct.new(:id)
38
+ include DNApi::Component
39
+
40
+ key :specific_component
41
+
42
+ belongs_to DNApi::App
43
+ end
44
+
45
+ it "won't let you attach it to the wrong model" do
46
+ env = DNApi::Environment.new
47
+ lambda do
48
+ env.add_component(:specific_component)
49
+ end.should raise_error(DNApi::ComponentPossessor::ComponentAttachmentError)
50
+ end
51
+
52
+ it "will let you attach it to the right model" do
53
+ app = DNApi::App.new
54
+ lambda do
55
+ app.add_component(:specific_component)
56
+ end.should_not raise_error
57
+ end
58
+
59
+ it "won't let you attach a bogus component" do
60
+ env = DNApi::Environment.new
61
+ lambda do
62
+ env.add_component(:lovely_bunch_of_coconuts)
63
+ end.should raise_error(DNApi::Component::NoSuchComponent)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe DNApi::Components::Addons do
4
+ before :each do
5
+ @environment = DNApi::Environment.new(:stack => DNApi::Stack.get('nginx_mongrel'))
6
+ @environment.build_instance(:role => :db_master)
7
+ @instance = @environment.build_instance(:id => 'default', :role => :app_master)
8
+ @app = @environment.build_app
9
+ @addons = @app.add_component :addons, {
10
+ :collection => [
11
+ {:name => 'hoptoad', :config => {"HOPTOAD_API_KEY" => "adf62722fda909cb"}},
12
+ ]}
13
+ end
14
+
15
+ it 'had addons component' do
16
+ @app.should have_component(:addons)
17
+ component = @app.component(:addons).entries.first #Note: 1.8.6's Enumerable does not include .first
18
+ component.should be_a DNApi::Components::Addons::Addon
19
+ component[:name].should == "hoptoad"
20
+ component[:config].should == {"HOPTOAD_API_KEY" => "adf62722fda909cb"}
21
+ end
22
+
23
+ it 'should be able to serialize and deserialize' do
24
+ json = @environment.dna_for_instance(@instance).to_json
25
+ DNApi.from(json)
26
+ end
27
+
28
+ it 'should be able to serialize and deserialize' do
29
+ json = @environment.dna_for_instance_id(@instance.id).to_json
30
+ DNApi.from(json)
31
+ end
32
+
33
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe DNApi::Components::Cloudkick do
4
+ before :each do
5
+ @environment = DNApi::Environment.new
6
+ @instance = @environment.build_instance(:id => 'default', :role => :app_master)
7
+ @cloudkick = @instance.add_component :cloudkick,
8
+ :name => 'blahblahblah',
9
+ :oauth_key => 'abc',
10
+ :oauth_secret => 'def',
11
+ :tags => %w[foo bar bang]
12
+ end
13
+
14
+ it 'is the win' do
15
+ @instance.should have_component(:cloudkick)
16
+ end
17
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe DNApi::Components::Nagios do
4
+
5
+ before do
6
+ @environment = DNApi::Environment.new
7
+ end
8
+
9
+ describe "#monitored_instances" do
10
+ context "for an app_master" do
11
+ before do
12
+ @instance = @environment.build_instance(:id => 'master', :private_hostname => 'master', :role => :app_master)
13
+ @instance.add_component(:nagios, :master_key => 'master', :endpoint => 'http://example.com/')
14
+
15
+ (1).upto(3) do |i|
16
+ instance = @environment.build_instance(:id => "slave#{i}", :private_hostname => "slave#{i}", :role => :app)
17
+ instance.add_component(:nagios, :master_key => 'master', :endpoint => 'http://example.com/')
18
+ end
19
+ end
20
+
21
+ it 'is all the instances in the cluster' do
22
+ @instance.component(:nagios).monitored_instances.should == @environment.instances
23
+ end
24
+ end
25
+
26
+ context "for an app" do
27
+ before do
28
+ master = @environment.build_instance(:id => 'master', :private_hostname => 'master', :role => :app_master)
29
+ master.add_component(:nagios, :master_key => 'master', :endpoint => 'http://example.com/')
30
+
31
+ (1).upto(3) do |i|
32
+ @instance = @environment.build_instance(:id => "slave#{i}", :private_hostname => "slave#{i}", :role => :app)
33
+ @instance.add_component(:nagios, :master_key => 'master', :endpoint => 'http://example.com/')
34
+ end
35
+ end
36
+
37
+ it 'is all the app_master instance' do
38
+ @instance.component(:nagios).monitored_instances.should == [@environment.app_master]
39
+ end
40
+ end
41
+ end
42
+ end