Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
40ff608
deps: install s3 v3
Hweinstock Mar 4, 2025
4ee7bba
refactor: rename file
Hweinstock Mar 4, 2025
8bd3452
refactor: rename client
Hweinstock Mar 4, 2025
44ad85c
refactor: migrate create and delete operations
Hweinstock Mar 4, 2025
1dbaab4
refactor: migrate createFolder
Hweinstock Mar 4, 2025
9b7b51d
Merge branch 'feature/sdkv3' into sdkv3/s3-v2
Hweinstock Mar 4, 2025
49ddc84
Merge master into feature/sdkv3
aws-toolkit-automation Mar 5, 2025
bf820e4
refactor: migrate downloading logic
Hweinstock Mar 5, 2025
1814a28
Merge master into feature/sdkv3
aws-toolkit-automation Mar 5, 2025
8947a9f
test: split up `listFiles` to be testable w/o stubs
Hweinstock Mar 5, 2025
e4e47a0
refactor: migrate request pre-signing
Hweinstock Mar 5, 2025
596f395
Merge master into feature/sdkv3
aws-toolkit-automation Mar 5, 2025
9f614b0
Merge master into feature/sdkv3
aws-toolkit-automation Mar 5, 2025
2b84748
Merge master into feature/sdkv3
aws-toolkit-automation Mar 5, 2025
8d9728f
refactor: migrate upload
Hweinstock Mar 5, 2025
aeff13b
merge: resolve package.json conflicts
Hweinstock Mar 5, 2025
c75da65
fix: duplicate code elimination
Hweinstock Mar 5, 2025
50645a7
Merge master into feature/sdkv3
aws-toolkit-automation Mar 5, 2025
0029d88
refactor: migrate listBuckets
Hweinstock Mar 5, 2025
86c032b
refactor: migrate listObjectVersions
Hweinstock Mar 5, 2025
698d7d0
refactor: migrate deleteObjects
Hweinstock Mar 5, 2025
92cb145
refactor: migrate final function to sdkv3
Hweinstock Mar 5, 2025
0d67f83
refactor: remove s3 import
Hweinstock Mar 5, 2025
f315823
fix: avoid unnecessary override
Hweinstock Mar 6, 2025
15e421c
refactor: clean up list buckets
Hweinstock Mar 6, 2025
4cce8d8
test: renable slow tests
Hweinstock Mar 6, 2025
aba5447
refactor: unify bucket types
Hweinstock Mar 6, 2025
d976e6c
Merge branch 'feature/sdkv3' into sdkv3/s3-v2
Hweinstock Mar 6, 2025
3c2fec8
fix: list buckets attached wrong region
Hweinstock Mar 6, 2025
004bd3c
refactor: remove remaining s3 imports
Hweinstock Mar 6, 2025
b1a1f07
Merge master into feature/sdkv3
aws-toolkit-automation Mar 6, 2025
1f061a0
Merge master into feature/sdkv3
aws-toolkit-automation Mar 6, 2025
236c4cd
Merge master into feature/sdkv3
aws-toolkit-automation Mar 6, 2025
e057ec4
Merge master into feature/sdkv3
aws-toolkit-automation Mar 6, 2025
4908c40
Merge branch 'feature/sdkv3' into sdkv3/s3-v2
Hweinstock Mar 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,252 changes: 1,138 additions & 114 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@
"@aws-sdk/client-docdb-elastic": "<3.696.0",
"@aws-sdk/client-ec2": "<3.696.0",
"@aws-sdk/client-iam": "<3.696.0",
"@aws-sdk/client-s3": "<3.696.0",
"@aws-sdk/lib-storage": "<3.696.0",
"@aws-sdk/client-lambda": "<3.696.0",
"@aws-sdk/client-ssm": "<3.696.0",
"@aws-sdk/client-sso": "<3.696.0",
Expand All @@ -514,6 +516,7 @@
"@aws-sdk/protocol-http": "<3.696.0",
"@aws-sdk/smithy-client": "<3.696.0",
"@aws-sdk/util-arn-parser": "<3.696.0",
"@aws-sdk/s3-request-presigner": "<3.696.0",
"@aws/mynah-ui": "^4.23.1",
"@gerhobbelt/gitignore-parser": "^0.2.0-9",
"@iarna/toml": "^2.2.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
PolicyChecksUiClick,
ValidatePolicyFindingType,
} from './constants'
import { DefaultS3Client, parseS3Uri } from '../../../shared/clients/s3Client'
import { S3Client, parseS3Uri } from '../../../shared/clients/s3'
import { ExpiredTokenException } from '@aws-sdk/client-sso-oidc'
import { ChildProcess } from '../../../shared/utilities/processUtils'

