ruby_yacht 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,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
|