vcloud-core 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.travis.yml +2 -0
  2. data/CHANGELOG.md +10 -1
  3. data/CONTRIBUTING.md +66 -0
  4. data/README.md +5 -5
  5. data/Rakefile +1 -1
  6. data/lib/vcloud/core/config_validator.rb +20 -20
  7. data/lib/vcloud/core/query_cli.rb +1 -1
  8. data/lib/vcloud/core/version.rb +1 -1
  9. data/lib/vcloud/core/vm.rb +2 -39
  10. data/lib/vcloud/fog/service_interface.rb +10 -5
  11. data/spec/integration/README.md +1 -1
  12. data/spec/integration/core/edge_gateway_spec.rb +133 -0
  13. data/spec/integration/core/query_runner_spec.rb +10 -4
  14. data/spec/integration/core/vapp_spec.rb +249 -0
  15. data/spec/integration/core/vdc_spec.rb +6 -4
  16. data/spec/integration/core/vm_spec.rb +24 -12
  17. data/spec/spec_helper.rb +21 -10
  18. data/spec/support/integration_helper.rb +27 -0
  19. data/spec/vcloud/core/config_loader_spec.rb +10 -10
  20. data/spec/vcloud/core/config_validator_spec.rb +7 -0
  21. data/spec/vcloud/core/edge_gateway_spec.rb +10 -10
  22. data/spec/vcloud/core/metadata_helper_spec.rb +2 -2
  23. data/spec/vcloud/core/org_vdc_network_spec.rb +15 -15
  24. data/spec/vcloud/core/query_runner_spec.rb +13 -13
  25. data/spec/vcloud/core/query_spec.rb +9 -9
  26. data/spec/vcloud/core/vapp_spec.rb +19 -19
  27. data/spec/vcloud/core/vapp_template_spec.rb +9 -9
  28. data/spec/vcloud/core/vdc_spec.rb +6 -6
  29. data/spec/vcloud/core/vm_spec.rb +50 -118
  30. data/spec/vcloud/fog/fog_model_interface_spec.rb +3 -3
  31. data/spec/vcloud/fog/service_interface_spec.rb +9 -9
  32. data/vcloud-core.gemspec +6 -6
  33. metadata +36 -35
  34. data/spec/integration/edge_gateway/configure_edge_gateway_services_spec.rb +0 -55
  35. data/spec/integration/edge_gateway/edge_gateway_spec.rb +0 -45
