ruby_yacht 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +27 -0
  3. data/.gitignore +4 -0
  4. data/.rdoc_options +29 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +1156 -0
  7. data/.travis.yml +4 -0
  8. data/Gemfile +3 -0
  9. data/Gemfile.lock +44 -0
  10. data/LICENSE +8 -0
  11. data/README.md +216 -0
  12. data/doc/CONTRIBUTING.md +12 -0
  13. data/doc/TODO.md +28 -0
  14. data/doc/configuration_sample.rb +87 -0
  15. data/lib/ruby_yacht/dsl/app.rb +59 -0
  16. data/lib/ruby_yacht/dsl/configuration.rb +55 -0
  17. data/lib/ruby_yacht/dsl/database.rb +57 -0
  18. data/lib/ruby_yacht/dsl/dns_server.rb +38 -0
  19. data/lib/ruby_yacht/dsl/dsl.rb +252 -0
  20. data/lib/ruby_yacht/dsl/project.rb +140 -0
  21. data/lib/ruby_yacht/dsl.rb +6 -0
  22. data/lib/ruby_yacht/images/app/Dockerfile.erb +32 -0
  23. data/lib/ruby_yacht/images/app/checkout.rb +7 -0
  24. data/lib/ruby_yacht/images/app/startup.rb +17 -0
  25. data/lib/ruby_yacht/images/app/update_database_config.rb +45 -0
  26. data/lib/ruby_yacht/images/app-dependencies/Dockerfile.erb +23 -0
  27. data/lib/ruby_yacht/images/app-dependencies/install_gems.rb +12 -0
  28. data/lib/ruby_yacht/images/database/Dockerfile.erb +26 -0
  29. data/lib/ruby_yacht/images/database/load_seeds.rb +42 -0
  30. data/lib/ruby_yacht/images/database/setup.rb +19 -0
  31. data/lib/ruby_yacht/images/database/setup_database.sql.erb +12 -0
  32. data/lib/ruby_yacht/images/deploy/Dockerfile.erb +2 -0
  33. data/lib/ruby_yacht/images/web/Dockerfile.erb +25 -0
  34. data/lib/ruby_yacht/images/web/add_app.rb +12 -0
  35. data/lib/ruby_yacht/images/web/add_project.rb +14 -0
  36. data/lib/ruby_yacht/images/web/app_config.erb +11 -0
  37. data/lib/ruby_yacht/images/web/index.html.erb +10 -0
  38. data/lib/ruby_yacht/images/web/index_config.erb +12 -0
  39. data/lib/ruby_yacht/images/web/setup.rb +22 -0
  40. data/lib/ruby_yacht/runner/build.rb +21 -0
  41. data/lib/ruby_yacht/runner/build_images.rb +82 -0
  42. data/lib/ruby_yacht/runner/checkout.rb +68 -0
  43. data/lib/ruby_yacht/runner/command.rb +161 -0
  44. data/lib/ruby_yacht/runner/help.rb +55 -0
  45. data/lib/ruby_yacht/runner/implode.rb +33 -0
  46. data/lib/ruby_yacht/runner/run_containers.rb +105 -0
  47. data/lib/ruby_yacht/runner/runner.rb +42 -0
  48. data/lib/ruby_yacht/runner/services.rb +79 -0
  49. data/lib/ruby_yacht/runner/shell.rb +66 -0
  50. data/lib/ruby_yacht/runner/update_hosts.rb +72 -0
  51. data/lib/ruby_yacht/runner.rb +18 -0
  52. data/lib/ruby_yacht.rb +6 -0
  53. data/ruby_yacht.gemspec +18 -0
  54. data/spec/docker/Dockerfile +5 -0
  55. data/spec/docker/build.bash +10 -0
  56. data/spec/dsl/app_spec.rb +47 -0
  57. data/spec/dsl/configuration_spec.rb +64 -0
  58. data/spec/dsl/database_spec.rb +75 -0
  59. data/spec/dsl/dns_server_spec.rb +25 -0
  60. data/spec/dsl/dsl_spec.rb +298 -0
  61. data/spec/dsl/project_spec.rb +266 -0
  62. data/spec/fixtures/app-dependencies-dockerfile +25 -0
  63. data/spec/fixtures/database-dockerfile +31 -0
  64. data/spec/fixtures/deploy-dockerfile +2 -0
  65. data/spec/fixtures/mars-dockerfile +32 -0
  66. data/spec/fixtures/multi-project-web-dockerfile +35 -0
  67. data/spec/fixtures/web-dockerfile +27 -0
  68. data/spec/runner/build_images_spec.rb +164 -0
  69. data/spec/runner/build_spec.rb +86 -0
  70. data/spec/runner/checkout_spec.rb +128 -0
  71. data/spec/runner/command_spec.rb +94 -0
  72. data/spec/runner/help_spec.rb +73 -0
  73. data/spec/runner/implode_spec.rb +62 -0
  74. data/spec/runner/run_containers_spec.rb +141 -0
  75. data/spec/runner/runner_spec.rb +117 -0
  76. data/spec/runner/services_spec.rb +135 -0
  77. data/spec/runner/shell_spec.rb +123 -0
  78. data/spec/runner/update_hosts_spec.rb +163 -0
  79. data/spec/spec_helper.rb +10 -0
  80. data/spec/support/docker_stubbing.rb +93 -0
  81. data/spec/support/test_project.rb +56 -0
  82. metadata +193 -0
