Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update AWS SDK to V3 #15215

Merged
merged 21 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
525e249
First pass at migrating to AWS SDK v3.
mike12345567 Dec 12, 2024
544efae
Finishing off async code changes from pre-signing changes.
mike12345567 Dec 12, 2024
f410520
Merge branch 'master' of github.com:Budibase/budibase into chore/aws-…
mike12345567 Dec 18, 2024
979d63c
Merge branch 'master' of github.com:Budibase/budibase into chore/aws-…
mike12345567 Dec 19, 2024
49dca3b
Some fixes for failing test cases.
mike12345567 Dec 19, 2024
0f65963
Fixing mocked test case.
mike12345567 Dec 19, 2024
bb53611
Fixing more test that rely on mocks.
mike12345567 Dec 19, 2024
cd2286e
removing some extra .promise calls.
mike12345567 Dec 19, 2024
5b4f71c
Fixing mocks in backend-core.
mike12345567 Dec 19, 2024
6e6c3c7
Fixing another test depending on mock behaviour.
mike12345567 Dec 19, 2024
f9e144f
Updating mocks.
mike12345567 Dec 19, 2024
bb4698f
Merge branch 'master' into chore/aws-v2-to-v3
mike12345567 Dec 19, 2024
8720991
Merge branch 'master' into chore/aws-v2-to-v3
mike12345567 Dec 20, 2024
4fe4939
Merge branch 'master' into chore/aws-v2-to-v3
mike12345567 Jan 6, 2025
b5003e1
Merge branch 'master' into chore/aws-v2-to-v3
mike12345567 Jan 6, 2025
80a77d2
PR comment fixes.
mike12345567 Jan 6, 2025
40a2f29
Merge branch 'master' into chore/aws-v2-to-v3
mike12345567 Jan 6, 2025
766d095
Adding dependency.
mike12345567 Jan 6, 2025
28c6187
Merge branch 'chore/aws-v2-to-v3' of github.com:Budibase/budibase int…
mike12345567 Jan 6, 2025
05a44ca
Merge branch 'master' into chore/aws-v2-to-v3
mike12345567 Jan 7, 2025
c27f7da
Merge branch 'master' into chore/aws-v2-to-v3
mike12345567 Jan 7, 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
28 changes: 28 additions & 0 deletions packages/backend-core/__mocks__/@aws-sdk/client-s3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export class S3 {
headBucket() {
return jest.fn().mockReturnThis()
}
deleteObject() {
return jest.fn().mockReturnThis()
}
deleteObjects() {
return jest.fn().mockReturnThis()
}
createBucket() {
return jest.fn().mockReturnThis()
}
getObject() {
return jest.fn().mockReturnThis()
}
listObject() {
return jest.fn().mockReturnThis()
}
promise() {
return jest.fn().mockReturnThis()
}
catch() {
return jest.fn()
}
}

export const GetObjectCommand = jest.fn(inputs => ({ inputs }))
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const getSignedUrl = jest.fn((_, cmd) => {
const { inputs } = cmd
return `http://s3.example.com/${inputs?.Bucket}/${inputs?.Key}`
})
19 changes: 0 additions & 19 deletions packages/backend-core/__mocks__/aws-sdk.ts

This file was deleted.

