vcloud-core 0.5.0 → 0.6.0

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.
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