diff --git a/go.mod b/go.mod index 8876b03f4..4d25aa255 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.26.4 require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/digitalocean/godo v1.198.0 + github.com/digitalocean/godo v1.203.0 github.com/go-logr/logr v1.4.3 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index c76103d3c..195884c60 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/digitalocean/godo v1.198.0 h1:jylPVf1efxpOZnTOSc3K4a+Qse9pTl/AHu+GExthMNw= -github.com/digitalocean/godo v1.198.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= +github.com/digitalocean/godo v1.203.0 h1:KCyLB/zPjoJbQ7HUtMBWGNwHKpiNsp51QlKjPCIL6Os= +github.com/digitalocean/godo v1.203.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= diff --git a/vendor/github.com/digitalocean/godo/CHANGELOG.md b/vendor/github.com/digitalocean/godo/CHANGELOG.md index 5b8b65dc3..d74659a72 100644 --- a/vendor/github.com/digitalocean/godo/CHANGELOG.md +++ b/vendor/github.com/digitalocean/godo/CHANGELOG.md @@ -1,5 +1,29 @@ # Change Log +## [1.203.0] - 2026-08-05 + +- #1076 - @rak16 - microdroplets: add image region, fix image URN, drop https protocol + +## [1.202.0] - 2026-07-29 + +- #1069 - @varshavaradarajan - doks: add isolated workers to kubernetes create call +- #1067 - @nveerdixit - MARSOHS-551: Session.origin on HostedAgents (stack on OHS_endpoints) + +## [1.201.0] - 2026-07-24 + +- #1060 - @DO-rrao - Add GPU partition mode support to Droplets and Sizes + +## [1.200.0] - 2026-07-22 + +- #1058 - @kwadhwa-source - MDROP-23:add godo support for microdroplets +- #1061 - @gangasingh01 - added support for ADVANCED MySQL config patch and get operations +- #1059 - @johannaratliff - Add VPCSubnetUUID support for LoadBalancer +- #1053 - @rbhatia-code - support byoip for load balancer and nat-gateway + +## [1.199.0] - 2026-07-15 + +- #1052 - @llDrLove - CON-13386 Add P2pOciRegistry plugin information to Kubernetes api calls (Create, Update, Get) + ## [1.198.0] - 2026-07-07 - #1043 - @johannaratliff - Support subnet_uuid in vpcnatgateway diff --git a/vendor/github.com/digitalocean/godo/databases.go b/vendor/github.com/digitalocean/godo/databases.go index 2c9bbb763..808f729ea 100644 --- a/vendor/github.com/digitalocean/godo/databases.go +++ b/vendor/github.com/digitalocean/godo/databases.go @@ -171,6 +171,7 @@ type DatabasesService interface { GetOpensearchConfig(context.Context, string) (*OpensearchConfig, *Response, error) GetKafkaConfig(context.Context, string) (*KafkaConfig, *Response, error) GetAdvancedPostgresSQLConfig(context.Context, string) (*AdvancedPostgresConfig, *Response, error) + GetAdvancedMySQLConfig(context.Context, string) (*AdvancedMySQLConfig, *Response, error) UpdatePostgreSQLConfig(context.Context, string, *PostgreSQLConfig) (*Response, error) UpdateRedisConfig(context.Context, string, *RedisConfig) (*Response, error) UpdateValkeyConfig(context.Context, string, *ValkeyConfig) (*Response, error) @@ -179,6 +180,7 @@ type DatabasesService interface { UpdateOpensearchConfig(context.Context, string, *OpensearchConfig) (*Response, error) UpdateKafkaConfig(context.Context, string, *KafkaConfig) (*Response, error) UpdateAdvancedPostgresSQLConfig(context.Context, string, *AdvancedPostgresConfigUpdate) (*Response, error) + UpdateAdvancedMySQLConfig(context.Context, string, *AdvancedMySQLConfigUpdate) (*Response, error) ListOptions(todo context.Context) (*DatabaseOptions, *Response, error) UpgradeMajorVersion(context.Context, string, *UpgradeVersionRequest) (*Response, error) ListTopics(context.Context, string, *ListOptions) ([]DatabaseTopic, *Response, error) @@ -760,6 +762,25 @@ type AdvancedPostgresConfigUpdate struct { PGParameters map[string]string `json:"pg_parameters,omitempty"` } +// AdvancedMySQLParameter is one system variable returned by GET /config for advanced_mysql clusters. +type AdvancedMySQLParameter struct { + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` + Description string `json:"description,omitempty"` + RequiresRestart bool `json:"requires_restart,omitempty"` + DefaultValue string `json:"default_value,omitempty"` +} + +// AdvancedMySQLConfig holds advanced configurations for advanced_mysql database clusters. +type AdvancedMySQLConfig struct { + MySQLParameters []AdvancedMySQLParameter `json:"mysql_parameters,omitempty"` +} + +// AdvancedMySQLConfigUpdate is the PATCH payload for advanced_mysql database clusters. +type AdvancedMySQLConfigUpdate struct { + MySQLParameters map[string]string `json:"mysql_parameters,omitempty"` +} + // PostgreSQLBouncerConfig configuration type PostgreSQLBouncerConfig struct { ServerResetQueryAlways *bool `json:"server_reset_query_always,omitempty"` @@ -984,6 +1005,14 @@ type databaseAdvancedPostgresConfigUpdateRoot struct { Config *AdvancedPostgresConfigUpdate `json:"config"` } +type databaseAdvancedMySQLConfigRoot struct { + Config *AdvancedMySQLConfig `json:"config"` +} + +type databaseAdvancedMySQLConfigUpdateRoot struct { + Config *AdvancedMySQLConfigUpdate `json:"config"` +} + type databaseBackupsRoot struct { Backups []DatabaseBackup `json:"backups"` } @@ -2017,6 +2046,38 @@ func (svc *DatabasesServiceOp) UpdateAdvancedPostgresSQLConfig(ctx context.Conte return resp, nil } +// GetAdvancedMySQLConfig retrieves the config for an advanced_mysql database cluster. +func (svc *DatabasesServiceOp) GetAdvancedMySQLConfig(ctx context.Context, databaseID string) (*AdvancedMySQLConfig, *Response, error) { + path := fmt.Sprintf(databaseConfigPath, databaseID) + req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + root := new(databaseAdvancedMySQLConfigRoot) + resp, err := svc.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Config, resp, nil +} + +// UpdateAdvancedMySQLConfig updates the config for an advanced_mysql database cluster. +func (svc *DatabasesServiceOp) UpdateAdvancedMySQLConfig(ctx context.Context, databaseID string, config *AdvancedMySQLConfigUpdate) (*Response, error) { + path := fmt.Sprintf(databaseConfigPath, databaseID) + root := &databaseAdvancedMySQLConfigUpdateRoot{ + Config: config, + } + req, err := svc.client.NewRequest(ctx, http.MethodPatch, path, root) + if err != nil { + return nil, err + } + resp, err := svc.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + // GetOpensearchConfig retrieves the config for a Opensearch database cluster. func (svc *DatabasesServiceOp) GetOpensearchConfig(ctx context.Context, databaseID string) (*OpensearchConfig, *Response, error) { path := fmt.Sprintf(databaseConfigPath, databaseID) diff --git a/vendor/github.com/digitalocean/godo/droplets.go b/vendor/github.com/digitalocean/godo/droplets.go index bb40ee5e4..3886fd956 100644 --- a/vendor/github.com/digitalocean/godo/droplets.go +++ b/vendor/github.com/digitalocean/godo/droplets.go @@ -44,6 +44,14 @@ type DropletsServiceOp struct { var _ DropletsService = &DropletsServiceOp{} +// GPU partition modes supported when creating a GPU Droplet. Omitting the value +// (or sending an empty string) is treated as PARTITION_MODE_UNSET, i.e. a full +// GPU with SPX/NPS1 behavior. +const ( + GPUPartitionModeSPXNPS1 = "PARTITION_MODE_SPX_NPS1" + GPUPartitionModeDPXNPS2 = "PARTITION_MODE_DPX_NPS2" +) + // Droplet represents a DigitalOcean Droplet type Droplet struct { ID int `json:"id,float64,omitempty"` @@ -67,6 +75,10 @@ type Droplet struct { Tags []string `json:"tags,omitempty"` VolumeIDs []string `json:"volume_ids"` VPCUUID string `json:"vpc_uuid,omitempty"` + // GPUPartitionMode is echoed back on create when the Droplet was created + // with a partitioned GPU. Note: read-back on droplet GET is not delivered in + // v1, so this is only reliably populated on the create response. + GPUPartitionMode string `json:"gpu_partition_mode,omitempty"` } // PublicIPv4 returns the public IPv4 address for the Droplet. @@ -238,6 +250,10 @@ type DropletCreateRequest struct { WithDropletAgent *bool `json:"with_droplet_agent,omitempty"` BackupPolicy *DropletBackupPolicyRequest `json:"backup_policy,omitempty"` PublicNetworking *bool `json:"public_networking,omitempty"` + // GPUPartitionMode selects the partition mode for a GPU Droplet. Omit or + // leave empty for PARTITION_MODE_UNSET (full GPU). Use one of the + // GPUPartitionMode* constants for supported values. + GPUPartitionMode string `json:"gpu_partition_mode,omitempty"` } // DropletMultiCreateRequest is a request to create multiple Droplets. @@ -257,6 +273,10 @@ type DropletMultiCreateRequest struct { WithDropletAgent *bool `json:"with_droplet_agent,omitempty"` BackupPolicy *DropletBackupPolicyRequest `json:"backup_policy,omitempty"` PublicNetworking *bool `json:"public_networking,omitempty"` + // GPUPartitionMode selects the partition mode for the GPU Droplets. Omit or + // leave empty for PARTITION_MODE_UNSET (full GPU). Use one of the + // GPUPartitionMode* constants for supported values. + GPUPartitionMode string `json:"gpu_partition_mode,omitempty"` } // DropletBackupPolicyRequest defines the backup policy when creating a Droplet. diff --git a/vendor/github.com/digitalocean/godo/godo.go b/vendor/github.com/digitalocean/godo/godo.go index f32ae97a8..3aec96527 100644 --- a/vendor/github.com/digitalocean/godo/godo.go +++ b/vendor/github.com/digitalocean/godo/godo.go @@ -21,7 +21,7 @@ import ( ) const ( - libraryVersion = "1.198.0" + libraryVersion = "1.203.0" defaultBaseURL = "https://api.digitalocean.com/" userAgent = "godo/" + libraryVersion mediaType = "application/json" @@ -77,6 +77,8 @@ type Client struct { Keys KeysService Kubernetes KubernetesService LoadBalancers LoadBalancersService + MicroDroplets MicroDropletsService + MicroDropletImages MicroDropletImagesService Monitoring MonitoringService Security SecurityService Secrets SecretsService @@ -319,6 +321,8 @@ func NewClient(httpClient *http.Client) *Client { c.Keys = &KeysServiceOp{client: c} c.Kubernetes = &KubernetesServiceOp{client: c} c.LoadBalancers = &LoadBalancersServiceOp{client: c} + c.MicroDroplets = &MicroDropletsServiceOp{client: c} + c.MicroDropletImages = &MicroDropletImagesServiceOp{client: c} c.Monitoring = &MonitoringServiceOp{client: c} c.Security = &SecurityServiceOp{client: c} c.Secrets = &SecretsServiceOp{client: c} diff --git a/vendor/github.com/digitalocean/godo/kubernetes.go b/vendor/github.com/digitalocean/godo/kubernetes.go index 039839369..609ffd06c 100644 --- a/vendor/github.com/digitalocean/godo/kubernetes.go +++ b/vendor/github.com/digitalocean/godo/kubernetes.go @@ -92,9 +92,16 @@ type KubernetesClusterCreateRequest struct { AmdGpuDevicePlugin *KubernetesAmdGpuDevicePlugin `json:"amd_gpu_device_plugin,omitempty"` AmdGpuDeviceMetricsExporterPlugin *KubernetesAmdGpuDeviceMetricsExporterPlugin `json:"amd_gpu_device_metrics_exporter_plugin,omitempty"` NvidiaGpuDevicePlugin *KubernetesNvidiaGpuDevicePlugin `json:"nvidia_gpu_device_plugin,omitempty"` + NvidiaGpuDraDriver *KubernetesNvidiaGpuDraDriver `json:"nvidia_gpu_dra_driver,omitempty"` + AmdGpuDraDriver *KubernetesAmdGpuDraDriver `json:"amd_gpu_dra_driver,omitempty"` RdmaSharedDevicePlugin *KubernetesRdmaSharedDevicePlugin `json:"rdma_shared_dev_plugin,omitempty"` CorednsAutoscaler *KubernetesCorednsAutoscaler `json:"coredns_autoscaler,omitempty"` SSO *KubernetesClusterSSO `json:"sso,omitempty"` + P2pOciRegistryPlugin *KubernetesP2pOciRegistry `json:"p2p_oci_registry_plugin,omitempty"` + // IsolatedWorkers enables isolated worker nodes. When true, the cluster's VPC + // must already have a NAT gateway attached, or the create request fails with a + // 422. This can only be set at creation time. + IsolatedWorkers bool `json:"isolated_workers,omitempty"` } // KubernetesClusterUpdateRequest represents a request to update a Kubernetes cluster. @@ -110,9 +117,12 @@ type KubernetesClusterUpdateRequest struct { AmdGpuDevicePlugin *KubernetesAmdGpuDevicePlugin `json:"amd_gpu_device_plugin,omitempty"` AmdGpuDeviceMetricsExporterPlugin *KubernetesAmdGpuDeviceMetricsExporterPlugin `json:"amd_gpu_device_metrics_exporter_plugin,omitempty"` NvidiaGpuDevicePlugin *KubernetesNvidiaGpuDevicePlugin `json:"nvidia_gpu_device_plugin,omitempty"` + NvidiaGpuDraDriver *KubernetesNvidiaGpuDraDriver `json:"nvidia_gpu_dra_driver,omitempty"` + AmdGpuDraDriver *KubernetesAmdGpuDraDriver `json:"amd_gpu_dra_driver,omitempty"` RdmaSharedDevicePlugin *KubernetesRdmaSharedDevicePlugin `json:"rdma_shared_dev_plugin,omitempty"` CorednsAutoscaler *KubernetesCorednsAutoscaler `json:"coredns_autoscaler,omitempty"` SSO *KubernetesClusterSSO `json:"sso,omitempty"` + P2pOciRegistryPlugin *KubernetesP2pOciRegistry `json:"p2p_oci_registry_plugin,omitempty"` // Convert cluster to run highly available control plane HA *bool `json:"ha,omitempty"` @@ -145,18 +155,26 @@ func (t Taint) String() string { return fmt.Sprintf("%s=%s:%s", t.Key, t.Value, t.Effect) } +// Kubernetes GPU partition modes for AMD GPU node pools. Omitting the value +// (or sending an empty string) leaves the pool unpartitioned. +const ( + KubernetesAMDPartitionModeSPXNPS1 = "AMD_PARTITION_MODE_SPX_NPS1" + KubernetesAMDPartitionModeDPXNPS2 = "AMD_PARTITION_MODE_DPX_NPS2" +) + // KubernetesNodePoolCreateRequest represents a request to create a node pool for a // Kubernetes cluster. type KubernetesNodePoolCreateRequest struct { - Name string `json:"name,omitempty"` - Size string `json:"size,omitempty"` - Count int `json:"count,omitempty"` - Tags []string `json:"tags,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Taints []Taint `json:"taints,omitempty"` - AutoScale bool `json:"auto_scale,omitempty"` - MinNodes int `json:"min_nodes,omitempty"` - MaxNodes int `json:"max_nodes,omitempty"` + Name string `json:"name,omitempty"` + Size string `json:"size,omitempty"` + Count int `json:"count,omitempty"` + Tags []string `json:"tags,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Taints []Taint `json:"taints,omitempty"` + AutoScale bool `json:"auto_scale,omitempty"` + MinNodes int `json:"min_nodes,omitempty"` + MaxNodes int `json:"max_nodes,omitempty"` + GPUPartitionMode string `json:"gpu_partition_mode,omitempty"` } // KubernetesNodePoolUpdateRequest represents a request to update a node pool in a @@ -255,9 +273,13 @@ type KubernetesCluster struct { AmdGpuDevicePlugin *KubernetesAmdGpuDevicePlugin `json:"amd_gpu_device_plugin,omitempty"` AmdGpuDeviceMetricsExporterPlugin *KubernetesAmdGpuDeviceMetricsExporterPlugin `json:"amd_gpu_device_metrics_exporter_plugin,omitempty"` NvidiaGpuDevicePlugin *KubernetesNvidiaGpuDevicePlugin `json:"nvidia_gpu_device_plugin,omitempty"` + NvidiaGpuDraDriver *KubernetesNvidiaGpuDraDriver `json:"nvidia_gpu_dra_driver,omitempty"` + AmdGpuDraDriver *KubernetesAmdGpuDraDriver `json:"amd_gpu_dra_driver,omitempty"` RdmaSharedDevicePlugin *KubernetesRdmaSharedDevicePlugin `json:"rdma_shared_dev_plugin,omitempty"` CorednsAutoscaler *KubernetesCorednsAutoscaler `json:"coredns_autoscaler,omitempty"` SSO *KubernetesClusterSSO `json:"sso,omitempty"` + P2pOciRegistryPlugin *KubernetesP2pOciRegistry `json:"p2p_oci_registry_plugin,omitempty"` + IsolatedWorkers bool `json:"isolated_workers,omitempty"` Status *KubernetesClusterStatus `json:"status,omitempty"` CreatedAt time.Time `json:"created_at,omitempty"` @@ -329,6 +351,18 @@ type KubernetesNvidiaGpuDevicePlugin struct { Enabled *bool `json:"enabled"` } +// KubernetesNvidiaGpuDraDriver represents information about the NVIDIA GPU DRA Driver cluster plugin. +// Mutually exclusive with the NVIDIA GPU Device Plugin. +type KubernetesNvidiaGpuDraDriver struct { + Enabled *bool `json:"enabled"` +} + +// KubernetesAmdGpuDraDriver represents information about the AMD GPU DRA Driver cluster plugin. +// Mutually exclusive with the AMD GPU Device Plugin. +type KubernetesAmdGpuDraDriver struct { + Enabled *bool `json:"enabled"` +} + // KubernetesRdmaSharedDevicePlugin represents information about the rdma-shared-dev cluster plugin. // If a cluster has a multi-node GPU ready slug it will be enabled by default. type KubernetesRdmaSharedDevicePlugin struct { @@ -340,6 +374,11 @@ type KubernetesCorednsAutoscaler struct { Enabled *bool `json:"enabled"` } +// KubernetesP2pOciRegistry represents information about the Peer-to-peer OCI registry cluster plugin. +type KubernetesP2pOciRegistry struct { + Enabled *bool `json:"enabled"` +} + // KubernetesClusterSSO configures Single Sign-On (SSO) for a Kubernetes cluster. type KubernetesClusterSSO struct { Enabled bool `json:"enabled"` @@ -499,16 +538,17 @@ type KubernetesClusterStatus struct { // KubernetesNodePool represents a node pool in a Kubernetes cluster. type KubernetesNodePool struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Size string `json:"size,omitempty"` - Count int `json:"count,omitempty"` - Tags []string `json:"tags,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Taints []Taint `json:"taints,omitempty"` - AutoScale bool `json:"auto_scale,omitempty"` - MinNodes int `json:"min_nodes,omitempty"` - MaxNodes int `json:"max_nodes,omitempty"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Size string `json:"size,omitempty"` + Count int `json:"count,omitempty"` + Tags []string `json:"tags,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Taints []Taint `json:"taints,omitempty"` + AutoScale bool `json:"auto_scale,omitempty"` + MinNodes int `json:"min_nodes,omitempty"` + MaxNodes int `json:"max_nodes,omitempty"` + GPUPartitionMode string `json:"gpu_partition_mode,omitempty"` Nodes []*KubernetesNode `json:"nodes,omitempty"` } diff --git a/vendor/github.com/digitalocean/godo/load_balancers.go b/vendor/github.com/digitalocean/godo/load_balancers.go index 11d8d35bc..6a7355cb1 100644 --- a/vendor/github.com/digitalocean/godo/load_balancers.go +++ b/vendor/github.com/digitalocean/godo/load_balancers.go @@ -75,6 +75,7 @@ type LoadBalancer struct { EnableProxyProtocol bool `json:"enable_proxy_protocol,omitempty"` EnableBackendKeepalive bool `json:"enable_backend_keepalive,omitempty"` VPCUUID string `json:"vpc_uuid,omitempty"` + VPCSubnetUUID string `json:"subnet_uuid,omitempty"` DisableLetsEncryptDNSRecords *bool `json:"disable_lets_encrypt_dns_records,omitempty"` ValidateOnly bool `json:"validate_only,omitempty"` ProjectID string `json:"project_id,omitempty"` @@ -114,6 +115,7 @@ func (l LoadBalancer) AsRequest() *LoadBalancerRequest { EnableProxyProtocol: l.EnableProxyProtocol, EnableBackendKeepalive: l.EnableBackendKeepalive, VPCUUID: l.VPCUUID, + VPCSubnetUUID: l.VPCSubnetUUID, DisableLetsEncryptDNSRecords: l.DisableLetsEncryptDNSRecords, ValidateOnly: l.ValidateOnly, ProjectID: l.ProjectID, @@ -252,6 +254,7 @@ type LoadBalancerRequest struct { EnableProxyProtocol bool `json:"enable_proxy_protocol,omitempty"` EnableBackendKeepalive bool `json:"enable_backend_keepalive,omitempty"` VPCUUID string `json:"vpc_uuid,omitempty"` + VPCSubnetUUID string `json:"subnet_uuid,omitempty"` DisableLetsEncryptDNSRecords *bool `json:"disable_lets_encrypt_dns_records,omitempty"` ValidateOnly bool `json:"validate_only,omitempty"` ProjectID string `json:"project_id,omitempty"` @@ -263,6 +266,9 @@ type LoadBalancerRequest struct { Network string `json:"network,omitempty"` NetworkStack string `json:"network_stack,omitempty"` TLSCipherPolicy string `json:"tls_cipher_policy,omitempty"` + // IP is an optional BYOIP address to assign on create. When omitted, a + // system-allocated floating IP is provisioned. Create-only; not used on update. + IP string `json:"ip,omitempty"` } // String creates a human-readable description of a LoadBalancerRequest. diff --git a/vendor/github.com/digitalocean/godo/micro_droplet_images.go b/vendor/github.com/digitalocean/godo/micro_droplet_images.go new file mode 100644 index 000000000..10c50d6b5 --- /dev/null +++ b/vendor/github.com/digitalocean/godo/micro_droplet_images.go @@ -0,0 +1,170 @@ +package godo + +import ( + "context" + "fmt" + "net/http" +) + +const microDropletImageBasePath = "v2/microdroplets/images" + +// MicroDropletImageStatus represents the lifecycle status of a MicroDroplet image. +type MicroDropletImageStatus string + +// Possible states for a MicroDroplet image. +const ( + MicroDropletImageStatusUnknown = MicroDropletImageStatus("IMAGE_UNKNOWN") + MicroDropletImageStatusImporting = MicroDropletImageStatus("IMAGE_IMPORTING") + MicroDropletImageStatusAvailable = MicroDropletImageStatus("IMAGE_AVAILABLE") + MicroDropletImageStatusFailed = MicroDropletImageStatus("IMAGE_FAILED") + MicroDropletImageStatusDeleted = MicroDropletImageStatus("IMAGE_DELETED") +) + +// MicroDropletImagesService is an interface for interfacing with the +// MicroDroplet image endpoints of the DigitalOcean API. +// See: https://docs.digitalocean.com/reference/api/api-reference/#tag/MicroDroplets +type MicroDropletImagesService interface { + List(ctx context.Context, opt *ListOptions) ([]MicroDropletImage, *Response, error) + Get(ctx context.Context, id string) (*MicroDropletImage, *Response, error) + Create(ctx context.Context, createRequest *MicroDropletImageCreateRequest) (*MicroDropletImage, *Response, error) + Delete(ctx context.Context, id string) (*Response, error) +} + +// MicroDropletImagesServiceOp handles communication with the MicroDroplet +// image related methods of the DigitalOcean API. +type MicroDropletImagesServiceOp struct { + client *Client +} + +var _ MicroDropletImagesService = &MicroDropletImagesServiceOp{} + +// MicroDropletImage represents an OCI image imported for use with MicroDroplets. +type MicroDropletImage struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Region string `json:"region,omitempty"` + Source string `json:"source,omitempty"` + Status MicroDropletImageStatus `json:"status,omitempty"` + Created string `json:"created_at,omitempty"` +} + +// MicroDropletImageCreateRequest represents a request to import a new +// MicroDroplet image from a public OCI ref or a DOCR ref. +type MicroDropletImageCreateRequest struct { + Name string `json:"name"` + Region string `json:"region"` + Source string `json:"source"` +} + +// String returns a human-readable description of a MicroDropletImage. +func (i MicroDropletImage) String() string { + return Stringify(i) +} + +// URN returns the MicroDropletImage ID in a valid DO API URN form. +func (i MicroDropletImage) URN() string { + return ToURN("microdroplet_image", i.ID) +} + +// String returns a human-readable description of a MicroDropletImageCreateRequest. +func (r MicroDropletImageCreateRequest) String() string { + return Stringify(r) +} + +type microDropletImageRoot struct { + Image *MicroDropletImage `json:"image"` +} + +type microDropletImagesRoot struct { + Images []MicroDropletImage `json:"images"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +// List lists all MicroDroplet images, with optional pagination. +func (s *MicroDropletImagesServiceOp) List(ctx context.Context, opt *ListOptions) ([]MicroDropletImage, *Response, error) { + path, err := addOptions(microDropletImageBasePath, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(microDropletImagesRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root.Images, resp, nil +} + +// Get retrieves a MicroDroplet image by its ID. +func (s *MicroDropletImagesServiceOp) Get(ctx context.Context, id string) (*MicroDropletImage, *Response, error) { + if id == "" { + return nil, nil, NewArgError("id", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s", microDropletImageBasePath, id) + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(microDropletImageRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Image, resp, nil +} + +// Create imports a new MicroDroplet image from an OCI ref. Image import is +// asynchronous; callers should poll Get and inspect Status until it reports +// MicroDropletImageStatusAvailable or MicroDropletImageStatusFailed. +func (s *MicroDropletImagesServiceOp) Create(ctx context.Context, createRequest *MicroDropletImageCreateRequest) (*MicroDropletImage, *Response, error) { + if createRequest == nil { + return nil, nil, NewArgError("createRequest", "cannot be nil") + } + + req, err := s.client.NewRequest(ctx, http.MethodPost, microDropletImageBasePath, createRequest) + if err != nil { + return nil, nil, err + } + + root := new(microDropletImageRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Image, resp, nil +} + +// Delete removes a MicroDroplet image by its ID. The DigitalOcean API returns +// a 204 on success and does not include a response body. +func (s *MicroDropletImagesServiceOp) Delete(ctx context.Context, id string) (*Response, error) { + if id == "" { + return nil, NewArgError("id", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s", microDropletImageBasePath, id) + + req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/digitalocean/godo/micro_droplets.go b/vendor/github.com/digitalocean/godo/micro_droplets.go new file mode 100644 index 000000000..2d68d364e --- /dev/null +++ b/vendor/github.com/digitalocean/godo/micro_droplets.go @@ -0,0 +1,358 @@ +package godo + +import ( + "context" + "fmt" + "net/http" +) + +const microDropletBasePath = "v2/microdroplets/instances" + +// MicroDropletState represents the lifecycle state of a MicroDroplet. +type MicroDropletState string + +// Possible lifecycle states for a MicroDroplet. +const ( + MicroDropletStateUnknown = MicroDropletState("unknown") + MicroDropletStateCreating = MicroDropletState("creating") + MicroDropletStateRunning = MicroDropletState("running") + MicroDropletStatePausing = MicroDropletState("pausing") + MicroDropletStatePaused = MicroDropletState("paused") + MicroDropletStateResuming = MicroDropletState("resuming") + MicroDropletStateTerminating = MicroDropletState("terminating") + MicroDropletStateTerminated = MicroDropletState("terminated") + MicroDropletStateFailed = MicroDropletState("failed") +) + +// MicroDropletNetworking represents the networking mode of a MicroDroplet. +type MicroDropletNetworking string + +// Possible networking modes for a MicroDroplet. +const ( + MicroDropletNetworkingUnknown = MicroDropletNetworking("unknown") + MicroDropletNetworkingPublic = MicroDropletNetworking("public") + MicroDropletNetworkingVPC = MicroDropletNetworking("vpc") +) + +// MicroDropletHTTPProtocol represents the HTTP protocol option for a MicroDroplet. +type MicroDropletHTTPProtocol string + +// Possible HTTP protocol values for a MicroDroplet. +const ( + MicroDropletHTTPProtocolHTTP = MicroDropletHTTPProtocol("http") + MicroDropletHTTPProtocolHTTP2 = MicroDropletHTTPProtocol("http2") +) + +// MicroDropletCheckpointStatus represents the status of a MicroDroplet checkpoint. +type MicroDropletCheckpointStatus string + +// Possible states for a MicroDroplet checkpoint. +const ( + MicroDropletCheckpointStatusUnknown = MicroDropletCheckpointStatus("CHECKPOINT_UNKNOWN") + MicroDropletCheckpointStatusCreating = MicroDropletCheckpointStatus("CHECKPOINT_CREATING") + MicroDropletCheckpointStatusAvailable = MicroDropletCheckpointStatus("CHECKPOINT_AVAILABLE") + MicroDropletCheckpointStatusFailed = MicroDropletCheckpointStatus("CHECKPOINT_FAILED") + MicroDropletCheckpointStatusDeleted = MicroDropletCheckpointStatus("CHECKPOINT_DELETED") +) + +// MicroDropletsService is an interface for interfacing with the MicroDroplet +// endpoints of the DigitalOcean API. +// See: https://docs.digitalocean.com/reference/api/api-reference/#tag/MicroDroplets +type MicroDropletsService interface { + List(ctx context.Context, opt *ListOptions) ([]MicroDroplet, *Response, error) + ListByRegion(ctx context.Context, region string, opt *ListOptions) ([]MicroDroplet, *Response, error) + ListByName(ctx context.Context, name string, opt *ListOptions) ([]MicroDroplet, *Response, error) + Get(ctx context.Context, id string) (*MicroDroplet, *Response, error) + Create(ctx context.Context, createRequest *MicroDropletCreateRequest) (*MicroDroplet, *Response, error) + Pause(ctx context.Context, id string) (*MicroDroplet, *Response, error) + Resume(ctx context.Context, id string) (*MicroDroplet, *Response, error) + Delete(ctx context.Context, id string) (*Response, error) + ListCheckpoints(ctx context.Context, id string, opt *ListOptions) ([]MicroDropletCheckpoint, *Response, error) +} + +// MicroDropletsServiceOp handles communication with the MicroDroplet related +// methods of the DigitalOcean API. +type MicroDropletsServiceOp struct { + client *Client +} + +var _ MicroDropletsService = &MicroDropletsServiceOp{} + +// MicroDroplet represents a DigitalOcean MicroDroplet. +type MicroDroplet struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Region string `json:"region,omitempty"` + State MicroDropletState `json:"state,omitempty"` + Size string `json:"size,omitempty"` + Networking MicroDropletNetworking `json:"networking,omitempty"` + Image string `json:"image,omitempty"` + Endpoint string `json:"endpoint,omitempty"` + AutoPause *AutoPauseConfig `json:"auto_pause,omitempty"` + AutoResume *bool `json:"auto_resume,omitempty"` + Created string `json:"created_at,omitempty"` +} + +// AutoPauseConfig configures MicroDroplet auto-pause behavior. IdleTimeout is +// a Go duration string (e.g. "5m", "30s") describing how long the MicroDroplet +// must be idle before it is paused. +type AutoPauseConfig struct { + Enabled *bool `json:"enabled,omitempty"` + IdleTimeout string `json:"idle_timeout,omitempty"` +} + +// MicroDropletCheckpoint represents a checkpoint of a MicroDroplet +// (persisted memory + disk state), captured automatically when the +// MicroDroplet is paused. +type MicroDropletCheckpoint struct { + ID string `json:"id,omitempty"` + MicroDropletID string `json:"micro_droplet_id,omitempty"` + Status MicroDropletCheckpointStatus `json:"status,omitempty"` + Name string `json:"name,omitempty"` + MemoryBytes uint64 `json:"memory_bytes,omitempty"` + DiskBytes uint64 `json:"disk_bytes,omitempty"` + Created string `json:"created_at,omitempty"` +} + +// MicroDropletCreateRequest represents a request to create a MicroDroplet. +type MicroDropletCreateRequest struct { + Name string `json:"name"` + Region string `json:"region"` + Size string `json:"size"` + Image string `json:"image"` + Networking MicroDropletNetworking `json:"networking,omitempty"` + VPCUUID string `json:"vpc_uuid,omitempty"` + AutoPause *AutoPauseConfig `json:"auto_pause,omitempty"` + AutoResume *bool `json:"auto_resume,omitempty"` + HTTPPort uint32 `json:"http_port,omitempty"` + HTTPProtocol MicroDropletHTTPProtocol `json:"http_protocol,omitempty"` + Environment map[string]string `json:"environment,omitempty"` + Tags []string `json:"tags,omitempty"` +} + +// String returns a human-readable description of a MicroDroplet. +func (m MicroDroplet) String() string { + return Stringify(m) +} + +// URN returns the MicroDroplet ID in a valid DO API URN form. +func (m MicroDroplet) URN() string { + return ToURN("MicroDroplet", m.ID) +} + +// String returns a human-readable description of a MicroDropletCheckpoint. +func (c MicroDropletCheckpoint) String() string { + return Stringify(c) +} + +// String returns a human-readable description of a MicroDropletCreateRequest. +func (r MicroDropletCreateRequest) String() string { + return Stringify(r) +} + +type microDropletRoot struct { + MicroDroplet *MicroDroplet `json:"micro_droplet"` +} + +type microDropletsRoot struct { + MicroDroplets []MicroDroplet `json:"micro_droplets"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +type microDropletCheckpointsRoot struct { + Checkpoints []MicroDropletCheckpoint `json:"checkpoints"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +// listMicroDropletOptions holds MicroDroplet-specific list filters that are +// not part of the shared ListOptions. +type listMicroDropletOptions struct { + Region string `url:"region,omitempty"` + Name string `url:"name,omitempty"` +} + +// List lists all MicroDroplets, with optional pagination. +func (s *MicroDropletsServiceOp) List(ctx context.Context, opt *ListOptions) ([]MicroDroplet, *Response, error) { + return s.list(ctx, opt, nil) +} + +// ListByRegion lists MicroDroplets filtered by region slug, with optional pagination. +func (s *MicroDropletsServiceOp) ListByRegion(ctx context.Context, region string, opt *ListOptions) ([]MicroDroplet, *Response, error) { + if region == "" { + return nil, nil, NewArgError("region", "cannot be empty") + } + return s.list(ctx, opt, &listMicroDropletOptions{Region: region}) +} + +// ListByName lists MicroDroplets filtered by exact name match, with optional pagination. +func (s *MicroDropletsServiceOp) ListByName(ctx context.Context, name string, opt *ListOptions) ([]MicroDroplet, *Response, error) { + if name == "" { + return nil, nil, NewArgError("name", "cannot be empty") + } + return s.list(ctx, opt, &listMicroDropletOptions{Name: name}) +} + +func (s *MicroDropletsServiceOp) list(ctx context.Context, opt *ListOptions, listOpt *listMicroDropletOptions) ([]MicroDroplet, *Response, error) { + path := microDropletBasePath + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + path, err = addOptions(path, listOpt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(microDropletsRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root.MicroDroplets, resp, nil +} + +// Get retrieves a MicroDroplet by its ID. +func (s *MicroDropletsServiceOp) Get(ctx context.Context, id string) (*MicroDroplet, *Response, error) { + if id == "" { + return nil, nil, NewArgError("id", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s", microDropletBasePath, id) + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(microDropletRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.MicroDroplet, resp, nil +} + +// Create provisions a new MicroDroplet with the provided configuration. +func (s *MicroDropletsServiceOp) Create(ctx context.Context, createRequest *MicroDropletCreateRequest) (*MicroDroplet, *Response, error) { + if createRequest == nil { + return nil, nil, NewArgError("createRequest", "cannot be nil") + } + + req, err := s.client.NewRequest(ctx, http.MethodPost, microDropletBasePath, createRequest) + if err != nil { + return nil, nil, err + } + + root := new(microDropletRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.MicroDroplet, resp, nil +} + +// Pause synchronously transitions a RUNNING MicroDroplet to PAUSED. It blocks +// until the platform has durably paused the MicroDroplet and returns the +// updated resource. The call is idempotent: pausing a MicroDroplet that is +// already PAUSED returns the current MicroDroplet with no side effects. +func (s *MicroDropletsServiceOp) Pause(ctx context.Context, id string) (*MicroDroplet, *Response, error) { + return s.doTransition(ctx, id, "pause") +} + +// Resume synchronously transitions a PAUSED MicroDroplet to RUNNING. It blocks +// until the platform has durably resumed the MicroDroplet and returns the +// updated resource. The call is idempotent: resuming a MicroDroplet that is +// already RUNNING returns the current MicroDroplet with no side effects. +func (s *MicroDropletsServiceOp) Resume(ctx context.Context, id string) (*MicroDroplet, *Response, error) { + return s.doTransition(ctx, id, "resume") +} + +// doTransition posts an empty body to a MicroDroplet transition sub-resource +// (e.g. /pause, /resume) and decodes the returned MicroDroplet. +func (s *MicroDropletsServiceOp) doTransition(ctx context.Context, id, action string) (*MicroDroplet, *Response, error) { + if id == "" { + return nil, nil, NewArgError("id", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s/%s", microDropletBasePath, id, action) + + req, err := s.client.NewRequest(ctx, http.MethodPost, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(microDropletRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.MicroDroplet, resp, nil +} + +// Delete removes a MicroDroplet by its ID. The DigitalOcean API returns a 204 +// on success and does not include a response body. +func (s *MicroDropletsServiceOp) Delete(ctx context.Context, id string) (*Response, error) { + if id == "" { + return nil, NewArgError("id", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s", microDropletBasePath, id) + + req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListCheckpoints lists checkpoints that belong to a MicroDroplet. +// Checkpoints are captured automatically by DigitalOcean when a MicroDroplet +// is paused; each one preserves the memory and disk state required to resume. +func (s *MicroDropletsServiceOp) ListCheckpoints(ctx context.Context, id string, opt *ListOptions) ([]MicroDropletCheckpoint, *Response, error) { + if id == "" { + return nil, nil, NewArgError("id", "cannot be empty") + } + + path := fmt.Sprintf("%s/%s/checkpoints", microDropletBasePath, id) + path, err := addOptions(path, opt) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(microDropletCheckpointsRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root.Checkpoints, resp, nil +} diff --git a/vendor/github.com/digitalocean/godo/sizes.go b/vendor/github.com/digitalocean/godo/sizes.go index 72d5321c9..3f6b043c2 100644 --- a/vendor/github.com/digitalocean/godo/sizes.go +++ b/vendor/github.com/digitalocean/godo/sizes.go @@ -54,6 +54,10 @@ type GPUInfo struct { Count int `json:"count,omitempty"` VRAM *VRAM `json:"vram,omitempty"` Model string `json:"model,omitempty"` + // SupportedPartitionModes lists the GPU partition modes available for this + // size. It is only returned to callers with access to the feature, so an + // empty/absent value means the partition-mode picker should be hidden. + SupportedPartitionModes []string `json:"supported_partition_modes,omitempty"` } // VRAM provides information about the amount of VRAM available to the GPU. diff --git a/vendor/github.com/digitalocean/godo/vpc_nat_gateways.go b/vendor/github.com/digitalocean/godo/vpc_nat_gateways.go index fca826ab1..f6177c33f 100644 --- a/vendor/github.com/digitalocean/godo/vpc_nat_gateways.go +++ b/vendor/github.com/digitalocean/godo/vpc_nat_gateways.go @@ -27,6 +27,7 @@ type VPCNATGatewayRequest struct { Region string `json:"region"` Size uint32 `json:"size"` VPCs []*IngressVPC `json:"vpcs"` + Egresses *Egresses `json:"egresses,omitempty"` UDPTimeoutSeconds uint32 `json:"udp_timeout_seconds,omitempty"` ICMPTimeoutSeconds uint32 `json:"icmp_timeout_seconds,omitempty"` TCPTimeoutSeconds uint32 `json:"tcp_timeout_seconds,omitempty"` @@ -64,9 +65,12 @@ type Egresses struct { PublicGateways []*PublicGateway `json:"public_gateways,omitempty"` } -// PublicGateway defines the public egress supported by a VPC NAT Gateway +// PublicGateway defines the public egress supported by a VPC NAT Gateway. +// On create, set IP (preferred) or IPv4 to assign a BYOIP / reserved IP. +// When omitted, a system-allocated reserved IP is provisioned. type PublicGateway struct { - IPv4 string `json:"ipv4"` + IPv4 string `json:"ipv4,omitempty"` + IP string `json:"ip,omitempty"` } // VPCNATGatewaysListOptions define custom options for listing VPC NAT Gateways diff --git a/vendor/modules.txt b/vendor/modules.txt index a6f8609e5..d24ef7ebe 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -33,7 +33,7 @@ github.com/coreos/go-systemd/v22/journal # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit github.com/davecgh/go-spew/spew -# github.com/digitalocean/godo v1.198.0 +# github.com/digitalocean/godo v1.203.0 ## explicit; go 1.23.0 github.com/digitalocean/godo github.com/digitalocean/godo/metrics