navyrb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module Navy
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'navy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "navyrb"
8
+ spec.version = Navy::VERSION
9
+ spec.authors = ["Navy Project"]
10
+ spec.email = ["mail@navyproject.com"]
11
+ spec.summary = %q{Navy library for ruby}
12
+ spec.description = %q{Provides utilities for navy project}
13
+ spec.homepage = ""
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.6"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "webmock"
22
+ end
@@ -0,0 +1,171 @@
1
+ require 'spec_helper'
2
+
3
+ describe Navy::AppContainerBuilder do
4
+ let(:app) do
5
+ app = double(:name => 'the_app',
6
+ :image => 'the_image',
7
+ :linked_apps => [],
8
+ :dependencies => [],
9
+ :env_var? => false,
10
+ :proxy_to? => false,
11
+ :modes => {"themode" => "the mode command", "other" => "other command"},
12
+ :volumes_from => [])
13
+ app
14
+ end
15
+
16
+ let(:config) do
17
+ config = double :environment => "config_env",
18
+ :docker_args => nil,
19
+ :pre_tasks => [],
20
+ :post_tasks => []
21
+ allow(config).to receive(:container_name) do |name, options|
22
+ convoy = options[:convoy]
23
+ mode = options[:mode]
24
+ scale = options[:scale]
25
+ name = [convoy, name, mode, scale].compact.join '_'
26
+ "container_for_#{name}"
27
+ end
28
+ config
29
+ end
30
+
31
+ let(:options) { {:convoy => 'convoy_id', :cluster => 'the-cluster.com', :mode => 'themode', :scale => 3} }
32
+
33
+ subject do
34
+ described_class.new(app, config, options).build
35
+ end
36
+
37
+ describe "#dependencies" do
38
+ context 'with dependencies' do
39
+ before :each do
40
+ allow(app).to receive(:dependencies).with(config).and_return(['dep1', 'dep2'])
41
+ end
42
+
43
+ it "returns array of container names depended on" do
44
+ expect(subject.dependencies).to eq ['container_for_convoy_id_dep1', 'container_for_convoy_id_dep2']
45
+ end
46
+ end
47
+
48
+ context 'with pre tasks' do
49
+ before :each do
50
+ allow(config).to receive(:pre_tasks) { |app| ["pre1_#{app}", "pre2_#{app}"] }
51
+ end
52
+
53
+ it "includes the task containers" do
54
+ expect(subject.dependencies).to eq ['container_for_convoy_id_the_app_pretasks']
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#specification" do
60
+ let(:spec) { subject.specification }
61
+
62
+ it "gives needed details to bring up the container" do
63
+ expect(spec[:container_name]).to eq "container_for_convoy_id_the_app_themode_3"
64
+ expect(spec[:name]).to eq "the_app"
65
+ expect(spec[:image]).to eq "the_image"
66
+ expect(spec[:type]).to eq "application"
67
+ expect(spec[:mode]).to eq "themode"
68
+ expect(spec[:cmd]).to eq "the mode command"
69
+ #expect(spec[:sha]).to eq "todo"
70
+ end
71
+
72
+ describe "Application Links" do
73
+ before :each do
74
+ expect(app).to receive(:linked_apps).with(config).and_return(['app1', 'app2'])
75
+ end
76
+
77
+ it "sets an environment variable for the host" do
78
+ env = spec[:env]
79
+
80
+ expect(env['APP1_HOST_ADDR']).to eq "https://convoy_id-app1-the-cluster.com"
81
+ expect(env['APP2_HOST_ADDR']).to eq "https://convoy_id-app2-the-cluster.com"
82
+ end
83
+
84
+ it "links to the host proxy" do
85
+ links = spec[:links]
86
+ expect(links).to include ['host_proxy', 'convoy_id-app1-the-cluster.com']
87
+ expect(links).to include ['host_proxy', 'convoy_id-app2-the-cluster.com']
88
+ end
89
+ end
90
+
91
+ describe "Dependency Links" do
92
+ before :each do
93
+ expect(app).to receive(:dependencies).with(config).and_return(['dep1', 'dep2'])
94
+ end
95
+
96
+ it "links to the container" do
97
+ links = spec[:links]
98
+ expect(links).to include ['container_for_convoy_id_dep1', 'dep1']
99
+ expect(links).to include ['container_for_convoy_id_dep2', 'dep2']
100
+ end
101
+ end
102
+
103
+ describe "Environment" do
104
+ context "when there's an env_variable" do
105
+ before :each do
106
+ expect(app).to receive(:env_var?) { true }
107
+ expect(app).to receive(:env_var) { "THE_ENV_VAR" }
108
+ end
109
+
110
+ it "sets an environment variable with the config's environment" do
111
+ env = spec[:env]
112
+ expect(env['THE_ENV_VAR']).to eq 'config_env'
113
+ end
114
+ end
115
+
116
+ context "when there's no env variable" do
117
+ it "sets no environment variable" do
118
+ env = spec[:env]
119
+ expect(env['THE_ENV_VAR']).to be_nil
120
+ end
121
+ end
122
+ end
123
+
124
+ describe "Proxy" do
125
+ context "with a proxy setting" do
126
+ before :each do
127
+ expect(app).to receive(:proxy_to?) { true }
128
+ expect(app).to receive(:proxy_port) { 1234 }
129
+ end
130
+
131
+ it "adds a VIRTUAL_HOST variable for the application" do
132
+ env = spec[:env]
133
+ expect(env['VIRTUAL_HOST']).to eq 'convoy_id-the_app-the-cluster.com'
134
+ end
135
+
136
+ it "adds a VIRTUAL_PORT variable for the application" do
137
+ env = spec[:env]
138
+ expect(env['VIRTUAL_PORT']).to eq 1234
139
+ end
140
+ end
141
+
142
+ context "with no proxy" do
143
+ it "adds no proxy variables" do
144
+ env = spec[:env]
145
+ expect(env.keys.detect { |c| c.match /VIRTUAL/ }).to be_nil
146
+ end
147
+ end
148
+ end
149
+
150
+ describe "Volumes" do
151
+ before :each do
152
+ expect(app).to receive(:volumes_from).and_return(['fromvol1', 'fromvol2'])
153
+ end
154
+
155
+ it "adds any given volumes from" do
156
+ vols = spec[:volumes_from]
157
+ expect(vols).to eq ['fromvol1', 'fromvol2']
158
+ end
159
+ end
160
+
161
+ describe "Docker Flags" do
162
+ before :each do
163
+ expect(config).to receive(:docker_args).and_return('-some flags for docker')
164
+ end
165
+
166
+ it "adds them to the specification" do
167
+ expect(spec[:docker_args]).to eq "-some flags for docker"
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe Navy::Application do
4
+ let(:config) do
5
+ cfg = Navy::Configuration.from_string <<-YAML
6
+ apps:
7
+ app1:
8
+ image: given_image
9
+ links:
10
+ - dep1
11
+ - otherapp1
12
+ - dep3
13
+ modes:
14
+ mode1: command1 to run
15
+ mode2: command2 to run
16
+ proxy_to:
17
+ mode1: 1234
18
+ env_var: SOME_ENV
19
+ volumes_from:
20
+ - somevol
21
+ - othervol
22
+ otherapp1:
23
+ image: foo
24
+ otherapp2:
25
+ image: bar
26
+ environments:
27
+ env:
28
+ dependencies:
29
+ dep1:
30
+ proxy_to: 9999
31
+ dep2:
32
+ dep3:
33
+ pre:
34
+ - pretask1
35
+ - pretask2
36
+ post:
37
+ docker:
38
+ app1: --some argument
39
+ YAML
40
+ cfg.set_env('env')
41
+ cfg
42
+ end
43
+
44
+ subject { config.find_app 'app1' }
45
+
46
+ it "has given image" do
47
+ expect(subject.image).to eq "given_image"
48
+ end
49
+
50
+ it "has given modes" do
51
+ modes = subject.modes
52
+ expect(modes['mode1']).to eq "command1 to run"
53
+ expect(modes['mode2']).to eq "command2 to run"
54
+ end
55
+
56
+ it "has given volumes" do
57
+ vols = subject.volumes_from
58
+ expect(vols).to eq ['somevol', 'othervol']
59
+ end
60
+
61
+ describe "Dependencies" do
62
+ it "returns names of dependencies for the app" do
63
+ deps = subject.dependencies(config)
64
+ expect(deps).to eq ['dep1', 'dep3']
65
+ end
66
+ end
67
+
68
+ describe "Linked Apps" do
69
+ it "returns names of other applications the app should link to" do
70
+ deps = subject.linked_apps(config)
71
+ expect(deps).to eq ['otherapp1']
72
+ end
73
+ end
74
+
75
+ describe "Proxy settings" do
76
+ context "with modes" do
77
+ it "can have a proxy and a port" do
78
+ expect(subject.proxy_to?('mode1')).to be true
79
+ expect(subject.proxy_to?('mode2')).to be false
80
+
81
+ expect(subject.proxy_port('mode1')).to eq 1234
82
+ end
83
+ end
84
+
85
+ context "without modes" do
86
+ it "has the port" do
87
+ app = config.dependencies.detect {|d| d.name == 'dep1' }
88
+ expect(app.proxy_to?).to be
89
+ expect(app.proxy_port).to eq 9999
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "Env Variable" do
95
+ it "returns named env var" do
96
+ expect(subject.env_var?).to be true
97
+ expect(subject.env_var).to eq 'SOME_ENV'
98
+
99
+ app = config.find_app('otherapp1')
100
+ expect(app.env_var?).to be false
101
+ end
102
+ end
103
+
104
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe Navy::CommandBuilder do
4
+
5
+ let(:specification) do
6
+ {
7
+ :env => {"VAR1" => "val1", "VAR2" => "val2"},
8
+ :links => [["fromcontainer", "toalias"], ["othercontainer", "otheralias"]],
9
+ :volumes_from => ["somecontainer"],
10
+ :name => "theapp",
11
+ :container_name => "the_app_container_name",
12
+ :image => "the_image",
13
+ :docker_args => "other docker args",
14
+ :type => "application",
15
+ :cmd => "the specified command"
16
+ }
17
+ end
18
+
19
+ let(:container) do
20
+ Navy::Container.new :specification => specification
21
+ end
22
+
23
+ subject do
24
+ described_class.new container
25
+ end
26
+
27
+ describe "#build" do
28
+ let(:cmd) { subject.build }
29
+
30
+ context "when the type is application" do
31
+ it"runs the container in daemon mode" do
32
+ expect(cmd.first).to eq "docker run -d"
33
+ end
34
+ end
35
+
36
+ context "when the type is task" do
37
+ before :each do
38
+ container.specification[:type] = "task"
39
+ end
40
+
41
+ it"runs the container in throw away mode" do
42
+ expect(cmd.first).to eq "docker run --rm"
43
+ end
44
+ end
45
+
46
+ it "starts the appropriate image" do
47
+ expect(cmd[-2]).to eq "the_image"
48
+ end
49
+
50
+ it "executes specified command" do
51
+ expect(cmd[-1]).to eq "the specified command"
52
+ end
53
+
54
+ context "when there's a given command" do
55
+ let(:cmd) { subject.build :command => "the command to run" }
56
+
57
+ it"starts the image with overridden command" do
58
+ expect(cmd[-2]).to eq "the_image"
59
+ expect(cmd[-1]).to eq "the command to run"
60
+ end
61
+ end
62
+
63
+ it "gives the container specified name" do
64
+ expect(cmd).to include "--name the_app_container_name"
65
+ end
66
+
67
+ it "sets specified environment variables" do
68
+ expect(cmd).to include "-e=\"VAR1=val1\""
69
+ expect(cmd).to include "-e=\"VAR2=val2\""
70
+ end
71
+
72
+ it "sets specified links" do
73
+ expect(cmd).to include "--link=fromcontainer:toalias"
74
+ expect(cmd).to include "--link=othercontainer:otheralias"
75
+ end
76
+
77
+ it "uses volumes from specified" do
78
+ expect(cmd).to include "--volumes-from=somecontainer"
79
+ end
80
+
81
+ it "includes any additional docker args" do
82
+ expect(cmd).to include "other docker args"
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+
3
+ describe Navy::Configuration do
4
+
5
+ describe ".from_file" do
6
+ it "loads from the file" do
7
+ expect(YAML).to receive(:load_file).with('the_file.yml').and_return('YAML')
8
+ expect(described_class).to receive(:new).with('YAML')
9
+
10
+ described_class.from_file('the_file.yml')
11
+ end
12
+ end
13
+
14
+ let(:yaml) do
15
+ <<-YAML
16
+ apps:
17
+ app1:
18
+ app2:
19
+ environments:
20
+ one:
21
+ dependencies:
22
+ dep1:
23
+ dep2:
24
+ pre:
25
+ app1:
26
+ - pretask1
27
+ - pretask2
28
+ post:
29
+ docker:
30
+ app1: --some argument
31
+ two:
32
+ dependencies:
33
+ twodep1:
34
+ twodep2:
35
+ post:
36
+ app2:
37
+ - posttask1
38
+ - posttask2
39
+ docker:
40
+ app1: --different argument
41
+ YAML
42
+ end
43
+
44
+ subject { described_class.from_string(yaml) }
45
+
46
+ describe "#container_name" do
47
+ it "returns the name the container will have" do
48
+ name = subject.container_name('app1', :convoy => 'convoy')
49
+ expect(name).to eq 'convoy_app1'
50
+ end
51
+
52
+ it "uses given mode" do
53
+ name = subject.container_name('app1', :convoy => 'convoy', :mode => 'the_mode')
54
+ expect(name).to eq 'convoy_app1_the_mode'
55
+ end
56
+
57
+ it "uses given scale" do
58
+ name = subject.container_name('app1', :convoy => 'convoy', :scale => 2)
59
+ expect(name).to eq 'convoy_app1_2'
60
+ end
61
+ end
62
+
63
+ describe "Applications" do
64
+
65
+ describe "#apps" do
66
+ it "yields an application for each application in the config" do
67
+ apps = []
68
+ subject.apps do |app|
69
+ apps << app
70
+ end
71
+
72
+ names = apps.map &:name
73
+
74
+ expect(names).to include 'app1'
75
+ expect(names).to include 'app2'
76
+ end
77
+ end
78
+
79
+ describe "#applications" do
80
+ it "returns array of app names" do
81
+ expect(subject.applications).to eq ['app1', 'app2']
82
+ end
83
+ end
84
+
85
+ describe "#find_app" do
86
+ it "finds the an application by the given name" do
87
+ apps = []
88
+ subject.apps { |a| apps << a }
89
+
90
+ expect(subject.find_app(apps[1].name)).to equal apps[1]
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ describe "Dependencies" do
97
+ before :each do
98
+ subject.set_env('one')
99
+ end
100
+
101
+ describe "#dependencies" do
102
+ it "yields and application for each defined dependency in the config" do
103
+ apps = []
104
+ subject.dependencies { |a| apps << a }
105
+
106
+ names = apps.map &:name
107
+
108
+ expect(names).to include 'dep1'
109
+ expect(names).to include 'dep2'
110
+ end
111
+
112
+ it "uses the given environment" do
113
+ subject.set_env('two')
114
+ apps = []
115
+ subject.dependencies { |a| apps << a.name }
116
+
117
+ expect(apps).to eq ['twodep1', 'twodep2']
118
+ end
119
+ end
120
+ end
121
+
122
+ describe "Tasks" do
123
+ before :each do
124
+ subject.set_env('one')
125
+ end
126
+
127
+ describe "#pre_tasks" do
128
+ it "returns an array of tasks for given app name" do
129
+ cmds = subject.pre_tasks('app1')
130
+ expect(cmds).to eq ['pretask1', 'pretask2']
131
+ end
132
+
133
+ it "uses the environment" do
134
+ subject.set_env('two')
135
+ cmds = subject.pre_tasks('app1')
136
+ expect(cmds).to be_empty
137
+ end
138
+ end
139
+
140
+ describe "#post_tasks" do
141
+ it "returns an array of tasks for given app name" do
142
+ subject.set_env('two')
143
+ cmds = subject.post_tasks('app2')
144
+ expect(cmds).to eq ['posttask1', 'posttask2']
145
+ end
146
+
147
+ it "uses the environment" do
148
+ cmds = subject.post_tasks('app2')
149
+ expect(cmds).to be_empty
150
+ end
151
+ end
152
+ end
153
+
154
+ describe "Docker Arguments" do
155
+ before :each do
156
+ subject.set_env('one')
157
+ end
158
+
159
+ it "gives the docker args from the environment for given app" do
160
+ expect(subject.docker_args('app1')).to eq "--some argument"
161
+ subject.set_env('two')
162
+ expect(subject.docker_args('app1')).to eq "--different argument"
163
+ end
164
+ end
165
+ end