bosh-stemcell 1.5.0.pre.1113
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.
- 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
|