baha 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +15 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +156 -0
- data/Rakefile +21 -0
- data/baha.gemspec +31 -0
- data/bin/baha +5 -0
- data/example/.gitignore +1 -0
- data/example/base/init.sh.erb +11 -0
- data/example/base/test-template.erb +22 -0
- data/example/example.yml +54 -0
- data/example/rvm/image.yml +33 -0
- data/example/rvm/init.sh.erb +12 -0
- data/lib/baha/builder.rb +130 -0
- data/lib/baha/cli.rb +69 -0
- data/lib/baha/config.rb +142 -0
- data/lib/baha/container_options/cmd.rb +33 -0
- data/lib/baha/container_options/entrypoint.rb +10 -0
- data/lib/baha/container_options/env.rb +21 -0
- data/lib/baha/container_options/exposed_ports.rb +35 -0
- data/lib/baha/container_options/invalid_option_error.rb +15 -0
- data/lib/baha/container_options/option.rb +59 -0
- data/lib/baha/container_options/volumes.rb +24 -0
- data/lib/baha/container_options.rb +38 -0
- data/lib/baha/image.rb +154 -0
- data/lib/baha/log.rb +80 -0
- data/lib/baha/pre_build/command.rb +51 -0
- data/lib/baha/pre_build/download.rb +28 -0
- data/lib/baha/pre_build/template.rb +48 -0
- data/lib/baha/pre_build.rb +47 -0
- data/lib/baha/version.rb +3 -0
- data/lib/baha/workspace.rb +13 -0
- data/lib/baha.rb +5 -0
- data/spec/builder_spec.rb +103 -0
- data/spec/config_spec.rb +93 -0
- data/spec/container_options/cmd_spec.rb +46 -0
- data/spec/container_options/entrypoint_spec.rb +32 -0
- data/spec/container_options/env_spec.rb +26 -0
- data/spec/container_options/exposed_ports_spec.rb +32 -0
- data/spec/container_options/option_spec.rb +43 -0
- data/spec/container_options/volumes_spec.rb +25 -0
- data/spec/fixtures/base_image.yml +5 -0
- data/spec/fixtures/config_build.yml +12 -0
- data/spec/fixtures/config_build_image.yml +10 -0
- data/spec/fixtures/config_eachimage.yml +12 -0
- data/spec/fixtures/config_embedded.yml +11 -0
- data/spec/fixtures/config_include.yml +7 -0
- data/spec/fixtures/config_ssl.yml +13 -0
- data/spec/fixtures/config_sslpath.yml +11 -0
- data/spec/helpers/docker_helpers.rb +31 -0
- data/spec/image_spec.rb +167 -0
- data/spec/log_spec.rb +89 -0
- data/spec/options_spec.rb +52 -0
- data/spec/pre_build/command_spec.rb +69 -0
- data/spec/pre_build/download_spec.rb +43 -0
- data/spec/pre_build/template_spec.rb +55 -0
- data/spec/pre_build_spec.rb +29 -0
- data/spec/spec_helper.rb +39 -0
- metadata +255 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'baha/pre_build'
|
2
|
+
require 'erb'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
class Baha::PreBuild::Module::Template
|
6
|
+
LOG = Baha::Log.for_name("Module::Template")
|
7
|
+
|
8
|
+
class ErbBinding < OpenStruct
|
9
|
+
def initialize(hash,config)
|
10
|
+
super(hash)
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
def get_binding
|
14
|
+
binding()
|
15
|
+
end
|
16
|
+
def render(file)
|
17
|
+
rfile = @config.resolve_file(file) || @config.resolve_file(File.join(name,file))
|
18
|
+
if rfile
|
19
|
+
ERB.new(File.read(rfile),0,'-').result(binding)
|
20
|
+
else
|
21
|
+
raise ArgumentError.new("Template unable to render #{file}: not found")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.execute(mod)
|
27
|
+
LOG.debug("template(#{mod.args.inspect})")
|
28
|
+
|
29
|
+
template = mod.args['template']
|
30
|
+
src = mod.config.resolve_file(mod.args['template'])
|
31
|
+
dest = mod.image.workspace + mod.args['dest']
|
32
|
+
raise ArgumentError.new("Unable to find template file #{template}") if src.nil?
|
33
|
+
LOG.info { "Loading template #{src}" }
|
34
|
+
template_str = File.read(src)
|
35
|
+
erb = ERB.new(template_str,0,'-')
|
36
|
+
environment = mod.image.env
|
37
|
+
environment.merge!(Hash[mod.args.map{|k,v| [k.to_sym, v]}])
|
38
|
+
LOG.debug { "template environment: #{environment.inspect}" }
|
39
|
+
LOG.info { "Writing to #{dest}" }
|
40
|
+
File.open(dest,"w") do |f|
|
41
|
+
f.write(erb.result(ErbBinding.new(environment,mod.config).get_binding))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Baha::PreBuild::Module.register(:template) do |mod|
|
47
|
+
Baha::PreBuild::Module::Template.execute(mod)
|
48
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Baha::PreBuild
|
2
|
+
LOG = Baha::Log.for_name(self.class.name)
|
3
|
+
class ModuleNotFoundError < StandardError
|
4
|
+
attr_reader :task
|
5
|
+
def initialize(task)
|
6
|
+
super("Could not find a module that could parse #{task.inspect}")
|
7
|
+
@task = task
|
8
|
+
end
|
9
|
+
end
|
10
|
+
class Module
|
11
|
+
class << self
|
12
|
+
@@modules = []
|
13
|
+
|
14
|
+
def register(name, options = {}, &block)
|
15
|
+
LOG.debug { "register module #{name} (#{options.inspect})" }
|
16
|
+
@@modules << name
|
17
|
+
name = name.intern
|
18
|
+
send(:define_singleton_method,"module_#{name}",&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute(task)
|
22
|
+
@@modules.each do |mod|
|
23
|
+
if task.has_key?(mod.to_s)
|
24
|
+
LOG.info { "Executing module #{mod}" }
|
25
|
+
method = "module_#{mod}".intern
|
26
|
+
self.send(method, Module.new(task))
|
27
|
+
return
|
28
|
+
end
|
29
|
+
end
|
30
|
+
raise ModuleNotFoundError.new(task)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :config, :image, :args
|
35
|
+
|
36
|
+
def initialize(task)
|
37
|
+
@config = task.delete(:config)
|
38
|
+
@image = task.delete(:image)
|
39
|
+
@args = task
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'baha/pre_build/download'
|
46
|
+
require 'baha/pre_build/template'
|
47
|
+
require 'baha/pre_build/command'
|
data/lib/baha/version.rb
ADDED
data/lib/baha.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/config'
|
3
|
+
require 'baha/builder'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
describe Baha::Builder do
|
7
|
+
let(:config) do
|
8
|
+
Baha::Config.load(fixture('config_build.yml'))
|
9
|
+
end
|
10
|
+
subject { described_class.new(config) }
|
11
|
+
|
12
|
+
describe "#new" do
|
13
|
+
it 'loads config file from filename' do
|
14
|
+
expect { described_class.new(fixture('config_build.yml')) }.not_to raise_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#inspect" do
|
19
|
+
its(:inspect) { should match(/^Baha::Builder<(@[a-z0-9_]+=.*)+>$/) }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#build!" do
|
23
|
+
before do
|
24
|
+
allow_any_instance_of(Baha::Config).to receive(:init_docker!)
|
25
|
+
allow(Baha::PreBuild::Module).to receive(:execute)
|
26
|
+
allow(FileUtils).to receive(:mkdir_p)
|
27
|
+
end
|
28
|
+
context "when no update needed" do
|
29
|
+
before do
|
30
|
+
allow_any_instance_of(Baha::Image).to receive(:needs_update?).and_return(false)
|
31
|
+
subject.build!
|
32
|
+
end
|
33
|
+
it 'does not execute pre_build' do
|
34
|
+
expect(Baha::PreBuild::Module).not_to have_received(:execute)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
context "when update needed" do
|
38
|
+
let(:container) {
|
39
|
+
double('container')
|
40
|
+
}
|
41
|
+
let(:image) {
|
42
|
+
double('image')
|
43
|
+
}
|
44
|
+
let(:image2) {
|
45
|
+
double('image2')
|
46
|
+
}
|
47
|
+
before do
|
48
|
+
allow_any_instance_of(Baha::Image).to receive(:needs_update?).and_return(true)
|
49
|
+
allow_any_instance_of(Baha::Image).to receive(:parent_id).and_return('AAAA')
|
50
|
+
allow(Docker::Container).to receive(:create).and_return(container)
|
51
|
+
allow(container).to receive(:start)
|
52
|
+
allow(container).to receive(:stop)
|
53
|
+
allow(container).to receive(:streaming_logs).with({"stdout"=>true, "stderr"=>true, "follow"=>true, "timestamps"=>false}).and_yield(:stdout,"console message").and_yield(:stderr,"error line")
|
54
|
+
allow(container).to receive(:wait).with(1200).and_return({'StatusCode' => 0})
|
55
|
+
allow(container).to receive(:commit).and_return(image)
|
56
|
+
allow(image).to receive(:id).and_return('BBBB')
|
57
|
+
allow(Docker::Image).to receive(:get).with('BBBB').and_return(image)
|
58
|
+
allow(image).to receive(:tag)
|
59
|
+
allow(container).to receive(:remove)
|
60
|
+
end
|
61
|
+
it 'executes pre_build step' do
|
62
|
+
subject.build!
|
63
|
+
expect(Baha::PreBuild::Module).to have_received(:execute).twice.with(hash_including('download' => "http://www.google.com"))
|
64
|
+
end
|
65
|
+
it 'creates containers' do
|
66
|
+
subject.build!
|
67
|
+
expect(Docker::Container).to have_received(:create).twice.with({"Image"=>"AAAA", "Cmd"=>["/bin/bash", "./init.sh"], "Workingdir"=>"/.baha"})
|
68
|
+
end
|
69
|
+
it 'starts containers' do
|
70
|
+
subject.build!
|
71
|
+
expect(container).to have_received(:start).twice
|
72
|
+
end
|
73
|
+
it 'commits containers' do
|
74
|
+
subject.build!
|
75
|
+
expect(container).to have_received(:commit).with({"run"=>{"ExposedPorts"=>{"8080/tcp"=>{}}}}).ordered
|
76
|
+
expect(container).to have_received(:commit).with({'run' => {}}).ordered
|
77
|
+
end
|
78
|
+
it 'tags image' do
|
79
|
+
subject.build!
|
80
|
+
expect(image).to have_received(:tag).with({:repo=>"docker.example.com/baha/base", :tag=>"1.0.0"})
|
81
|
+
expect(image).to have_received(:tag).with({:repo=>"docker.example.com/baha/base", :tag=>"latest"})
|
82
|
+
expect(image).to have_received(:tag).with({:repo=>"base", :tag=>"1.0.0"})
|
83
|
+
expect(image).to have_received(:tag).with({:repo=>"base", :tag=>"latest"})
|
84
|
+
expect(image).to have_received(:tag).with({:repo=>"docker.example.com/baha/derived", :tag=>"1.0.0"})
|
85
|
+
expect(image).to have_received(:tag).with({:repo=>"docker.example.com/baha/derived", :tag=>"latest"})
|
86
|
+
expect(image).to have_received(:tag).with({:repo=>"derived", :tag=>"1.0.0"})
|
87
|
+
expect(image).to have_received(:tag).with({:repo=>"derived", :tag=>"latest"})
|
88
|
+
end
|
89
|
+
context "when error building image" do
|
90
|
+
before do
|
91
|
+
allow(container).to receive(:wait).with(1200).and_return({'StatusCode' => 1})
|
92
|
+
end
|
93
|
+
it { expect { subject.build! }.to raise_error(Baha::Builder::BuildError) }
|
94
|
+
end
|
95
|
+
context "when exception building image" do
|
96
|
+
before do
|
97
|
+
allow(container).to receive(:wait).with(1200).and_raise(Exception)
|
98
|
+
end
|
99
|
+
it { expect { subject.build! }.to raise_error(Baha::Builder::BuildError) }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/config'
|
3
|
+
|
4
|
+
describe Baha::Config do
|
5
|
+
before do
|
6
|
+
ENV['DOCKER_CERT_PATH'] = nil
|
7
|
+
ENV['DOCKER_TLS_VERIFY'] = nil
|
8
|
+
end
|
9
|
+
describe "#load" do
|
10
|
+
context "with embedded images" do
|
11
|
+
subject { Baha::Config.load(fixture('config_embedded.yml')) }
|
12
|
+
its(:defaults) { should eq(
|
13
|
+
{
|
14
|
+
:parent=>"ubuntu:14.04.1",
|
15
|
+
:bind=>"/.baha",
|
16
|
+
:repository=>'docker.example.com/baha',
|
17
|
+
:maintainer => "Ishmael <ishmael@example.com>",
|
18
|
+
:command => ['/bin/bash','./init.sh'],
|
19
|
+
:timeout => 1200
|
20
|
+
})
|
21
|
+
}
|
22
|
+
its(:options) { should eq({}) }
|
23
|
+
its(:configdir) { should eq(fixture_path) }
|
24
|
+
its(:workspace) { should eq(fixture_path + 'workspace') }
|
25
|
+
end
|
26
|
+
context "with included image files" do
|
27
|
+
subject { Baha::Config.load(fixture('config_include.yml')) }
|
28
|
+
its(:defaults) { should eq(
|
29
|
+
{
|
30
|
+
:parent=>"ubuntu:14.04.1",
|
31
|
+
:bind=>"/.baha",
|
32
|
+
:repository=>'docker.example.com/baha',
|
33
|
+
:maintainer => "Ishmael <ishmael@example.com>",
|
34
|
+
:command => ['/bin/bash','./init.sh'],
|
35
|
+
:timeout => 1200
|
36
|
+
})
|
37
|
+
}
|
38
|
+
its(:options) { should eq({}) }
|
39
|
+
its(:configdir) { should eq(fixture_path) }
|
40
|
+
its(:workspace) { should eq(fixture_path + 'workspace') }
|
41
|
+
end
|
42
|
+
context "with DOCKER_CERT_PATH set" do
|
43
|
+
subject { Baha::Config.load(fixture('config_embedded.yml')) }
|
44
|
+
before do
|
45
|
+
ENV['DOCKER_CERT_PATH'] = '/tmp'
|
46
|
+
ENV['DOCKER_TLS_VERIFY'] = nil
|
47
|
+
end
|
48
|
+
its(:options) { should eq({:client_cert=>"/tmp/cert.pem", :client_key=>"/tmp/key.pem", :ssl_ca_file=>"/tmp/ca.pem", :ssl_verify_peer=>false}) }
|
49
|
+
its(:secure) { should eq(true) }
|
50
|
+
context "with DOCKER_TLS_VERIFY=1" do
|
51
|
+
before do
|
52
|
+
ENV['DOCKER_CERT_PATH'] = '/tmp'
|
53
|
+
ENV['DOCKER_TLS_VERIFY'] = '1'
|
54
|
+
end
|
55
|
+
its(:options) { should eq({:client_cert=>"/tmp/cert.pem", :client_key=>"/tmp/key.pem", :ssl_ca_file=>"/tmp/ca.pem", :ssl_verify_peer=>true}) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
context "with ssl in config" do
|
59
|
+
subject { Baha::Config.load(fixture('config_ssl.yml')) }
|
60
|
+
its(:options) { should eq({:client_cert=>"cert.pem", :client_key=>"key.pem", :ssl_ca_file=>"ca.pem", :ssl_verify_peer=>true}) }
|
61
|
+
its(:secure) { should eq(true) }
|
62
|
+
end
|
63
|
+
context "with ssl cert_path" do
|
64
|
+
subject { Baha::Config.load(fixture('config_sslpath.yml')) }
|
65
|
+
its(:options) { should eq({:client_cert=>"/ssl/cert.pem", :client_key=>"/ssl/key.pem", :ssl_ca_file=>"/ssl/ca.pem", :ssl_verify_peer=>true}) }
|
66
|
+
its(:secure) { should eq(true) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
describe "#init_docker!" do
|
70
|
+
subject { Baha::Config.load(fixture('config_ssl.yml')) }
|
71
|
+
before do
|
72
|
+
allow(Docker).to receive(:validate_version!)
|
73
|
+
subject.init_docker!
|
74
|
+
end
|
75
|
+
it { expect(Docker).to have_received(:validate_version!) }
|
76
|
+
it { expect(Docker.url).to eq('https://127.0.1.1:2375') }
|
77
|
+
it { expect(Docker.options).to eq({:client_cert=>"cert.pem", :client_key=>"key.pem", :ssl_ca_file=>"ca.pem", :ssl_verify_peer=>true}) }
|
78
|
+
end
|
79
|
+
describe "#inspect" do
|
80
|
+
subject { Baha::Config.load(fixture('config_embedded.yml')) }
|
81
|
+
its(:inspect) { should match(/^Baha::Config<(@[a-z0-9_]+=.*)+>$/) }
|
82
|
+
end
|
83
|
+
describe "#each_image" do
|
84
|
+
subject { Baha::Config.load(fixture('config_eachimage.yml')) }
|
85
|
+
it 'loads images it can find' do
|
86
|
+
images = []
|
87
|
+
subject.each_image do |image|
|
88
|
+
images << image
|
89
|
+
end
|
90
|
+
expect(images.size).to eq(2)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/container_options'
|
3
|
+
|
4
|
+
describe Baha::ContainerOptions::Cmd do
|
5
|
+
subject(:option) { described_class.new(["/bin/bash","-l"]) }
|
6
|
+
subject(:option2) { described_class.new('/bin/bash -l') }
|
7
|
+
describe 'validate!' do
|
8
|
+
subject(:invalid) { described_class.new(123) }
|
9
|
+
it 'validates on array values' do
|
10
|
+
expect { option.validate! }.to_not raise_error
|
11
|
+
end
|
12
|
+
it 'validates on string values' do
|
13
|
+
expect { option2.validate! }.to_not raise_error
|
14
|
+
end
|
15
|
+
it 'does not validate other values' do
|
16
|
+
expect { invalid.validate! }.to raise_error(Baha::ContainerOptions::InvalidOptionError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
describe 'apply' do
|
20
|
+
let(:expected) { { 'Cmd' => ["/bin/bash","-l"] } }
|
21
|
+
it 'applies array command' do
|
22
|
+
conf = {}
|
23
|
+
option.apply(conf)
|
24
|
+
expect(conf).to eq(expected)
|
25
|
+
end
|
26
|
+
it 'applies string command' do
|
27
|
+
conf = {}
|
28
|
+
option2.apply(conf)
|
29
|
+
expect(conf).to eq(expected)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
describe 'split_command' do
|
33
|
+
it 'splits on spaces' do
|
34
|
+
expect(described_class.split_command('/bin/bash -l')).to eq(['/bin/bash','-l'])
|
35
|
+
end
|
36
|
+
it 'splits on multiple spaces' do
|
37
|
+
expect(described_class.split_command('/bin/bash -l')).to eq(['/bin/bash','-l'])
|
38
|
+
end
|
39
|
+
it 'does not split quotes' do
|
40
|
+
expect(described_class.split_command('/bin/bash -l echo "Hello, World!"')).to eq(['/bin/bash','-l','echo','Hello, World!'])
|
41
|
+
end
|
42
|
+
it 'does not squash escaped quotes' do
|
43
|
+
expect(described_class.split_command('/bin/bash -l echo "Hello, ""World!"')).to eq(['/bin/bash','-l','echo','Hello, "World!'])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/container_options'
|
3
|
+
|
4
|
+
describe Baha::ContainerOptions::Entrypoint do
|
5
|
+
subject(:option) { described_class.new(["/bin/bash","-l"]) }
|
6
|
+
subject(:option2) { described_class.new('/bin/bash -l') }
|
7
|
+
describe 'validate!' do
|
8
|
+
subject(:invalid) { described_class.new(123) }
|
9
|
+
it 'validates on array values' do
|
10
|
+
expect { option.validate! }.to_not raise_error
|
11
|
+
end
|
12
|
+
it 'validates on string values' do
|
13
|
+
expect { option2.validate! }.to_not raise_error
|
14
|
+
end
|
15
|
+
it 'does not validate other values' do
|
16
|
+
expect { invalid.validate! }.to raise_error(Baha::ContainerOptions::InvalidOptionError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
describe 'apply' do
|
20
|
+
let(:expected) { { 'Entrypoint' => ["/bin/bash","-l"] } }
|
21
|
+
it 'applies array command' do
|
22
|
+
conf = {}
|
23
|
+
option.apply(conf)
|
24
|
+
expect(conf).to eq(expected)
|
25
|
+
end
|
26
|
+
it 'applies string command' do
|
27
|
+
conf = {}
|
28
|
+
option2.apply(conf)
|
29
|
+
expect(conf).to eq(expected)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/container_options'
|
3
|
+
|
4
|
+
describe Baha::ContainerOptions::Env do
|
5
|
+
subject(:option) { described_class.new({'KEY' => 'value'}) }
|
6
|
+
|
7
|
+
describe 'validate!' do
|
8
|
+
let(:invalid) { described_class.new('value') }
|
9
|
+
|
10
|
+
it 'validates on hash values' do
|
11
|
+
expect { option.validate! }.to_not raise_error
|
12
|
+
end
|
13
|
+
it 'does not validate non-hash values' do
|
14
|
+
expect { invalid.validate! }.to raise_error(Baha::ContainerOptions::InvalidOptionError)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'apply' do
|
19
|
+
let(:expected) { { 'Env' => ['KEY=value'] } }
|
20
|
+
it 'applies its key=value pair' do
|
21
|
+
conf = {}
|
22
|
+
option.apply(conf)
|
23
|
+
expect(conf).to eq(expected)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/container_options'
|
3
|
+
|
4
|
+
describe Baha::ContainerOptions::ExposedPorts do
|
5
|
+
subject(:option) { described_class.new([8080]) }
|
6
|
+
subject(:option2) { described_class.new(['8080/tcp']) }
|
7
|
+
describe 'validate!' do
|
8
|
+
subject(:invalid) { described_class.new(['wtf']) }
|
9
|
+
it 'validates on num values' do
|
10
|
+
expect { option.validate! }.to_not raise_error
|
11
|
+
end
|
12
|
+
it 'validates on string values' do
|
13
|
+
expect { option2.validate! }.to_not raise_error
|
14
|
+
end
|
15
|
+
it 'does not validate other values' do
|
16
|
+
expect { invalid.validate! }.to raise_error(Baha::ContainerOptions::InvalidOptionError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
describe 'apply' do
|
20
|
+
let(:expected) { { 'ExposedPorts' => { '8080/tcp' => {} } } }
|
21
|
+
it 'applies array command' do
|
22
|
+
conf = {}
|
23
|
+
option.apply(conf)
|
24
|
+
expect(conf).to eq(expected)
|
25
|
+
end
|
26
|
+
it 'applies string command' do
|
27
|
+
conf = {}
|
28
|
+
option2.apply(conf)
|
29
|
+
expect(conf).to eq(expected)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/container_options'
|
3
|
+
|
4
|
+
describe Baha::ContainerOptions::Option do
|
5
|
+
subject(:option) { described_class.new('hostname','value') }
|
6
|
+
let(:other) { described_class.new("hostname","value") }
|
7
|
+
let(:otherkey) { described_class.new("user","value") }
|
8
|
+
|
9
|
+
describe '#eql?' do
|
10
|
+
it 'is equal to same key' do
|
11
|
+
expect(option.eql?(other)).to eq(true)
|
12
|
+
end
|
13
|
+
it 'is not equal to other key' do
|
14
|
+
expect(option.eql?(otherkey)).to eq(false)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#validate!' do
|
19
|
+
it 'always validates' do
|
20
|
+
expect(option.validate!).to eq(true)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#apply' do
|
25
|
+
it 'applies its key/value pair' do
|
26
|
+
conf = {}
|
27
|
+
option.apply(conf)
|
28
|
+
expect(conf['Hostname']).to eq('value')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#inspect' do
|
33
|
+
its(:inspect) { should match(/Baha::ContainerOptions::Option<(@[a-z0-9_]+=.*)+>/) }
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'has a sym key' do
|
37
|
+
expect(option.key).to be_a(Symbol)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'has a value' do
|
41
|
+
expect(option.value).to eq('value')
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'baha/container_options'
|
3
|
+
|
4
|
+
describe Baha::ContainerOptions::Volumes do
|
5
|
+
subject(:option) { described_class.new(["/mnt/data","/mnt/logs"]) }
|
6
|
+
|
7
|
+
describe 'validate!' do
|
8
|
+
subject(:invalid) { described_class.new("value") }
|
9
|
+
it 'validates on hash values' do
|
10
|
+
expect { option.validate! }.to_not raise_error
|
11
|
+
end
|
12
|
+
it 'does not validate non-hash values' do
|
13
|
+
expect { invalid.validate! }.to raise_error(Baha::ContainerOptions::InvalidOptionError)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'apply' do
|
18
|
+
let(:expected) { { 'Volumes' => {'/mnt/data' => {}, '/mnt/logs' => {} } } }
|
19
|
+
it 'applies volume config' do
|
20
|
+
conf = {}
|
21
|
+
option.apply(conf)
|
22
|
+
expect(conf).to eq(expected)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
---
|
2
|
+
defaults:
|
3
|
+
parent: ubuntu:14.04.1
|
4
|
+
repository: docker.example.com/baha
|
5
|
+
maintainer: Ishmael <ishmael@example.com>
|
6
|
+
images:
|
7
|
+
- include: config_build_image.yml
|
8
|
+
- parent: 'base:1.0.0'
|
9
|
+
name: derived
|
10
|
+
tag: 1.0.0
|
11
|
+
pre_build:
|
12
|
+
- { download: 'http://www.google.com', file: 'myfile.txt' }
|
@@ -0,0 +1,12 @@
|
|
1
|
+
---
|
2
|
+
defaults:
|
3
|
+
parent: ubuntu:14.04.1
|
4
|
+
repository: docker.example.com/baha
|
5
|
+
maintainer: Ishmael <ishmael@example.com>
|
6
|
+
images:
|
7
|
+
- include: base_image.yml
|
8
|
+
- include: no_such_file_exists.yml
|
9
|
+
- parent: 'ubuntu:14.04.1'
|
10
|
+
name: base
|
11
|
+
tag: 1.0.0
|
12
|
+
maintainer: '"Captain Ahab" <ahab@example.com>'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
---
|
2
|
+
docker_url: unix:///var/run/docker.sock
|
3
|
+
defaults:
|
4
|
+
parent: ubuntu:14.04.1
|
5
|
+
repository: docker.example.com/baha
|
6
|
+
maintainer: Ishmael <ishmael@example.com>
|
7
|
+
images:
|
8
|
+
- parent: 'ubuntu:14.04.1'
|
9
|
+
name: base
|
10
|
+
tag: 1.0.0
|
11
|
+
maintainer: '"Captain Ahab" <ahab@example.com>'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
---
|
2
|
+
docker_url: tcp://127.0.1.1:2375
|
3
|
+
defaults:
|
4
|
+
parent: ubuntu:14.04.1
|
5
|
+
repository: docker.example.com/baha
|
6
|
+
maintainer: Ishmael <ishmael@example.com>
|
7
|
+
ssl:
|
8
|
+
key: key.pem
|
9
|
+
cert: cert.pem
|
10
|
+
ca: ca.pem
|
11
|
+
verify: true
|
12
|
+
images:
|
13
|
+
- include: base_image.yml
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module DockerHelpers
|
2
|
+
require 'docker'
|
3
|
+
def mock_registry(images)
|
4
|
+
allow(Docker::Image).to receive(:create).and_raise(RuntimeError)
|
5
|
+
allow(Docker::Image).to receive(:get).and_raise(RuntimeError)
|
6
|
+
images.each do |image|
|
7
|
+
i = double("image-#{image[:id]}")
|
8
|
+
allow(i).to receive(:id) { image[:id] }
|
9
|
+
allow(i).to receive(:info) do
|
10
|
+
{ 'Parent' => image[:parent] }
|
11
|
+
end
|
12
|
+
allow(i).to receive(:history) do
|
13
|
+
[{'Tags' => image[:tags] }]
|
14
|
+
end
|
15
|
+
name = "#{image[:name]}:#{image[:tag]}"
|
16
|
+
if image[:pulled]
|
17
|
+
allow(Docker::Image).to receive(:get).with(name).and_return(i)
|
18
|
+
else
|
19
|
+
allow(Docker::Image).to receive(:get).with(name).and_raise(RuntimeError)
|
20
|
+
allow(Docker::Image).to receive(:create).with('fromImage'=>image[:name], 'tag' =>image[:tag]).and_raise(RuntimeError)
|
21
|
+
end
|
22
|
+
allow(Docker::Image).to receive(:get).with(image[:id]).and_return(i)
|
23
|
+
if image[:tags]
|
24
|
+
image[:tags].each do |tag|
|
25
|
+
t = tag.split(':')
|
26
|
+
allow(Docker::Image).to receive(:create).with('fromImage'=>t[0], 'tag' =>t[1]).and_return(i)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|