diff --git a/packages/clients/src/api/index.ts b/packages/clients/src/api/index.ts index 9c2983942..2faaca5ae 100644 --- a/packages/clients/src/api/index.ts +++ b/packages/clients/src/api/index.ts @@ -12,6 +12,7 @@ export * as Function from './function' export * as IAM from './iam' export * as Instance from './instance' export * as IOT from './iot' +export * as IPAM from './ipam' export * as IPFS from './ipfs' export * as K8S from './k8s' export * as LB from './lb' diff --git a/packages/clients/src/api/ipam/index.ts b/packages/clients/src/api/ipam/index.ts new file mode 100644 index 000000000..73ddaf23c --- /dev/null +++ b/packages/clients/src/api/ipam/index.ts @@ -0,0 +1 @@ +export * as v1 from './v1/index.gen' diff --git a/packages/clients/src/api/ipam/v1/api.gen.ts b/packages/clients/src/api/ipam/v1/api.gen.ts new file mode 100644 index 000000000..c8e37964f --- /dev/null +++ b/packages/clients/src/api/ipam/v1/api.gen.ts @@ -0,0 +1,174 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +import { + API as ParentAPI, + enrichForPagination, + resolveOneOf, + urlParams, + validatePathParam, +} from '../../../bridge' +import type { Region } from '../../../bridge' +import { + marshalBookIPRequest, + marshalUpdateIPRequest, + unmarshalIP, + unmarshalListIPsResponse, +} from './marshalling.gen' +import type { + BookIPRequest, + GetIPRequest, + IP, + ListIPsRequest, + ListIPsResponse, + ReleaseIPRequest, + UpdateIPRequest, +} from './types.gen' + +const jsonContentHeaders = { + 'Content-Type': 'application/json; charset=utf-8', +} + +/** + * IPAM API. + * + * This API allows you to manage IP addresses with Scaleway's IP Address + * Management tool. IPAM API. + */ +export class API extends ParentAPI { + /** Lists the available regions of the API. */ + public static readonly LOCALITIES: Region[] = ['fr-par', 'nl-ams', 'pl-waw'] + + /** + * Book a new IP. Book a new IP from the specified source. Currently IPs can + * only be booked from a Private Network. + * + * @param request - The request {@link BookIPRequest} + * @returns A Promise of IP + */ + bookIP = (request: Readonly) => + this.client.fetch( + { + body: JSON.stringify( + marshalBookIPRequest(request, this.client.settings), + ), + headers: jsonContentHeaders, + method: 'POST', + path: `/ipam/v1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/ips`, + }, + unmarshalIP, + ) + + /** + * Release an IP. Release an IP not currently attached to a resource, and + * returns it to the available IP pool. + * + * @param request - The request {@link ReleaseIPRequest} + */ + releaseIP = (request: Readonly) => + this.client.fetch({ + body: '{}', + headers: jsonContentHeaders, + method: 'DELETE', + path: `/ipam/v1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/ips/${validatePathParam('ipId', request.ipId)}`, + }) + + /** + * Get an IP. Retrieve details of an existing IP, specified by its IP ID. + * + * @param request - The request {@link GetIPRequest} + * @returns A Promise of IP + */ + getIP = (request: Readonly) => + this.client.fetch( + { + method: 'GET', + path: `/ipam/v1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/ips/${validatePathParam('ipId', request.ipId)}`, + }, + unmarshalIP, + ) + + /** + * Update an IP. Update parameters including tags of the specified IP. + * + * @param request - The request {@link UpdateIPRequest} + * @returns A Promise of IP + */ + updateIP = (request: Readonly) => + this.client.fetch( + { + body: JSON.stringify( + marshalUpdateIPRequest(request, this.client.settings), + ), + headers: jsonContentHeaders, + method: 'PATCH', + path: `/ipam/v1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/ips/${validatePathParam('ipId', request.ipId)}`, + }, + unmarshalIP, + ) + + protected pageOfListIPs = (request: Readonly = {}) => + this.client.fetch( + { + method: 'GET', + path: `/ipam/v1/regions/${validatePathParam( + 'region', + request.region ?? this.client.settings.defaultRegion, + )}/ips`, + urlParams: urlParams( + ['attached', request.attached], + ['is_ipv6', request.isIpv6], + ['mac_address', request.macAddress], + ['order_by', request.orderBy ?? 'created_at_desc'], + ['organization_id', request.organizationId], + ['page', request.page], + [ + 'page_size', + request.pageSize ?? this.client.settings.defaultPageSize, + ], + ['project_id', request.projectId], + ['resource_id', request.resourceId], + ['resource_name', request.resourceName], + ['resource_type', request.resourceType ?? 'unknown_type'], + ['tags', request.tags], + ...Object.entries( + resolveOneOf([ + { + param: 'zonal', + value: request.zonal, + }, + { + param: 'private_network_id', + value: request.privateNetworkId, + }, + ]), + ), + ), + }, + unmarshalListIPsResponse, + ) + + /** + * List existing IPs. List existing IPs in the specified region using various + * filters. For example, you can filter for IPs within a specified Private + * Network, or for public IPs within a specified Project. By default, the IPs + * returned in the list are ordered by creation date in ascending order, + * though this can be modified via the order_by field. + * + * @param request - The request {@link ListIPsRequest} + * @returns A Promise of ListIPsResponse + */ + listIPs = (request: Readonly = {}) => + enrichForPagination('ips', this.pageOfListIPs, request) +} diff --git a/packages/clients/src/api/ipam/v1/index.gen.ts b/packages/clients/src/api/ipam/v1/index.gen.ts new file mode 100644 index 000000000..7e0df4959 --- /dev/null +++ b/packages/clients/src/api/ipam/v1/index.gen.ts @@ -0,0 +1,17 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +export { API } from './api.gen' +export type { + BookIPRequest, + GetIPRequest, + IP, + ListIPsRequest, + ListIPsRequestOrderBy, + ListIPsResponse, + ReleaseIPRequest, + Resource, + ResourceType, + Source, + UpdateIPRequest, +} from './types.gen' +export * as ValidationRules from './validation-rules.gen' diff --git a/packages/clients/src/api/ipam/v1/marshalling.gen.ts b/packages/clients/src/api/ipam/v1/marshalling.gen.ts new file mode 100644 index 000000000..e0b96ef82 --- /dev/null +++ b/packages/clients/src/api/ipam/v1/marshalling.gen.ts @@ -0,0 +1,119 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +import { + isJSONObject, + resolveOneOf, + unmarshalArrayOfObject, + unmarshalDate, +} from '../../../bridge' +import type { DefaultValues } from '../../../bridge' +import type { + BookIPRequest, + IP, + ListIPsResponse, + Resource, + Source, + UpdateIPRequest, +} from './types.gen' + +const unmarshalResource = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'Resource' failed as data isn't a dictionary.`, + ) + } + + return { + id: data.id, + macAddress: data.mac_address, + name: data.name, + type: data.type, + } as Resource +} + +const unmarshalSource = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'Source' failed as data isn't a dictionary.`, + ) + } + + return { + privateNetworkId: data.private_network_id, + subnetId: data.subnet_id, + zonal: data.zonal, + } as Source +} + +export const unmarshalIP = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'IP' failed as data isn't a dictionary.`, + ) + } + + return { + address: data.address, + createdAt: unmarshalDate(data.created_at), + id: data.id, + isIpv6: data.is_ipv6, + projectId: data.project_id, + region: data.region, + resource: data.resource ? unmarshalResource(data.resource) : undefined, + source: data.source ? unmarshalSource(data.source) : undefined, + tags: data.tags, + updatedAt: unmarshalDate(data.updated_at), + zone: data.zone, + } as IP +} + +export const unmarshalListIPsResponse = (data: unknown) => { + if (!isJSONObject(data)) { + throw new TypeError( + `Unmarshalling the type 'ListIPsResponse' failed as data isn't a dictionary.`, + ) + } + + return { + ips: unmarshalArrayOfObject(data.ips, unmarshalIP), + totalCount: data.total_count, + } as ListIPsResponse +} + +const marshalSource = ( + request: Source, + defaults: DefaultValues, +): Record => ({ + ...resolveOneOf([ + { + param: 'zonal', + value: request.zonal, + }, + { + param: 'private_network_id', + value: request.privateNetworkId, + }, + { + param: 'subnet_id', + value: request.subnetId, + }, + ]), +}) + +export const marshalBookIPRequest = ( + request: BookIPRequest, + defaults: DefaultValues, +): Record => ({ + address: request.address, + is_ipv6: request.isIpv6, + project_id: request.projectId ?? defaults.defaultProjectId, + source: request.source ? marshalSource(request.source, defaults) : undefined, + tags: request.tags, +}) + +export const marshalUpdateIPRequest = ( + request: UpdateIPRequest, + defaults: DefaultValues, +): Record => ({ + tags: request.tags, +}) diff --git a/packages/clients/src/api/ipam/v1/types.gen.ts b/packages/clients/src/api/ipam/v1/types.gen.ts new file mode 100644 index 000000000..d67e4eb2a --- /dev/null +++ b/packages/clients/src/api/ipam/v1/types.gen.ts @@ -0,0 +1,224 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. +import type { Region, Zone } from '../../../bridge' + +export type ListIPsRequestOrderBy = + | 'created_at_desc' + | 'created_at_asc' + | 'updated_at_desc' + | 'updated_at_asc' + | 'attached_at_desc' + | 'attached_at_asc' + +export type ResourceType = + | 'unknown_type' + | 'instance_server' + | 'instance_ip' + | 'instance_private_nic' + | 'lb_server' + | 'fip_ip' + | 'vpc_gateway' + | 'vpc_gateway_network' + | 'k8s_node' + | 'rdb_instance' + | 'redis_cluster' + | 'baremetal_server' + | 'baremetal_private_nic' + +/** Ip. */ +export interface IP { + /** IP ID. */ + id: string + /** IPv4 or IPv6 address in CIDR notation. */ + address: string + /** Scaleway Project the IP belongs to. */ + projectId: string + /** Defines whether the IP is an IPv6 (false = IPv4). */ + isIpv6: boolean + /** Date the IP was booked. */ + createdAt?: Date + /** Date the IP was last modified. */ + updatedAt?: Date + /** Source pool where the IP was booked in. */ + source?: Source + /** Resource which the IP is attached to. */ + resource?: Resource + /** Tags for the IP. */ + tags: string[] + /** Region of the IP. */ + region: Region + /** Zone of the IP, if zonal. */ + zone: Zone +} + +export interface ListIPsResponse { + totalCount: number + ips: IP[] +} + +/** Resource. */ +export interface Resource { + /** Type of resource the IP is attached to. */ + type: ResourceType + /** ID of the resource the IP is attached to. */ + id: string + /** MAC of the resource the IP is attached to. */ + macAddress?: string + /** + * Name of the resource the IP is attached to. When the IP is in a Private + * Network, then a DNS record is available to resolve the resource name to + * this IP. + */ + name?: string +} + +/** Source. */ +export interface Source { + /** + * Zone the IP lives in if the IP is a public zoned IP. This source is global. + * + * One-of ('source'): at most one of 'zonal', 'privateNetworkId', 'subnetId' + * could be set. + */ + zonal?: string + /** + * Private Network the IP lives in if the IP is a private IP. This source is + * specific. + * + * One-of ('source'): at most one of 'zonal', 'privateNetworkId', 'subnetId' + * could be set. + */ + privateNetworkId?: string + /** + * Private Network subnet the IP lives in if the IP is a private IP in a + * Private Network. This source is specific. + * + * One-of ('source'): at most one of 'zonal', 'privateNetworkId', 'subnetId' + * could be set. + */ + subnetId?: string +} + +export type BookIPRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** + * Scaleway Project in which to create the IP. When creating an IP in a + * Private Network, the Project must match the Private Network's Project. + */ + projectId?: string + /** Source in which to book the IP. Not all sources are available for booking. */ + source?: Source + /** Request an IPv6 instead of an IPv4. */ + isIpv6: boolean + /** + * Request a specific IP in the requested source pool. Note that only the + * Private Network source allows you to pick a specific IP. If the requested + * IP is already booked, then the call will fail. + */ + address?: string + /** Tags for the IP. */ + tags?: string[] +} + +export type ReleaseIPRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** IP ID. */ + ipId: string +} + +export type GetIPRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** IP ID. */ + ipId: string +} + +export type UpdateIPRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** IP ID. */ + ipId: string + /** Tags for the IP. */ + tags?: string[] +} + +export type ListIPsRequest = { + /** + * Region to target. If none is passed will use default region from the + * config. + */ + region?: Region + /** Sort order of the returned IPs. */ + orderBy?: ListIPsRequestOrderBy + /** Page number to return, from the paginated results. */ + page?: number + /** Maximum number of IPs to return per page. */ + pageSize?: number + /** + * Project ID to filter for. Only IPs belonging to this Project will be + * returned. + */ + projectId?: string + /** + * Zone to filter for. Only IPs that are zonal, and in this zone, will be + * returned. + * + * One-of ('source'): at most one of 'zonal', 'privateNetworkId' could be set. + */ + zonal?: string + /** + * Private Network to filter for. Only IPs that are private, and in this + * Private Network, will be returned. + * + * One-of ('source'): at most one of 'zonal', 'privateNetworkId' could be set. + */ + privateNetworkId?: string + /** Defines whether to filter only for IPs which are attached to a resource. */ + attached?: boolean + /** + * Resource ID to filter for. Only IPs attached to this resource will be + * returned. + */ + resourceId?: string + /** + * Resource type to filter for. Only IPs attached to this type of resource + * will be returned. + */ + resourceType?: ResourceType + /** + * MAC address to filter for. Only IPs attached to a resource with this MAC + * address will be returned. + */ + macAddress?: string + /** + * Tags to filter for, only IPs with one or more matching tags will be + * returned. + */ + tags?: string[] + /** + * Organization ID to filter for. Only IPs belonging to this Organization will + * be returned. + */ + organizationId?: string + /** Defines whether to filter only for IPv4s or IPv6s. */ + isIpv6?: boolean + /** + * Attached resource name to filter for, only IPs attached to a resource with + * this string within their name will be returned. + */ + resourceName?: string +} diff --git a/packages/clients/src/api/ipam/v1/validation-rules.gen.ts b/packages/clients/src/api/ipam/v1/validation-rules.gen.ts new file mode 100644 index 000000000..01ea03e66 --- /dev/null +++ b/packages/clients/src/api/ipam/v1/validation-rules.gen.ts @@ -0,0 +1,9 @@ +// This file was automatically generated. DO NOT EDIT. +// If you have any remark or suggestion do not hesitate to open an issue. + +export const ListIPsRequest = { + resourceName: { + maxLength: 63, + minLength: 2, + }, +}