vcloud-core 0.0.1
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/.gitignore +2 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +20 -0
- data/README.md +103 -0
- data/Rakefile +18 -0
- data/bin/vcloud-query +84 -0
- data/jenkins.sh +10 -0
- data/lib/vcloud/core.rb +23 -0
- data/lib/vcloud/core/compute_metadata.rb +13 -0
- data/lib/vcloud/core/edge_gateway.rb +46 -0
- data/lib/vcloud/core/entity.rb +23 -0
- data/lib/vcloud/core/metadata_helper.rb +29 -0
- data/lib/vcloud/core/org_vdc_network.rb +102 -0
- data/lib/vcloud/core/query.rb +142 -0
- data/lib/vcloud/core/vapp.rb +118 -0
- data/lib/vcloud/core/vapp_template.rb +39 -0
- data/lib/vcloud/core/vdc.rb +37 -0
- data/lib/vcloud/core/version.rb +5 -0
- data/lib/vcloud/core/vm.rb +162 -0
- data/lib/vcloud/fog.rb +5 -0
- data/lib/vcloud/fog/content_types.rb +20 -0
- data/lib/vcloud/fog/model_interface.rb +33 -0
- data/lib/vcloud/fog/relation.rb +8 -0
- data/lib/vcloud/fog/service_interface.rb +257 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/stub_fog_interface.rb +59 -0
- data/spec/vcloud/core/edge_gateway_spec.rb +79 -0
- data/spec/vcloud/core/metadata_helper_spec.rb +89 -0
- data/spec/vcloud/core/org_vdc_network_spec.rb +257 -0
- data/spec/vcloud/core/query_spec.rb +111 -0
- data/spec/vcloud/core/vapp_spec.rb +173 -0
- data/spec/vcloud/core/vapp_template_spec.rb +77 -0
- data/spec/vcloud/core/vdc_spec.rb +68 -0
- data/spec/vcloud/core/vm_spec.rb +290 -0
- data/spec/vcloud/data/basic_preamble_test.erb +8 -0
- data/spec/vcloud/data/basic_preamble_test.erb.OUT +8 -0
- data/spec/vcloud/fog/fog_model_interface_spec.rb +25 -0
- data/spec/vcloud/fog/service_interface_spec.rb +30 -0
- data/vcloud-core.gemspec +30 -0
- metadata +198 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Vcloud
|
4
|
+
module Core
|
5
|
+
describe MetadataHelper do
|
6
|
+
context "get_metadata" do
|
7
|
+
|
8
|
+
it "should process valid metadata types" do
|
9
|
+
metadata_entries = [
|
10
|
+
{
|
11
|
+
:type => Fog::ContentTypes::METADATA,
|
12
|
+
:Key => 'role_name',
|
13
|
+
:TypedValue => {
|
14
|
+
:xsi_type => 'MetadataStringValue',
|
15
|
+
:Value => 'james-bond'
|
16
|
+
}},
|
17
|
+
{
|
18
|
+
:type => Fog::ContentTypes::METADATA,
|
19
|
+
:Key => "server_number",
|
20
|
+
:TypedValue => {:xsi_type => "MetadataNumberValue", :Value => "-10"}
|
21
|
+
},
|
22
|
+
{
|
23
|
+
:type => Fog::ContentTypes::METADATA,
|
24
|
+
:Key => "created_at",
|
25
|
+
:TypedValue => {:xsi_type => "MetadataDateTimeValue", :Value => "2013-12-16T14:30:05.000Z"}
|
26
|
+
},
|
27
|
+
{
|
28
|
+
:type => Fog::ContentTypes::METADATA,
|
29
|
+
:Key => "daily_shutdown",
|
30
|
+
:TypedValue => {:xsi_type => "MetadataBooleanValue", :Value => "false"}
|
31
|
+
}
|
32
|
+
]
|
33
|
+
metadata = MetadataHelper.extract_metadata(metadata_entries)
|
34
|
+
metadata.count.should == 4
|
35
|
+
metadata[:role_name].should == 'james-bond'
|
36
|
+
metadata[:server_number].should == -10
|
37
|
+
metadata[:created_at].should == DateTime.parse("2013-12-16T14:30:05.000Z")
|
38
|
+
metadata[:daily_shutdown].should == false
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should skip metadata entry if entry type is not application/vnd.vmware.vcloud.metadata.value+xml" do
|
42
|
+
metadata_entries = [
|
43
|
+
{
|
44
|
+
:type => Fog::ContentTypes::METADATA,
|
45
|
+
:Key => 'role_name',
|
46
|
+
:TypedValue => {
|
47
|
+
:xsi_type => 'MetadataStringValue',
|
48
|
+
:Value => 'james-bond'
|
49
|
+
}},
|
50
|
+
{
|
51
|
+
:Key => "untyped_key",
|
52
|
+
:TypedValue => {:xsi_type => "MetadataNumberValue", :Value => "-10"}
|
53
|
+
},
|
54
|
+
|
55
|
+
]
|
56
|
+
metadata = MetadataHelper.extract_metadata(metadata_entries)
|
57
|
+
metadata.count.should == 1
|
58
|
+
metadata.keys.should_not include :untyped_key
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should include unrecognized metadata types" do
|
62
|
+
metadata_entries = [
|
63
|
+
{
|
64
|
+
:type => Fog::ContentTypes::METADATA,
|
65
|
+
:Key => 'role_name',
|
66
|
+
:TypedValue => {
|
67
|
+
:xsi_type => 'MetadataStringValue',
|
68
|
+
:Value => 'james-bond'
|
69
|
+
}},
|
70
|
+
{
|
71
|
+
:type => Fog::ContentTypes::METADATA,
|
72
|
+
:Key => "unrecognized_type_key",
|
73
|
+
:TypedValue => {:xsi_type => "MetadataWholeNumberValue", :Value => "-10"}
|
74
|
+
},
|
75
|
+
|
76
|
+
]
|
77
|
+
metadata = MetadataHelper.extract_metadata(metadata_entries)
|
78
|
+
metadata.count.should == 2
|
79
|
+
metadata.keys.should include :unrecognized_type_key
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Vcloud
|
4
|
+
module Core
|
5
|
+
describe OrgVdcNetwork do
|
6
|
+
|
7
|
+
before (:each) do
|
8
|
+
@vdc_id = '12345678-1234-1234-1234-000000111111'
|
9
|
+
@edgegw_id = '12345678-1234-1234-1234-000000222222'
|
10
|
+
@net_id = '12345678-1234-1234-1234-000000333333'
|
11
|
+
@vdc_name = 'test-vdc-1'
|
12
|
+
@net_name = 'test-net-1'
|
13
|
+
@mock_fog_interface = StubFogInterface.new
|
14
|
+
Vcloud::Fog::ServiceInterface.stub(:new).and_return(@mock_fog_interface)
|
15
|
+
Vdc.any_instance.stub(:id).and_return(@vdc_id)
|
16
|
+
@mock_vdc = double(:vdc, :id => @vdc_id)
|
17
|
+
Vdc.stub(:get_by_name).and_return(@mock_vdc)
|
18
|
+
end
|
19
|
+
|
20
|
+
context "Class public interface" do
|
21
|
+
it { OrgVdcNetwork.should respond_to(:provision) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context "Object public interface" do
|
25
|
+
subject { OrgVdcNetwork.new(@net_id) }
|
26
|
+
it { should respond_to(:id) }
|
27
|
+
it { should respond_to(:name) }
|
28
|
+
it { should respond_to(:href) }
|
29
|
+
it { should respond_to(:delete) }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "#initialize" do
|
33
|
+
|
34
|
+
it "should be constructable from just an id reference" do
|
35
|
+
obj = OrgVdcNetwork.new(@net_id)
|
36
|
+
expect(obj.class).to be(Vcloud::Core::OrgVdcNetwork)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should store the id specified" do
|
40
|
+
obj = OrgVdcNetwork.new(@net_id)
|
41
|
+
expect(obj.id) == @net_id
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should raise error if id is not in correct format" do
|
45
|
+
bogus_id = '123123-bogus-id-123445'
|
46
|
+
expect{ OrgVdcNetwork.new(bogus_id) }.
|
47
|
+
to raise_error("orgVdcNetwork id : #{bogus_id} is not in correct format" )
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context "#delete" do
|
53
|
+
it "should call down to Fog::ServiceInterface.delete_network with the correct id" do
|
54
|
+
@mock_fog_interface.should_receive(:delete_network).with(@net_id)
|
55
|
+
OrgVdcNetwork.new(@net_id).delete
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "#provision" do
|
60
|
+
|
61
|
+
before(:each) do
|
62
|
+
@mock_vdc = double(
|
63
|
+
:vdc,
|
64
|
+
:id => @vdc_id,
|
65
|
+
:href => "/#{@vdc_id}",
|
66
|
+
:name => @vdc_name
|
67
|
+
)
|
68
|
+
Vdc.stub(:get_by_name).and_return(@mock_vdc)
|
69
|
+
end
|
70
|
+
|
71
|
+
context "should fail gracefully on bad input" do
|
72
|
+
|
73
|
+
before(:each) do
|
74
|
+
@config = {
|
75
|
+
:name => @net_name,
|
76
|
+
:vdc_name => @vdc_name,
|
77
|
+
:fence_mode => 'isolated'
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should fail if :name is not set" do
|
82
|
+
@config.delete(:name)
|
83
|
+
expect { Vcloud::Core::OrgVdcNetwork.provision(@config) }.
|
84
|
+
to raise_exception(RuntimeError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should fail if :vdc_name is not set" do
|
88
|
+
@config.delete(:vdc_name)
|
89
|
+
expect { Vcloud::Core::OrgVdcNetwork.provision(@config) }.
|
90
|
+
to raise_exception(RuntimeError)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should fail if :fence_mode is not set" do
|
94
|
+
@config.delete(:fence_mode)
|
95
|
+
expect { Vcloud::Core::OrgVdcNetwork.provision(@config) }.
|
96
|
+
to raise_exception(RuntimeError)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should fail if :fence_mode is not 'isolated' or 'natRouted'" do
|
100
|
+
@config[:fence_mode] = 'testfail'
|
101
|
+
expect { Vcloud::Core::OrgVdcNetwork.provision(@config) }.
|
102
|
+
to raise_exception(RuntimeError)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
context "isolated orgVdcNetwork" do
|
108
|
+
|
109
|
+
before(:each) do
|
110
|
+
q_results = [
|
111
|
+
{ :name => @net_name, :href => "/#{@net_id}" }
|
112
|
+
]
|
113
|
+
@mock_net_query = double(:query, :get_all_results => q_results)
|
114
|
+
@config = {
|
115
|
+
:name => @net_name,
|
116
|
+
:vdc_name => @vdc_name,
|
117
|
+
:fence_mode => 'isolated'
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should create an OrgVdcNetwork with minimal config" do
|
122
|
+
expected_vcloud_attrs = {
|
123
|
+
:IsShared => false,
|
124
|
+
:Configuration => {
|
125
|
+
:FenceMode => 'isolated',
|
126
|
+
:IpScopes => {
|
127
|
+
:IpScope => {
|
128
|
+
:IsInherited => false,
|
129
|
+
:IsEnabled => true
|
130
|
+
}
|
131
|
+
}
|
132
|
+
},
|
133
|
+
}
|
134
|
+
Vcloud::Core.logger.should_receive(:info)
|
135
|
+
@mock_fog_interface.should_receive(:post_create_org_vdc_network).
|
136
|
+
with(@vdc_id, @config[:name], expected_vcloud_attrs).
|
137
|
+
and_return({ :href => "/#{@net_id}" })
|
138
|
+
obj = Vcloud::Core::OrgVdcNetwork.provision(@config)
|
139
|
+
expect(obj.id) == @net_id
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should handle specification of one ip_ranges" do
|
143
|
+
@config[:ip_ranges] = [
|
144
|
+
{ :start_address => '10.53.53.100', :end_address => '10.53.53.110' }
|
145
|
+
]
|
146
|
+
expected_vcloud_attrs = {
|
147
|
+
:IsShared => false,
|
148
|
+
:Configuration => {
|
149
|
+
:FenceMode => 'isolated',
|
150
|
+
:IpScopes => {
|
151
|
+
:IpScope => {
|
152
|
+
:IsInherited => false,
|
153
|
+
:IsEnabled => true,
|
154
|
+
:IpRanges => [{
|
155
|
+
:IpRange => {
|
156
|
+
:StartAddress => '10.53.53.100',
|
157
|
+
:EndAddress => '10.53.53.110'
|
158
|
+
},
|
159
|
+
}],
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
Vcloud::Core.logger.should_receive(:info)
|
165
|
+
@mock_fog_interface.should_receive(:post_create_org_vdc_network).
|
166
|
+
with(@vdc_id, @config[:name], expected_vcloud_attrs).
|
167
|
+
and_return({ :href => "/#{@net_id}" })
|
168
|
+
obj = Vcloud::Core::OrgVdcNetwork.provision(@config)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should handle specification of two ip_ranges" do
|
172
|
+
@config[:ip_ranges] = [
|
173
|
+
{ :start_address => '10.53.53.100', :end_address => '10.53.53.110' },
|
174
|
+
{ :start_address => '10.53.53.120', :end_address => '10.53.53.130' },
|
175
|
+
]
|
176
|
+
expected_vcloud_attrs = {
|
177
|
+
:IsShared => false,
|
178
|
+
:Configuration => {
|
179
|
+
:FenceMode => 'isolated',
|
180
|
+
:IpScopes => {
|
181
|
+
:IpScope => {
|
182
|
+
:IsInherited => false,
|
183
|
+
:IsEnabled => true,
|
184
|
+
:IpRanges => [
|
185
|
+
{ :IpRange =>
|
186
|
+
{
|
187
|
+
:StartAddress => '10.53.53.100',
|
188
|
+
:EndAddress => '10.53.53.110'
|
189
|
+
}
|
190
|
+
},
|
191
|
+
{ :IpRange =>
|
192
|
+
{
|
193
|
+
:StartAddress => '10.53.53.120',
|
194
|
+
:EndAddress => '10.53.53.130'
|
195
|
+
}
|
196
|
+
},
|
197
|
+
]
|
198
|
+
}
|
199
|
+
}
|
200
|
+
},
|
201
|
+
}
|
202
|
+
Vcloud::Core.logger.should_receive(:info)
|
203
|
+
@mock_fog_interface.should_receive(:post_create_org_vdc_network).
|
204
|
+
with(@vdc_id, @config[:name], expected_vcloud_attrs).
|
205
|
+
and_return({ :href => "/#{@net_id}" })
|
206
|
+
obj = Vcloud::Core::OrgVdcNetwork.provision(@config)
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
context "natRouted orgVdcNetwork" do
|
212
|
+
|
213
|
+
before(:each) do
|
214
|
+
@config = {
|
215
|
+
:name => @net_name,
|
216
|
+
:vdc_name => @vdc_name,
|
217
|
+
:fence_mode => 'natRouted'
|
218
|
+
}
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should fail if an edge_gateway is not supplied" do
|
222
|
+
expect{ Vcloud::Core::OrgVdcNetwork.provision(@config) }.
|
223
|
+
to raise_exception(RuntimeError)
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should handle lack of ip_ranges on natRouted networks" do
|
227
|
+
@config[:edge_gateway] = 'test gateway'
|
228
|
+
mock_edgegw = Vcloud::Core::EdgeGateway.new(@edgegw_id)
|
229
|
+
Vcloud::Core::EdgeGateway.stub(:get_by_name).and_return(mock_edgegw)
|
230
|
+
|
231
|
+
expected_vcloud_attrs = {
|
232
|
+
:IsShared => false,
|
233
|
+
:Configuration => {
|
234
|
+
:FenceMode => 'natRouted',
|
235
|
+
:IpScopes => {
|
236
|
+
:IpScope => {
|
237
|
+
:IsInherited => false,
|
238
|
+
:IsEnabled => true
|
239
|
+
}
|
240
|
+
}
|
241
|
+
},
|
242
|
+
:EdgeGateway => { :href => "/#{@edgegw_id}" },
|
243
|
+
}
|
244
|
+
Vcloud::Core.logger.should_receive(:info)
|
245
|
+
@mock_fog_interface.should_receive(:post_create_org_vdc_network).
|
246
|
+
with(@vdc_id, @config[:name], expected_vcloud_attrs).
|
247
|
+
and_return({ :href => "/#{@net_id}" })
|
248
|
+
obj = Vcloud::Core::OrgVdcNetwork.provision(@config)
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vcloud::Query do
|
4
|
+
context "attributes" do
|
5
|
+
|
6
|
+
context "our object should have methods" do
|
7
|
+
before(:each) do
|
8
|
+
@mock_fog_interface = StubFogInterface.new
|
9
|
+
Vcloud::Fog::ServiceInterface.stub(:new).and_return(@mock_fog_interface)
|
10
|
+
@query = Vcloud::Query.new()
|
11
|
+
end
|
12
|
+
it { @query.should respond_to(:run) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "#run with no type set" do
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
@mock_fog_interface = StubFogInterface.new
|
19
|
+
Vcloud::Fog::ServiceInterface.stub(:new).and_return(@mock_fog_interface)
|
20
|
+
@query = @query = Vcloud::Query.new()
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should call output_potential_query_types when run not provided with a type" do
|
24
|
+
@query.should_receive(:output_potential_query_types)
|
25
|
+
@query.run()
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should output viable types when run not provided with a type" do
|
29
|
+
@mock_fog_interface.stub(:get_execute_query).and_return(
|
30
|
+
{ :Link => [
|
31
|
+
{:rel=>"down",
|
32
|
+
:href=>"query?type=alice&format=references"},
|
33
|
+
{:rel=>"down",
|
34
|
+
:href=>"query?type=alice&format=records"},
|
35
|
+
{:rel=>"down",
|
36
|
+
:href=>"query?type=bob&format=records"},
|
37
|
+
]})
|
38
|
+
|
39
|
+
@query.should_receive(:puts).with("alice records,references")
|
40
|
+
@query.should_receive(:puts).with("bob records")
|
41
|
+
|
42
|
+
@query.run
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context "gracefully handle zero results" do
|
48
|
+
before(:each) do
|
49
|
+
@mock_fog_interface = StubFogInterface.new
|
50
|
+
Vcloud::Fog::ServiceInterface.stub(:new).and_return(@mock_fog_interface)
|
51
|
+
@query = Vcloud::Query.new('bob')
|
52
|
+
@mock_fog_interface.stub(:get_execute_query).and_return({})
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should not output when given tsv output_format" do
|
56
|
+
@query = Vcloud::Query.new('bob', :output_format => 'tsv')
|
57
|
+
@query.should_not_receive(:puts)
|
58
|
+
@query.run()
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should not output when given csv output_format" do
|
62
|
+
@query = Vcloud::Query.new('bob', :output_format => 'csv')
|
63
|
+
@query.should_not_receive(:puts)
|
64
|
+
@query.run()
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
context "get results with a single response page" do
|
70
|
+
|
71
|
+
before(:each) do
|
72
|
+
@mock_fog_interface = StubFogInterface.new
|
73
|
+
Vcloud::Fog::ServiceInterface.stub(:new).and_return(@mock_fog_interface)
|
74
|
+
@query = Vcloud::Query.new('bob')
|
75
|
+
@mock_fog_interface.stub(:get_execute_query).and_return( {
|
76
|
+
:WibbleRecord=>
|
77
|
+
[{:field1=>"Stuff 1",
|
78
|
+
:field2=>"Stuff 2",
|
79
|
+
:field3=>"Stuff 3",
|
80
|
+
},
|
81
|
+
{:field1=>"More Stuff 1",
|
82
|
+
:field2=>"More Stuff 2",
|
83
|
+
:field3=>"More Stuff 3",
|
84
|
+
},
|
85
|
+
]
|
86
|
+
} )
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should output a query in tsv when run with a type" do
|
90
|
+
@query = Vcloud::Query.new('bob', :output_format => 'tsv')
|
91
|
+
@query.should_receive(:puts).with("field1\tfield2\tfield3")
|
92
|
+
@query.should_receive(:puts).with("Stuff 1\tStuff 2\tStuff 3")
|
93
|
+
@query.should_receive(:puts).with("More Stuff 1\tMore Stuff 2\tMore Stuff 3")
|
94
|
+
@query.run()
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should output a query in csv when run with a type" do
|
98
|
+
@query = Vcloud::Query.new('bob', :output_format => 'csv')
|
99
|
+
@query.should_receive(:puts).with("field1,field2,field3\n")
|
100
|
+
@query.should_receive(:puts).with("Stuff 1,Stuff 2,Stuff 3\nMore Stuff 1,More Stuff 2,More Stuff 3\n")
|
101
|
+
@query.run()
|
102
|
+
end
|
103
|
+
|
104
|
+
# it "should output a query in yaml when run with a type"
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|