bosh-stemcell 1.5.0.pre.1113
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +3 -0
- data/README.md +104 -0
- data/Vagrantfile +37 -0
- data/bosh-stemcell.gemspec +28 -0
- data/lib/bosh/stemcell.rb +4 -0
- data/lib/bosh/stemcell/archive.rb +59 -0
- data/lib/bosh/stemcell/archive_filename.rb +29 -0
- data/lib/bosh/stemcell/aws/ami.rb +58 -0
- data/lib/bosh/stemcell/aws/light_stemcell.rb +44 -0
- data/lib/bosh/stemcell/aws/region.rb +15 -0
- data/lib/bosh/stemcell/builder_command.rb +174 -0
- data/lib/bosh/stemcell/builder_options.rb +85 -0
- data/lib/bosh/stemcell/disk_image.rb +61 -0
- data/lib/bosh/stemcell/infrastructure.rb +49 -0
- data/lib/bosh/stemcell/operating_system.rb +31 -0
- data/lib/bosh/stemcell/stage_collection.rb +154 -0
- data/lib/bosh/stemcell/stage_runner.rb +53 -0
- data/lib/bosh/stemcell/version.rb +5 -0
- data/lib/monkeypatch/serverspec/backend/exec.rb +86 -0
- data/spec/assets/fake-stemcell-aws.tgz +0 -0
- data/spec/assets/fake-stemcell-vsphere.tgz +0 -0
- data/spec/assets/light-fake-stemcell-aws.tgz +0 -0
- data/spec/bosh/monkeypatch/serverspec/backend/exec_spec.rb +46 -0
- data/spec/bosh/stemcell/archive_filename_spec.rb +42 -0
- data/spec/bosh/stemcell/archive_spec.rb +98 -0
- data/spec/bosh/stemcell/aws/ami_spec.rb +30 -0
- data/spec/bosh/stemcell/aws/light_stemcell_spec.rb +94 -0
- data/spec/bosh/stemcell/aws/region_spec.rb +12 -0
- data/spec/bosh/stemcell/builder_command_spec.rb +241 -0
- data/spec/bosh/stemcell/builder_options_spec.rb +201 -0
- data/spec/bosh/stemcell/disk_image_spec.rb +163 -0
- data/spec/bosh/stemcell/infrastructure_spec.rb +66 -0
- data/spec/bosh/stemcell/operating_system_spec.rb +47 -0
- data/spec/bosh/stemcell/stage_collection_spec.rb +213 -0
- data/spec/bosh/stemcell/stage_runner_spec.rb +141 -0
- data/spec/bosh/stemcell/version_spec.rb +12 -0
- data/spec/bosh/stemcell_spec.rb +6 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/stemcells/aws_spec.rb +9 -0
- data/spec/stemcells/centos_spec.rb +131 -0
- data/spec/stemcells/openstack_spec.rb +9 -0
- data/spec/stemcells/ubuntu_spec.rb +143 -0
- data/spec/stemcells/vsphere_spec.rb +9 -0
- data/spec/support/rspec_fire.rb +9 -0
- data/spec/support/serverspec.rb +4 -0
- data/spec/support/spec_assets.rb +11 -0
- data/spec/support/stemcell_image.rb +26 -0
- data/spec/support/stemcell_shared_examples.rb +43 -0
- data/spec/support/stub_env.rb +5 -0
- metadata +236 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
# rubocop:disable all
|
2
|
+
# => disabling rubocop to preserve original style
|
3
|
+
require 'serverspec'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
raise "Unexpected Serverspec version #{Serverspec::VERSION}" unless Serverspec::VERSION == '0.7.10'
|
7
|
+
module Serverspec::Backend
|
8
|
+
class Exec
|
9
|
+
# ORIGINAL
|
10
|
+
#def run_command(cmd, opts={})
|
11
|
+
# cmd = build_command(cmd)
|
12
|
+
# cmd = add_pre_command(cmd)
|
13
|
+
# stdout = `#{build_command(cmd)} 2>&1`
|
14
|
+
# # In ruby 1.9, it is possible to use Open3.capture3, but not in 1.8
|
15
|
+
# #stdout, stderr, status = Open3.capture3(cmd)
|
16
|
+
#
|
17
|
+
# if @example
|
18
|
+
# @example.metadata[:command] = cmd
|
19
|
+
# @example.metadata[:stdout] = stdout
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# { :stdout => stdout, :stderr => nil,
|
23
|
+
# :exit_status => $?, :exit_signal => nil }
|
24
|
+
#end
|
25
|
+
#/ORIGINAL
|
26
|
+
|
27
|
+
def run_command(cmd, opts={})
|
28
|
+
cmd = build_command(cmd)
|
29
|
+
cmd = add_pre_command(cmd)
|
30
|
+
cmd = build_command(cmd)
|
31
|
+
|
32
|
+
if use_chroot?
|
33
|
+
chroot_stdout = `#{chroot_cmd(cmd)} 2>&1`
|
34
|
+
|
35
|
+
stdout = get_stdout(chroot_stdout)
|
36
|
+
exit_status = get_exit_status(chroot_stdout)
|
37
|
+
else
|
38
|
+
stdout = `#{cmd} 2>&1`
|
39
|
+
exit_status = $?
|
40
|
+
end
|
41
|
+
# In ruby 1.9, it is possible to use Open3.capture3, but not in 1.8
|
42
|
+
#stdout, stderr, status = Open3.capture3(cmd)
|
43
|
+
|
44
|
+
if @example
|
45
|
+
@example.metadata[:command] = cmd
|
46
|
+
@example.metadata[:stdout] = stdout
|
47
|
+
end
|
48
|
+
|
49
|
+
{ :stdout => stdout, :stderr => nil,
|
50
|
+
:exit_status => exit_status, :exit_signal => nil }
|
51
|
+
end
|
52
|
+
|
53
|
+
attr_accessor :chroot_dir
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def get_stdout(chroot_stdout)
|
58
|
+
chroot_stdout.gsub(/#{exit_code_regexp}/, '')
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_exit_status(chroot_stdout)
|
62
|
+
chroot_command_exit_status = chroot_stdout.match(/#{exit_code_regexp}/)[1]
|
63
|
+
chroot_command_exit_status.to_i
|
64
|
+
end
|
65
|
+
|
66
|
+
def use_chroot?
|
67
|
+
chroot_dir
|
68
|
+
end
|
69
|
+
|
70
|
+
def exit_code_token
|
71
|
+
'EXIT_CODE='
|
72
|
+
end
|
73
|
+
|
74
|
+
def exit_code_regexp
|
75
|
+
"#{exit_code_token}(\\d+)\s*\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
def chroot_cmd(cmd)
|
79
|
+
%Q{
|
80
|
+
sudo chroot #{chroot_dir} /bin/bash <<CHROOT_CMD
|
81
|
+
#{cmd} 2>&1; echo #{exit_code_token}\\$?
|
82
|
+
CHROOT_CMD
|
83
|
+
}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Serverspec::Backend
|
4
|
+
describe Exec do
|
5
|
+
subject(:exec) { Serverspec::Backend::Exec.instance }
|
6
|
+
|
7
|
+
describe '#run_command' do
|
8
|
+
context 'when #chroot_dir is NOT set' do
|
9
|
+
before do
|
10
|
+
exec.stub(chroot_dir: nil) # because "include Singleton"
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'runs the provided command as expected' do
|
14
|
+
exec.should_receive(:`).with('echo "FOO" 2>&1')
|
15
|
+
|
16
|
+
exec.run_command('echo "FOO"')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when #chroot_dir is set' do
|
21
|
+
before do
|
22
|
+
exec.stub(chroot_dir: '/path/to/chroot') # because "include Singleton"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'runs the provided command within the chroot' do
|
26
|
+
chroot_command = %Q{
|
27
|
+
sudo chroot /path/to/chroot /bin/bash <<CHROOT_CMD
|
28
|
+
echo "FOO" 2>&1; echo EXIT_CODE=\\$?
|
29
|
+
CHROOT_CMD
|
30
|
+
2>&1}
|
31
|
+
exec.should_receive(:`).with(chroot_command).and_return("FOO\nEXIT_CODE=0\n")
|
32
|
+
|
33
|
+
exec.run_command('echo "FOO"')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'extracts the exit code returned from within the chroot into an Integer' do
|
37
|
+
exec.stub(:` => "ATTENTION\nDO NOT CARE\nEXIT_CODE=8675309\n")
|
38
|
+
|
39
|
+
result = exec.run_command('do_not_care')
|
40
|
+
|
41
|
+
expect(result[:exit_status]).to eq(867_5309)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'bosh/stemcell/archive_filename'
|
4
|
+
require 'bosh/stemcell/infrastructure'
|
5
|
+
require 'bosh/stemcell/operating_system'
|
6
|
+
|
7
|
+
module Bosh::Stemcell
|
8
|
+
describe ArchiveFilename do
|
9
|
+
let(:version) { '007' }
|
10
|
+
let(:infrastructure) do
|
11
|
+
instance_double('Bosh::Stemcell::Infrastructure::Base',
|
12
|
+
name: 'INFRASTRUCTURE',
|
13
|
+
hypervisor: 'HYPERVISOR')
|
14
|
+
end
|
15
|
+
let(:operating_system) do
|
16
|
+
instance_double('Bosh::Stemcell::OperatingSystem::Base',
|
17
|
+
name: 'OPERATING_SYSTEM')
|
18
|
+
end
|
19
|
+
|
20
|
+
subject(:archive_filename) do
|
21
|
+
ArchiveFilename.new(version, infrastructure, operating_system, 'FAKE_NAME', light)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#to_s' do
|
25
|
+
context 'when stemcell is NOT light' do
|
26
|
+
let(:light) { false }
|
27
|
+
|
28
|
+
it 'includes name, version, infrastructure name, infrastructure hypervisor' do
|
29
|
+
expect(archive_filename.to_s).to eq ('FAKE_NAME-007-INFRASTRUCTURE-HYPERVISOR-OPERATING_SYSTEM.tgz')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when stemcell is light' do
|
34
|
+
let(:light) { true }
|
35
|
+
|
36
|
+
it 'prefixes the name with "light-"' do
|
37
|
+
expect(archive_filename.to_s).to eq ('light-FAKE_NAME-007-INFRASTRUCTURE-HYPERVISOR-OPERATING_SYSTEM.tgz')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bosh/stemcell/archive'
|
3
|
+
|
4
|
+
module Bosh::Stemcell
|
5
|
+
describe Archive do
|
6
|
+
let(:stemcell_path) { spec_asset('fake-stemcell-aws.tgz') }
|
7
|
+
|
8
|
+
subject { Archive.new(stemcell_path) }
|
9
|
+
|
10
|
+
describe '#initialize' do
|
11
|
+
it 'errors if path does not exist' do
|
12
|
+
expect { Archive.new('/not/found/stemcell.tgz') }.to raise_error "Cannot find file `/not/found/stemcell.tgz'"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#manifest' do
|
17
|
+
it 'has a manifest' do
|
18
|
+
expect(subject.manifest).to be_a Hash
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#name' do
|
23
|
+
it 'has a name' do
|
24
|
+
expect(subject.name).to eq 'fake-stemcell'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#infrastructure' do
|
29
|
+
it 'has an infrastructure' do
|
30
|
+
expect(subject.infrastructure).to eq 'aws'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#path' do
|
35
|
+
it 'has a path' do
|
36
|
+
expect(subject.path).to eq(stemcell_path)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#version' do
|
41
|
+
it 'has a version' do
|
42
|
+
expect(subject.version).to eq('007')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#light?' do
|
47
|
+
context 'when infrastructure is "aws"' do
|
48
|
+
context 'when there is not an "ami" key in the "cloud_properties" section of the manifest' do
|
49
|
+
it { should_not be_light }
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when there is an "ami" key in the "cloud_properties" section of the manifest' do
|
53
|
+
let(:stemcell_path) { spec_asset('light-fake-stemcell-aws.tgz') }
|
54
|
+
|
55
|
+
it { should be_light }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when infrastructure is anything but "aws"' do
|
60
|
+
let(:stemcell_path) { spec_asset('fake-stemcell-vsphere.tgz') }
|
61
|
+
|
62
|
+
it { should_not be_light }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#ami_id' do
|
67
|
+
context 'when infrastructure is "aws"' do
|
68
|
+
context 'when there is not an "ami" key in the "cloud_properties" section of the manifest' do
|
69
|
+
its(:ami_id) { should be_nil }
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when there is an "ami" key in the "cloud_properties" section of the manifest' do
|
73
|
+
let(:stemcell_path) { spec_asset('light-fake-stemcell-aws.tgz') }
|
74
|
+
|
75
|
+
its(:ami_id) { should eq('ami-FAKE_AMI_KEY') }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when infrastructure is anything but "aws"' do
|
80
|
+
let(:stemcell_path) { spec_asset('fake-stemcell-vsphere.tgz') }
|
81
|
+
|
82
|
+
its(:ami_id) { should be_nil }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#extract' do
|
87
|
+
it 'extracts stemcell' do
|
88
|
+
Rake::FileUtilsExt.should_receive(:sh).with(/tar xzf .*#{stemcell_path} --directory/)
|
89
|
+
subject.extract {}
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'extracts stemcell and excludes files' do
|
93
|
+
Rake::FileUtilsExt.should_receive(:sh).with(/tar xzf .*#{stemcell_path} --directory .* --exclude=image/)
|
94
|
+
subject.extract(exclude: 'image') {}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bosh/stemcell/aws/ami'
|
3
|
+
|
4
|
+
module Bosh::Stemcell::Aws
|
5
|
+
describe Ami do
|
6
|
+
let(:stemcell) do
|
7
|
+
stemcell = double('Bosh::Dev::Stemcell')
|
8
|
+
stemcell_manifest = { 'cloud_properties' => { 'ami' => '' } }
|
9
|
+
stemcell.stub(:extract).and_yield('/foo/bar', stemcell_manifest)
|
10
|
+
stemcell
|
11
|
+
end
|
12
|
+
|
13
|
+
subject(:ami) do
|
14
|
+
Ami.new(stemcell, instance_double('Bosh::Stemcell::Aws::Region', name: 'fake-region'))
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
Logger.stub(:new)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'publish' do
|
22
|
+
it 'creates a new ami' do
|
23
|
+
provider = instance_double('Bosh::AwsCloud::Cloud', create_stemcell: 'fake-ami-id').as_null_object
|
24
|
+
Bosh::Clouds::Provider.stub(create: provider)
|
25
|
+
|
26
|
+
expect(ami.publish).to eq('fake-ami-id')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bosh/stemcell/aws/light_stemcell'
|
3
|
+
require 'bosh/stemcell/archive'
|
4
|
+
|
5
|
+
module Bosh::Stemcell
|
6
|
+
module Aws
|
7
|
+
describe LightStemcell do
|
8
|
+
let(:stemcell) do
|
9
|
+
Archive.new(spec_asset('fake-stemcell-aws.tgz'))
|
10
|
+
end
|
11
|
+
|
12
|
+
subject(:light_stemcell) do
|
13
|
+
LightStemcell.new(stemcell)
|
14
|
+
end
|
15
|
+
|
16
|
+
its(:path) { should eq(spec_asset('light-fake-stemcell-aws.tgz')) }
|
17
|
+
|
18
|
+
describe '#write_archive' do
|
19
|
+
let(:region) do
|
20
|
+
instance_double('Bosh::Stemcell::Aws::Region', name: 'fake-region')
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:ami) do
|
24
|
+
instance_double('Bosh::Stemcell::Aws::Ami', publish: 'fake-ami-id')
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:stemcell) do
|
28
|
+
Archive.new(spec_asset('fake-stemcell-aws.tgz'))
|
29
|
+
end
|
30
|
+
|
31
|
+
subject(:light_stemcell) do
|
32
|
+
LightStemcell.new(stemcell)
|
33
|
+
end
|
34
|
+
|
35
|
+
before do
|
36
|
+
Region.stub(new: region)
|
37
|
+
Ami.stub(:new).with(stemcell, region).and_return(ami)
|
38
|
+
Rake::FileUtilsExt.stub(:sh)
|
39
|
+
FileUtils.stub(:touch)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'creates an ami from the stemcell' do
|
43
|
+
ami.should_receive(:publish)
|
44
|
+
|
45
|
+
light_stemcell.write_archive
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'creates a new tgz' do
|
49
|
+
Rake::FileUtilsExt.should_receive(:sh) do |command|
|
50
|
+
command.should match(/tar xzf #{stemcell.path} --directory .*/)
|
51
|
+
end
|
52
|
+
|
53
|
+
expected_tarfile = File.join(File.dirname(stemcell.path), 'light-fake-stemcell-aws.tgz')
|
54
|
+
|
55
|
+
Rake::FileUtilsExt.should_receive(:sh) do |command|
|
56
|
+
command.should match(/sudo tar cvzf #{expected_tarfile} \*/)
|
57
|
+
end
|
58
|
+
|
59
|
+
light_stemcell.write_archive
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'replaces the raw image with a blank placeholder' do
|
63
|
+
FileUtils.should_receive(:touch).and_return do |file, options|
|
64
|
+
expect(file).to match('image')
|
65
|
+
expect(options).to eq(verbose: true)
|
66
|
+
end
|
67
|
+
light_stemcell.write_archive
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'adds the ami to the stemcell manifest' do
|
71
|
+
Psych.should_receive(:dump).and_return do |stemcell_properties, out|
|
72
|
+
expect(stemcell_properties['cloud_properties']['ami']).to eq({ 'fake-region' => 'fake-ami-id' })
|
73
|
+
end
|
74
|
+
|
75
|
+
light_stemcell.write_archive
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'names the stemcell manifest correctly' do
|
79
|
+
# Example fails on linux without File.stub
|
80
|
+
File.stub(:open).and_call_original
|
81
|
+
File.should_receive(:open).with('stemcell.MF', 'w')
|
82
|
+
|
83
|
+
light_stemcell.write_archive
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'does not mutate original stemcell manifest' do
|
87
|
+
expect {
|
88
|
+
light_stemcell.write_archive
|
89
|
+
}.not_to change { stemcell.manifest['cloud_properties'] }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bosh/stemcell/aws/region'
|
3
|
+
|
4
|
+
module Bosh::Stemcell::Aws
|
5
|
+
describe Region do
|
6
|
+
it 'queries AWS for its region' do
|
7
|
+
az_query = '/latest/meta-data/placement/availability-zone'
|
8
|
+
Net::HTTP.stub(:get).with('169.254.169.254', az_query).and_return("us-east-1\n")
|
9
|
+
expect(subject.name).to eq 'us-east-1'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bosh/stemcell/builder_command'
|
3
|
+
|
4
|
+
module Bosh::Stemcell
|
5
|
+
describe BuilderCommand do
|
6
|
+
subject(:stemcell_builder_command) do
|
7
|
+
described_class.new(
|
8
|
+
env,
|
9
|
+
infrastructure_name: infrastructure.name,
|
10
|
+
operating_system_name: operating_system.name,
|
11
|
+
release_tarball_path: release_tarball_path,
|
12
|
+
version: version
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:env) { {} }
|
17
|
+
|
18
|
+
let(:infrastructure) do
|
19
|
+
instance_double(
|
20
|
+
'Bosh::Stemcell::Infrastructure::Vsphere',
|
21
|
+
name: 'vsphere',
|
22
|
+
hypervisor: 'esxi'
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:operating_system) { instance_double('Bosh::Stemcell::OperatingSystem::Ubuntu', name: 'ubuntu') }
|
27
|
+
let(:release_tarball_path) { "/fake/path/to/bosh-#{version}.tgz" }
|
28
|
+
let(:version) { '007' }
|
29
|
+
|
30
|
+
before do
|
31
|
+
Infrastructure.stub(:for).with('vsphere').and_return(infrastructure)
|
32
|
+
OperatingSystem.stub(:for).with(operating_system.name).and_return(operating_system)
|
33
|
+
StageCollection.stub(:new).with(
|
34
|
+
infrastructure: infrastructure,
|
35
|
+
operating_system: operating_system
|
36
|
+
).and_return(stage_collection)
|
37
|
+
|
38
|
+
StageRunner.stub(:new).with(
|
39
|
+
build_path: File.join(root_dir, 'build', 'build'),
|
40
|
+
command_env: 'env ',
|
41
|
+
settings_file: settings_file,
|
42
|
+
work_path: File.join(root_dir, 'work')
|
43
|
+
).and_return(stage_runner)
|
44
|
+
|
45
|
+
BuilderOptions.stub(:new).with(
|
46
|
+
env,
|
47
|
+
tarball: release_tarball_path,
|
48
|
+
stemcell_version: version,
|
49
|
+
infrastructure: infrastructure,
|
50
|
+
operating_system: operating_system
|
51
|
+
).and_return(stemcell_builder_options)
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:root_dir) do
|
55
|
+
File.join('/mnt/stemcells', infrastructure.name, infrastructure.hypervisor, operating_system.name)
|
56
|
+
end
|
57
|
+
|
58
|
+
let(:stemcell_builder_options) do
|
59
|
+
instance_double('Bosh::Stemcell::BuilderOptions', default: options)
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:stage_collection) do
|
63
|
+
instance_double(
|
64
|
+
'Bosh::Stemcell::StageCollection',
|
65
|
+
operating_system_stages: ['FAKE_OS_STAGES'],
|
66
|
+
infrastructure_stages: ['FAKE_INFRASTRUCTURE_STAGES']
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:stage_runner) { instance_double('Bosh::Stemcell::StageRunner', configure_and_apply: nil) }
|
71
|
+
|
72
|
+
let(:etc_dir) { File.join(root_dir, 'build', 'build', 'etc') }
|
73
|
+
let(:settings_file) { File.join(etc_dir, 'settings.bash') }
|
74
|
+
|
75
|
+
let(:options) do
|
76
|
+
{
|
77
|
+
'hello' => 'world',
|
78
|
+
'stemcell_tgz' => 'fake-stemcell.tgz',
|
79
|
+
'stemcell_image_name' => 'fake-root-disk-image.raw'
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
its(:chroot_dir) { should eq(File.join(root_dir, 'work', 'work', 'chroot')) }
|
84
|
+
|
85
|
+
describe '#build' do
|
86
|
+
include FakeFS::SpecHelpers
|
87
|
+
|
88
|
+
before do
|
89
|
+
Process.stub(pid: 99999)
|
90
|
+
|
91
|
+
stemcell_builder_command.stub(system: true)
|
92
|
+
FileUtils.touch('leftover.tgz')
|
93
|
+
|
94
|
+
FileUtils.stub(:cp_r).with([], File.join(root_dir, 'build', 'build'), preserve: true, verbose: true) do
|
95
|
+
FileUtils.mkdir_p(etc_dir)
|
96
|
+
FileUtils.touch(settings_file)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'sanitizing the environment' do
|
101
|
+
it 'removes any tgz files from current working directory' do
|
102
|
+
expect {
|
103
|
+
stemcell_builder_command.build
|
104
|
+
}.to change { Dir.glob('*.tgz').size }.to(0)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'unmounts the disk image used to install Grub' do
|
108
|
+
image_path = File.join(root_dir, 'work/work/mnt/tmp/grub/fake-root-disk-image.raw')
|
109
|
+
unmount_img_command = "sudo umount #{image_path} 2> /dev/null"
|
110
|
+
stemcell_builder_command.should_receive(:system).with(unmount_img_command)
|
111
|
+
stemcell_builder_command.build
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'unmounts work/work/mnt directory' do
|
115
|
+
unmount_dir_command = "sudo umount #{File.join(root_dir, 'work/work/mnt')} 2> /dev/null"
|
116
|
+
stemcell_builder_command.should_receive(:system).with(unmount_dir_command)
|
117
|
+
stemcell_builder_command.build
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'removes stemcell root directory' do
|
121
|
+
stemcell_builder_command.should_receive(:system).with("sudo rm -rf #{root_dir}")
|
122
|
+
stemcell_builder_command.build
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'returns the full path of the generated stemcell archive' do
|
127
|
+
expect(stemcell_builder_command.build).to eq(File.join(root_dir, 'work', 'work', 'fake-stemcell.tgz'))
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'creates a base directory for stemcell creation' do
|
131
|
+
expect {
|
132
|
+
stemcell_builder_command.build
|
133
|
+
}.to change { Dir.exists?(root_dir) }.from(false).to(true)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'creates a build directory for stemcell creation' do
|
137
|
+
expect {
|
138
|
+
stemcell_builder_command.build
|
139
|
+
}.to change { Dir.exists?(File.join(root_dir, 'build')) }.from(false).to(true)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'copies the stemcell_builder code into the build directory' do
|
143
|
+
FileUtils.should_receive(:cp_r).with([],
|
144
|
+
File.join(root_dir, 'build', 'build'),
|
145
|
+
preserve: true,
|
146
|
+
verbose: true) do
|
147
|
+
FileUtils.mkdir_p(etc_dir)
|
148
|
+
FileUtils.touch(settings_file)
|
149
|
+
end
|
150
|
+
|
151
|
+
stemcell_builder_command.build
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'creates a work directory for stemcell creation chroot' do
|
155
|
+
expect {
|
156
|
+
stemcell_builder_command.build
|
157
|
+
}.to change { Dir.exists?(File.join(root_dir, 'work')) }.from(false).to(true)
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'writes a settings file into the build directory' do
|
161
|
+
stemcell_builder_command.build
|
162
|
+
|
163
|
+
expect(File.read(settings_file)).to match(/hello=world/)
|
164
|
+
end
|
165
|
+
|
166
|
+
describe 'running stages' do
|
167
|
+
let(:expected_rspec_command) do
|
168
|
+
[
|
169
|
+
"cd #{File.expand_path('../../..', File.dirname(__FILE__))};",
|
170
|
+
"STEMCELL_IMAGE=#{File.join(root_dir, 'work', 'work', 'fake-root-disk-image.raw')}",
|
171
|
+
'bundle exec rspec -fd',
|
172
|
+
"spec/stemcells/#{operating_system.name}_spec.rb",
|
173
|
+
"spec/stemcells/#{infrastructure.name}_spec.rb",
|
174
|
+
].join(' ')
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'calls #configure_and_apply' do
|
178
|
+
stage_runner.should_receive(:configure_and_apply).
|
179
|
+
with(['FAKE_OS_STAGES']).ordered
|
180
|
+
stage_runner.should_receive(:configure_and_apply).
|
181
|
+
with(['FAKE_INFRASTRUCTURE_STAGES']).ordered
|
182
|
+
stemcell_builder_command.should_receive(:system).
|
183
|
+
with(expected_rspec_command).ordered
|
184
|
+
|
185
|
+
stemcell_builder_command.build
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'with CentOS' do
|
189
|
+
let(:operating_system) { instance_double('Bosh::Stemcell::OperatingSystem::Centos', name: 'centos') }
|
190
|
+
|
191
|
+
it 'calls #configure_and_apply' do
|
192
|
+
stage_runner.should_receive(:configure_and_apply).
|
193
|
+
with(['FAKE_OS_STAGES']).ordered
|
194
|
+
stage_runner.should_receive(:configure_and_apply).
|
195
|
+
with(['FAKE_INFRASTRUCTURE_STAGES']).ordered
|
196
|
+
stemcell_builder_command.should_receive(:system).
|
197
|
+
with(expected_rspec_command).ordered
|
198
|
+
|
199
|
+
stemcell_builder_command.build
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context 'when ENV contains variables besides HTTP_PROXY and NO_PROXY' do
|
205
|
+
let(:env) do
|
206
|
+
{
|
207
|
+
'NOT_HTTP_PROXY' => 'nice_proxy',
|
208
|
+
'no_proxy_just_kidding' => 'naughty_proxy'
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'nothing is passed to sudo via "env"' do
|
213
|
+
StageRunner.stub(:new).with(build_path: File.join(root_dir, 'build', 'build'),
|
214
|
+
command_env: 'env ',
|
215
|
+
settings_file: settings_file,
|
216
|
+
work_path: File.join(root_dir, 'work')).and_return(stage_runner)
|
217
|
+
|
218
|
+
stemcell_builder_command.build
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'ENV variables for HTTP_PROXY and NO_PROXY are passed to "env"' do
|
223
|
+
let(:env) do
|
224
|
+
{
|
225
|
+
'HTTP_PROXY' => 'nice_proxy',
|
226
|
+
'no_proxy' => 'naughty_proxy'
|
227
|
+
}
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'they are passed to sudo via "env"' do
|
231
|
+
StageRunner.stub(:new).with(build_path: File.join(root_dir, 'build', 'build'),
|
232
|
+
command_env: "env HTTP_PROXY='nice_proxy' no_proxy='naughty_proxy'",
|
233
|
+
settings_file: settings_file,
|
234
|
+
work_path: File.join(root_dir, 'work')).and_return(stage_runner)
|
235
|
+
|
236
|
+
stemcell_builder_command.build
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|