Skip to content

Commit

Permalink
more detailed comments about API logic we're imitating
Browse files Browse the repository at this point in the history
  • Loading branch information
david-crespo committed Aug 27, 2024
1 parent 5292988 commit c174d8f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 13 deletions.
27 changes: 19 additions & 8 deletions mock-api/msw/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// note that isUuid checks for any kind of UUID. strictly speaking, we should
// only be checking for v4
import * as R from 'remeda'
import { validate as isUuid } from 'uuid'

import type { ApiTypes as Api, PathParams as PP } from '@oxide/api'
import * as mock from '@oxide/api-mocks'
Expand All @@ -17,7 +16,7 @@ import { json } from '~/api/__generated__/msw-handlers'
import { commaSeries } from '~/util/str'

import type { Json } from '../json-type'
import { internalError } from './util'
import { internalError, isUuid } from './util'

const notFoundBody = { error_code: 'ObjectNotFound' } as const
export type NotFound = typeof notFoundBody
Expand Down Expand Up @@ -219,21 +218,33 @@ export const lookup = {
image({ image: id, project: projectId }: PP.Image): Json<Api.Image> {
if (!id) throw notFoundErr('no image specified')

// We match the API logic:
//
// match image_selector {
// (image ID, no project) =>
// look up image in DB by ID
// if project ID is present, it's a project image, otherwise silo image
// (image Name, project specified) => it's a project image
// (image Name, no project) => it's a silo image
// (image ID, project specified) => error
// }
//
// https://github.com/oxidecomputer/omicron/blob/219121a/nexus/src/app/image.rs#L32-L76

if (isUuid(id)) {
// this matches the error case above
ensureNoParentSelectors('image', { project: projectId })
return lookupById(db.images, id)
}

// TODO: is this logic right? seems kinda weird. you should be able to look
// up either kind by ID. we should probably have two lookup functions
let image: Json<Api.Image> | undefined
if (projectId === undefined) {
// silo image
image = db.images.find((d) => d.project_id === undefined && d.name === id)
} else {
if (projectId) {
// project image
const project = lookup.project({ project: projectId })
image = db.images.find((d) => d.project_id === project.id && d.name === id)
} else {
// silo image
image = db.images.find((d) => d.project_id === undefined && d.name === id)
}

if (!image) throw notFoundErr(`image '${id}'`)
Expand Down
17 changes: 12 additions & 5 deletions mock-api/msw/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
handleMetrics,
ipInAnyRange,
ipRangeLen,
isUuid,
NotImplemented,
paginated,
requireFleetCollab,
Expand Down Expand Up @@ -293,9 +294,14 @@ export const handlers = makeHandlers({
if (dbFloatingIp.instance_id) {
throw 'floating IP cannot be attached to one instance while still attached to another'
}
// TODO: make sure the logic around when project is passed matches
// the API
const dbInstance = lookup.instance({ instance: body.parent })
// Following the API logic here, which says that when the instance is passed
// by name, we pull the project ID off the floating IP.
//
// https://github.com/oxidecomputer/omicron/blob/e434307/nexus/src/app/external_ip.rs#L171-L201
const dbInstance = lookup.instance({
instance: body.parent,
project: isUuid(body.parent) ? undefined : project,
})
dbFloatingIp.instance_id = dbInstance.id

return dbFloatingIp
Expand Down Expand Up @@ -362,8 +368,9 @@ export const handlers = makeHandlers({
return json(image, { status: 202 })
},
imageDemote({ path: { image }, query: { project } }) {
// TODO: change this to lookup.siloImage when I add that. or at least
// check API logic to make sure we match it
// unusual case because the project is never used to resolve the image. you
// can only demote silo images, and whether we have an image name or ID, if
// there is no project specified, the lookup assumes it's a silo image
const dbImage = lookup.image({ image })
const dbProject = lookup.project({ project })

Expand Down
7 changes: 7 additions & 0 deletions mock-api/msw/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { differenceInSeconds, subHours } from 'date-fns'
// Works without the .js for dev server and prod build in MSW mode, but
// playwright wants the .js. No idea why, let's just add the .js.
import { IPv4, IPv6 } from 'ip-num/IPNumber.js'
import { validate as uuidValidate, version as uuidVersion } from 'uuid'

import {
FLEET_ID,
Expand Down Expand Up @@ -413,3 +414,9 @@ export function updateDesc(
resource.description = update.description
}
}

/**
* Check if something is a v4 UUID. Implementation follows uuid readme:
* https://github.com/uuidjs/uuid/blob/9e69599/README.md#L407-L422
*/
export const isUuid = (s: string) => uuidValidate(s) && uuidVersion(s) === 4

0 comments on commit c174d8f

Please sign in to comment.