@@ -0,0 +1,252 @@
1
+ module RubyYacht
2
+ # This module contains types for defining our configuration DSL.
3
+ module DSL
4
+ # This module provides the core functionality for providing configuration
5
+ # DSLs.
6
+ #
7
+ # Classes that provide DSLs should include this module and extend the
8
+ # ClassMethods module.
9
+ module Base
10
+ # This module provides class methods for defining DSLs.
11
+ module ClassMethods
12
+ # The attributes that must be provided on this DSL type.
13
+ def required_attributes
14
+ @required_attributes ||= []
15
+ end
16
+
17
+ # The attributes that this DSL type can accept.
18
+ def all_attributes
19
+ @all_attributes ||= []
20
+ end
21
+
22
+ # The default values that should be set on new DSL objects.
23
+ def default_values
24
+ @default_values ||= {}
25
+ end
26
+
27
+ # The attributes that we copy from this type to the real type the DSL
28
+ # creates.
29
+ def copied_attributes
30
+ @copied_attributes
31
+ end
32
+
33
+ # The real type that this DSL creates.
34
+ def created_type
35
+ @created_type
36
+ end
37
+
38
+ # This method adds an attribute to the DSL.
39
+ #
40
+ # This will define a method on the DSL class, and register the attribute
41
+ # with the class.
42
+ #
43
+ # You generally won't need to call this yourself, but it provides a
44
+ # shared implementation for the rest of the attribute-definition
45
+ # methods.
46
+ #
47
+ # ### Parameters
48
+ #
49
+ # * **method_name: Symbol** The name of the method to create.
50
+ # * **attribute_name: Symbol** The name of the instance variable that
51
+ # the method sets.
52
+ # * **default: Object** The default value that should be set
53
+ # for this attribute.
54
+ # * **required: Bool** Whether the user should be required to
55
+ # provide a value for this attribute.
56
+ # * **processing_block: Proc** The block that we should invoke when
57
+ # the method is called, to set the value
58
+ # of the attribute.
59
+ def add_generic_attribute(method_name, attribute_name, default = nil, required = true, &processing_block)
60
+ define_method(method_name, &processing_block)
61
+ if default != nil
62
+ default_values[attribute_name] = default
63
+ end
64
+ if required
65
+ required_attributes << attribute_name
66
+ end
67
+ all_attributes << attribute_name
68
+ end
69
+
70
+ # This method adds a standard attribute to the DSL.
71
+ #
72
+ # This will create a method that you can invoke with a single parameter,
73
+ # which provides the new value for the attribute.
74
+ #
75
+ # ### Parameters
76
+ #
77
+ # * **name: Symbol** The name of the attribute, which will also be
78
+ # the name of the method.
79
+ # * **default: Object** The default value for the attribute.
80
+ # * **required: Bool** Whether we should require the user to provide
81
+ # a value for the attribute.
82
+ def add_attribute(name, default = nil, required = true)
83
+ add_generic_attribute name, name, default, required do |value|
84
+ instance_variable_set("@#{name}", value)
85
+ end
86
+ end
87
+
88
+ # This method adds an attribute to the DSL for managing a list.
89
+ #
90
+ # This will create a method that you can invoke with a single parameter,
91
+ # which will be added to the list.
92
+ #
93
+ # ### Parameters
94
+ #
95
+ # * **name: Symbol** The name of the method. The name of the
96
+ # attribute will be this name, followed by an s.
97
+ def add_list(name)
98
+ add_generic_attribute name, "#{name}s", [], false do |value|
99
+ variable_name = "@#{name}s"
100
+ list = instance_variable_get(variable_name)
101
+ list << value
102
+ instance_variable_set(variable_name, list)
103
+ end
104
+ end
105
+
106
+ # This method adds an attribute to the DSL for managing a Boolean flag.
107
+ #
108
+ # This will create a method that you can call to change the value from
109
+ # true to false.
110
+ #
111
+ # The value will always be false by default.
112
+ #
113
+ # ### Parameters
114
+ #
115
+ # * **name: Symbol** The name of the method, which will also be the
116
+ # name of the attribute.
117
+ def add_boolean(name)
118
+ add_generic_attribute name, name, false, false do
119
+ instance_variable_set("@#{name}", true)
120
+ end
121
+ end
122
+
123
+ # This method adds an object from another DSL to this DSL.
124
+ #
125
+ # This will create a method that you can call with a block, which will
126
+ # allow you to use the other DSL object. You can also give it arbitrary
127
+ # other arguments, which will be given to the initializer for the DSL.
128
+ #
129
+ # ### Parameters
130
+ #
131
+ # * **name: Symbol** The name of the method, which will also be the
132
+ # name of the attribute.
133
+ # * **type: String** The name of the type that provides the DSL when
134
+ # they call this method.
135
+ # * **options: Hash** Other options about the DSL. Right now the only
136
+ # option is *required*, which indicates whether
137
+ # they must define this configuraiton.
138
+ def add_object(name, type, options = {})
139
+ unless options.has_key?(:required)
140
+ options[:required] = true
141
+ end
142
+ add_generic_attribute name, name, nil, options[:required] do |*args, &config_block|
143
+ variable_name = "@#{name}"
144
+ object_config = Kernel.const_get(type).new(*args)
145
+ value = object_config.run(config_block).create_object
146
+ instance_variable_set(variable_name, value)
147
+ end
148
+ end
149
+
150
+ # This method adds a list of objects from another DSL to this DSL.
151
+ #
152
+ # This will create a method that you can call with a block to create the
153
+ # other object and add it to the list. You can also give it arbitrary
154
+ # other arguments, which will be given to the initializer for the DSL.
155
+ #
156
+ # ### Parameters
157
+ #
158
+ # * **name: Symbol** The name of the method. The attribute name will
159
+ # be this, followed by an "s"
160
+ # * **type: String** The name of the type that provides the type when
161
+ # they call this method.
162
+ def add_object_list(name, type)
163
+ add_generic_attribute name, "#{name}s", [], false do |*args, &config_block|
164
+ variable_name = "@#{name}s"
165
+ list = instance_variable_get(variable_name)
166
+ object_config = Kernel.const_get(type).new(*args)
167
+ value = object_config.run(config_block).create_object
168
+ list << value
169
+ instance_variable_set(variable_name, list)
170
+ end
171
+ end
172
+
173
+ # This method specifies that this DSL class creates a real object of
174
+ # a certain type.
175
+ #
176
+ # ### Parameters
177
+ #
178
+ # * **type: Class** The type that this DSL creates.
179
+ # * **attributes: Array** The attributes that we copy from the DSL
180
+ # to the related object. If this is not
181
+ # provided, we will copy all of the
182
+ # attributes that this DSL has defined so far.
183
+ def creates_object(type, attributes = nil)
184
+ attributes ||= self.all_attributes
185
+ @copied_attributes = attributes
186
+ @created_type = type
187
+ end
188
+ end
189
+
190
+ # This method runs a block with DSL methods.
191
+ #
192
+ # The block will reun in the instance context of the DSL object, so you
193
+ # can call the DSL methods directly.
194
+ #
195
+ # It will also copy the default values into the attributes on the DSL
196
+ # object.
197
+ #
198
+ # ### Parameters
199
+ #
200
+ # * **block: Proc** The block to run.
201
+ def run(block)
202
+ defaults = self.class.default_values || {}
203
+ defaults.each do |name, value|
204
+ copy =
205
+ case value
206
+ when TrueClass, FalseClass, Fixnum
207
+ value
208
+ else
209
+ value.dup
210
+ end
211
+ instance_variable_set("@#{name}", copy)
212
+ end
213
+ instance_eval(&block)
214
+ self
215
+ end
216
+
217
+ # This method checks that all of the required attributes have been set on
218
+ # the object.
219
+ #
220
+ # If they haven't, this will raise an exception.
221
+ def check_required_attributes
222
+ attributes = self.class.required_attributes || []
223
+ attributes.each do |name|
224
+ value = instance_variable_get("@#{name}")
225
+ if value == nil || value == ''
226
+ raise "Missing required attribute #{name} for #{self.class}"
227
+ end
228
+ end
229
+ end
230
+
231
+ # This method creates an object with the attributes from this instance.
232
+ #
233
+ # We will check that all the required attributes have been set first, and
234
+ # will raise an exception if they haven't.
235
+ #
236
+ # The created type, and the attributes we set on it, will be defined by
237
+ # the call to the class method `creates_object`.
238
+ #
239
+ # ### Returns
240
+ # This will return the newly created object.
241
+ def create_object
242
+ check_required_attributes
243
+ object = self.class.created_type.new
244
+
245
+ self.class.copied_attributes.each do |name|
246
+ object.send("#{name}=", instance_variable_get("@#{name}"))
247
+ end
248
+ object
249
+ end
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,140 @@
1
+ module RubyYacht
2
+ # This class provides a configuration for a project in our system.
3
+ #
4
+ # A project is a family of apps that communicate with each other and
5
+ # share a database.
6
+ class Project
7
+ # The name of the project.
8
+ attr_accessor :name
9
+
10
+ # The prefix that we use before all of the images and containers for the
11
+ # project.
12
+ attr_accessor :system_prefix
13
+
14
+ # The domain that the apps for this project are accessed under.
15
+ attr_accessor :domain
16
+
17
+ # The hostname for the repository that contains the code for the apps.
18
+ attr_accessor :repository
19
+
20
+ # The secret key that the apps should use for signing cookies.
21
+ attr_accessor :secret_key_base
22
+
23
+ # The environment that the apps should run in.
24
+ attr_accessor :rails_environment
25
+
26
+ # Whether we should check out the code on the host machine, rather than
27
+ # keeping it entirely inside the container.
28
+ attr_accessor :check_out_locally
29
+
30
+ # Whether we should create a special container with all the apps for running
31
+ # deploys.
32
+ attr_accessor :create_deploy_container
33
+
34
+ # The configuration for the database. This is a RubyYacht::Database.
35
+ attr_accessor :database
36
+
37
+ # The configuration for the apps. Each entry is a RubyYacht::App.
38
+ attr_accessor :apps
39
+
40
+ # The configuration for the DNS for the apps. This is a RubyYacht::DnsServer.
41
+ attr_accessor :dns_server
42
+
43
+ # This class provides a DSL for configuring a project.
44
+ #
45
+ # You can access this inside RubyYacht::Configuration::DSL by calling
46
+ # `project`. It will create a RubyYacht::Project.
47
+ class DSL
48
+ include RubyYacht::DSL::Base
49
+ extend RubyYacht::DSL::Base::ClassMethods
50
+
51
+ # This initializer creates a new project.
52
+ #
53
+ # ### Parameters
54
+ #
55
+ # * *name: String* The name of the project
56
+ def initialize(name)
57
+ @name = name.to_sym
58
+ end
59
+
60
+ add_attribute :name
61
+
62
+ ##
63
+ # :method: system_prefix
64
+ # You can call `system_prefix 'my-apps'` to set the projects
65
+ # system_prefix` to `my-apps`
66
+ add_attribute :system_prefix
67
+
68
+ ##
69
+ # :method: domain
70
+ # You can call `domain 'test.com'` to set the project's `domain` to
71
+ # test.com
72
+ add_attribute :domain
73
+
74
+ ##
75
+ # :method: secret_key_base
76
+ # You can call `secret_key_base '1234kj1234k;lj1234jklh'` to set the
77
+ # project's `secret_key_base` to `1234kj1234k;lj1234jklh`.
78
+ add_attribute :secret_key_base
79
+
80
+ ##
81
+ # :method: repository
82
+ # You can call `repository 'github.com'` to set the project's `repository`
83
+ # to `github.com`
84
+ add_attribute :repository
85
+
86
+ ##
87
+ # :method: rails_environment
88
+ #
89
+ # You can call `rails_environment 'staging'` to set the project's
90
+ # `rails_environment` to `staging`.
91
+ #
92
+ # The default is `development`.
93
+ add_attribute :rails_environment, 'development'
94
+
95
+ ##
96
+ # :method: check_out_locally
97
+ #
98
+ # You can call `check_out_locally` to set the project's
99
+ # `check_out_locally` flag to `true`. The default is false.
100
+ add_boolean :check_out_locally
101
+
102
+ ##
103
+ # :method: create_deploy_container
104
+ #
105
+ # You can call `create_deploy_container` to set the project's
106
+ # `create_deploy_container` flag to `true`. The default is false.
107
+ add_boolean :create_deploy_container
108
+
109
+ ##
110
+ # :method: app
111
+ #
112
+ # You can call `app 'mars'` to add an app called `mars`. This takes a
113
+ # block for configuring the app, which allows you to call methods in
114
+ # RubyYacht::App::DSL
115
+ add_object_list :app, 'RubyYacht::App::DSL'
116
+
117
+ ##
118
+ # :method: database
119
+ #
120
+ # You can call `database` to configure the database for the project.
121
+ # This takes a block for configuring the database, which allows you to
122
+ # call methods in RubyYacht::Database::DSL
123
+ #
124
+ # You must call this in your project config.
125
+ add_object :database, 'RubyYacht::Database::DSL'
126
+
127
+ ##
128
+ # :method: dns_server
129
+ #
130
+ # You can call `dns_server` to configure the DNS for the project.
131
+ # This takes a block for configuring the DNS , which allows you to
132
+ # call methods in RubyYacht::DnsServer::DSL
133
+ #
134
+ # This is optional.
135
+ add_object :dns_server, 'RubyYacht::DnsServer::DSL', required: false
136
+
137
+ creates_object Project
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,6 @@
1
+ require 'ruby_yacht/dsl/dsl'
2
+ require 'ruby_yacht/dsl/project'
3
+ require 'ruby_yacht/dsl/app'
4
+ require 'ruby_yacht/dsl/database'
5
+ require 'ruby_yacht/dsl/dns_server'
6
+ require 'ruby_yacht/dsl/configuration'
@@ -0,0 +1,32 @@
1
+ FROM <%= @project.system_prefix %>-app-dependencies
2
+
3
+ ENV DATABASE_HOST <%= @project.database.host %>
4
+ ENV DATABASE_NAME <%= @project.database.name %>
5
+ ENV DATABASE_PASSWORD <%= @project.database.password %>
6
+ ENV DATABASE_USERNAME <%= @project.database.username %>
7
+ ENV RAILS_ENV <%= @project.rails_environment %>
8
+ ENV RAILS_PORT <%= @app.port %>
9
+ ENV REPOSITORY_HOST <%= @project.repository %>
10
+ ENV SECRET_KEY_BASE <%= @project.secret_key_base %>
11
+ ENV SYSTEM_PREFIX <%= @project.system_prefix %>
12
+
13
+ RUN rm -r /var/code
14
+ RUN mkdir -p /var/code
15
+
16
+ COPY startup.rb /var/docker/startup.rb
17
+ COPY checkout.rb /var/docker/checkout.rb
18
+ COPY update_database_config.rb /var/docker/update_database_config.rb
19
+
20
+ RUN chmod u+x /var/docker/*.rb
21
+
22
+ ENV REPOSITORY_NAME <%= @app.repository_name %>
23
+
24
+ RUN /var/docker/checkout.rb
25
+
26
+ WORKDIR /var/code
27
+
28
+ RUN bundle install && bundle clean --force
29
+
30
+ EXPOSE <%= @app.port %>
31
+
32
+ CMD /var/docker/startup.rb
@@ -0,0 +1,7 @@
1
+ #! /usr/local/bin/ruby
2
+
3
+ if !File.exist?('/var/code/Gemfile')
4
+ repository_host = ENV['REPOSITORY_HOST']
5
+ repository_name = ENV['REPOSITORY_NAME']
6
+ system "git clone git@#{repository_host}:#{repository_name} /var/code"
7
+ end
@@ -0,0 +1,17 @@
1
+ #! /usr/local/bin/ruby
2
+
3
+ require 'fileutils'
4
+ require_relative 'checkout'
5
+ require_relative 'update_database_config'
6
+
7
+ FileUtils.cd '/var/code'
8
+
9
+ system "bundle install"
10
+ system "rake db:migrate"
11
+
12
+ system "rails r Rails.cache.clear"
13
+ if ENV['RAILS_ENV'] != 'development'
14
+ system "rake assets:precompile"
15
+ end
16
+
17
+ exec "rails s -b 0.0.0.0 -p $RAILS_PORT -e $RAILS_ENV"
@@ -0,0 +1,45 @@
1
+ #! /usr/local/bin/ruby
2
+ require 'yaml'
3
+
4
+ database_host = ENV['DATABASE_HOST']
5
+ local_database = (database_host == 'localhost')
6
+ if local_database
7
+ database_host = ENV['SYSTEM_PREFIX'] + '-database'
8
+ end
9
+
10
+ common_config = {
11
+ 'adapter' => 'mysql2',
12
+ 'username' => ENV['DATABASE_USERNAME'],
13
+ 'password' => ENV['DATABASE_PASSWORD'],
14
+ 'reconnect' => true,
15
+ 'host' => database_host,
16
+ 'database' => ENV['DATABASE_NAME']
17
+ }
18
+
19
+ database_config = {
20
+ ENV['RAILS_ENV'] => common_config
21
+ }
22
+
23
+ if ENV['RAILS_ENV'] == 'development' && local_database
24
+ database_config['test'] = common_config.dup
25
+ database_config['test']['database'] += '_test'
26
+ database_config['development']['database'] += '_development'
27
+ end
28
+
29
+ File.open('/var/code/config/database.yml', 'w') do |file|
30
+ file.write(database_config.to_yaml)
31
+ end
32
+
33
+ secret_key_config = {
34
+ ENV['RAILS_ENV'] => {
35
+ 'secret_key_base' => ENV['SECRET_KEY_BASE']
36
+ }
37
+ }
38
+
39
+ if ENV['RAILS_ENV'] == 'development'
40
+ secret_key_config['test'] = secret_key_config['development'].dup
41
+ end
42
+
43
+ File.open('/var/code/config/secrets.yml', 'w') do |file|
44
+ file.write(secret_key_config.to_yaml)
45
+ end
@@ -0,0 +1,23 @@
1
+ # This Dockerfile creates an image for installing all of the gem dependencies
2
+ # for all of the apps.
3
+ #
4
+ # This is a slow process, so this should be kept as simple as possible so that
5
+ # it can remain unchanged.
6
+
7
+ FROM ruby:2.3
8
+
9
+ RUN mkdir -p /root/.ssh
10
+ COPY id_rsa /root/.ssh
11
+ RUN ssh-keyscan <%= @project.repository %> >> /root/.ssh/known_hosts
12
+
13
+ RUN mkdir -p /var/docker/
14
+ COPY install_gems.rb /var/docker/install_gems.rb
15
+
16
+ <% @project.apps.each do |app| %>
17
+ RUN ruby /var/docker/install_gems.rb <%= app.name %> <%= @project.repository %> <%= app.repository_name %>
18
+ <% end %>
19
+
20
+ RUN rm /var/docker/install_gems.rb
21
+
22
+ RUN apt-get update && apt-get upgrade -y
23
+ RUN apt-get install -y mysql-client
@@ -0,0 +1,12 @@
1
+ #! /usr/local/bin/ruby
2
+
3
+ require 'yaml'
4
+
5
+ app_name = ARGV.shift
6
+ repository_host = ARGV.shift
7
+ repository_name = ARGV.shift
8
+
9
+ puts "Installing gems for #{app_name}"
10
+ system "mkdir -p /var/code"
11
+ system "git clone git@#{repository_host}:#{repository_name} /var/code/#{app_name}"
12
+ system "cd /var/code/#{app_name} && bundle install"
@@ -0,0 +1,26 @@
1
+ FROM <%= @project.system_prefix %>-app-dependencies
2
+
3
+ <% database = @project.database %>
4
+
5
+ ENV DEBIAN_FRONTEND noninteractive
6
+ RUN apt-get install -y mysql-server
7
+
8
+ COPY setup.rb /var/docker/setup.rb
9
+ COPY setup_database.sql.erb /var/docker/setup_database.sql.erb
10
+ COPY load_seeds.rb /var/docker/load_seeds.rb
11
+
12
+ RUN ruby /var/docker/setup.rb <%= database.name %> <%= database.username %> <%= database.password %> <%= @project.rails_environment %>
13
+
14
+ <% initialized = false %>
15
+ <% @project.apps.each do |app| %>
16
+ <% database_name = database.name %>
17
+ <% database_name += '_development' if @project.rails_environment == 'development' %>
18
+ RUN ruby /var/docker/load_seeds.rb <%= app.name %> <%= database_name %> <%= database.username %> <%= database.password %> <%= initialized %>
19
+ <% initialized = true %>
20
+ <% end %>
21
+ RUN rm -r /var/docker
22
+ RUN rm -r /var/code
23
+
24
+ EXPOSE 3306
25
+
26
+ CMD mysqld_safe --bind-address=0.0.0.0
@@ -0,0 +1,42 @@
1
+ #! /usr/local/bin/ruby
2
+
3
+ require 'yaml'
4
+ require 'fileutils'
5
+
6
+ puts "Loading seeds"
7
+
8
+ app_name = ARGV.shift
9
+ name = ARGV.shift
10
+ username = ARGV.shift
11
+ password = ARGV.shift
12
+ initialized_database = (ARGV.shift == 'true')
13
+
14
+ puts "Creating #{name} database"
15
+ system "service mysql start"
16
+
17
+ directory = "/var/code/#{app_name}"
18
+ config_path = "#{directory}/config/database.yml"
19
+
20
+ FileUtils.cd directory
21
+ database_config = {
22
+ 'development' => {
23
+ 'adapter' => 'mysql2',
24
+ 'encoding' => 'utf8',
25
+ 'reconnect' => true,
26
+ 'username' => username,
27
+ 'password' => password,
28
+ 'host' => 'localhost',
29
+ 'database' => name
30
+ }
31
+ }
32
+
33
+ File.open(config_path, "w") do |file|
34
+ file.write(database_config.to_yaml)
35
+ end
36
+
37
+ if initialized_database
38
+ rake_command = "bundle exec rake db:migrate; bundle exec rake db:seed"
39
+ else
40
+ rake_command = "bundle exec rake db:reset"
41
+ end
42
+ system "bundle install; #{rake_command}"
@@ -0,0 +1,19 @@
1
+ #! /usr/local/bin/ruby
2
+
3
+ require 'erb'
4
+ require 'yaml'
5
+
6
+ @database_name = ARGV.shift
7
+ @database_user = ARGV.shift
8
+ @database_password = ARGV.shift
9
+ @rails_environment = ARGV.shift
10
+
11
+ system "service mysql start"
12
+ system "mysql -uroot -e \"CREATE USER '#{@database_user}'@'localhost' IDENTIFIED BY '#{@database_password}'\""
13
+ system "mysql -uroot -e \"CREATE USER '#{@database_user}'@'%' IDENTIFIED BY '#{@database_password}'\""
14
+
15
+ template = ERB.new(File.read('/var/docker/setup_database.sql.erb'))
16
+ File.open('/var/docker/create_database.sql', 'w') do |file|
17
+ file.write(template.result(binding))
18
+ end
19
+ system "mysql -uroot < /var/docker/create_database.sql"
@@ -0,0 +1,12 @@
1
+ <%
2
+ if @rails_environment == 'development'
3
+ database_names = %w(_development _test).map { |suffix| @database_name + suffix }
4
+ else
5
+ database_names = [@database_name]
6
+ end
7
+ %>
8
+ <% database_names.each do |database_name| %>
9
+ GRANT ALL ON <%= database_name %>.* to '<%= @database_user %>'@'localhost';
10
+ GRANT ALL ON <%= database_name %>.* to '<%= @database_user %>'@'%';
11
+ CREATE DATABASE <%= database_name %>;
12
+ <% end %>
@@ -0,0 +1,2 @@
1
+ FROM <%= @project.system_prefix %>-app-dependencies
2
+ CMD bash
@@ -0,0 +1,25 @@
1
+ FROM nginx
2
+
3
+ RUN apt-get update
4
+ RUN apt-get upgrade -y
5
+ RUN apt-get install -y ruby
6
+
7
+ RUN mkdir -p /var/docker
8
+
9
+ COPY add_project.rb /var/docker/add_project.rb
10
+ COPY add_app.rb /var/docker/add_app.rb
11
+ COPY index.html.erb /var/docker/index.html.erb
12
+ COPY index_config.erb /var/docker/index_config.erb
13
+ COPY app_config.erb /var/docker/app_config.erb
14
+
15
+ <% @projects.each do |project| %>
16
+ <% app_list = project.apps.map(&:name).join(',') %>
17
+ RUN ruby /var/docker/add_project.rb <%= project.system_prefix %> <%= project.domain %> <%= app_list %>
18
+ <% project.apps.each do |app| %>
19
+ RUN ruby /var/docker/add_app.rb <%= project.system_prefix %> <%= project.domain %> <%= app.name %> <%= app.port %>
20
+ <% end %>
21
+ <% end %>
22
+
23
+ RUN rm -r /var/docker
24
+ RUN apt-get remove -y ruby
25
+ RUN apt-get autoremove -y