This commit is contained in:
Sam Rose 2025-03-03 17:10:20 +00:00
parent ab8ec8f09d
commit b0c1d7ee6d
No known key found for this signature in database
6 changed files with 179 additions and 151 deletions

View File

@ -4,3 +4,4 @@ POSTGRES_SHA=sha256:bd0d8e485d1aca439d39e5ea99b931160bd28d862e74c786f7508e9d0053
MONGODB_SHA=sha256:afa36bca12295b5f9dae68a493c706113922bdab520e901bd5d6c9d7247a1d8d MONGODB_SHA=sha256:afa36bca12295b5f9dae68a493c706113922bdab520e901bd5d6c9d7247a1d8d
MARIADB_SHA=sha256:e59ba8783bf7bc02a4779f103bb0d8751ac0e10f9471089709608377eded7aa8 MARIADB_SHA=sha256:e59ba8783bf7bc02a4779f103bb0d8751ac0e10f9471089709608377eded7aa8
ELASTICSEARCH_SHA=sha256:9a6443f55243f6acbfeb4a112d15eb3b9aac74bf25e0e39fa19b3ddd3a6879d0 ELASTICSEARCH_SHA=sha256:9a6443f55243f6acbfeb4a112d15eb3b9aac74bf25e0e39fa19b3ddd3a6879d0
DYNAMODB_SHA=sha256:cf8cebd061f988628c02daff10fdb950a54478feff9c52f6ddf84710fe3c3906

View File

