vmware-vra 3.0.0 → 3.1.1

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
  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.