@@ -0,0 +1,249 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vcloud::Core::Vapp do
4
+
5
+ let(:uuid_matcher) { "[-0-9a-f]+" }
6
+
7
+ before(:all) do
8
+ config_file = File.join(File.dirname(__FILE__), "../vcloud_tools_testing_config.yaml")
9
+ required_user_params = [
10
+ "catalog",
11
+ "network_1",
12
+ "network_2",
13
+ "vapp_template",
14
+ "vdc_1_name",
15
+ ]
16
+
17
+ @test_params = Vcloud::Tools::Tester::TestSetup.new(config_file, required_user_params).test_params
18
+ @vapp_name_prefix = "vcloud-core-vapp-tests"
19
+ quantity_of_test_case_vapps = 1
20
+ @network_names = [ @test_params.network_1, @test_params.network_2 ]
21
+ @test_case_vapps = IntegrationHelper.create_test_case_vapps(
22
+ quantity_of_test_case_vapps,
23
+ @test_params.vdc_1_name,
24
+ @test_params.catalog,
25
+ @test_params.vapp_template,
26
+ @network_names,
27
+ @vapp_name_prefix
28
+ )
29
+ @vapp = @test_case_vapps.first
30
+ end
31
+
32
+ subject(:fixture_vapp) { @vapp }
33
+
34
+ context "before the integration tests run" do
35
+
36
+ it "ensures we have a valid vApp fixture, for subsequent tests to run against" do
37
+ expect(fixture_vapp).to be_instance_of(Vcloud::Core::Vapp)
38
+ end
39
+
40
+ end
41
+
42
+ describe "#vcloud_attributes" do
43
+
44
+ it "has a :href element containing the expected vApp id" do
45
+ expect(fixture_vapp.vcloud_attributes[:href].split('/').last).to eq(fixture_vapp.id)
46
+ end
47
+
48
+ end
49
+
50
+ describe "#id" do
51
+
52
+ it "returns the a valid vApp id" do
53
+ expect(fixture_vapp.id).to match(/^vapp-#{uuid_matcher}$/)
54
+ end
55
+
56
+ end
57
+
58
+ describe "#name" do
59
+
60
+ it "returns the name of the vApp" do
61
+ expect(fixture_vapp.name).to include(@vapp_name_prefix)
62
+ end
63
+
64
+ end
65
+
66
+ describe "#vdc_id" do
67
+
68
+ it "returns a valid uuid" do
69
+ expect(fixture_vapp.vdc_id).to match(/^#{uuid_matcher}$/)
70
+ end
71
+
72
+ end
73
+
74
+ describe "#networks" do
75
+
76
+ it "returns hashes for each network, plus the 'none' placeholder network" do
77
+ network_output = fixture_vapp.networks
78
+ # The API return a 'placeholder' network hash as well as
79
+ # any configured networks, for any VMs that have disconnected interfaces.
80
+ # This has the :ovf_name of 'none'. So, we expect our @network_names, plus 'none'.
81
+ #
82
+ expect(network_output.map { |network| network[:ovf_name] }).
83
+ to match_array(@network_names + ["none"])
84
+ end
85
+
86
+ end
87
+
88
+ describe "#power_on" do
89
+
90
+ it "powers up a powered down Vapp" do
91
+ expect(Integer(fixture_vapp.vcloud_attributes[:status])).to eq(Vcloud::Core::Vapp::STATUS::POWERED_OFF)
92
+ expect(fixture_vapp.power_on).to be_true
93
+ expect(Integer(fixture_vapp.vcloud_attributes[:status])).to eq(Vcloud::Core::Vapp::STATUS::RUNNING)
94
+ end
95
+
96
+ end
97
+
98
+ describe ".get_by_name" do
99
+
100
+ it "can find our fixture vApp by its name" do
101
+ retrieved_vapp = Vcloud::Core::Vapp.get_by_name(fixture_vapp.name)
102
+ expect(retrieved_vapp.id).to eq(fixture_vapp.id)
103
+ end
104
+
105
+ it "raises an error if it cannot find the named vApp" do
106
+ bogus_vapp_name = "bogus-vapp-name-wefoiuhwef"
107
+ expect {
108
+ Vcloud::Core::Vapp.get_by_name(bogus_vapp_name)
109
+ }.to raise_error("vApp #{bogus_vapp_name} not found")
110
+ end
111
+
112
+ end
113
+
114
+ describe ".instantiate" do
115
+
116
+ let(:vapp_template) {
117
+ Vcloud::Core::VappTemplate.get(@test_params.vapp_template, @test_params.catalog)
118
+ }
119
+
120
+ let(:vapp_name) { "#{@vapp_name_prefix}-instantiate-#{Time.new.to_i}" }
121
+
122
+ it "can create a vApp with no networks assigned" do
123
+ new_vapp = Vcloud::Core::Vapp.instantiate(
124
+ vapp_name,
125
+ [],
126
+ vapp_template.id,
127
+ @test_params.vdc_1_name
128
+ )
129
+ @test_case_vapps << new_vapp
130
+ expect(new_vapp.name).to eq(vapp_name)
131
+ expect(sanitize_networks_output(new_vapp.networks).size).to eq(0)
132
+ end
133
+
134
+ it "can create a vApp with one networks assigned" do
135
+ new_vapp = Vcloud::Core::Vapp.instantiate(
136
+ vapp_name,
137
+ [ @test_params.network_1 ],
138
+ vapp_template.id,
139
+ @test_params.vdc_1_name
140
+ )
141
+ @test_case_vapps << new_vapp
142
+ expect(new_vapp.name).to eq(vapp_name)
143
+ expect(sanitize_networks_output(new_vapp.networks).size).to eq(1)
144
+ end
145
+
146
+ it "can create a vApp with two networks assigned" do
147
+ new_vapp = Vcloud::Core::Vapp.instantiate(
148
+ vapp_name,
149
+ [ @test_params.network_1, @test_params.network_2 ],
150
+ vapp_template.id,
151
+ @test_params.vdc_1_name
152
+ )
153
+ @test_case_vapps << new_vapp
154
+ expect(new_vapp.name).to eq(vapp_name)
155
+ expect(sanitize_networks_output(new_vapp.networks).size).to eq(2)
156
+ end
157
+
158
+ it "raises a Fog error if the vAppTemplate id refers to a non-existent template" do
159
+ expect {
160
+ Vcloud::Core::Vapp.instantiate(
161
+ vapp_name,
162
+ [],
163
+ "vAppTemplate-12345678-1234-1234-1234-1234567890ab",
164
+ @test_params.vdc_1_name
165
+ )
166
+ }.to raise_error(Fog::Compute::VcloudDirector::Forbidden, "Access is forbidden")
167
+ end
168
+
169
+ it "raises a Fog error if the vAppTemplate id is invalid" do
170
+ expect {
171
+ Vcloud::Core::Vapp.instantiate(
172
+ vapp_name,
173
+ [],
174
+ "invalid-vapp-template-id",
175
+ @test_params.vdc_1_name
176
+ )
177
+ }.to raise_error(Fog::Compute::VcloudDirector::Forbidden, "This operation is denied.")
178
+ end
179
+
180
+ it "raises a Fog error if the vAppTemplate id is nil" do
181
+ expect {
182
+ Vcloud::Core::Vapp.instantiate(
183
+ vapp_name,
184
+ [],
185
+ nil,
186
+ @test_params.vdc_1_name
187
+ )
188
+ }.to raise_error(Fog::Compute::VcloudDirector::BadRequest)
189
+ end
190
+
191
+ it "raises an error if we try to instantiate into a non-existent vDC" do
192
+ bogus_vdc_name = "NonExistentVdc asnfiuqwf"
193
+ expect {
194
+ Vcloud::Core::Vapp.instantiate(
195
+ vapp_name,
196
+ [],
197
+ vapp_template.id,
198
+ bogus_vdc_name
199
+ )
200
+ }.to raise_error("vdc #{bogus_vdc_name} cannot be found")
201
+ end
202
+
203
+ it "raises an error if the vDC name is nil" do
204
+ expect {
205
+ Vcloud::Core::Vapp.instantiate(
206
+ vapp_name,
207
+ [],
208
+ vapp_template.id,
209
+ nil
210
+ )
211
+ }.to raise_error("vdc cannot be found")
212
+ end
213
+
214
+ it "skips bogus network names specified in the network_names array" do
215
+ new_vapp = Vcloud::Core::Vapp.instantiate(
216
+ vapp_name,
217
+ ['bogus-network-name-ijwioewiwego', 'bogus-network-name-asofijqweof'],
218
+ vapp_template.id,
219
+ @test_params.vdc_1_name
220
+ )
221
+ @test_case_vapps << new_vapp
222
+ expect(new_vapp.networks).to eq({
223
+ :ovf_name => "none",
224
+ :"ovf:Description" =>
225
+ "This is a special place-holder used for disconnected network interfaces."
226
+ })
227
+ end
228
+
229
+ end
230
+
231
+ after(:all) do
232
+ IntegrationHelper.delete_vapps(@test_case_vapps)
233
+ end
234
+
235
+ def sanitize_networks_output(networks_output)
236
+ if networks_output.is_a?(Hash)
237
+ # Fog currently has a bug (https://github.com/fog/fog/issues/2927) that
238
+ # means the output from Vapp#networks can be a hash or array.
239
+ # Work around this by converting to a single element Array.
240
+ networks_output = [ networks_output ]
241
+ end
242
+ new_output = []
243
+ networks_output.each do |network_hash|
244
+ new_output << network_hash unless network_hash[:ovf_name] == 'none'
245
+ end
246
+ new_output
247
+ end
248
+
249
+ end
@@ -6,7 +6,9 @@ describe Vcloud::Core::Vdc do
6
6
 
7
7
  before(:all) do
8
8
  config_file = File.join(File.dirname(__FILE__), "../vcloud_tools_testing_config.yaml")
9
- @test_data = Vcloud::Tools::Tester::TestParameters.new(config_file)
9
+ required_user_params = %w{ vdc_1_name }
10
+
11
+ @test_params = Vcloud::Tools::Tester::TestSetup.new(config_file, required_user_params).test_params
10
12
  end
11
13
 
12
14
  describe ".get_by_name" do
@@ -15,7 +17,7 @@ describe Vcloud::Core::Vdc do
15
17
 
16
18
  context "when looking up a valid vDC name" do
17
19
 
18
- let(:name) { @test_data.vdc_1_name }
20
+ let(:name) { @test_params.vdc_1_name }
19
21
 
20
22
  it "returns a Vcloud::Core::Vdc object" do
21
23
  expect(subject).to be_instance_of(Vcloud::Core::Vdc)
@@ -49,7 +51,7 @@ describe Vcloud::Core::Vdc do
49
51
 
50
52
  context "when instantiating with a valid ID" do
51
53
 
52
- let(:vdc_id) { Vcloud::Core::Vdc.get_by_name(@test_data.vdc_1_name).id }
54
+ let(:vdc_id) { Vcloud::Core::Vdc.get_by_name(@test_params.vdc_1_name).id }
53
55
 
54
56
  it "returns a valid Vdc object" do
55
57
  expect(subject).to be_instance_of(Vcloud::Core::Vdc)
@@ -60,7 +62,7 @@ describe Vcloud::Core::Vdc do
60
62
  end
61
63
 
62
64
  it "has our expected #name" do
63
- expect(subject.name).to eq(@test_data.vdc_1_name)
65
+ expect(subject.name).to eq(@test_params.vdc_1_name)
64
66
  end
65
67
 
66
68
  end
@@ -4,17 +4,29 @@ describe Vcloud::Core::Vm do
4
4
 
5
5
  before(:all) do
6
6
  config_file = File.join(File.dirname(__FILE__), "../vcloud_tools_testing_config.yaml")
7
- @test_data = Vcloud::Tools::Tester::TestParameters.new(config_file)
8
- @network_names = [ @test_data.network_1, @test_data.network_2 ]
7
+ required_user_params = [
8
+ "catalog",
9
+ "default_storage_profile_name",
10
+ "network_1",
11
+ "network_1_ip",
12
+ "network_2",
13
+ "network_2_ip",
14
+ "storage_profile",
15
+ "vapp_template",
16
+ "vdc_1_name",
17
+ ]
18
+
19
+ @test_params = Vcloud::Tools::Tester::TestSetup.new(config_file, required_user_params).test_params
20
+ @network_names = [ @test_params.network_1, @test_params.network_2 ]
9
21
  @network_ips = {
10
- @test_data.network_1 => @test_data.network_1_ip,
11
- @test_data.network_2 => @test_data.network_2_ip,
22
+ @test_params.network_1 => @test_params.network_1_ip,
23
+ @test_params.network_2 => @test_params.network_2_ip,
12
24
  }
13
25
  @test_case_vapps = IntegrationHelper.create_test_case_vapps(
14
26
  1,
15
- @test_data.vdc_1_name,
16
- @test_data.catalog,
17
- @test_data.vapp_template,
27
+ @test_params.vdc_1_name,
28
+ @test_params.catalog,
29
+ @test_params.vapp_template,
18
30
  @network_names,
19
31
  "vcloud-core-vm-tests"
20
32
  )
@@ -224,15 +236,15 @@ describe Vcloud::Core::Vm do
224
236
  it "can update the storage profile of a VM" do
225
237
  available_storage_profiles = Vcloud::Core::QueryRunner.new.run(
226
238
  'orgVdcStorageProfile',
227
- filter: "vdcName==#{@test_data.vdc_1_name}"
239
+ filter: "vdcName==#{@test_params.vdc_1_name}"
228
240
  )
229
241
  if available_storage_profiles.size == 1
230
- pending("There is only one StorageProfile in vDC #{@test_data.vdc_1_name}: cannot test.")
242
+ pending("There is only one StorageProfile in vDC #{@test_params.vdc_1_name}: cannot test.")
231
243
  end
232
244
  original_storage_profile_name = @vm.vcloud_attributes[:StorageProfile][:name]
233
- expect(original_storage_profile_name).to eq(@test_data.default_storage_profile_name)
234
- @vm.update_storage_profile(@test_data.storage_profile)
235
- expect(@vm.vcloud_attributes[:StorageProfile][:name]).to eq(@test_data.storage_profile)
245
+ expect(original_storage_profile_name).to eq(@test_params.default_storage_profile_name)
246
+ @vm.update_storage_profile(@test_params.storage_profile)
247
+ expect(@vm.vcloud_attributes[:StorageProfile][:name]).to eq(@test_params.storage_profile)
236
248
  end
237
249
 
238
250
  end
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,22 @@
1
+ # SimpleCov must run _first_ according to its README
1
2
  if ENV['COVERAGE']
2
3
  require 'simplecov'
3
4
 
4
- SimpleCov.profiles.define 'gem' do
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
5
13
  add_filter '/spec/'
6
14
  add_filter '/vendor/'
7
15
 
8
16
  add_group 'Libraries', '/lib/'
9
17
  end
10
18
 
19
+ SimpleCov.minimum_coverage(84)
11
20
  SimpleCov.start 'gem'
12
21
  end
13
22
 
@@ -17,14 +26,16 @@ require 'vcloud/tools/tester'
17
26
  require 'support/stub_fog_interface.rb'
18
27
  require 'support/integration_helper'
19
28
 
20
- if ENV['COVERAGE']
21
- SimpleCov.at_exit do
22
- SimpleCov.result.format!
23
- # do not change the coverage percentage, instead add more unit tests to fix coverage failures.
24
- if SimpleCov.result.covered_percent < 81
25
- print "ERROR::BAD_COVERAGE\n"
26
- print "Coverage is less than acceptable limit(81%). Please add more tests to improve the coverage"
27
- exit(1)
28
- end
29
+ RSpec.configure do |config|
30
+ config.expect_with :rspec do |c|
31
+ c.syntax = :expect
29
32
  end
30
33
  end
34
+
35
+ # To enable Fog Mock mode use FOG_CREDENTIAL=fog_mock and FOG_MOCK=true
36
+ # If you do not have configuration for fog_mock in your vcloud_tools_testing_config.yaml,
37
+ # the test data is defined here: https://github.com/fog/fog/blob/master/lib/fog/vcloud_director/compute.rb#L483-L733
38
+ #
39
+ if ENV['FOG_MOCK']
40
+ Fog.mock!
41
+ end
@@ -25,8 +25,35 @@ module IntegrationHelper
25
25
  def self.delete_vapps(vapp_list)
26
26
  fsi = Vcloud::Fog::ServiceInterface.new()
27
27
  vapp_list.each do |vapp|
28
+ if Integer(vapp.vcloud_attributes[:status]) == Vcloud::Core::Vapp::STATUS::RUNNING
29
+ fsi.post_undeploy_vapp(vapp.id)
30
+ end
28
31
  fsi.delete_vapp(vapp.id)
29
32
  end
30
33
  end
31
34
 
35
+ def self.reset_edge_gateway(edge_gateway)
36
+ configuration = {
37
+ :FirewallService =>
38
+ {
39
+ :IsEnabled => "false",
40
+ :FirewallRule => [],
41
+ :DefaultAction => "drop",
42
+ :LogDefaultAction => "false",
43
+ },
44
+ :LoadBalancerService =>
45
+ {
46
+ :IsEnabled => "false",
47
+ :Pool => [],
48
+ :VirtualServer => [],
49
+ },
50
+ :NatService =>
51
+ {
52
+ :IsEnabled => "false",
53
+ :NatRule => [],
54
+ },
55
+ }
56
+
57
+ edge_gateway.update_configuration(configuration)
58
+ end
32
59
  end
@@ -13,21 +13,21 @@ module Vcloud
13
13
  input_file = "#{@data_dir}/working.json"
14
14
  loader = ConfigLoader.new
15
15
  actual_config = loader.load_config(input_file)
16
- valid_config.should eq(actual_config)
16
+ expect(valid_config).to eq(actual_config)
17
17
  end
18
18
 
19
19
  it "should create a valid hash when input is YAML" do
20
20
  input_file = "#{@data_dir}/working.yaml"
21
21
  loader = ConfigLoader.new
22
22
  actual_config = loader.load_config(input_file)
23
- valid_config.should eq(actual_config)
23
+ expect(valid_config).to eq(actual_config)
24
24
  end
25
25
 
26
26
  it "should create a valid hash when input is YAML with anchor defaults" do
27
27
  input_file = "#{@data_dir}/working_with_defaults.yaml"
28
28
  loader = ConfigLoader.new
29
29
  actual_config = loader.load_config(input_file)
30
- valid_config['vapps'].should eq(actual_config['vapps'])
30
+ expect(valid_config['vapps']).to eq(actual_config['vapps'])
31
31
  end
32
32
  end
33
33
 
@@ -37,7 +37,7 @@ module Vcloud
37
37
  vars_file = "#{@data_dir}/working_variables.yaml"
38
38
  loader = ConfigLoader.new
39
39
  actual_config = loader.load_config(input_file, nil, vars_file)
40
- valid_config.should eq(actual_config)
40
+ expect(valid_config).to eq(actual_config)
41
41
  end
42
42
  end
43
43
 
@@ -47,13 +47,13 @@ module Vcloud
47
47
  loader = ConfigLoader.new
48
48
  schema = vapp_config_schema
49
49
  actual_config = loader.load_config(input_file, schema)
50
- valid_config['vapps'].should eq(actual_config['vapps'])
50
+ expect(valid_config['vapps']).to eq(actual_config['vapps'])
51
51
  end
52
52
 
53
53
  it "should raise an error if checked against an invalid schema" do
54
54
  input_file = "#{@data_dir}/working_with_defaults.yaml"
55
55
  loader = ConfigLoader.new
56
- Vcloud::Core.logger.should_receive(:fatal).with("vapps: is not a hash")
56
+ expect(Vcloud::Core.logger).to receive(:fatal).with("vapps: is not a hash")
57
57
  expect { loader.load_config(input_file, invalid_schema) }.
58
58
  to raise_error('Supplied configuration does not match supplied schema')
59
59
  end
@@ -62,7 +62,7 @@ module Vcloud
62
62
  input_file = "#{@data_dir}/working_with_defaults.yaml"
63
63
  loader = ConfigLoader.new
64
64
 
65
- Vcloud::Core.logger.should_not_receive(:warn)
65
+ expect(Vcloud::Core.logger).not_to receive(:warn)
66
66
  loader.load_config(input_file, vapp_config_schema)
67
67
  end
68
68
 
@@ -70,7 +70,7 @@ module Vcloud
70
70
  input_file = "#{@data_dir}/working_with_defaults.yaml"
71
71
  loader = ConfigLoader.new
72
72
 
73
- Vcloud::Core.logger.should_receive(:warn).with("vapps: is deprecated by 'vapps_new'")
73
+ expect(Vcloud::Core.logger).to receive(:warn).with("vapps: is deprecated by 'vapps_new'")
74
74
  loader.load_config(input_file, deprecated_schema)
75
75
  end
76
76
 
@@ -78,8 +78,8 @@ module Vcloud
78
78
  input_file = "#{@data_dir}/working_with_defaults.yaml"
79
79
  loader = ConfigLoader.new
80
80
 
81
- Vcloud::Core.logger.should_receive(:warn).with("vapps: is deprecated by 'vapps_new'")
82
- Vcloud::Core.logger.should_receive(:fatal).with("vapps: is not a hash")
81
+ expect(Vcloud::Core.logger).to receive(:warn).with("vapps: is deprecated by 'vapps_new'")
82
+ expect(Vcloud::Core.logger).to receive(:fatal).with("vapps: is not a hash")
83
83
  expect { loader.load_config(input_file, invalid_and_deprecated_schema) }.
84
84
  to raise_error('Supplied configuration does not match supplied schema')
85
85
  end