@ -17,7 +17,7 @@ import {
import { DynamoDB } from "@aws-sdk/client-dynamodb" import { DynamoDB } from "@aws-sdk/client-dynamodb"
import { AWS_REGION } from "../constants" import { AWS_REGION } from "../constants"
interface DynamoDBConfig { export interface DynamoDBConfig {
region: string region: string
accessKeyId: string accessKeyId: string
secretAccessKey: string secretAccessKey: string
@ -138,9 +138,9 @@ const SCHEMA: Integration = {
}, },
} }
class DynamoDBIntegration implements IntegrationBase { export class DynamoDBIntegration implements IntegrationBase {
private config: DynamoDBConfig private config: DynamoDBConfig
private client private client: DynamoDBDocument
constructor(config: DynamoDBConfig) { constructor(config: DynamoDBConfig) {
this.config = config this.config = config

View File

@ -1,55 +1,36 @@
jest.mock("@aws-sdk/lib-dynamodb", () => ({ import { Datasource } from "@budibase/types"
DynamoDBDocument: { import { DynamoDBConfig, DynamoDBIntegration } from "../dynamodb"
from: jest.fn(() => ({ import { DatabaseName, datasourceDescribe } from "./utils"
update: jest.fn(),
put: jest.fn(),
query: jest.fn(() => ({
Items: [],
})),
scan: jest.fn(() => ({
Items: [],
})),
delete: jest.fn(),
get: jest.fn(),
})),
},
}))
jest.mock("@aws-sdk/client-dynamodb")
import { default as DynamoDBIntegration } from "../dynamodb"
class TestConfiguration { const describes = datasourceDescribe({ only: [DatabaseName.DYNAMODB] })
integration: any
constructor(config: any = {}) { if (describes.length > 0) {
this.integration = new DynamoDBIntegration.integration(config) describe.each(describes)("DynamoDB Integration", ({ dsProvider }) => {
}
}
describe("DynamoDB Integration", () => {
let config: any
let tableName = "Users" let tableName = "Users"
let rawDatasource: Datasource
let dynamodb: DynamoDBIntegration
beforeEach(() => { beforeEach(async () => {
config = new TestConfiguration() const ds = await dsProvider()
rawDatasource = ds.rawDatasource!
dynamodb = new DynamoDBIntegration(
rawDatasource.config! as DynamoDBConfig
)
}) })
it("calls the create method with the correct params", async () => { it.only("calls the create method with the correct params", async () => {
await config.integration.create({ await dynamodb.create({
table: tableName, table: tableName,
json: { json: {
Name: "John", Name: "John",
}, },
}) })
expect(config.integration.client.put).toHaveBeenCalledWith({
TableName: tableName,
Name: "John",
})
}) })
it("calls the read method with the correct params", async () => { it("calls the read method with the correct params", async () => {
const indexName = "Test" const indexName = "Test"
const response = await config.integration.read({ const response = await dynamodb.read({
table: tableName, table: tableName,
index: indexName, index: indexName,
json: {}, json: {},
@ -64,7 +45,7 @@ describe("DynamoDB Integration", () => {
it("calls the scan method with the correct params", async () => { it("calls the scan method with the correct params", async () => {
const indexName = "Test" const indexName = "Test"
const response = await config.integration.scan({ const response = await dynamodb.scan({
table: tableName, table: tableName,
index: indexName, index: indexName,
json: {}, json: {},
@ -77,7 +58,7 @@ describe("DynamoDB Integration", () => {
}) })
it("calls the get method with the correct params", async () => { it("calls the get method with the correct params", async () => {
await config.integration.get({ await dynamodb.get({
table: tableName, table: tableName,
json: { json: {
Id: 123, Id: 123,
@ -91,7 +72,7 @@ describe("DynamoDB Integration", () => {
}) })
it("calls the update method with the correct params", async () => { it("calls the update method with the correct params", async () => {
await config.integration.update({ await dynamodb.update({
table: tableName, table: tableName,
json: { json: {
Name: "John", Name: "John",
@ -104,7 +85,7 @@ describe("DynamoDB Integration", () => {
}) })
it("calls the delete method with the correct params", async () => { it("calls the delete method with the correct params", async () => {
await config.integration.delete({ await dynamodb.delete({
table: tableName, table: tableName,
json: { json: {
Name: "John", Name: "John",
@ -164,4 +145,5 @@ describe("DynamoDB Integration", () => {
...config, ...config,
}) })
}) })
}) })
}

View File

@ -0,0 +1,41 @@
import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait } from "testcontainers"
import { testContainerUtils } from "@budibase/backend-core/tests"
import { startContainer } from "."
import { DYNAMODB_IMAGE } from "./images"
import { DynamoDBConfig } from "../../dynamodb"
let ports: Promise<testContainerUtils.Port[]>
export async function getDatasource(): Promise<Datasource> {
if (!ports) {
ports = startContainer(
new GenericContainer(DYNAMODB_IMAGE)
.withExposedPorts(8000)
.withWaitStrategy(
Wait.forSuccessfulCommand(
// https://stackoverflow.com/a/77373799
`if [ "$(curl -s -o /dev/null -I -w ''%{http_code}'' http://localhost:8000)" == "400" ]; then exit 0; else exit 1; fi`
).withStartupTimeout(60000)
)
)
}
const port = (await ports).find(x => x.container === 8000)?.host
if (!port) {
throw new Error("DynamoDB port not found")
}
const config: DynamoDBConfig = {
accessKeyId: "test",
secretAccessKey: "test",
region: "us-east-1",
endpoint: `http://127.0.0.1:${port}`,
}
return {
type: "datasource",
source: SourceName.DYNAMODB,
config,
}
}

View File

@ -13,3 +13,4 @@ export const POSTGRES_LEGACY_IMAGE = `postgres:9.5.25`
export const MONGODB_IMAGE = `mongo@${process.env.MONGODB_SHA}` export const MONGODB_IMAGE = `mongo@${process.env.MONGODB_SHA}`
export const MARIADB_IMAGE = `mariadb@${process.env.MARIADB_SHA}` export const MARIADB_IMAGE = `mariadb@${process.env.MARIADB_SHA}`
export const ELASTICSEARCH_IMAGE = `elasticsearch@${process.env.ELASTICSEARCH_SHA}` export const ELASTICSEARCH_IMAGE = `elasticsearch@${process.env.ELASTICSEARCH_SHA}`
export const DYNAMODB_IMAGE = `amazon/dynamodb-local@${process.env.DYNAMODB_SHA}`

View File

@ -7,6 +7,7 @@ import * as mssql from "./mssql"
import * as mariadb from "./mariadb" import * as mariadb from "./mariadb"
import * as oracle from "./oracle" import * as oracle from "./oracle"
import * as elasticsearch from "./elasticsearch" import * as elasticsearch from "./elasticsearch"
import * as dynamodb from "./dynamodb"
import { testContainerUtils } from "@budibase/backend-core/tests" import { testContainerUtils } from "@budibase/backend-core/tests"
import { Knex } from "knex" import { Knex } from "knex"
import TestConfiguration from "../../../tests/utilities/TestConfiguration" import TestConfiguration from "../../../tests/utilities/TestConfiguration"
@ -25,6 +26,7 @@ export enum DatabaseName {
ORACLE = "oracle", ORACLE = "oracle",
SQS = "sqs", SQS = "sqs",
ELASTICSEARCH = "elasticsearch", ELASTICSEARCH = "elasticsearch",
DYNAMODB = "dynamodb",
} }
const DATASOURCE_PLUS = [ const DATASOURCE_PLUS = [
@ -50,6 +52,7 @@ const providers: Record<DatabaseName, DatasourceProvider> = {
// rest // rest
[DatabaseName.ELASTICSEARCH]: elasticsearch.getDatasource, [DatabaseName.ELASTICSEARCH]: elasticsearch.getDatasource,
[DatabaseName.MONGODB]: mongodb.getDatasource, [DatabaseName.MONGODB]: mongodb.getDatasource,
[DatabaseName.DYNAMODB]: dynamodb.getDatasource,
} }
export interface DatasourceDescribeReturnPromise { export interface DatasourceDescribeReturnPromise {