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.
@@ -12,7 +12,7 @@
12
12
 
13
13
  There is a [template file](/spec/integration/vcloud_tools_testing_config.yaml.template) to help with this. Copy the template file to `/spec/integration` (i.e. next to the template file) and remove the `.template`. This file will now be ignored by Git and you can safely add the parameters relevant to your environment.
14
14
 
15
- - You need to include the set-up for your testing environment in your [fog file](https://github.com/alphagov/vcloud-launcher#credentials).
15
+ - You need to include the set-up for your testing environment in your [fog file](https://github.com/gds-operations/vcloud-launcher#credentials).
16
16
 
17
17
  - The tests use the [vCloud Tools Tester](http://rubygems.org/gems/vcloud-tools-tester) gem. You do not need to install this, `bundler` will do this for you.
18
18
 
@@ -5,44 +5,14 @@ vapps:
5
5
  catalog_name: <%= catalog %>
6
6
  vapp_template_name: <%= vapp_template %>
7
7
  vm:
8
- hardware_config: &hardware_config
9
- memory: 4096
10
- cpu: 2
11
- bootstrap: &bootstrap
12
- script_path: <%= bootstrap_script %>
13
- vars:
14
- message: hello world
15
8
  storage_profile: <%= storage_profile %>
16
9
  - name: <%= vapp_name_2 %>
17
10
  vdc_name: <%= vdc_2_name %>
18
11
  catalog_name: <%= catalog %>
19
12
  vapp_template_name: <%= vapp_template %>
20
13
  vm:
21
- hardware_config:
22
- <<: *hardware_config
23
- bootstrap:
24
- <<: *bootstrap
25
14
  storage_profile: <%= storage_profile %>
26
15
  - name: <%= vapp_name_3 %>
27
16
  vdc_name: <%= vdc_1_name %>
28
17
  catalog_name: <%= catalog %>
29
18
  vapp_template_name: <%= vapp_template %>
30
- vm:
31
- hardware_config:
32
- <<: *hardware_config
33
- metadata:
34
- storage_profile_test_vm: true
35
- bootstrap:
36
- <<: *bootstrap
37
- - name: <%= vapp_name_4 %>
38
- vdc_name: <%= vdc_1_name %>
39
- catalog_name: <%= catalog %>
40
- vapp_template_name: <%= vapp_template %>
41
- vm:
42
- hardware_config:
43
- <<: *hardware_config
44
- metadata:
45
- storage_profile_test_vm: true
46
- bootstrap:
47
- <<: *bootstrap
48
- storage_profile: <%= nonsense_storage_profile %>
@@ -18,15 +18,15 @@ describe Vcloud::Launcher::Launch do
18
18
  @provisioned_vapp_id = vapp_query_result[:href].split('/').last
19
19
  provisioned_vapp = @fog_interface.get_vapp @provisioned_vapp_id
20
20
 
21
- provisioned_vapp.should_not be_nil
22
- provisioned_vapp[:name].should eq(test_data_1[:vapp_name])
23
- provisioned_vapp[:Children][:Vm].count.should eq(1)
21
+ expect(provisioned_vapp).not_to be_nil
22
+ expect(provisioned_vapp[:name]).to eq(test_data_1[:vapp_name])
23
+ expect(provisioned_vapp[:Children][:Vm].count).to eq(1)
24
24
  end
25
25
 
26
26
  after(:each) do
27
27
  unless ENV['VCLOUD_TOOLS_RSPEC_NO_DELETE_VAPP']
28
28
  File.delete @minimum_data_yaml
29
- @fog_interface.delete_vapp(@provisioned_vapp_id).should eq(true)
29
+ expect(@fog_interface.delete_vapp(@provisioned_vapp_id)).to eq(true)
30
30
  end
31
31
  end
32
32
  end
@@ -50,69 +50,69 @@ describe Vcloud::Launcher::Launch do
50
50
 
51
51
  context 'provision vapp' do
52
52
  it 'should create a vapp' do
53
- @vapp[:name].should eq(@test_data[:vapp_name])
54
- @vapp[:'ovf:NetworkSection'][:'ovf:Network'].count.should eq(2)
53
+ expect(@vapp[:name]).to eq(@test_data[:vapp_name])
54
+ expect(@vapp[:'ovf:NetworkSection'][:'ovf:Network'].count).to eq(2)
55
55
  vapp_networks = @vapp[:'ovf:NetworkSection'][:'ovf:Network'].collect { |connection| connection[:ovf_name] }
56
- vapp_networks.should =~ [@test_data[:network_1], @test_data[:network_2]]
56
+ expect(vapp_networks).to match_array([@test_data[:network_1], @test_data[:network_2]])
57
57
  end
58
58
 
59
59
  it "should create vm within vapp" do
60
- @vm.should_not be_nil
60
+ expect(@vm).not_to be_nil
61
61
  end
62
62
 
63
63
  end
64
64
 
65
65
  context "customize vm" do
66
66
  it "change cpu for given vm" do
67
- extract_memory(@vm).should eq('8192')
68
- extract_cpu(@vm).should eq('4')
67
+ expect(extract_memory(@vm)).to eq('8192')
68
+ expect(extract_cpu(@vm)).to eq('4')
69
69
  end
70
70
 
71
71
  it "should have added the right number of metadata values" do
72
- @vm_metadata.count.should eq(6)
72
+ expect(@vm_metadata.count).to eq(6)
73
73
  end
74
74
 
75
75
  it "the metadata should be equivalent to our input" do
76
- @vm_metadata[:is_true].should eq(true)
77
- @vm_metadata[:is_integer].should eq(-999)
78
- @vm_metadata[:is_string].should eq('Hello World')
76
+ expect(@vm_metadata[:is_true]).to eq(true)
77
+ expect(@vm_metadata[:is_integer]).to eq(-999)
78
+ expect(@vm_metadata[:is_string]).to eq('Hello World')
79
79
  end
80
80
 
81
81
  it "should attach extra hard disks to vm" do
82
82
  disks = extract_disks(@vm)
83
- disks.count.should eq(3)
83
+ expect(disks.count).to eq(3)
84
84
  [{:name => 'Hard disk 2', :size => '1024'}, {:name => 'Hard disk 3', :size => '2048'}].each do |new_disk|
85
- disks.should include(new_disk)
85
+ expect(disks).to include(new_disk)
86
86
  end
87
87
  end
88
88
 
89
89
  it "should configure the vm network interface" do
90
90
  vm_network_connection = @vm[:NetworkConnectionSection][:NetworkConnection]
91
- vm_network_connection.should_not be_nil
92
- vm_network_connection.count.should eq(2)
91
+ expect(vm_network_connection).not_to be_nil
92
+ expect(vm_network_connection.count).to eq(2)
93
93
 
94
94
 
95
95
  primary_nic = vm_network_connection.detect { |connection| connection[:network] == @test_data[:network_1] }
96
- primary_nic[:network].should eq(@test_data[:network_1])
97
- primary_nic[:NetworkConnectionIndex].should eq(@vm[:NetworkConnectionSection][:PrimaryNetworkConnectionIndex])
98
- primary_nic[:IpAddress].should eq(@test_data[:network_1_ip])
99
- primary_nic[:IpAddressAllocationMode].should eq('MANUAL')
96
+ expect(primary_nic[:network]).to eq(@test_data[:network_1])
97
+ expect(primary_nic[:NetworkConnectionIndex]).to eq(@vm[:NetworkConnectionSection][:PrimaryNetworkConnectionIndex])
98
+ expect(primary_nic[:IpAddress]).to eq(@test_data[:network_1_ip])
99
+ expect(primary_nic[:IpAddressAllocationMode]).to eq('MANUAL')
100
100
 
101
101
  second_nic = vm_network_connection.detect { |connection| connection[:network] == @test_data[:network_2] }
102
- second_nic[:network].should eq(@test_data[:network_2])
103
- second_nic[:NetworkConnectionIndex].should eq('1')
104
- second_nic[:IpAddress].should eq(@test_data[:network_2_ip])
105
- second_nic[:IpAddressAllocationMode].should eq('MANUAL')
102
+ expect(second_nic[:network]).to eq(@test_data[:network_2])
103
+ expect(second_nic[:NetworkConnectionIndex]).to eq('1')
104
+ expect(second_nic[:IpAddress]).to eq(@test_data[:network_2_ip])
105
+ expect(second_nic[:IpAddressAllocationMode]).to eq('MANUAL')
106
106
 
107
107
  end
108
108
 
109
109
  it 'should assign guest customization script to the VM' do
110
- @vm[:GuestCustomizationSection][:CustomizationScript].should =~ /message: hello world/
111
- @vm[:GuestCustomizationSection][:ComputerName].should eq(@test_data[:vapp_name])
110
+ expect(@vm[:GuestCustomizationSection][:CustomizationScript]).to match(/message: hello world/)
111
+ expect(@vm[:GuestCustomizationSection][:ComputerName]).to eq(@test_data[:vapp_name])
112
112
  end
113
113
 
114
114
  it "should assign storage profile to the VM" do
115
- @vm[:StorageProfile][:name].should eq(@test_data[:storage_profile])
115
+ expect(@vm[:StorageProfile][:name]).to eq(@test_data[:storage_profile])
116
116
  end
117
117
 
118
118
  end
@@ -120,7 +120,7 @@ describe Vcloud::Launcher::Launch do
120
120
  after(:all) do
121
121
  unless ENV['VCLOUD_TOOLS_RSPEC_NO_DELETE_VAPP']
122
122
  File.delete @config_yaml
123
- @fog_interface.delete_vapp(@vapp_id).should eq(true)
123
+ expect(@fog_interface.delete_vapp(@vapp_id)).to eq(true)
124
124
  end
125
125
  end
126
126
 
@@ -143,7 +143,18 @@ describe Vcloud::Launcher::Launch do
143
143
  def define_test_data
144
144
  config_file = File.join(File.dirname(__FILE__),
145
145
  "../vcloud_tools_testing_config.yaml")
146
- parameters = Vcloud::Tools::Tester::TestParameters.new(config_file)
146
+ required_user_params = [
147
+ "vdc_1_name",
148
+ "catalog",
149
+ "vapp_template",
150
+ "storage_profile",
151
+ "network_1",
152
+ "network_2",
153
+ "network_1_ip",
154
+ "network_2_ip",
155
+ ]
156
+
157
+ parameters = Vcloud::Tools::Tester::TestSetup.new(config_file, required_user_params).test_params
147
158
  {
148
159
  vapp_name: "vapp-vcloud-tools-tests-#{Time.now.strftime('%s')}",
149
160
  vdc_name: parameters.vdc_1_name,
@@ -24,58 +24,35 @@ describe Vcloud::Launcher::Launch do
24
24
  @vapp_3 = @fog_interface.get_vapp @vapp_id_3
25
25
  @vm_3 = @vapp_3[:Children][:Vm].first
26
26
 
27
- @vapp_query_result_4 = @fog_interface.get_vapp_by_name_and_vdc_name(@test_data[:vapp_name_4], @test_data[:vdc_1_name])
28
- @vapp_id_4 = @vapp_query_result_4[:href].split('/').last
29
- @vapp_4 = @fog_interface.get_vapp @vapp_id_4
30
- @vm_4 = @vapp_4[:Children][:Vm].first
31
27
  end
32
28
 
33
29
  it "vdc 1 should have a storage profile without the href being specified" do
34
- @vm_1[:StorageProfile][:name].should eq(@test_data[:storage_profile])
30
+ expect(@vm_1[:StorageProfile][:name]).to eq(@test_data[:storage_profile])
35
31
  end
36
32
 
37
33
  it "vdc 1's storage profile should have the expected href" do
38
- @vm_1[:StorageProfile][:href].should eq(@test_data[:vdc_1_sp_href])
34
+ expect(@vm_1[:StorageProfile][:href]).to eq(@test_data[:vdc_1_sp_href])
39
35
  end
40
36
 
41
37
  it "vdc 2 should have the same named storage profile as vdc 1" do
42
- @vm_2[:StorageProfile][:name].should eq(@test_data[:storage_profile])
38
+ expect(@vm_2[:StorageProfile][:name]).to eq(@test_data[:storage_profile])
43
39
  end
44
40
 
45
41
  it "the storage profile in vdc 2 should have a different href to the storage profile in vdc 1" do
46
- @vm_2[:StorageProfile][:href].should eq(@test_data[:vdc_2_sp_href])
42
+ expect(@vm_2[:StorageProfile][:href]).to eq(@test_data[:vdc_2_sp_href])
47
43
  end
48
44
 
49
- it "when a storage profile is not specified, vm uses the default and continues" do
50
- @vm_3[:StorageProfile][:name].should eq(@test_data[:default_storage_profile_name])
51
- @vm_3[:StorageProfile][:href].should eq(@test_data[:default_storage_profile_href])
52
- end
53
-
54
- it "when a storage profile is not specified, customize continues with other customizations" do
55
- @vm_3_id = @vm_3[:href].split('/').last
56
- @vm_3_metadata = Vcloud::Core::Vm.get_metadata @vm_3_id
57
- @vm_3_metadata[:storage_profile_test_vm].should eq(true)
58
- end
59
-
60
- it "when a storage profile specified does not exist, vm uses the default" do
61
- @vm_4[:StorageProfile][:name].should eq(@test_data[:default_storage_profile_name])
62
- @vm_4[:StorageProfile][:href].should eq(@test_data[:default_storage_profile_href])
63
- end
64
-
65
- # This is a bug - if it has failed customization it should let the user know
66
- it "when storage profile specified doesn't exist, it errors and continues" do
67
- @vm_4_id = @vm_4[:href].split('/').last
68
- @vm_4_metadata = Vcloud::Core::Vm.get_metadata @vm_4_id
69
- @vm_4_metadata[:storage_profile_test_vm].should be_nil
45
+ it "when a storage profile is not specified, vm uses the default" do
46
+ expect(@vm_3[:StorageProfile][:name]).to eq(@test_data[:default_storage_profile_name])
47
+ expect(@vm_3[:StorageProfile][:href]).to eq(@test_data[:default_storage_profile_href])
70
48
  end
71
49
 
72
50
  after(:all) do
73
51
  unless ENV['VCLOUD_TOOLS_RSPEC_NO_DELETE_VAPP']
74
52
  File.delete @config_yaml
75
- @fog_interface.delete_vapp(@vapp_id_1).should eq(true)
76
- @fog_interface.delete_vapp(@vapp_id_2).should eq(true)
77
- @fog_interface.delete_vapp(@vapp_id_3).should eq(true)
78
- @fog_interface.delete_vapp(@vapp_id_4).should eq(true)
53
+ expect(@fog_interface.delete_vapp(@vapp_id_1)).to eq(true)
54
+ expect(@fog_interface.delete_vapp(@vapp_id_2)).to eq(true)
55
+ expect(@fog_interface.delete_vapp(@vapp_id_3)).to eq(true)
79
56
  end
80
57
  end
81
58
 
@@ -86,12 +63,23 @@ end
86
63
  def define_test_data
87
64
  config_file = File.join(File.dirname(__FILE__),
88
65
  "../vcloud_tools_testing_config.yaml")
89
- parameters = Vcloud::Tools::Tester::TestParameters.new(config_file)
66
+ required_user_parameters = [
67
+ "vdc_1_name",
68
+ "vdc_2_name",
69
+ "catalog",
70
+ "vapp_template",
71
+ "storage_profile",
72
+ "vdc_1_storage_profile_href",
73
+ "vdc_2_storage_profile_href",
74
+ "default_storage_profile_name",
75
+ "default_storage_profile_href",
76
+ ]
77
+
78
+ parameters = Vcloud::Tools::Tester::TestSetup.new(config_file, required_user_parameters).test_params
90
79
  {
91
80
  vapp_name_1: "vdc-1-sp-#{Time.now.strftime('%s')}",
92
81
  vapp_name_2: "vdc-2-sp-#{Time.now.strftime('%s')}",
93
82
  vapp_name_3: "vdc-3-sp-#{Time.now.strftime('%s')}",
94
- vapp_name_4: "vdc-4-sp-#{Time.now.strftime('%s')}",
95
83
  vdc_1_name: parameters.vdc_1_name,
96
84
  vdc_2_name: parameters.vdc_2_name,
97
85
  catalog: parameters.catalog,
@@ -1,2 +1,31 @@
1
+ # SimpleCov must run _first_ according to its README
2
+ if ENV['COVERAGE']
3
+ require 'simplecov'
4
+
5
+ # monkey-patch to prevent SimpleCov from reporting coverage percentage
6
+ class SimpleCov::Formatter::HTMLFormatter
7
+ def output_message(_message)
8
+ nil
9
+ end
10
+ end
11
+
12
+ SimpleCov.adapters.define 'gem' do
13
+ add_filter '/spec/'
14
+ add_filter '/features/'
15
+ add_filter '/vendor/'
16
+
17
+ add_group 'Libraries', '/lib/'
18
+ end
19
+
20
+ SimpleCov.minimum_coverage(99)
21
+ SimpleCov.start 'gem'
22
+ end
23
+
1
24
  require 'erb_helper'
2
25
  require 'vcloud/launcher'
26
+
27
+ RSpec.configure do |config|
28
+ config.expect_with :rspec do |c|
29
+ c.syntax = :expect
30
+ end
31
+ end
@@ -0,0 +1,214 @@
1
+ require 'spec_helper'
2
+
3
+ class CommandRun
4
+ attr_accessor :stdout, :stderr, :exitstatus
5
+
6
+ def initialize(args)
7
+ out = StringIO.new
8
+ err = StringIO.new
9
+
10
+ $stdout = out
11
+ $stderr = err
12
+
13
+ begin
14
+ Vcloud::Launcher::Cli.new(args).run
15
+ @exitstatus = 0
16
+ rescue SystemExit => e
17
+ # Capture exit(n) value.
18
+ @exitstatus = e.status
19
+ end
20
+
21
+ @stdout = out.string.strip
22
+ @stderr = err.string.strip
23
+
24
+ $stdout = STDOUT
25
+ $stderr = STDERR
26
+ end
27
+ end
28
+
29
+ describe Vcloud::Launcher::Cli do
30
+ subject { CommandRun.new(args) }
31
+
32
+ let(:mock_launch) {
33
+ double(:launch, :run => true)
34
+ }
35
+ let(:config_file) { 'config.yaml' }
36
+
37
+ describe "under normal usage" do
38
+ shared_examples "a good CLI command" do
39
+ it "passes the right CLI options and exits normally" do
40
+ expect(Vcloud::Launcher::Launch).to receive(:new).
41
+ and_return(mock_launch)
42
+ expect(mock_launch).to receive(:run).
43
+ with(config_file, cli_options)
44
+ expect(subject.exitstatus).to eq(0)
45
+ end
46
+ end
47
+
48
+ context "when given a single config file" do
49
+ let(:args) { [ config_file ] }
50
+ let(:cli_options) {
51
+ {
52
+ "dont-power-on" => false,
53
+ "continue-on-error" => false,
54
+ "quiet" => false,
55
+ "verbose" => false,
56
+ }
57
+ }
58
+
59
+ it_behaves_like "a good CLI command"
60
+ end
61
+
62
+ context "when asked not to power VMs on" do
63
+ let(:args) { [ config_file, "--dont-power-on" ] }
64
+ let(:cli_options) {
65
+ {
66
+ "dont-power-on" => true,
67
+ "continue-on-error" => false,
68
+ "quiet" => false,
69
+ "verbose" => false,
70
+ }
71
+ }
72
+
73
+ it_behaves_like "a good CLI command"
74
+ end
75
+
76
+ context "when asked to continue on error" do
77
+ let(:args) { [ config_file, "--continue-on-error" ] }
78
+ let(:cli_options) {
79
+ {
80
+ "dont-power-on" => false,
81
+ "continue-on-error" => true,
82
+ "quiet" => false,
83
+ "verbose" => false,
84
+ }
85
+ }
86
+
87
+ it_behaves_like "a good CLI command"
88
+ end
89
+
90
+ context "when asked to be quiet" do
91
+ let(:args) { [ config_file, "--quiet" ] }
92
+ let(:cli_options) {
93
+ {
94
+ "dont-power-on" => false,
95
+ "continue-on-error" => false,
96
+ "quiet" => true,
97
+ "verbose" => false,
98
+ }
99
+ }
100
+
101
+ it_behaves_like "a good CLI command"
102
+ end
103
+
104
+ context "when asked to be verbose" do
105
+ let(:args) { [ config_file, "--verbose" ] }
106
+ let(:cli_options) {
107
+ {
108
+ "dont-power-on" => false,
109
+ "continue-on-error" => false,
110
+ "quiet" => false,
111
+ "verbose" => true,
112
+ }
113
+ }
114
+
115
+ it_behaves_like "a good CLI command"
116
+ end
117
+
118
+ context "when asked to be verbose and continue on errors" do
119
+ let(:args) { [ config_file, "--continue-on-error", "--verbose" ] }
120
+ let(:cli_options) {
121
+ {
122
+ "dont-power-on" => false,
123
+ "continue-on-error" => true,
124
+ "quiet" => false,
125
+ "verbose" => true,
126
+ }
127
+ }
128
+
129
+ it_behaves_like "a good CLI command"
130
+ end
131
+
132
+ context "when asked to display version" do
133
+ let(:args) { %w{--version} }
134
+
135
+ it "does not call Launch" do
136
+ expect(Vcloud::Launcher::Launch).not_to receive(:new)
137
+ end
138
+
139
+ it "prints version and exits normally" do
140
+ expect(subject.stdout).to eq(Vcloud::Launcher::VERSION)
141
+ expect(subject.exitstatus).to eq(0)
142
+ end
143
+ end
144
+
145
+ context "when asked to display help" do
146
+ let(:args) { %w{--help} }
147
+
148
+ it "does not call Launch" do
149
+ expect(Vcloud::Launcher::Launch).not_to receive(:new)
150
+ end
151
+
152
+ it "prints usage and exits normally" do
153
+ expect(subject.stderr).to match(/\AUsage: \S+ \[options\] config_file\n/)
154
+ expect(subject.exitstatus).to eq(0)
155
+ end
156
+ end
157
+ end
158
+
159
+ describe "incorrect usage" do
160
+ shared_examples "print usage and exit abnormally" do |error|
161
+ it "does not call Launch" do
162
+ expect(Vcloud::Launcher::Launch).not_to receive(:new)
163
+ end
164
+
165
+ it "prints error message and usage" do
166
+ expect(subject.stderr).to match(/\A\S+: #{error}\nUsage: \S+/)
167
+ end
168
+
169
+ it "exits abnormally for incorrect usage" do
170
+ expect(subject.exitstatus).to eq(2)
171
+ end
172
+ end
173
+
174
+ context "when run without any arguments" do
175
+ let(:args) { %w{} }
176
+
177
+ it_behaves_like "print usage and exit abnormally", "must supply config_file"
178
+ end
179
+
180
+ context "when given multiple config files" do
181
+ let(:args) { %w{one.yaml two.yaml} }
182
+
183
+ it_behaves_like "print usage and exit abnormally", "must supply config_file"
184
+ end
185
+
186
+ context "when given an unrecognised argument" do
187
+ let(:args) { %w{--this-is-garbage} }
188
+
189
+ it_behaves_like "print usage and exit abnormally", "invalid option: --this-is-garbage"
190
+ end
191
+ end
192
+
193
+ describe "error handling" do
194
+ context "when underlying code raises an exception" do
195
+ let(:args) { %w{test.yaml} }
196
+
197
+ it "should print error without backtrace and exit abnormally" do
198
+ expect(Vcloud::Launcher::Launch).to receive(:new).
199
+ and_raise("something went horribly wrong")
200
+ expect(subject.stderr).to eq("something went horribly wrong")
201
+ expect(subject.exitstatus).to eq(1)
202
+ end
203
+ end
204
+
205
+ context "when passed an non-existent configuration file" do
206
+ let(:args) { %w{non-existent.yaml} }
207
+
208
+ it "raises a descriptive error" do
209
+ expect(subject.stderr).to match("No such file or directory(?: @ rb_sysopen)? - non-existent.yaml")
210
+ expect(subject.exitstatus).to eq(1)
211
+ end
212
+ end
213
+ end
214
+ end