navyrb 0.0.1

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.
@@ -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