ruby_yacht 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile.lock +1 -1
- data/doc/TODO.md +16 -6
- data/doc/configuration_sample.rb +8 -9
- data/lib/ruby_yacht/dsl/app.rb +29 -1
- data/lib/ruby_yacht/dsl/app_type.rb +112 -0
- data/lib/ruby_yacht/dsl/configuration.rb +163 -2
- data/lib/ruby_yacht/dsl/dsl.rb +51 -9
- data/lib/ruby_yacht/dsl/hook.rb +105 -0
- data/lib/ruby_yacht/dsl/project.rb +17 -21
- data/lib/ruby_yacht/dsl.rb +2 -0
- data/lib/ruby_yacht/images/app/Dockerfile.erb +20 -13
- data/lib/ruby_yacht/images/app/before_startup.bash.erb +8 -0
- data/lib/ruby_yacht/images/app/checkout.bash +6 -0
- data/lib/ruby_yacht/images/app/startup.bash.erb +5 -0
- data/lib/ruby_yacht/images/app-dependencies/Dockerfile.erb +23 -5
- data/lib/ruby_yacht/images/database/Dockerfile.erb +25 -11
- data/lib/ruby_yacht/images/database/checkout.bash +10 -0
- data/lib/ruby_yacht/images/database/setup.bash +15 -0
- data/lib/ruby_yacht/images/web/Dockerfile.erb +4 -3
- data/lib/ruby_yacht/plugins/rails/scripts/install_gems.rb +3 -0
- data/lib/ruby_yacht/plugins/rails/scripts/load_seeds.rb +34 -0
- data/lib/ruby_yacht/{images/app/startup.rb → plugins/rails/scripts/prepare_rails_for_launch.rb} +2 -8
- data/lib/ruby_yacht/{images/app/update_database_config.rb → plugins/rails/scripts/update_rails_config.rb} +0 -1
- data/lib/ruby_yacht/plugins/rails.rb +40 -0
- data/lib/ruby_yacht/plugins.rb +6 -0
- data/lib/ruby_yacht/runner/build_images.rb +72 -5
- data/lib/ruby_yacht/runner/checkout.rb +1 -1
- data/lib/ruby_yacht.rb +2 -1
- data/ruby_yacht.gemspec +2 -1
- data/spec/docker/Dockerfile +1 -1
- data/spec/dsl/app_spec.rb +34 -0
- data/spec/dsl/app_type_spec.rb +176 -0
- data/spec/dsl/configuration_spec.rb +161 -2
- data/spec/dsl/dsl_spec.rb +3 -3
- data/spec/dsl/hook_spec.rb +111 -0
- data/spec/dsl/project_spec.rb +19 -83
- data/spec/fixtures/app-dependencies-dockerfile-generic +21 -0
- data/spec/fixtures/app-dependencies-dockerfile-generic-with-library-install +28 -0
- data/spec/fixtures/app-dependencies-dockerfile-rails +32 -0
- data/spec/fixtures/database-dockerfile +16 -15
- data/spec/fixtures/database-dockerfile-rails +35 -0
- data/spec/fixtures/database-dockerfile-with-seed-hooks +34 -0
- data/spec/fixtures/hooks/hook1.rb +0 -0
- data/spec/fixtures/hooks/hook2.rb +0 -0
- data/spec/fixtures/mars-before-startup +4 -0
- data/spec/fixtures/mars-before-startup-rails +7 -0
- data/spec/fixtures/mars-before-startup-with-before-startup-hooks +7 -0
- data/spec/fixtures/mars-dockerfile +9 -14
- data/spec/fixtures/mars-dockerfile-rails +33 -0
- data/spec/fixtures/mars-dockerfile-with-after-checkout-hooks +30 -0
- data/spec/fixtures/mars-dockerfile-with-before-startup-hooks +29 -0
- data/spec/fixtures/mars-startup +3 -0
- data/spec/fixtures/mars-startup-rails +3 -0
- data/spec/fixtures/multi-project-web-dockerfile +0 -10
- data/spec/fixtures/web-dockerfile +0 -6
- data/spec/plugins/rails_spec.rb +198 -0
- data/spec/runner/build_images_spec.rb +181 -15
- data/spec/runner/checkout_spec.rb +2 -2
- data/spec/support/test_project.rb +16 -8
- metadata +62 -30
- data/lib/ruby_yacht/images/app/checkout.rb +0 -7
- data/lib/ruby_yacht/images/app-dependencies/install_gems.rb +0 -12
- data/lib/ruby_yacht/images/database/load_seeds.rb +0 -42
- data/lib/ruby_yacht/images/database/setup.rb +0 -19
- data/lib/ruby_yacht/images/database/setup_database.sql.erb +0 -12
- data/spec/fixtures/app-dependencies-dockerfile +0 -25
@@ -7,6 +7,8 @@ module RubyYacht
|
|
7
7
|
#
|
8
8
|
# A project is a family of apps that communicate with each other and
|
9
9
|
# share a database.
|
10
|
+
#
|
11
|
+
# You can configure this with RubyYacht::Project::DSL
|
10
12
|
class Project
|
11
13
|
# The name of the project.
|
12
14
|
attr_accessor :name
|
@@ -21,12 +23,6 @@ module RubyYacht
|
|
21
23
|
# The hostname for the repository that contains the code for the apps.
|
22
24
|
attr_accessor :repository
|
23
25
|
|
24
|
-
# The secret key that the apps should use for signing cookies.
|
25
|
-
attr_accessor :secret_key_base
|
26
|
-
|
27
|
-
# The environment that the apps should run in.
|
28
|
-
attr_accessor :rails_environment
|
29
|
-
|
30
26
|
# Whether we should check out the code on the host machine, rather than
|
31
27
|
# keeping it entirely inside the container.
|
32
28
|
attr_accessor :check_out_locally
|
@@ -59,6 +55,8 @@ module RubyYacht
|
|
59
55
|
# * *name: String* The name of the project
|
60
56
|
def initialize(name)
|
61
57
|
@name = name.to_sym
|
58
|
+
load_custom_attributes
|
59
|
+
load_app_initializers
|
62
60
|
end
|
63
61
|
|
64
62
|
add_attribute :name
|
@@ -75,27 +73,12 @@ module RubyYacht
|
|
75
73
|
# test.com
|
76
74
|
add_attribute :domain
|
77
75
|
|
78
|
-
##
|
79
|
-
# :method: secret_key_base
|
80
|
-
# You can call `secret_key_base '1234kj1234k;lj1234jklh'` to set the
|
81
|
-
# project's `secret_key_base` to `1234kj1234k;lj1234jklh`.
|
82
|
-
add_attribute :secret_key_base
|
83
|
-
|
84
76
|
##
|
85
77
|
# :method: repository
|
86
78
|
# You can call `repository 'github.com'` to set the project's `repository`
|
87
79
|
# to `github.com`
|
88
80
|
add_attribute :repository
|
89
81
|
|
90
|
-
##
|
91
|
-
# :method: rails_environment
|
92
|
-
#
|
93
|
-
# You can call `rails_environment 'staging'` to set the project's
|
94
|
-
# `rails_environment` to `staging`.
|
95
|
-
#
|
96
|
-
# The default is `development`.
|
97
|
-
add_attribute :rails_environment, 'development'
|
98
|
-
|
99
82
|
##
|
100
83
|
# :method: check_out_locally
|
101
84
|
#
|
@@ -139,6 +122,19 @@ module RubyYacht
|
|
139
122
|
add_object :dns_server, RubyYacht::DnsServer::DSL, required: false
|
140
123
|
|
141
124
|
creates_object Project
|
125
|
+
|
126
|
+
# This method loads the special DSL methods for defining apps of a certain
|
127
|
+
# type.
|
128
|
+
#
|
129
|
+
# For the app type with the name `foo`, this will create a `foo_app`
|
130
|
+
# method on the DSL that builds an app with the type `foo`.
|
131
|
+
def load_app_initializers
|
132
|
+
RubyYacht.configuration.app_types.each do |app_type|
|
133
|
+
define_singleton_method "#{app_type.name}_app" do |name, &block|
|
134
|
+
app name, app_type.name, &block
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
142
138
|
end
|
143
139
|
end
|
144
140
|
end
|
data/lib/ruby_yacht/dsl.rb
CHANGED
@@ -1,32 +1,39 @@
|
|
1
|
-
FROM <%= @project.system_prefix %>-app-dependencies
|
1
|
+
FROM <%= @project.system_prefix %>-<%= @app.app_type %>-app-dependencies
|
2
2
|
|
3
3
|
ENV DATABASE_HOST <%= @project.database.host %>
|
4
4
|
ENV DATABASE_NAME <%= @project.database.name %>
|
5
5
|
ENV DATABASE_PASSWORD <%= @project.database.password %>
|
6
6
|
ENV DATABASE_USERNAME <%= @project.database.username %>
|
7
|
-
ENV
|
8
|
-
ENV RAILS_PORT <%= @app.port %>
|
7
|
+
ENV APP_PORT <%= @app.port %>
|
9
8
|
ENV REPOSITORY_HOST <%= @project.repository %>
|
10
|
-
ENV SECRET_KEY_BASE <%= @project.secret_key_base %>
|
11
9
|
ENV SYSTEM_PREFIX <%= @project.system_prefix %>
|
10
|
+
<% app_type = RubyYacht.configuration.find_app_type(@app.app_type) %>
|
11
|
+
<% app_type.environment_variables.select { |variable| variable[:image] == :app }.each do |variable| %>
|
12
|
+
ENV <%= variable[:name] %> <%= instance_eval(&variable[:block]) %>
|
13
|
+
<% end %>
|
12
14
|
|
13
15
|
RUN rm -r /var/code
|
14
16
|
RUN mkdir -p /var/code
|
15
17
|
|
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
18
|
ENV REPOSITORY_NAME <%= @app.repository_name %>
|
19
|
+
COPY checkout.bash /var/docker/checkout.bash
|
20
|
+
RUN bash /var/docker/checkout.bash
|
21
|
+
|
22
|
+
COPY before_startup.bash /var/docker/before_startup.bash
|
23
|
+
COPY startup.bash /var/docker/startup.bash
|
24
|
+
<% RubyYacht.configuration.fetch_hooks(app_type: @app.app_type).select { |hook| hook.script_name != '' }.each do |hook| %>
|
25
|
+
<% next unless [:startup, :build_checkout].include?(hook.event_type) %>
|
26
|
+
COPY <%= hook.script_name %> /var/docker/<%= hook.script_name %>
|
27
|
+
<% end %>
|
23
28
|
|
24
|
-
RUN /var/docker
|
29
|
+
RUN chmod u+x /var/docker/*
|
25
30
|
|
26
31
|
WORKDIR /var/code
|
27
32
|
|
28
|
-
|
33
|
+
<% RubyYacht.configuration.fetch_hooks(app_type: @app.app_type, event_time: :after, event_type: :build_checkout).each do |hook| %>
|
34
|
+
RUN <%= hook.command %>
|
35
|
+
<% end %>
|
29
36
|
|
30
37
|
EXPOSE <%= @app.port %>
|
31
38
|
|
32
|
-
CMD /var/docker/startup.
|
39
|
+
CMD /var/docker/startup.bash
|
@@ -1,23 +1,41 @@
|
|
1
|
-
# This Dockerfile creates an image for installing all of the
|
1
|
+
# This Dockerfile creates an image for installing all of the dependencies
|
2
2
|
# for all of the apps.
|
3
3
|
#
|
4
4
|
# This is a slow process, so this should be kept as simple as possible so that
|
5
5
|
# it can remain unchanged.
|
6
6
|
|
7
|
-
FROM
|
7
|
+
FROM <%= @app_type.baseline_image %>
|
8
8
|
|
9
9
|
RUN mkdir -p /root/.ssh
|
10
10
|
COPY id_rsa /root/.ssh
|
11
11
|
RUN ssh-keyscan <%= @project.repository %> >> /root/.ssh/known_hosts
|
12
12
|
|
13
13
|
RUN mkdir -p /var/docker/
|
14
|
-
|
14
|
+
|
15
|
+
<% library_scripts = RubyYacht.configuration.fetch_hooks(app_type: @app_type.name, event_time: :during, event_type: :install_libraries).select { |hook| hook.script_name != '' } %>
|
16
|
+
<% library_scripts.each do |hook |%>
|
17
|
+
COPY <%= hook.script_name %> /var/docker/<%= hook.script_name %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<% if library_scripts.any? %>
|
21
|
+
RUN chmod u+x /var/docker/*
|
22
|
+
<% end %>
|
15
23
|
|
16
24
|
<% @project.apps.each do |app| %>
|
17
|
-
|
25
|
+
<% next unless app.app_type == @app_type.name %>
|
26
|
+
|
27
|
+
RUN git clone git@<%= @project.repository %>:<%= app.repository_name %> /var/code/<%= app.name %>
|
28
|
+
WORKDIR /var/code/<%= app.name %>
|
29
|
+
<% RubyYacht.configuration.fetch_hooks(app_type: @app_type.name, event_time: :during, event_type: :install_libraries).each do |hook |%>
|
30
|
+
RUN <%= hook.command %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<% if library_scripts.any? %>
|
35
|
+
RUN rm /var/docker/*
|
18
36
|
<% end %>
|
19
37
|
|
20
|
-
|
38
|
+
WORKDIR /
|
21
39
|
|
22
40
|
RUN apt-get update && apt-get upgrade -y
|
23
41
|
RUN apt-get install -y mysql-client
|
@@ -1,26 +1,40 @@
|
|
1
|
-
FROM <%= @project.system_prefix %>-app-dependencies
|
2
|
-
|
1
|
+
FROM <%= @project.system_prefix %>-<%= @app_type.name %>-app-dependencies
|
3
2
|
<% database = @project.database %>
|
4
3
|
|
5
4
|
ENV DEBIAN_FRONTEND noninteractive
|
6
5
|
RUN apt-get install -y mysql-server
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
ENV DATABASE_USERNAME <%= @project.database.username %>
|
8
|
+
ENV DATABASE_PASSWORD <%= @project.database.password %>
|
9
|
+
ENV DATABASE_NAME <%= @project.database.name %>
|
10
|
+
|
11
|
+
COPY setup.bash /var/docker/setup.bash
|
12
|
+
COPY checkout.bash /var/docker/checkout.bash
|
13
|
+
<% @project.apps.map(&:app_type).uniq.each do |app_type| %>
|
14
|
+
<% RubyYacht.configuration.fetch_hooks(app_type: app_type, event_type: :load_database_seeds).each do |hook| %>
|
15
|
+
COPY <%= hook.script_name %> /var/docker/<%= hook.script_name %>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
RUN chmod u+x /var/docker/*
|
11
20
|
|
12
|
-
RUN
|
21
|
+
RUN /var/docker/setup.bash <%= database.name %> <%= database.username %> <%= database.password %>
|
13
22
|
|
14
|
-
<% initialized = false %>
|
15
23
|
<% @project.apps.each do |app| %>
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
24
|
+
|
25
|
+
RUN /var/docker/checkout.bash <%= @project.repository %> <%= app.name %> <%= app.repository_name %>
|
26
|
+
WORKDIR /var/code/<%= app.name %>
|
27
|
+
<% @app_type = RubyYacht.configuration.find_app_type(app.app_type) %>
|
28
|
+
<%= include_event :load_database_seeds %>
|
20
29
|
<% end %>
|
30
|
+
|
21
31
|
RUN rm -r /var/docker
|
22
32
|
RUN rm -r /var/code
|
23
33
|
|
34
|
+
ENV DATABASE_USERNAME ''
|
35
|
+
ENV DATABASE_PASSWORD ''
|
36
|
+
ENV DATABASE_NAME ''
|
37
|
+
|
24
38
|
EXPOSE 3306
|
25
39
|
|
26
40
|
CMD mysqld_safe --bind-address=0.0.0.0
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#! /bin/bash
|
2
|
+
|
3
|
+
DATABASE_NAME=$1
|
4
|
+
DATABASE_USER=$2
|
5
|
+
DATABASE_PASSWORD=$3
|
6
|
+
|
7
|
+
service mysql start;
|
8
|
+
COMMAND="CREATE USER '$DATABASE_USER'@'localhost' IDENTIFIED BY '$DATABASE_PASSWORD';";
|
9
|
+
COMMAND="$COMMAND CREATE USER '$DATABASE_USER'@'%' IDENTIFIED BY '$DATABASE_PASSWORD';";
|
10
|
+
|
11
|
+
COMMAND="$COMMAND GRANT ALL ON $DATABASE_NAME.* to '$DATABASE_USER'@'localhost';";
|
12
|
+
COMMAND="$COMMAND GRANT ALL ON $DATABASE_NAME.* to '$DATABASE_USER'@'%';";
|
13
|
+
COMMAND="$COMMAND CREATE DATABASE $DATABASE_NAME;";
|
14
|
+
|
15
|
+
mysql -uroot -e "$COMMAND";
|
@@ -13,11 +13,12 @@ COPY index_config.erb /var/docker/index_config.erb
|
|
13
13
|
COPY app_config.erb /var/docker/app_config.erb
|
14
14
|
|
15
15
|
<% @projects.each do |project| %>
|
16
|
-
|
16
|
+
|
17
|
+
<% app_list = project.apps.map(&:name).join(',') %>
|
17
18
|
RUN ruby /var/docker/add_project.rb <%= project.system_prefix %> <%= project.domain %> <%= app_list %>
|
18
|
-
|
19
|
+
<% project.apps.each do |app| %>
|
19
20
|
RUN ruby /var/docker/add_app.rb <%= project.system_prefix %> <%= project.domain %> <%= app.name %> <%= app.port %>
|
20
|
-
|
21
|
+
<% end %>
|
21
22
|
<% end %>
|
22
23
|
|
23
24
|
RUN rm -r /var/docker
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#! /usr/local/bin/ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
puts "Loading seeds"
|
7
|
+
|
8
|
+
system "service mysql start"
|
9
|
+
|
10
|
+
config_path = "./config/database.yml"
|
11
|
+
|
12
|
+
database_config = {
|
13
|
+
'development' => {
|
14
|
+
'adapter' => 'mysql2',
|
15
|
+
'encoding' => 'utf8',
|
16
|
+
'reconnect' => true,
|
17
|
+
'username' => ENV['DATABASE_USERNAME'],
|
18
|
+
'password' => ENV['DATABASE_PASSWORD'],
|
19
|
+
'host' => 'localhost',
|
20
|
+
'database' => ENV['DATABASE_NAME']
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
File.open(config_path, "w") do |file|
|
25
|
+
file.write(database_config.to_yaml)
|
26
|
+
end
|
27
|
+
|
28
|
+
system "bundle install"
|
29
|
+
tables = `mysql -uroot -e "SHOW TABLES" #{ENV['DATABASE_NAME']}`
|
30
|
+
if tables == ''
|
31
|
+
system "bundle exec rake db:reset"
|
32
|
+
else
|
33
|
+
system "bundle exec rake db:migrate; bundle exec rake db:seed"
|
34
|
+
end
|
data/lib/ruby_yacht/{images/app/startup.rb → plugins/rails/scripts/prepare_rails_for_launch.rb}
RENAMED
@@ -1,17 +1,11 @@
|
|
1
1
|
#! /usr/local/bin/ruby
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
|
-
require_relative 'checkout'
|
5
|
-
require_relative 'update_database_config'
|
6
|
-
|
7
|
-
FileUtils.cd '/var/code'
|
8
4
|
|
9
5
|
system "bundle install"
|
10
6
|
system "rake db:migrate"
|
11
|
-
|
12
7
|
system "rails r Rails.cache.clear"
|
8
|
+
|
13
9
|
if ENV['RAILS_ENV'] != 'development'
|
14
10
|
system "rake assets:precompile"
|
15
|
-
end
|
16
|
-
|
17
|
-
exec "rails s -b 0.0.0.0 -p $RAILS_PORT -e $RAILS_ENV"
|
11
|
+
end
|
@@ -23,7 +23,6 @@ database_config = {
|
|
23
23
|
if ENV['RAILS_ENV'] == 'development' && local_database
|
24
24
|
database_config['test'] = common_config.dup
|
25
25
|
database_config['test']['database'] += '_test'
|
26
|
-
database_config['development']['database'] += '_development'
|
27
26
|
end
|
28
27
|
|
29
28
|
File.open('/var/code/config/database.yml', 'w') do |file|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RubyYacht::Plugins
|
2
|
+
# This module provides the plugin for managing Ruby on Rails apps.
|
3
|
+
module Rails
|
4
|
+
# This method loads the configuration for the Rails plugin.
|
5
|
+
def self.load
|
6
|
+
RubyYacht.configure do
|
7
|
+
app_type :rails do
|
8
|
+
baseline_image 'ruby:2.3'
|
9
|
+
project_attribute name: :environment, default: 'development'
|
10
|
+
project_attribute name: :secret_key_base
|
11
|
+
|
12
|
+
environment_variable :app, 'RAILS_ENV' do
|
13
|
+
@project.rails_environment
|
14
|
+
end
|
15
|
+
|
16
|
+
environment_variable :app, 'SECRET_KEY_BASE' do
|
17
|
+
@project.rails_secret_key_base
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
RubyYacht.configure do
|
23
|
+
add_hooks(app_type: :rails, folder: File.join(File.dirname(__FILE__), 'rails', 'scripts')) do
|
24
|
+
during(:install_libraries) { run_script 'install_gems.rb' }
|
25
|
+
|
26
|
+
after(:build_checkout) { command 'bundle install && bundle clean --force' }
|
27
|
+
|
28
|
+
during(:load_database_seeds) { run_script 'load_seeds.rb' }
|
29
|
+
|
30
|
+
before(:startup) { run_script 'update_rails_config.rb' }
|
31
|
+
before(:startup) { run_script 'prepare_rails_for_launch.rb' }
|
32
|
+
|
33
|
+
during(:startup) { command 'rails s -b 0.0.0.0 -p $APP_PORT -e $RAILS_ENV' }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
RubyYacht::Plugins::Rails.load
|
@@ -28,13 +28,19 @@ module RubyYacht::Runner
|
|
28
28
|
FileUtils.cp(id_path, tmp_id_path)
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
project.apps.map(&:app_type).uniq.each do |type_name|
|
32
|
+
@app_type = RubyYacht.configuration.find_app_type(type_name)
|
33
|
+
build_image 'app-dependencies', "#{@project.system_prefix}-#{@app_type.name}-app-dependencies"
|
34
|
+
end
|
35
|
+
|
32
36
|
build_image 'database' if project.database.local?
|
33
37
|
|
34
38
|
@project.apps.each do |app|
|
35
39
|
@app = app
|
40
|
+
@app_type = RubyYacht.configuration.find_app_type(@app.app_type)
|
36
41
|
build_image 'app', "#{@project.system_prefix}-#{app.name}"
|
37
42
|
end
|
43
|
+
@app = nil
|
38
44
|
|
39
45
|
if @project.create_deploy_container
|
40
46
|
build_image 'deploy'
|
@@ -55,6 +61,10 @@ module RubyYacht::Runner
|
|
55
61
|
# current context, and write it to the Dockerfile in the tmp folder. It will
|
56
62
|
# then build the image, and clear out the tmp folder.
|
57
63
|
#
|
64
|
+
# Depending on the image type, it may also copy and interpret other template
|
65
|
+
# files. For instance, for app containers we also have erb files for the
|
66
|
+
# `startup.bash` and `before_startup.bash` scripts.
|
67
|
+
#
|
58
68
|
# ### Parameters
|
59
69
|
#
|
60
70
|
# * **folder_name: String** The name of the folder containing the
|
@@ -65,12 +75,46 @@ module RubyYacht::Runner
|
|
65
75
|
# dash, followed by the folder name.
|
66
76
|
def build_image(folder_name, image_name = nil)
|
67
77
|
Dir[File.join(File.dirname(File.dirname(__FILE__)), 'images', folder_name, '*')].each do |path|
|
68
|
-
FileUtils.cp(path, 'tmp')
|
78
|
+
FileUtils.cp(path, File.join('tmp', File.basename(path)))
|
69
79
|
end
|
80
|
+
|
81
|
+
templates =
|
82
|
+
case folder_name
|
83
|
+
when 'app' then ['Dockerfile', 'before_startup.bash', 'startup.bash']
|
84
|
+
else ['Dockerfile']
|
85
|
+
end
|
86
|
+
|
87
|
+
hook_events =
|
88
|
+
case folder_name
|
89
|
+
when 'app' then [:startup, :build_checkout]
|
90
|
+
when 'app-dependencies' then [:install_libraries]
|
91
|
+
when 'database' then [:load_database_seeds]
|
92
|
+
else []
|
93
|
+
end
|
94
|
+
|
95
|
+
app_types =
|
96
|
+
case folder_name
|
97
|
+
when 'database' then @project.apps.map(&:app_type).uniq
|
98
|
+
else [@app_type.name]
|
99
|
+
end
|
70
100
|
|
71
|
-
|
72
|
-
|
73
|
-
|
101
|
+
hook_events.each do |event|
|
102
|
+
app_types.each do |app_type|
|
103
|
+
RubyYacht.configuration.fetch_hooks(app_type: app_type, event_type: event).each do |hook|
|
104
|
+
next unless hook.script_path
|
105
|
+
FileUtils.cp hook.script_path, "tmp"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
templates.each do |template_name|
|
111
|
+
File.open(File.join('tmp', template_name), 'w') do |file|
|
112
|
+
template_contents = File.read(File.join('tmp', template_name + '.erb'))
|
113
|
+
file_contents = ERB.new(template_contents, nil, '<>').result(binding)
|
114
|
+
file_contents.gsub!(/\n\n\n+/, "\n\n")
|
115
|
+
file_contents.gsub!(/\n*\Z/, "")
|
116
|
+
file.write(file_contents)
|
117
|
+
end
|
74
118
|
end
|
75
119
|
|
76
120
|
image_name ||= "#{@project.system_prefix}-#{folder_name}"
|
@@ -78,5 +122,28 @@ module RubyYacht::Runner
|
|
78
122
|
|
79
123
|
FileUtils.rm(Dir[File.join("tmp", "*")])
|
80
124
|
end
|
125
|
+
|
126
|
+
# This method includes the hooks for an event in a Dockerfile.
|
127
|
+
#
|
128
|
+
# It will run the commands for the before hooks, then the during hooks, then
|
129
|
+
# the after hooks.
|
130
|
+
#
|
131
|
+
# ### Parameters
|
132
|
+
#
|
133
|
+
# * **event_type: Symbol** The event whose hooks we are running.
|
134
|
+
#
|
135
|
+
# ### Returns
|
136
|
+
#
|
137
|
+
# A String with the contents of the Dockerfile for running the hooks.
|
138
|
+
def include_event(event_type)
|
139
|
+
result = ""
|
140
|
+
[:before, :during, :after].each do |time|
|
141
|
+
before_hooks = RubyYacht.configuration.fetch_hooks(app_type: @app_type.name, event_type: event_type, event_time: time).each do |hook|
|
142
|
+
result += "RUN #{hook.command}\n"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
result
|
147
|
+
end
|
81
148
|
end
|
82
149
|
end
|
@@ -59,7 +59,7 @@ module RubyYacht::Runner
|
|
59
59
|
container_name = "#{project.system_prefix}-#{app}"
|
60
60
|
|
61
61
|
docker "exec #{container_name} bash -c 'cd /var/code; git fetch; git checkout .; git checkout #{branch}; git pull'"
|
62
|
-
docker "exec #{container_name}
|
62
|
+
docker "exec #{container_name} /var/docker/before_startup.bash"
|
63
63
|
docker "restart #{container_name}"
|
64
64
|
|
65
65
|
true
|
data/lib/ruby_yacht.rb
CHANGED
data/ruby_yacht.gemspec
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = 'ruby_yacht'
|
3
|
-
spec.version = '0.
|
3
|
+
spec.version = '0.2.0'
|
4
4
|
spec.date = '2016-04-17'
|
5
|
+
spec.description = "A DSL for building docker containers for a family of Rails apps"
|
5
6
|
spec.summary = "A DSL for building docker containers for a family of Rails apps"
|
6
7
|
spec.authors = ["John Brownlee"]
|
7
8
|
spec.email = 'apps@mail.johnbrownlee.com'
|
data/spec/docker/Dockerfile
CHANGED
data/spec/dsl/app_spec.rb
CHANGED
@@ -5,28 +5,62 @@ RSpec.describe RubyYacht::App do
|
|
5
5
|
let(:name) { :test_app }
|
6
6
|
let(:app) { RubyYacht::App::DSL.new(name).run(@builder).create_object }
|
7
7
|
|
8
|
+
before do
|
9
|
+
RubyYacht.configuration.clear
|
10
|
+
RubyYacht.configure do
|
11
|
+
app_type :test do
|
12
|
+
baseline_image 'ubuntu'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
8
17
|
it "creates an app with all fields" do
|
9
18
|
@builder = Proc.new do
|
10
19
|
repository_name 'brownleej/test-app'
|
20
|
+
app_type :test
|
11
21
|
port 3000
|
12
22
|
end
|
13
23
|
expect(app.name).to eq :test_app
|
14
24
|
expect(app.repository_name).to eq 'brownleej/test-app'
|
25
|
+
expect(app.app_type).to eq :test
|
15
26
|
expect(app.port).to eq 3000
|
16
27
|
end
|
17
28
|
|
18
29
|
it "requires the repository name" do
|
19
30
|
@builder = Proc.new do
|
20
31
|
port 3000
|
32
|
+
app_type :test
|
21
33
|
end
|
22
34
|
expect do
|
23
35
|
self.app
|
24
36
|
end.to raise_exception("Missing required attribute repository_name for RubyYacht::App::DSL")
|
25
37
|
end
|
26
38
|
|
39
|
+
it "requires the app type" do
|
40
|
+
@builder = Proc.new do
|
41
|
+
repository_name 'brownleej/test-app'
|
42
|
+
port 3000
|
43
|
+
end
|
44
|
+
expect do
|
45
|
+
self.app
|
46
|
+
end.to raise_exception("Missing required attribute app_type for RubyYacht::App::DSL")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "requires a defined app type" do
|
50
|
+
@builder = Proc.new do
|
51
|
+
app_type :invalid
|
52
|
+
repository_name 'brownleej/test-app'
|
53
|
+
port 3000
|
54
|
+
end
|
55
|
+
expect do
|
56
|
+
self.app
|
57
|
+
end.to raise_exception("App has invalid app type `invalid`")
|
58
|
+
end
|
59
|
+
|
27
60
|
it "defaults the port to 8080" do
|
28
61
|
@builder = Proc.new do
|
29
62
|
repository_name 'brownleej/test-app'
|
63
|
+
app_type :test
|
30
64
|
end
|
31
65
|
expect(app.port).to eq 8080
|
32
66
|
end
|