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