ruby_yacht 0.1.0
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.
- 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
|