Avoid duplicate runner names
This commit is contained in:
parent
88cde4392a
commit
d959b763f0
|
@ -27,7 +27,7 @@ import { CONFIG, registerConfigChangedHandler } from './config'
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const LAST_MIGRATION_VERSION = 790
|
||||
const LAST_MIGRATION_VERSION = 795
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
const query = 'DELETE FROM "runner" r1 ' +
|
||||
'USING (SELECT MIN(id) as id, "name" FROM "runner" GROUP BY "name" HAVING COUNT(*) > 1) r2 ' +
|
||||
'WHERE r1."name" = r2."name" AND r1.id <> r2.id'
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
|
@ -35,6 +35,15 @@ const registerRunnerValidator = [
|
|||
})
|
||||
}
|
||||
|
||||
const existing = await RunnerModel.loadByName(body.name)
|
||||
if (existing) {
|
||||
return res.fail({
|
||||
status: HttpStatusCode.BAD_REQUEST_400,
|
||||
message: 'This runner name already exists on this instance',
|
||||
tags
|
||||
})
|
||||
}
|
||||
|
||||
res.locals.runnerRegistrationToken = runnerRegistrationToken
|
||||
|
||||
return next()
|
||||
|
|
|
@ -16,6 +16,10 @@ import { CONSTRAINTS_FIELDS } from '@server/initializers/constants'
|
|||
},
|
||||
{
|
||||
fields: [ 'runnerRegistrationTokenId' ]
|
||||
},
|
||||
{
|
||||
fields: [ 'name' ],
|
||||
unique: true
|
||||
}
|
||||
]
|
||||
})
|
||||
|
@ -74,6 +78,14 @@ export class RunnerModel extends Model<Partial<AttributesOnly<RunnerModel>>> {
|
|||
return RunnerModel.findOne(query)
|
||||
}
|
||||
|
||||
static loadByName (name: string) {
|
||||
const query = {
|
||||
where: { name }
|
||||
}
|
||||
|
||||
return RunnerModel.findOne(query)
|
||||
}
|
||||
|
||||
static listForApi (options: {
|
||||
start: number
|
||||
count: number
|
||||
|
|
|
@ -177,6 +177,15 @@ describe('Test managing runners', function () {
|
|||
|
||||
toDeleteId = id
|
||||
})
|
||||
|
||||
it('Should fail with the same runner name', async function () {
|
||||
await server.runners.register({
|
||||
name,
|
||||
description: 'super description',
|
||||
registrationToken,
|
||||
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Delete', function () {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { pick } from '@shared/core-utils'
|
||||
import { buildUUID } from '@shared/extra-utils'
|
||||
import { HttpStatusCode, RegisterRunnerBody, RegisterRunnerResult, ResultList, Runner, UnregisterRunnerBody } from '@shared/models'
|
||||
import { unwrapBody } from '../requests'
|
||||
import { AbstractCommand, OverrideCommandOptions } from '../shared'
|
||||
|
@ -68,7 +69,7 @@ export class RunnersCommand extends AbstractCommand {
|
|||
const { data } = await this.server.runnerRegistrationTokens.list({ sort: 'createdAt' })
|
||||
|
||||
const { runnerToken } = await this.register({
|
||||
name: 'runner',
|
||||
name: 'runner ' + buildUUID(),
|
||||
registrationToken: data[0].registrationToken
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue