vmware-vra 2.3.0 → 2.4.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.
- 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
|