vmware-vra 3.0.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3671834fbc97510772f7d42d524f2775789c7ac0fe7f29c80dad8c64effe3b6
4
- data.tar.gz: 394929c607677c9c2341e9a6060e9341810f2a8941111247e2fe1e1f71ce5afb
3
+ metadata.gz: '04187d64c2726dfbe9dcf8128710daa94c17593d17da436b4c797932d7399f39'
4
+ data.tar.gz: 2456b3f5fb84a99f12493ba357e8603d2bfb42c42858139bc53fcbd60b8f8984
5
5
  SHA512:
6
- metadata.gz: a04bbf0434372a58119367bb5f3d9f35c10fff450263e14f92fac6bc78082a74d0ca8fbca713b4ae7a1c0fdc1e1a40a953b321b21be32bfd0996db3cf107d776
7
- data.tar.gz: 3f3646d1aa4fb7d15fd451fce246ab9ccb1e4828dfd4e13110abdb5ce552a3c4a158fb3ff8ab6a6139154af6fec3c57646566876ae4af2c6414bd6f5fb5284b7
6
+ metadata.gz: 9820fab88049710e06f5814994d6a215338d7039e775523d27c32fbaf6e80463721d9ae5bce0e876a3b5236a14009d6350a2abb7716cda6f10f15e05676107dd
7
+ data.tar.gz: '0998fa84339c1f467d585041b2b1b4f8dbc0eae3b70f9fd03c7fcb5ea37afd280d61a58fc10fe4d1cd389e782430c532b639f02d09ec888fa3b52b31a71b8f2c'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## [3.1.1](https://github.com/chef-partners/vmware-vra-gem/tree/v3.1.1) (2022-03-01)
4
+
5
+ - Send Authorization: Bearer header instead of csp-auth-token for greater compatibility [@oshvarts]
6
+
7
+ ## [3.1.0](https://github.com/chef-partners/vmware-vra-gem/tree/v3.1.0) (2022-01-30)
8
+ [Full Changelog](https://github.com/chef-partners/vmware-vra-gem/compare/v3.0.1...v3.1.0)
9
+
10
+ - Make the version param optional in deployment request api
11
+
12
+ ## [3.0.1](https://github.com/chef-partners/vmware-vra-gem/tree/v3.0.1) (2022-01-25)
13
+ [Full Changelog](https://github.com/chef-partners/vmware-vra-gem/compare/v3.0.0...v3.0.1)
14
+
15
+ - Fix access token workflow to work with VRA8
16
+
3
17
  ## [3.0.0](https://github.com/chef-partners/vmware-vra-gem/tree/v3.0.0) (2022-01-18)
4
18
  [Full Changelog](https://github.com/chef-partners/vmware-vra-gem/compare/v2.7.2...v3.0.0)
5
19
 
data/README.md CHANGED
@@ -125,8 +125,10 @@ request = client.catalog.request(
125
125
  #<Vra::DeploymentRequest:0x00007fb7340b7438
126
126
  ...
127
127
  ```
128
- To request a deployment from a catalog item, you can use the above method with a project ID that has a cloud template version released to the project.
129
- The ID of the catalog item from which you are requesting the deployment should be also included, and the version of the released cloud template.
128
+ To request a deployment from a catalog item, you can use the above method with a project ID that has a cloud template version released to the project.
129
+
130
+ The ID of the catalog item from which you are requesting the deployment should be also included, and the version of the released cloud template. If the user doesn't specify a version explicitly, the latest version will be fetched automatically and will be used for the request.
131
+
130
132
  Additionally, the name of the deployment should be specified and it should be unique.
131
133
  The image mapping specifies the OS image for a VM and the flavor mapping specifies the CPU count and RAM of a VM.
132
134
 
@@ -73,12 +73,24 @@ module Vra
73
73
  data['iconId']
74
74
  end
75
75
 
76
+ def versions
77
+ client
78
+ .http_get_paginated_array!("/catalog/api/items/#{id}/versions")
79
+ .map { |v| v['id'] }
80
+ end
81
+
76
82
  def entitle!(opts = {})
77
83
  super(opts.merge(type: 'CatalogItemIdentifier'))
78
84
  end
79
85
 
80
- def self.entitle!(client, id)
81
- new(client, id: id).entitle!
86
+ class << self
87
+ def entitle!(client, id)
88
+ new(client, id: id).entitle!
89
+ end
90
+
91
+ def fetch_latest_version(client, id)
92
+ new(client, data: { 'id' => id }).versions&.first
93
+ end
82
94
  end
83
95
  end
84
96
  end
data/lib/vra/client.rb CHANGED
@@ -23,7 +23,8 @@ require 'vra/http'
23
23
 
24
24
  module Vra
25
25
  class Client
26
- ACCESS_TOKEN_URL = '/csp/gateway/am/api/login?access_token'
26
+ REFRESH_TOKEN_URL = '/csp/gateway/am/api/login?access_token'
27
+ ACCESS_TOKEN_URL = '/iaas/api/login'
27
28
  ROLES_URL = '/csp/gateway/am/api/loggedin/user/orgs'
28
29
 
29
30
  attr_accessor :page_size
@@ -87,7 +88,7 @@ module Vra
87
88
  headers = {}
88
89
  headers['Accept'] = 'application/json'
89
90
  headers['Content-Type'] = 'application/json'
90
- headers['csp-auth-token'] = @access_token.value unless @access_token.value.nil?
91
+ headers['Authorization'] = 'Bearer ' + @access_token.value unless @access_token.value.nil?
91
92
 
92
93
  headers
93
94
  end
@@ -106,17 +107,26 @@ module Vra
106
107
  end
107
108
 
108
109
  def generate_access_token
110
+ @refresh_token.value = nil
109
111
  @access_token.value = nil
110
112
  validate_client_options!
111
113
 
112
- response = http_post(ACCESS_TOKEN_URL,
114
+ # VRA 8 has a two-step authentication process - This probably breaks VRA7, who knows?!?
115
+ # First step: Sending Username/Password to get a Refresh Token
116
+ refresh_response = http_post(REFRESH_TOKEN_URL,
113
117
  FFI_Yajl::Encoder.encode(token_params),
114
118
  :skip_auth)
115
- raise Vra::Exception::Unauthorized, "Unable to get the access token: #{response.body}" unless response.success_ok?
119
+ raise Vra::Exception::Unauthorized, "Unable to get the refresh token: #{refresh_response.body}" unless refresh_response.success_ok?
116
120
 
117
- response_body = FFI_Yajl::Parser.parse(response.body)
118
- @access_token.value = response_body['access_token']
119
- @refresh_token.value = response_body['refresh_token']
121
+ refresh_response_body = FFI_Yajl::Parser.parse(refresh_response.body)
122
+ @refresh_token.value = refresh_response_body['refresh_token']
123
+
124
+ # Second Step: Sending the refresh token to a separate endpoint to get an Access Token
125
+ access_response = http_post(ACCESS_TOKEN_URL, "{ \"refreshToken\": \"#{@refresh_token.value}\" }", :skip_auth)
126
+ raise Vra::Exception::Unauthorized, "Unable to get the access token: #{access_response.body}" unless access_response.success_ok?
127
+
128
+ access_response_body = FFI_Yajl::Parser.parse(access_response.body)
129
+ @access_token.value = access_response_body['token']
120
130
  end
121
131
 
122
132
  def full_url(path)
@@ -85,13 +85,21 @@ module Vra
85
85
 
86
86
  def validate!
87
87
  missing_params = []
88
- %i[image_mapping flavor_mapping name project_id version].each do |arg|
88
+ %i[image_mapping flavor_mapping name project_id].each do |arg|
89
89
  missing_params << arg if send(arg).nil?
90
90
  end
91
91
 
92
- return if missing_params.empty?
92
+ unless missing_params.empty?
93
+ raise ArgumentError, "Unable to submit request, required param(s) missing => #{missing_params.join(', ')}"
94
+ end
95
+
96
+ # If the user doesn't supply the catalog version, fetch the latest version and use it
97
+ # and if the API was unable to find a valid version, alert the user.
98
+ return unless @version.nil?
99
+
93
100
 
94
- raise ArgumentError, "Unable to submit request, required param(s) missing => #{missing_params.join(', ')}"
101
+ @version = CatalogItem.fetch_latest_version(client, catalog_id)
102
+ raise ArgumentError, 'Unable to fetch a valid catalog version' if @version.nil?
95
103
  end
96
104
 
97
105
  def send_request!
data/lib/vra/version.rb CHANGED
@@ -18,5 +18,5 @@
18
18
  #
19
19
 
20
20
  module Vra
21
- VERSION = "3.0.0"
21
+ VERSION = "3.1.1"
22
22
  end
@@ -122,4 +122,37 @@ describe Vra::CatalogItem do
122
122
  expect(catalog_item.type).to be_a(Vra::CatalogType)
123
123
  end
124
124
  end
125
+
126
+ describe '#versions' do
127
+ let(:versions_response) do
128
+ [{ id: '2', description: 'v2.0' }, { id: '1', description: 'v1.0' }]
129
+ end
130
+
131
+ before do
132
+ allow(client).to receive(:authorized?).and_return(true)
133
+ end
134
+
135
+ it 'should call the api to fetch the versions' do
136
+ expect(client)
137
+ .to receive(:http_get_paginated_array!)
138
+ .with('/catalog/api/items/catalog-12345/versions')
139
+ .and_return(versions_response)
140
+
141
+ described_class.fetch_latest_version(client, 'catalog-12345')
142
+ end
143
+
144
+ it 'should return the correct version' do
145
+ stub_request(:get, client.full_url('/catalog/api/items/catalog-12345/versions?$skip=0&$top=20'))
146
+ .to_return(
147
+ status: 200,
148
+ body: {
149
+ content: versions_response,
150
+ totalPages: 1
151
+ }.to_json,
152
+ headers: {}
153
+ )
154
+
155
+ expect(described_class.fetch_latest_version(client, 'catalog-12345')).to eq('2')
156
+ end
157
+ end
125
158
  end
data/spec/client_spec.rb CHANGED
@@ -54,16 +54,16 @@ describe Vra::Client do
54
54
  end
55
55
 
56
56
  describe '#request_headers' do
57
- context 'when bearer token exists' do
57
+ context 'when access token exists' do
58
58
  it 'has an Authorization header' do
59
59
  client.access_token = '12345'
60
- expect(client.request_headers.key?('csp-auth-token')).to be true
60
+ expect(client.request_headers.key?('Authorization')).to be true
61
61
  end
62
62
  end
63
63
 
64
64
  context 'when access token does not exist' do
65
65
  it 'does not have an Authorization header' do
66
- expect(client.request_headers.key?('csp-auth-token')).to be false
66
+ expect(client.request_headers.key?('Authorization')).to be false
67
67
  end
68
68
  end
69
69
  end
@@ -131,7 +131,7 @@ describe Vra::Client do
131
131
  end
132
132
  end
133
133
 
134
- describe '#generate_bearer_token' do
134
+ describe '#generate_access_token' do
135
135
  let(:payload) do
136
136
  {
137
137
  username: 'user@corp.local',
@@ -148,23 +148,37 @@ describe Vra::Client do
148
148
  }.to_json
149
149
  end
150
150
 
151
+ let(:refresh_response_body) { { token: '123456' }.to_json }
152
+
151
153
  it 'posts to the tokens API endpoint' do
152
154
  response = double('response', code: 200, body: success_response, success_ok?: true)
155
+ refresh_response = double('response', code: 200, body: refresh_response_body, success_ok?: true)
156
+ # First request to generate the refresh token
153
157
  expect(Vra::Http).to receive(:execute)
154
158
  .with(method: :post,
155
- url: client.full_url(described_class::ACCESS_TOKEN_URL),
159
+ url: client.full_url(described_class::REFRESH_TOKEN_URL),
156
160
  payload: payload,
157
161
  headers: anything,
158
162
  verify_ssl: true)
159
163
  .and_return(response)
160
164
 
165
+ # Second request to generate access token
166
+ expect(Vra::Http).to receive(:execute)
167
+ .with(method: :post,
168
+ url: client.full_url(described_class::ACCESS_TOKEN_URL),
169
+ payload: "{ \"refreshToken\": \"654321\" }",
170
+ headers: anything,
171
+ verify_ssl: true)
172
+ .and_return(refresh_response)
173
+
161
174
  client.generate_access_token
162
175
  end
163
176
 
164
177
  context 'when token is generated successfully' do
165
178
  it 'sets the token' do
166
179
  response = double('response', code: 200, body: success_response, success_ok?: true)
167
- allow(Vra::Http).to receive(:execute).and_return(response)
180
+ refresh_response = double('response', code: 200, body: refresh_response_body, success_ok?: true)
181
+ allow(Vra::Http).to receive(:execute).twice.and_return(response, refresh_response)
168
182
 
169
183
  client.generate_access_token
170
184
 
@@ -70,6 +70,45 @@ describe Vra::DeploymentRequest do
70
70
 
71
71
  expect { request.send(:validate!) }.not_to raise_error(ArgumentError)
72
72
  end
73
+
74
+ context 'versions' do
75
+ let(:dep_request) do
76
+ described_class.new(
77
+ client,
78
+ catalog_id,
79
+ image_mapping: 'centos',
80
+ name: 'sample dep',
81
+ flavor_mapping: 'small',
82
+ project_id: 'pro-123'
83
+ )
84
+ end
85
+
86
+ before do
87
+ allow(client).to receive(:authorized?).and_return(true)
88
+ end
89
+
90
+ it 'should not call the api to fetch versions if provided in the params' do
91
+ expect(client).not_to receive(:http_get_paginated_array!)
92
+
93
+ dep_request.version = '1'
94
+ dep_request.send(:validate!)
95
+ end
96
+
97
+ it 'should fetch version from api if version is blank' do
98
+ expect(client).to receive(:http_get_paginated_array!).and_return([{ 'id' => '2', 'description' => 'v2.0' }])
99
+
100
+ dep_request.send(:validate!)
101
+ expect(dep_request.version).to eq('2')
102
+ end
103
+
104
+ it 'should raise an exception if no valid versions found' do
105
+ expect(client).to receive(:http_get_paginated_array!).and_return([])
106
+
107
+ expect { dep_request.send(:validate!) }
108
+ .to raise_error(ArgumentError)
109
+ .with_message('Unable to fetch a valid catalog version')
110
+ end
111
+ end
73
112
  end
74
113
 
75
114
  describe '#additional parameters' do
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: 3.0.0
4
+ version: 3.1.1
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: 2022-01-18 00:00:00.000000000 Z
12
+ date: 2022-03-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi-yajl
@@ -206,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
206
206
  - !ruby/object:Gem::Version
207
207
  version: '0'
208
208
  requirements: []
209
- rubygems_version: 3.2.32
209
+ rubygems_version: 3.3.7
210
210
  signing_key:
211
211
  specification_version: 4
212
212
  summary: Client gem for interacting with VMware vRealize Automation.