vmware-vra 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -2
- data/README.md +43 -6
- data/lib/vra/catalog_item.rb +41 -0
- data/lib/vra/catalog_request.rb +36 -7
- data/lib/vra/request_parameters.rb +9 -3
- data/lib/vra/version.rb +1 -1
- data/spec/catalog_item_spec.rb +144 -0
- data/spec/catalog_request_spec.rb +93 -35
- data/spec/client_spec.rb +25 -0
- data/spec/fixtures/catalog_request_template.json +130 -0
- data/spec/spec_helper.rb +7 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11be1f053e0b79413a97f73d65dd7736e5da7c3c
|
4
|
+
data.tar.gz: 5f034f6c50a4bd6a3ec8ee69a72672deb291747d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12f97a5705101ab63b43212722a3501ac03ba76365f4cb856dfcbc39015ae86de6745c9090bd76c59dfd44362387964eff4e4a5b7cb55a4eab15bf8026aaeb19
|
7
|
+
data.tar.gz: a6b900474a68a4b02064429cba79606423e34f085a46b86f3a73394d837cbf240433238e4b3cc87cb0efa1b5deab6a3c6376e30126e7cc6458cb967ce9786f28
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,21 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [2.
|
4
|
-
[Full Changelog](https://github.com/chef-partners/vmware-vra-gem/compare/v2.
|
3
|
+
## [2.4.0](https://github.com/chef-partners/vmware-vra-gem/tree/2.4.0) (2017-09-19)
|
4
|
+
[Full Changelog](https://github.com/chef-partners/vmware-vra-gem/compare/v2.3.0...2.4.0)
|
5
|
+
|
6
|
+
**Closed issues:**
|
7
|
+
|
8
|
+
- cpu and memory parameters request [\#52](https://github.com/chef-partners/vmware-vra-gem/issues/52)
|
9
|
+
- Minor typo in README [\#51](https://github.com/chef-partners/vmware-vra-gem/issues/51)
|
10
|
+
|
11
|
+
**Merged pull requests:**
|
12
|
+
|
13
|
+
- Adds ability to supply template files to catalog request [\#57](https://github.com/chef-partners/vmware-vra-gem/pull/57) ([logicminds](https://github.com/logicminds))
|
14
|
+
- Adds the ability to dump catalog templates via class methods [\#56](https://github.com/chef-partners/vmware-vra-gem/pull/56) ([logicminds](https://github.com/logicminds))
|
15
|
+
- Symbols [\#53](https://github.com/chef-partners/vmware-vra-gem/pull/53) ([logicminds](https://github.com/logicminds))
|
16
|
+
|
17
|
+
## [v2.3.0](https://github.com/chef-partners/vmware-vra-gem/tree/v2.3.0) (2017-06-30)
|
18
|
+
[Full Changelog](https://github.com/chef-partners/vmware-vra-gem/compare/v2.2.0...v2.3.0)
|
5
19
|
|
6
20
|
**Closed issues:**
|
7
21
|
|
data/README.md
CHANGED
@@ -103,9 +103,9 @@ catalog_request.set_parameter('object~my_parameter', 'string', 'my value')
|
|
103
103
|
```
|
104
104
|
|
105
105
|
### Creating a request from a yaml or json payload
|
106
|
-
Should you want to create a request ahead of time you can create the parameters up front by
|
106
|
+
Should you want to create a request ahead of time you can create the parameters up front by
|
107
107
|
reading from a file or a hard coded payload you use every time. This is not required by any means but allows
|
108
|
-
for some extra flexibility when using this request object directly. The only difference is that you can pass
|
108
|
+
for some extra flexibility when using this request object directly. The only difference is that you can pass
|
109
109
|
in the request parameters instead of having to set them after you create the object.
|
110
110
|
|
111
111
|
Given a sample request object like the following you will want to read the yaml into an ruby object:
|
@@ -131,18 +131,18 @@ And now use that data to create the Vra::RequestParameters to feed into the cata
|
|
131
131
|
```ruby
|
132
132
|
# read in the request data
|
133
133
|
yaml_data = YAML,load(data)
|
134
|
-
# create a parameters array
|
134
|
+
# create a parameters array, although this only works with VRA6, since VRA7 can have complex data
|
135
135
|
parameters = yaml_data['requestData']['entries'].map {|item| [item['key'], item['value'].values].flatten }
|
136
136
|
# We put the values in a array so we can easily explode the parameters using the splat operator later
|
137
|
-
|
138
|
-
# loop through each parameter and setting each parameter
|
137
|
+
request_params = Vra::RequestParameters.new
|
138
|
+
# loop through each parameter and setting each parameter
|
139
139
|
parameters.each {|p| request_params.set(*p) # splat
|
140
140
|
request_options = {
|
141
141
|
cpus: 1,
|
142
142
|
memory: 1024,
|
143
143
|
requested_for: 'me@me.com',
|
144
144
|
lease_days: 2,
|
145
|
-
additional_params:
|
145
|
+
additional_params: request_params
|
146
146
|
}
|
147
147
|
# create the request
|
148
148
|
catalog_request = vra.catalog.request(blueprint, request_options)
|
@@ -230,6 +230,43 @@ vra.resources.all_resources
|
|
230
230
|
vra.requests.all_requests
|
231
231
|
```
|
232
232
|
|
233
|
+
### Download VRA catalog templates
|
234
|
+
It can be quite useful to download the catalog templates from your VRA server for future playback or inspection. This
|
235
|
+
can now be easily done with some helpful class methods.
|
236
|
+
|
237
|
+
To get a json string representation of the catalog template you can use `Vra::CatalogItem.dump_template(client, catalog_id)`
|
238
|
+
|
239
|
+
To dump the catalog template to a file instead of a string `Vra::CatalogItem.write_template(client, catalog_id)`. This will create a file like `windows2012.json`.
|
240
|
+
|
241
|
+
If you just want to dump all the templates you can use `Vra::CatalogItem.dump_templates(client)`. This will create a directory named vra_templates
|
242
|
+
with all the entitled templates for the current user.
|
243
|
+
|
244
|
+
There are additional options you can provide to these methods in order to customize output file names and directories, so please see the source code in lib/vra/catalog_item.rb
|
245
|
+
|
246
|
+
### Supply custom VRA catalog template and create request
|
247
|
+
If you previously had some custom templates already in JSON format you can now use those to create requests instead of setting
|
248
|
+
a bunch of parameters. This can be especially useful when your request has complex parameters or you have a bunch of templates
|
249
|
+
that you want to create unique requests for.
|
250
|
+
|
251
|
+
To use you can do something like:
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
payload_file = '/tmp/windows_2012.json' # must be in json format
|
255
|
+
cr = Vra::CatalogRequest.request_from_payload(client, payload_file)
|
256
|
+
cr.submit
|
257
|
+
|
258
|
+
```
|
259
|
+
|
260
|
+
If you already have a catalog request object you can still supply a custom payload by simply setting the template_payload property.
|
261
|
+
Note this custom payload will be merged with the properties originally set when creating the catalog request object.
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
cr = Vra::CatalogRequest.new(id, opts)
|
265
|
+
cr.template_payload = File.read('/tmp/windows_2012.json')
|
266
|
+
cr.submit
|
267
|
+
|
268
|
+
```
|
269
|
+
|
233
270
|
### Pagination
|
234
271
|
|
235
272
|
vRA paginates API requests where lists of items are returned. By default, this gem will ask vRA to provide items in groups of 20. However, as reported in [Issue 10](https://github.com/chef-partners/vmware-vra-gem/issues/10), it appears vRA may have a pagination bug. You can change the default page size from 20 to a value of your choice by passing in a `page_size` option when setting up the client:
|
data/lib/vra/catalog_item.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
#
|
19
19
|
|
20
20
|
require "ffi_yajl"
|
21
|
+
require "vra/catalog"
|
21
22
|
|
22
23
|
module Vra
|
23
24
|
class CatalogItem
|
@@ -85,5 +86,45 @@ module Vra
|
|
85
86
|
def blueprint_id
|
86
87
|
@catalog_item_data["providerBinding"]["bindingId"]
|
87
88
|
end
|
89
|
+
|
90
|
+
# @param [String] - the id of the catalog item
|
91
|
+
# @param [Vra::Client] - a vra client object
|
92
|
+
# @return [String] - returns a json string of the catalog template
|
93
|
+
def self.dump_template(client, id)
|
94
|
+
response = client.http_get("/catalog-service/api/consumer/entitledCatalogItems/#{id}/requests/template")
|
95
|
+
response.body
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param client [Vra::Client] - a vra client object
|
99
|
+
# @param id [String] - the id of the catalog item
|
100
|
+
# @param filename [String] - the name of the file you want to output the template to
|
101
|
+
# if left blank, will default to the id of the item
|
102
|
+
# @note outputs the catalog template to a file in serialized format
|
103
|
+
def self.write_template(client, id, filename = nil)
|
104
|
+
filename ||= "#{id}.json"
|
105
|
+
begin
|
106
|
+
contents = dump_template(client, id)
|
107
|
+
data = JSON.parse(contents)
|
108
|
+
pretty_contents = JSON.pretty_generate(data)
|
109
|
+
File.write(filename, pretty_contents)
|
110
|
+
return filename
|
111
|
+
rescue Vra::Exception::HTTPError => e
|
112
|
+
raise e
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# @param [Vra::Client] - a vra client object
|
117
|
+
# @param [String] - the directory path to write the files to
|
118
|
+
# @param [Boolean] - set to true if you wish the file name to be the id of the catalog item
|
119
|
+
# @return [Array[String]] - a array of all the files that were generated
|
120
|
+
def self.dump_templates(client, dir_name = "vra_templates", use_id = false)
|
121
|
+
FileUtils.mkdir(dir_name) unless File.exist?(dir_name)
|
122
|
+
client.catalog.entitled_items.map do |c|
|
123
|
+
id = use_id ? c.id : c.name.tr(" ", "_")
|
124
|
+
filename = File.join(dir_name, "#{id}.json").downcase
|
125
|
+
write_template(client, c.id, filename)
|
126
|
+
filename
|
127
|
+
end
|
128
|
+
end
|
88
129
|
end
|
89
130
|
end
|
data/lib/vra/catalog_request.rb
CHANGED
@@ -16,12 +16,13 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
|
+
require "vra/catalog_item"
|
19
20
|
|
20
21
|
module Vra
|
21
22
|
class CatalogRequest
|
22
23
|
attr_reader :catalog_id, :catalog_item, :client, :custom_fields
|
23
24
|
attr_writer :subtenant_id
|
24
|
-
attr_accessor :cpus, :memory, :requested_for, :lease_days, :notes
|
25
|
+
attr_accessor :cpus, :memory, :requested_for, :lease_days, :notes, :template_payload
|
25
26
|
|
26
27
|
def initialize(client, catalog_id, opts = {})
|
27
28
|
@client = client
|
@@ -33,10 +34,29 @@ module Vra
|
|
33
34
|
@notes = opts[:notes]
|
34
35
|
@subtenant_id = opts[:subtenant_id]
|
35
36
|
@additional_params = opts[:additional_params] || Vra::RequestParameters.new
|
36
|
-
|
37
37
|
@catalog_item = Vra::CatalogItem.new(client, id: catalog_id)
|
38
38
|
end
|
39
39
|
|
40
|
+
# @param payload_file [String] - A json payload that represents the catalog template you want to merge with this request
|
41
|
+
# @param client [Vra::Client] - a vra client object
|
42
|
+
# @return [Vra::CatalogRequest] - a request with the given payload merged
|
43
|
+
def self.request_from_payload(client, payload_file)
|
44
|
+
hash_payload = JSON.parse(File.read(payload_file))
|
45
|
+
catalog_id = hash_payload["catalogItemId"]
|
46
|
+
blueprint_name = hash_payload["data"].select { |_k, v| v.is_a?(Hash) }.keys.first
|
47
|
+
blueprint_data = hash_payload["data"][blueprint_name]
|
48
|
+
opts = {}
|
49
|
+
opts[:cpus] = blueprint_data["data"]["cpu"]
|
50
|
+
opts[:memory] = blueprint_data["data"]["memory"]
|
51
|
+
opts[:requested_for] = hash_payload["requestedFor"]
|
52
|
+
opts[:lease_days] = blueprint_data.fetch("leaseDays", nil) || hash_payload["data"].fetch("_lease_days", 1)
|
53
|
+
opts[:description] = hash_payload["description"]
|
54
|
+
opts[:subtenant_id] = hash_payload["businessGroupId"]
|
55
|
+
cr = Vra::CatalogRequest.new(client, catalog_id, opts)
|
56
|
+
cr.template_payload = File.read(payload_file)
|
57
|
+
cr
|
58
|
+
end
|
59
|
+
|
40
60
|
def set_parameter(key, type, value)
|
41
61
|
@additional_params.set(key, type, value)
|
42
62
|
end
|
@@ -66,31 +86,40 @@ module Vra
|
|
66
86
|
raise ArgumentError, "Unable to submit request, required param(s) missing => #{missing_params.join(', ')}" unless missing_params.empty?
|
67
87
|
end
|
68
88
|
|
89
|
+
# @return [String] - the current catalog template payload merged with the settings applied from this request
|
90
|
+
# @param [String] - A json payload that represents the catalog template you want to merge with this request
|
69
91
|
def merge_payload(payload)
|
70
92
|
hash_payload = JSON.parse(payload)
|
71
93
|
blueprint_name = hash_payload["data"].select { |_k, v| v.is_a?(Hash) }.keys.first
|
72
|
-
|
73
94
|
hash_payload["data"][blueprint_name]["data"]["cpu"] = @cpus
|
74
95
|
hash_payload["data"][blueprint_name]["data"]["memory"] = @memory
|
75
96
|
hash_payload["requestedFor"] = @requested_for
|
76
97
|
hash_payload["data"]["_leaseDays"] = @lease_days
|
77
98
|
hash_payload["description"] = @notes
|
78
|
-
|
79
99
|
JSON.pretty_generate(deep_merge(hash_payload, parameters))
|
80
100
|
end
|
81
101
|
|
102
|
+
# @return [String] - the current catalog template payload merged with the settings applied from this request
|
103
|
+
def merged_payload
|
104
|
+
merge_payload(template_payload)
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [String] - the current catalog template payload from VRA or custom payload set in JSON format
|
108
|
+
def template_payload
|
109
|
+
@template_payload ||= Vra::CatalogItem.dump_template(client, @catalog_id)
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return [Vra::Request] - submits and returns the request, validating before hand
|
82
113
|
def submit
|
83
114
|
validate_params!
|
84
115
|
|
85
116
|
begin
|
86
|
-
|
87
|
-
post_response = client.http_post("/catalog-service/api/consumer/entitledCatalogItems/#{@catalog_id}/requests", merge_payload(response.body))
|
117
|
+
post_response = client.http_post("/catalog-service/api/consumer/entitledCatalogItems/#{@catalog_id}/requests", merged_payload)
|
88
118
|
rescue Vra::Exception::HTTPError => e
|
89
119
|
raise Vra::Exception::RequestError, "Unable to submit request: #{e.errors.join(', ')}"
|
90
120
|
rescue
|
91
121
|
raise
|
92
122
|
end
|
93
|
-
|
94
123
|
request_id = JSON.parse(post_response.body)["id"]
|
95
124
|
Vra::Request.new(client, request_id)
|
96
125
|
end
|
@@ -22,12 +22,18 @@ module Vra
|
|
22
22
|
@entries = {}
|
23
23
|
end
|
24
24
|
|
25
|
+
# @param key [String] - the name of the key
|
26
|
+
# @param value_data [Hash] - the data of the key name
|
27
|
+
# @note - the value_data must have type and value property in the hash
|
25
28
|
def set_parameters(key, value_data, parent = nil)
|
26
|
-
|
29
|
+
value_type = value_data[:type] || value_data["type"]
|
30
|
+
data_value = value_data[:value] || value_data["value"]
|
31
|
+
|
32
|
+
if value_type
|
27
33
|
if parent.nil?
|
28
|
-
set(key,
|
34
|
+
set(key, value_type, data_value)
|
29
35
|
else
|
30
|
-
parent.add_child(Vra::RequestParameter.new(key,
|
36
|
+
parent.add_child(Vra::RequestParameter.new(key, value_type, data_value))
|
31
37
|
end
|
32
38
|
else
|
33
39
|
if parent.nil?
|
data/lib/vra/version.rb
CHANGED
data/spec/catalog_item_spec.rb
CHANGED
@@ -54,6 +54,31 @@ describe Vra::CatalogItem do
|
|
54
54
|
}
|
55
55
|
end
|
56
56
|
|
57
|
+
let(:other_catalog_item_payload) do
|
58
|
+
{
|
59
|
+
"@type" => "CatalogItem",
|
60
|
+
"id" => "3232323e-5443-4082-afd5-ab5a32939bbc",
|
61
|
+
"version" => 2,
|
62
|
+
"name" => "CentOS 6.6",
|
63
|
+
"description" => "Blueprint for deploying a CentOS Linux development server",
|
64
|
+
"status" => "PUBLISHED",
|
65
|
+
"statusName" => "Published",
|
66
|
+
"organization" => {
|
67
|
+
"tenantRef" => "vsphere.local",
|
68
|
+
"tenantLabel" => "vsphere.local",
|
69
|
+
"subtenantRef" => "962ab3f9-858c-4483-a49f-fa97392c314b",
|
70
|
+
"subtenantLabel" => "catalog_subtenant",
|
71
|
+
},
|
72
|
+
"providerBinding" => {
|
73
|
+
"bindingId" => "33af5413-4f20-4b3b-8268-32edad434dfb",
|
74
|
+
"providerRef" => {
|
75
|
+
"id" => "c3b2bc30-47b0-454f-b57d-df02a7356fe6",
|
76
|
+
"label" => "iaas-service",
|
77
|
+
},
|
78
|
+
},
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
57
82
|
describe "#initialize" do
|
58
83
|
it "raises an error if no ID or catalog item data have been provided" do
|
59
84
|
expect { Vra::CatalogItem.new }.to raise_error(ArgumentError)
|
@@ -135,5 +160,124 @@ describe Vra::CatalogItem do
|
|
135
160
|
expect(catalog_item.organization["tenantRef"]).to eq(nil)
|
136
161
|
end
|
137
162
|
end
|
163
|
+
|
164
|
+
describe "class methods" do
|
165
|
+
let(:response) { double("response", code: 200, body: catalog_item_payload.to_json) }
|
166
|
+
|
167
|
+
it "#dump_template" do
|
168
|
+
expect(client).to receive(:http_get).with("/catalog-service/api/consumer/entitledCatalogItems/#{catalog_id}/requests/template")
|
169
|
+
.and_return(response)
|
170
|
+
described_class.dump_template(client, catalog_id )
|
171
|
+
end
|
172
|
+
|
173
|
+
it "#write_template" do
|
174
|
+
allow(client).to receive(:http_get).with("/catalog-service/api/consumer/entitledCatalogItems/#{catalog_id}/requests/template")
|
175
|
+
.and_return(response)
|
176
|
+
expect(File).to receive(:write).with("9e98042e-5443-4082-afd5-ab5a32939bbc.json", JSON.pretty_generate(catalog_item_payload))
|
177
|
+
expect(described_class.write_template(client, catalog_id)).to eq("9e98042e-5443-4082-afd5-ab5a32939bbc.json")
|
178
|
+
end
|
179
|
+
|
180
|
+
it "#write_template with custom filename" do
|
181
|
+
allow(client).to receive(:http_get).with("/catalog-service/api/consumer/entitledCatalogItems/#{catalog_id}/requests/template")
|
182
|
+
.and_return(response)
|
183
|
+
expect(File).to receive(:write).with("somefile.json", JSON.pretty_generate(catalog_item_payload))
|
184
|
+
expect(described_class.write_template(client, catalog_id, "somefile.json")).to eq("somefile.json")
|
185
|
+
end
|
186
|
+
|
187
|
+
context "entitled items" do
|
188
|
+
let(:response2) { double("response", code: 200, body: other_catalog_item_payload.to_json) }
|
189
|
+
|
190
|
+
let(:entitled_catalog_item) do
|
191
|
+
{
|
192
|
+
"@type" => "ConsumerEntitledCatalogItem",
|
193
|
+
"catalogItem" => {
|
194
|
+
"id" => "d29efd6b-3cd6-4f8d-b1d8-da4ddd4e52b1",
|
195
|
+
"version" => 2,
|
196
|
+
"name" => "WindowsServer2012",
|
197
|
+
"description" => "Windows Server 2012 with the latest updates and patches.",
|
198
|
+
"status" => "PUBLISHED",
|
199
|
+
"statusName" => "Published",
|
200
|
+
"organization" => {
|
201
|
+
"tenantRef" => "vsphere.local",
|
202
|
+
"tenantLabel" => "vsphere.local",
|
203
|
+
"subtenantRef" => nil,
|
204
|
+
"subtenantLabel" => nil,
|
205
|
+
},
|
206
|
+
"providerBinding" => {
|
207
|
+
"bindingId" => "59fd02a1-acca-4918-9d3d-2298d310caef",
|
208
|
+
"providerRef" => {
|
209
|
+
"id" => "c3b2bc30-47b0-454f-b57d-df02a7356fe6",
|
210
|
+
"label" => "iaas-service",
|
211
|
+
},
|
212
|
+
},
|
213
|
+
},
|
214
|
+
}
|
215
|
+
end
|
216
|
+
|
217
|
+
let(:entitled_catalog_item2) do
|
218
|
+
{
|
219
|
+
"@type" => "ConsumerEntitledCatalogItem",
|
220
|
+
"catalogItem" => {
|
221
|
+
"id" => "3232323e-5443-4082-afd5-ab5a32939bbc",
|
222
|
+
"version" => 2,
|
223
|
+
"name" => "WindowsServer2016",
|
224
|
+
"description" => "Windows Server 2012 with the latest updates and patches.",
|
225
|
+
"status" => "PUBLISHED",
|
226
|
+
"statusName" => "Published",
|
227
|
+
"organization" => {
|
228
|
+
"tenantRef" => "vsphere.local",
|
229
|
+
"tenantLabel" => "vsphere.local",
|
230
|
+
"subtenantRef" => nil,
|
231
|
+
"subtenantLabel" => nil,
|
232
|
+
},
|
233
|
+
"providerBinding" => {
|
234
|
+
"bindingId" => "59fd02a1-acca-4918-9d3d-2298d310caef",
|
235
|
+
"providerRef" => {
|
236
|
+
"id" => "c3b2bc30-47b0-454f-b57d-df02a7356fe6",
|
237
|
+
"label" => "iaas-service",
|
238
|
+
},
|
239
|
+
},
|
240
|
+
},
|
241
|
+
}
|
242
|
+
end
|
243
|
+
|
244
|
+
before(:each) do
|
245
|
+
allow(client).to receive(:http_get_paginated_array!).with("/catalog-service/api/consumer/entitledCatalogItems")
|
246
|
+
.and_return([ entitled_catalog_item, entitled_catalog_item2 ])
|
247
|
+
allow(client).to receive(:http_get)
|
248
|
+
.with("/catalog-service/api/consumer/entitledCatalogItems/d29efd6b-3cd6-4f8d-b1d8-da4ddd4e52b1/requests/template")
|
249
|
+
.and_return(response)
|
250
|
+
allow(client).to receive(:http_get)
|
251
|
+
.with("/catalog-service/api/consumer/entitledCatalogItems/3232323e-5443-4082-afd5-ab5a32939bbc/requests/template")
|
252
|
+
.and_return(response)
|
253
|
+
allow(File).to receive(:write).with("vra_templates/d29efd6b-3cd6-4f8d-b1d8-da4ddd4e52b1.json", JSON.pretty_generate(catalog_item_payload))
|
254
|
+
allow(File).to receive(:write).with("vra_templates/3232323e-5443-4082-afd5-ab5a32939bbc.json", JSON.pretty_generate(catalog_item_payload))
|
255
|
+
allow(File).to receive(:write).with("vra_templates/windowsserver2012.json", JSON.pretty_generate(catalog_item_payload))
|
256
|
+
allow(File).to receive(:write).with("vra_templates/windowsserver2016.json", JSON.pretty_generate(catalog_item_payload))
|
257
|
+
allow(File).to receive(:write).with("custom_dir/windowsserver2012.json", JSON.pretty_generate(catalog_item_payload))
|
258
|
+
allow(File).to receive(:write).with("custom_dir/windowsserver2016.json", JSON.pretty_generate(catalog_item_payload))
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
it "#dump_templates" do
|
263
|
+
expect(described_class.dump_templates(client)).to eq(["vra_templates/windowsserver2012.json",
|
264
|
+
"vra_templates/windowsserver2016.json"])
|
265
|
+
end
|
266
|
+
|
267
|
+
it "#dump_templates with custom directory" do
|
268
|
+
expect(described_class.dump_templates(client, "custom_dir")).to eq(["custom_dir/windowsserver2012.json",
|
269
|
+
"custom_dir/windowsserver2016.json"])
|
270
|
+
end
|
271
|
+
|
272
|
+
it "#dump_templates with id" do
|
273
|
+
expect(described_class.dump_templates(client, "vra_templates", true))
|
274
|
+
.to eq(["vra_templates/d29efd6b-3cd6-4f8d-b1d8-da4ddd4e52b1.json",
|
275
|
+
"vra_templates/3232323e-5443-4082-afd5-ab5a32939bbc.json"])
|
276
|
+
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
138
282
|
end
|
139
283
|
end
|
@@ -35,6 +35,50 @@ describe Vra::CatalogRequest do
|
|
35
35
|
base_url: "https://vra.corp.local")
|
36
36
|
end
|
37
37
|
|
38
|
+
let(:catalog_item_payload) do
|
39
|
+
{
|
40
|
+
"@type" => "CatalogItem",
|
41
|
+
"id" => "9e98042e-5443-4082-afd5-ab5a32939bbc",
|
42
|
+
"version" => 2,
|
43
|
+
"name" => "CentOS 6.6",
|
44
|
+
"description" => "Blueprint for deploying a CentOS Linux development server",
|
45
|
+
"status" => "PUBLISHED",
|
46
|
+
"statusName" => "Published",
|
47
|
+
"organization" => {
|
48
|
+
"tenantRef" => "vsphere.local",
|
49
|
+
"tenantLabel" => "vsphere.local",
|
50
|
+
"subtenantRef" => "962ab3f9-858c-4483-a49f-fa97392c314b",
|
51
|
+
"subtenantLabel" => "catalog_subtenant",
|
52
|
+
},
|
53
|
+
"providerBinding" => {
|
54
|
+
"bindingId" => "33af5413-4f20-4b3b-8268-32edad434dfb",
|
55
|
+
"providerRef" => {
|
56
|
+
"id" => "c3b2bc30-47b0-454f-b57d-df02a7356fe6",
|
57
|
+
"label" => "iaas-service",
|
58
|
+
},
|
59
|
+
},
|
60
|
+
"requestedFor" => "me@me.com",
|
61
|
+
"data" => {
|
62
|
+
"_leaseDays" => "2",
|
63
|
+
"my_blueprint" => {
|
64
|
+
"componentTypeId" => "com.vmware.csp.component.cafe.composition",
|
65
|
+
"componentId" => nil,
|
66
|
+
"classId" => "Blueprint.Component.Declaration",
|
67
|
+
"typeFilter" => "",
|
68
|
+
"data" => {
|
69
|
+
"cpu" => "2",
|
70
|
+
"memory" => "4096",
|
71
|
+
|
72
|
+
},
|
73
|
+
},
|
74
|
+
},
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:request_template_response) do
|
79
|
+
double("response", code: 200, body: catalog_item_payload.to_json)
|
80
|
+
end
|
81
|
+
|
38
82
|
context "when no subtenant ID is provided" do
|
39
83
|
let(:request) do
|
40
84
|
client.catalog.request("catalog-12345",
|
@@ -152,58 +196,72 @@ describe Vra::CatalogRequest do
|
|
152
196
|
end
|
153
197
|
|
154
198
|
describe "#submit" do
|
199
|
+
let(:response) do
|
200
|
+
double("response", code: 200, body: { id: "12345678910" }.to_json)
|
201
|
+
end
|
202
|
+
|
155
203
|
before do
|
156
204
|
allow(request).to receive(:request_payload).and_return({})
|
157
|
-
|
205
|
+
allow(client).to receive(:authorize!).and_return(true)
|
158
206
|
allow(client).to receive(:http_post).with("/catalog-service/api/consumer/requests", "{}").and_return(response)
|
207
|
+
allow(client).to receive(:http_get).with("/catalog-service/api/consumer/entitledCatalogItems/catalog-12345/requests/template")
|
208
|
+
.and_return(request_template_response)
|
159
209
|
end
|
160
210
|
|
161
|
-
it "calls
|
162
|
-
|
163
|
-
|
211
|
+
it "calls http_get template" do
|
212
|
+
expect(client).to receive(:http_get).with("/catalog-service/api/consumer/entitledCatalogItems/catalog-12345/requests/template")
|
213
|
+
.and_return(request_template_response)
|
214
|
+
allow(client).to receive(:http_post).with("/catalog-service/api/consumer/entitledCatalogItems/catalog-12345/requests", request.merged_payload).and_return(response)
|
215
|
+
request.submit
|
216
|
+
end
|
164
217
|
|
218
|
+
it "calls http_post" do
|
219
|
+
expect(client).to receive(:http_post).with("/catalog-service/api/consumer/entitledCatalogItems/catalog-12345/requests", request.merged_payload).and_return(response)
|
165
220
|
request.submit
|
166
221
|
end
|
167
222
|
|
168
|
-
it "returns
|
169
|
-
|
170
|
-
expect(request.submit).to
|
223
|
+
it "returns Vra::Request" do
|
224
|
+
allow(client).to receive(:http_post).with("/catalog-service/api/consumer/entitledCatalogItems/catalog-12345/requests", request.merged_payload).and_return(response)
|
225
|
+
expect(request.submit).to be_a(Vra::Request)
|
171
226
|
end
|
172
227
|
end
|
173
228
|
end
|
174
229
|
|
175
|
-
|
176
|
-
Vra::Client.new(username: "user@corp.local",
|
177
|
-
password: "password",
|
178
|
-
tenant: "tenant",
|
179
|
-
base_url: "https://vra.corp.local",
|
180
|
-
verify_ssl: false)
|
181
|
-
end
|
182
|
-
|
183
|
-
context "when ssl is not verified by the client" do
|
230
|
+
describe "merges payload" do
|
184
231
|
let(:request) do
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
232
|
+
client.catalog.request("catalog-12345",
|
233
|
+
cpus: 2,
|
234
|
+
memory: 1024,
|
235
|
+
lease_days: 15,
|
236
|
+
requested_for: "tester@corp.local",
|
237
|
+
notes: "test notes")
|
238
|
+
end
|
239
|
+
before(:each) do
|
240
|
+
allow(Vra::CatalogItem).to receive(:dump_template).and_return({ data2: { key2: "value2" } }.merge(catalog_item_payload).to_json)
|
192
241
|
end
|
193
242
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
expect(Vra::Http).to receive(:execute).and_wrap_original do |_http, *args|
|
201
|
-
expect(*args).to include(verify_ssl: false)
|
202
|
-
double(location: "auth/request_id")
|
203
|
-
end
|
243
|
+
it "without catalog template" do
|
244
|
+
request.template_payload = { data2: { key1: "value1" } }.merge(catalog_item_payload).to_json
|
245
|
+
template = JSON.parse(request.merged_payload)
|
246
|
+
expect(template["data2"].keys).to_not include("key2")
|
247
|
+
end
|
204
248
|
|
205
|
-
|
206
|
-
|
249
|
+
it "with catalog template" do
|
250
|
+
request.template_payload = nil
|
251
|
+
template = JSON.parse(request.merged_payload)
|
252
|
+
expect(template["data2"].keys).to include("key2")
|
207
253
|
end
|
208
254
|
end
|
255
|
+
|
256
|
+
it "creates request" do
|
257
|
+
payload_file = File.join(fixtures_dir, "catalog_request_template.json")
|
258
|
+
expect(Vra::CatalogRequest.request_from_payload(client, payload_file)).to be_a(Vra::CatalogRequest)
|
259
|
+
end
|
260
|
+
|
261
|
+
it "creates request with correct payload" do
|
262
|
+
payload_file = File.join(fixtures_dir, "catalog_request_template.json")
|
263
|
+
cr = Vra::CatalogRequest.request_from_payload(client, payload_file)
|
264
|
+
data = JSON.parse(cr.merged_payload)
|
265
|
+
expect(data["data"]["superduper_key"]).to eq("superduper_value")
|
266
|
+
end
|
209
267
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -27,6 +27,14 @@ describe Vra::Client do
|
|
27
27
|
base_url: "https://vra.corp.local")
|
28
28
|
end
|
29
29
|
|
30
|
+
let(:client_without_ssl) do
|
31
|
+
Vra::Client.new(username: "user@corp.local",
|
32
|
+
password: "password",
|
33
|
+
tenant: "tenant",
|
34
|
+
base_url: "https://vra.corp.local",
|
35
|
+
verify_ssl: false)
|
36
|
+
end
|
37
|
+
|
30
38
|
describe "#initialize" do
|
31
39
|
it "calls validate_client_options!" do
|
32
40
|
client = Vra::Client.allocate
|
@@ -206,6 +214,23 @@ describe Vra::Client do
|
|
206
214
|
client.http_head(path)
|
207
215
|
end
|
208
216
|
|
217
|
+
it "calls Vra::Http.execute with verify_ssl false" do
|
218
|
+
response = double("response")
|
219
|
+
path = "/test"
|
220
|
+
full_url = "https://vra.corp.local/test"
|
221
|
+
headers = { "Accept" => "application/json", "Content-Type" => "application/json" }
|
222
|
+
verify_ssl = false
|
223
|
+
|
224
|
+
allow(client_without_ssl).to receive(:authorize!)
|
225
|
+
expect(Vra::Http).to receive(:execute).with(method: :head,
|
226
|
+
url: full_url,
|
227
|
+
headers: headers,
|
228
|
+
verify_ssl: verify_ssl)
|
229
|
+
.and_return(response)
|
230
|
+
|
231
|
+
client_without_ssl.http_head(path)
|
232
|
+
end
|
233
|
+
|
209
234
|
it "raises an HTTPNotFound on a 404 error" do
|
210
235
|
allow(client).to receive(:authorize!)
|
211
236
|
allow(Vra::Http).to receive(:execute)
|
@@ -0,0 +1,130 @@
|
|
1
|
+
{
|
2
|
+
"type": "com.vmware.vcac.catalog.domain.request.CatalogItemProvisioningRequest",
|
3
|
+
"catalogItemId": "7c8275d6-1bd6-452a-97c4-d6c053e4baa4",
|
4
|
+
"requestedFor": "csummers@example.com",
|
5
|
+
"businessGroupId": "c0683388-6db2-4cb5-9033-b24d15ad3766",
|
6
|
+
"description": null,
|
7
|
+
"reasons": null,
|
8
|
+
"data": {
|
9
|
+
"superduper_key": "superduper_value",
|
10
|
+
"Existing_Network_1": {
|
11
|
+
"componentTypeId": "com.vmware.csp.component.cafe.composition",
|
12
|
+
"componentId": null,
|
13
|
+
"classId": "Blueprint.Component.Declaration",
|
14
|
+
"typeFilter": "LinuxDemo*Existing_Network_1",
|
15
|
+
"data": {
|
16
|
+
"_cluster": 1,
|
17
|
+
"_hasChildren": false,
|
18
|
+
"description": null,
|
19
|
+
"name": "Existing Network",
|
20
|
+
"networkname": "Existing Network",
|
21
|
+
"subnetmask": "255.255.255.0"
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"vSphere-Linux": {
|
25
|
+
"componentTypeId": "com.vmware.csp.component.cafe.composition",
|
26
|
+
"componentId": null,
|
27
|
+
"classId": "Blueprint.Component.Declaration",
|
28
|
+
"typeFilter": "LinuxDemo*vSphere-Linux",
|
29
|
+
"data": {
|
30
|
+
"Cafe.Shim.VirtualMachine.MaxCost": 0,
|
31
|
+
"Cafe.Shim.VirtualMachine.MinCost": 0,
|
32
|
+
"_cluster": 1,
|
33
|
+
"_hasChildren": false,
|
34
|
+
"action": "FullClone",
|
35
|
+
"allow_storage_policies": false,
|
36
|
+
"archive_days": 0,
|
37
|
+
"blueprint_type": "1",
|
38
|
+
"cpu": 1,
|
39
|
+
"custom_properties": [],
|
40
|
+
"daily_cost": 0,
|
41
|
+
"datacenter_location": null,
|
42
|
+
"description": null,
|
43
|
+
"disks": [
|
44
|
+
{
|
45
|
+
"componentTypeId": "com.vmware.csp.iaas.blueprint.service",
|
46
|
+
"componentId": null,
|
47
|
+
"classId": "Infrastructure.Compute.Machine.MachineDisk",
|
48
|
+
"typeFilter": null,
|
49
|
+
"data": {
|
50
|
+
"capacity": 6,
|
51
|
+
"id": 0,
|
52
|
+
"initial_location": "",
|
53
|
+
"is_clone": false,
|
54
|
+
"label": "",
|
55
|
+
"storage_reservation_policy": "",
|
56
|
+
"userCreated": true,
|
57
|
+
"volumeId": 0
|
58
|
+
}
|
59
|
+
}
|
60
|
+
],
|
61
|
+
"display_location": false,
|
62
|
+
"guest_customization_specification": null,
|
63
|
+
"lease_days": 0,
|
64
|
+
"machine_actions": [
|
65
|
+
"DESTROY",
|
66
|
+
"POWER_ON",
|
67
|
+
"CONNECT_RDP_SSH",
|
68
|
+
"REPROVISION",
|
69
|
+
"POWER_CYCLE",
|
70
|
+
"EXPIRE",
|
71
|
+
"SUSPEND",
|
72
|
+
"CONNECT_REMOTE_CONSOLE",
|
73
|
+
"CONNECT_USING_VDI"
|
74
|
+
],
|
75
|
+
"machine_prefix": {
|
76
|
+
"componentId": null,
|
77
|
+
"classId": "Infrastructure.Compute.MachinePrefix",
|
78
|
+
"id": "Use group default"
|
79
|
+
},
|
80
|
+
"max_network_adapters": 0,
|
81
|
+
"max_per_user": 0,
|
82
|
+
"max_volumes": 60,
|
83
|
+
"memory": 4096,
|
84
|
+
"nics": [
|
85
|
+
{
|
86
|
+
"componentTypeId": "com.vmware.csp.iaas.blueprint.service",
|
87
|
+
"componentId": null,
|
88
|
+
"classId": "Infrastructure.Compute.Machine.Nic",
|
89
|
+
"typeFilter": null,
|
90
|
+
"data": {
|
91
|
+
"address": "",
|
92
|
+
"assignment_type": "DHCP",
|
93
|
+
"custom_properties": null,
|
94
|
+
"id": 0,
|
95
|
+
"load_balancing": "",
|
96
|
+
"network_profile": "Existing Network"
|
97
|
+
}
|
98
|
+
}
|
99
|
+
],
|
100
|
+
"number_of_instances": 1,
|
101
|
+
"os_arch": "x86_64",
|
102
|
+
"os_distribution": null,
|
103
|
+
"os_type": "Linux",
|
104
|
+
"os_version": null,
|
105
|
+
"platform_name": "vsphere",
|
106
|
+
"platform_type": "virtual",
|
107
|
+
"property_groups": [
|
108
|
+
null
|
109
|
+
],
|
110
|
+
"provisioning_workflow": {
|
111
|
+
"componentId": null,
|
112
|
+
"classId": "Infrastructure.Compute.ProvisioningWorkflow",
|
113
|
+
"id": "CloneWorkflow"
|
114
|
+
},
|
115
|
+
"reservation_policy": {
|
116
|
+
"componentId": null,
|
117
|
+
"classId": "Infrastructure.Reservation.Policy.ComputeResource",
|
118
|
+
"id": "None"
|
119
|
+
},
|
120
|
+
"security_groups": [],
|
121
|
+
"security_tags": [],
|
122
|
+
"source_machine": null,
|
123
|
+
"source_machine_external_snapshot": null,
|
124
|
+
"source_machine_name": "cbpcentos_63_x86",
|
125
|
+
"source_machine_vmsnapshot": null,
|
126
|
+
"storage": 6
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vmware-vra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Leff
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-09-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi-yajl
|
@@ -172,6 +172,7 @@ files:
|
|
172
172
|
- spec/catalog_request_spec.rb
|
173
173
|
- spec/catalog_spec.rb
|
174
174
|
- spec/client_spec.rb
|
175
|
+
- spec/fixtures/catalog_request_template.json
|
175
176
|
- spec/fixtures/resource/catalog_request.json
|
176
177
|
- spec/fixtures/resource/ip_address.txt
|
177
178
|
- spec/fixtures/resource/no_ip_address.txt
|
@@ -216,6 +217,7 @@ test_files:
|
|
216
217
|
- spec/catalog_request_spec.rb
|
217
218
|
- spec/catalog_spec.rb
|
218
219
|
- spec/client_spec.rb
|
220
|
+
- spec/fixtures/catalog_request_template.json
|
219
221
|
- spec/fixtures/resource/catalog_request.json
|
220
222
|
- spec/fixtures/resource/ip_address.txt
|
221
223
|
- spec/fixtures/resource/no_ip_address.txt
|