f210d9b749
* feat(projects): add project regions, default to null * feat(multiregion): add projectRegion Db client lookup logic * feat(multiregion): add project region repositories and caching * feat(multiRegion): db initialization and get project db client * feat(docker-compose): add second db for regions testing * feat(multiRegion): initialize region with pubs and subs working * fix(multiRegion): get region client even if it was registered in another pod * feat(workspaces): create workspace resolver split * feat: update server region metadata * feat(projects): rewrite project creation * feat(multiRegion): getRegionDb * fix(workspaces): get projects now can retur null * feat(multiRegion): make local multi region DB-s work * feat: set d efault workspace region * CR changes * tests * feat(multiRegion): bind region properly * fe update * test fixes * feat(multiRegion): automatically create aiven extras plugin * ci(postgres): use published postgres with aiven extras * fix(multiRegion): roll back the aiven extras migration, there is a better way * tests fix * fix(billing): we do not need to add a seat, if the workspace is on a plan, but has no sub --------- Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>
275 lines
8.2 KiB
TypeScript
275 lines
8.2 KiB
TypeScript
import { MultiRegionConfig } from '@/modules/multiregion/domain/types'
|
|
import { Regions } from '@/modules/multiregion/repositories'
|
|
import { BasicTestUser, createTestUser } from '@/test/authHelper'
|
|
import {
|
|
CreateNewRegionDocument,
|
|
CreateServerRegionInput,
|
|
GetAvailableRegionKeysDocument,
|
|
GetRegionsDocument,
|
|
UpdateRegionDocument,
|
|
UpdateServerRegionInput
|
|
} from '@/test/graphql/generated/graphql'
|
|
import {
|
|
ExecuteOperationOptions,
|
|
testApolloServer,
|
|
TestApolloServer
|
|
} from '@/test/graphqlHelper'
|
|
import { beforeEachContext, truncateTables } from '@/test/hooks'
|
|
import { MultiRegionConfigServiceMock } from '@/test/mocks/global'
|
|
import { Roles } from '@speckle/shared'
|
|
import { expect } from 'chai'
|
|
|
|
describe.skip('Multi Region Server Settings', () => {
|
|
let testAdminUser: BasicTestUser
|
|
let testBasicUser: BasicTestUser
|
|
let apollo: TestApolloServer
|
|
|
|
const fakeRegionKey1 = 'us-west-1'
|
|
const fakeRegionKey2 = 'eu-east-2'
|
|
|
|
const fakeRegionConfig: MultiRegionConfig = {
|
|
[fakeRegionKey1]: {
|
|
postgres: {
|
|
connectionUri: 'postgres://user:password@uswest1:port/dbname'
|
|
}
|
|
},
|
|
[fakeRegionKey2]: {
|
|
postgres: {
|
|
connectionUri: 'postgres://user:password@eueast3:port/dbname'
|
|
}
|
|
}
|
|
}
|
|
|
|
before(async () => {
|
|
// Have to mock both
|
|
// MultiRegionConfigServiceMock.mockFunction(
|
|
// 'getAvailableRegionConfigsFactory',
|
|
// () => async () => fakeRegionConfig
|
|
// )
|
|
MultiRegionConfigServiceMock.mockFunction(
|
|
'getAvailableRegionKeysFactory',
|
|
() => async () => Object.keys(fakeRegionConfig)
|
|
)
|
|
|
|
await beforeEachContext()
|
|
testAdminUser = await createTestUser({ role: Roles.Server.Admin })
|
|
testBasicUser = await createTestUser({ role: Roles.Server.User })
|
|
apollo = await testApolloServer({ authUserId: testAdminUser.id })
|
|
})
|
|
|
|
after(() => {
|
|
MultiRegionConfigServiceMock.resetMockedFunctions()
|
|
})
|
|
|
|
describe('server config', () => {
|
|
const createRegion = (
|
|
input: CreateServerRegionInput,
|
|
options?: ExecuteOperationOptions
|
|
) => apollo.execute(CreateNewRegionDocument, { input }, options)
|
|
|
|
it("region keys can't be retrieved by non-admin", async () => {
|
|
const res = await apollo.execute(
|
|
GetAvailableRegionKeysDocument,
|
|
{},
|
|
{
|
|
context: {
|
|
userId: testBasicUser.id,
|
|
role: Roles.Server.User
|
|
}
|
|
}
|
|
)
|
|
expect(res).to.haveGraphQLErrors('You do not have the required server role')
|
|
expect(res.data?.serverInfo.multiRegion.availableKeys).to.be.not.ok
|
|
})
|
|
|
|
it('allows retrieving available config keys', async () => {
|
|
const res = await apollo.execute(GetAvailableRegionKeysDocument, {})
|
|
expect(res.data?.serverInfo.multiRegion.availableKeys).to.deep.equal(
|
|
Object.keys(fakeRegionConfig)
|
|
)
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
})
|
|
|
|
describe('when creating new region', async () => {
|
|
afterEach(async () => {
|
|
// Wipe created regions
|
|
await truncateTables([Regions.name])
|
|
})
|
|
|
|
it("it can't be created by non-admin", async () => {
|
|
const res = await createRegion(
|
|
{
|
|
key: fakeRegionKey1,
|
|
name: 'US West 1',
|
|
description: 'Helloooo'
|
|
},
|
|
{
|
|
context: {
|
|
userId: testBasicUser.id,
|
|
role: Roles.Server.User
|
|
}
|
|
}
|
|
)
|
|
expect(res).to.haveGraphQLErrors('You do not have the required server role')
|
|
})
|
|
|
|
it('it works with valid input', async () => {
|
|
const input: CreateServerRegionInput = {
|
|
key: fakeRegionKey1,
|
|
name: 'US West 1',
|
|
description: 'Helloooo'
|
|
}
|
|
|
|
const res = await createRegion(input)
|
|
expect(res.data?.serverInfoMutations.multiRegion.create).to.deep.equal({
|
|
...input,
|
|
id: input.key
|
|
})
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
})
|
|
|
|
it("doesn't work with already used up key", async () => {
|
|
const input: CreateServerRegionInput = {
|
|
key: fakeRegionKey1,
|
|
name: 'US West 1',
|
|
description: 'Helloooo'
|
|
}
|
|
|
|
const res1 = await createRegion(input)
|
|
expect(res1).to.not.haveGraphQLErrors()
|
|
|
|
const res2 = await createRegion(input)
|
|
expect(res2).to.haveGraphQLErrors('Region with this key already exists')
|
|
})
|
|
|
|
it("doesn't work with invalid key", async () => {
|
|
const input: CreateServerRegionInput = {
|
|
key: 'randooo-key',
|
|
name: 'US West 1',
|
|
description: 'Helloooo'
|
|
}
|
|
|
|
const res = await createRegion(input)
|
|
expect(res).to.haveGraphQLErrors('Region key is not valid')
|
|
})
|
|
})
|
|
|
|
describe('when working with existing regions', async () => {
|
|
const createdRegionInput: CreateServerRegionInput = {
|
|
key: fakeRegionKey1,
|
|
name: 'US West 1',
|
|
description: 'Helloooo'
|
|
}
|
|
|
|
before(async () => {
|
|
// Create a region
|
|
await createRegion(createdRegionInput, { assertNoErrors: true })
|
|
})
|
|
|
|
it("can't retrieve regions if non-admin", async () => {
|
|
const res = await apollo.execute(
|
|
GetRegionsDocument,
|
|
{},
|
|
{
|
|
context: {
|
|
userId: testBasicUser.id,
|
|
role: Roles.Server.User
|
|
}
|
|
}
|
|
)
|
|
expect(res).to.haveGraphQLErrors('You do not have the required server role')
|
|
})
|
|
|
|
it('allows retrieving all regions', async () => {
|
|
const res = await apollo.execute(GetRegionsDocument, {})
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(res.data?.serverInfo.multiRegion.regions).to.have.length(1)
|
|
expect(res.data?.serverInfo.multiRegion.regions).to.deep.equal([
|
|
{
|
|
...createdRegionInput,
|
|
id: createdRegionInput.key
|
|
}
|
|
])
|
|
})
|
|
|
|
it('filters out used region from available keys', async () => {
|
|
const res = await apollo.execute(GetAvailableRegionKeysDocument, {})
|
|
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
expect(res.data?.serverInfo.multiRegion.availableKeys).to.deep.equal([
|
|
fakeRegionKey2
|
|
])
|
|
})
|
|
})
|
|
|
|
describe('when updating existing region', async () => {
|
|
const createdRegionInput: CreateServerRegionInput = {
|
|
key: fakeRegionKey2,
|
|
name: 'Updatable Region 1',
|
|
description: 'Helloooo'
|
|
}
|
|
|
|
const updateRegion = (
|
|
input: UpdateServerRegionInput,
|
|
options?: ExecuteOperationOptions
|
|
) => apollo.execute(UpdateRegionDocument, { input }, options)
|
|
|
|
beforeEach(async () => {
|
|
// Create new region
|
|
await createRegion(createdRegionInput, { assertNoErrors: true })
|
|
})
|
|
|
|
afterEach(async () => {
|
|
// Wipe created regions
|
|
await truncateTables([Regions.name])
|
|
})
|
|
|
|
it("can't update region if non-admin", async () => {
|
|
const res = await updateRegion(
|
|
{
|
|
key: createdRegionInput.key,
|
|
name: 'Updated Region 1'
|
|
},
|
|
{
|
|
context: {
|
|
userId: testBasicUser.id,
|
|
role: Roles.Server.User
|
|
}
|
|
}
|
|
)
|
|
expect(res).to.haveGraphQLErrors('You do not have the required server role')
|
|
})
|
|
|
|
it('works with valid input', async () => {
|
|
const updatedName = 'aaa Updated Region 1'
|
|
const updatedDescription = 'bbb Updated description'
|
|
|
|
const res = await updateRegion({
|
|
key: createdRegionInput.key,
|
|
name: updatedName,
|
|
description: updatedDescription
|
|
})
|
|
|
|
expect(res.data?.serverInfoMutations.multiRegion.update).to.deep.equal({
|
|
...createdRegionInput,
|
|
id: createdRegionInput.key,
|
|
name: updatedName,
|
|
description: updatedDescription
|
|
})
|
|
expect(res).to.not.haveGraphQLErrors()
|
|
})
|
|
|
|
it('fails gracefully with invalid region key', async () => {
|
|
const res = await updateRegion({
|
|
key: 'invalid-key',
|
|
name: 'Updated Region 1'
|
|
})
|
|
|
|
expect(res).to.haveGraphQLErrors('Region not found')
|
|
expect(res.data?.serverInfoMutations.multiRegion.update).to.be.not.ok
|
|
})
|
|
})
|
|
})
|
|
})
|