Skip to content

Commit 0eac465

Browse files
author
David Hasani
committed
just get .sct file
1 parent 5a14711 commit 0eac465

File tree

6 files changed

+79
-31
lines changed

6 files changed

+79
-31
lines changed

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

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* the Gumby extension.
77
*/
88
import nodefs from 'fs' // eslint-disable-line no-restricted-imports
9-
import os from 'os'
9+
import * as xml2js from 'xml2js'
1010
import path from 'path'
1111
import * as vscode from 'vscode'
1212
import { GumbyNamedMessages, Messenger } from './messenger/messenger'
@@ -62,7 +62,6 @@ import { getAuthType } from '../../../codewhisperer/service/transformByQ/transfo
6262
import DependencyVersions from '../../models/dependencies'
6363
import { getStringHash } from '../../../shared/utilities/textUtilities'
6464
import { getVersionData } from '../../../codewhisperer/service/transformByQ/transformMavenHandler'
65-
import AdmZip from 'adm-zip'
6665

6766
// These events can be interactions within the chat,
6867
// or elsewhere in the IDE
@@ -530,6 +529,9 @@ export class GumbyController {
530529
const fileUri = await vscode.window.showOpenDialog({
531530
canSelectMany: false, // Allow only one file to be selected
532531
openLabel: 'Select', // Label for the open button
532+
filters: {
533+
'SCT metadata': ['sct'], // Restrict user to only pick a .sct file
534+
},
533535
})
534536

535537
if (!fileUri || fileUri.length === 0) {
@@ -541,26 +543,44 @@ export class GumbyController {
541543
return
542544
}
543545

544-
const metadataZip = new AdmZip(fileUri[0].fsPath)
545-
const pathToZip = path.join(os.tmpdir(), 'SCT-metadata')
546-
metadataZip.extractAllTo(pathToZip, true)
547-
const zipEntries = metadataZip.getEntries()
548-
const pathToRules = zipEntries.find((entry) => entry.name === 'sct-rules.json')?.entryName
546+
const fileContents = nodefs.readFileSync(fileUri[0].fsPath, 'utf-8')
547+
let parsedData: any = undefined
548+
xml2js.parseString(fileContents, (err, result) => {
549+
if (err) {
550+
getLogger().error('Error parsing SCT file:', err)
551+
} else {
552+
parsedData = result
553+
}
554+
})
549555

550-
if (!pathToRules) {
556+
if (!parsedData) {
551557
this.transformationFinished({
552-
message: CodeWhispererConstants.invalidMetadataFileNoRulesJson,
558+
message: CodeWhispererConstants.invalidMetadataFileUnknownIssueParsing,
553559
tabID: message.tabID,
554560
})
555561
return
556562
}
557563

558-
const sctRulesData = nodefs.readFileSync(path.join(pathToZip, pathToRules), 'utf8')
559-
const isValidSctRulesData = await validateSQLMetadataFile(sctRulesData, message)
560-
if (!isValidSctRulesData) {
564+
const isValidMetadata = await validateSQLMetadataFile(parsedData, message)
565+
if (!isValidMetadata) {
561566
return
562567
}
563568

569+
// extract schema names from metadata file
570+
// probably if anything throws here we should just continue and not validate the user's schema input
571+
// unless we show a form with the schema options, in which case this needs to pass
572+
const serverNodeLocations =
573+
parsedData['tree']['instances'][0]['ProjectModel'][0]['relations'][0]['server-node-location']
574+
const schemaNames = new Set<string>()
575+
serverNodeLocations.forEach((serverNodeLocation: any) => {
576+
const schemaNodes = serverNodeLocation['FullNameNodeInfoList'][0]['nameParts'][0][
577+
'FullNameNodeInfo'
578+
].filter((node: any) => node['$']['typeNode'] === 'schema')
579+
schemaNodes.forEach((node: any) => {
580+
schemaNames.add(node['$']['nameNode'].toUpperCase())
581+
})
582+
})
583+
564584
transformByQState.setMetadataPathSQL(fileUri[0].fsPath)
565585

566586
this.messenger.sendAsyncEventProgress(

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,8 @@ export class Messenger {
536536
message: CodeWhispererConstants.checkingForProjectsChatMessage,
537537
})
538538
)
539+
540+
// TO-DO: add a delay for 2s here to match IntelliJ
539541
}
540542

541543
public sendLanguageUpgradeProjectSelectionMessage(
@@ -722,7 +724,7 @@ ${codeSnippet}
722724
}
723725

724726
public sendSelectSQLMetadataFileMessage(tabID: string) {
725-
const message = 'Please select your metadata ZIP file.'
727+
const message = 'Please select your metadata .sct file.'
726728
const buttons: ChatItemButton[] = []
727729

728730
buttons.push({

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,13 @@ export async function parseBuildFile() {
274274
return undefined
275275
}
276276

277-
export async function validateSQLMetadataFile(sctRulesData: any, message: any) {
277+
export async function validateSQLMetadataFile(sctData: any, message: any) {
278278
try {
279-
const sctRules = JSON.parse(sctRulesData)
280-
const sourceDB = sctRules['rules'][0]['locator']['sourceVendor'] as string
281-
const targetDB = sctRules['rules'][0]['locator']['targetVendor'] as string
279+
const dbEntities = sctData['tree']['instances'][0]['ProjectModel'][0]['entities'][0]
280+
const sourceDB = dbEntities['sources'][0]['DbServer'][0]['$']['vendor']
281+
const targetDB = dbEntities['targets'][0]['DbServer'][0]['$']['vendor']
282+
const sourceServerName = dbEntities['sources'][0]['DbServer'][0]['$']['name']
283+
transformByQState.setSourceServerName(sourceServerName)
282284
if (sourceDB.toUpperCase() !== DB.ORACLE) {
283285
transformByQState.getChatControllers()?.transformationFinished.fire({
284286
message: CodeWhispererConstants.invalidMetadataFileUnsupportedSourceVendor(sourceDB),
@@ -301,6 +303,7 @@ export async function validateSQLMetadataFile(sctRulesData: any, message: any) {
301303
})
302304
return false
303305
}
306+
// TO-DO: when more than just Oracle is supported, validate that sourceDB === transformByQState.getSourceDB()
304307
} catch (e: any) {
305308
transformByQState.getChatControllers()?.transformationFinished.fire({
306309
message: CodeWhispererConstants.invalidMetadataFileUnknownIssueParsing,

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ export const newCustomizationMessage = 'You have access to new Amazon Q customiz
352352
// Start of QCT Strings
353353

354354
// feature flag for SQL transformations
355-
export const isSQLTransformReady = false
355+
export const isSQLTransformReady = true
356356

357357
export const uploadZipSizeLimitInBytes = 2000000000 // 2GB
358358

@@ -508,13 +508,13 @@ export const invalidMetadataFileNoRulesJson =
508508
"Sorry, your metadata ZIP appears to be invalid; it does not contain an 'sct-rules.json' file."
509509

510510
export const invalidMetadataFileUnsupportedSourceVendor = (vendor: string) =>
511-
`Sorry, your metadata ZIP appears to be invalid; the source vendor is '${vendor}', but only 'Oracle' is supported.`
511+
`Sorry, your metadata file appears to be invalid; the source vendor is '${vendor}', but only Oracle is supported.`
512512

513513
export const invalidMetadataFileUnsupportedTargetVendor = (vendor: string) =>
514-
`Sorry, your metadata ZIP appears to be invalid; the target vendor is '${vendor}', but only 'Amazon Aurora PostgreSQL' and 'Amazon RDS for PostgreSQL' are supported.`
514+
`Sorry, your metadata file appears to be invalid; the target vendor is '${vendor}', but only Amazon Aurora PostgreSQL and Amazon RDS for PostgreSQL are supported.`
515515

516516
export const invalidMetadataFileTargetVendorMismatch = (foundVendor: string, selectedVendor: string) =>
517-
`Sorry, your metadata ZIP appears to be invalid; the target vendor is '${foundVendor}', but you previously selected a target vendor of '${selectedVendor}'.`
517+
`Sorry, your metadata file appears to be invalid; the target vendor is '${foundVendor}', but you previously selected a target vendor of '${selectedVendor}'.`
518518

519519
export const invalidMetadataFileUnknownIssueParsing =
520520
'Sorry, I had an issue parsing the metadata ZIP you provided; please make sure it is valid.'

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,13 @@ export class ZipManifest {
324324
hilCapabilities: string[] = ['HIL_1pDependency_VersionUpgrade']
325325
transformCapabilities: string[] = ['EXPLAINABILITY_V1']
326326
customBuildCommand: string = 'clean test'
327-
sqlMetadataPath: string | undefined = undefined
327+
customConversions: {
328+
type: string | undefined
329+
source: string | undefined
330+
target: string | undefined
331+
schema: string | undefined
332+
host: string | undefined
333+
} = { type: undefined, source: undefined, target: undefined, schema: undefined, host: undefined }
328334
}
329335

330336
export interface IHilZipManifestParams {
@@ -389,6 +395,8 @@ export class TransformByQState {
389395

390396
private targetDB: DB | undefined = undefined
391397

398+
private sourceServerName: string = ''
399+
392400
private metadataPathSQL: string = ''
393401

394402
private planFilePath: string = ''
@@ -486,6 +494,10 @@ export class TransformByQState {
486494
return this.targetDB
487495
}
488496

497+
public getSourceServerName() {
498+
return this.sourceServerName
499+
}
500+
489501
public getMetadataPathSQL() {
490502
return this.metadataPathSQL
491503
}
@@ -622,6 +634,10 @@ export class TransformByQState {
622634
this.targetDB = db
623635
}
624636

637+
public setSourceServerName(serverName: string) {
638+
this.sourceServerName = serverName
639+
}
640+
625641
public setMetadataPathSQL(path: string) {
626642
this.metadataPathSQL = path
627643
}
@@ -705,6 +721,7 @@ export class TransformByQState {
705721
this.jobFailureMetadata = ''
706722
this.payloadFilePath = ''
707723
this.metadataPathSQL = ''
724+
this.sourceServerName = ''
708725
this.errorLog = ''
709726
this.customBuildCommand = ''
710727
this.intervalId = undefined

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

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -315,21 +315,26 @@ export async function zipCode(
315315
getLogger().info(`CodeTransformation: source code files size = ${sourceFilesSize}`)
316316
}
317317

318-
if (transformByQState.getMetadataPathSQL()) {
319-
// user is doing a SQL conversion
320-
zip.addLocalFile(transformByQState.getMetadataPathSQL())
321-
// must be true here, since only other option is HilZipManifest (not used for SQL conversions)
322-
if (zipManifest instanceof ZipManifest) {
323-
zipManifest.sqlMetadataPath = path.basename(transformByQState.getMetadataPathSQL())
324-
}
318+
if (transformByQState.getMetadataPathSQL() && zipManifest instanceof ZipManifest) {
319+
// user is doing a SQL conversion since metadataPath is defined
320+
// also, it must be a ZipManifest since only other option is HilZipManifest which is not used for SQL conversions
321+
zip.addLocalFile(
322+
transformByQState.getMetadataPathSQL(),
323+
path.join(zipManifest.sourcesRoot, 'sct-metadata-random-num')
324+
)
325+
zipManifest.customConversions['source'] = transformByQState.getSourceDB()
326+
zipManifest.customConversions['target'] = transformByQState.getTargetDB()
327+
zipManifest.customConversions['type'] = 'SQL'
328+
zipManifest.customConversions['schema'] = 'ADMIN-get-from-user'
329+
zipManifest.customConversions['host'] = transformByQState.getSourceServerName()
325330
const sqlMetadataSize = (await nodefs.promises.stat(transformByQState.getMetadataPathSQL())).size
326331
getLogger().info(`CodeTransformation: SQL metadata file size = ${sqlMetadataSize}`)
327332
}
328333

329334
throwIfCancelled()
330335

331336
let dependencyFiles: string[] = []
332-
if (dependenciesFolder && await fs.exists(dependenciesFolder.path)) {
337+
if (dependenciesFolder && (await fs.exists(dependenciesFolder.path))) {
333338
dependencyFiles = getFilesRecursively(dependenciesFolder.path, true)
334339
}
335340

@@ -367,10 +372,11 @@ export async function zipCode(
367372

368373
tempFilePath = path.join(os.tmpdir(), 'zipped-code.zip')
369374
await fs.writeFile(tempFilePath, zip.toBuffer())
370-
if (dependenciesFolder && await fs.exists(dependenciesFolder.path)) {
375+
if (dependenciesFolder && (await fs.exists(dependenciesFolder.path))) {
371376
await fs.delete(dependenciesFolder.path, { recursive: true, force: true })
372377
}
373378
} catch (e: any) {
379+
getLogger().error(`CodeTransformation: zipCode error = ${e}`)
374380
throw Error('Failed to zip project')
375381
} finally {
376382
if (logFilePath) {

0 commit comments

Comments
 (0)