130 lines
7.0 KiB
TypeScript
130 lines
7.0 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { after, before, test } from 'node:test'
|
|
import pg from 'pg'
|
|
import { HttpError } from './http.ts'
|
|
import { createTfvarsStore, tfvarsText, type TfvarsStore } from './tfvarsStore.ts'
|
|
|
|
// The tests create a scratch database on the server the PG* variables name, connected to through the database
|
|
// postgres, and drop it at the end.
|
|
const database = `tfvars_store_test_${process.pid}`
|
|
const admin = new pg.Client({ database: 'postgres' })
|
|
let pool: pg.Pool
|
|
let store: TfvarsStore
|
|
|
|
before(async () => {
|
|
await admin.connect()
|
|
await admin.query(`CREATE DATABASE ${database}`)
|
|
pool = new pg.Pool({ database })
|
|
store = createTfvarsStore(pool)
|
|
})
|
|
|
|
after(async () => {
|
|
await pool?.end()
|
|
await admin.query(`DROP DATABASE IF EXISTS ${database}`)
|
|
await admin.end()
|
|
})
|
|
|
|
const status = async (promise: Promise<unknown>) => {
|
|
try {
|
|
await promise
|
|
} catch (error) {
|
|
assert.ok(error instanceof HttpError, String(error))
|
|
return error.statusCode
|
|
}
|
|
return 0
|
|
}
|
|
|
|
test('modules are created, changed, listed and deleted', async () => {
|
|
await store.modules.put({ name: 'router', root: 'router/terraform', description: 'VPN router', configuratorUrl: null })
|
|
await store.modules.put({ name: 'router', root: 'router/terraform', description: 'VPN router', configuratorUrl: 'http://localhost:7083/' })
|
|
await store.modules.put({ name: 'app', root: 'app', description: '', configuratorUrl: null })
|
|
assert.deepEqual(await store.modules.list(), [
|
|
{ name: 'app', root: 'app', description: '', configuratorUrl: null },
|
|
{ name: 'router', root: 'router/terraform', description: 'VPN router', configuratorUrl: 'http://localhost:7083/' },
|
|
])
|
|
await store.modules.delete('app')
|
|
assert.deepEqual((await store.modules.list()).map((module) => module.name), ['router'])
|
|
assert.equal(await status(store.modules.put({ name: 'Bad', root: 'x', description: '', configuratorUrl: null })), 400)
|
|
})
|
|
|
|
test('instances are created and refused for a missing module or a name in use', async () => {
|
|
await store.instances.create('router', 'platform', 'terraform_remote_state')
|
|
await store.instances.create('router', 'test', 'tf_router_test')
|
|
assert.deepEqual((await store.instances.list('router')).map((instance) => [instance.name, instance.stateSchema]), [
|
|
['platform', 'terraform_remote_state'],
|
|
['test', 'tf_router_test'],
|
|
])
|
|
assert.equal(await status(store.instances.create('missing', 'x', 'tf_missing_x')), 404)
|
|
assert.equal(await status(store.instances.create('router', 'test', 'tf_other')), 409)
|
|
assert.equal(await status(store.instances.create('router', 'other', 'tf_router_test')), 409)
|
|
assert.equal(await status(store.modules.delete('router')), 409)
|
|
})
|
|
|
|
const META = { schema: 1, producer: 'Test Configurator 1.0.0' }
|
|
|
|
test('variable files are written with their version and refused against another version', async () => {
|
|
const variables = store.variables('router', 'test')
|
|
const empty = await variables.read()
|
|
assert.deepEqual(empty.files, [])
|
|
assert.equal(empty.version, '')
|
|
assert.equal(empty.revision, null)
|
|
assert.equal(await variables.write(empty.version, { 'platform.tfvars.json': tfvarsText({ a: 1 }), 'secrets.tfvars.json': tfvarsText({ s: 'x' }) }, META), true)
|
|
const written = await variables.read()
|
|
assert.deepEqual(written.files.map((file) => [file.name, file.content.toString('utf8')]), [
|
|
['platform.tfvars.json', tfvarsText({ a: 1 })],
|
|
['secrets.tfvars.json', tfvarsText({ s: 'x' })],
|
|
])
|
|
assert.deepEqual(written.status.map((file) => file.previous), [false, false])
|
|
assert.equal(await variables.write(empty.version, { 'platform.tfvars.json': tfvarsText({ a: 2 }) }, META), false)
|
|
assert.equal(await variables.write(written.version, { 'platform.tfvars.json': tfvarsText({ a: 2 }) }, META), true)
|
|
const changed = await variables.read()
|
|
assert.deepEqual(changed.status.map((file) => file.previous), [true, false])
|
|
assert.notEqual(changed.version, written.version)
|
|
assert.equal(await variables.remove(written.version, 'secrets.tfvars.json', META), false)
|
|
assert.equal(await variables.remove(changed.version, 'secrets.tfvars.json', META), true)
|
|
assert.deepEqual((await variables.read()).files.map((file) => file.name), ['platform.tfvars.json'])
|
|
assert.deepEqual((await store.variables('router', 'platform').read()).files, [])
|
|
assert.equal(await status(variables.write((await variables.read()).version, { 'notes.json': tfvarsText({}) }, META)), 400)
|
|
assert.equal(await status(store.variables('router', 'missing').write('', { 'a.tfvars.json': tfvarsText({}) }, META)), 404)
|
|
})
|
|
|
|
test('every write is a revision with its files, schema and producer', async () => {
|
|
const variables = store.variables('router', 'test')
|
|
assert.deepEqual((await variables.revisions()).map((revision) => [revision.revision, revision.schema, revision.producer, revision.names]), [
|
|
[3, 1, META.producer, ['platform.tfvars.json']],
|
|
[2, 1, META.producer, ['platform.tfvars.json', 'secrets.tfvars.json']],
|
|
[1, 1, META.producer, ['platform.tfvars.json', 'secrets.tfvars.json']],
|
|
])
|
|
const current = await variables.read()
|
|
assert.equal(await variables.write(current.version, {}, META), true)
|
|
assert.equal(await variables.write(current.version, { 'platform.tfvars.json': tfvarsText({ a: 3 }) }, { schema: null, producer: 'manage.mjs import' }), true)
|
|
const newest = (await variables.read()).revision
|
|
assert.deepEqual(newest && [newest.revision, newest.schema, newest.producer], [4, null, 'manage.mjs import'])
|
|
const first = await variables.revision(1)
|
|
assert.deepEqual(first?.files.map((file) => [file.name, file.content.toString('utf8')]), [
|
|
['platform.tfvars.json', tfvarsText({ a: 1 })],
|
|
['secrets.tfvars.json', tfvarsText({ s: 'x' })],
|
|
])
|
|
assert.equal(await variables.revision(9), null)
|
|
assert.deepEqual(await store.variables('router', 'platform').revisions(), [])
|
|
})
|
|
|
|
test('the files of an instance without revisions become its revision 1 of an unknown producer', async () => {
|
|
await pool.query(`INSERT INTO tf_variable_files (module, instance, name, content) VALUES ('router', 'platform', 'a.tfvars.json', '{"b": 1}')`)
|
|
await pool.query('DELETE FROM tf_variable_revisions')
|
|
const again = createTfvarsStore(pool)
|
|
const revisions = await again.variables('router', 'platform').revisions()
|
|
assert.deepEqual(revisions.map((revision) => [revision.revision, revision.schema, revision.producer, revision.names]), [[1, null, 'unknown', ['a.tfvars.json']]])
|
|
assert.deepEqual((await again.variables('router', 'test').revisions()).map((revision) => revision.revision), [1])
|
|
})
|
|
|
|
test('an instance is deleted with its variable files, then its module', async () => {
|
|
await store.instances.delete('router', 'test')
|
|
await store.instances.delete('router', 'platform')
|
|
assert.deepEqual(await store.instances.list('router'), [])
|
|
assert.equal((await pool.query('SELECT count(*)::int AS n FROM tf_variable_files')).rows[0].n, 0)
|
|
assert.equal((await pool.query('SELECT count(*)::int AS n FROM tf_variable_revisions')).rows[0].n, 0)
|
|
await store.modules.delete('router')
|
|
assert.deepEqual(await store.modules.list(), [])
|
|
})
|