ruby_yacht 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,27 @@
1
+ FROM nginx
2
+
3
+ RUN apt-get update
4
+ RUN apt-get upgrade -y
5
+ RUN apt-get install -y ruby
6
+
7
+ RUN mkdir -p /var/docker
8
+
9
+ COPY add_project.rb /var/docker/add_project.rb
10
+ COPY add_app.rb /var/docker/add_app.rb
11
+ COPY index.html.erb /var/docker/index.html.erb
12
+ COPY index_config.erb /var/docker/index_config.erb
13
+ COPY app_config.erb /var/docker/app_config.erb
14
+
15
+
16
+
17
+ RUN ruby /var/docker/add_project.rb apollo apollo.test.com mars,saturn
18
+
19
+ RUN ruby /var/docker/add_app.rb apollo apollo.test.com mars 8080
20
+
21
+ RUN ruby /var/docker/add_app.rb apollo apollo.test.com saturn 8080
22
+
23
+
24
+
25
+ RUN rm -r /var/docker
26
+ RUN apt-get remove -y ruby
27
+ RUN apt-get autoremove -y
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyYacht::Runner::BuildImages do
4
+ include DockerCommandSpec
5
+
6
+ describe "command information" do
7
+ specify { expect(described_class.command).to eq 'build_images' }
8
+ specify { expect(described_class.description).to eq 'Build images for your environment' }
9
+ end
10
+
11
+ describe "running" do
12
+ it "builds all the images for the project" do
13
+ docker.fail_unexpected_commands!
14
+ docker.expect "network create apollo 2> /dev/null"
15
+ docker.expect "build -t apollo-app-dependencies tmp"
16
+ docker.expect "build -t apollo-mars tmp"
17
+ docker.expect "build -t apollo-saturn tmp"
18
+ docker.expect "build -t apollo-web tmp"
19
+ subject.run
20
+ end
21
+
22
+ it "generates the dockerfile for the app dependencies" do
23
+ docker.expect("build -t apollo-app-dependencies tmp") do
24
+ files = Dir[File.join("tmp", "*")].sort
25
+ expect(files).to eq ['tmp/Dockerfile', 'tmp/Dockerfile.erb', 'tmp/install_gems.rb']
26
+ dockerfile = File.read(File.join('tmp', 'Dockerfile'))
27
+ expected = File.read(File.join('spec', 'fixtures', 'app-dependencies-dockerfile'))
28
+ expect(dockerfile).to eq expected
29
+ end
30
+ subject.run
31
+ end
32
+
33
+ it "generates the dockerfiles for the apps" do
34
+ docker.expect("build -t apollo-mars tmp") do
35
+ files = Dir[File.join("tmp", "*")].sort
36
+ expect(files).to eq ['tmp/Dockerfile', 'tmp/Dockerfile.erb', 'tmp/checkout.rb', 'tmp/startup.rb', 'tmp/update_database_config.rb']
37
+ dockerfile = File.read(File.join('tmp', 'Dockerfile'))
38
+ expected = File.read(File.join('spec', 'fixtures', 'mars-dockerfile'))
39
+ expect(dockerfile).to eq expected
40
+ end
41
+ subject.run
42
+ end
43
+
44
+ it "generates the dockerfiles for the web server" do
45
+ docker.expect "build -t apollo-web tmp" do
46
+ files = Dir[File.join("tmp", "*")].sort
47
+ expect(files).to eq ['tmp/Dockerfile', 'tmp/Dockerfile.erb', 'tmp/add_app.rb', 'tmp/add_project.rb', 'tmp/app_config.erb', 'tmp/index.html.erb', 'tmp/index_config.erb', 'tmp/setup.rb']
48
+ dockerfile = File.read(File.join('tmp', 'Dockerfile'))
49
+ expected = File.read(File.join('spec', 'fixtures', 'web-dockerfile'))
50
+ expect(dockerfile).to eq expected
51
+ end
52
+ subject.run
53
+ end
54
+
55
+ it "returns true" do
56
+ expect(subject.run).to be_truthy
57
+ end
58
+
59
+ context "with a local database" do
60
+ before do
61
+ RubyYacht.configuration.projects[0].database.host = 'localhost'
62
+ end
63
+
64
+ it "builds the database" do
65
+ docker.expect("build -t apollo-database tmp") do
66
+ files = Dir[File.join("tmp", "*")].sort
67
+ expect(files).to eq ['tmp/Dockerfile', 'tmp/Dockerfile.erb', 'tmp/load_seeds.rb', 'tmp/setup.rb', 'tmp/setup_database.sql.erb']
68
+ dockerfile = File.read(File.join('tmp', 'Dockerfile'))
69
+ expected = File.read(File.join('spec', 'fixtures', 'database-dockerfile'))
70
+ expect(dockerfile).to eq expected
71
+ end
72
+ subject.run
73
+ end
74
+
75
+ it "returns true" do
76
+ expect(subject.run).to be_truthy
77
+ end
78
+ end
79
+
80
+ context "with an id_rsa key" do
81
+ let(:id_file_path) { File.join(ENV['HOME'], '.ssh', 'id_rsa') }
82
+ let(:missing_id_file) { !File.exist?(id_file_path) }
83
+ before do
84
+ if missing_id_file
85
+ FileUtils.mkdir_p(File.dirname(id_file_path))
86
+ File.open(id_file_path, 'w') do |file|
87
+ file.write('test')
88
+ end
89
+ end
90
+ end
91
+
92
+ it "copies the id_rsa key to the app-dependencies container" do
93
+ docker.expect "build -t apollo-app-dependencies tmp" do
94
+ files = Dir[File.join("tmp", "*")].sort
95
+ expect(files).to eq ['tmp/Dockerfile', 'tmp/Dockerfile.erb', 'tmp/id_rsa', 'tmp/install_gems.rb']
96
+ expect(File.read('tmp/id_rsa')).to eq File.read(id_file_path)
97
+ end
98
+
99
+ subject.run
100
+ end
101
+
102
+ it "returns true" do
103
+ expect(subject.run).to be_truthy
104
+ end
105
+
106
+ after do
107
+ if missing_id_file
108
+ FileUtils.rm(id_file_path)
109
+ end
110
+ end
111
+ end
112
+
113
+ context "with a deploy container" do
114
+ before do
115
+ RubyYacht.configuration.projects.first.create_deploy_container = true
116
+ end
117
+
118
+ it "creates the deploy container" do
119
+ docker.expect("build -t apollo-deploy tmp") do
120
+ files = Dir[File.join("tmp", "*")].sort
121
+ expect(files).to eq ['tmp/Dockerfile', 'tmp/Dockerfile.erb']
122
+ dockerfile = File.read(File.join('tmp', 'Dockerfile'))
123
+ expected = File.read(File.join('spec', 'fixtures', 'deploy-dockerfile'))
124
+ expect(dockerfile).to eq expected
125
+ end
126
+ subject.run
127
+ end
128
+ end
129
+
130
+ context "with multiple projects" do
131
+ before do
132
+ RubyYacht.configure_second_test_project
133
+ end
134
+
135
+ it "builds the containers for both projects" do
136
+ docker.fail_unexpected_commands!
137
+ docker.expect "network create apollo 2> /dev/null"
138
+ docker.expect "build -t apollo-app-dependencies tmp"
139
+ docker.expect "build -t apollo-mars tmp"
140
+ docker.expect "build -t apollo-saturn tmp"
141
+ docker.expect "build -t jupiter-app-dependencies tmp"
142
+ docker.expect "build -t jupiter-venus tmp"
143
+ docker.expect "build -t jupiter-saturn tmp"
144
+ docker.expect "build -t apollo-web tmp"
145
+ subject.run
146
+ end
147
+
148
+ it "generates one dockerfile for the web server with both projects" do
149
+ docker.expect "build -t apollo-web tmp" do
150
+ files = Dir[File.join("tmp", "*")].sort
151
+ expect(files).to eq ['tmp/Dockerfile', 'tmp/Dockerfile.erb', 'tmp/add_app.rb', 'tmp/add_project.rb', 'tmp/app_config.erb', 'tmp/index.html.erb', 'tmp/index_config.erb', 'tmp/setup.rb']
152
+ dockerfile = File.read(File.join('tmp', 'Dockerfile'))
153
+ expected = File.read(File.join('spec', 'fixtures', 'multi-project-web-dockerfile'))
154
+ expect(dockerfile).to eq expected
155
+ end
156
+ subject.run
157
+ end
158
+
159
+ it "returns true" do
160
+ expect(subject.run).to be_truthy
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyYacht::Runner::Build do
4
+ include DockerCommandSpec
5
+
6
+ describe "command information" do
7
+ specify { expect(described_class.command).to eq 'build' }
8
+ specify { expect(described_class.description).to eq 'Build images and run containers' }
9
+ end
10
+
11
+ describe "run behavior" do
12
+ let(:commands) { [double, double, double] }
13
+
14
+ before do
15
+ allow(RubyYacht::Runner::BuildImages).to receive(:new).and_return commands[0]
16
+ allow(RubyYacht::Runner::RunContainers).to receive(:new).and_return commands[1]
17
+ allow(RubyYacht::Runner::UpdateHosts).to receive(:new).and_return commands[2]
18
+
19
+ commands.each { |command| allow(command).to receive(:run).and_return(true) }
20
+ end
21
+
22
+ context "with successes from all commands" do
23
+ it "builds the images, runs the containers, and update the hosts" do
24
+ subject.run
25
+ expect(commands[0]).to have_received(:run)
26
+ expect(commands[1]).to have_received(:run)
27
+ expect(commands[2]).to have_received(:run)
28
+ end
29
+
30
+ it "returns true" do
31
+ expect(subject.run).to be_truthy
32
+ end
33
+ end
34
+
35
+ context "with an error building the images" do
36
+ before do
37
+ allow(commands[0]).to receive(:run).and_return false
38
+ end
39
+
40
+ it "builds the images, but does not runs the containers or update the hosts" do
41
+ subject.run
42
+ expect(commands[0]).to have_received(:run)
43
+ expect(commands[1]).not_to have_received(:run)
44
+ expect(commands[2]).not_to have_received(:run)
45
+ end
46
+
47
+ it "returns false" do
48
+ expect(subject.run).to be_falsey
49
+ end
50
+ end
51
+
52
+ context "an error running containers" do
53
+ before do
54
+ allow(commands[1]).to receive(:run).and_return false
55
+ end
56
+
57
+ it "builds the images and runs the containers, but does not update the hosts" do
58
+ subject.run
59
+ expect(commands[0]).to have_received(:run)
60
+ expect(commands[1]).to have_received(:run)
61
+ expect(commands[2]).not_to have_received(:run)
62
+ end
63
+
64
+ it "returns false" do
65
+ expect(subject.run).to be_falsey
66
+ end
67
+ end
68
+
69
+ context "with an error updating hosts" do
70
+ before do
71
+ allow(commands[2]).to receive(:run).and_return false
72
+ end
73
+
74
+ it "builds the images, runs the containers, and update the hosts" do
75
+ subject.run
76
+ expect(commands[0]).to have_received(:run)
77
+ expect(commands[1]).to have_received(:run)
78
+ expect(commands[2]).to have_received(:run)
79
+ end
80
+
81
+ it "returns true" do
82
+ expect(subject.run).to be_falsey
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyYacht::Runner::Checkout do
4
+ include DockerCommandSpec
5
+
6
+ describe "command information" do
7
+ specify { expect(described_class.command).to eq 'checkout' }
8
+ specify { expect(described_class.description).to eq 'Check out a new branch for an app' }
9
+
10
+ describe "command-line parsing" do
11
+ let(:options) { subject.option_parser }
12
+ it "gives a summary in the banner" do
13
+ expect(options.banner).to eq "Usage: rspec checkout [options] [APP] [BRANCH]"
14
+ end
15
+
16
+ it "explains the options in the summary" do
17
+ expect(options.summarize).to eq [
18
+ "Options:\n",
19
+ " -p, --project PROJECT The project with the app we are checking out the branch in. Default: apollo\n"
20
+ ]
21
+ end
22
+
23
+ it "sets the project name from the command line" do
24
+ RubyYacht.configure_second_test_project
25
+ arguments = %w(-p jupiter venus issue1234)
26
+ subject.option_parser.parse!(arguments)
27
+ expect(subject.project_name).to eq :jupiter
28
+ expect(arguments).to eq %w(venus issue1234)
29
+ end
30
+
31
+ it "takes the app and checkout from the command line" do
32
+ subject.parse_positional_arguments(['venus', 'issue1234'])
33
+ expect(subject.app).to eq 'venus'
34
+ expect(subject.branch).to eq 'issue1234'
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "run behavior" do
40
+ before do
41
+ subject.app = 'saturn'
42
+ subject.branch = 'issue1234'
43
+ end
44
+
45
+ it "runs the commands to check out the branch and update the app" do
46
+ docker.fail_unexpected_commands!
47
+ docker.expect "exec apollo-saturn bash -c 'cd /var/code; git fetch; git checkout .; git checkout issue1234; git pull'"
48
+ docker.expect "exec apollo-saturn bash -c '/var/docker/update_database_config.rb; rake db:migrate'"
49
+ docker.expect "restart apollo-saturn"
50
+ subject.run
51
+ end
52
+
53
+ it "returns true" do
54
+ expect(subject.run).to be_truthy
55
+ end
56
+
57
+ context "with an explicit project" do
58
+ before do
59
+ RubyYacht.configure_second_test_project
60
+ subject.project_name = :jupiter
61
+ end
62
+
63
+ it "runs the command in that project" do
64
+ subject.app = 'venus'
65
+ docker.fail_unexpected_commands!
66
+ docker.expect "exec jupiter-venus bash -c 'cd /var/code; git fetch; git checkout .; git checkout issue1234; git pull'"
67
+ docker.expect "exec jupiter-venus bash -c '/var/docker/update_database_config.rb; rake db:migrate'"
68
+ docker.expect "restart jupiter-venus"
69
+ subject.run
70
+ end
71
+
72
+ it "returns true" do
73
+ expect(subject.run).to be_truthy
74
+ end
75
+ end
76
+
77
+ context "with an invalid project" do
78
+ before do
79
+ subject.project_name = :foo
80
+ end
81
+
82
+ it "logs an error" do
83
+ subject.run
84
+ expect(@log_entries).to eq ['There is no project named foo']
85
+ end
86
+
87
+ it "returns false" do
88
+ expect(subject.run).to be_falsey
89
+ end
90
+ end
91
+
92
+ context "with no app" do
93
+ before do
94
+ subject.app = nil
95
+ end
96
+
97
+ it "logs an error" do
98
+ subject.run
99
+ expect(@log_entries).to eq [
100
+ "You must provide an app name",
101
+ "Run rspec help checkout for more information"
102
+ ]
103
+ end
104
+
105
+ it "returns false" do
106
+ expect(subject.run).to be_falsey
107
+ end
108
+ end
109
+
110
+ context "with no branch" do
111
+ before do
112
+ subject.branch = nil
113
+ end
114
+
115
+ it "logs an error" do
116
+ subject.run
117
+ expect(@log_entries).to eq [
118
+ "You must provide a branch",
119
+ "Run rspec help checkout for more information"
120
+ ]
121
+ end
122
+
123
+ it "returns false" do
124
+ expect(subject.run).to be_falsey
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyYacht::Runner::Command do
4
+ class SampleCommand < RubyYacht::Runner::Command
5
+ def self.command; 'sample_command'; end
6
+ def self.description; 'Provides a sample command for testing'; end
7
+ end
8
+
9
+ describe "command information" do
10
+ specify { expect { described_class.command }.to raise_error "Command not defined for RubyYacht::Runner::Command" }
11
+ specify { expect { described_class.description }.to raise_error "Description not defined for RubyYacht::Runner::Command" }
12
+
13
+ describe "option_parser" do
14
+ it "takes the usage from the command information" do
15
+ expect(SampleCommand.new.option_parser.banner).to eq "Usage: rspec sample_command\n\nProvides a sample command for testing"
16
+ end
17
+
18
+ it "does not have anything beyond the banner" do
19
+ parser = SampleCommand.new.option_parser
20
+ expect(parser.to_s).to eq parser.banner + "\n"
21
+ end
22
+ end
23
+
24
+ describe "parse_positional_arguments" do
25
+ it "does not modify the arguments" do
26
+ arguments = %w(foo bar)
27
+ subject.parse_positional_arguments(arguments)
28
+ expect(arguments).to eq %w(foo bar)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "run behavior" do
34
+ it "raises an error" do
35
+ expect { subject.run }.to raise_error "Run method not defined for #{subject}"
36
+ end
37
+ end
38
+
39
+ describe "helpers" do
40
+ describe "short_script_name" do
41
+ it "is the name of the invoked command" do
42
+ expect(described_class.short_script_name).to eq "rspec"
43
+ end
44
+ end
45
+
46
+ describe "projects" do
47
+ it "provides the full list of projects" do
48
+ RubyYacht.configure_test_project
49
+ RubyYacht.configure_second_test_project
50
+ expect(subject.projects.collect(&:name)).to eq [:apollo, :jupiter]
51
+ end
52
+ end
53
+
54
+ describe "get_machine_info" do
55
+ it "gets the property from docker" do
56
+ allow(subject).to receive(:backtick).with("docker-machine inspect default -f {{System.Name}}").and_return("Jimmy\n")
57
+ expect(subject.get_machine_info('System.Name')).to eq 'Jimmy'
58
+ end
59
+ end
60
+
61
+ describe "logs" do
62
+ it "logs the message to stdout" do
63
+ allow($stdout).to receive(:puts)
64
+ subject.log('Test Message')
65
+ expect($stdout).to have_received(:puts).with('Test Message')
66
+ end
67
+ end
68
+
69
+ describe "docker" do
70
+ it "sends the command to docker" do
71
+ allow(subject).to receive(:system)
72
+ subject.docker "run hello-world"
73
+ expect(subject).to have_received(:system).with('docker run hello-world')
74
+ end
75
+ end
76
+
77
+ describe "system" do
78
+ it "executes the command" do
79
+ subject.system 'echo test > tmp/test'
80
+ expect(File.read('tmp/test')).to eq "test\n"
81
+ FileUtils.rm('tmp/test')
82
+ end
83
+ end
84
+
85
+ describe "backtick" do
86
+ it "returns the result of executing the command" do
87
+ File.open('tmp/test', 'w') { |f| f.write('test contents') }
88
+ value = subject.backtick('cat tmp/test')
89
+ expect(value).to eq 'test contents'
90
+ FileUtils.rm('tmp/test')
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyYacht::Runner::Help do
4
+ include DockerCommandSpec
5
+
6
+ describe "command information" do
7
+ specify { expect(described_class.command).to eq 'help' }
8
+ specify { expect(described_class.description).to eq 'Get information on available commands' }
9
+
10
+ describe "option_parser" do
11
+ it "provides the usage information" do
12
+ options = subject.option_parser
13
+ expect(options.banner).to eq "Usage: rspec help [command]\n\nGet information on available commands"
14
+ end
15
+ end
16
+
17
+ describe "parse_positional_arguments" do
18
+ it "takes the command from the arguments" do
19
+ subject.parse_positional_arguments(%w(checkout foo))
20
+ expect(subject.command).to eq 'checkout'
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "run behavior" do
26
+ context "with no command" do
27
+ it "prints the available commands" do
28
+ subject.run
29
+ expected = ["Available commands: \n\n"]
30
+ expected += RubyYacht::Runner.commands.map { |c| "#{c.name}: #{c.description}" }
31
+ expected << "\nRun rspec help [command] for more information on a command"
32
+ expect(@log_entries).to eq expected
33
+ end
34
+
35
+ it "returns true" do
36
+ expect(subject.run).to be_truthy
37
+ end
38
+ end
39
+
40
+ context "with a command" do
41
+ before do
42
+ subject.command = 'checkout'
43
+ end
44
+
45
+ it "prints the usage information for the command" do
46
+ subject.run
47
+ expect(@log_entries).to eq [RubyYacht::Runner::Checkout.new.option_parser.to_s]
48
+ end
49
+
50
+ it "returns true" do
51
+ expect(subject.run).to be_truthy
52
+ end
53
+ end
54
+
55
+ context "with an invalid command" do
56
+ before do
57
+ subject.command = 'foo'
58
+ end
59
+
60
+ it "prints an error" do
61
+ subject.run
62
+ expect(@log_entries).to eq [
63
+ "Command not available: foo",
64
+ "Run rspec help for more options"
65
+ ]
66
+ end
67
+
68
+ it "returns false" do
69
+ expect(subject.run).to be_falsey
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyYacht::Runner::Implode do
4
+ include DockerCommandSpec
5
+
6
+ describe "command information" do
7
+ specify { expect(described_class.command).to eq 'implode' }
8
+ specify { expect(described_class.description).to eq 'Destroy your local environment' }
9
+ end
10
+
11
+ describe "run behavior" do
12
+ before do
13
+ allow(subject).to receive(:backtick).with('docker ps -a | grep apollo').and_return("123 up apollo-mars\n456 up apollo-saturn\n789 apollo-venus")
14
+ allow(subject).to receive(:backtick).with('docker images | grep apollo').and_return("apollo-app-dependencies 1GB\napollo-mars 1GB")
15
+ allow(subject).to receive(:backtick).with('docker ps -a | grep jupiter').and_return("abc up jupiter-saturn")
16
+ allow(subject).to receive(:backtick).with('docker images | grep jupiter').and_return("jupiter-app-dependencies 1GB\njupiter-mars 1GB")
17
+
18
+ allow(subject).to receive(:backtick).with('docker images -q --filter dangling=true').and_return("111\n222")
19
+ end
20
+
21
+ it "removes all the containers and images" do
22
+ docker.fail_unexpected_commands!
23
+ docker.expect 'rm -f 123'
24
+ docker.expect 'rm -f 456'
25
+ docker.expect 'rm -f 789'
26
+ docker.expect 'rmi apollo-app-dependencies'
27
+ docker.expect 'rmi apollo-mars'
28
+ docker.expect 'rmi 111'
29
+ docker.expect 'rmi 222'
30
+ subject.run
31
+ end
32
+
33
+ it "returns true" do
34
+ expect(subject.run).to be_truthy
35
+ end
36
+
37
+ context "with a second project" do
38
+ before do
39
+ RubyYacht.configure_second_test_project
40
+ end
41
+
42
+ it "removes containers and images for both projects" do
43
+ docker.fail_unexpected_commands!
44
+ docker.expect 'rm -f 123'
45
+ docker.expect 'rm -f 456'
46
+ docker.expect 'rm -f 789'
47
+ docker.expect 'rmi apollo-app-dependencies'
48
+ docker.expect 'rmi apollo-mars'
49
+ docker.expect 'rm -f abc'
50
+ docker.expect 'rmi jupiter-app-dependencies'
51
+ docker.expect 'rmi jupiter-mars'
52
+ docker.expect 'rmi 111'
53
+ docker.expect 'rmi 222'
54
+ subject.run
55
+ end
56
+
57
+ it "returns true" do
58
+ expect(subject.run).to be_truthy
59
+ end
60
+ end
61
+ end
62
+ end