Expand Down Expand Up @@ -842,7 +842,7 @@ export async function _readCustomChecksFile(input: string): Promise<string> {
} else {
try {
const [region, bucket, key] = parseS3Uri(input)
const s3Client = new DefaultS3Client(region)
const s3Client = new S3Client(region)
const resp = await s3Client.getObject({ bucketName: bucket, key })
// Lint warning: this may evaluate to '[object Object]'. @typescript-eslint/no-base-to-string
// eslint-disable-next-line @typescript-eslint/no-base-to-string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { defaultPartition } from '../../../../shared/regions/regionProvider'
import { Lambda, APIGateway } from 'aws-sdk'
import { LambdaNode } from '../../../../lambda/explorer/lambdaNodes'
import { LambdaFunctionNode } from '../../../../lambda/explorer/lambdaFunctionNode'
import { DefaultS3Client, DefaultBucket } from '../../../../shared/clients/s3Client'
import { S3Client, toBucket } from '../../../../shared/clients/s3'
import { S3Node } from '../../../../awsService/s3/explorer/s3Nodes'
import { S3BucketNode } from '../../../../awsService/s3/explorer/s3BucketNode'
import { ApiGatewayNode } from '../../../../awsService/apigateway/explorer/apiGatewayNodes'
Expand Down Expand Up @@ -100,13 +100,9 @@ export async function generateDeployedNode(
break
}
case s3BucketType: {
const s3Client = new DefaultS3Client(regionCode)
const s3Client = new S3Client(regionCode)
const s3Node = new S3Node(s3Client)
const s3Bucket = new DefaultBucket({
partitionId: partitionId,
region: regionCode,
name: deployedResource.PhysicalResourceId,
})
const s3Bucket = toBucket(deployedResource.PhysicalResourceId, regionCode, partitionId)
newDeployedResource = new S3BucketNode(s3Bucket, s3Node, s3Client)
break
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/awsService/s3/activation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { VirtualFileSystem } from '../../shared/virtualFilesystem'
import { Commands } from '../../shared/vscode/commands2'

import * as nls from 'vscode-nls'
import { DefaultS3Client } from '../../shared/clients/s3Client'
import { S3Client } from '../../shared/clients/s3'
import { TreeNode } from '../../shared/treeview/resourceTreeDataProvider'
import { getSourceNode } from '../../shared/utilities/treeNodeUtils'
const localize = nls.loadMessageBundle()
Expand All @@ -37,7 +37,7 @@ export async function activate(ctx: ExtContext): Promise<void> {
const fs = new VirtualFileSystem(
localize('AWS.s3.fileViewer.genericError', 'Unable to open S3 file, try reopening from the explorer')
)
const manager = new S3FileViewerManager((region) => new DefaultS3Client(region), fs)
const manager = new S3FileViewerManager((region) => new S3Client(region), fs)

ctx.extensionContext.subscriptions.push(manager)
ctx.extensionContext.subscriptions.push(
Expand All @@ -64,7 +64,7 @@ export async function activate(ctx: ExtContext): Promise<void> {
if (!node) {
const awsContext = ctx.awsContext
const regionCode = awsContext.getCredentialDefaultRegion()
const s3Client = new DefaultS3Client(regionCode)
const s3Client = new S3Client(regionCode)
const document = vscode.window.activeTextEditor?.document.uri
await uploadFileCommand(s3Client, document)
} else {
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/awsService/s3/commands/createFolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import * as vscode from 'vscode'
import { DEFAULT_DELIMITER } from '../../../shared/clients/s3Client'
import { DEFAULT_DELIMITER } from '../../../shared/clients/s3'
import { getLogger } from '../../../shared/logger/logger'
import { S3BucketNode } from '../explorer/s3BucketNode'
import { S3FolderNode } from '../explorer/s3FolderNode'
Expand Down Expand Up @@ -40,10 +40,10 @@ export async function createFolderCommand(node: S3BucketNode | S3FolderNode): Pr
}

const path = node.path + folderName + DEFAULT_DELIMITER
getLogger().info(`Creating folder "${path}" in bucket '${node.bucket.name}'`)
getLogger().info(`Creating folder "${path}" in bucket '${node.bucket.Name}'`)

const { folder } = await node
.createFolder({ path, bucketName: node.bucket.name })
.createFolder({ path, bucketName: node.bucket.Name })
.catch((e) => {
const message = localize(
'AWS.s3.createFolder.error.general',
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/awsService/s3/commands/deleteBucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,23 @@ export async function deleteBucketCommand(node: S3BucketNode): Promise<void> {
getLogger().debug('DeleteBucket called for %O', node)

await telemetry.s3_deleteBucket.run(async () => {
const isConfirmed = await showConfirmationDialog(node.bucket.name)
const isConfirmed = await showConfirmationDialog(node.bucket.Name)
if (!isConfirmed) {
throw new CancellationError('user')
}

getLogger().info(`Deleting bucket: ${node.bucket.name}`)
getLogger().info(`Deleting bucket: ${node.bucket.Name}`)
await deleteWithProgress(node)
.catch((e) => {
const message = localize(
'AWS.s3.deleteBucket.error.general',
'Failed to delete bucket {0}',
node.bucket.name
node.bucket.Name
)
throw ToolkitError.chain(e, message)
})
.finally(() => refreshNode(node.parent))
getLogger().info(`deleted bucket: ${node.bucket.name}`)
getLogger().info(`deleted bucket: ${node.bucket.Name}`)
})
}

Expand All @@ -65,7 +65,7 @@ async function deleteWithProgress(node: S3BucketNode): Promise<void> {
return vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: localize('AWS.s3.deleteBucket.progressTitle', 'Deleting {0}...', node.bucket.name),
title: localize('AWS.s3.deleteBucket.progressTitle', 'Deleting {0}...', node.bucket.Name),
},
() => {
return node.deleteBucket()
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/awsService/s3/commands/downloadFileAs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { readablePath } from '../util'
import { progressReporter } from '../progressReporter'
import { localize } from '../../../shared/utilities/vsCodeUtils'
import { showOutputMessage } from '../../../shared/utilities/messages'
import { DefaultS3Client, S3Client } from '../../../shared/clients/s3Client'
import { S3Client } from '../../../shared/clients/s3'
import { Timeout, CancellationError } from '../../../shared/utilities/timeoutUtils'
import { ToolkitError } from '../../../shared/errors'
import { streamToBuffer, streamToFile } from '../../../shared/utilities/streamUtilities'
Expand Down Expand Up @@ -55,7 +55,7 @@ async function downloadS3File(
file: S3File,
options?: FileOptions | BufferOptions
): Promise<Buffer | void> {
const downloadStream = await client.downloadFileStream(file.bucket.name, file.key)
const downloadStream = await client.downloadFileStream(file.bucket.Name, file.key)
const result = options?.saveLocation
? streamToFile(downloadStream, options.saveLocation)
: streamToBuffer(downloadStream, file.sizeBytes)
Expand Down Expand Up @@ -86,7 +86,7 @@ async function downloadS3File(
export async function downloadFile(file: S3File, options: FileOptions): Promise<void>
export async function downloadFile(file: S3File, options?: BufferOptions): Promise<Buffer>
export async function downloadFile(file: S3File, options?: FileOptions | BufferOptions): Promise<Buffer | void> {
const client = options?.client ?? new DefaultS3Client(file.bucket.region)
const client = options?.client ?? new S3Client(file.bucket.BucketRegion)

return downloadS3File(client, file, options).catch((err) => {
const message = localize('AWS.s3.downloadFile.error.general', 'Failed to download file {0}', file.name)
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/awsService/s3/commands/presignedURL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { SignedUrlRequest } from '../../../shared/clients/s3Client'
import { SignedUrlRequest } from '../../../shared/clients/s3'
import { copyToClipboard } from '../../../shared/utilities/messages'
import { S3FileNode } from '../explorer/s3FileNode'
import * as vscode from 'vscode'
Expand All @@ -19,13 +19,12 @@ export async function presignedURLCommand(node: S3FileNode): Promise<void> {
const validTime = await promptTime(node.file.key)
const s3Client = node.s3
const request: SignedUrlRequest = {
bucketName: node.bucket.name,
bucketName: node.bucket.Name,
key: node.file.key,
time: validTime * 60,
operation: 'getObject',
}

const url = await s3Client.getSignedUrl(request).catch((e) => {
const url = await s3Client.getSignedUrlForObject(request).catch((e) => {
throw ToolkitError.chain(
e,
'Error creating the presigned URL. Make sure you have access to the requested file.'
Expand Down
30 changes: 15 additions & 15 deletions packages/core/src/awsService/s3/commands/uploadFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import * as path from 'path'
import * as mime from 'mime-types'
import * as vscode from 'vscode'
import { statSync } from 'fs' // eslint-disable-line no-restricted-imports
import { S3 } from 'aws-sdk'
import { getLogger } from '../../../shared/logger/logger'
import { S3Node } from '../explorer/s3Nodes'
import { readablePath } from '../util'
import { localize } from '../../../shared/utilities/vsCodeUtils'
import { showOutputMessage } from '../../../shared/utilities/messages'
import { createQuickPick, promptUser, verifySinglePickerOutput } from '../../../shared/ui/picker'
import { addCodiconToString } from '../../../shared/utilities/textUtilities'
import { Bucket, Folder, S3Client } from '../../../shared/clients/s3Client'
import { S3Bucket, Folder, S3Client } from '../../../shared/clients/s3'
import { createBucketCommand } from './createBucket'
import { S3BucketNode } from '../explorer/s3BucketNode'
import { S3FolderNode } from '../explorer/s3FolderNode'
Expand All @@ -24,6 +23,7 @@ import { CancellationError } from '../../../shared/utilities/timeoutUtils'
import { progressReporter } from '../progressReporter'
import globals from '../../../shared/extensionGlobals'
import { telemetry } from '../../../shared/telemetry/telemetry'
import { Upload } from '@aws-sdk/lib-storage'

export interface FileSizeBytes {
/**
Expand All @@ -38,7 +38,7 @@ interface UploadRequest {
fileLocation: vscode.Uri
fileSizeBytes: number
s3Client: S3Client
ongoingUpload?: S3.ManagedUpload
ongoingUpload?: Upload
}

/**
Expand Down Expand Up @@ -97,7 +97,7 @@ export async function uploadFileCommand(
uploadRequests.push(
...filesToUpload.map((file) => {
const key = node!.path + path.basename(file.fsPath)
return fileToUploadRequest(node!.bucket.name, key, file)
return fileToUploadRequest(node!.bucket.Name, key, file)
})
)
if (node instanceof S3FolderNode) {
Expand Down Expand Up @@ -281,15 +281,15 @@ async function uploadBatchOfFiles(

token.onCancellationRequested((e) => {
if (uploadRequests[requestIdx].ongoingUpload) {
uploadRequests[requestIdx].ongoingUpload?.abort()
void uploadRequests[requestIdx].ongoingUpload?.abort()
}
return failedRequests
})

while (!token.isCancellationRequested && requestIdx < uploadRequests.length) {
const request = uploadRequests[requestIdx]
const fileName = path.basename(request.key)
const destinationPath = readablePath({ bucket: { name: request.bucketName }, path: request.key })
const destinationPath = readablePath({ bucket: { Name: request.bucketName }, path: request.key })
showOutputMessage(
localize('AWS.s3.uploadFile.startUpload', 'Uploading file {0} to {1}', fileName, destinationPath),
outputChannel
Expand Down Expand Up @@ -377,23 +377,23 @@ async function uploadWithProgress(

const cancelled = new Promise<void>((_, reject) => {
token.onCancellationRequested((e) => {
currentStream.abort()
void currentStream.abort()
reject(new CancellationError('user'))
})
})

await Promise.race([currentStream.promise(), cancelled])
await Promise.race([currentStream.done(), cancelled])

return (request.ongoingUpload = undefined)
}

export interface BucketQuickPickItem extends vscode.QuickPickItem {
bucket: S3.Bucket | undefined
bucket: (Partial<S3Bucket> & { Name: string }) | undefined
folder?: Folder | undefined
}

interface SavedFolder {
bucket: Bucket
bucket: S3Bucket
folder: Folder
}

Expand All @@ -411,9 +411,9 @@ export async function promptUserForBucket(
promptUserFunction = promptUser,
createBucket = createBucketCommand
): Promise<BucketQuickPickItem | 'cancel' | 'back'> {
let allBuckets: S3.Bucket[]
let allBuckets: S3Bucket[]
try {
allBuckets = await s3client.listAllBuckets()
allBuckets = (await s3client.listBuckets()).buckets
} catch (e) {
getLogger().error('Failed to list buckets from client %O', e)
void vscode.window.showErrorMessage(
Expand All @@ -424,7 +424,7 @@ export async function promptUserForBucket(

const s3Buckets = allBuckets.filter((bucket) => {
return bucket && bucket.Name
}) as S3.Bucket[]
})

const createNewBucket: BucketQuickPickItem = {
label: localize('AWS.command.s3.createBucket', 'Create new bucket'),
Expand All @@ -443,7 +443,7 @@ export async function promptUserForBucket(
lastFolderItem = {
label: lastTouchedFolder.folder.name,
description: '(last opened S3 folder)',
bucket: { Name: lastTouchedFolder.bucket.name },
bucket: { Name: lastTouchedFolder.bucket.Name },
folder: lastTouchedFolder.folder,
}
}
Expand All @@ -454,7 +454,7 @@ export async function promptUserForBucket(
lastUploadedFolderItem = {
label: lastUploadedToFolder.folder.name,
description: '(last uploaded-to S3 folder)',
bucket: { Name: lastUploadedToFolder.bucket.name },
bucket: { Name: lastUploadedToFolder.bucket.Name },
folder: lastUploadedToFolder.folder,
}
}
Expand Down
18 changes: 9 additions & 9 deletions packages/core/src/awsService/s3/explorer/s3BucketNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as vscode from 'vscode'
import { ChildNodePage } from '../../../awsexplorer/childNodeLoader'
import { Bucket, CreateFolderRequest, CreateFolderResponse, S3Client } from '../../../shared/clients/s3Client'
import { S3Bucket, CreateFolderRequest, CreateFolderResponse, S3Client } from '../../../shared/clients/s3'

import { AWSResourceNode } from '../../../shared/treeview/nodes/awsResourceNode'
import { AWSTreeNodeBase } from '../../../shared/treeview/nodes/awsTreeNodeBase'
Expand All @@ -30,13 +30,13 @@ export class S3BucketNode extends AWSTreeNodeBase implements AWSResourceNode, Lo
private readonly childLoader = new ChildNodeLoader(this, (token) => this.loadPage(token))

public constructor(
public readonly bucket: Bucket,
public readonly bucket: S3Bucket,
public readonly parent: S3Node,
public readonly s3: S3Client,
protected readonly settings: ClassToInterfaceType<Settings> = Settings.instance
) {
super(bucket.name, vscode.TreeItemCollapsibleState.Collapsed)
this.tooltip = bucket.name
super(bucket.Name, vscode.TreeItemCollapsibleState.Collapsed)
this.tooltip = bucket.Name
this.iconPath = getIcon('aws-s3-bucket')
this.contextValue = 'awsS3BucketNode'
}
Expand Down Expand Up @@ -64,7 +64,7 @@ export class S3BucketNode extends AWSTreeNodeBase implements AWSResourceNode, Lo
private async loadPage(continuationToken: string | undefined): Promise<ChildNodePage<S3FolderNode | S3FileNode>> {
getLogger().debug(`Loading page for %O using continuationToken %s`, this, continuationToken)
const response = await this.s3.listFiles({
bucketName: this.bucket.name,
bucketName: this.bucket.Name,
continuationToken,
maxResults: this.getMaxItemsPerPage(),
})
Expand All @@ -90,15 +90,15 @@ export class S3BucketNode extends AWSTreeNodeBase implements AWSResourceNode, Lo
* See {@link S3Client.deleteBucket}.
*/
public async deleteBucket(): Promise<void> {
await this.s3.deleteBucket({ bucketName: this.bucket.name })
await this.s3.deleteBucket({ bucketName: this.bucket.Name })
}

public get arn(): string {
return this.bucket.arn
return this.bucket.Arn
}

public get name(): string {
return this.bucket.name
return this.bucket.Name
}

public get path(): string {
Expand All @@ -107,7 +107,7 @@ export class S3BucketNode extends AWSTreeNodeBase implements AWSResourceNode, Lo
}

public [inspect.custom](): string {
return `S3BucketNode (bucket=${this.bucket.name})`
return `S3BucketNode (bucket=${this.bucket.Name})`
}

private getMaxItemsPerPage(): number | undefined {
Expand Down
Loading
Loading