Skip to content

Commit 562508f

Browse files
authored
fix(ipam): make public detach & move ips idempotency (#1411)
1 parent 019d960 commit 562508f

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed

packages/clients/src/api/ipam/v1/api.gen.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,24 @@ import {
99
} from '../../../bridge'
1010
import type { Region } from '../../../bridge'
1111
import {
12+
marshalAttachIPRequest,
1213
marshalBookIPRequest,
14+
marshalDetachIPRequest,
15+
marshalMoveIPRequest,
1316
marshalReleaseIPSetRequest,
1417
marshalUpdateIPRequest,
1518
unmarshalIP,
1619
unmarshalListIPsResponse,
1720
} from './marshalling.gen'
1821
import type {
22+
AttachIPRequest,
1923
BookIPRequest,
24+
DetachIPRequest,
2025
GetIPRequest,
2126
IP,
2227
ListIPsRequest,
2328
ListIPsResponse,
29+
MoveIPRequest,
2430
ReleaseIPRequest,
2531
ReleaseIPSetRequest,
2632
UpdateIPRequest,
@@ -165,4 +171,75 @@ export class API extends ParentAPI {
165171
*/
166172
listIPs = (request: Readonly<ListIPsRequest> = {}) =>
167173
enrichForPagination('ips', this.pageOfListIPs, request)
174+
175+
/**
176+
* Attach existing IP to custom resource. Attach an existing IP from a Private
177+
* Network subnet to a custom, named resource via its MAC address. An example
178+
* of a custom resource is a virtual machine hosted on an Elastic Metal
179+
* server. Do not use this method for attaching IP addresses to standard
180+
* Scaleway resources as it will fail - see the relevant product API for an
181+
* equivalent method.
182+
*
183+
* @param request - The request {@link AttachIPRequest}
184+
* @returns A Promise of IP
185+
*/
186+
attachIP = (request: Readonly<AttachIPRequest>) =>
187+
this.client.fetch<IP>(
188+
{
189+
body: JSON.stringify(
190+
marshalAttachIPRequest(request, this.client.settings),
191+
),
192+
headers: jsonContentHeaders,
193+
method: 'POST',
194+
path: `/ipam/v1/regions/${validatePathParam('region', request.region ?? this.client.settings.defaultRegion)}/ips/${validatePathParam('ipId', request.ipId)}/attach`,
195+
},
196+
unmarshalIP,
197+
)
198+
199+
/**
200+
* Detach existing IP from a custom resource. Detach a private IP from a
201+
* custom resource. An example of a custom resource is a virtual machine
202+
* hosted on an Elastic Metal server. Do not use this method for attaching IP
203+
* addresses to standard Scaleway resources (e.g. Instances, Load Balancers)
204+
* as it will fail - see the relevant product API for an equivalent method.
205+
*
206+
* @param request - The request {@link DetachIPRequest}
207+
* @returns A Promise of IP
208+
*/
209+
detachIP = (request: Readonly<DetachIPRequest>) =>
210+
this.client.fetch<IP>(
211+
{
212+
body: JSON.stringify(
213+
marshalDetachIPRequest(request, this.client.settings),
214+
),
215+
headers: jsonContentHeaders,
216+
method: 'POST',
217+
path: `/ipam/v1/regions/${validatePathParam('region', request.region ?? this.client.settings.defaultRegion)}/ips/${validatePathParam('ipId', request.ipId)}/detach`,
218+
},
219+
unmarshalIP,
220+
)
221+
222+
/**
223+
* Move existing IP to a custom resource. Move an existing private IP from one
224+
* custom resource (e.g. a virtual machine hosted on an Elastic Metal server)
225+
* to another custom resource. This will detach it from the first resource,
226+
* and attach it to the second. Do not use this method for moving IP addresses
227+
* between standard Scaleway resources (e.g. Instances, Load Balancers) as it
228+
* will fail - see the relevant product API for an equivalent method.
229+
*
230+
* @param request - The request {@link MoveIPRequest}
231+
* @returns A Promise of IP
232+
*/
233+
moveIP = (request: Readonly<MoveIPRequest>) =>
234+
this.client.fetch<IP>(
235+
{
236+
body: JSON.stringify(
237+
marshalMoveIPRequest(request, this.client.settings),
238+
),
239+
headers: jsonContentHeaders,
240+
method: 'POST',
241+
path: `/ipam/v1/regions/${validatePathParam('region', request.region ?? this.client.settings.defaultRegion)}/ips/${validatePathParam('ipId', request.ipId)}/move`,
242+
},
243+
unmarshalIP,
244+
)
168245
}

packages/clients/src/api/ipam/v1/index.gen.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22
// If you have any remark or suggestion do not hesitate to open an issue.
33
export { API } from './api.gen'
44
export type {
5+
AttachIPRequest,
56
BookIPRequest,
7+
CustomResource,
8+
DetachIPRequest,
69
GetIPRequest,
710
IP,
811
ListIPsRequest,
912
ListIPsRequestOrderBy,
1013
ListIPsResponse,
14+
MoveIPRequest,
1115
ReleaseIPRequest,
1216
ReleaseIPSetRequest,
1317
Resource,

packages/clients/src/api/ipam/v1/marshalling.gen.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ import {
88
} from '../../../bridge'
99
import type { DefaultValues } from '../../../bridge'
1010
import type {
11+
AttachIPRequest,
1112
BookIPRequest,
13+
CustomResource,
14+
DetachIPRequest,
1215
IP,
1316
ListIPsResponse,
17+
MoveIPRequest,
1418
ReleaseIPSetRequest,
1519
Resource,
1620
Reverse,
@@ -96,6 +100,21 @@ export const unmarshalListIPsResponse = (data: unknown): ListIPsResponse => {
96100
} as ListIPsResponse
97101
}
98102

103+
const marshalCustomResource = (
104+
request: CustomResource,
105+
defaults: DefaultValues,
106+
): Record<string, unknown> => ({
107+
mac_address: request.macAddress,
108+
name: request.name,
109+
})
110+
111+
export const marshalAttachIPRequest = (
112+
request: AttachIPRequest,
113+
defaults: DefaultValues,
114+
): Record<string, unknown> => ({
115+
resource: marshalCustomResource(request.resource, defaults),
116+
})
117+
99118
const marshalSource = (
100119
request: Source,
101120
defaults: DefaultValues,
@@ -114,10 +133,32 @@ export const marshalBookIPRequest = (
114133
address: request.address,
115134
is_ipv6: request.isIpv6,
116135
project_id: request.projectId ?? defaults.defaultProjectId,
136+
resource:
137+
request.resource !== undefined
138+
? marshalCustomResource(request.resource, defaults)
139+
: undefined,
117140
source: marshalSource(request.source, defaults),
118141
tags: request.tags,
119142
})
120143

144+
export const marshalDetachIPRequest = (
145+
request: DetachIPRequest,
146+
defaults: DefaultValues,
147+
): Record<string, unknown> => ({
148+
resource: marshalCustomResource(request.resource, defaults),
149+
})
150+
151+
export const marshalMoveIPRequest = (
152+
request: MoveIPRequest,
153+
defaults: DefaultValues,
154+
): Record<string, unknown> => ({
155+
from_resource: marshalCustomResource(request.fromResource, defaults),
156+
to_resource:
157+
request.toResource !== undefined
158+
? marshalCustomResource(request.toResource, defaults)
159+
: undefined,
160+
})
161+
121162
export const marshalReleaseIPSetRequest = (
122163
request: ReleaseIPSetRequest,
123164
defaults: DefaultValues,

packages/clients/src/api/ipam/v1/types.gen.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type ListIPsRequestOrderBy =
1212

1313
export type ResourceType =
1414
| 'unknown_type'
15+
| 'custom'
1516
| 'instance_server'
1617
| 'instance_ip'
1718
| 'instance_private_nic'
@@ -72,6 +73,16 @@ export interface Source {
7273
subnetId?: string
7374
}
7475

76+
export interface CustomResource {
77+
/** MAC address of the custom resource. */
78+
macAddress: string
79+
/**
80+
* When the resource is in a Private Network, a DNS record is available to
81+
* resolve the resource name.
82+
*/
83+
name?: string
84+
}
85+
7586
export interface IP {
7687
/** IP ID. */
7788
id: string
@@ -99,6 +110,18 @@ export interface IP {
99110
zone?: Zone
100111
}
101112

113+
export type AttachIPRequest = {
114+
/**
115+
* Region to target. If none is passed will use default region from the
116+
* config.
117+
*/
118+
region?: Region
119+
/** IP ID. */
120+
ipId: string
121+
/** Custom resource to be attached to the IP. */
122+
resource: CustomResource
123+
}
124+
102125
export type BookIPRequest = {
103126
/**
104127
* Region to target. If none is passed will use default region from the
@@ -122,6 +145,25 @@ export type BookIPRequest = {
122145
address?: string
123146
/** Tags for the IP. */
124147
tags?: string[]
148+
/**
149+
* Custom resource to attach to the IP being booked. An example of a custom
150+
* resource is a virtual machine hosted on an Elastic Metal server. Do not use
151+
* this for attaching IP addresses to standard Scaleway resources, as it will
152+
* fail - instead, see the relevant product API for an equivalent method.
153+
*/
154+
resource?: CustomResource
155+
}
156+
157+
export type DetachIPRequest = {
158+
/**
159+
* Region to target. If none is passed will use default region from the
160+
* config.
161+
*/
162+
region?: Region
163+
/** IP ID. */
164+
ipId: string
165+
/** Custom resource currently attached to the IP. */
166+
resource: CustomResource
125167
}
126168

127169
export type GetIPRequest = {
@@ -221,6 +263,20 @@ export interface ListIPsResponse {
221263
ips: IP[]
222264
}
223265

266+
export type MoveIPRequest = {
267+
/**
268+
* Region to target. If none is passed will use default region from the
269+
* config.
270+
*/
271+
region?: Region
272+
/** IP ID. */
273+
ipId: string
274+
/** Custom resource currently attached to the IP. */
275+
fromResource: CustomResource
276+
/** Custom resource to be attached to the IP. */
277+
toResource?: CustomResource
278+
}
279+
224280
export type ReleaseIPRequest = {
225281
/**
226282
* Region to target. If none is passed will use default region from the

0 commit comments

Comments
 (0)