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