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,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,10 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <body>
4
+ <ul>
5
+ <% @app_names.each do |name| %>
6
+ <li><a href="http://<%= name %>.<%= @domain %>/"><%= name %></li>
7
+ <% end %>
8
+ </ul>
9
+ </body>
10
+ </html>
@@ -0,0 +1,12 @@
1
+ server {
2
+ listen 80;
3
+ server_name <%= @domain %>;
4
+
5
+ #charset koi8-r;
6
+ #access_log /var/log/nginx/log/host.access.log main;
7
+
8
+ location / {
9
+ root /usr/share/nginx/html;
10
+ index <%= @project %>.html ;
11
+ }
12
+ }
@@ -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