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