Skip to content

Commit 614f1bb

Browse files
authored
mock API: Move floating IP checks earlier in instance create handler (#2466)
separate floating IP validation from allocation in mock instance create
1 parent df2dc14 commit 614f1bb

File tree

1 file changed

+41
-17
lines changed

1 file changed

+41
-17
lines changed

mock-api/msw/handlers.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,33 @@ export const handlers = makeHandlers({
448448
})
449449
}
450450

451-
/////////////////////////////////////////////////////////////
452-
// DB write stuff starts here
453-
/////////////////////////////////////////////////////////////
451+
// validate floating IP attachments before we actually do anything
452+
body.external_ips?.forEach((ip) => {
453+
if (ip.type === 'floating') {
454+
// throw if floating IP doesn't exist
455+
const floatingIp = lookup.floatingIp({
456+
project: project.id,
457+
floatingIp: ip.floating_ip,
458+
})
459+
if (floatingIp.instance_id) {
460+
throw 'floating IP cannot be attached to one instance while still attached to another'
461+
}
462+
} else {
463+
// just make sure we can get one. technically this will only throw
464+
// if there are no ranges in the pool or if the pool doesn't exist,
465+
// which aren't quite as good as checking that there are actually IPs
466+
// available, but they are good things to check
467+
getIpFromPool(ip.pool)
468+
}
469+
})
470+
471+
//////////////////////////////////////////////////////////////////////////
472+
// DB WRITES START HERE
473+
//
474+
// We don't have transactions or sagas, so we need to make sure we do all
475+
// our validation and throw any errors about bad input before we make any
476+
// changes to the DB that would have to be undone on failure.
477+
//////////////////////////////////////////////////////////////////////////
454478

455479
for (const diskParams of allDisks) {
456480
if (diskParams.type === 'create') {
@@ -515,26 +539,15 @@ export const handlers = makeHandlers({
515539
)
516540
}
517541

518-
const newInstance: Json<Api.Instance> = {
519-
id: instanceId,
520-
project_id: project.id,
521-
...R.pick(body, ['name', 'description', 'hostname', 'memory', 'ncpus']),
522-
...getTimestamps(),
523-
run_state: 'creating',
524-
time_run_state_updated: new Date().toISOString(),
525-
boot_disk_id: bootDiskId,
526-
auto_restart_enabled: true,
527-
}
528-
542+
// actually set up IPs. looks very similar to validation step but this time
543+
// we are writing to the DB
529544
body.external_ips?.forEach((ip) => {
530545
if (ip.type === 'floating') {
531546
const floatingIp = lookup.floatingIp({
532547
project: project.id,
533548
floatingIp: ip.floating_ip,
534549
})
535-
if (floatingIp.instance_id) {
536-
throw 'floating IP cannot be attached to one instance while still attached to another'
537-
}
550+
// we've already validated that the IP isn't attached
538551
floatingIp.instance_id = instanceId
539552
} else if (ip.type === 'ephemeral') {
540553
const firstAvailableAddress = getIpFromPool(ip.pool)
@@ -548,6 +561,17 @@ export const handlers = makeHandlers({
548561
}
549562
})
550563

564+
const newInstance: Json<Api.Instance> = {
565+
id: instanceId,
566+
project_id: project.id,
567+
...R.pick(body, ['name', 'description', 'hostname', 'memory', 'ncpus']),
568+
...getTimestamps(),
569+
run_state: 'creating',
570+
time_run_state_updated: new Date().toISOString(),
571+
boot_disk_id: bootDiskId,
572+
auto_restart_enabled: true,
573+
}
574+
551575
setTimeout(() => {
552576
newInstance.run_state = 'starting'
553577
}, 500)

0 commit comments

Comments
 (0)