Changing tactic to relying on stable container names to prevent duplication.
This commit is contained in:
parent
6a54b58303
commit
85c59c0350
|
@ -9,6 +9,7 @@ import { testContainerUtils } from "@budibase/backend-core/tests"
|
||||||
import lockfile from "proper-lockfile"
|
import lockfile from "proper-lockfile"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
|
import _ from "lodash"
|
||||||
|
|
||||||
export type DatasourceProvider = () => Promise<Datasource>
|
export type DatasourceProvider = () => Promise<Datasource>
|
||||||
|
|
||||||
|
@ -68,28 +69,38 @@ export async function rawQuery(ds: Datasource, sql: string): Promise<any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startContainer(container: GenericContainer) {
|
export async function startContainer(container: GenericContainer) {
|
||||||
container = container.withReuse().withLabels({ "com.budibase": "true" })
|
|
||||||
|
|
||||||
// If two tests try to spin up the same container at the same time, there's a
|
|
||||||
// possibility that two containers of the same type will be started. To avoid
|
|
||||||
// this, we use a filesystem lock to ensure that only one container of a given
|
|
||||||
// type is started at a time.
|
|
||||||
const imageName = (container as any).imageName.string as string
|
const imageName = (container as any).imageName.string as string
|
||||||
const lockPath = path.resolve(
|
const key = imageName.replaceAll("/", "-").replaceAll(":", "-")
|
||||||
__dirname,
|
|
||||||
`${imageName.replaceAll("/", "-")}.lock`
|
|
||||||
)
|
|
||||||
|
|
||||||
const unlock = await lockfile.lock(lockPath, {
|
container = container
|
||||||
retries: 10,
|
.withReuse()
|
||||||
realpath: false,
|
.withLabels({ "com.budibase": "true" })
|
||||||
})
|
.withName(key)
|
||||||
|
|
||||||
let startedContainer: StartedTestContainer
|
let startedContainer: StartedTestContainer | undefined = undefined
|
||||||
|
let lastError = undefined
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
startedContainer = await container.start()
|
// container.start() is not an idempotent operation, calling `start`
|
||||||
} finally {
|
// modifies the internal state of a GenericContainer instance such that
|
||||||
await unlock()
|
// the hash it uses to determine reuse changes. We need to clone the
|
||||||
|
// container before calling start to ensure that we're using the same
|
||||||
|
// reuse hash every time.
|
||||||
|
const containerCopy = _.cloneDeep(container)
|
||||||
|
startedContainer = await containerCopy.start()
|
||||||
|
lastError = undefined
|
||||||
|
break
|
||||||
|
} catch (e: any) {
|
||||||
|
lastError = e
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!startedContainer) {
|
||||||
|
if (lastError) {
|
||||||
|
throw lastError
|
||||||
|
}
|
||||||
|
throw new Error(`failed to start container: ${imageName}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const info = testContainerUtils.getContainerById(startedContainer.getId())
|
const info = testContainerUtils.getContainerById(startedContainer.getId())
|
||||||
|
|
|
@ -29,6 +29,9 @@ export async function getDatasource(): Promise<Datasource> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const port = (await ports).find(x => x.container === 1433)?.host
|
const port = (await ports).find(x => x.container === 1433)?.host
|
||||||
|
if (!port) {
|
||||||
|
throw new Error("SQL Server port not found")
|
||||||
|
}
|
||||||
|
|
||||||
const datasource: Datasource = {
|
const datasource: Datasource = {
|
||||||
type: "datasource_plus",
|
type: "datasource_plus",
|
||||||
|
|
|
@ -38,6 +38,9 @@ export async function getDatasource(): Promise<Datasource> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const port = (await ports).find(x => x.container === 3306)?.host
|
const port = (await ports).find(x => x.container === 3306)?.host
|
||||||
|
if (!port) {
|
||||||
|
throw new Error("MySQL port not found")
|
||||||
|
}
|
||||||
|
|
||||||
const datasource: Datasource = {
|
const datasource: Datasource = {
|
||||||
type: "datasource_plus",
|
type: "datasource_plus",
|
||||||
|
|
|
@ -21,6 +21,9 @@ export async function getDatasource(): Promise<Datasource> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const port = (await ports).find(x => x.container === 5432)?.host
|
const port = (await ports).find(x => x.container === 5432)?.host
|
||||||
|
if (!port) {
|
||||||
|
throw new Error("Postgres port not found")
|
||||||
|
}
|
||||||
|
|
||||||
const datasource: Datasource = {
|
const datasource: Datasource = {
|
||||||
type: "datasource_plus",
|
type: "datasource_plus",
|
||||||
|
|
Loading…
Reference in New Issue