Skip to content

Commit 20a5e85

Browse files
authored
feat(smus): Migrate private model from sdk v2 to sdk v3 - GlueCatalog (#8396)
## Summary This PR migrates the GlueCatalog custom API client from the deprecated AWS SDK v2 generator pattern to standalone AWS SDK v3-compatible packages. This migration is required as part of the broader AWS Toolkit repository migration from SDK v2 to v3. The AWS Toolkit VSCode repository is deprecating the centralized generateServiceClient.ts script that generates TypeScript clients from service JSON definitions. The SageMaker Unified Studio (SMUS) team currently uses this v2 generator for GlueCatalog. ## Solution * Created standalone package @amzn/glue-catalog-client * Updated imports to use new standalone package * Removed dependency for `GlueCatalogApi` on the deprecated generateServiceClient.ts script --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 60bd541 commit 20a5e85

File tree

11 files changed

+1193
-2797
lines changed

11 files changed

+1193
-2797
lines changed

package-lock.json

Lines changed: 1093 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@
581581
"@amzn/amazon-q-developer-streaming-client": "file:../../src.gen/@amzn/amazon-q-developer-streaming-client",
582582
"@amzn/codewhisperer-streaming": "file:../../src.gen/@amzn/codewhisperer-streaming",
583583
"@amzn/sagemaker-client": "file:../../src.gen/@amzn/sagemaker-client/1.0.0.tgz",
584+
"@amzn/glue-catalog-client": "file:../../src.gen/@amzn/glue-catalog-client/0.0.1.tgz",
584585
"@aws-sdk/client-accessanalyzer": "^3.888.0",
585586
"@aws-sdk/client-api-gateway": "<3.731.0",
586587
"@aws-sdk/client-apprunner": "<3.731.0",

packages/core/scripts/build/generateServiceClient.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,6 @@ void (async () => {
241241
serviceJsonPath: 'src/codewhisperer/client/user-service-2.json',
242242
serviceName: 'CodeWhispererUserClient',
243243
},
244-
{
245-
serviceJsonPath: 'src/sagemakerunifiedstudio/shared/client/gluecatalogapi.json',
246-
serviceName: 'GlueCatalogApi',
247-
},
248244
{
249245
serviceJsonPath: 'src/sagemakerunifiedstudio/shared/client/sqlworkbench.json',
250246
serviceName: 'SQLWorkbench',

packages/core/src/sagemakerunifiedstudio/explorer/nodes/lakehouseStrategy.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as vscode from 'vscode'
77
import { TreeNode } from '../../../shared/treeview/resourceTreeDataProvider'
88
import { getLogger } from '../../../shared/logger/logger'
99
import { DataZoneConnection } from '../../shared/client/datazoneClient'
10-
import { GlueCatalog, GlueCatalogClient } from '../../shared/client/glueCatalogClient'
10+
import { Catalog } from '@amzn/glue-catalog-client'
1111
import { GlueClient } from '../../shared/client/glueClient'
1212
import { ConnectionClientStore } from '../../shared/client/connectionClientStore'
1313
import {
@@ -38,6 +38,7 @@ import { Column, Database, Table } from '@aws-sdk/client-glue'
3838
import { ConnectionCredentialsProvider } from '../../auth/providers/connectionCredentialsProvider'
3939
import { telemetry } from '../../../shared/telemetry/telemetry'
4040
import { recordDataConnectionTelemetry } from '../../shared/telemetry'
41+
import { GlueCatalogClient } from '../../shared/client/glueCatalogClient'
4142

4243
/**
4344
* Lakehouse data node for SageMaker Unified Studio
@@ -249,8 +250,8 @@ function createAwsDataCatalogNode(parent: LakehouseNode, glueClient: GlueClient)
249250
}
250251

251252
export interface CatalogTree {
252-
parent: GlueCatalog
253-
children?: GlueCatalog[]
253+
parent: Catalog
254+
children?: Catalog[]
254255
}
255256

256257
/**
@@ -265,7 +266,7 @@ export interface CatalogTree {
265266
*
266267
* Without the first pass, we'd need O(n²) time to find parent catalogs for each child catalog.
267268
*/
268-
function buildCatalogTree(catalogs: GlueCatalog[]): CatalogTree[] {
269+
function buildCatalogTree(catalogs: Catalog[]): CatalogTree[] {
269270
const catalogMap: Record<string, CatalogTree> = {}
270271
const rootCatalogs: CatalogTree[] = []
271272

@@ -372,7 +373,7 @@ async function getCatalogs(
372373
*/
373374
function createCatalogNode(
374375
catalogId: string,
375-
catalog: GlueCatalog,
376+
catalog: Catalog,
376377
glueClient: GlueClient,
377378
parent: LakehouseNode,
378379
isParent: boolean = false

packages/core/src/sagemakerunifiedstudio/explorer/nodes/redshiftStrategy.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
} from './utils'
2323
import { createPlaceholderItem } from '../../../shared/treeview/utils'
2424
import { ConnectionCredentialsProvider } from '../../auth/providers/connectionCredentialsProvider'
25-
import { GlueCatalog } from '../../shared/client/glueCatalogClient'
25+
import { Catalog } from '@amzn/glue-catalog-client'
2626
import { handleCredExpiredError } from '../../shared/credentialExpiryHandler'
2727
import { telemetry } from '../../../shared/telemetry/telemetry'
2828
import { recordDataConnectionTelemetry } from '../../shared/telemetry'
@@ -169,7 +169,7 @@ export function createRedshiftConnectionNode(
169169

170170
// Fetch Glue catalogs for filtering purposes only
171171
// This will help determine which catalogs are accessible within the project
172-
let glueCatalogs: GlueCatalog[] = []
172+
let glueCatalogs: Catalog[] = []
173173
try {
174174
glueCatalogs = await listGlueCatalogs(
175175
connection.connectionId,
@@ -771,7 +771,7 @@ async function listGlueCatalogs(
771771
connectionId: string,
772772
region: string,
773773
connectionCredentialsProvider: ConnectionCredentialsProvider
774-
): Promise<GlueCatalog[]> {
774+
): Promise<Catalog[]> {
775775
const clientStore = ConnectionClientStore.getInstance()
776776
const glueCatalogClient = clientStore.getGlueCatalogClient(connectionId, region, connectionCredentialsProvider)
777777

packages/core/src/sagemakerunifiedstudio/explorer/nodes/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { getContext } from '../../../shared/vscode/setContext'
2424
import { SmusAuthenticationProvider } from '../../auth/providers/smusAuthenticationProvider'
2525
import { SmusIamConnection } from '../../auth/model'
2626
import { ConnectionStatus } from '@aws-sdk/client-datazone'
27-
import { GlueCatalog } from '../../shared/client/glueCatalogClient'
27+
import { Catalog } from '@amzn/glue-catalog-client'
2828

2929
/**
3030
* Polling interval in milliseconds for checking space status updates
@@ -35,7 +35,7 @@ export const PENDING_NODE_POLLING_INTERVAL_MS = 5000
3535
/**
3636
* Check if a catalog is a RedLake catalog
3737
*/
38-
export const isRedLakeCatalog = (catalog?: GlueCatalog) => {
38+
export const isRedLakeCatalog = (catalog?: Catalog) => {
3939
return (
4040
catalog?.FederatedCatalog?.ConnectionName === 'aws:redshift' ||
4141
catalog?.CatalogProperties?.DataLakeAccessProperties?.CatalogType === 'aws:redshift'
@@ -45,7 +45,7 @@ export const isRedLakeCatalog = (catalog?: GlueCatalog) => {
4545
/**
4646
* Check if a catalog is a S3 table catalog
4747
*/
48-
export const isS3TablesCatalog = (catalog?: GlueCatalog) => {
48+
export const isS3TablesCatalog = (catalog?: Catalog) => {
4949
return catalog?.FederatedCatalog?.ConnectionName === 'aws:s3tables'
5050
}
5151

packages/core/src/sagemakerunifiedstudio/shared/client/glueCatalogClient.ts

Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,15 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { Service } from 'aws-sdk'
7-
import globals from '../../../shared/extensionGlobals'
86
import { getLogger } from '../../../shared/logger/logger'
9-
import * as GlueCatalogApi from './gluecatalogapi'
10-
import apiConfig = require('./gluecatalogapi.json')
11-
import { ServiceConfigurationOptions } from 'aws-sdk/lib/service'
7+
import { GlueCatalog, Catalog } from '@amzn/glue-catalog-client'
128
import { ConnectionCredentialsProvider } from '../../auth/providers/connectionCredentialsProvider'
13-
import { adaptConnectionCredentialsProvider } from './credentialsAdapter'
14-
15-
/**
16-
* Represents a Glue catalog
17-
*/
18-
export type GlueCatalog = GlueCatalogApi.Types.Catalog
199

2010
/**
2111
* Client for interacting with Glue Catalog API
2212
*/
2313
export class GlueCatalogClient {
24-
private glueClient: GlueCatalogApi | undefined
14+
private glueClient: GlueCatalog | undefined
2515
private static instance: GlueCatalogClient | undefined
2616
private readonly logger = getLogger('smus')
2717

@@ -67,21 +57,19 @@ export class GlueCatalogClient {
6757
* @param nextToken Optional pagination token
6858
* @returns Object containing catalogs and nextToken
6959
*/
70-
public async getCatalogs(nextToken?: string): Promise<{ catalogs: GlueCatalog[]; nextToken?: string }> {
60+
public async getCatalogs(nextToken?: string): Promise<{ catalogs: Catalog[]; nextToken?: string }> {
7161
try {
7262
this.logger.info(`GlueCatalogClient: Getting catalogs in region ${this.region}`)
7363

7464
const glueClient = await this.getGlueCatalogClient()
7565

7666
// Call the GetCatalogs API with pagination
77-
const response = await glueClient
78-
.getCatalogs({
79-
Recursive: true,
80-
NextToken: nextToken,
81-
})
82-
.promise()
67+
const response = await glueClient.getCatalogs({
68+
Recursive: true,
69+
NextToken: nextToken,
70+
})
8371

84-
const catalogs: GlueCatalog[] = response.CatalogList || []
72+
const catalogs: Catalog[] = response.CatalogList || []
8573

8674
this.logger.info(`GlueCatalogClient: Found ${catalogs.length} catalogs in this page`)
8775
return {
@@ -97,32 +85,30 @@ export class GlueCatalogClient {
9785
/**
9886
* Gets the Glue client, initializing it if necessary
9987
*/
100-
private async getGlueCatalogClient(): Promise<GlueCatalogApi> {
88+
private async getGlueCatalogClient(): Promise<GlueCatalog> {
10189
if (!this.glueClient) {
10290
try {
10391
if (this.connectionCredentialsProvider) {
104-
// Create client with provided credentials
105-
this.glueClient = (await globals.sdkClientBuilder.createAwsService(
106-
Service,
107-
{
108-
apiConfig: apiConfig,
109-
region: this.region,
110-
credentialProvider: adaptConnectionCredentialsProvider(this.connectionCredentialsProvider),
111-
} as ServiceConfigurationOptions,
112-
undefined,
113-
false
114-
)) as GlueCatalogApi
92+
// Create client with credential provider function for auto-refresh
93+
const awsCredentialProvider = async () => {
94+
const credentials = await this.connectionCredentialsProvider!.getCredentials()
95+
return {
96+
accessKeyId: credentials.accessKeyId,
97+
secretAccessKey: credentials.secretAccessKey,
98+
sessionToken: credentials.sessionToken,
99+
expiration: credentials.expiration,
100+
}
101+
}
102+
103+
this.glueClient = new GlueCatalog({
104+
region: this.region,
105+
credentials: awsCredentialProvider,
106+
})
115107
} else {
116-
// Use the SDK client builder for default credentials
117-
this.glueClient = (await globals.sdkClientBuilder.createAwsService(
118-
Service,
119-
{
120-
apiConfig: apiConfig,
121-
region: this.region,
122-
} as ServiceConfigurationOptions,
123-
undefined,
124-
false
125-
)) as GlueCatalogApi
108+
// Use default credentials
109+
this.glueClient = new GlueCatalog({
110+
region: this.region,
111+
})
126112
}
127113

128114
this.logger.debug('GlueCatalogClient: Successfully created Glue client')

0 commit comments

Comments
 (0)