6 changes: 5 additions & 1 deletion packages/backend-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
"test:watch": "jest --watchAll"
},
"dependencies": {
"@aws-sdk/client-s3": "3.709.0",
"@aws-sdk/lib-storage": "3.709.0",
"@aws-sdk/s3-request-presigner": "3.709.0",
"@budibase/nano": "10.1.5",
"@budibase/pouchdb-replication-stream": "1.2.11",
"@budibase/shared-core": "*",
Expand Down Expand Up @@ -71,19 +74,20 @@
"devDependencies": {
"@jest/types": "^29.6.3",
"@shopify/jest-koa-mocks": "5.1.1",
"@smithy/types": "4.0.0",
"@swc/core": "1.3.71",
"@swc/jest": "0.2.27",
"@types/chance": "1.1.3",
"@types/cookies": "0.7.8",
"@types/jest": "29.5.5",
"@types/koa": "2.13.4",
"@types/lodash": "4.14.200",
"@types/node-fetch": "2.6.4",
"@types/pouchdb": "6.4.2",
"@types/redlock": "4.0.7",
"@types/semver": "7.3.7",
"@types/tar-fs": "2.0.1",
"@types/uuid": "8.3.4",
"@types/koa": "2.13.4",
"chance": "1.1.8",
"ioredis-mock": "8.9.0",
"jest": "29.7.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/backend-core/src/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ const environment = {
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN,
AWS_REGION: process.env.AWS_REGION,
AWS_REGION: process.env.AWS_REGION || "eu-west-1",
MINIO_URL: process.env.MINIO_URL,
MINIO_ENABLED: process.env.MINIO_ENABLED || 1,
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
Expand Down
8 changes: 4 additions & 4 deletions packages/backend-core/src/objectStore/buckets/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function clientLibraryPath(appId: string) {
* due to issues with the domain we were unable to continue doing this - keeping
* incase we are able to switch back to CDN path again in future.
*/
export function clientLibraryCDNUrl(appId: string, version: string) {
export async function clientLibraryCDNUrl(appId: string, version: string) {
let file = clientLibraryPath(appId)
if (env.CLOUDFRONT_CDN) {
// append app version to bust the cache
Expand All @@ -24,7 +24,7 @@ export function clientLibraryCDNUrl(appId: string, version: string) {
// file is public
return cloudfront.getUrl(file)
} else {
return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, file)
return await objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, file)
}
}

Expand All @@ -44,10 +44,10 @@ export function clientLibraryUrl(appId: string, version: string) {
return `/api/assets/client?${qs.encode(qsParams)}`
}

export function getAppFileUrl(s3Key: string) {
export async function getAppFileUrl(s3Key: string) {
if (env.CLOUDFRONT_CDN) {
return cloudfront.getPresignedUrl(s3Key)
} else {
return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, s3Key)
return await objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, s3Key)
}
}
8 changes: 6 additions & 2 deletions packages/backend-core/src/objectStore/buckets/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ import * as cloudfront from "../cloudfront"

// URLs

export const getGlobalFileUrl = (type: string, name: string, etag?: string) => {
export const getGlobalFileUrl = async (
type: string,
name: string,
etag?: string
) => {
let file = getGlobalFileS3Key(type, name)
if (env.CLOUDFRONT_CDN) {
if (etag) {
file = `${file}?etag=${etag}`
}
return cloudfront.getPresignedUrl(file)
} else {
return objectStore.getPresignedUrl(env.GLOBAL_BUCKET_NAME, file)
return await objectStore.getPresignedUrl(env.GLOBAL_BUCKET_NAME, file)
}
}

Expand Down
22 changes: 12 additions & 10 deletions packages/backend-core/src/objectStore/buckets/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,37 @@ import { Plugin } from "@budibase/types"

// URLS

export function enrichPluginURLs(plugins?: Plugin[]): Plugin[] {
export async function enrichPluginURLs(plugins?: Plugin[]): Promise<Plugin[]> {
if (!plugins || !plugins.length) {
return []
}
return plugins.map(plugin => {
const jsUrl = getPluginJSUrl(plugin)
const iconUrl = getPluginIconUrl(plugin)
return { ...plugin, jsUrl, iconUrl }
})
return await Promise.all(
plugins.map(async plugin => {
const jsUrl = await getPluginJSUrl(plugin)
const iconUrl = await getPluginIconUrl(plugin)
return { ...plugin, jsUrl, iconUrl }
})
)
}

function getPluginJSUrl(plugin: Plugin) {
async function getPluginJSUrl(plugin: Plugin) {
const s3Key = getPluginJSKey(plugin)
return getPluginUrl(s3Key)
}

function getPluginIconUrl(plugin: Plugin): string | undefined {
async function getPluginIconUrl(plugin: Plugin) {
const s3Key = getPluginIconKey(plugin)
if (!s3Key) {
return
}
return getPluginUrl(s3Key)
}

function getPluginUrl(s3Key: string) {
async function getPluginUrl(s3Key: string) {
if (env.CLOUDFRONT_CDN) {
return cloudfront.getPresignedUrl(s3Key)
} else {
return objectStore.getPresignedUrl(env.PLUGIN_BUCKET_NAME, s3Key)
return await objectStore.getPresignedUrl(env.PLUGIN_BUCKET_NAME, s3Key)
}
}

Expand Down
24 changes: 12 additions & 12 deletions packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,25 @@ describe("app", () => {
testEnv.multiTenant()
})

it("gets url with embedded minio", () => {
it("gets url with embedded minio", async () => {
testEnv.withMinio()
const url = getAppFileUrl()
const url = await getAppFileUrl()
expect(url).toBe(
"/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg"
)
})

it("gets url with custom S3", () => {
it("gets url with custom S3", async () => {
testEnv.withS3()
const url = getAppFileUrl()
const url = await getAppFileUrl()
expect(url).toBe(
"http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg"
)
})

it("gets url with cloudfront + s3", () => {
it("gets url with cloudfront + s3", async () => {
testEnv.withCloudfront()
const url = getAppFileUrl()
const url = await getAppFileUrl()
// omit rest of signed params
expect(
url.includes("http://cf.example.com/app_123/attachments/image.jpeg?")
Expand All @@ -126,8 +126,8 @@ describe("app", () => {

it("gets url with embedded minio", async () => {
testEnv.withMinio()
await testEnv.withTenant(() => {
const url = getAppFileUrl()
await testEnv.withTenant(async () => {
const url = await getAppFileUrl()
expect(url).toBe(
"/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg"
)
Expand All @@ -136,8 +136,8 @@ describe("app", () => {

it("gets url with custom S3", async () => {
testEnv.withS3()
await testEnv.withTenant(() => {
const url = getAppFileUrl()
await testEnv.withTenant(async () => {
const url = await getAppFileUrl()
expect(url).toBe(
"http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg"
)
Expand All @@ -146,8 +146,8 @@ describe("app", () => {

it("gets url with cloudfront + s3", async () => {
testEnv.withCloudfront()
await testEnv.withTenant(() => {
const url = getAppFileUrl()
await testEnv.withTenant(async () => {
const url = await getAppFileUrl()
// omit rest of signed params
expect(
url.includes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { testEnv } from "../../../../tests/extra"

describe("global", () => {
describe("getGlobalFileUrl", () => {
function getGlobalFileUrl() {
async function getGlobalFileUrl() {
return global.getGlobalFileUrl("settings", "logoUrl", "etag")
}

Expand All @@ -12,21 +12,21 @@ describe("global", () => {
testEnv.singleTenant()
})

it("gets url with embedded minio", () => {
it("gets url with embedded minio", async () => {
testEnv.withMinio()
const url = getGlobalFileUrl()
const url = await getGlobalFileUrl()
expect(url).toBe("/files/signed/global/settings/logoUrl")
})

it("gets url with custom S3", () => {
it("gets url with custom S3", async () => {
testEnv.withS3()
const url = getGlobalFileUrl()
const url = await getGlobalFileUrl()
expect(url).toBe("http://s3.example.com/global/settings/logoUrl")
})

it("gets url with cloudfront + s3", () => {
it("gets url with cloudfront + s3", async () => {
testEnv.withCloudfront()
const url = getGlobalFileUrl()
const url = await getGlobalFileUrl()
// omit rest of signed params
expect(
url.includes("http://cf.example.com/settings/logoUrl?etag=etag&")
Expand All @@ -41,16 +41,16 @@ describe("global", () => {

it("gets url with embedded minio", async () => {
testEnv.withMinio()
await testEnv.withTenant(tenantId => {
const url = getGlobalFileUrl()
await testEnv.withTenant(async tenantId => {
const url = await getGlobalFileUrl()
expect(url).toBe(`/files/signed/global/${tenantId}/settings/logoUrl`)
})
})

it("gets url with custom S3", async () => {
testEnv.withS3()
await testEnv.withTenant(tenantId => {
const url = getGlobalFileUrl()
await testEnv.withTenant(async tenantId => {
const url = await getGlobalFileUrl()
expect(url).toBe(
`http://s3.example.com/global/${tenantId}/settings/logoUrl`
)
Expand All @@ -59,8 +59,8 @@ describe("global", () => {

it("gets url with cloudfront + s3", async () => {
testEnv.withCloudfront()
await testEnv.withTenant(tenantId => {
const url = getGlobalFileUrl()
await testEnv.withTenant(async tenantId => {
const url = await getGlobalFileUrl()
// omit rest of signed params
expect(
url.includes(
Expand Down
Loading
Loading