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,12 @@
|
|
1
|
+
#! /usr/local/bin/ruby
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
@project = ARGV.shift
|
5
|
+
@domain = ARGV.shift
|
6
|
+
@app = ARGV.shift
|
7
|
+
@port = ARGV.shift
|
8
|
+
@container_name = "#{@project}-#{@app}"
|
9
|
+
|
10
|
+
File.open(File.join("/etc/nginx/conf.d/#{@container_name}.conf"), 'w') do |file|
|
11
|
+
file.write(ERB.new(File.read('/var/docker/app_config.erb')).result(binding))
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#! /usr/local/bin/ruby
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
@project = ARGV.shift
|
5
|
+
@domain = ARGV.shift
|
6
|
+
@app_names = ARGV.shift.split(',')
|
7
|
+
|
8
|
+
File.open(File.join("/usr/share/nginx/html/#{@project}.html"), 'w') do |file|
|
9
|
+
file.write(ERB.new(File.read('/var/docker/index.html.erb')).result(binding))
|
10
|
+
end
|
11
|
+
|
12
|
+
File.open(File.join("/etc/nginx/conf.d/#{@project}-index.conf"), 'w') do |file|
|
13
|
+
file.write(ERB.new(File.read('/var/docker/index_config.erb')).result(binding))
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
server {
|
2
|
+
listen 80;
|
3
|
+
server_name <%= @app %>.<%= @domain %>;
|
4
|
+
|
5
|
+
location / {
|
6
|
+
proxy_pass http://<%= @container_name %>:<%= @port %>;
|
7
|
+
proxy_redirect off;
|
8
|
+
proxy_set_header Host $host;
|
9
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
10
|
+
}
|
11
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#! /usr/local/bin/ruby
|
2
|
+
require 'erb'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
@project = ARGV.shift
|
6
|
+
@domain = ARGV.shift
|
7
|
+
@app_names = ARGV.shift.split(',')
|
8
|
+
@app_ports = ARGV.shift.split(',')
|
9
|
+
|
10
|
+
File.open(File.join("/usr/share/nginx/html/#{@project}.html"), 'w') do |file|
|
11
|
+
file.write(ERB.new(File.read('/var/docker/index.html.erb')).result(binding))
|
12
|
+
end
|
13
|
+
|
14
|
+
File.open(File.join("/etc/nginx/conf.d/#{@project}.conf"), 'w') do |file|
|
15
|
+
file.write(ERB.new(File.read('/var/docker/index_config.erb')).result(binding))
|
16
|
+
@app_names.each_with_index do |app, port|
|
17
|
+
@app = app
|
18
|
+
@app_port = port
|
19
|
+
@container_name = @project + '-' + @app
|
20
|
+
file.write(ERB.new(File.read('/var/docker/app_config.erb')).result(binding))
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RubyYacht::Runner
|
2
|
+
# This class provides a command for building the system.
|
3
|
+
#
|
4
|
+
# It will build the images, run the containers, and update the hosts file.
|
5
|
+
class Build < Command
|
6
|
+
# The identifier for the command.
|
7
|
+
def self.command; 'build'; end
|
8
|
+
|
9
|
+
# The description for the command.
|
10
|
+
def self.description
|
11
|
+
"Build images and run containers"
|
12
|
+
end
|
13
|
+
|
14
|
+
# This method runs the logic for this command.
|
15
|
+
def run
|
16
|
+
return BuildImages.new.run &&
|
17
|
+
RunContainers.new.run &&
|
18
|
+
UpdateHosts.new.run
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module RubyYacht::Runner
|
4
|
+
# This command builds the images for the system.
|
5
|
+
class BuildImages < Command
|
6
|
+
# The identifier for the command.
|
7
|
+
def self.command; 'build_images'; end
|
8
|
+
|
9
|
+
# The description for the command.
|
10
|
+
def self.description
|
11
|
+
"Build images for your environment"
|
12
|
+
end
|
13
|
+
|
14
|
+
# This method runs the logic for the command.
|
15
|
+
def run
|
16
|
+
FileUtils.mkdir_p 'tmp'
|
17
|
+
|
18
|
+
default_system_prefix = projects.first.system_prefix
|
19
|
+
docker "network create #{default_system_prefix} 2> /dev/null"
|
20
|
+
|
21
|
+
projects.each do |project|
|
22
|
+
log "Building images for #{project.name}"
|
23
|
+
@project = project
|
24
|
+
|
25
|
+
id_path = File.join(ENV['HOME'], '.ssh', 'id_rsa')
|
26
|
+
tmp_id_path = File.join('tmp', 'id_rsa')
|
27
|
+
if File.exist?(id_path)
|
28
|
+
FileUtils.cp(id_path, tmp_id_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
build_image 'app-dependencies'
|
32
|
+
build_image 'database' if project.database.local?
|
33
|
+
|
34
|
+
@project.apps.each do |app|
|
35
|
+
@app = app
|
36
|
+
build_image 'app', "#{@project.system_prefix}-#{app.name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
if @project.create_deploy_container
|
40
|
+
build_image 'deploy'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
@projects = projects
|
45
|
+
build_image 'web', "#{default_system_prefix}-web"
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
# This method builds an image.
|
51
|
+
#
|
52
|
+
# This will copy a Dockerfile template from a folder underneath the `images`
|
53
|
+
# folder, as well as any other files in that folder, into the tmp folder.
|
54
|
+
# It will then evaluate the Dockerfile.erb file, using the binding from the
|
55
|
+
# current context, and write it to the Dockerfile in the tmp folder. It will
|
56
|
+
# then build the image, and clear out the tmp folder.
|
57
|
+
#
|
58
|
+
# ### Parameters
|
59
|
+
#
|
60
|
+
# * **folder_name: String** The name of the folder containing the
|
61
|
+
# Dockerfile and related files.
|
62
|
+
# * **image_name: String** The name for the new image. If this is not
|
63
|
+
# provided, the image name will be the
|
64
|
+
# current project's prefix, followed by a
|
65
|
+
# dash, followed by the folder name.
|
66
|
+
def build_image(folder_name, image_name = nil)
|
67
|
+
Dir[File.join(File.dirname(File.dirname(__FILE__)), 'images', folder_name, '*')].each do |path|
|
68
|
+
FileUtils.cp(path, 'tmp')
|
69
|
+
end
|
70
|
+
|
71
|
+
File.open(File.join('tmp', 'Dockerfile'), 'w') do |file|
|
72
|
+
contents = ERB.new(File.read(File.join('tmp', 'Dockerfile.erb'))).result(binding)
|
73
|
+
file.write(contents)
|
74
|
+
end
|
75
|
+
|
76
|
+
image_name ||= "#{@project.system_prefix}-#{folder_name}"
|
77
|
+
docker "build -t #{image_name} tmp"
|
78
|
+
|
79
|
+
FileUtils.rm(Dir[File.join("tmp", "*")])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module RubyYacht::Runner
|
2
|
+
# This class provides a command for checking out a new branch for an app.
|
3
|
+
class Checkout < Command
|
4
|
+
# The name of the command.
|
5
|
+
def self.command; 'checkout'; end
|
6
|
+
|
7
|
+
# The short description for the command.
|
8
|
+
def self.description
|
9
|
+
"Check out a new branch for an app"
|
10
|
+
end
|
11
|
+
|
12
|
+
# The name of the project that the app is in.
|
13
|
+
attr_accessor :project_name
|
14
|
+
|
15
|
+
# The name of the app.
|
16
|
+
attr_accessor :app
|
17
|
+
|
18
|
+
# The branch that we are checking out.
|
19
|
+
attr_accessor :branch
|
20
|
+
|
21
|
+
# This OptionParser for parsing command-line flags.
|
22
|
+
#
|
23
|
+
# This command accepts the project name as an optional flag.
|
24
|
+
def option_parser
|
25
|
+
OptionParser.new do |options|
|
26
|
+
options.banner = "Usage: #{Command.short_script_name} checkout [options] [APP] [BRANCH]"
|
27
|
+
options.separator "Options:"
|
28
|
+
|
29
|
+
options.on('-p', '--project PROJECT', "The project with the app we are checking out the branch in. Default: #{default_project.name}") do |name|
|
30
|
+
self.project_name = name.to_sym
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# This method extracts the positional arguments from the command line.
|
36
|
+
#
|
37
|
+
# This will take the app name and branch from the command line.
|
38
|
+
def parse_positional_arguments(arguments)
|
39
|
+
self.app = arguments.shift
|
40
|
+
self.branch = arguments.shift
|
41
|
+
end
|
42
|
+
|
43
|
+
# This method runs the logic for the command.
|
44
|
+
def run
|
45
|
+
if app.nil?
|
46
|
+
log "You must provide an app name"
|
47
|
+
log "Run #{Command.short_script_name} help checkout for more information"
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
if branch.nil?
|
51
|
+
log "You must provide a branch"
|
52
|
+
log "Run #{Command.short_script_name} help checkout for more information"
|
53
|
+
return false
|
54
|
+
end
|
55
|
+
|
56
|
+
project = self.project_named(self.project_name)
|
57
|
+
return false unless project
|
58
|
+
|
59
|
+
container_name = "#{project.system_prefix}-#{app}"
|
60
|
+
|
61
|
+
docker "exec #{container_name} bash -c 'cd /var/code; git fetch; git checkout .; git checkout #{branch}; git pull'"
|
62
|
+
docker "exec #{container_name} bash -c '/var/docker/update_database_config.rb; rake db:migrate'"
|
63
|
+
docker "restart #{container_name}"
|
64
|
+
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module RubyYacht::Runner
|
4
|
+
# This class is the base class for the commands that users can run for
|
5
|
+
# managing their system.
|
6
|
+
class Command
|
7
|
+
# Command information
|
8
|
+
|
9
|
+
# The name of the command that users run to trigger this command.
|
10
|
+
# This implementation raises an error. Subclasses must implement it to
|
11
|
+
# provide the command name.
|
12
|
+
def self.command
|
13
|
+
raise "Command not defined for #{self}"
|
14
|
+
end
|
15
|
+
|
16
|
+
# This class gets a short description of the command.
|
17
|
+
# This implementation raises an error. Subclasses must implement it to
|
18
|
+
# provide the command description.
|
19
|
+
def self.description
|
20
|
+
raise "Description not defined for #{self}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# This method gets the command-line options for invoking this script.
|
24
|
+
#
|
25
|
+
# This must return an OptionParser.
|
26
|
+
#
|
27
|
+
# The default implementation returns an OptionParser with the command name
|
28
|
+
# and description. Subclasses should implement this if they want to accept
|
29
|
+
# other command-line options.
|
30
|
+
def option_parser
|
31
|
+
OptionParser.new do |options|
|
32
|
+
options.banner = "Usage: #{Command.short_script_name} #{self.class.command}\n\n#{self.class.description}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# This method extracts the positional arguments from the command line.
|
37
|
+
#
|
38
|
+
# This will be called after all the flags have been consumed by the
|
39
|
+
# OptionParser.
|
40
|
+
#
|
41
|
+
# The default implementation does nothing. Subclasses should implement this
|
42
|
+
# if they want to extract arguments from the command line.
|
43
|
+
#
|
44
|
+
# ### Parameters
|
45
|
+
#
|
46
|
+
# * **arguments: Array** The remaining arguments from the command line.
|
47
|
+
def parse_positional_arguments(arguments)
|
48
|
+
end
|
49
|
+
|
50
|
+
# This method runs the logic for the command.
|
51
|
+
#
|
52
|
+
# The default implementation raises an exception. Subclasses must implement
|
53
|
+
# this with their command-specific logic.
|
54
|
+
#
|
55
|
+
# ### Returns
|
56
|
+
#
|
57
|
+
# This must return a Boolean indicating whether the command succeeded or
|
58
|
+
# not.
|
59
|
+
def run
|
60
|
+
raise "Run method not defined for #{self}"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Helpers
|
64
|
+
|
65
|
+
# This method gets the name of the script that was invoked to run the
|
66
|
+
# commands.
|
67
|
+
#
|
68
|
+
# This will just be the filename of the script.
|
69
|
+
def self.short_script_name
|
70
|
+
return File.basename($0)
|
71
|
+
end
|
72
|
+
|
73
|
+
# This method gets the projects that have been configured.
|
74
|
+
def projects
|
75
|
+
RubyYacht.configuration.projects
|
76
|
+
end
|
77
|
+
|
78
|
+
# The project that we will use if they do not provide one from the command
|
79
|
+
# line.
|
80
|
+
def default_project
|
81
|
+
projects.first
|
82
|
+
end
|
83
|
+
|
84
|
+
# This method finds a project by name.
|
85
|
+
#
|
86
|
+
# If the name is nil, this will use the default project. If the name is
|
87
|
+
# provided, but does not match any project, this will log an error and
|
88
|
+
# return nil.
|
89
|
+
#
|
90
|
+
# ### Parameters
|
91
|
+
#
|
92
|
+
# * **name: Symbol** The name of the project.
|
93
|
+
def project_named(name)
|
94
|
+
if self.project_name
|
95
|
+
project = projects.find { |p| p.name == name }
|
96
|
+
unless project
|
97
|
+
log "There is no project named #{name}"
|
98
|
+
end
|
99
|
+
project
|
100
|
+
else
|
101
|
+
self.default_project
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# This method gets a property from the default docker machine.
|
106
|
+
#
|
107
|
+
# ### Parameters
|
108
|
+
#
|
109
|
+
# * **property: String** The docker machine property to fetch.
|
110
|
+
#
|
111
|
+
# ### Returns
|
112
|
+
# The response from docker-machine.
|
113
|
+
def get_machine_info(property)
|
114
|
+
backtick("docker-machine inspect default -f {{#{property}}}").strip
|
115
|
+
end
|
116
|
+
|
117
|
+
# Stubbing
|
118
|
+
|
119
|
+
# This method logs a message to standard out. It allows us to stub out and
|
120
|
+
# test the logging behavior of the commands.
|
121
|
+
def log(message)
|
122
|
+
$stdout.puts message
|
123
|
+
end
|
124
|
+
|
125
|
+
# This method sends a command to docker.
|
126
|
+
#
|
127
|
+
# This should start with exec, run, build, etc.
|
128
|
+
#
|
129
|
+
# This allows us to stub out and test the docker commands that get sent.
|
130
|
+
#
|
131
|
+
# ### Parameters
|
132
|
+
# * **command: String** The command to execute.
|
133
|
+
def docker(command)
|
134
|
+
system "docker #{command}"
|
135
|
+
end
|
136
|
+
|
137
|
+
# This method sends a command to the system.
|
138
|
+
#
|
139
|
+
# This is a proxy for Kernel.system that allows us to stub out and test the
|
140
|
+
# system interaction.
|
141
|
+
#
|
142
|
+
# ### Parameters
|
143
|
+
# * **command: String** The command to execute.
|
144
|
+
def system(command)
|
145
|
+
Kernel.system(command)
|
146
|
+
end
|
147
|
+
|
148
|
+
# This method runs a command using the backtick operator.
|
149
|
+
#
|
150
|
+
# This allows us to stub and and test the system interaction.
|
151
|
+
#
|
152
|
+
# ### Parameters
|
153
|
+
# * **command: String** The command to execute.
|
154
|
+
#
|
155
|
+
# ### Returns
|
156
|
+
# This returns the output from the command.
|
157
|
+
def backtick(command)
|
158
|
+
`#{command}`
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module RubyYacht::Runner
|
2
|
+
# This command provides help information about other commands.
|
3
|
+
class Help < Command
|
4
|
+
# The name of the command.
|
5
|
+
def self.command; 'help'; end
|
6
|
+
|
7
|
+
# The short description of the command.
|
8
|
+
def self.description
|
9
|
+
"Get information on available commands"
|
10
|
+
end
|
11
|
+
|
12
|
+
# The command that we are getting help in.
|
13
|
+
attr_accessor :command
|
14
|
+
|
15
|
+
# This method gets the command-line options for the command.
|
16
|
+
def option_parser
|
17
|
+
OptionParser.new do |options|
|
18
|
+
options.banner = "Usage: #{Command.short_script_name} help [command]\n\n#{self.class.description}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# This method extracts arguments from the command line.
|
23
|
+
#
|
24
|
+
# ### Parameters
|
25
|
+
#
|
26
|
+
# * **arguments: Array** The command line arguments.
|
27
|
+
def parse_positional_arguments(arguments)
|
28
|
+
self.command = arguments.shift
|
29
|
+
end
|
30
|
+
|
31
|
+
# This method runs the logic for the command.
|
32
|
+
def run
|
33
|
+
if self.command
|
34
|
+
RubyYacht::Runner.commands.each do |command|
|
35
|
+
if command.command == self.command
|
36
|
+
log command.new.option_parser.to_s
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
log "Command not available: #{self.command}"
|
42
|
+
log "Run #{Command.short_script_name} help for more options"
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
|
46
|
+
log "Available commands: \n\n"
|
47
|
+
RubyYacht::Runner.commands.each do |command|
|
48
|
+
log "#{command.name}: #{command.description}"
|
49
|
+
end
|
50
|
+
|
51
|
+
log "\nRun #{Command.short_script_name} help [command] for more information on a command"
|
52
|
+
true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RubyYacht::Runner
|
2
|
+
# This class provides a command for destroying the local docker environment.
|
3
|
+
class Implode < Command
|
4
|
+
# The name of the command.
|
5
|
+
def self.command; 'implode'; end
|
6
|
+
|
7
|
+
# The description of the command.
|
8
|
+
def self.description
|
9
|
+
"Destroy your local environment"
|
10
|
+
end
|
11
|
+
|
12
|
+
# This method runs the logic of the command.
|
13
|
+
def run
|
14
|
+
projects.each do |project|
|
15
|
+
system_prefix = project.system_prefix
|
16
|
+
|
17
|
+
machines = backtick("docker ps -a | grep #{system_prefix}").split("\n").map { |line| line.split(/\s+/)[0] }
|
18
|
+
machines.each do |machine|
|
19
|
+
docker "rm -f #{machine}"
|
20
|
+
end
|
21
|
+
|
22
|
+
images = backtick("docker images | grep #{system_prefix}").split("\n").map { |line| line.split(/\s+/)[0] }
|
23
|
+
images.each do |image|
|
24
|
+
docker "rmi #{image}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
backtick("docker images -q --filter dangling=true").split("\n").each do |image|
|
29
|
+
docker "rmi #{image}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module RubyYacht::Runner
|
2
|
+
# This class provides a command for running all the images in new containers.
|
3
|
+
#
|
4
|
+
# It will also remove any existing containers with conflicting names.
|
5
|
+
class RunContainers < Command
|
6
|
+
# THe name of the command.
|
7
|
+
def self.command; 'run_containers'; end
|
8
|
+
|
9
|
+
# The short description of the command.
|
10
|
+
def self.description; 'Runs containers for all the apps'; end
|
11
|
+
|
12
|
+
# This method runs the logic of the command.
|
13
|
+
def run
|
14
|
+
@network = projects.first.system_prefix
|
15
|
+
|
16
|
+
projects.each do |project|
|
17
|
+
@project = project
|
18
|
+
if @project.check_out_locally
|
19
|
+
FileUtils.mkdir_p File.join(ENV["PWD"], '..', 'code')
|
20
|
+
end
|
21
|
+
|
22
|
+
if project.database.local?
|
23
|
+
run_container :database
|
24
|
+
end
|
25
|
+
|
26
|
+
project.apps.each do |app|
|
27
|
+
run_container app.name
|
28
|
+
end
|
29
|
+
|
30
|
+
if @project.create_deploy_container
|
31
|
+
run_container :deploy
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@project = projects.first
|
36
|
+
|
37
|
+
run_container :web
|
38
|
+
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
# This method gets the flags for defining DNS server config when running
|
43
|
+
# a container.
|
44
|
+
def dns_server_flags
|
45
|
+
flags = []
|
46
|
+
if @project.dns_server
|
47
|
+
flags += @project.dns_server.servers.map { |server| "--dns=#{server}" }
|
48
|
+
flags += @project.dns_server.search_domains.map { |domain| "--dns-search=#{domain}" }
|
49
|
+
end
|
50
|
+
flags
|
51
|
+
end
|
52
|
+
|
53
|
+
# This method gets the flags for mapping the code volume to a local path for
|
54
|
+
# a container.
|
55
|
+
#
|
56
|
+
# ### Parameters
|
57
|
+
#
|
58
|
+
# * **container_name: Symbol** The name of the container, not including
|
59
|
+
# the system prefix.
|
60
|
+
def volume_flags(container_name)
|
61
|
+
if @project.check_out_locally && ![:database, :web].include?(container_name)
|
62
|
+
if container_name == :deploy
|
63
|
+
return ["-v $PWD/../code:/var/code"]
|
64
|
+
else
|
65
|
+
return ["-v $PWD/../code/#{container_name}:/var/code"]
|
66
|
+
end
|
67
|
+
else
|
68
|
+
return []
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# This method runs a container.
|
73
|
+
#
|
74
|
+
# It will also remove any existing containers with conflicting names.
|
75
|
+
#
|
76
|
+
# ### Parameters
|
77
|
+
#
|
78
|
+
# * **name: Symbol** The name of the container, not including the system
|
79
|
+
# prefix.
|
80
|
+
def run_container(name)
|
81
|
+
container_name = "#{@project.system_prefix}-#{name}"
|
82
|
+
remove_container container_name
|
83
|
+
|
84
|
+
flags = ["-d"]
|
85
|
+
flags += dns_server_flags
|
86
|
+
flags += volume_flags(name)
|
87
|
+
flags << "-it" if name == :deploy
|
88
|
+
flags << "-p 80:80" if name == :web
|
89
|
+
flags << "--net=#{@network}"
|
90
|
+
flags << "--net-alias=#{container_name}"
|
91
|
+
|
92
|
+
flag_text = flags.join(' ')
|
93
|
+
docker "run #{flag_text} --name=#{container_name} #{container_name}"
|
94
|
+
end
|
95
|
+
|
96
|
+
# This method removes a container.
|
97
|
+
#
|
98
|
+
# ### Parameters
|
99
|
+
#
|
100
|
+
# * **container_name: String** The full name of the container.
|
101
|
+
def remove_container(container_name)
|
102
|
+
IO.popen("docker rm -f #{container_name}", err: :close) {}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module RubyYacht::Runner
|
2
|
+
# This method provides the commands that we can run.
|
3
|
+
def self.commands
|
4
|
+
[Help, Build, BuildImages, RunContainers, Services, Checkout, Shell, UpdateHosts, Implode]
|
5
|
+
end
|
6
|
+
|
7
|
+
# This method gets the arguments for the current command.
|
8
|
+
def self.arguments
|
9
|
+
ARGV
|
10
|
+
end
|
11
|
+
|
12
|
+
# This method runs a command based on the command line arguments.
|
13
|
+
def self.run
|
14
|
+
arg = arguments[0]
|
15
|
+
|
16
|
+
if arg == '' || arg == nil
|
17
|
+
puts "You must provide a command to run"
|
18
|
+
puts "Run `#{$0} help` for more information"
|
19
|
+
exit(1)
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
command = self.commands.find { |c| c.command == arg }
|
24
|
+
if command
|
25
|
+
command_arguments = arguments
|
26
|
+
command_arguments.shift
|
27
|
+
|
28
|
+
instance = command.new
|
29
|
+
instance.option_parser.parse! command_arguments
|
30
|
+
instance.parse_positional_arguments command_arguments
|
31
|
+
|
32
|
+
success = instance.run
|
33
|
+
unless success
|
34
|
+
exit(1)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
puts "Command not recognized: #{arg}"
|
38
|
+
puts "Run `#{$0} help` for more information"
|
39
|
+
exit(1)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|