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,141 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RubyYacht::Runner::RunContainers do
|
4
|
+
include DockerCommandSpec
|
5
|
+
|
6
|
+
describe "command information" do
|
7
|
+
specify { expect(described_class.command).to eq 'run_containers' }
|
8
|
+
specify { expect(described_class.description).to eq 'Runs containers for all the apps' }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "run behavior" do
|
12
|
+
before do
|
13
|
+
allow(subject).to receive(:remove_container)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "runs the containers for all the apps" do
|
17
|
+
docker.fail_unexpected_commands!
|
18
|
+
docker.expect 'run -d --net=apollo --net-alias=apollo-mars --name=apollo-mars apollo-mars'
|
19
|
+
docker.expect 'run -d --net=apollo --net-alias=apollo-saturn --name=apollo-saturn apollo-saturn'
|
20
|
+
docker.expect 'run -d -p 80:80 --net=apollo --net-alias=apollo-web --name=apollo-web apollo-web'
|
21
|
+
subject.run
|
22
|
+
end
|
23
|
+
|
24
|
+
it "tries to remove all the containers" do
|
25
|
+
subject.run
|
26
|
+
expect(subject).to have_received(:remove_container).with('apollo-mars')
|
27
|
+
expect(subject).to have_received(:remove_container).with('apollo-saturn')
|
28
|
+
expect(subject).to have_received(:remove_container).with('apollo-web')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns true" do
|
32
|
+
expect(subject.run).to be_truthy
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with a deploy container" do
|
36
|
+
before do
|
37
|
+
RubyYacht.configuration.projects.first.create_deploy_container = true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "runs the deploy container" do
|
41
|
+
docker.expect 'run -d -it --net=apollo --net-alias=apollo-deploy --name=apollo-deploy apollo-deploy'
|
42
|
+
subject.run
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns true" do
|
46
|
+
expect(subject.run).to be_truthy
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with a local database" do
|
51
|
+
before do
|
52
|
+
RubyYacht.configuration.projects.first.database.host = 'localhost'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "runs the database container" do
|
56
|
+
docker.expect 'run -d --net=apollo --net-alias=apollo-database --name=apollo-database apollo-database'
|
57
|
+
subject.run
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns true" do
|
61
|
+
expect(subject.run).to be_truthy
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with multiple projects" do
|
66
|
+
before do
|
67
|
+
RubyYacht.configure_second_test_project
|
68
|
+
end
|
69
|
+
|
70
|
+
it "runs the containers for both projects" do
|
71
|
+
docker.fail_unexpected_commands!
|
72
|
+
docker.expect 'run -d --net=apollo --net-alias=apollo-mars --name=apollo-mars apollo-mars'
|
73
|
+
docker.expect 'run -d --net=apollo --net-alias=apollo-saturn --name=apollo-saturn apollo-saturn'
|
74
|
+
docker.expect 'run -d --net=apollo --net-alias=jupiter-venus --name=jupiter-venus jupiter-venus'
|
75
|
+
docker.expect 'run -d --net=apollo --net-alias=jupiter-saturn --name=jupiter-saturn jupiter-saturn'
|
76
|
+
docker.expect 'run -d -p 80:80 --net=apollo --net-alias=apollo-web --name=apollo-web apollo-web'
|
77
|
+
subject.run
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns true" do
|
81
|
+
expect(subject.run).to be_truthy
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with DNS server config" do
|
86
|
+
before do
|
87
|
+
project = RubyYacht.configuration.projects.first
|
88
|
+
project.dns_server = RubyYacht::DnsServer.new
|
89
|
+
project.dns_server.servers = ['8.10.1.1', '8.10.1.2']
|
90
|
+
project.dns_server.search_domains = ['apps.test.com', 'db.test.com']
|
91
|
+
end
|
92
|
+
|
93
|
+
it "gives the DNS information to the docker container" do
|
94
|
+
docker.expect 'run -d --dns=8.10.1.1 --dns=8.10.1.2 --dns-search=apps.test.com --dns-search=db.test.com --net=apollo --net-alias=apollo-mars --name=apollo-mars apollo-mars'
|
95
|
+
subject.run
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns true" do
|
99
|
+
expect(subject.run).to be_truthy
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when checking out the code locally" do
|
104
|
+
before do
|
105
|
+
RubyYacht.configuration.projects.first.check_out_locally = true
|
106
|
+
end
|
107
|
+
|
108
|
+
it "maps the code volume to a local directory" do
|
109
|
+
docker.expect 'run -d -v $PWD/../code/mars:/var/code --net=apollo --net-alias=apollo-mars --name=apollo-mars apollo-mars'
|
110
|
+
docker.expect 'run -d -v $PWD/../code/saturn:/var/code --net=apollo --net-alias=apollo-saturn --name=apollo-saturn apollo-saturn'
|
111
|
+
subject.run
|
112
|
+
end
|
113
|
+
|
114
|
+
it "returns true" do
|
115
|
+
expect(subject.run).to be_truthy
|
116
|
+
end
|
117
|
+
|
118
|
+
context "when creating a deploy container" do
|
119
|
+
before do
|
120
|
+
RubyYacht.configuration.projects.first.create_deploy_container = true
|
121
|
+
end
|
122
|
+
it "maps the code volume to a local directory" do
|
123
|
+
docker.expect 'run -d -v $PWD/../code:/var/code -it --net=apollo --net-alias=apollo-deploy --name=apollo-deploy apollo-deploy'
|
124
|
+
subject.run
|
125
|
+
end
|
126
|
+
|
127
|
+
it "returns true" do
|
128
|
+
expect(subject.run).to be_truthy
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "remove_container" do
|
135
|
+
it "sends the command to docker" do
|
136
|
+
allow(IO).to receive(:popen)
|
137
|
+
subject.remove_container('apollo-mars')
|
138
|
+
expect(IO).to have_received(:popen).with('docker rm -f apollo-mars', err: :close)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RubyYacht::Runner do
|
4
|
+
before do
|
5
|
+
allow(described_class).to receive(:puts)
|
6
|
+
allow(described_class).to receive(:exit)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "commands" do
|
10
|
+
it "contains all the defined commands" do
|
11
|
+
commands = ObjectSpace.each_object(Class).select { |klass| klass < RubyYacht::Runner::Command && klass.inspect =~ /^RubyYacht::Runner/ }.uniq
|
12
|
+
expect(described_class.commands.sort_by(&:name)).to eq commands.sort_by(&:name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "arguments" do
|
17
|
+
it "gets the command-line arguments" do
|
18
|
+
expect(described_class.arguments).to eq ARGV
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "run" do
|
23
|
+
let(:command) { RubyYacht::Runner::Checkout.new }
|
24
|
+
before do
|
25
|
+
allow(described_class).to receive(:arguments).and_return %w(checkout -p apollo mars issue1234)
|
26
|
+
allow(command).to receive(:run)
|
27
|
+
allow(RubyYacht::Runner::Checkout).to receive(:new).and_return(command)
|
28
|
+
RubyYacht.configure_test_project
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with a valid command" do
|
32
|
+
context "with a successful command" do
|
33
|
+
before do
|
34
|
+
allow(command).to receive(:run).and_return(true)
|
35
|
+
described_class.run
|
36
|
+
end
|
37
|
+
|
38
|
+
it "calls the command" do
|
39
|
+
expect(command.project_name).to eq :apollo
|
40
|
+
expect(command.app).to eq 'mars'
|
41
|
+
expect(command.branch).to eq 'issue1234'
|
42
|
+
expect(command).to have_received(:run)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "does not exit" do
|
46
|
+
expect(described_class).not_to have_received(:exit)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with a failed command" do
|
51
|
+
before do
|
52
|
+
allow(command).to receive(:run).and_return(false)
|
53
|
+
described_class.run
|
54
|
+
end
|
55
|
+
|
56
|
+
it "calls the command" do
|
57
|
+
expect(command).to have_received(:run)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "exits with a failure code" do
|
61
|
+
expect(described_class).to have_received(:exit).with(1)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with a nil command" do
|
67
|
+
before do
|
68
|
+
allow(described_class).to receive(:arguments).and_return []
|
69
|
+
described_class.run
|
70
|
+
end
|
71
|
+
|
72
|
+
it "logs a message" do
|
73
|
+
invocation = $0
|
74
|
+
expect(described_class).to have_received(:puts).with("You must provide a command to run")
|
75
|
+
expect(described_class).to have_received(:puts).with("Run `#{invocation} help` for more information")
|
76
|
+
end
|
77
|
+
|
78
|
+
it "exits with a failure code" do
|
79
|
+
expect(described_class).to have_received(:exit).with(1)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "with a blank command" do
|
84
|
+
before do
|
85
|
+
allow(described_class).to receive(:arguments).and_return ['']
|
86
|
+
described_class.run
|
87
|
+
end
|
88
|
+
|
89
|
+
it "logs a message" do
|
90
|
+
invocation = $0
|
91
|
+
expect(described_class).to have_received(:puts).with("You must provide a command to run")
|
92
|
+
expect(described_class).to have_received(:puts).with("Run `#{invocation} help` for more information")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "exits with a failure code" do
|
96
|
+
expect(described_class).to have_received(:exit).with(1)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "with an invalid command" do
|
101
|
+
before do
|
102
|
+
allow(described_class).to receive(:arguments).and_return %w(foo bar)
|
103
|
+
described_class.run
|
104
|
+
end
|
105
|
+
|
106
|
+
it "logs a message" do
|
107
|
+
invocation = $0
|
108
|
+
expect(described_class).to have_received(:puts).with("Command not recognized: foo")
|
109
|
+
expect(described_class).to have_received(:puts).with("Run `#{invocation} help` for more information")
|
110
|
+
end
|
111
|
+
|
112
|
+
it "exits with a failure code" do
|
113
|
+
expect(described_class).to have_received(:exit).with(1)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RubyYacht::Runner::Services do
|
4
|
+
include DockerCommandSpec
|
5
|
+
|
6
|
+
describe "command information" do
|
7
|
+
specify { expect(described_class.command).to eq 'services' }
|
8
|
+
specify { expect(described_class.description).to eq 'Start, stop, or restart containers' }
|
9
|
+
|
10
|
+
it "has a banner with more information about the command" do
|
11
|
+
usage = "Usage: rspec services [COMMAND]"
|
12
|
+
usage += "\n\nStart, stop, or restart containers"
|
13
|
+
usage += "\n\n[COMMAND] is required, and can be start, stop, or restart"
|
14
|
+
expect(subject.option_parser.banner).to eq usage
|
15
|
+
end
|
16
|
+
|
17
|
+
it "gets the command from position arguments" do
|
18
|
+
subject.parse_positional_arguments(["restart", "foo"])
|
19
|
+
expect(subject.command).to eq 'restart'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "run behavior" do
|
24
|
+
before do
|
25
|
+
subject.command = 'stop'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "sends the command to each container" do
|
29
|
+
docker.fail_unexpected_commands!
|
30
|
+
docker.expect 'stop apollo-mars'
|
31
|
+
docker.expect 'stop apollo-saturn'
|
32
|
+
docker.expect 'stop apollo-web'
|
33
|
+
subject.run
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns true" do
|
37
|
+
expect(subject.run).to be_truthy
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with a local database" do
|
41
|
+
before do
|
42
|
+
RubyYacht.configuration.projects.first.database.host = 'localhost'
|
43
|
+
end
|
44
|
+
|
45
|
+
it "stops the database" do
|
46
|
+
docker.expect 'stop apollo-database'
|
47
|
+
subject.run
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns true" do
|
51
|
+
expect(subject.run).to be_truthy
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with a docker machine" do
|
56
|
+
before do
|
57
|
+
allow(subject).to receive(:backtick).with('which docker-machine').and_return '/usr/bin/docker-machine'
|
58
|
+
allow(subject).to receive(:backtick).with('docker-machine env default').and_return "# Test\nexport TEST_VAL=\"123\""
|
59
|
+
ENV.delete('TEST_VAL')
|
60
|
+
end
|
61
|
+
|
62
|
+
after do
|
63
|
+
ENV.delete('TEST_VAL')
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with the start command" do
|
67
|
+
before do
|
68
|
+
subject.command = 'start'
|
69
|
+
end
|
70
|
+
|
71
|
+
it "starts the docker machine" do
|
72
|
+
subject.run
|
73
|
+
expect(@system_commands).to eq ['docker-machine start default']
|
74
|
+
expect(ENV['TEST_VAL']).to eq '123'
|
75
|
+
end
|
76
|
+
|
77
|
+
it "returns true" do
|
78
|
+
expect(subject.run).to be_truthy
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "with the stop command" do
|
83
|
+
before do
|
84
|
+
subject.command = 'stop'
|
85
|
+
end
|
86
|
+
|
87
|
+
it "does not send a message to docker machine" do
|
88
|
+
subject.run
|
89
|
+
expect(@system_commands).to eq []
|
90
|
+
expect(ENV['TEST_VAL']).to be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns true" do
|
94
|
+
expect(subject.run).to be_truthy
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "with no command" do
|
100
|
+
before do
|
101
|
+
subject.command = nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it "logs error messages" do
|
105
|
+
subject.run
|
106
|
+
expect(@log_entries).to eq [
|
107
|
+
"You must provide a command",
|
108
|
+
"Run rspec help services for more information"
|
109
|
+
]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "returns false" do
|
113
|
+
expect(subject.run).to be_falsey
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "with an invalid command" do
|
118
|
+
before do
|
119
|
+
subject.command = 'foo'
|
120
|
+
end
|
121
|
+
|
122
|
+
it "logs error messages" do
|
123
|
+
subject.run
|
124
|
+
expect(@log_entries).to eq [
|
125
|
+
"foo is not a valid docker command",
|
126
|
+
"Run rspec help services for more information"
|
127
|
+
]
|
128
|
+
end
|
129
|
+
|
130
|
+
it "returns false" do
|
131
|
+
expect(subject.run).to be_falsey
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RubyYacht::Runner::Shell do
|
4
|
+
include DockerCommandSpec
|
5
|
+
|
6
|
+
describe "command information" do
|
7
|
+
specify { expect(described_class.command).to eq 'shell' }
|
8
|
+
specify { expect(described_class.description).to eq 'Open a shell in a container' }
|
9
|
+
|
10
|
+
describe "option parser" do
|
11
|
+
it "has the usage banner" do
|
12
|
+
expect(subject.option_parser.banner).to eq "Usage: rspec shell [options] [APP] [command]"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has the usage summary" do
|
16
|
+
usage = ["\n"]
|
17
|
+
usage << "The command is optional. If you omit it, this will open a bash shell\n"
|
18
|
+
usage << "\n"
|
19
|
+
usage << "Options:\n"
|
20
|
+
usage << " -p, --project PROJECT The project with the app we are opening the sell in. Default: apollo\n"
|
21
|
+
expect(subject.option_parser.summarize).to eq usage
|
22
|
+
end
|
23
|
+
|
24
|
+
it "takes the project from the command line" do
|
25
|
+
arguments = ["-p", "jupiter", "venus"]
|
26
|
+
subject.option_parser.parse!(arguments)
|
27
|
+
expect(subject.project_name).to eq :jupiter
|
28
|
+
expect(arguments).to eq ["venus"]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "parse_positional_arguments" do
|
33
|
+
it "takes the app from the command line" do
|
34
|
+
subject.parse_positional_arguments(["venus", "rails", "c"])
|
35
|
+
expect(subject.app).to eq "venus"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "takes the command from the command line" do
|
39
|
+
subject.parse_positional_arguments(["venus", "rails", "c"])
|
40
|
+
expect(subject.command).to eq "rails c"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "defaults the command to bash" do
|
44
|
+
subject.parse_positional_arguments(["venus"])
|
45
|
+
expect(subject.command).to eq "bash"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "run behavior" do
|
51
|
+
before do
|
52
|
+
subject.app = 'saturn'
|
53
|
+
subject.command = 'rails c'
|
54
|
+
RubyYacht.configure_second_test_project
|
55
|
+
allow(subject).to receive :exec
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "default_project" do
|
59
|
+
it "is the first project defined" do
|
60
|
+
expect(subject.default_project.name).to eq :apollo
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "opens the shell in docker" do
|
65
|
+
subject.run
|
66
|
+
expect(subject).to have_received(:exec).with("docker exec -it apollo-saturn bash -c 'cd /var/code; TERM=xterm rails c'")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "returns true" do
|
70
|
+
expect(subject.run).to be_truthy
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with no app" do
|
74
|
+
before do
|
75
|
+
subject.app = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "logs an error" do
|
79
|
+
subject.run
|
80
|
+
expect(@log_entries).to eq [
|
81
|
+
"You must provide an app name",
|
82
|
+
"Run rspec help shell for more information"
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
it "returns false" do
|
87
|
+
expect(subject.run).to be_falsey
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "with a specific project" do
|
92
|
+
before do
|
93
|
+
subject.project_name = :jupiter
|
94
|
+
end
|
95
|
+
|
96
|
+
it "opens the shell in that project" do
|
97
|
+
subject.run
|
98
|
+
expect(subject).to have_received(:exec).with("docker exec -it jupiter-saturn bash -c 'cd /var/code; TERM=xterm rails c'")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "returns true" do
|
102
|
+
expect(subject.run).to be_truthy
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "with an invalid project name" do
|
107
|
+
before do
|
108
|
+
subject.project_name = 'foo'
|
109
|
+
end
|
110
|
+
|
111
|
+
it "logs an error" do
|
112
|
+
subject.run
|
113
|
+
expect(@log_entries).to eq [
|
114
|
+
"There is no project named foo"
|
115
|
+
]
|
116
|
+
end
|
117
|
+
|
118
|
+
it "returns false" do
|
119
|
+
expect(subject.run).to be_falsey
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
describe RubyYacht::Runner::UpdateHosts do
|
5
|
+
include DockerCommandSpec
|
6
|
+
|
7
|
+
describe "command information" do
|
8
|
+
specify { expect(described_class.command).to eq 'update_hosts' }
|
9
|
+
specify { expect(described_class.description).to eq 'Add entries for your app domains to your hosts file' }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "current_host_contents" do
|
13
|
+
it "is the contents of the hosts file" do
|
14
|
+
expect(subject.current_host_contents).to eq File.read('/etc/hosts')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "run behavior" do
|
19
|
+
before do
|
20
|
+
allow(subject).to receive("current_host_contents").and_return(<<-EOS.gsub(/^ +/, '')
|
21
|
+
# Local information
|
22
|
+
127.0.0.1 localhost
|
23
|
+
|
24
|
+
# Database server
|
25
|
+
|
26
|
+
40.1.30.10 db1.test.com
|
27
|
+
EOS
|
28
|
+
)
|
29
|
+
|
30
|
+
allow(subject).to receive("get_machine_info").with('.Driver.IPAddress').and_return('192.168.1.27')
|
31
|
+
Timecop.freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
after do
|
35
|
+
FileUtils.rm(File.join('tmp', 'hosts'))
|
36
|
+
Timecop.return
|
37
|
+
end
|
38
|
+
|
39
|
+
it "adds the entries to the hosts file in the tmp folder" do
|
40
|
+
subject.run
|
41
|
+
expect(File.exist?(File.join('tmp', 'hosts'))).to be_truthy
|
42
|
+
|
43
|
+
contents = File.read(File.join('tmp', 'hosts'))
|
44
|
+
expect(contents).to eq <<-EOS.gsub(/^ +/, '').strip
|
45
|
+
# Local information
|
46
|
+
127.0.0.1 localhost
|
47
|
+
|
48
|
+
# Database server
|
49
|
+
|
50
|
+
40.1.30.10 db1.test.com
|
51
|
+
|
52
|
+
# apollo docker containers
|
53
|
+
192.168.1.27 apollo.test.com
|
54
|
+
192.168.1.27 mars.apollo.test.com
|
55
|
+
192.168.1.27 saturn.apollo.test.com
|
56
|
+
EOS
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
it "copies the hosts file to a backup, and the tmp hosts file to the hosts file" do
|
61
|
+
timestamp = Time.now.utc.strftime('%Y%m%d%H%M%S')
|
62
|
+
subject.run
|
63
|
+
expect(@system_commands).to eq ["sudo cp /etc/hosts /etc/hosts.#{timestamp}.backup", "sudo mv tmp/hosts /etc/hosts"]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns true" do
|
67
|
+
expect(subject.run).to be_truthy
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with existing entries in the hosts file" do
|
71
|
+
before do
|
72
|
+
allow(subject).to receive("current_host_contents").and_return(<<-EOS.gsub(/^ +/, '')
|
73
|
+
# Local information
|
74
|
+
127.0.0.1 localhost
|
75
|
+
|
76
|
+
# Database server
|
77
|
+
|
78
|
+
40.1.30.10 db1.test.com
|
79
|
+
|
80
|
+
# apollo docker containers
|
81
|
+
192.168.1.24 apollo.test.com
|
82
|
+
192.168.1.24 mars.apollo.test.com
|
83
|
+
192.168.1.24 venus.apollo.test.com
|
84
|
+
EOS
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "replaces the existing entries with the correct entries" do
|
89
|
+
subject.run
|
90
|
+
|
91
|
+
contents = File.read(File.join('tmp', 'hosts'))
|
92
|
+
expect(contents).to eq <<-EOS.gsub(/^ +/, '').strip
|
93
|
+
# Local information
|
94
|
+
127.0.0.1 localhost
|
95
|
+
|
96
|
+
# Database server
|
97
|
+
|
98
|
+
40.1.30.10 db1.test.com
|
99
|
+
|
100
|
+
# apollo docker containers
|
101
|
+
192.168.1.27 apollo.test.com
|
102
|
+
192.168.1.27 mars.apollo.test.com
|
103
|
+
192.168.1.27 saturn.apollo.test.com
|
104
|
+
EOS
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "with no address from docker machine" do
|
109
|
+
before do
|
110
|
+
allow(subject).to receive("get_machine_info").with('.Driver.IPAddress').and_return('')
|
111
|
+
end
|
112
|
+
|
113
|
+
it "points the domains to localhost" do
|
114
|
+
subject.run
|
115
|
+
|
116
|
+
contents = File.read(File.join('tmp', 'hosts'))
|
117
|
+
expect(contents).to eq <<-EOS.gsub(/^ +/, '').strip
|
118
|
+
# Local information
|
119
|
+
127.0.0.1 localhost
|
120
|
+
|
121
|
+
# Database server
|
122
|
+
|
123
|
+
40.1.30.10 db1.test.com
|
124
|
+
|
125
|
+
# apollo docker containers
|
126
|
+
127.0.0.1 apollo.test.com
|
127
|
+
127.0.0.1 mars.apollo.test.com
|
128
|
+
127.0.0.1 saturn.apollo.test.com
|
129
|
+
EOS
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "with multiple projects" do
|
134
|
+
before do
|
135
|
+
RubyYacht.configure_second_test_project
|
136
|
+
end
|
137
|
+
|
138
|
+
it "creates entries for both projects" do
|
139
|
+
subject.run
|
140
|
+
|
141
|
+
contents = File.read(File.join('tmp', 'hosts'))
|
142
|
+
expect(contents).to eq <<-EOS.gsub(/^ +/, '').strip
|
143
|
+
# Local information
|
144
|
+
127.0.0.1 localhost
|
145
|
+
|
146
|
+
# Database server
|
147
|
+
|
148
|
+
40.1.30.10 db1.test.com
|
149
|
+
|
150
|
+
# apollo docker containers
|
151
|
+
192.168.1.27 apollo.test.com
|
152
|
+
192.168.1.27 mars.apollo.test.com
|
153
|
+
192.168.1.27 saturn.apollo.test.com
|
154
|
+
|
155
|
+
# jupiter docker containers
|
156
|
+
192.168.1.27 jupiter.test.com
|
157
|
+
192.168.1.27 venus.jupiter.test.com
|
158
|
+
192.168.1.27 saturn.jupiter.test.com
|
159
|
+
EOS
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
data/spec/spec_helper.rb
ADDED