Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion packages/clients/src/api/instance/v1/api.utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { validatePathParam } from '../../../bridge'
import {
createExponentialBackoffStrategy,
tryAtIntervals,
Expand All @@ -11,6 +12,8 @@ import {
SNAPSHOT_TRANSIENT_STATUSES,
VOLUME_TRANSIENT_STATUSES,
} from './content.gen'
import { unmarshalSetImageResponse } from './marshalling.gen'
import { marshalSetImageRequestWithID } from './marshalling.utils'
import type {
GetImageRequest,
GetPrivateNICRequest,
Expand All @@ -26,13 +29,18 @@ import type {
Volume,
VolumeServerTemplate,
} from './types.gen'
import type { SetSecurityGroupRuleRequest } from './types.private.gen'
import type {
SetImageResponse,
SetSecurityGroupRuleRequest,
} from './types.private.gen'
import type {
AttachVolumeRequest,
AttachVolumeResponse,
CreateServerRequest,
DetachVolumeRequest,
DetachVolumeResponse,
UpdateImageRequest,
UpdateImageResponse,
UpdateSecurityGroupRequest,
UpdateSecurityGroupResponse,
UpdateSecurityGroupRuleRequest,
Expand Down Expand Up @@ -467,4 +475,39 @@ export class InstanceV1UtilsAPI extends API {
zone: request.zone,
} as UpdateServerRequest).then(obj => obj as DetachVolumeResponse)
}

/**
* Updates an image.
*
* @param request - The request {@link UpdateImageRequest}
* @returns A Promise of UpdateImageResponse
*/
updateImage = (
request: Readonly<UpdateImageRequest>,
): Promise<UpdateImageResponse> =>
this.getImage({ zone: request.zone, imageId: request.imageId })
.then(res => validateNotUndefined(res.image))
.then(image => ({
...image,
name: request.name ?? image.name,
tags: request.tags ?? image.tags,
id: image.id,
}))
.then(imageReq =>
this.client.fetch<SetImageResponse>(
{
body: JSON.stringify(
marshalSetImageRequestWithID(imageReq, this.client.settings),
),
headers: { 'Content-Type': 'application/json; charset=utf-8' },
method: 'PUT',
path: `/instance/v1/zones/${validatePathParam(
'zone',
imageReq.zone ?? this.client.settings.defaultZone,
)}/images/${validatePathParam('id', imageReq.id)}`,
},
unmarshalSetImageResponse,
),
)
.then(res => ({ image: res.image }))
}
97 changes: 97 additions & 0 deletions packages/clients/src/api/instance/v1/marshalling.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { type DefaultValues } from '../../../bridge'
import type {
Bootscript,
ServerSummary,
Volume,
VolumeSummary,
} from './types.gen'
import type { SetImageRequest } from './types.private.gen'

const marshalVolumeSummary = (
request: VolumeSummary,
defaults: DefaultValues,
): Record<string, unknown> => ({
id: request.id,
name: request.name,
size: request.size,
volume_type: request.volumeType,
})

const marshalServerSummary = (
request: ServerSummary,
defaults: DefaultValues,
): Record<string, unknown> => ({
id: request.id,
name: request.name,
})

const marshalBootscript = (
request: Bootscript,
defaults: DefaultValues,
): Record<string, unknown> => ({
arch: request.arch,
bootcmdargs: request.bootcmdargs,
default: request.default,
dtb: request.dtb,
id: request.id,
initrd: request.initrd,
kernel: request.kernel,
organization: request.organization,
project: request.project,
public: request.public,
title: request.title,
zone: request.zone,
})

const marshalVolume = (
request: Volume,
defaults: DefaultValues,
): Record<string, unknown> => ({
creation_date: request.creationDate,
export_uri: request.exportUri,
id: request.id,
modification_date: request.modificationDate,
name: request.name,
organization: request.organization,
project: request.project,
server: request.server
? marshalServerSummary(request.server, defaults)
: undefined,
size: request.size,
state: request.state,
tags: request.tags,
volume_type: request.volumeType,
zone: request.zone,
})

export const marshalSetImageRequestWithID = (
request: SetImageRequest,
defaults: DefaultValues,
): Record<string, unknown> => ({
arch: request.arch,
creation_date: request.creationDate,
default_bootscript: request.defaultBootscript
? marshalBootscript(request.defaultBootscript, defaults)
: undefined,
extra_volumes: request.extraVolumes
? Object.entries(request.extraVolumes).reduce(
(acc, [key, value]) => ({
...acc,
[key]: marshalVolume(value, defaults),
}),
{},
)
: undefined,
from_server: request.fromServer,
modification_date: request.modificationDate,
id: request.id,
name: request.name,
organization: request.organization,
project: request.project,
public: request.public,
root_volume: request.rootVolume
? marshalVolumeSummary(request.rootVolume, defaults)
: undefined,
state: request.state,
tags: request.tags,
})
13 changes: 13 additions & 0 deletions packages/clients/src/api/instance/v1/types.utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Zone } from '../../../scw/locality'
import type {
Image,
SecurityGroup,
SecurityGroupPolicy,
SecurityGroupRule,
Expand Down Expand Up @@ -93,6 +94,18 @@ export interface DetachVolumeResponse {
server?: Server
}

export type UpdateImageRequest = {
/** Zone to target. If none is passed will use default zone from the config */
zone?: Zone
imageId: string
name?: string
tags?: string[]
}

export interface UpdateImageResponse {
image?: Image
}

export type {
CreateServerRequest,
UpdateServerRequest,
Expand Down