Skip to content

Commit d2d4e91

Browse files
author
David Hasani
committed
address feedback
1 parent 1af134f commit d2d4e91

File tree

7 files changed

+83
-183
lines changed

7 files changed

+83
-183
lines changed

packages/core/src/amazonqGumby/app.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,5 @@ export function init(appContext: AmazonQAppInitContext) {
7171
showTransformationHub.register()
7272

7373
transformByQState.setChatControllers(gumbyChatControllerEventEmitters)
74+
transformByQState.setChatMessenger(messenger)
7475
}

packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ export type UnrecoverableErrorType =
4848
| 'unsupported-source-jdk-version'
4949
| 'upload-to-s3-failed'
5050
| 'job-start-failed'
51-
| 'unsupported-source-db-version'
51+
| 'unsupported-source-db'
52+
| 'unsupported-target-db'
53+
| 'error-parsing-sct-file'
5254

5355
export enum GumbyNamedMessages {
5456
COMPILATION_PROGRESS_MESSAGE = 'gumbyProjectCompilationMessage',
@@ -430,9 +432,14 @@ export class Messenger {
430432
case 'unsupported-source-jdk-version':
431433
message = CodeWhispererConstants.unsupportedJavaVersionChatMessage
432434
break
433-
case 'unsupported-source-db-version':
434-
message = CodeWhispererConstants.unsupportedDatabaseChatMessage
435+
case 'unsupported-source-db':
436+
message = CodeWhispererConstants.invalidMetadataFileUnsupportedSourceVendor
435437
break
438+
case 'unsupported-target-db':
439+
message = CodeWhispererConstants.invalidMetadataFileUnsupportedTargetVendor
440+
break
441+
case 'error-parsing-sct-file':
442+
message = CodeWhispererConstants.invalidMetadataFileErrorParsing
436443
}
437444

438445
const buttons: ChatItemButton[] = []
@@ -549,7 +556,13 @@ export class Messenger {
549556
| **Target DB** | ${transformByQState.getTargetDB()} |
550557
| **Host** | ${transformByQState.getSourceServerName()} |
551558
`
552-
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'prompt' }, tabID))
559+
this.dispatcher.sendChatMessage(
560+
new ChatMessage(
561+
{ message: 'I detected the following in your .sct metadata file.', messageType: 'ai-prompt' },
562+
tabID
563+
)
564+
)
565+
this.dispatcher.sendChatMessage(new ChatMessage({ message, messageType: 'ai-prompt' }, tabID))
553566
}
554567

555568
public sendSkipTestsSelectionMessage(skipTestsSelection: string, tabID: string) {

packages/core/src/codewhisperer/commands/startTransformByQ.ts

Lines changed: 50 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,56 @@ export async function processSQLConversionTransformFormInput(pathToProject: stri
103103
transformByQState.setSchema(schema)
104104
}
105105

106+
export async function validateSQLMetadataFile(fileContents: string, message: any) {
107+
try {
108+
let sctData: any = undefined
109+
xml2js.parseString(fileContents, (err, result) => {
110+
if (err) {
111+
getLogger().error('Error parsing .sct file, not valid XML:', err)
112+
throw new Error(`Invalid XML encountered`)
113+
} else {
114+
sctData = result
115+
}
116+
})
117+
118+
const dbEntities = sctData['tree']['instances'][0]['ProjectModel'][0]['entities'][0]
119+
const sourceDB = dbEntities['sources'][0]['DbServer'][0]['$']['vendor'].trim().toUpperCase()
120+
const targetDB = dbEntities['targets'][0]['DbServer'][0]['$']['vendor'].trim().toUpperCase()
121+
const sourceServerName = dbEntities['sources'][0]['DbServer'][0]['$']['name'].trim()
122+
transformByQState.setSourceServerName(sourceServerName)
123+
if (sourceDB !== DB.ORACLE) {
124+
transformByQState.getChatMessenger()?.sendUnrecoverableErrorResponse('unsupported-source-db', message.tabID)
125+
return false
126+
} else if (targetDB !== DB.AURORA_POSTGRESQL && targetDB !== DB.RDS_POSTGRESQL) {
127+
transformByQState.getChatMessenger()?.sendUnrecoverableErrorResponse('unsupported-target-db', message.tabID)
128+
return false
129+
}
130+
transformByQState.setSourceDB(sourceDB)
131+
transformByQState.setTargetDB(targetDB)
132+
133+
const serverNodeLocations =
134+
sctData['tree']['instances'][0]['ProjectModel'][0]['relations'][0]['server-node-location']
135+
const schemaNames = new Set<string>()
136+
serverNodeLocations.forEach((serverNodeLocation: any) => {
137+
const schemaNodes = serverNodeLocation['FullNameNodeInfoList'][0]['nameParts'][0][
138+
'FullNameNodeInfo'
139+
].filter((node: any) => node['$']['typeNode'] === 'schema')
140+
schemaNodes.forEach((node: any) => {
141+
schemaNames.add(node['$']['nameNode'].toUpperCase())
142+
})
143+
})
144+
transformByQState.setSchemaOptions(schemaNames) // user will choose one of these
145+
getLogger().info(
146+
`Parsed SCT file with source DB: ${sourceDB}, target DB: ${targetDB}, source host name: ${sourceServerName}, and schema names: ${schemaNames}`
147+
)
148+
} catch (e: any) {
149+
getLogger().error('Error parsing .sct file:', e)
150+
transformByQState.getChatMessenger()?.sendUnrecoverableErrorResponse('error-parsing-sct-file', message.tabID)
151+
return false
152+
}
153+
return true
154+
}
155+
106156
export async function setMaven() {
107157
let mavenWrapperExecutableName = os.platform() === 'win32' ? 'mvnw.cmd' : 'mvnw'
108158
const mavenWrapperExecutablePath = path.join(transformByQState.getProjectPath(), mavenWrapperExecutableName)
@@ -274,76 +324,6 @@ export async function parseBuildFile() {
274324
return undefined
275325
}
276326

277-
export async function validateSQLMetadataFile(fileContents: string, message: any) {
278-
try {
279-
let sctData: any = undefined
280-
xml2js.parseString(fileContents, (err, result) => {
281-
if (err) {
282-
getLogger().error('Error parsing .sct file, not valid XML:', err)
283-
throw err
284-
} else {
285-
sctData = result
286-
}
287-
})
288-
289-
const dbEntities = sctData['tree']['instances'][0]['ProjectModel'][0]['entities'][0]
290-
const sourceDB = dbEntities['sources'][0]['DbServer'][0]['$']['vendor'].toUpperCase()
291-
const targetDB = dbEntities['targets'][0]['DbServer'][0]['$']['vendor'].toUpperCase()
292-
const sourceServerName = dbEntities['sources'][0]['DbServer'][0]['$']['name']
293-
if (!sourceServerName) {
294-
transformByQState.getChatControllers()?.transformationFinished.fire({
295-
message: CodeWhispererConstants.invalidMetadataFileNoSourceServerName,
296-
tabID: message.tabID,
297-
})
298-
return false
299-
}
300-
transformByQState.setSourceServerName(sourceServerName)
301-
if (sourceDB !== DB.ORACLE) {
302-
transformByQState.getChatControllers()?.transformationFinished.fire({
303-
message: CodeWhispererConstants.invalidMetadataFileUnsupportedSourceVendor(sourceDB),
304-
tabID: message.tabID,
305-
})
306-
return false
307-
} else if (targetDB !== DB.AURORA_POSTGRESQL && targetDB !== DB.RDS_POSTGRESQL) {
308-
transformByQState.getChatControllers()?.transformationFinished.fire({
309-
message: CodeWhispererConstants.invalidMetadataFileUnsupportedTargetVendor(targetDB),
310-
tabID: message.tabID,
311-
})
312-
return false
313-
}
314-
transformByQState.setSourceDB(sourceDB)
315-
transformByQState.setTargetDB(targetDB)
316-
317-
// extract schema names from metadata file
318-
const serverNodeLocations =
319-
sctData['tree']['instances'][0]['ProjectModel'][0]['relations'][0]['server-node-location']
320-
const schemaNames = new Set<string>()
321-
serverNodeLocations.forEach((serverNodeLocation: any) => {
322-
const schemaNodes = serverNodeLocation['FullNameNodeInfoList'][0]['nameParts'][0][
323-
'FullNameNodeInfo'
324-
].filter((node: any) => node['$']['typeNode'] === 'schema')
325-
schemaNodes.forEach((node: any) => {
326-
schemaNames.add(node['$']['nameNode'].toUpperCase())
327-
})
328-
})
329-
if (schemaNames.size === 0) {
330-
transformByQState.getChatControllers()?.transformationFinished.fire({
331-
message: CodeWhispererConstants.invalidMetadataFileNoSchemaNamesFound,
332-
tabID: message.tabID,
333-
})
334-
return false
335-
}
336-
transformByQState.setSchemaOptions(schemaNames) // user will choose one of these
337-
} catch (e: any) {
338-
transformByQState.getChatControllers()?.transformationFinished.fire({
339-
message: `${CodeWhispererConstants.invalidMetadataFileUnknownIssueParsing} ${e.message ?? ''}`,
340-
tabID: message.tabID,
341-
})
342-
return false
343-
}
344-
return true
345-
}
346-
347327
export async function preTransformationUploadCode() {
348328
await vscode.commands.executeCommand('aws.amazonq.transformationHub.focus')
349329

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -502,28 +502,14 @@ export const absolutePathDetectedMessage = (numPaths: number, buildFile: string,
502502

503503
export const unsupportedJavaVersionChatMessage = `Sorry, currently I can only upgrade Java 8 or Java 11 projects. For more information, see the [Amazon Q documentation](${codeTransformPrereqDoc}).`
504504

505-
export const unsupportedDatabaseChatMessage = `Sorry, currently I can only convert SQL built on Oracle. For more information, see the [Amazon Q documentation](${codeTransformPrereqDoc}).`
506-
507505
export const selectSQLMetadataFileHelpMessage =
508-
'You can download the .sct file by going to AWS Console -> AWS DMS -> Migration Projects. Open the schema conversion project and navigate to the S3 bucket linked to it. You will find the ZIP containing the .sct file under the <schema-conversion-project>/ directory.'
509-
510-
export const invalidMetadataFileNoSourceServerName =
511-
'Sorry, your metadata .sct file appears to be invalid; I could not find the server name of the source DB.'
512-
513-
export const invalidMetadataFileUnsupportedSourceVendor = (vendor: string) =>
514-
`Sorry, your metadata .sct file appears to be invalid; the source vendor is '${vendor}', but only Oracle is supported.`
515-
516-
export const invalidMetadataFileUnsupportedTargetVendor = (vendor: string) =>
517-
`Sorry, your metadata .sct file appears to be invalid; the target vendor is '${vendor}', but only Amazon Aurora PostgreSQL and Amazon RDS for PostgreSQL are supported.`
506+
'Next, I need the .sct metadata file of your project. You can download the .sct file by going to AWS Console -> AWS DMS -> Migration Projects. Open the schema conversion project and navigate to the S3 bucket linked to it. You will find the ZIP containing the .sct file under the {schema-conversion-project}/ directory.'
518507

519-
export const invalidMetadataFileTargetVendorMismatch = (foundVendor: string, selectedVendor: string) =>
520-
`Sorry, your metadata .sct file appears to be invalid; the target vendor is '${foundVendor}', but you previously selected a target vendor of '${selectedVendor}'.`
508+
export const invalidMetadataFileUnsupportedSourceVendor = `Sorry, your .sct metadata file appears to be invalid; the source DB must be Oracle.`
521509

522-
export const invalidMetadataFileNoSchemaNamesFound =
523-
'Sorry, your metadata.sct file appears to be invalid; I could not find any schema names.'
510+
export const invalidMetadataFileUnsupportedTargetVendor = `Sorry, your .sct metadata file appears to be invalid; the target DB must be Aurora Postgresql or Amazon RDS for Postgresql.`
524511

525-
export const invalidMetadataFileUnknownIssueParsing =
526-
'Sorry, I had an issue parsing the metadata .sct file you provided; please make sure it is valid.'
512+
export const invalidMetadataFileErrorParsing = 'Sorry, the .sct metadata file you provided appears to be invalid.'
527513

528514
export const oracleVendor = 'Oracle'
529515

packages/core/src/codewhisperer/models/model.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { References } from '../client/codewhisperer'
1717
import globals from '../../shared/extensionGlobals'
1818
import { ChatControllerEventEmitters } from '../../amazonqGumby/chat/controller/controller'
1919
import { TransformationSteps } from '../client/codewhispereruserclient'
20+
import { Messenger } from '../../amazonqGumby/chat/controller/messenger/messenger'
2021

2122
// unavoidable global variables
2223
interface VsCodeState {
@@ -427,6 +428,7 @@ export class TransformByQState {
427428
private javaHome: string | undefined = undefined
428429

429430
private chatControllers: ChatControllerEventEmitters | undefined = undefined
431+
private chatMessenger: Messenger | undefined = undefined
430432

431433
private dependencyFolderInfo: FolderInfo | undefined = undefined
432434

@@ -570,6 +572,10 @@ export class TransformByQState {
570572
return this.chatControllers
571573
}
572574

575+
public getChatMessenger() {
576+
return this.chatMessenger
577+
}
578+
573579
public getDependencyFolderInfo(): FolderInfo | undefined {
574580
return this.dependencyFolderInfo
575581
}
@@ -710,6 +716,10 @@ export class TransformByQState {
710716
this.chatControllers = controllers
711717
}
712718

719+
public setChatMessenger(messenger: Messenger) {
720+
this.chatMessenger = messenger
721+
}
722+
713723
public setDependencyFolderInfo(folderInfo: FolderInfo) {
714724
this.dependencyFolderInfo = folderInfo
715725
}

packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ export async function zipCode({ dependenciesFolder, humanInTheLoopFlag, projectP
402402
export async function startJob(uploadId: string) {
403403
const sourceLanguageVersion = `JAVA_${transformByQState.getSourceJDKVersion()}`
404404
const targetLanguageVersion = `JAVA_${transformByQState.getTargetJDKVersion()}`
405+
// TO-DO: figure out what to set source and target language version too, along with transformation type
405406
try {
406407
const response = await codeWhisperer.codeWhispererClient.codeModernizerStartCodeTransformation({
407408
workspaceState: {

packages/core/src/test/codewhisperer/commands/transformByQ.test.ts

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -493,95 +493,4 @@ describe('transformByQ', function () {
493493
const isValidMetadata = await validateSQLMetadataFile(sampleFileContents, { tabID: 'abc123' })
494494
assert.strictEqual(isValidMetadata, false)
495495
})
496-
497-
it(`WHEN validateMetadataFile on .sct file with no source server name THEN fails validation`, async function () {
498-
const sampleFileContents = `<?xml version="1.0" encoding="UTF-8"?>
499-
<tree>
500-
<instances>
501-
<ProjectModel>
502-
<entities>
503-
<sources>
504-
<DbServer vendor="oracle">
505-
</DbServer>
506-
</sources>
507-
<targets>
508-
<DbServer vendor="rds_postgresql" />
509-
</targets>
510-
</entities>
511-
<relations>
512-
<server-node-location>
513-
<FullNameNodeInfoList>
514-
<nameParts>
515-
<FullNameNodeInfo typeNode="schema" nameNode="schema1"/>
516-
<FullNameNodeInfo typeNode="table" nameNode="table1"/>
517-
</nameParts>
518-
</FullNameNodeInfoList>
519-
</server-node-location>
520-
<server-node-location>
521-
<FullNameNodeInfoList>
522-
<nameParts>
523-
<FullNameNodeInfo typeNode="schema" nameNode="schema2"/>
524-
<FullNameNodeInfo typeNode="table" nameNode="table2"/>
525-
</nameParts>
526-
</FullNameNodeInfoList>
527-
</server-node-location>
528-
<server-node-location>
529-
<FullNameNodeInfoList>
530-
<nameParts>
531-
<FullNameNodeInfo typeNode="schema" nameNode="schema3"/>
532-
<FullNameNodeInfo typeNode="table" nameNode="table3"/>
533-
</nameParts>
534-
</FullNameNodeInfoList>
535-
</server-node-location>
536-
</relations>
537-
</ProjectModel>
538-
</instances>
539-
</tree>`
540-
const isValidMetadata = await validateSQLMetadataFile(sampleFileContents, { tabID: 'abc123' })
541-
assert.strictEqual(isValidMetadata, false)
542-
})
543-
544-
it(`WHEN validateMetadataFile on .sct file with no schema names present THEN fails validation`, async function () {
545-
const sampleFileContents = `<?xml version="1.0" encoding="UTF-8"?>
546-
<tree>
547-
<instances>
548-
<ProjectModel>
549-
<entities>
550-
<sources>
551-
<DbServer vendor="oracle" name="sample.rds.amazonaws.com">
552-
</DbServer>
553-
</sources>
554-
<targets>
555-
<DbServer vendor="rds_postgresql" />
556-
</targets>
557-
</entities>
558-
<relations>
559-
<server-node-location>
560-
<FullNameNodeInfoList>
561-
<nameParts>
562-
<FullNameNodeInfo typeNode="table" nameNode="table1"/>
563-
</nameParts>
564-
</FullNameNodeInfoList>
565-
</server-node-location>
566-
<server-node-location>
567-
<FullNameNodeInfoList>
568-
<nameParts>
569-
<FullNameNodeInfo typeNode="table" nameNode="table2"/>
570-
</nameParts>
571-
</FullNameNodeInfoList>
572-
</server-node-location>
573-
<server-node-location>
574-
<FullNameNodeInfoList>
575-
<nameParts>
576-
<FullNameNodeInfo typeNode="table" nameNode="table3"/>
577-
</nameParts>
578-
</FullNameNodeInfoList>
579-
</server-node-location>
580-
</relations>
581-
</ProjectModel>
582-
</instances>
583-
</tree>`
584-
const isValidMetadata = await validateSQLMetadataFile(sampleFileContents, { tabID: 'abc123' })
585-
assert.strictEqual(isValidMetadata, false)
586-
})
587496
})

0 commit comments

Comments
 (0)