ruby_yacht 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +27 -0
- data/.gitignore +4 -0
- data/.rdoc_options +29 -0
- data/.rspec +1 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +44 -0
- data/LICENSE +8 -0
- data/README.md +216 -0
- data/doc/CONTRIBUTING.md +12 -0
- data/doc/TODO.md +28 -0
- data/doc/configuration_sample.rb +87 -0
- data/lib/ruby_yacht/dsl/app.rb +59 -0
- data/lib/ruby_yacht/dsl/configuration.rb +55 -0
- data/lib/ruby_yacht/dsl/database.rb +57 -0
- data/lib/ruby_yacht/dsl/dns_server.rb +38 -0
- data/lib/ruby_yacht/dsl/dsl.rb +252 -0
- data/lib/ruby_yacht/dsl/project.rb +140 -0
- data/lib/ruby_yacht/dsl.rb +6 -0
- data/lib/ruby_yacht/images/app/Dockerfile.erb +32 -0
- data/lib/ruby_yacht/images/app/checkout.rb +7 -0
- data/lib/ruby_yacht/images/app/startup.rb +17 -0
- data/lib/ruby_yacht/images/app/update_database_config.rb +45 -0
- data/lib/ruby_yacht/images/app-dependencies/Dockerfile.erb +23 -0
- data/lib/ruby_yacht/images/app-dependencies/install_gems.rb +12 -0
- data/lib/ruby_yacht/images/database/Dockerfile.erb +26 -0
- data/lib/ruby_yacht/images/database/load_seeds.rb +42 -0
- data/lib/ruby_yacht/images/database/setup.rb +19 -0
- data/lib/ruby_yacht/images/database/setup_database.sql.erb +12 -0
- data/lib/ruby_yacht/images/deploy/Dockerfile.erb +2 -0
- data/lib/ruby_yacht/images/web/Dockerfile.erb +25 -0
- data/lib/ruby_yacht/images/web/add_app.rb +12 -0
- data/lib/ruby_yacht/images/web/add_project.rb +14 -0
- data/lib/ruby_yacht/images/web/app_config.erb +11 -0
- data/lib/ruby_yacht/images/web/index.html.erb +10 -0
- data/lib/ruby_yacht/images/web/index_config.erb +12 -0
- data/lib/ruby_yacht/images/web/setup.rb +22 -0
- data/lib/ruby_yacht/runner/build.rb +21 -0
- data/lib/ruby_yacht/runner/build_images.rb +82 -0
- data/lib/ruby_yacht/runner/checkout.rb +68 -0
- data/lib/ruby_yacht/runner/command.rb +161 -0
- data/lib/ruby_yacht/runner/help.rb +55 -0
- data/lib/ruby_yacht/runner/implode.rb +33 -0
- data/lib/ruby_yacht/runner/run_containers.rb +105 -0
- data/lib/ruby_yacht/runner/runner.rb +42 -0
- data/lib/ruby_yacht/runner/services.rb +79 -0
- data/lib/ruby_yacht/runner/shell.rb +66 -0
- data/lib/ruby_yacht/runner/update_hosts.rb +72 -0
- data/lib/ruby_yacht/runner.rb +18 -0
- data/lib/ruby_yacht.rb +6 -0
- data/ruby_yacht.gemspec +18 -0
- data/spec/docker/Dockerfile +5 -0
- data/spec/docker/build.bash +10 -0
- data/spec/dsl/app_spec.rb +47 -0
- data/spec/dsl/configuration_spec.rb +64 -0
- data/spec/dsl/database_spec.rb +75 -0
- data/spec/dsl/dns_server_spec.rb +25 -0
- data/spec/dsl/dsl_spec.rb +298 -0
- data/spec/dsl/project_spec.rb +266 -0
- data/spec/fixtures/app-dependencies-dockerfile +25 -0
- data/spec/fixtures/database-dockerfile +31 -0
- data/spec/fixtures/deploy-dockerfile +2 -0
- data/spec/fixtures/mars-dockerfile +32 -0
- data/spec/fixtures/multi-project-web-dockerfile +35 -0
- data/spec/fixtures/web-dockerfile +27 -0
- data/spec/runner/build_images_spec.rb +164 -0
- data/spec/runner/build_spec.rb +86 -0
- data/spec/runner/checkout_spec.rb +128 -0
- data/spec/runner/command_spec.rb +94 -0
- data/spec/runner/help_spec.rb +73 -0
- data/spec/runner/implode_spec.rb +62 -0
- data/spec/runner/run_containers_spec.rb +141 -0
- data/spec/runner/runner_spec.rb +117 -0
- data/spec/runner/services_spec.rb +135 -0
- data/spec/runner/shell_spec.rb +123 -0
- data/spec/runner/update_hosts_spec.rb +163 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/docker_stubbing.rb +93 -0
- data/spec/support/test_project.rb +56 -0
- 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,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,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,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
|