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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4206fd0351845613715dd83cc91a70b57067a025
4
- data.tar.gz: 1ff2b3429cda1eb4f46cad5f9832cded71d60fde
3
+ metadata.gz: 11be1f053e0b79413a97f73d65dd7736e5da7c3c
4
+ data.tar.gz: 5f034f6c50a4bd6a3ec8ee69a72672deb291747d
5
5
  SHA512:
6
- metadata.gz: 9f8e728e3be572a2d9094115702cc1ba4293ee92cebd5d43fb6430cfa80c48d378abde08d98013cf986c703ef126a05add06d955def8b407c30f017424de9dc4
7
- data.tar.gz: ec94a0eec7d637ce06affef14c82aed642a520d5d8548a3e5288e501b87b6a78f93d5b671b601d6ccf3ef502949fc1b6633f46d2e16e5f3507166154d02813a4
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.3.0](https://github.com/chef-partners/vmware-vra-gem/tree/2.3.0) (2017-06-30)
4
- [Full Changelog](https://github.com/chef-partners/vmware-vra-gem/compare/v2.2.0...2.3.0)
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
- request_parans = Vra::RequestParameters.new
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: request_parans
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:
@@ -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
@@ -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
- response = client.http_get("/catalog-service/api/consumer/entitledCatalogItems/#{@catalog_id}/requests/template")
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
- if value_data.key?(:type)
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, value_data[:type], value_data[:value])
34
+ set(key, value_type, data_value)
29
35
  else
30
- parent.add_child(Vra::RequestParameter.new(key, value_data[:type], value_data[:value]))
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
@@ -18,5 +18,5 @@
18
18
  #
19
19
 
20
20
  module Vra
21
- VERSION = "2.3.0".freeze
21
+ VERSION = "2.4.0"
22
22
  end
@@ -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
- response = double("response", location: "/requests/request-12345")
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 http_post" do
162
- skip "broken and needs to be updated per changes -JJ 2017-04-14"
163
- expect(client).to receive(:http_post).with("/catalog-service/api/consumer/requests", "{}")
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 a Vra::Request object" do
169
- skip "broken and needs to be updated per changes -JJ 2017-04-14"
170
- expect(request.submit).to be_an_instance_of(Vra::Request)
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
- let(:client_without_ssl) do
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
- client_without_ssl.catalog.request("catalog-12345",
186
- cpus: 2,
187
- memory: 1024,
188
- lease_days: 15,
189
- requested_for: "tester@corp.local",
190
- notes: "test notes",
191
- subtenant_id: "user_subtenant")
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
- describe do
195
- it "passes verify_false to Vra::Http" do
196
- skip "broken and needs to be updated per changes -JJ 2017-04-14"
197
- allow(request.client).to receive(:authorized?).and_return(true)
198
- expect(request.client.instance_variable_get("@verify_ssl")).to eq false
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
- request.submit
206
- end
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
@@ -20,4 +20,11 @@
20
20
  require "vra"
21
21
  require "webmock/rspec"
22
22
 
23
+ def fixtures_dir
24
+ @fixtures_dir ||= begin
25
+ base_dir = File.dirname(__FILE__)
26
+ File.join(base_dir, "fixtures")
27
+ end
28
+ end
29
+
23
30
  WebMock.disable_net_connect!(allow_localhost: true)
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.3.0
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-06-30 00:00:00.000000000 Z
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