Skip to content

Commit 75f1bc5

Browse files
authored
Add Platform info to Fusion license (#6142) [ci fast]
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
1 parent 898c25c commit 75f1bc5

File tree

3 files changed

+91
-25
lines changed

3 files changed

+91
-25
lines changed

plugins/nf-tower/src/main/io/seqera/tower/plugin/TowerFusionToken.groovy

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,26 @@ class TowerFusionToken implements FusionToken {
8282
// Platform access token to use for requests
8383
private String accessToken
8484

85+
// Platform workflowId
86+
private String workspaceId
87+
88+
// Platform workflowId
89+
private String workflowId
90+
8591
TowerFusionToken() {
8692
final config = PlatformHelper.config()
8793
final env = SysEnv.get()
8894
this.endpoint = PlatformHelper.getEndpoint(config, env)
89-
if( !endpoint )
90-
throw new IllegalArgumentException("Missing Seqera Platform endpoint")
9195
this.accessToken = PlatformHelper.getAccessToken(config, env)
96+
this.workflowId = env.get('TOWER_WORKFLOW_ID')
97+
this.workspaceId = PlatformHelper.getWorkspaceId(config, env)
9298
}
9399

94100
protected void validateConfig() {
95101
if( !endpoint )
96102
throw new IllegalArgumentException("Missing Seqera Platform endpoint")
97103
if( !accessToken )
98104
throw new IllegalArgumentException("Missing Seqera Platform access token")
99-
final client = TowerFactory.client()
100-
if( !client )
101-
throw new IllegalArgumentException("Seqera Platform client is not enabled")
102105
}
103106

104107
/**
@@ -138,7 +141,12 @@ class TowerFusionToken implements FusionToken {
138141
* @return The signed JWT token
139142
*/
140143
protected String getLicenseToken(String product, String version) {
141-
final req = new GetLicenseTokenRequest(product: product, version: version ?: 'unknown')
144+
final req = new GetLicenseTokenRequest(
145+
product: product,
146+
version: version ?: 'unknown',
147+
workflowId: workflowId,
148+
workspaceId: workspaceId
149+
)
142150
final key = '${product}-${version}'
143151
try {
144152
final now = Instant.now()

plugins/nf-tower/src/main/io/seqera/tower/plugin/exchange/GetLicenseTokenRequest.groovy

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package io.seqera.tower.plugin.exchange
22

3+
34
import groovy.transform.CompileStatic
45
import groovy.transform.EqualsAndHashCode
56
import groovy.transform.ToString
6-
77
/**
88
* Models a REST request to obtain a license-scoped JWT token from Platform
99
*
@@ -19,4 +19,14 @@ class GetLicenseTokenRequest {
1919

2020
/** The product version */
2121
String version
22+
23+
/**
24+
* The Platform workflow ID associated with this request
25+
*/
26+
String workflowId
27+
28+
/**
29+
* The Platform workspace ID associated with this request
30+
*/
31+
String workspaceId
2232
}

plugins/nf-tower/src/test/io/seqera/tower/plugin/TowerFusionEnvTest.groovy

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import nextflow.SysEnv
1212
import nextflow.util.GsonHelper
1313
import spock.lang.Shared
1414
import spock.lang.Specification
15+
16+
import static com.github.tomakehurst.wiremock.client.WireMock.*
17+
1518
/**
1619
* Test cases for the TowerFusionEnv class.
1720
*
@@ -244,24 +247,29 @@ class TowerFusionEnvTest extends Specification {
244247
SysEnv.pop()
245248
}
246249

247-
def 'should get a license token'() {
248-
given: 'a TowerFusionEnv provider'
249-
Global.session = Mock(Session) {
250-
config >> [
251-
tower: [
252-
endpoint : wireMockServer.baseUrl(),
253-
accessToken: 'abc123'
254-
]
255-
]
256-
}
250+
def 'should get a license token with config'() {
251+
given:
252+
def config = [
253+
endpoint : wireMockServer.baseUrl(),
254+
accessToken: 'abc123',
255+
workspaceId: '67890'
256+
]
257+
def PRODUCT = 'some-product'
258+
def VERSION = 'some-version'
259+
and:
260+
Global.session = Mock(Session) {getConfig() >> [ tower: config ] }
261+
and:
257262
def provider = new TowerFusionToken()
258263

259264
and: 'a mock endpoint returning a valid token'
260265
final now = Instant.now()
261266
final expirationDate = GsonHelper.toJson(now.plus(1, ChronoUnit.DAYS))
262267
wireMockServer.stubFor(
263-
WireMock.post(WireMock.urlEqualTo("/license/token/"))
264-
.withHeader('Authorization', WireMock.equalTo('Bearer abc123'))
268+
WireMock.post(urlEqualTo("/license/token/"))
269+
.withHeader('Authorization', equalTo('Bearer abc123'))
270+
.withRequestBody(matchingJsonPath('$.product', equalTo("some-product")))
271+
.withRequestBody(matchingJsonPath('$.version', equalTo("some-version")))
272+
.withRequestBody(matchingJsonPath('$.workspaceId', equalTo("67890")))
265273
.willReturn(
266274
WireMock.aResponse()
267275
.withStatus(200)
@@ -280,14 +288,53 @@ class TowerFusionEnvTest extends Specification {
280288
wireMockServer.verify(1, WireMock.postRequestedFor(WireMock.urlEqualTo("/license/token/"))
281289
.withHeader('Authorization', WireMock.equalTo('Bearer abc123')))
282290

283-
where:
284-
PRODUCT | VERSION
285-
'some-product' | 'some-version'
286-
'some-product' | null
287-
null | 'some-version'
288-
null | null
289291
}
290292

293+
def 'should get a license token with environment'() {
294+
given:
295+
SysEnv.push([
296+
TOWER_WORKFLOW_ID: '12345',
297+
TOWER_ACCESS_TOKEN: 'abc123',
298+
TOWER_WORKSPACE_ID: '67890',
299+
TOWER_API_ENDPOINT: wireMockServer.baseUrl()
300+
])
301+
def PRODUCT = 'some-product'
302+
def VERSION = 'some-version'
303+
and:
304+
Global.session = Mock(Session) {getConfig() >> [:] }
305+
and:
306+
def provider = new TowerFusionToken()
307+
308+
and: 'a mock endpoint returning a valid token'
309+
final now = Instant.now()
310+
final expirationDate = GsonHelper.toJson(now.plus(1, ChronoUnit.DAYS))
311+
wireMockServer.stubFor(
312+
WireMock.post(urlEqualTo("/license/token/"))
313+
.withHeader('Authorization', equalTo('Bearer abc123'))
314+
.withRequestBody(matchingJsonPath('$.product', equalTo("some-product")))
315+
.withRequestBody(matchingJsonPath('$.version', equalTo("some-version")))
316+
.withRequestBody(matchingJsonPath('$.workspaceId', equalTo("67890")))
317+
.willReturn(
318+
WireMock.aResponse()
319+
.withStatus(200)
320+
.withHeader('Content-Type', 'application/json')
321+
.withBody('{"signedToken":"xyz789", "expiresAt":' + expirationDate + '}')
322+
)
323+
)
324+
325+
when: 'a license token is requested'
326+
final token = provider.getLicenseToken(PRODUCT, VERSION)
327+
328+
then: 'the token has the expected value'
329+
token == 'xyz789'
330+
331+
and: 'the request is correct'
332+
wireMockServer.verify(1, WireMock.postRequestedFor(WireMock.urlEqualTo("/license/token/"))
333+
.withHeader('Authorization', WireMock.equalTo('Bearer abc123')))
334+
335+
cleanup:
336+
SysEnv.pop()
337+
}
291338

292339

293340
def 'should throw UnauthorizedException if getting a token fails with 401'() {
@@ -300,6 +347,7 @@ class TowerFusionEnvTest extends Specification {
300347
]
301348
]
302349
}
350+
and:
303351
def provider = new TowerFusionToken()
304352

305353
and: 'a mock endpoint returning an error'

0 commit comments

Comments
 (0)