vcloud-launcher 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +2 -0
- data/CHANGELOG.md +13 -0
- data/CONTRIBUTING.md +66 -0
- data/Gemfile +2 -2
- data/Rakefile +3 -9
- data/bin/vcloud-launch +1 -44
- data/lib/vcloud/launcher.rb +2 -0
- data/lib/vcloud/launcher/cli.rb +103 -0
- data/lib/vcloud/launcher/launch.rb +36 -1
- data/lib/vcloud/launcher/preamble.rb +60 -0
- data/lib/vcloud/launcher/version.rb +1 -1
- data/lib/vcloud/launcher/vm_orchestrator.rb +10 -5
- data/spec/integration/README.md +1 -1
- data/spec/integration/launcher/data/storage_profile.yaml.erb +0 -30
- data/spec/integration/launcher/{vcloud_launcher_spec.rb → launch_spec.rb} +42 -31
- data/spec/integration/launcher/storage_profile_integration_spec.rb +23 -35
- data/spec/spec_helper.rb +29 -0
- data/spec/vcloud/launcher/cli_spec.rb +214 -0
- data/spec/vcloud/launcher/launch_spec.rb +107 -1
- data/spec/vcloud/launcher/preamble_spec.rb +214 -0
- data/spec/vcloud/launcher/vapp_orchestrator_spec.rb +14 -14
- data/spec/vcloud/launcher/vm_orchestrator_spec.rb +109 -22
- data/vcloud-launcher.gemspec +8 -8
- metadata +40 -71
- data/features/step_definitions/vcloud-launch_steps.rb +0 -3
- data/features/support/env.rb +0 -16
- data/features/vcloud-launch.feature +0 -18
@@ -68,7 +68,113 @@ describe Vcloud::Launcher::Launch do
|
|
68
68
|
expect(Vcloud::Core.logger).to receive(:level=).with(Logger::INFO)
|
69
69
|
subject.set_logging_level({})
|
70
70
|
end
|
71
|
-
|
72
71
|
end
|
73
72
|
|
73
|
+
describe "configuration validation" do
|
74
|
+
let(:config_file) { 'foo' }
|
75
|
+
|
76
|
+
before(:each) do
|
77
|
+
Vcloud::Core::ConfigLoader.any_instance.stub(:load_config).and_return(config)
|
78
|
+
|
79
|
+
allow(Vcloud::Launcher::VappOrchestrator).
|
80
|
+
to receive(:provision).and_return(double(:vapp, :power_on => true))
|
81
|
+
end
|
82
|
+
|
83
|
+
subject { Vcloud::Launcher::Launch.new }
|
84
|
+
|
85
|
+
context "when bootstrap configuration is supplied" do
|
86
|
+
context "script_path is missing" do
|
87
|
+
let(:config) do
|
88
|
+
{ vapps: [
|
89
|
+
{
|
90
|
+
name: "test_vapp_name",
|
91
|
+
vdc_name: "Test VDC",
|
92
|
+
catalog_name: "default",
|
93
|
+
vapp_template_name: "ubuntu-precise",
|
94
|
+
bootstrap: {
|
95
|
+
vars: { foo: 'bar' }
|
96
|
+
}
|
97
|
+
}
|
98
|
+
]
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
it "raises MissingConfigurationError" do
|
103
|
+
expect{ subject.run(config_file) }.
|
104
|
+
to raise_error(Vcloud::Launcher::Launch::MissingConfigurationError)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "script_path does not exist" do
|
109
|
+
let(:config) do
|
110
|
+
{ vapps: [
|
111
|
+
{
|
112
|
+
name: "test_vapp_name",
|
113
|
+
vdc_name: "Test VDC",
|
114
|
+
catalog_name: "default",
|
115
|
+
vapp_template_name: "ubuntu-precise",
|
116
|
+
bootstrap: {
|
117
|
+
script_path: 'nonexistent_preamble.sh.erb',
|
118
|
+
vars: { foo: 'bar' }
|
119
|
+
}
|
120
|
+
}
|
121
|
+
]
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
it "raises MissingPreambleError" do
|
126
|
+
expect{ subject.run(config_file) }.
|
127
|
+
to raise_error(Vcloud::Launcher::Launch::MissingPreambleError)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "script_path is specified, without vars" do
|
132
|
+
# Avoid triggering exceptions on missing preamble file.
|
133
|
+
before do
|
134
|
+
File.stub(:exist?).and_return(true)
|
135
|
+
allow(Vcloud::Core.logger).to receive(:info)
|
136
|
+
end
|
137
|
+
|
138
|
+
let(:config) do
|
139
|
+
{ vapps: [
|
140
|
+
{
|
141
|
+
name: "test_vapp_name",
|
142
|
+
vdc_name: "Test VDC",
|
143
|
+
catalog_name: "default",
|
144
|
+
vapp_template_name: "ubuntu-precise",
|
145
|
+
bootstrap: {
|
146
|
+
script_path: 'nonexistent_preamble.sh.erb'
|
147
|
+
}
|
148
|
+
}
|
149
|
+
]
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
it "logs an informative message" do
|
154
|
+
# A rather overly specific test to find the message of
|
155
|
+
# interest amongst other log messages.
|
156
|
+
expect(Vcloud::Core.logger).to receive(:info).with(/without variables to template/)
|
157
|
+
subject.run(config_file)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context "when bootstrap configuration is absent" do
|
163
|
+
let(:config) do
|
164
|
+
{ vapps: [
|
165
|
+
{
|
166
|
+
name: "test_vapp_name",
|
167
|
+
vdc_name: "Test VDC",
|
168
|
+
catalog_name: "default",
|
169
|
+
vapp_template_name: "ubuntu-precise"
|
170
|
+
}
|
171
|
+
]
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should not raise an error" do
|
176
|
+
expect{ subject.run(config_file) }.not_to raise_error
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
74
180
|
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Vcloud
|
4
|
+
module Launcher
|
5
|
+
describe Preamble do
|
6
|
+
subject { Vcloud::Launcher::Preamble }
|
7
|
+
|
8
|
+
let(:vm_name) { 'test-vm' }
|
9
|
+
let(:minimal_vm_config) do
|
10
|
+
{ bootstrap: {
|
11
|
+
script_path: 'hello_world.erb',
|
12
|
+
vars: { bob: 'Hello', mary: 'Hola' }
|
13
|
+
}
|
14
|
+
}
|
15
|
+
end
|
16
|
+
let(:minimal_template) do
|
17
|
+
<<-'EOF'
|
18
|
+
vars:
|
19
|
+
bob: <%= vars[:bob] -%>.
|
20
|
+
mary: <%= vars[:mary] %>.
|
21
|
+
EOF
|
22
|
+
end
|
23
|
+
let(:minimal_template_output) do
|
24
|
+
<<-EOF
|
25
|
+
vars:
|
26
|
+
bob: Hello.
|
27
|
+
mary: Hola.
|
28
|
+
EOF
|
29
|
+
end
|
30
|
+
let(:minimal_template_lines) { 3 }
|
31
|
+
|
32
|
+
let(:complete_vm_config) do
|
33
|
+
{ bootstrap: {
|
34
|
+
script_path: 'hello_world.erb',
|
35
|
+
script_post_processor: '/usr/bin/wc -l',
|
36
|
+
vars: { bob: 'Hello', mary: 'Hola' }
|
37
|
+
},
|
38
|
+
extra_disks: [
|
39
|
+
{ size: 5120, fs_file: '/opt/test_disk1' },
|
40
|
+
{ size: 10240, fs_file: '/opt/test_disk2' },
|
41
|
+
]
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'public interface' do
|
46
|
+
describe 'instance methods' do
|
47
|
+
subject { Vcloud::Launcher::Preamble.new(vm_name, minimal_vm_config) }
|
48
|
+
|
49
|
+
it { should respond_to(:generate) }
|
50
|
+
it { should respond_to(:interpolated_preamble) }
|
51
|
+
|
52
|
+
it { should respond_to(:preamble_vars) }
|
53
|
+
it { should respond_to(:script_path) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#new' do
|
58
|
+
it "accepts complete configuration without error" do
|
59
|
+
expect { subject.new(vm_name, minimal_vm_config) }.not_to raise_error
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when the preamble template is missing" do
|
63
|
+
let(:vm_config) do
|
64
|
+
{ bootstrap: {
|
65
|
+
script_post_processor: 'remove_hello.rb',
|
66
|
+
vars: { bob: 'hello', mary: 'hola' }
|
67
|
+
}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
it "raises a MissingTemplateError" do
|
72
|
+
expect { subject.new(vm_name, vm_config) }.
|
73
|
+
to raise_error( Vcloud::Launcher::Preamble::MissingTemplateError)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when bootstrap configuration is empty" do
|
78
|
+
it "raises a MissingConfigurationError" do
|
79
|
+
expect { subject.new(vm_name, {}) }.
|
80
|
+
to raise_error(Vcloud::Launcher::Preamble::MissingConfigurationError)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when vars are absent" do
|
85
|
+
let(:vm_config) do
|
86
|
+
{ bootstrap: {
|
87
|
+
script_path: 'hello_world.erb',
|
88
|
+
script_post_processor: 'remove_hello.rb'
|
89
|
+
},
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
it "does not raise an error (allows for post-processing only)" do
|
94
|
+
expect { subject.new(vm_name, vm_config ) }.not_to raise_error
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when vars are empty" do
|
99
|
+
let(:vm_config) do
|
100
|
+
{ bootstrap: {
|
101
|
+
script_path: 'hello_world.erb',
|
102
|
+
script_post_processor: 'remove_hello.rb',
|
103
|
+
vars: {},
|
104
|
+
}
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
it "raises a MissingConfigurationError (allows for post-processing only)" do
|
109
|
+
expect { subject.new(vm_name, vm_config ) }.not_to raise_error
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "extra_disks" do
|
114
|
+
subject { Vcloud::Launcher::Preamble.new(vm_name, complete_vm_config) }
|
115
|
+
|
116
|
+
it "merges extra_disks into preamble_vars" do
|
117
|
+
expect( subject.preamble_vars ).to have_key(:extra_disks)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe ".generate" do
|
123
|
+
subject { Vcloud::Launcher::Preamble.new(vm_name, minimal_vm_config) }
|
124
|
+
|
125
|
+
before(:each) do
|
126
|
+
subject.stub(:load_erb_file).and_return(minimal_template)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "invokes .interpolate_preamble_erb_file" do
|
130
|
+
subject.should_receive(:interpolate_erb_file)
|
131
|
+
subject.generate
|
132
|
+
end
|
133
|
+
|
134
|
+
context "interpolating variables" do
|
135
|
+
subject { Vcloud::Launcher::Preamble.new(vm_name, minimal_vm_config) }
|
136
|
+
|
137
|
+
context "environment variables" do
|
138
|
+
before(:each) do
|
139
|
+
stub_const('ENV', {'TEST_INTERPOLATED_ENVVAR' => 'test_interpolated_env'})
|
140
|
+
subject.stub(:load_erb_file).and_return('env_var: <%= ENV["TEST_INTERPOLATED_ENVVAR"] -%>')
|
141
|
+
end
|
142
|
+
|
143
|
+
it "interpolates environment variables into template" do
|
144
|
+
expect(subject.generate).to eq 'env_var: test_interpolated_env'
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "vars hash" do
|
149
|
+
before(:each) do
|
150
|
+
subject.stub(:load_erb_file).and_return(minimal_template)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "interpolates vars hash into template" do
|
154
|
+
expect(subject.generate).to eq minimal_template_output
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "vapp_name" do
|
159
|
+
before(:each) do
|
160
|
+
subject.stub(:load_erb_file).and_return('vapp_name: <%= vapp_name -%>')
|
161
|
+
end
|
162
|
+
|
163
|
+
it "interpolates vapp_name into template" do
|
164
|
+
expect(subject.generate).to eq "vapp_name: #{vm_name}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "when a post processor is supplied" do
|
170
|
+
let(:vm_config) do
|
171
|
+
{ bootstrap: {
|
172
|
+
script_path: 'hello_world.erb',
|
173
|
+
script_post_processor: '/usr/bin/wc -l',
|
174
|
+
vars: { bob: 'hello', mary: 'hola' }
|
175
|
+
}
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
let(:template) do
|
180
|
+
<<-EOF
|
181
|
+
one
|
182
|
+
two
|
183
|
+
three
|
184
|
+
EOF
|
185
|
+
end
|
186
|
+
|
187
|
+
subject { Vcloud::Launcher::Preamble.new(vm_name, vm_config) }
|
188
|
+
|
189
|
+
before(:each) do
|
190
|
+
subject.stub(:load_erb_file).and_return(template)
|
191
|
+
end
|
192
|
+
|
193
|
+
it "invokes .post_process_erb_output" do
|
194
|
+
subject.should_receive(:post_process_erb_output)
|
195
|
+
subject.generate
|
196
|
+
end
|
197
|
+
|
198
|
+
it "returns the post-processed interpolated template" do
|
199
|
+
expect(subject.generate).to match(/\s*#{minimal_template_lines}/)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe ".interpolated_preamble" do
|
204
|
+
subject { Vcloud::Launcher::Preamble.new(vm_name, minimal_vm_config) }
|
205
|
+
|
206
|
+
it "returns the interpolated template" do
|
207
|
+
expect(subject.interpolated_preamble).to eq minimal_template_output
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
@@ -31,25 +31,25 @@ describe Vcloud::Launcher::VappOrchestrator do
|
|
31
31
|
it "should return a vapp if it already exists" do
|
32
32
|
existing_vapp = double(:vapp, :name => 'existing-vapp-1')
|
33
33
|
|
34
|
-
Vcloud::Core::Vapp.
|
35
|
-
Vcloud::Core.logger.
|
34
|
+
expect(Vcloud::Core::Vapp).to receive(:get_by_name_and_vdc_name).with('test-vapp-1', 'test-vdc-1').and_return(existing_vapp)
|
35
|
+
expect(Vcloud::Core.logger).to receive(:info).with('Found existing vApp test-vapp-1 in vDC \'test-vdc-1\'. Skipping.')
|
36
36
|
actual_vapp = subject.provision @config
|
37
|
-
actual_vapp.
|
38
|
-
actual_vapp.
|
37
|
+
expect(actual_vapp).not_to be_nil
|
38
|
+
expect(actual_vapp).to eq(existing_vapp)
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should create a vapp if it does not exist" do
|
42
42
|
#this test highlights the problems in vapp
|
43
43
|
|
44
|
-
Vcloud::Core::Vapp.
|
45
|
-
Vcloud::Core::VappTemplate.
|
44
|
+
expect(Vcloud::Core::Vapp).to receive(:get_by_name_and_vdc_name).with('test-vapp-1', 'test-vdc-1').and_return(nil)
|
45
|
+
expect(Vcloud::Core::VappTemplate).to receive(:get).with('org-1-template', 'org-1-catalog').and_return(double(:vapp_template, :id => 1))
|
46
46
|
|
47
|
-
Vcloud::Core::Vapp.
|
47
|
+
expect(Vcloud::Core::Vapp).to receive(:instantiate).with('test-vapp-1', ['org-vdc-1-net-1'], 1, 'test-vdc-1')
|
48
48
|
.and_return(mock_vapp)
|
49
|
-
Vcloud::Launcher::VmOrchestrator.
|
49
|
+
expect(Vcloud::Launcher::VmOrchestrator).to receive(:new).with(mock_fog_vm, mock_vapp).and_return(mock_vm_orchestrator)
|
50
50
|
|
51
51
|
new_vapp = subject.provision @config
|
52
|
-
new_vapp.
|
52
|
+
expect(new_vapp).to eq(mock_vapp)
|
53
53
|
end
|
54
54
|
|
55
55
|
context "deprecated config items" do
|
@@ -57,9 +57,9 @@ describe Vcloud::Launcher::VappOrchestrator do
|
|
57
57
|
double(:vapp_template, :id => 2)
|
58
58
|
}
|
59
59
|
before(:each) {
|
60
|
-
Vcloud::Core::Vapp.
|
61
|
-
Vcloud::Core::Vapp.
|
62
|
-
Vcloud::Launcher::VmOrchestrator.
|
60
|
+
allow(Vcloud::Core::Vapp).to receive(:get_by_name_and_vdc_name)
|
61
|
+
allow(Vcloud::Core::Vapp).to receive(:instantiate).and_return(mock_vapp)
|
62
|
+
allow(Vcloud::Launcher::VmOrchestrator).to receive(:new).and_return(mock_vm_orchestrator)
|
63
63
|
}
|
64
64
|
|
65
65
|
it "should use catalog_item when vapp_template_name is not present" do
|
@@ -67,7 +67,7 @@ describe Vcloud::Launcher::VappOrchestrator do
|
|
67
67
|
config.delete(:vapp_template_name)
|
68
68
|
config[:catalog_item] = 'deprecated-template'
|
69
69
|
|
70
|
-
Vcloud::Core::VappTemplate.
|
70
|
+
expect(Vcloud::Core::VappTemplate).to receive(:get).with('deprecated-template', 'org-1-catalog').and_return(mock_vapp_template)
|
71
71
|
Vcloud::Launcher::VappOrchestrator.provision(config)
|
72
72
|
end
|
73
73
|
|
@@ -76,7 +76,7 @@ describe Vcloud::Launcher::VappOrchestrator do
|
|
76
76
|
config.delete(:catalog_name)
|
77
77
|
config[:catalog] = 'deprecated-catalog'
|
78
78
|
|
79
|
-
Vcloud::Core::VappTemplate.
|
79
|
+
expect(Vcloud::Core::VappTemplate).to receive(:get).with('org-1-template', 'deprecated-catalog').and_return(mock_vapp_template)
|
80
80
|
Vcloud::Launcher::VappOrchestrator.provision(config)
|
81
81
|
end
|
82
82
|
end
|
@@ -16,7 +16,7 @@ describe Vcloud::Launcher::VmOrchestrator do
|
|
16
16
|
Vcloud::Launcher::VmOrchestrator.new(fog_vm, vapp)
|
17
17
|
}
|
18
18
|
|
19
|
-
it "
|
19
|
+
it "orchestrates customization" do
|
20
20
|
vm_config = {
|
21
21
|
:hardware_config => {
|
22
22
|
:memory => 4096,
|
@@ -33,28 +33,23 @@ describe Vcloud::Launcher::VmOrchestrator do
|
|
33
33
|
:network_connections => [
|
34
34
|
{:name => "network1", :ip_address => "198.12.1.21"},
|
35
35
|
],
|
36
|
-
:bootstrap => {
|
37
|
-
:script_path => '/tmp/boostrap.erb',
|
38
|
-
:vars => {
|
39
|
-
:message => 'hello world'
|
40
|
-
}
|
41
|
-
},
|
42
36
|
:storage_profile => {
|
43
37
|
:name => 'basic-storage',
|
44
38
|
:href => 'https://vcloud.example.net/api/vdcStorageProfile/000aea1e-a5e9-4dd1-a028-40db8c98d237'
|
45
39
|
}
|
46
40
|
}
|
47
41
|
vm = double(:vm, :id => @vm_id, :vapp_name => 'web-app1', :vapp => vapp, :name => 'test-vm-1')
|
48
|
-
Vcloud::Core::Vm.
|
42
|
+
expect(Vcloud::Core::Vm).to receive(:new).with(@vm_id, vapp).and_return(vm)
|
43
|
+
|
44
|
+
expect(vm).to receive(:update_name).with('web-app1')
|
45
|
+
expect(vm).to receive(:configure_network_interfaces).with(vm_config[:network_connections])
|
46
|
+
expect(vm).to receive(:update_storage_profile).with(vm_config[:storage_profile])
|
47
|
+
expect(vm).to receive(:update_cpu_count).with(2)
|
48
|
+
expect(vm).to receive(:update_memory_size_in_mb).with(4096)
|
49
|
+
expect(vm).to receive(:add_extra_disks).with(vm_config[:extra_disks])
|
50
|
+
expect(vm).to receive(:update_metadata).with(vm_config[:metadata])
|
49
51
|
|
50
|
-
vm.
|
51
|
-
vm.should_receive(:configure_network_interfaces).with(vm_config[:network_connections])
|
52
|
-
vm.should_receive(:update_storage_profile).with(vm_config[:storage_profile])
|
53
|
-
vm.should_receive(:update_cpu_count).with(2)
|
54
|
-
vm.should_receive(:update_memory_size_in_mb).with(4096)
|
55
|
-
vm.should_receive(:add_extra_disks).with(vm_config[:extra_disks])
|
56
|
-
vm.should_receive(:update_metadata).with(vm_config[:metadata])
|
57
|
-
vm.should_receive(:configure_guest_customization_section).with('web-app1', vm_config[:bootstrap], vm_config[:extra_disks])
|
52
|
+
allow(vm).to receive(:configure_guest_customization_section).with('')
|
58
53
|
|
59
54
|
subject.customize(vm_config)
|
60
55
|
end
|
@@ -69,14 +64,106 @@ describe Vcloud::Launcher::VmOrchestrator do
|
|
69
64
|
{:size => '2048', :name => 'Hard disk 3', :fs_file => 'solr', :fs_mntops => 'solr-something'}
|
70
65
|
]
|
71
66
|
}
|
72
|
-
Vcloud::Core::Vm.
|
73
|
-
vm.
|
74
|
-
vm.
|
75
|
-
vm.
|
76
|
-
vm.
|
77
|
-
|
67
|
+
expect(Vcloud::Core::Vm).to receive(:new).with(@vm_id, vapp).and_return(vm)
|
68
|
+
expect(vm).to receive(:update_metadata).with(:shutdown => true)
|
69
|
+
expect(vm).to receive(:update_name).with('web-app1')
|
70
|
+
expect(vm).to receive(:add_extra_disks).with(vm_config[:extra_disks])
|
71
|
+
expect(vm).to receive(:configure_network_interfaces).with(vm_config[:network_connections])
|
72
|
+
|
73
|
+
allow(vm).to receive(:configure_guest_customization_section)
|
78
74
|
|
79
75
|
subject.customize(vm_config)
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when customizing a VM" do
|
79
|
+
let(:vm_config_with_bootstrap) do
|
80
|
+
{
|
81
|
+
hardware_config: {
|
82
|
+
memory: 4096,
|
83
|
+
cpu: 2
|
84
|
+
},
|
85
|
+
network_connections: [
|
86
|
+
{ name: "network1", ip_address: "198.12.1.21" }
|
87
|
+
],
|
88
|
+
bootstrap: {
|
89
|
+
script_path: '/tmp/bootstrap.erb',
|
90
|
+
vars: { message: 'hello world' }
|
91
|
+
}
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
let(:vm_config_without_bootstrap) do
|
96
|
+
{
|
97
|
+
hardware_config: {
|
98
|
+
memory: 4096,
|
99
|
+
cpu: 2
|
100
|
+
},
|
101
|
+
network_connections: [
|
102
|
+
{ name: "network1", ip_address: "198.12.1.21" }
|
103
|
+
]
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
let(:vm) { double(:vm, id: @vm_id, vapp_name: 'web-app1', vapp: vapp, name: 'test-vm-1') }
|
108
|
+
|
109
|
+
before(:each) do
|
110
|
+
Vcloud::Core::Vm.stub(:new).and_return(vm)
|
111
|
+
allow(vm).to receive(:update_name)
|
112
|
+
allow(vm).to receive(:configure_network_interfaces)
|
113
|
+
allow(vm).to receive(:update_cpu_count)
|
114
|
+
allow(vm).to receive(:update_memory_size_in_mb)
|
115
|
+
allow(vm).to receive(:add_extra_disks)
|
116
|
+
allow(vm).to receive(:update_metadata)
|
117
|
+
end
|
118
|
+
|
119
|
+
context "when bootstrap configuration is omitted" do
|
120
|
+
before { allow(vm).to receive(:configure_guest_customization_section) }
|
121
|
+
|
122
|
+
it "skips preamble processing" do
|
123
|
+
expect(Vcloud::Launcher::Preamble).not_to receive(:new)
|
124
|
+
expect(Vcloud::Launcher::Preamble).not_to receive(:generate)
|
125
|
+
|
126
|
+
subject.customize(vm_config_without_bootstrap)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "uses an empty string as the host preamble" do
|
130
|
+
expect(vm).to receive(:configure_guest_customization_section).with('')
|
131
|
+
subject.customize(vm_config_without_bootstrap)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "when bootstrap configuration is supplied" do
|
136
|
+
context "Vcloud::Launcher::Preamble used to generate a preamble" do
|
137
|
+
it "instantiates Vcloud::Launcher::Preamble" do
|
138
|
+
preamble = double
|
139
|
+
allow(preamble).to receive(:generate)
|
140
|
+
allow(vm).to receive(:configure_guest_customization_section)
|
141
|
+
|
142
|
+
expect(Vcloud::Launcher::Preamble).to receive(:new).with(vm.vapp_name, vm_config_with_bootstrap).and_return(preamble)
|
143
|
+
|
144
|
+
subject.customize(vm_config_with_bootstrap)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "uses Vcloud::Launcher::Preamble.generate to template a preamble" do
|
148
|
+
preamble = double
|
149
|
+
allow(Vcloud::Launcher::Preamble).to receive(:new).with(vm.vapp_name, vm_config_with_bootstrap).and_return(preamble)
|
150
|
+
allow(vm).to receive(:configure_guest_customization_section)
|
151
|
+
|
152
|
+
expect(preamble).to receive(:generate)
|
153
|
+
|
154
|
+
subject.customize(vm_config_with_bootstrap)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "passes the generated preamble to configure_guest_customization_section" do
|
158
|
+
preamble = double
|
159
|
+
allow(Vcloud::Launcher::Preamble).to receive(:new).with(vm.vapp_name, vm_config_with_bootstrap).and_return(preamble)
|
160
|
+
allow(preamble).to receive(:generate).and_return('FAKE_PREAMBLE')
|
161
|
+
|
162
|
+
expect(vm).to receive(:configure_guest_customization_section).with('FAKE_PREAMBLE')
|
80
163
|
|
164
|
+
subject.customize(vm_config_with_bootstrap)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
81
168
|
end
|
82
169
|
end
|