ruby_yacht 0.5.0 → 0.6.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 +4 -4
- data/.gitignore +3 -1
- data/.rdoc_options +8 -2
- data/.rspec +1 -0
- data/.travis.yml +17 -1
- data/Gemfile.lock +18 -2
- data/README.md +28 -10
- data/bin/ruby_yacht +5 -0
- data/doc/TODO.md +1 -20
- data/doc/configuration.md +104 -21
- data/doc/configuration_sample.rb +19 -8
- data/doc/contributing.md +28 -5
- data/doc/plugins.md +105 -45
- data/lib/ruby_yacht/dsl/app.rb +14 -18
- data/lib/ruby_yacht/dsl/configuration.rb +51 -32
- data/lib/ruby_yacht/dsl/database.rb +24 -8
- data/lib/ruby_yacht/dsl/dsl.rb +32 -4
- data/lib/ruby_yacht/dsl/hook.rb +182 -48
- data/lib/ruby_yacht/dsl/project.rb +20 -14
- data/lib/ruby_yacht/dsl/server_type.rb +14 -31
- data/lib/ruby_yacht/dsl/web_server.rb +87 -0
- data/lib/ruby_yacht/dsl.rb +1 -0
- data/lib/ruby_yacht/images/app/Dockerfile.erb +17 -6
- data/lib/ruby_yacht/images/app/before_startup.bash.erb +5 -3
- data/lib/ruby_yacht/images/app/startup.bash.erb +5 -2
- data/lib/ruby_yacht/images/app-dependencies/Dockerfile.erb +7 -11
- data/lib/ruby_yacht/images/database/Dockerfile.erb +7 -18
- data/lib/ruby_yacht/images/database/startup.bash.erb +1 -1
- data/lib/ruby_yacht/images/web/Dockerfile.erb +25 -19
- data/lib/ruby_yacht/plugins/mysql.rb +18 -8
- data/lib/ruby_yacht/{images/web → plugins/nginx/scripts}/add_app.rb +5 -5
- data/lib/ruby_yacht/{images/web → plugins/nginx/scripts}/add_project.rb +3 -3
- data/lib/ruby_yacht/plugins/nginx.rb +28 -0
- data/lib/ruby_yacht/plugins/rails/scripts/build_new_app.rb +10 -0
- data/lib/ruby_yacht/plugins/rails/scripts/update_rails_config.rb +6 -1
- data/lib/ruby_yacht/plugins/rails.rb +34 -19
- data/lib/ruby_yacht/plugins.rb +2 -1
- data/lib/ruby_yacht/runner/build_images.rb +87 -73
- data/lib/ruby_yacht/runner/checkout.rb +1 -1
- data/lib/ruby_yacht/runner/command.rb +13 -1
- data/lib/ruby_yacht/runner/create_new_project.rb +91 -0
- data/lib/ruby_yacht/runner/help.rb +1 -1
- data/lib/ruby_yacht/runner/run_containers.rb +17 -21
- data/lib/ruby_yacht/runner/runner.rb +27 -2
- data/lib/ruby_yacht/runner/services.rb +15 -10
- data/lib/ruby_yacht/runner/shell.rb +1 -1
- data/lib/ruby_yacht/runner/update_hosts.rb +16 -11
- data/lib/ruby_yacht/runner.rb +1 -0
- data/log/.gitkeep +0 -0
- data/ruby_yacht.gemspec +4 -2
- data/spec/docker/Dockerfile +19 -3
- data/spec/docker/install_gems.bash +5 -0
- data/spec/docker/run.bash +44 -0
- data/spec/docker/startup.bash +10 -0
- data/spec/dsl/app_spec.rb +66 -38
- data/spec/dsl/configuration_spec.rb +236 -30
- data/spec/dsl/database_spec.rb +103 -4
- data/spec/dsl/dsl_spec.rb +46 -3
- data/spec/dsl/hook_spec.rb +278 -57
- data/spec/dsl/project_spec.rb +75 -45
- data/spec/dsl/server_type_spec.rb +52 -12
- data/spec/dsl/web_server_spec.rb +160 -0
- data/spec/fixtures/apollo-new-project-config +20 -0
- data/spec/fixtures/app-dependencies-dockerfile-generic +4 -7
- data/spec/fixtures/app-dependencies-dockerfile-generic-with-library-install +6 -10
- data/spec/fixtures/app-dependencies-dockerfile-rails +9 -11
- data/spec/fixtures/app-dependencies-dockerfile-with-no-repository +20 -0
- data/spec/fixtures/database-dockerfile +1 -1
- data/spec/fixtures/database-dockerfile-mysql +3 -3
- data/spec/fixtures/database-dockerfile-rails +5 -4
- data/spec/fixtures/database-dockerfile-rails-with-no-repository +27 -0
- data/spec/fixtures/database-dockerfile-with-seed-hooks +3 -3
- data/spec/fixtures/database-startup-mysql +2 -1
- data/spec/fixtures/mars-before-startup +2 -2
- data/spec/fixtures/mars-before-startup-rails +5 -4
- data/spec/fixtures/mars-before-startup-with-before-startup-hooks +5 -4
- data/spec/fixtures/mars-before-startup-with-custom-file-copy +3 -3
- data/spec/fixtures/mars-before-startup-with-no-repository +3 -0
- data/spec/fixtures/mars-dockerfile +3 -2
- data/spec/fixtures/mars-dockerfile-rails +6 -5
- data/spec/fixtures/mars-dockerfile-rails-with-no-repository +32 -0
- data/spec/fixtures/mars-dockerfile-with-after-checkout-hooks +5 -4
- data/spec/fixtures/mars-dockerfile-with-before-startup-hooks +5 -4
- data/spec/fixtures/mars-dockerfile-with-custom-file-copy +4 -3
- data/spec/fixtures/mars-dockerfile-with-local-database +4 -2
- data/spec/fixtures/mars-dockerfile-with-no-repository +22 -0
- data/spec/fixtures/mars-dockerfile-with-remote-database +4 -2
- data/spec/fixtures/mars-startup +2 -2
- data/spec/fixtures/mars-startup-rails +2 -2
- data/spec/fixtures/mars-startup-rails-with-no-repository +5 -0
- data/spec/fixtures/mars-startup-with-no-repository +4 -0
- data/spec/fixtures/web-dockerfile +18 -11
- data/spec/fixtures/web-dockerfile-jupiter +28 -0
- data/spec/fixtures/web-dockerfile-nginx +38 -0
- data/spec/fixtures/web-dockerfile-with-eponymous-app +16 -10
- data/spec/fixtures/web-dockerfile-with-primary-app +16 -10
- data/spec/integration/build_images_spec.rb +210 -0
- data/spec/integration/build_spec.rb +23 -0
- data/spec/integration/checkout_spec.rb +94 -0
- data/spec/integration/create_new_project_spec.rb +50 -0
- data/spec/integration/implode_spec.rb +20 -0
- data/spec/integration/run.rb +93 -0
- data/spec/integration/run_containers_spec.rb +279 -0
- data/spec/integration/services_spec.rb +99 -0
- data/spec/integration/shell_spec.rb +31 -0
- data/spec/integration/update_hosts_spec.rb +35 -0
- data/spec/plugins/mysql_spec.rb +18 -1
- data/spec/plugins/nginx_spec.rb +66 -0
- data/spec/plugins/rails_spec.rb +61 -89
- data/spec/runner/build_images_spec.rb +111 -58
- data/spec/runner/command_spec.rb +55 -3
- data/spec/runner/create_new_project_spec.rb +93 -0
- data/spec/runner/help_spec.rb +5 -1
- data/spec/runner/run_containers_spec.rb +22 -10
- data/spec/runner/runner_spec.rb +31 -4
- data/spec/runner/services_spec.rb +32 -4
- data/spec/runner/update_hosts_spec.rb +2 -1
- data/spec/spec_helper.rb +16 -1
- data/spec/support/integration_helpers.rb +76 -0
- data/spec/support/test_project.rb +15 -3
- metadata +97 -14
- data/spec/docker/build.bash +0 -10
- data/spec/fixtures/deploy-dockerfile +0 -2
- data/spec/fixtures/multi-project-web-dockerfile +0 -25
- /data/lib/ruby_yacht/{images/web → plugins/nginx/scripts}/app_config.erb +0 -0
- /data/lib/ruby_yacht/{images/web → plugins/nginx/scripts}/index.html.erb +0 -0
- /data/lib/ruby_yacht/{images/web → plugins/nginx/scripts}/index_config.erb +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module RubyYacht::Runner
|
|
4
|
+
# This command provides help information about other commands.
|
|
5
|
+
class CreateNewProject < Command
|
|
6
|
+
# The name of the command.
|
|
7
|
+
def self.command; 'new'; end
|
|
8
|
+
|
|
9
|
+
# The short description of the command.
|
|
10
|
+
def self.description
|
|
11
|
+
'Create a new ruby-yacht project'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# The project that we are creating.
|
|
15
|
+
attr_accessor :project
|
|
16
|
+
|
|
17
|
+
# The directory where we should place the config.
|
|
18
|
+
attr_accessor :directory
|
|
19
|
+
|
|
20
|
+
# This method gets the command-line options for the command.
|
|
21
|
+
def option_parser
|
|
22
|
+
OptionParser.new do |options|
|
|
23
|
+
options.banner = "Usage: #{Command.short_script_name} new [PROJECT] [DIRECTORY]\n\n#{self.class.description}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# This method extracts arguments from the command line.
|
|
28
|
+
#
|
|
29
|
+
# ### Parameters
|
|
30
|
+
#
|
|
31
|
+
# * **arguments: Array** The command line arguments.
|
|
32
|
+
def parse_positional_arguments(arguments)
|
|
33
|
+
self.project = arguments.shift
|
|
34
|
+
self.directory = arguments.shift
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# This method runs the logic for the command.
|
|
38
|
+
def run
|
|
39
|
+
if project.nil?
|
|
40
|
+
log 'You must provide a project'
|
|
41
|
+
log "Run #{Command.short_script_name} help new for more information"
|
|
42
|
+
return false
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if directory.nil?
|
|
46
|
+
log 'You must provide a directory'
|
|
47
|
+
log "Run #{Command.short_script_name} help new for more information"
|
|
48
|
+
return false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
FileUtils.mkdir_p(directory)
|
|
52
|
+
File.open(File.join(directory, 'run.rb'), 'w') do |file|
|
|
53
|
+
write_config_file(file)
|
|
54
|
+
end
|
|
55
|
+
log "Your project has been created in #{directory}/run.rb."
|
|
56
|
+
log "You can go to #{directory} and run `ruby run.rb build` to create your docker containers."
|
|
57
|
+
log "Your initial app will be created in the #{project} directory."
|
|
58
|
+
true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
# This method writes the config file for the new project to a file.
|
|
64
|
+
#
|
|
65
|
+
# ### Parameters
|
|
66
|
+
#
|
|
67
|
+
# * **file: IO** The file to write to.
|
|
68
|
+
def write_config_file(file)
|
|
69
|
+
file.puts "require 'ruby_yacht'"
|
|
70
|
+
file.puts ''
|
|
71
|
+
file.puts 'RubyYacht.configure do'
|
|
72
|
+
file.puts " project :#{project} do"
|
|
73
|
+
file.puts " system_prefix :#{project}"
|
|
74
|
+
file.puts " repository 'github.com'"
|
|
75
|
+
file.puts " rails_secret_key_base 'testkey'"
|
|
76
|
+
file.puts " check_out_locally"
|
|
77
|
+
file.puts ""
|
|
78
|
+
file.puts " rails_app :#{project}"
|
|
79
|
+
file.puts ""
|
|
80
|
+
file.puts " primary_app :#{project}"
|
|
81
|
+
file.puts ""
|
|
82
|
+
file.puts " nginx_web_server do"
|
|
83
|
+
file.puts " domain '#{project}.test.com'"
|
|
84
|
+
file.puts " end"
|
|
85
|
+
file.puts " end"
|
|
86
|
+
file.puts "end"
|
|
87
|
+
file.puts ""
|
|
88
|
+
file.puts "RubyYacht::Runner.run"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -45,7 +45,7 @@ module RubyYacht::Runner
|
|
|
45
45
|
|
|
46
46
|
log "Available commands: \n\n"
|
|
47
47
|
RubyYacht::Runner.commands.each do |command|
|
|
48
|
-
log "#{command.
|
|
48
|
+
log "#{command.command}: #{command.description}"
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
log "\nRun #{Command.short_script_name} help [command] for more information on a command"
|
|
@@ -17,18 +17,18 @@ module RubyYacht::Runner
|
|
|
17
17
|
@project = project
|
|
18
18
|
|
|
19
19
|
project.databases.select(&:local?).each do |database|
|
|
20
|
-
run_container database
|
|
20
|
+
run_container database
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
project.apps.each do |app|
|
|
24
|
-
run_container app
|
|
24
|
+
run_container app
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
project.web_servers.each do |web_server|
|
|
28
|
+
run_container web_server
|
|
25
29
|
end
|
|
26
30
|
end
|
|
27
31
|
|
|
28
|
-
@project = projects.first
|
|
29
|
-
|
|
30
|
-
run_container :web
|
|
31
|
-
|
|
32
32
|
true
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -48,11 +48,11 @@ module RubyYacht::Runner
|
|
|
48
48
|
#
|
|
49
49
|
# ### Parameters
|
|
50
50
|
#
|
|
51
|
-
# * **
|
|
52
|
-
#
|
|
53
|
-
def volume_flags(
|
|
54
|
-
if @project.check_out_locally &&
|
|
55
|
-
return ["-v $PWD/../#{
|
|
51
|
+
# * **server: App/Database/WebServer** The server we are running a
|
|
52
|
+
# container for.
|
|
53
|
+
def volume_flags(server)
|
|
54
|
+
if @project.check_out_locally && server.is_a?(RubyYacht::App)
|
|
55
|
+
return ["-v $PWD/../#{server.name}:/var/code"]
|
|
56
56
|
else
|
|
57
57
|
return []
|
|
58
58
|
end
|
|
@@ -64,20 +64,16 @@ module RubyYacht::Runner
|
|
|
64
64
|
#
|
|
65
65
|
# ### Parameters
|
|
66
66
|
#
|
|
67
|
-
# * **
|
|
68
|
-
#
|
|
69
|
-
def run_container(
|
|
70
|
-
|
|
71
|
-
container_name = name
|
|
72
|
-
else
|
|
73
|
-
container_name = "#{@project.system_prefix}-#{name}"
|
|
74
|
-
end
|
|
67
|
+
# * **server: App/Database/WebServer** The server we are running a
|
|
68
|
+
# container for.
|
|
69
|
+
def run_container(server)
|
|
70
|
+
container_name = server.container_name
|
|
75
71
|
remove_container container_name
|
|
76
72
|
|
|
77
73
|
flags = ["-d"]
|
|
78
74
|
flags += dns_server_flags
|
|
79
|
-
flags += volume_flags(
|
|
80
|
-
flags << "-p
|
|
75
|
+
flags += volume_flags(server)
|
|
76
|
+
flags << "-p #{server.port}:80" if server.is_a?(RubyYacht::WebServer)
|
|
81
77
|
flags << "--net=#{@network}"
|
|
82
78
|
flags << "--net-alias=#{container_name}"
|
|
83
79
|
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
module RubyYacht::Runner
|
|
2
2
|
# This method provides the commands that we can run.
|
|
3
3
|
def self.commands
|
|
4
|
-
|
|
4
|
+
@commands ||= []
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# This method clears our list of commands that we can run.
|
|
8
|
+
def self.clear_commands
|
|
9
|
+
@commands = []
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# This method loads the default commands into our command list.
|
|
13
|
+
#
|
|
14
|
+
# ### Parameters
|
|
15
|
+
#
|
|
16
|
+
# * **in_project* Boolean** Whether we are running a script in the context
|
|
17
|
+
# of a project, or in the top-level ruby_yacht
|
|
18
|
+
# command.
|
|
19
|
+
def self.load_default_commands(in_project=true)
|
|
20
|
+
@commands ||= []
|
|
21
|
+
if in_project
|
|
22
|
+
@commands += [Help, Build, BuildImages, RunContainers, Services, Checkout, Shell, UpdateHosts, Implode]
|
|
23
|
+
else
|
|
24
|
+
@commands += [Help, CreateNewProject]
|
|
25
|
+
end
|
|
5
26
|
end
|
|
6
27
|
|
|
7
28
|
# This method gets the arguments for the current command.
|
|
@@ -11,13 +32,14 @@ module RubyYacht::Runner
|
|
|
11
32
|
|
|
12
33
|
# This method runs a command based on the command line arguments.
|
|
13
34
|
def self.run
|
|
35
|
+
load_default_commands if self.commands == []
|
|
14
36
|
arg = arguments[0]
|
|
15
37
|
|
|
16
38
|
if arg == '' || arg == nil
|
|
17
39
|
puts "You must provide a command to run"
|
|
18
40
|
puts "Run `#{$0} help` for more information"
|
|
19
41
|
exit(1)
|
|
20
|
-
return
|
|
42
|
+
return false
|
|
21
43
|
end
|
|
22
44
|
|
|
23
45
|
command = self.commands.find { |c| c.command == arg }
|
|
@@ -32,11 +54,14 @@ module RubyYacht::Runner
|
|
|
32
54
|
success = instance.run
|
|
33
55
|
unless success
|
|
34
56
|
exit(1)
|
|
57
|
+
return false
|
|
35
58
|
end
|
|
36
59
|
else
|
|
37
60
|
puts "Command not recognized: #{arg}"
|
|
38
61
|
puts "Run `#{$0} help` for more information"
|
|
39
62
|
exit(1)
|
|
63
|
+
return false
|
|
40
64
|
end
|
|
65
|
+
true
|
|
41
66
|
end
|
|
42
67
|
end
|
|
@@ -46,32 +46,37 @@ module RubyYacht::Runner
|
|
|
46
46
|
return false
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
if command == 'start'
|
|
49
|
+
if command == 'start'
|
|
50
50
|
start_docker_machine
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
projects.each do |project|
|
|
54
54
|
project.databases.select(&:local?).each do |database|
|
|
55
|
-
docker "#{command} #{database.container_name
|
|
55
|
+
docker "#{command} #{database.container_name}"
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
project.apps.each do |app|
|
|
59
|
-
docker "#{command} #{app.container_name
|
|
59
|
+
docker "#{command} #{app.container_name}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
project.web_servers.each do |server|
|
|
63
|
+
docker "#{command} #{server.container_name}"
|
|
60
64
|
end
|
|
61
65
|
end
|
|
62
|
-
docker "#{command} #{projects.first.system_prefix}-web"
|
|
63
66
|
|
|
64
67
|
true
|
|
65
68
|
end
|
|
66
69
|
|
|
67
70
|
# This method starts the default docker machine.
|
|
68
71
|
def start_docker_machine
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
if docker_machine != ''
|
|
73
|
+
system "#{docker_machine} start default"
|
|
74
|
+
|
|
75
|
+
environment_args = backtick("#{docker_machine} env default").split("\n")
|
|
76
|
+
environment_args.each do |arg|
|
|
77
|
+
if arg =~ /export (\w*)=\"(.*)\"/
|
|
78
|
+
ENV[$1] = $2
|
|
79
|
+
end
|
|
75
80
|
end
|
|
76
81
|
end
|
|
77
82
|
end
|
|
@@ -58,7 +58,7 @@ module RubyYacht::Runner
|
|
|
58
58
|
return false unless project
|
|
59
59
|
|
|
60
60
|
app = project.apps.find { |a| a.name == app_name.to_sym }
|
|
61
|
-
container = app.container_name
|
|
61
|
+
container = app.container_name
|
|
62
62
|
exec("docker exec -it #{container} bash -c 'cd /var/code; TERM=xterm #{command}'")
|
|
63
63
|
true
|
|
64
64
|
end
|
|
@@ -24,7 +24,9 @@ module RubyYacht::Runner
|
|
|
24
24
|
current_hosts = current_host_contents.split("\n")
|
|
25
25
|
new_hosts = current_hosts.select do |entry|
|
|
26
26
|
projects.none? do |project|
|
|
27
|
-
|
|
27
|
+
project.web_servers.any? do |server|
|
|
28
|
+
entry.include?(server.domain) || entry.include?("#{project.system_prefix} docker containers")
|
|
29
|
+
end
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -39,9 +41,9 @@ module RubyYacht::Runner
|
|
|
39
41
|
|
|
40
42
|
timestamp = Time.now.utc.strftime('%Y%m%d%H%M%S')
|
|
41
43
|
log "Please enter your password so that we can update the hosts file"
|
|
42
|
-
|
|
43
|
-
system "
|
|
44
|
-
|
|
44
|
+
sudo_command = backtick('which sudo').strip
|
|
45
|
+
system "#{sudo_command} cp /etc/hosts /etc/hosts.#{timestamp}.backup"
|
|
46
|
+
system "#{sudo_command} cat tmp/hosts > /etc/hosts"
|
|
45
47
|
true
|
|
46
48
|
end
|
|
47
49
|
|
|
@@ -57,15 +59,18 @@ module RubyYacht::Runner
|
|
|
57
59
|
# An Array with the new lines for the hosts file.
|
|
58
60
|
def hosts_file_entries(project, ip_address)
|
|
59
61
|
system_prefix = project.system_prefix
|
|
60
|
-
main_domain = project.domain
|
|
61
|
-
|
|
62
|
-
domains = [main_domain]
|
|
63
|
-
apps = project.apps.select { |app| app.name != system_prefix }
|
|
64
|
-
domains += apps.map { |app| "#{app.name}.#{main_domain}" }
|
|
65
|
-
|
|
66
62
|
header = "# #{system_prefix} docker containers"
|
|
67
63
|
new_hosts = ["", header]
|
|
68
|
-
|
|
64
|
+
|
|
65
|
+
project.web_servers.each do |web_server|
|
|
66
|
+
main_domain = web_server.domain
|
|
67
|
+
|
|
68
|
+
domains = [main_domain]
|
|
69
|
+
apps = project.apps.select { |app| app.name != system_prefix }
|
|
70
|
+
domains += apps.map { |app| "#{app.name}.#{main_domain}" }
|
|
71
|
+
|
|
72
|
+
new_hosts += domains.map { |domain| "#{ip_address} #{domain}" }
|
|
73
|
+
end
|
|
69
74
|
new_hosts
|
|
70
75
|
end
|
|
71
76
|
end
|
data/lib/ruby_yacht/runner.rb
CHANGED
data/log/.gitkeep
ADDED
|
File without changes
|
data/ruby_yacht.gemspec
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Gem::Specification.new do |spec|
|
|
2
2
|
spec.name = 'ruby_yacht'
|
|
3
|
-
spec.version = '0.
|
|
4
|
-
spec.date = '2016-05-
|
|
3
|
+
spec.version = '0.6.0'
|
|
4
|
+
spec.date = '2016-05-15'
|
|
5
5
|
spec.description = "A DSL for building docker containers for a family of Rails apps"
|
|
6
6
|
spec.summary = "A DSL for building docker containers for a family of Rails apps"
|
|
7
7
|
spec.authors = ["John Brownlee"]
|
|
@@ -16,4 +16,6 @@ Gem::Specification.new do |spec|
|
|
|
16
16
|
spec.add_development_dependency "rspec"
|
|
17
17
|
spec.add_development_dependency "codeclimate-test-reporter"
|
|
18
18
|
spec.add_development_dependency "timecop"
|
|
19
|
+
spec.add_development_dependency "byebug"
|
|
20
|
+
spec.add_development_dependency 'rubocop'
|
|
19
21
|
end
|
data/spec/docker/Dockerfile
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
FROM ruby:2.3
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
RUN apt-get update
|
|
4
|
+
RUN curl -fsSL https://get.docker.com/ | sh
|
|
5
|
+
|
|
6
|
+
RUN mkdir -p /var/docker
|
|
7
|
+
|
|
8
|
+
COPY startup.bash /var/docker/
|
|
9
|
+
COPY install_gems.bash /var/docker/
|
|
10
|
+
RUN chmod u+x /var/docker/*.bash
|
|
11
|
+
|
|
12
|
+
RUN /var/docker/install_gems.bash
|
|
13
|
+
|
|
14
|
+
RUN mkdir -p /root/.ssh
|
|
15
|
+
COPY id_rsa /root/.ssh
|
|
16
|
+
|
|
17
|
+
VOLUME /var/lib/docker
|
|
18
|
+
VOLUME /var/code/ruby-yacht
|
|
19
|
+
WORKDIR /var/code/ruby-yacht
|
|
20
|
+
|
|
21
|
+
CMD /var/docker/startup.bash
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#! /bin/bash
|
|
2
|
+
|
|
3
|
+
# This script runs our tests in a docker container.
|
|
4
|
+
#
|
|
5
|
+
# This keeps the development dependencies isolated from other parts of the
|
|
6
|
+
# system.
|
|
7
|
+
|
|
8
|
+
EXISTING_IMAGE=`docker images | grep ruby-yacht-tests`
|
|
9
|
+
if [ -z "$EXISTING_IMAGE" ]; then
|
|
10
|
+
if [ -f ~/.ssh/id_rsa ]; then
|
|
11
|
+
cp ~/.ssh/id_rsa spec/docker
|
|
12
|
+
else
|
|
13
|
+
touch spec/docker/id_rsa
|
|
14
|
+
fi
|
|
15
|
+
docker build -t ruby-yacht-tests spec/docker
|
|
16
|
+
rm spec/docker/id_rsa
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
if [ -z $PRESERVE_IMAGES ]; then
|
|
20
|
+
PRESERVE_IMAGES='0'
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
EXTRA_FLAGS="$EXTRA_FLAGS -e PRESERVE_IMAGES=$PRESERVE_IMAGES"
|
|
24
|
+
|
|
25
|
+
if [ $PRESERVE_IMAGES -eq 1 ]; then
|
|
26
|
+
EXTRA_FLAGS="$EXTRA_FLAGS -d"
|
|
27
|
+
EXISTING_CONTAINER=`docker ps | grep ruby-yacht-tests`
|
|
28
|
+
else
|
|
29
|
+
docker rm -f ruby-yacht-tests 1> /dev/null 2> /dev/null
|
|
30
|
+
EXTRA_FLAGS="$EXTRA_FLAGS --rm"
|
|
31
|
+
EXISTING_CONTAINER=""
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [ -z "$EXISTING_CONTAINER" ]; then
|
|
35
|
+
docker run -it $EXTRA_FLAGS --privileged --name=ruby-yacht-tests -v $PWD:/var/code/ruby-yacht ruby-yacht-tests /var/docker/startup.bash $*
|
|
36
|
+
RESULT=$?
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if [ $PRESERVE_IMAGES -eq 1 ]; then
|
|
40
|
+
docker exec -it ruby-yacht-tests bash -c "bundle install --quiet; rspec $*"
|
|
41
|
+
RESULT=$?
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
exit $RESULT
|
data/spec/dsl/app_spec.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
|
3
3
|
RSpec.describe RubyYacht::App do
|
|
4
4
|
describe "DSL" do
|
|
5
5
|
let(:name) { :test_app }
|
|
6
|
-
let(:app) { RubyYacht::App::DSL.new(name).run(@builder).create_object }
|
|
6
|
+
let(:app) { RubyYacht::App::DSL.new(:test, name).run(@builder).create_object }
|
|
7
7
|
|
|
8
8
|
before do
|
|
9
9
|
RubyYacht.configuration.clear
|
|
@@ -19,7 +19,6 @@ RSpec.describe RubyYacht::App do
|
|
|
19
19
|
@builder = Proc.new do
|
|
20
20
|
repository_name 'brownleej/test-app'
|
|
21
21
|
database_name :database
|
|
22
|
-
server_type :test
|
|
23
22
|
port 3000
|
|
24
23
|
end
|
|
25
24
|
expect(app.name).to eq :test_app
|
|
@@ -29,32 +28,17 @@ RSpec.describe RubyYacht::App do
|
|
|
29
28
|
expect(app.port).to eq 3000
|
|
30
29
|
end
|
|
31
30
|
|
|
32
|
-
it "
|
|
31
|
+
it "defaults the repository name to nil" do
|
|
33
32
|
@builder = Proc.new do
|
|
34
33
|
port 3000
|
|
35
|
-
server_type :test
|
|
36
34
|
database_name :database
|
|
37
35
|
end
|
|
38
|
-
expect
|
|
39
|
-
self.app
|
|
40
|
-
end.to raise_exception("Missing required attribute repository_name for RubyYacht::App::DSL")
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "requires the server type" do
|
|
44
|
-
@builder = Proc.new do
|
|
45
|
-
repository_name 'brownleej/test-app'
|
|
46
|
-
port 3000
|
|
47
|
-
database_name :database
|
|
48
|
-
end
|
|
49
|
-
expect do
|
|
50
|
-
self.app
|
|
51
|
-
end.to raise_exception("Missing required attribute server_type for RubyYacht::App::DSL")
|
|
36
|
+
expect(self.app.repository_name).to be_nil
|
|
52
37
|
end
|
|
53
38
|
|
|
54
39
|
it "does not require the database name" do
|
|
55
40
|
@builder = Proc.new do
|
|
56
41
|
repository_name 'brownleej/test-app'
|
|
57
|
-
server_type :test
|
|
58
42
|
port 3000
|
|
59
43
|
end
|
|
60
44
|
expect(app.database_name).to be_nil
|
|
@@ -69,7 +53,7 @@ RSpec.describe RubyYacht::App do
|
|
|
69
53
|
end
|
|
70
54
|
expect do
|
|
71
55
|
self.app
|
|
72
|
-
end.to raise_exception("App has invalid server type `invalid`")
|
|
56
|
+
end.to raise_exception("RubyYacht::App::DSL has invalid app server type `invalid`")
|
|
73
57
|
end
|
|
74
58
|
|
|
75
59
|
it "requires a defined server type for apps" do
|
|
@@ -88,41 +72,82 @@ RSpec.describe RubyYacht::App do
|
|
|
88
72
|
end
|
|
89
73
|
expect do
|
|
90
74
|
self.app
|
|
91
|
-
end.to raise_exception("App has invalid server type `sqlite`")
|
|
75
|
+
end.to raise_exception("RubyYacht::App::DSL has invalid app server type `sqlite`")
|
|
92
76
|
end
|
|
93
77
|
|
|
94
78
|
it "defaults the port to 8080" do
|
|
95
79
|
@builder = Proc.new do
|
|
96
80
|
repository_name 'brownleej/test-app'
|
|
97
|
-
server_type :test
|
|
98
81
|
database_name :database
|
|
99
82
|
end
|
|
100
83
|
expect(app.port).to eq 8080
|
|
101
84
|
end
|
|
102
85
|
end
|
|
103
86
|
|
|
87
|
+
describe 'project' do
|
|
88
|
+
before do
|
|
89
|
+
RubyYacht.configuration.clear
|
|
90
|
+
RubyYacht.configure do
|
|
91
|
+
server_type :test do
|
|
92
|
+
container_type :app
|
|
93
|
+
baseline_image 'ubuntu'
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
RubyYacht.configure do
|
|
97
|
+
project :project1 do
|
|
98
|
+
repository 'github.com'
|
|
99
|
+
system_prefix :project1
|
|
100
|
+
|
|
101
|
+
test_app :app1 do
|
|
102
|
+
repository_name 'app1'
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
test_app :app2 do
|
|
106
|
+
repository_name 'app2'
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
project :project2 do
|
|
111
|
+
repository 'github.com'
|
|
112
|
+
system_prefix :project2
|
|
113
|
+
|
|
114
|
+
test_app :app3 do
|
|
115
|
+
repository_name 'app3'
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'finds the project that contains the app' do
|
|
122
|
+
app2 = RubyYacht.configuration.projects[0].apps[1]
|
|
123
|
+
expect(app2.project.name).to eq :project1
|
|
124
|
+
|
|
125
|
+
app3 = RubyYacht.configuration.projects[1].apps[0]
|
|
126
|
+
expect(app3.project.name).to eq :project2
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
104
130
|
describe "container_name" do
|
|
105
|
-
|
|
106
|
-
project = RubyYacht::Project.new
|
|
107
|
-
project.name = :test_project
|
|
108
|
-
project.system_prefix = :tests
|
|
131
|
+
before do
|
|
132
|
+
@project = RubyYacht::Project.new
|
|
133
|
+
@project.name = :test_project
|
|
134
|
+
@project.system_prefix = :tests
|
|
109
135
|
|
|
110
|
-
app = RubyYacht::App.new
|
|
111
|
-
app.name = 'app1'
|
|
136
|
+
@app = RubyYacht::App.new
|
|
137
|
+
@app.name = 'app1'
|
|
138
|
+
@project.apps = [@app]
|
|
139
|
+
RubyYacht.configuration.projects << @project
|
|
140
|
+
end
|
|
112
141
|
|
|
113
|
-
|
|
142
|
+
it "combines the project's prefix with the app's name" do
|
|
143
|
+
expect(@app.container_name).to eq 'tests-app1'
|
|
114
144
|
end
|
|
115
145
|
|
|
116
146
|
context "with the same name as the project's system_prefix" do
|
|
117
147
|
it "is just the project's system prefix" do
|
|
118
|
-
|
|
119
|
-
project.name = :test_project
|
|
120
|
-
project.system_prefix = :tests
|
|
148
|
+
@app.name = :tests
|
|
121
149
|
|
|
122
|
-
app
|
|
123
|
-
app.name = :tests
|
|
124
|
-
|
|
125
|
-
expect(app.container_name(project)).to eq 'tests'
|
|
150
|
+
expect(@app.container_name).to eq 'tests'
|
|
126
151
|
end
|
|
127
152
|
end
|
|
128
153
|
end
|
|
@@ -146,10 +171,13 @@ RSpec.describe RubyYacht::App do
|
|
|
146
171
|
@app = RubyYacht::App.new
|
|
147
172
|
@app.name = 'app1'
|
|
148
173
|
@app.database_name = 'second_db'
|
|
174
|
+
|
|
175
|
+
@project.apps = [@app]
|
|
176
|
+
RubyYacht.configuration.projects << @project
|
|
149
177
|
end
|
|
150
178
|
|
|
151
179
|
it "is the database with the app's database_name" do
|
|
152
|
-
database = @app.database
|
|
180
|
+
database = @app.database
|
|
153
181
|
expect(database).not_to be_nil
|
|
154
182
|
expect(database.host).to eq 'db2.test.com'
|
|
155
183
|
end
|
|
@@ -160,7 +188,7 @@ RSpec.describe RubyYacht::App do
|
|
|
160
188
|
end
|
|
161
189
|
|
|
162
190
|
it "is nil" do
|
|
163
|
-
expect(@app.database
|
|
191
|
+
expect(@app.database).to be_nil
|
|
164
192
|
end
|
|
165
193
|
end
|
|
166
194
|
end
|