Skip to content

Commit 7571ffd

Browse files
authored
fix(amazonq): add regionalization support to .NET Transform server (#952)
This change updates the .NET Transform server to use AmazonQTokenServiceManager when producing the service client. This way, the service calls are able to provide the developer profile arn or region details for IdC based connections. This change is based on #859, which made a similar change for security scanning. I worked on this change with @shruti0085 , and we tested it by using the Visual Studio Toolkit to perform a .NET Transform using a local build of the server. We were able to see the profileArn field being passed along with all of the .NET Transform related service calls. License By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 1318d29 commit 7571ffd

File tree

3 files changed

+53
-55
lines changed

3 files changed

+53
-55
lines changed

server/aws-lsp-codewhisperer/src/language-server/netTransform/netTransformServer.ts

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
Server,
77
Workspace,
88
} from '@aws/language-server-runtimes/server-interface'
9-
import { StreamingClient } from '../../client/streamingClient/codewhispererStreamingClient'
109
import { CodeWhispererServiceToken } from '../../shared/codeWhispererService'
1110
import {
1211
emitTransformationJobArtifactsDownloadedFailure,
@@ -32,8 +31,6 @@ import {
3231
StartTransformRequest,
3332
} from './models'
3433
import { TransformHandler } from './transformHandler'
35-
import { CodeWhispererStreamingClientConfig } from '@amzn/codewhisperer-streaming'
36-
import { getUserAgent } from '../../shared/telemetryUtils'
3734

3835
export const validStatesForGettingPlan = ['COMPLETED', 'PARTIALLY_COMPLETED', 'PLANNED', 'TRANSFORMING', 'TRANSFORMED']
3936
export const validStatesForComplete = ['COMPLETED']
@@ -45,13 +42,8 @@ const PollTransformForPlanCommand = 'aws/qNetTransform/pollTransformForPlan'
4542
const GetTransformPlanCommand = 'aws/qNetTransform/getTransformPlan'
4643
const CancelTransformCommand = 'aws/qNetTransform/cancelTransform'
4744
const DownloadArtifactsCommand = 'aws/qNetTransform/downloadArtifacts'
48-
import {
49-
DEFAULT_AWS_Q_REGION,
50-
DEFAULT_AWS_Q_ENDPOINT_URL,
51-
AWS_Q_REGION_ENV_VAR,
52-
AWS_Q_ENDPOINT_URL_ENV_VAR,
53-
} from '../../shared/constants'
5445
import { SDKInitializator } from '@aws/language-server-runtimes/server-interface'
46+
import { AmazonQTokenServiceManager } from '../../shared/amazonQServiceManager/AmazonQTokenServiceManager'
5547

5648
/**
5749
*
@@ -69,14 +61,8 @@ export const QNetTransformServerToken =
6961
) => CodeWhispererServiceToken
7062
): Server =>
7163
({ credentialsProvider, workspace, logging, lsp, telemetry, runtime, sdkInitializator }) => {
72-
const codewhispererclient = service(
73-
credentialsProvider,
74-
workspace,
75-
runtime.getConfiguration(AWS_Q_REGION_ENV_VAR) ?? DEFAULT_AWS_Q_REGION,
76-
runtime.getConfiguration(AWS_Q_ENDPOINT_URL_ENV_VAR) ?? DEFAULT_AWS_Q_ENDPOINT_URL,
77-
sdkInitializator
78-
)
79-
const transformHandler = new TransformHandler(codewhispererclient, workspace, logging, runtime)
64+
let amazonQServiceManager: AmazonQTokenServiceManager
65+
let transformHandler: TransformHandler
8066
const runTransformCommand = async (params: ExecuteCommandParams, _token: CancellationToken) => {
8167
try {
8268
switch (params.command) {
@@ -128,17 +114,8 @@ export const QNetTransformServerToken =
128114
}
129115
case DownloadArtifactsCommand: {
130116
const request = params as DownloadArtifactsRequest
131-
const cwStreamingClientInstance = new StreamingClient()
132-
const cwStreamingClient = await cwStreamingClientInstance.getStreamingClient(
133-
credentialsProvider,
134-
runtime.getConfiguration(AWS_Q_REGION_ENV_VAR) ?? DEFAULT_AWS_Q_REGION,
135-
runtime.getConfiguration(AWS_Q_ENDPOINT_URL_ENV_VAR) ?? DEFAULT_AWS_Q_ENDPOINT_URL,
136-
sdkInitializator,
137-
customCWClientConfig
138-
)
139117

140118
const response = await transformHandler.downloadExportResultArchive(
141-
cwStreamingClient,
142119
request.TransformationJobId,
143120
request.SolutionRootPath
144121
)
@@ -202,15 +179,25 @@ export const QNetTransformServerToken =
202179
return runTransformCommand(params, _token)
203180
}
204181

205-
const customCWClientConfig: CodeWhispererStreamingClientConfig = {}
206-
const onInitializeHandler = (params: InitializeParams) => {
207-
// Cache user agent to reuse between commands calls
208-
customCWClientConfig.customUserAgent = getUserAgent(params, runtime.serverInfo)
209-
210-
codewhispererclient.updateClientConfig({
211-
customUserAgent: customCWClientConfig.customUserAgent,
182+
const onInitializeHandler = async (params: InitializeParams) => {
183+
amazonQServiceManager = AmazonQTokenServiceManager.getInstance({
184+
lsp,
185+
logging,
186+
runtime,
187+
credentialsProvider,
188+
sdkInitializator,
189+
workspace,
212190
})
213191

192+
transformHandler = new TransformHandler(amazonQServiceManager, workspace, logging, runtime)
193+
194+
/*
195+
Calling handleDidChangeConfiguration once to ensure we get configuration atleast once at start up
196+
197+
TODO: TODO: consider refactoring such responsibilities to common service manager config/initialisation server
198+
*/
199+
await amazonQServiceManager.handleDidChangeConfiguration()
200+
214201
return {
215202
capabilities: {
216203
executeCommandProvider: {

server/aws-lsp-codewhisperer/src/language-server/netTransform/tests/transformHandler.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { Readable } from 'stream'
3232
import { ArtifactManager } from '../artifactManager'
3333
import path = require('path')
3434
import { IZipEntry } from 'adm-zip'
35+
import { AmazonQTokenServiceManager } from '../../../shared/amazonQServiceManager/AmazonQTokenServiceManager'
3536

3637
const mocked$Response = {
3738
$response: {
@@ -62,7 +63,12 @@ describe('Test Transform handler ', () => {
6263
client = stubInterface<CodeWhispererServiceToken>()
6364
workspace = stubInterface<Workspace>()
6465
runtime = stubInterface<Runtime>()
65-
transformHandler = new TransformHandler(client, workspace, mockedLogging, runtime)
66+
67+
const serviceManager = stubInterface<AmazonQTokenServiceManager>()
68+
client = stubInterface<CodeWhispererServiceToken>()
69+
serviceManager.getCodewhispererService.returns(client)
70+
71+
transformHandler = new TransformHandler(serviceManager, workspace, mockedLogging, runtime)
6672
})
6773

6874
describe('test upload artifact', () => {

server/aws-lsp-codewhisperer/src/language-server/netTransform/transformHandler.ts

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CodeWhispererStreaming, ExportIntent } from '@amzn/codewhisperer-streaming'
1+
import { ExportIntent } from '@amzn/codewhisperer-streaming'
22
import { Logging, Runtime, Workspace } from '@aws/language-server-runtimes/server-interface'
33
import * as fs from 'fs'
44
import got from 'got'
@@ -9,7 +9,6 @@ import {
99
StopTransformationRequest,
1010
TransformationJob,
1111
} from '../../client/token/codewhispererbearertokenclient'
12-
import { CodeWhispererServiceToken } from '../../shared/codeWhispererService'
1312
import { ArtifactManager } from './artifactManager'
1413
import { getCWStartTransformRequest, getCWStartTransformResponse } from './converter'
1514
import {
@@ -29,21 +28,17 @@ import {
2928
import * as validation from './validation'
3029
import path = require('path')
3130
import AdmZip = require('adm-zip')
32-
import { Console } from 'console'
33-
import { supportedProjects, unsupportedViewComponents } from './resources/SupportedProjects'
34-
import { String } from 'aws-sdk/clients/codebuild'
35-
import { ProjectMetadata } from 'aws-sdk/clients/lookoutvision'
36-
import { httpstatus } from 'aws-sdk/clients/glacier'
31+
import { AmazonQTokenServiceManager } from '../../shared/amazonQServiceManager/AmazonQTokenServiceManager'
3732

3833
const workspaceFolderName = 'artifactWorkspace'
3934

4035
export class TransformHandler {
41-
private client: CodeWhispererServiceToken
36+
private serviceManager: AmazonQTokenServiceManager
4237
private workspace: Workspace
4338
private logging: Logging
4439
private runtime: Runtime
45-
constructor(client: CodeWhispererServiceToken, workspace: Workspace, logging: Logging, runtime: Runtime) {
46-
this.client = client
40+
constructor(serviceManager: AmazonQTokenServiceManager, workspace: Workspace, logging: Logging, runtime: Runtime) {
41+
this.serviceManager = serviceManager
4742
this.workspace = workspace
4843
this.logging = logging
4944
this.runtime = runtime
@@ -82,7 +77,9 @@ export class TransformHandler {
8277
const uploadId = await this.preTransformationUploadCode(payloadFilePath)
8378
const request = getCWStartTransformRequest(userInputrequest, uploadId, this.logging)
8479
this.logging.log('Sending request to start transform api: ' + JSON.stringify(request))
85-
const response = await this.client.codeModernizerStartCodeTransformation(request)
80+
const response = await this.serviceManager
81+
.getCodewhispererService()
82+
.codeModernizerStartCodeTransformation(request)
8683
this.logging.log('Received transformation job Id: ' + response?.transformationJobId)
8784
return getCWStartTransformResponse(
8885
response,
@@ -122,7 +119,7 @@ export class TransformHandler {
122119
const sha256 = await ArtifactManager.getSha256Async(payloadFileName)
123120
let response: CreateUploadUrlResponse
124121
try {
125-
response = await this.client.codeModernizerCreateUploadUrl({
122+
response = await this.serviceManager.getCodewhispererService().codeModernizerCreateUploadUrl({
126123
contentChecksum: sha256,
127124
contentChecksumType: 'SHA_256',
128125
uploadIntent: 'TRANSFORMATION',
@@ -192,7 +189,9 @@ export class TransformHandler {
192189
const getCodeTransformationRequest = {
193190
transformationJobId: request.TransformationJobId,
194191
} as GetTransformationRequest
195-
const response = await this.client.codeModernizerGetCodeTransformation(getCodeTransformationRequest)
192+
const response = await this.serviceManager
193+
.getCodewhispererService()
194+
.codeModernizerGetCodeTransformation(getCodeTransformationRequest)
196195
this.logging.log('Transformation status: ' + response.transformationJob?.status)
197196
return {
198197
TransformationJob: response.transformationJob,
@@ -211,9 +210,9 @@ export class TransformHandler {
211210
const getCodeTransformationPlanRequest = {
212211
transformationJobId: request.TransformationJobId,
213212
} as GetTransformationRequest
214-
const response = await this.client.codeModernizerGetCodeTransformationPlan(
215-
getCodeTransformationPlanRequest
216-
)
213+
const response = await this.serviceManager
214+
.getCodewhispererService()
215+
.codeModernizerGetCodeTransformationPlan(getCodeTransformationPlanRequest)
217216
return {
218217
TransformationPlan: response.transformationPlan,
219218
} as GetTransformPlanResponse
@@ -247,7 +246,9 @@ export class TransformHandler {
247246
this.logging.log(
248247
'Sending CancelTransformRequest with job Id: ' + stopCodeTransformationRequest.transformationJobId
249248
)
250-
const response = await this.client.codeModernizerStopCodeTransformation(stopCodeTransformationRequest)
249+
const response = await this.serviceManager
250+
.getCodewhispererService()
251+
.codeModernizerStopCodeTransformation(stopCodeTransformationRequest)
251252
this.logging.log('Transformation status: ' + response.transformationStatus)
252253
let status: CancellationJobStatus
253254
switch (response.transformationStatus) {
@@ -293,7 +294,9 @@ export class TransformHandler {
293294
const getCodeTransformationRequest = {
294295
transformationJobId: request.TransformationJobId,
295296
} as GetTransformationRequest
296-
let response = await this.client.codeModernizerGetCodeTransformation(getCodeTransformationRequest)
297+
let response = await this.serviceManager
298+
.getCodewhispererService()
299+
.codeModernizerGetCodeTransformation(getCodeTransformationRequest)
297300
this.logging.log('Start polling for transformation plan.')
298301
this.logging.log('The valid status to exit polling are: ' + validExitStatus)
299302
this.logging.log('The failure status are: ' + failureStates)
@@ -308,7 +311,9 @@ export class TransformHandler {
308311
const getCodeTransformationRequest = {
309312
transformationJobId: request.TransformationJobId,
310313
} as GetTransformationRequest
311-
response = await this.client.codeModernizerGetCodeTransformation(getCodeTransformationRequest)
314+
response = await this.serviceManager
315+
.getCodewhispererService()
316+
.codeModernizerGetCodeTransformation(getCodeTransformationRequest)
312317
this.logging.log('Transformation status: ' + response.transformationJob?.status)
313318

314319
if (validExitStatus.includes(status)) {
@@ -350,10 +355,10 @@ export class TransformHandler {
350355
} as GetTransformResponse
351356
}
352357

353-
async downloadExportResultArchive(cwStreamingClient: CodeWhispererStreaming, exportId: string, saveToDir: string) {
358+
async downloadExportResultArchive(exportId: string, saveToDir: string) {
354359
let result
355360
try {
356-
result = await cwStreamingClient.exportResultArchive({
361+
result = await this.serviceManager.getStreamingClient().client.exportResultArchive({
357362
exportId,
358363
exportIntent: ExportIntent.TRANSFORMATION,
359364
})

0 commit comments

Comments
 (0)