Documentation
¶
Overview ¶
Package drivers contains ResourceDriver implementations for each DigitalOcean resource type.
Package drivers implements per-resource DigitalOcean drivers used by the plugin. shared.go holds helpers that are used by more than one driver.
Package drivers — SpacesKeyDriver provisions DigitalOcean Spaces access keys (resource type `infra.spaces_key`) via godo's SpacesKeysService.
Engine-routing pattern (workflow v0.27.0+):
Create returns ResourceOutput.Outputs containing every field including access_key and secret_key, and flags both as Sensitive via ResourceOutput.Sensitive[k]==true. The workflow engine's iac/sensitive package routes those flagged values through the configured secrets.Provider (keyed `<resource>_<output>`) and replaces them with `secret_ref://...` placeholders before persisting state. The driver itself NEVER touches secrets.Provider — it stays platform-agnostic.
Read and Update return Outputs WITHOUT secret_key (the DO API only exposes secret_key on Create; Get/List/Update never re-emit it). The secret value lives in the secrets.Provider after Create routed it. Audit/refresh paths reconcile against access_key, name, created_at, grants — the only fields the API can re-read.
Delete is idempotent on 404: when the underlying DELETE responds 404 (key already gone), the driver returns nil so reapply / cleanup pipelines don't error on prior partial success. Sister provider RevokeProviderCredential takes the same stance.
Diff compares mutable fields (name, grants). godo's SpacesKeysService.Update accepts both Name and Grants, so name divergence is a NeedsUpdate (in-place rename), NOT NeedsReplace. A FieldChange entry is appended for each differing field.
SensitiveKeys() returns access_key + secret_key for plan/diff display masking; this is independent from the per-call routing trigger above.
ProviderID == access_key — matches the sister bucket driver (internal/drivers/spaces.go) and the EnumerateAll path in internal/provider.go::enumerateAllSpacesKeys. Per ADR 0015/0020.
Index ¶
- Constants
- Variables
- func ParseImageRef(imageStr string) (*godo.ImageSourceSpec, error)
- func WrapGodoError(err error) error
- type APIGatewayAppClient
- type APIGatewayDriver
- func (d *APIGatewayDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *APIGatewayDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *APIGatewayDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *APIGatewayDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *APIGatewayDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *APIGatewayDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *APIGatewayDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *APIGatewayDriver) SensitiveKeys() []string
- func (d *APIGatewayDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type ActionsClient
- type AppBlueGreenDriver
- func (d *AppBlueGreenDriver) CreateGreen(ctx context.Context, image string) error
- func (d *AppBlueGreenDriver) CurrentImage(ctx context.Context) (string, error)
- func (d *AppBlueGreenDriver) DestroyBlue(ctx context.Context) error
- func (d *AppBlueGreenDriver) GreenEndpoint(_ context.Context) (string, error)
- func (d *AppBlueGreenDriver) HealthCheck(ctx context.Context, path string) error
- func (d *AppBlueGreenDriver) ReplicaCount(ctx context.Context) (int, error)
- func (d *AppBlueGreenDriver) SwitchTraffic(ctx context.Context) error
- func (d *AppBlueGreenDriver) Update(ctx context.Context, image string) error
- type AppCanaryDriver
- func (d *AppCanaryDriver) CheckMetricGate(_ context.Context, _ string) error
- func (d *AppCanaryDriver) CreateCanary(ctx context.Context, image string) error
- func (d *AppCanaryDriver) CurrentImage(ctx context.Context) (string, error)
- func (d *AppCanaryDriver) DestroyCanary(ctx context.Context) error
- func (d *AppCanaryDriver) HealthCheck(ctx context.Context, path string) error
- func (d *AppCanaryDriver) PromoteCanary(ctx context.Context) error
- func (d *AppCanaryDriver) ReplicaCount(ctx context.Context) (int, error)
- func (d *AppCanaryDriver) RoutePercent(_ context.Context, percent int) error
- func (d *AppCanaryDriver) Update(ctx context.Context, image string) error
- type AppDeployDriver
- type AppPlatformClient
- type AppPlatformDriver
- func (d *AppPlatformDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *AppPlatformDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *AppPlatformDriver) Diff(ctx context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *AppPlatformDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *AppPlatformDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *AppPlatformDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *AppPlatformDriver) RepairDirtyMigration(ctx context.Context, req interfaces.MigrationRepairRequest) (*interfaces.MigrationRepairResult, error)
- func (d *AppPlatformDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
- func (d *AppPlatformDriver) SensitiveKeys() []string
- func (d *AppPlatformDriver) SupportsUpsert() bool
- func (d *AppPlatformDriver) Troubleshoot(ctx context.Context, ref interfaces.ResourceRef, _ string) ([]interfaces.Diagnostic, error)
- func (d *AppPlatformDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type CacheClient
- type CacheDriver
- func (d *CacheDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *CacheDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *CacheDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *CacheDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *CacheDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *CacheDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *CacheDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
- func (d *CacheDriver) SensitiveKeys() []string
- func (d *CacheDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type CertificateClient
- type CertificateDriver
- func (d *CertificateDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *CertificateDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *CertificateDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *CertificateDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *CertificateDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *CertificateDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *CertificateDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *CertificateDriver) SensitiveKeys() []string
- func (d *CertificateDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type DNSDriver
- func (d *DNSDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *DNSDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *DNSDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *DNSDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *DNSDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *DNSDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *DNSDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *DNSDriver) SensitiveKeys() []string
- func (d *DNSDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type DatabaseClient
- type DatabaseDriver
- func (d *DatabaseDriver) AdoptionRef(spec interfaces.ResourceSpec) (interfaces.ResourceRef, bool, error)
- func (d *DatabaseDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *DatabaseDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *DatabaseDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *DatabaseDriver) FlushDeferredUpdates(ctx context.Context) error
- func (d *DatabaseDriver) HasDeferredUpdates() bool
- func (d *DatabaseDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *DatabaseDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *DatabaseDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *DatabaseDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
- func (d *DatabaseDriver) SensitiveKeys() []string
- func (d *DatabaseDriver) SupportsUpsert() bool
- func (d *DatabaseDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type DomainsClient
- type DropletDriver
- func (d *DropletDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *DropletDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *DropletDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *DropletDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *DropletDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *DropletDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *DropletDriver) Replace(ctx context.Context, oldRef interfaces.ResourceRef, ...) (*interfaces.ResourceOutput, error)
- func (d *DropletDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *DropletDriver) SensitiveKeys() []string
- func (d *DropletDriver) SetReplaceTimeoutsForTest(timeout, pollInterval time.Duration)
- func (d *DropletDriver) Update(_ context.Context, _ interfaces.ResourceRef, _ interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type DropletsClient
- type FirewallClient
- type FirewallDriver
- func (d *FirewallDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *FirewallDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *FirewallDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *FirewallDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *FirewallDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *FirewallDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *FirewallDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *FirewallDriver) SensitiveKeys() []string
- func (d *FirewallDriver) SupportsUpsert() bool
- func (d *FirewallDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type IAMRoleDriver
- func (d *IAMRoleDriver) Create(_ context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *IAMRoleDriver) Delete(_ context.Context, _ interfaces.ResourceRef) error
- func (d *IAMRoleDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *IAMRoleDriver) HealthCheck(_ context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *IAMRoleDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *IAMRoleDriver) Read(_ context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *IAMRoleDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *IAMRoleDriver) SensitiveKeys() []string
- func (d *IAMRoleDriver) Update(_ context.Context, _ interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type KubernetesClient
- type KubernetesDriver
- func (d *KubernetesDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *KubernetesDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *KubernetesDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *KubernetesDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *KubernetesDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *KubernetesDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *KubernetesDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
- func (d *KubernetesDriver) SensitiveKeys() []string
- func (d *KubernetesDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type LoadBalancerClient
- type LoadBalancerDriver
- func (d *LoadBalancerDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *LoadBalancerDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *LoadBalancerDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *LoadBalancerDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *LoadBalancerDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *LoadBalancerDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *LoadBalancerDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *LoadBalancerDriver) SensitiveKeys() []string
- func (d *LoadBalancerDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type RegistryClient
- type RegistryDriver
- func (d *RegistryDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *RegistryDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *RegistryDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *RegistryDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *RegistryDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *RegistryDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *RegistryDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *RegistryDriver) SensitiveKeys() []string
- func (d *RegistryDriver) Update(ctx context.Context, _ interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type SpacesBucket
- type SpacesBucketClient
- type SpacesDriver
- func (d *SpacesDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *SpacesDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *SpacesDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *SpacesDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *SpacesDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *SpacesDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *SpacesDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *SpacesDriver) SensitiveKeys() []string
- func (d *SpacesDriver) Update(_ context.Context, _ interfaces.ResourceRef, _ interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type SpacesKeyDriver
- func (d *SpacesKeyDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *SpacesKeyDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *SpacesKeyDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *SpacesKeyDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *SpacesKeyDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *SpacesKeyDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *SpacesKeyDriver) ResourceType() string
- func (d *SpacesKeyDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *SpacesKeyDriver) SensitiveKeys() []string
- func (d *SpacesKeyDriver) SupportsUpsert() bool
- func (d *SpacesKeyDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type StorageActionsClient
- type StorageClient
- type VPCClient
- type VPCDriver
- func (d *VPCDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *VPCDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *VPCDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *VPCDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *VPCDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *VPCDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *VPCDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *VPCDriver) SensitiveKeys() []string
- func (d *VPCDriver) SupportsUpsert() bool
- func (d *VPCDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- type VolumeDriver
- func (d *VolumeDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
- func (d *VolumeDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
- func (d *VolumeDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, ...) (*interfaces.DiffResult, error)
- func (d *VolumeDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
- func (d *VolumeDriver) ProviderIDFormat() interfaces.ProviderIDFormat
- func (d *VolumeDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
- func (d *VolumeDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
- func (d *VolumeDriver) SensitiveKeys() []string
- func (d *VolumeDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
Constants ¶
const NoTargetsErrFmt = `` /* 152-byte string literal not displayed */
NoTargetsErrFmt is the format string for the error returned by validateFirewallTargets when a firewall spec has neither droplet_ids nor tags. The string is exported and stable so tests can assert exact-match equality without redefining the literal, and so plan-output greps and runbooks can rely on a fixed phrase. The em dash (U+2014) and the App Platform clause are part of the contract — DO firewalls do not protect App Platform apps, and the surfaced error must say so.
Variables ¶
var ErrAppNotFound = fmt.Errorf("trusted_sources app: %w", ErrResourceNotFound)
ErrAppNotFound is returned by resolveAppNamesMap when a requested app name is absent from the DO Apps.List result. It wraps ErrResourceNotFound so callers using errors.Is(err, ErrResourceNotFound) continue to work; the more specific sentinel is used internally to distinguish "app not yet created" from API-level failures (rate-limit, transient, auth) that must NOT trigger the deferred-update path.
var ErrResourceNotFound = interfaces.ErrResourceNotFound
ErrResourceNotFound is returned when a resource cannot be located by name or ID. It is an alias for interfaces.ErrResourceNotFound so that cross-package errors.Is checks work for the DetectDrift ghost-classification path.
Functions ¶
func ParseImageRef ¶ added in v0.5.1
func ParseImageRef(imageStr string) (*godo.ImageSourceSpec, error)
ParseImageRef parses a flat image reference string into a DO App Platform ImageSourceSpec. Supports:
- registry.digitalocean.com/<registry>/<repo>:<tag> → DOCR (Registry left empty per DO API requirement)
- ghcr.io/<org>/<repo>:<tag> → GHCR
- docker.io/<org>/<repo>:<tag> → DOCKER_HUB
- <org>/<repo>:<tag> → DOCKER_HUB (bare form)
A missing tag defaults to "latest".
func WrapGodoError ¶ added in v0.6.1
WrapGodoError inspects err for a *godo.ErrorResponse and maps its HTTP status code to the matching interfaces.Err* sentinel. The returned error wraps the sentinel so callers can use errors.Is for classification while still having access to the original DO API message via err.Error().
Two passthrough branches return err unchanged:
- err is nil → return nil (no-op; safe to call unconditionally)
- err is not a *godo.ErrorResponse, or its Response field is nil → return err (e.g. network errors, context cancellation, or SDK bugs; not DO API errors)
HTTP codes with no sentinel mapping (e.g. 301, 400 handled elsewhere) also pass through unchanged via sentinelForStatus returning nil.
Types ¶
type APIGatewayAppClient ¶ added in v0.1.1
type APIGatewayAppClient interface {
Create(ctx context.Context, req *godo.AppCreateRequest) (*godo.App, *godo.Response, error)
Get(ctx context.Context, appID string) (*godo.App, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]*godo.App, *godo.Response, error)
Update(ctx context.Context, appID string, req *godo.AppUpdateRequest) (*godo.App, *godo.Response, error)
Delete(ctx context.Context, appID string) (*godo.Response, error)
}
APIGatewayAppClient is the godo App interface used for API gateway management (for mocking).
type APIGatewayDriver ¶ added in v0.1.1
type APIGatewayDriver struct {
// contains filtered or unexported fields
}
APIGatewayDriver manages API routing via DigitalOcean App Platform (infra.api_gateway). It creates an App Platform application with HTTP route rules mapping paths to backend services.
Config keys:
region string — DO region slug (default: driver region)
routes []map[string]any — each: {path, component, preserve_path_prefix}
component maps to an App Platform service component name
func NewAPIGatewayDriver ¶ added in v0.1.1
func NewAPIGatewayDriver(c *godo.Client, region string) *APIGatewayDriver
NewAPIGatewayDriver creates an APIGatewayDriver backed by a real godo client.
func NewAPIGatewayDriverWithClient ¶ added in v0.1.1
func NewAPIGatewayDriverWithClient(c APIGatewayAppClient, region string) *APIGatewayDriver
NewAPIGatewayDriverWithClient creates a driver with an injected client (for tests).
func (*APIGatewayDriver) Create ¶ added in v0.1.1
func (d *APIGatewayDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*APIGatewayDriver) Delete ¶ added in v0.1.1
func (d *APIGatewayDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*APIGatewayDriver) Diff ¶ added in v0.1.1
func (d *APIGatewayDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*APIGatewayDriver) HealthCheck ¶ added in v0.1.1
func (d *APIGatewayDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*APIGatewayDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *APIGatewayDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*APIGatewayDriver) Read ¶ added in v0.1.1
func (d *APIGatewayDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*APIGatewayDriver) Scale ¶ added in v0.1.1
func (d *APIGatewayDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*APIGatewayDriver) SensitiveKeys ¶ added in v0.2.1
func (d *APIGatewayDriver) SensitiveKeys() []string
func (*APIGatewayDriver) Update ¶ added in v0.1.1
func (d *APIGatewayDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type ActionsClient ¶ added in v0.11.0
type ActionsClient interface {
Get(ctx context.Context, actionID int) (*godo.Action, *godo.Response, error)
}
ActionsClient is the godo ActionsService subset DropletDriver uses for waiting on async actions (volume detach is the canonical case). Subset means: only Get(ctx, actionID) — the pollable status read.
type AppBlueGreenDriver ¶ added in v0.2.0
type AppBlueGreenDriver struct {
// contains filtered or unexported fields
}
AppBlueGreenDriver implements module.BlueGreenDriver for DigitalOcean App Platform.
Blue environment: the existing app identified by blueID. Green environment: a new app created with the "-green" name suffix.
SwitchTraffic is implemented by updating the blue app's spec with the green image (making blue the new stable), then DestroyBlue removes the green clone. The green app's live URL is returned from GreenEndpoint.
func NewAppBlueGreenDriver ¶ added in v0.2.0
func NewAppBlueGreenDriver(c AppPlatformClient, region, blueID, blueName string) *AppBlueGreenDriver
NewAppBlueGreenDriver creates a BlueGreenDriver for DO App Platform.
func (*AppBlueGreenDriver) CreateGreen ¶ added in v0.2.0
func (d *AppBlueGreenDriver) CreateGreen(ctx context.Context, image string) error
CreateGreen creates a new App Platform app with the "-green" name suffix and the given image, recording the green app ID and live URL for later use.
func (*AppBlueGreenDriver) CurrentImage ¶ added in v0.2.0
func (d *AppBlueGreenDriver) CurrentImage(ctx context.Context) (string, error)
func (*AppBlueGreenDriver) DestroyBlue ¶ added in v0.2.0
func (d *AppBlueGreenDriver) DestroyBlue(ctx context.Context) error
DestroyBlue deletes the green clone (the temporary environment).
func (*AppBlueGreenDriver) GreenEndpoint ¶ added in v0.2.0
func (d *AppBlueGreenDriver) GreenEndpoint(_ context.Context) (string, error)
GreenEndpoint returns the live URL of the green App Platform app.
func (*AppBlueGreenDriver) HealthCheck ¶ added in v0.2.0
func (d *AppBlueGreenDriver) HealthCheck(ctx context.Context, path string) error
func (*AppBlueGreenDriver) ReplicaCount ¶ added in v0.2.0
func (d *AppBlueGreenDriver) ReplicaCount(ctx context.Context) (int, error)
func (*AppBlueGreenDriver) SwitchTraffic ¶ added in v0.2.0
func (d *AppBlueGreenDriver) SwitchTraffic(ctx context.Context) error
SwitchTraffic updates the blue app spec to use the green image, effectively promoting the green version as the stable app. DO App Platform does not support weighted traffic splitting natively; this performs a full cutover.
type AppCanaryDriver ¶ added in v0.2.0
type AppCanaryDriver struct {
// contains filtered or unexported fields
}
AppCanaryDriver implements module.CanaryDriver for DigitalOcean App Platform.
DigitalOcean App Platform does not support native traffic splitting between app instances. RoutePercent returns a clear unsupported error directing users to DigitalOcean Load Balancer + Droplets for canary deployments.
CreateCanary, PromoteCanary, and DestroyCanary follow the standard create/promote/delete pattern using two separate apps.
func NewAppCanaryDriver ¶ added in v0.2.0
func NewAppCanaryDriver(c AppPlatformClient, region, stableID, stableName string) *AppCanaryDriver
NewAppCanaryDriver creates a CanaryDriver for DO App Platform.
func (*AppCanaryDriver) CheckMetricGate ¶ added in v0.2.0
func (d *AppCanaryDriver) CheckMetricGate(_ context.Context, _ string) error
CheckMetricGate always passes (no native metric integration).
func (*AppCanaryDriver) CreateCanary ¶ added in v0.2.0
func (d *AppCanaryDriver) CreateCanary(ctx context.Context, image string) error
CreateCanary creates a new App Platform app with the "-canary" name suffix and the given image.
func (*AppCanaryDriver) CurrentImage ¶ added in v0.2.0
func (d *AppCanaryDriver) CurrentImage(ctx context.Context) (string, error)
func (*AppCanaryDriver) DestroyCanary ¶ added in v0.2.0
func (d *AppCanaryDriver) DestroyCanary(ctx context.Context) error
DestroyCanary deletes the canary App Platform app.
func (*AppCanaryDriver) HealthCheck ¶ added in v0.2.0
func (d *AppCanaryDriver) HealthCheck(ctx context.Context, path string) error
func (*AppCanaryDriver) PromoteCanary ¶ added in v0.2.0
func (d *AppCanaryDriver) PromoteCanary(ctx context.Context) error
PromoteCanary updates the stable app with the canary image and deletes the canary.
func (*AppCanaryDriver) ReplicaCount ¶ added in v0.2.0
func (d *AppCanaryDriver) ReplicaCount(ctx context.Context) (int, error)
func (*AppCanaryDriver) RoutePercent ¶ added in v0.2.0
func (d *AppCanaryDriver) RoutePercent(_ context.Context, percent int) error
RoutePercent is not supported by DigitalOcean App Platform. Use DigitalOcean Load Balancer with Droplets for canary traffic splitting.
type AppDeployDriver ¶ added in v0.2.0
type AppDeployDriver struct {
// contains filtered or unexported fields
}
AppDeployDriver implements module.DeployDriver for DigitalOcean App Platform. It manages a single App Platform application identified by its app ID.
func NewAppDeployDriver ¶ added in v0.2.0
func NewAppDeployDriver(c AppPlatformClient, region, appID, appName string) *AppDeployDriver
NewAppDeployDriver creates a DeployDriver backed by a DO App Platform app.
func (*AppDeployDriver) CurrentImage ¶ added in v0.2.0
func (d *AppDeployDriver) CurrentImage(ctx context.Context) (string, error)
func (*AppDeployDriver) HealthCheck ¶ added in v0.2.0
func (d *AppDeployDriver) HealthCheck(ctx context.Context, _ string) error
func (*AppDeployDriver) ReplicaCount ¶ added in v0.2.0
func (d *AppDeployDriver) ReplicaCount(ctx context.Context) (int, error)
type AppPlatformClient ¶
type AppPlatformClient interface {
Create(ctx context.Context, req *godo.AppCreateRequest) (*godo.App, *godo.Response, error)
Get(ctx context.Context, appID string) (*godo.App, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]*godo.App, *godo.Response, error)
Update(ctx context.Context, appID string, req *godo.AppUpdateRequest) (*godo.App, *godo.Response, error)
CreateDeployment(ctx context.Context, appID string, req ...*godo.DeploymentCreateRequest) (*godo.Deployment, *godo.Response, error)
ListDeployments(ctx context.Context, appID string, opts *godo.ListOptions) ([]*godo.Deployment, *godo.Response, error)
Delete(ctx context.Context, appID string) (*godo.Response, error)
GetLogs(ctx context.Context, appID, deploymentID, component string, logType godo.AppLogType, follow bool, tailLines int) (*godo.AppLogs, *godo.Response, error)
}
AppPlatformClient is the godo App interface used by AppPlatformDriver (for mocking).
type AppPlatformDriver ¶
type AppPlatformDriver struct {
// contains filtered or unexported fields
}
AppPlatformDriver manages DigitalOcean App Platform (infra.container_service).
func NewAppPlatformDriver ¶
func NewAppPlatformDriver(c *godo.Client, region string) *AppPlatformDriver
NewAppPlatformDriver creates an AppPlatformDriver backed by a real godo client.
func NewAppPlatformDriverWithClient ¶
func NewAppPlatformDriverWithClient(c AppPlatformClient, region string) *AppPlatformDriver
NewAppPlatformDriverWithClient creates a driver with an injected apps client (for tests). regClient is nil; image-presence check is skipped.
func NewAppPlatformDriverWithClients ¶ added in v0.12.0
func NewAppPlatformDriverWithClients(c AppPlatformClient, r RegistryClient, region string) *AppPlatformDriver
NewAppPlatformDriverWithClients creates a driver with both clients injected (for tests).
func (*AppPlatformDriver) Create ¶
func (d *AppPlatformDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*AppPlatformDriver) Delete ¶
func (d *AppPlatformDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*AppPlatformDriver) Diff ¶
func (d *AppPlatformDriver) Diff(ctx context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*AppPlatformDriver) HealthCheck ¶
func (d *AppPlatformDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*AppPlatformDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *AppPlatformDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*AppPlatformDriver) Read ¶
func (d *AppPlatformDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*AppPlatformDriver) RepairDirtyMigration ¶ added in v0.7.13
func (d *AppPlatformDriver) RepairDirtyMigration(ctx context.Context, req interfaces.MigrationRepairRequest) (*interfaces.MigrationRepairResult, error)
func (*AppPlatformDriver) Scale ¶
func (d *AppPlatformDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
func (*AppPlatformDriver) SensitiveKeys ¶ added in v0.2.1
func (d *AppPlatformDriver) SensitiveKeys() []string
func (*AppPlatformDriver) SupportsUpsert ¶ added in v0.7.2
func (d *AppPlatformDriver) SupportsUpsert() bool
SupportsUpsert reports that AppPlatformDriver can locate a resource by name alone (empty ProviderID), enabling the ErrResourceAlreadyExists → upsert path in DOProvider.Apply. Other drivers that require ProviderID in Read do not implement this method and are excluded from the upsert path.
func (*AppPlatformDriver) Troubleshoot ¶ added in v0.7.8
func (d *AppPlatformDriver) Troubleshoot(ctx context.Context, ref interfaces.ResourceRef, _ string) ([]interfaces.Diagnostic, error)
Troubleshoot implements interfaces.Troubleshooter for AppPlatformDriver. It fetches the app (to inspect its three deployment slots: InProgress, Pending, Active) plus recent historical deployments, prioritises them, and returns per-deployment Diagnostics so wfctl can render a structured failure block on health-check timeout without requiring a DO console visit.
For each candidate deployment in a terminal error phase (Error, Canceled, Superseded), Troubleshoot fetches deploy logs via GetLogs and appends the last troubleshootLogTailLines of output per component to the Diagnostic.Detail. Log fetch failures are best-effort: the Diagnostic is still produced without the log block when GetLogs or the HTTP fetch fails.
func (*AppPlatformDriver) Update ¶
func (d *AppPlatformDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type CacheClient ¶ added in v0.1.1
type CacheClient interface {
Create(ctx context.Context, req *godo.DatabaseCreateRequest) (*godo.Database, *godo.Response, error)
Get(ctx context.Context, databaseID string) (*godo.Database, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]godo.Database, *godo.Response, error)
Resize(ctx context.Context, databaseID string, req *godo.DatabaseResizeRequest) (*godo.Response, error)
Delete(ctx context.Context, databaseID string) (*godo.Response, error)
}
CacheClient is the godo Databases interface used for Redis cache clusters (for mocking).
type CacheDriver ¶ added in v0.1.1
type CacheDriver struct {
// contains filtered or unexported fields
}
CacheDriver manages DigitalOcean Managed Redis clusters (infra.cache). It uses the same Databases API as DatabaseDriver with engine=redis.
func NewCacheDriver ¶ added in v0.1.1
func NewCacheDriver(c *godo.Client, region string) *CacheDriver
NewCacheDriver creates a CacheDriver backed by a real godo client.
func NewCacheDriverWithClient ¶ added in v0.1.1
func NewCacheDriverWithClient(c CacheClient, region string) *CacheDriver
NewCacheDriverWithClient creates a driver with an injected client (for tests).
func (*CacheDriver) Create ¶ added in v0.1.1
func (d *CacheDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*CacheDriver) Delete ¶ added in v0.1.1
func (d *CacheDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*CacheDriver) Diff ¶ added in v0.1.1
func (d *CacheDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*CacheDriver) HealthCheck ¶ added in v0.1.1
func (d *CacheDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*CacheDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *CacheDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*CacheDriver) Read ¶ added in v0.1.1
func (d *CacheDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*CacheDriver) Scale ¶ added in v0.1.1
func (d *CacheDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
func (*CacheDriver) SensitiveKeys ¶ added in v0.2.1
func (d *CacheDriver) SensitiveKeys() []string
func (*CacheDriver) Update ¶ added in v0.1.1
func (d *CacheDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type CertificateClient ¶
type CertificateClient interface {
Create(ctx context.Context, req *godo.CertificateRequest) (*godo.Certificate, *godo.Response, error)
Get(ctx context.Context, certID string) (*godo.Certificate, *godo.Response, error)
Delete(ctx context.Context, certID string) (*godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]godo.Certificate, *godo.Response, error)
}
CertificateClient is the godo Certificates interface (for mocking).
type CertificateDriver ¶
type CertificateDriver struct {
// contains filtered or unexported fields
}
CertificateDriver manages DigitalOcean SSL/TLS certificates (infra.certificate).
func NewCertificateDriver ¶
func NewCertificateDriver(c *godo.Client) *CertificateDriver
NewCertificateDriver creates a CertificateDriver backed by a real godo client.
func NewCertificateDriverWithClient ¶
func NewCertificateDriverWithClient(c CertificateClient) *CertificateDriver
NewCertificateDriverWithClient creates a driver with an injected client (for tests).
func (*CertificateDriver) Create ¶
func (d *CertificateDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*CertificateDriver) Delete ¶
func (d *CertificateDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*CertificateDriver) Diff ¶
func (d *CertificateDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*CertificateDriver) HealthCheck ¶
func (d *CertificateDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*CertificateDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *CertificateDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*CertificateDriver) Read ¶
func (d *CertificateDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*CertificateDriver) Scale ¶
func (d *CertificateDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*CertificateDriver) SensitiveKeys ¶ added in v0.2.1
func (d *CertificateDriver) SensitiveKeys() []string
func (*CertificateDriver) Update ¶
func (d *CertificateDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type DNSDriver ¶
type DNSDriver struct {
// contains filtered or unexported fields
}
DNSDriver manages DigitalOcean Domains and DNS records (infra.dns). Idempotent: creates domain if missing, creates or updates records.
func NewDNSDriver ¶
NewDNSDriver creates a DNSDriver backed by a real godo client.
func NewDNSDriverWithClient ¶
func NewDNSDriverWithClient(c DomainsClient) *DNSDriver
NewDNSDriverWithClient creates a driver with an injected client (for tests).
func (*DNSDriver) Create ¶
func (d *DNSDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
Create creates a domain and any declared DNS records idempotently. Config keys:
domain string — the zone name (e.g. "example.com")
records []any|[]map[string]any — each: {type, name, data, ttl}
func (*DNSDriver) Delete ¶
func (d *DNSDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*DNSDriver) Diff ¶
func (d *DNSDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*DNSDriver) HealthCheck ¶
func (d *DNSDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*DNSDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *DNSDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*DNSDriver) Read ¶
func (d *DNSDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*DNSDriver) Scale ¶
func (d *DNSDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*DNSDriver) SensitiveKeys ¶ added in v0.2.1
func (*DNSDriver) Update ¶
func (d *DNSDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type DatabaseClient ¶
type DatabaseClient interface {
Create(ctx context.Context, req *godo.DatabaseCreateRequest) (*godo.Database, *godo.Response, error)
Get(ctx context.Context, databaseID string) (*godo.Database, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]godo.Database, *godo.Response, error)
Resize(ctx context.Context, databaseID string, req *godo.DatabaseResizeRequest) (*godo.Response, error)
Delete(ctx context.Context, databaseID string) (*godo.Response, error)
UpdateFirewallRules(ctx context.Context, databaseID string, req *godo.DatabaseUpdateFirewallRulesRequest) (*godo.Response, error)
}
DatabaseClient is the godo Databases interface (for mocking).
type DatabaseDriver ¶
type DatabaseDriver struct {
// contains filtered or unexported fields
}
DatabaseDriver manages DigitalOcean Managed Databases (infra.database). Supports pg, mysql, redis, mongodb, kafka.
func NewDatabaseDriver ¶
func NewDatabaseDriver(c *godo.Client, region string) *DatabaseDriver
NewDatabaseDriver creates a DatabaseDriver backed by a real godo client. The godo Apps client is wired automatically to support type=app trusted_source name → UUID resolution at apply time.
func NewDatabaseDriverWithClient ¶
func NewDatabaseDriverWithClient(c DatabaseClient, region string) *DatabaseDriver
NewDatabaseDriverWithClient creates a driver with an injected database client (for tests). appsClient may be nil when tests do not exercise type=app trusted_source rules.
func NewDatabaseDriverWithClients ¶ added in v0.7.10
func NewDatabaseDriverWithClients(c DatabaseClient, apps appNameLister, region string) *DatabaseDriver
NewDatabaseDriverWithClients creates a driver with injected database and apps clients (for tests that exercise type=app trusted_source name → UUID resolution). apps must implement appNameLister (i.e. have a List method); any *fakeAppsClient or real godo.AppsService satisfies this.
func (*DatabaseDriver) AdoptionRef ¶ added in v0.14.4
func (d *DatabaseDriver) AdoptionRef(spec interfaces.ResourceSpec) (interfaces.ResourceRef, bool, error)
func (*DatabaseDriver) Create ¶
func (d *DatabaseDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*DatabaseDriver) Delete ¶
func (d *DatabaseDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*DatabaseDriver) Diff ¶
func (d *DatabaseDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*DatabaseDriver) FlushDeferredUpdates ¶ added in v0.8.2
func (d *DatabaseDriver) FlushDeferredUpdates(ctx context.Context) error
FlushDeferredUpdates applies all pending firewall updates that were deferred during Create/Update because referenced app(s) did not exist yet. Each entry re-resolves its type=app trusted_sources entries (app must now exist) and calls UpdateFirewallRules with the full rule set. Returns an error if any update fails — the caller (DOProvider.Apply) appends these to result.Errors so the failure is visible to the operator.
Only successfully-flushed entries are removed from the queue. Entries that failed (rule-resolution error or UpdateFirewallRules API error) are retained so that a subsequent Apply automatically re-attempts the flush without requiring operator intervention. This matters because DatabaseDriver.Diff does not compare trusted_sources, meaning a retry Apply would otherwise produce no update action and the second-pass flush would never fire.
func (*DatabaseDriver) HasDeferredUpdates ¶ added in v0.8.2
func (d *DatabaseDriver) HasDeferredUpdates() bool
HasDeferredUpdates reports whether the driver has pending firewall updates queued from Create or Update calls where type=app trusted_sources entries referenced apps that did not exist yet. DOProvider.Apply checks this after the main action loop and calls FlushDeferredUpdates when true.
func (*DatabaseDriver) HealthCheck ¶
func (d *DatabaseDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*DatabaseDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *DatabaseDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*DatabaseDriver) Read ¶
func (d *DatabaseDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*DatabaseDriver) Scale ¶
func (d *DatabaseDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
func (*DatabaseDriver) SensitiveKeys ¶ added in v0.2.1
func (d *DatabaseDriver) SensitiveKeys() []string
func (*DatabaseDriver) SupportsUpsert ¶ added in v0.7.3
func (d *DatabaseDriver) SupportsUpsert() bool
SupportsUpsert reports that DatabaseDriver can locate a resource by name alone (empty ProviderID), enabling the ErrResourceAlreadyExists → upsert path.
func (*DatabaseDriver) Update ¶
func (d *DatabaseDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type DomainsClient ¶
type DomainsClient interface {
Create(ctx context.Context, req *godo.DomainCreateRequest) (*godo.Domain, *godo.Response, error)
Get(ctx context.Context, name string) (*godo.Domain, *godo.Response, error)
Delete(ctx context.Context, name string) (*godo.Response, error)
CreateRecord(ctx context.Context, domain string, req *godo.DomainRecordEditRequest) (*godo.DomainRecord, *godo.Response, error)
EditRecord(ctx context.Context, domain string, id int, req *godo.DomainRecordEditRequest) (*godo.DomainRecord, *godo.Response, error)
DeleteRecord(ctx context.Context, domain string, id int) (*godo.Response, error)
Records(ctx context.Context, domain string, opts *godo.ListOptions) ([]godo.DomainRecord, *godo.Response, error)
}
DomainsClient is the godo Domains interface (for mocking).
type DropletDriver ¶
type DropletDriver struct {
// contains filtered or unexported fields
}
DropletDriver manages DigitalOcean Droplets (infra.droplet).
func NewDropletDriver ¶
func NewDropletDriver(c *godo.Client, region string) *DropletDriver
NewDropletDriver creates a DropletDriver backed by a real godo client. The Storage, StorageActions, and Actions clients are wired so volumes-by-name resolution and Replace's detach-wait work without additional configuration.
func NewDropletDriverWithClient ¶
func NewDropletDriverWithClient(c DropletsClient, region string, optional ...interface{}) *DropletDriver
NewDropletDriverWithClient creates a driver with injected clients (for tests). Optional clients are provided via a variadic interface{} parameter; each value is type-switched to the appropriate field. Typed-nil interface values are rejected (treated as "not provided") to prevent nil-method-set panics at call time.
Existing tests that pass (DropletsClient, region) continue to compile unchanged. Tests that exercise Replace must additionally pass StorageActionsClient and ActionsClient.
func (*DropletDriver) Create ¶
func (d *DropletDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*DropletDriver) Delete ¶
func (d *DropletDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*DropletDriver) Diff ¶
func (d *DropletDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
Diff compares the desired spec against the current droplet output and returns a DiffResult. Update is disallowed by godo (Droplet PUT only resizes), so every detected change is flagged as ForceNew — the caller must replace the droplet, not patch it.
Detected: size, vpc_uuid, enable_backups, tags, volumes (by NAME after dropletOutput's ID→name resolution), monitoring, ipv6 (via the droplet.Features string slice returned by the DO API).
NOT detected (godo Read limitation, tracked in issue #56): user_data, ssh_keys. Operators must taint the Droplet manually to roll a new value for any of these. See the inline comment near the end of this function for the full rationale.
func (*DropletDriver) HealthCheck ¶
func (d *DropletDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*DropletDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *DropletDriver) ProviderIDFormat() interfaces.ProviderIDFormat
ProviderIDFormat returns Freeform because DO Droplet IDs are integers, not UUIDs. We declare Freeform; providerIDToInt performs strict local validation and rejects any non-integer ProviderID with an explicit error before any API call is made — no UUID-based state-heal needed for Droplet.
func (*DropletDriver) Read ¶
func (d *DropletDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*DropletDriver) Replace ¶ added in v0.11.0
func (d *DropletDriver) Replace(ctx context.Context, oldRef interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
Replace implements interfaces.ResourceReplacer for DigitalOcean Droplets. Orchestration: read old → DetachByDropletID per attached Volume → wait for each detach action → delete old Droplet → create new Droplet with the same resolved Volume IDs (bypassing the name-resolution race in Create's resolveDropletVolumes path).
On 404 from the initial Get(oldID), Replace falls through with detach-skipped + delete-skipped; Create still fires (orphan-state recovery — same as engine-default Delete-then-Create when the old Droplet is gone).
Error wrapping: every sub-step wraps with "droplet replace %q: <step>: %w" so the workflow engine's error-prefix backstop sees the recognized "<resource-type> replace " family and passes the error through unchanged.
func (*DropletDriver) Scale ¶
func (d *DropletDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*DropletDriver) SensitiveKeys ¶ added in v0.2.1
func (d *DropletDriver) SensitiveKeys() []string
func (*DropletDriver) SetReplaceTimeoutsForTest ¶ added in v0.11.0
func (d *DropletDriver) SetReplaceTimeoutsForTest(timeout, pollInterval time.Duration)
SetReplaceTimeoutsForTest is a test-only seam to override the production 60s/2s detach-wait bounds. Production code MUST NOT call this.
func (*DropletDriver) Update ¶
func (d *DropletDriver) Update(_ context.Context, _ interfaces.ResourceRef, _ interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type DropletsClient ¶
type DropletsClient interface {
Create(ctx context.Context, req *godo.DropletCreateRequest) (*godo.Droplet, *godo.Response, error)
Get(ctx context.Context, dropletID int) (*godo.Droplet, *godo.Response, error)
Delete(ctx context.Context, dropletID int) (*godo.Response, error)
}
DropletsClient is the godo Droplets interface (for mocking).
type FirewallClient ¶
type FirewallClient interface {
Create(ctx context.Context, req *godo.FirewallRequest) (*godo.Firewall, *godo.Response, error)
Get(ctx context.Context, fwID string) (*godo.Firewall, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]godo.Firewall, *godo.Response, error)
Update(ctx context.Context, fwID string, req *godo.FirewallRequest) (*godo.Firewall, *godo.Response, error)
Delete(ctx context.Context, fwID string) (*godo.Response, error)
}
FirewallClient is the godo Firewalls interface (for mocking).
type FirewallDriver ¶
type FirewallDriver struct {
// contains filtered or unexported fields
}
FirewallDriver manages DigitalOcean Firewalls (infra.firewall).
Targets are required: every firewall must declare at least one of `droplet_ids` (a list of Droplet integer IDs) or `tags` (a list of Droplet/DOKS-pool tag strings, which auto-attach future resources). Both Create and Update reject specs with neither field set.
Note: DO firewalls do NOT attach to App Platform apps. For App-Platform-only deployments, omit `infra.firewall` and instead use `expose: internal` on the service plus `trusted_sources` on managed databases.
func NewFirewallDriver ¶
func NewFirewallDriver(c *godo.Client) *FirewallDriver
NewFirewallDriver creates a FirewallDriver backed by a real godo client.
func NewFirewallDriverWithClient ¶
func NewFirewallDriverWithClient(c FirewallClient) *FirewallDriver
NewFirewallDriverWithClient creates a driver with an injected client (for tests).
func (*FirewallDriver) Create ¶
func (d *FirewallDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*FirewallDriver) Delete ¶
func (d *FirewallDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*FirewallDriver) Diff ¶
func (d *FirewallDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
Diff compares the desired spec against the live firewall recorded on `current` to detect in-place reconfiguration. It compares the four canonical fields (`droplet_ids`, `tags`, `inbound_rules`, `outbound_rules`) so that toggling any of them between deploys produces a Plan action rather than silently no-op'ing.
`droplet_ids` and `tags` use SET semantics: reorder is not a change, since DO normalizes membership server-side. Rules use ORDER-SENSITIVE deep-equal because rule order is preserved in the API response and may carry user intent.
Both sides of the rule comparison are normalized to the structpb- compatible canonical map shape so the comparison is symmetric whether `current.Outputs` is read in-process or after a wfctl→plugin gRPC round- trip.
Legacy state without the recorded keys (`ResourceOutput` written by older plugin versions) is treated as having empty fields, which surfaces a Plan action on first Diff post-upgrade — the safe over-detect direction.
func (*FirewallDriver) HealthCheck ¶
func (d *FirewallDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*FirewallDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *FirewallDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*FirewallDriver) Read ¶
func (d *FirewallDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*FirewallDriver) Scale ¶
func (d *FirewallDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*FirewallDriver) SensitiveKeys ¶ added in v0.2.1
func (d *FirewallDriver) SensitiveKeys() []string
func (*FirewallDriver) SupportsUpsert ¶ added in v0.7.3
func (d *FirewallDriver) SupportsUpsert() bool
SupportsUpsert reports that FirewallDriver can locate a resource by name alone (empty ProviderID), enabling the ErrResourceAlreadyExists → upsert path.
func (*FirewallDriver) Update ¶
func (d *FirewallDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type IAMRoleDriver ¶ added in v0.1.1
type IAMRoleDriver struct{}
IAMRoleDriver provides a ResourceDriver for infra.iam_role on DigitalOcean.
Limitation ¶
DigitalOcean does not expose fine-grained IAM role management via the godo API. Personal Access Tokens and OAuth applications must be created through the DO control panel (https://cloud.digitalocean.com/account/api/tokens).
This driver is entirely declarative: Create/Update return the declared config as outputs with a limitation notice; Read/HealthCheck return a healthy declared state; Delete and Scale are no-ops. No godo API calls are made.
func NewIAMRoleDriver ¶ added in v0.1.1
func NewIAMRoleDriver() *IAMRoleDriver
NewIAMRoleDriver creates an IAMRoleDriver.
func (*IAMRoleDriver) Create ¶ added in v0.1.1
func (d *IAMRoleDriver) Create(_ context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
Create records an IAM role declaration. Since DO has no native role API the driver returns the declared metadata as outputs with a clear limitation notice.
func (*IAMRoleDriver) Delete ¶ added in v0.1.1
func (d *IAMRoleDriver) Delete(_ context.Context, _ interfaces.ResourceRef) error
func (*IAMRoleDriver) Diff ¶ added in v0.1.1
func (d *IAMRoleDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*IAMRoleDriver) HealthCheck ¶ added in v0.1.1
func (d *IAMRoleDriver) HealthCheck(_ context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*IAMRoleDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *IAMRoleDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*IAMRoleDriver) Read ¶ added in v0.1.1
func (d *IAMRoleDriver) Read(_ context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*IAMRoleDriver) Scale ¶ added in v0.1.1
func (d *IAMRoleDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*IAMRoleDriver) SensitiveKeys ¶ added in v0.2.1
func (d *IAMRoleDriver) SensitiveKeys() []string
func (*IAMRoleDriver) Update ¶ added in v0.1.1
func (d *IAMRoleDriver) Update(_ context.Context, _ interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type KubernetesClient ¶
type KubernetesClient interface {
Create(ctx context.Context, req *godo.KubernetesClusterCreateRequest) (*godo.KubernetesCluster, *godo.Response, error)
Get(ctx context.Context, clusterID string) (*godo.KubernetesCluster, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]*godo.KubernetesCluster, *godo.Response, error)
Update(ctx context.Context, clusterID string, req *godo.KubernetesClusterUpdateRequest) (*godo.KubernetesCluster, *godo.Response, error)
Delete(ctx context.Context, clusterID string) (*godo.Response, error)
UpdateNodePool(ctx context.Context, clusterID, poolID string, req *godo.KubernetesNodePoolUpdateRequest) (*godo.KubernetesNodePool, *godo.Response, error)
}
KubernetesClient is the godo Kubernetes interface (for mocking).
type KubernetesDriver ¶
type KubernetesDriver struct {
// contains filtered or unexported fields
}
KubernetesDriver manages DigitalOcean Kubernetes Service (DOKS) clusters (infra.k8s_cluster).
func NewKubernetesDriver ¶
func NewKubernetesDriver(c *godo.Client, region string) *KubernetesDriver
NewKubernetesDriver creates a KubernetesDriver backed by a real godo client.
func NewKubernetesDriverWithClient ¶
func NewKubernetesDriverWithClient(c KubernetesClient, region string) *KubernetesDriver
NewKubernetesDriverWithClient creates a driver with an injected client (for tests).
func (*KubernetesDriver) Create ¶
func (d *KubernetesDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*KubernetesDriver) Delete ¶
func (d *KubernetesDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*KubernetesDriver) Diff ¶
func (d *KubernetesDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*KubernetesDriver) HealthCheck ¶
func (d *KubernetesDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*KubernetesDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *KubernetesDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*KubernetesDriver) Read ¶
func (d *KubernetesDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*KubernetesDriver) Scale ¶
func (d *KubernetesDriver) Scale(ctx context.Context, ref interfaces.ResourceRef, replicas int) (*interfaces.ResourceOutput, error)
Scale resizes the first node pool of the cluster to the given replica count using godo.Kubernetes.UpdateNodePool.
func (*KubernetesDriver) SensitiveKeys ¶ added in v0.2.1
func (d *KubernetesDriver) SensitiveKeys() []string
func (*KubernetesDriver) Update ¶
func (d *KubernetesDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type LoadBalancerClient ¶
type LoadBalancerClient interface {
Create(ctx context.Context, req *godo.LoadBalancerRequest) (*godo.LoadBalancer, *godo.Response, error)
Get(ctx context.Context, lbID string) (*godo.LoadBalancer, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]godo.LoadBalancer, *godo.Response, error)
Update(ctx context.Context, lbID string, req *godo.LoadBalancerRequest) (*godo.LoadBalancer, *godo.Response, error)
Delete(ctx context.Context, lbID string) (*godo.Response, error)
}
LoadBalancerClient is the godo LoadBalancers interface (for mocking).
type LoadBalancerDriver ¶
type LoadBalancerDriver struct {
// contains filtered or unexported fields
}
LoadBalancerDriver manages DigitalOcean Load Balancers (infra.load_balancer).
func NewLoadBalancerDriver ¶
func NewLoadBalancerDriver(c *godo.Client, region string) *LoadBalancerDriver
NewLoadBalancerDriver creates a LoadBalancerDriver backed by a real godo client.
func NewLoadBalancerDriverWithClient ¶
func NewLoadBalancerDriverWithClient(c LoadBalancerClient, region string) *LoadBalancerDriver
NewLoadBalancerDriverWithClient creates a driver with an injected client (for tests).
func (*LoadBalancerDriver) Create ¶
func (d *LoadBalancerDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*LoadBalancerDriver) Delete ¶
func (d *LoadBalancerDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*LoadBalancerDriver) Diff ¶
func (d *LoadBalancerDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*LoadBalancerDriver) HealthCheck ¶
func (d *LoadBalancerDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*LoadBalancerDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *LoadBalancerDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*LoadBalancerDriver) Read ¶
func (d *LoadBalancerDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*LoadBalancerDriver) Scale ¶
func (d *LoadBalancerDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*LoadBalancerDriver) SensitiveKeys ¶ added in v0.2.1
func (d *LoadBalancerDriver) SensitiveKeys() []string
func (*LoadBalancerDriver) Update ¶
func (d *LoadBalancerDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type RegistryClient ¶
type RegistryClient interface {
Create(ctx context.Context, req *godo.RegistryCreateRequest) (*godo.Registry, *godo.Response, error)
Get(ctx context.Context) (*godo.Registry, *godo.Response, error)
Delete(ctx context.Context) (*godo.Response, error)
// ListRepositoryTags lists tags for a repository under the named registry.
// Used by AppPlatformDriver image-presence pre-flight.
ListRepositoryTags(ctx context.Context, registry, repository string, opts *godo.ListOptions) ([]*godo.RepositoryTag, *godo.Response, error)
}
RegistryClient is the godo Registry interface (for mocking).
type RegistryDriver ¶
type RegistryDriver struct {
// contains filtered or unexported fields
}
RegistryDriver manages the DigitalOcean Container Registry (infra.registry).
DOCR is account-level: Basic plan supports one registry per account, Professional supports up to ten. A registry can host many repositories, so multi-project consolidation under one registry is supported on every plan tier.
This driver is **account-singleton**: godo's Registry.Get(ctx) and Delete(ctx) take no name parameter, so the driver can only see and manage one registry per account regardless of plan tier. On Professional accounts with multiple registries, the others must be managed out-of-band.
Two deployment topologies are supported:
- Owned: declare an infra.registry IaC module; this driver manages create/update/destroy. Use on single-project DO accounts.
- Shared: omit the module declaration and reference only the path under ci.registries; bootstrap the registry once out-of-band. Use when multiple projects share a DO account.
See docs/container-registry.md for the canonical pattern, including migration guidance and the deploy-time verification snippet for Shared consumers. Picking the wrong topology produces a peer-deploy race that only surfaces when the second project tries to create the registry.
Create is idempotent against the DO API for same name + region. Update is a no-op (DOCR does not support in-place tier/region changes; drift is not reconciled).
func NewRegistryDriver ¶
func NewRegistryDriver(c *godo.Client) *RegistryDriver
NewRegistryDriver creates a RegistryDriver backed by a real godo client.
func NewRegistryDriverWithClient ¶
func NewRegistryDriverWithClient(c RegistryClient) *RegistryDriver
NewRegistryDriverWithClient creates a driver with an injected client (for tests).
func (*RegistryDriver) Create ¶
func (d *RegistryDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*RegistryDriver) Delete ¶
func (d *RegistryDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*RegistryDriver) Diff ¶
func (d *RegistryDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*RegistryDriver) HealthCheck ¶
func (d *RegistryDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*RegistryDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *RegistryDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*RegistryDriver) Read ¶
func (d *RegistryDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*RegistryDriver) Scale ¶
func (d *RegistryDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*RegistryDriver) SensitiveKeys ¶ added in v0.2.1
func (d *RegistryDriver) SensitiveKeys() []string
func (*RegistryDriver) Update ¶
func (d *RegistryDriver) Update(ctx context.Context, _ interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type SpacesBucket ¶
SpacesBucket is a minimal representation of a DigitalOcean Spaces bucket.
type SpacesBucketClient ¶
type SpacesBucketClient interface {
CreateBucket(ctx context.Context, name, region string) (*SpacesBucket, error)
GetBucket(ctx context.Context, name, region string) (*SpacesBucket, error)
DeleteBucket(ctx context.Context, name, region string) error
}
SpacesBucketClient is the interface for Spaces bucket management (injectable for mocking). DigitalOcean Spaces uses an S3-compatible API; this interface abstracts those calls.
type SpacesDriver ¶
type SpacesDriver struct {
// contains filtered or unexported fields
}
SpacesDriver manages DigitalOcean Spaces object storage buckets (infra.storage).
func NewSpacesDriver ¶
func NewSpacesDriver(_ *godo.Client, region, accessKey, secretKey string) *SpacesDriver
NewSpacesDriver creates a SpacesDriver. If accessKey and secretKey are non-empty a real S3-compatible client is used; otherwise a no-op client is used (suitable only for tests / dry-run mode).
func NewSpacesDriverWithClient ¶
func NewSpacesDriverWithClient(c SpacesBucketClient, region string) *SpacesDriver
NewSpacesDriverWithClient creates a driver with an injected client (for tests).
func (*SpacesDriver) Create ¶
func (d *SpacesDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*SpacesDriver) Delete ¶
func (d *SpacesDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*SpacesDriver) Diff ¶
func (d *SpacesDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*SpacesDriver) HealthCheck ¶
func (d *SpacesDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*SpacesDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *SpacesDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*SpacesDriver) Read ¶
func (d *SpacesDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*SpacesDriver) Scale ¶
func (d *SpacesDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*SpacesDriver) SensitiveKeys ¶ added in v0.2.1
func (d *SpacesDriver) SensitiveKeys() []string
func (*SpacesDriver) Update ¶
func (d *SpacesDriver) Update(_ context.Context, _ interfaces.ResourceRef, _ interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type SpacesKeyDriver ¶ added in v0.14.0
type SpacesKeyDriver struct {
// contains filtered or unexported fields
}
SpacesKeyDriver manages DigitalOcean Spaces access keys (infra.spaces_key). Constructed with a *godo.Client only — the secrets.Provider is the engine's concern under the v0.27.0 engine-side routing contract.
func NewSpacesKeyDriver ¶ added in v0.14.0
func NewSpacesKeyDriver(client *godo.Client) *SpacesKeyDriver
NewSpacesKeyDriver returns a driver bound to the given godo client.
func (*SpacesKeyDriver) Create ¶ added in v0.14.0
func (d *SpacesKeyDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
Create provisions a new Spaces key and returns its full outputs flagged for engine-side sensitive routing.
func (*SpacesKeyDriver) Delete ¶ added in v0.14.0
func (d *SpacesKeyDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
Delete removes the Spaces key by access_key. 404 is treated as success (idempotent delete) — sister provider RevokeProviderCredential takes the same stance.
func (*SpacesKeyDriver) Diff ¶ added in v0.14.0
func (d *SpacesKeyDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
Diff compares desired spec against current state. Spaces keys support in-place rename + grant updates; both go via Update (NeedsUpdate=true), no replace path.
func (*SpacesKeyDriver) HealthCheck ¶ added in v0.14.0
func (d *SpacesKeyDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
HealthCheck has no provider-side concept for Spaces keys; report healthy if the key still exists. Errors here are non-fatal at the call site.
func (*SpacesKeyDriver) ProviderIDFormat ¶ added in v0.14.0
func (d *SpacesKeyDriver) ProviderIDFormat() interfaces.ProviderIDFormat
ProviderIDFormat declares ProviderIDs are freeform (DO access keys are not UUIDs). Disables UUID validation while still enforcing non-empty.
func (*SpacesKeyDriver) Read ¶ added in v0.14.0
func (d *SpacesKeyDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
Read refreshes metadata for an existing Spaces key. secret_key is NOT returned (the DO API only exposes it on Create); the cached value lives in the secrets.Provider after Create routed it.
func (*SpacesKeyDriver) ResourceType ¶ added in v0.14.0
func (d *SpacesKeyDriver) ResourceType() string
ResourceType is the canonical resource-type string this driver serves.
func (*SpacesKeyDriver) Scale ¶ added in v0.14.0
func (d *SpacesKeyDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
Scale is not supported (access keys have no replica concept).
func (*SpacesKeyDriver) SensitiveKeys ¶ added in v0.14.0
func (d *SpacesKeyDriver) SensitiveKeys() []string
SensitiveKeys returns the output keys whose values should be masked in plan/diff display. The engine ALSO consults ResourceOutput.Sensitive per-call to decide routing through secrets.Provider; SensitiveKeys is strictly the display-side signal.
func (*SpacesKeyDriver) SupportsUpsert ¶ added in v0.14.0
func (d *SpacesKeyDriver) SupportsUpsert() bool
SupportsUpsert advertises that Read can locate by Name when ProviderID is empty, so wfctl ApplyPlan can recover from ErrResourceAlreadyExists.
func (*SpacesKeyDriver) Update ¶ added in v0.14.0
func (d *SpacesKeyDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
Update mutates a Spaces key in place. The DO API only allows changing grants and name — name change is treated as in-place rename via SpacesKeyUpdateRequest.
type StorageActionsClient ¶ added in v0.9.0
type StorageActionsClient interface {
Resize(ctx context.Context, volumeID string, sizeGigabytes int, regionSlug string) (*godo.Action, *godo.Response, error)
// DetachByDropletID detaches the volume from the given Droplet. Used by
// DropletDriver.Replace before deleting the old Droplet so DO does not
// reject the new Droplet's create with "422 storage already associated".
DetachByDropletID(ctx context.Context, volumeID string, dropletID int) (*godo.Action, *godo.Response, error)
}
StorageActionsClient is the subset of godo.StorageActionsService used by VolumeDriver (resize) and DropletDriver.Replace (volume detach before delete). Both operations are on the same godo.StorageActionsService so one interface covers both callers.
type StorageClient ¶ added in v0.9.0
type StorageClient interface {
CreateVolume(ctx context.Context, req *godo.VolumeCreateRequest) (*godo.Volume, *godo.Response, error)
GetVolume(ctx context.Context, volumeID string) (*godo.Volume, *godo.Response, error)
DeleteVolume(ctx context.Context, volumeID string) (*godo.Response, error)
ListVolumes(ctx context.Context, params *godo.ListVolumeParams) ([]godo.Volume, *godo.Response, error)
}
StorageClient is the godo Storage interface (for mocking). Subset of godo.StorageService — only the methods VolumeDriver and DropletDriver (volumes-by-name resolution) need.
type VPCClient ¶
type VPCClient interface {
Create(ctx context.Context, req *godo.VPCCreateRequest) (*godo.VPC, *godo.Response, error)
Get(ctx context.Context, vpcID string) (*godo.VPC, *godo.Response, error)
List(ctx context.Context, opts *godo.ListOptions) ([]*godo.VPC, *godo.Response, error)
Update(ctx context.Context, vpcID string, req *godo.VPCUpdateRequest) (*godo.VPC, *godo.Response, error)
Delete(ctx context.Context, vpcID string) (*godo.Response, error)
}
VPCClient is the godo VPCs interface (for mocking).
type VPCDriver ¶
type VPCDriver struct {
// contains filtered or unexported fields
}
VPCDriver manages DigitalOcean VPCs (infra.vpc).
func NewVPCDriver ¶
NewVPCDriver creates a VPCDriver backed by a real godo client.
func NewVPCDriverWithClient ¶
NewVPCDriverWithClient creates a driver with an injected client (for tests).
func (*VPCDriver) Create ¶
func (d *VPCDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*VPCDriver) Delete ¶
func (d *VPCDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*VPCDriver) Diff ¶
func (d *VPCDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*VPCDriver) HealthCheck ¶
func (d *VPCDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*VPCDriver) ProviderIDFormat ¶ added in v0.7.9
func (d *VPCDriver) ProviderIDFormat() interfaces.ProviderIDFormat
func (*VPCDriver) Read ¶
func (d *VPCDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*VPCDriver) Scale ¶
func (d *VPCDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*VPCDriver) SensitiveKeys ¶ added in v0.2.1
func (*VPCDriver) SupportsUpsert ¶ added in v0.7.3
SupportsUpsert reports that VPCDriver can locate a resource by name alone (empty ProviderID), enabling the ErrResourceAlreadyExists → upsert path.
func (*VPCDriver) Update ¶
func (d *VPCDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
type VolumeDriver ¶ added in v0.9.0
type VolumeDriver struct {
// contains filtered or unexported fields
}
VolumeDriver manages DigitalOcean Block Storage volumes (infra.volume).
Update semantics: only size GROWTH is supported in-place via StorageActions.Resize. Size shrinks are unsupported by DO; any other attribute change (region, filesystem_type) forces replace via Diff.
func NewVolumeDriver ¶ added in v0.9.0
func NewVolumeDriver(c *godo.Client, region string) *VolumeDriver
NewVolumeDriver creates a VolumeDriver backed by a real godo client.
func NewVolumeDriverWithClient ¶ added in v0.9.0
func NewVolumeDriverWithClient(c StorageClient, actions StorageActionsClient, region string) *VolumeDriver
NewVolumeDriverWithClient creates a driver with injected clients (for tests). The actions client may be nil for tests that do not exercise the resize path.
func (*VolumeDriver) Create ¶ added in v0.9.0
func (d *VolumeDriver) Create(ctx context.Context, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
func (*VolumeDriver) Delete ¶ added in v0.9.0
func (d *VolumeDriver) Delete(ctx context.Context, ref interfaces.ResourceRef) error
func (*VolumeDriver) Diff ¶ added in v0.9.0
func (d *VolumeDriver) Diff(_ context.Context, desired interfaces.ResourceSpec, current *interfaces.ResourceOutput) (*interfaces.DiffResult, error)
func (*VolumeDriver) HealthCheck ¶ added in v0.9.0
func (d *VolumeDriver) HealthCheck(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.HealthResult, error)
func (*VolumeDriver) ProviderIDFormat ¶ added in v0.9.0
func (d *VolumeDriver) ProviderIDFormat() interfaces.ProviderIDFormat
ProviderIDFormat is UUID — DO Block Storage volume IDs are UUIDs.
func (*VolumeDriver) Read ¶ added in v0.9.0
func (d *VolumeDriver) Read(ctx context.Context, ref interfaces.ResourceRef) (*interfaces.ResourceOutput, error)
func (*VolumeDriver) Scale ¶ added in v0.9.0
func (d *VolumeDriver) Scale(_ context.Context, _ interfaces.ResourceRef, _ int) (*interfaces.ResourceOutput, error)
func (*VolumeDriver) SensitiveKeys ¶ added in v0.9.0
func (d *VolumeDriver) SensitiveKeys() []string
func (*VolumeDriver) Update ¶ added in v0.9.0
func (d *VolumeDriver) Update(ctx context.Context, ref interfaces.ResourceRef, spec interfaces.ResourceSpec) (*interfaces.ResourceOutput, error)
Source Files
¶
- actions_wait.go
- api_gateway.go
- app_platform.go
- app_platform_buildspec.go
- app_platform_image_presence.go
- app_platform_migration_repair.go
- app_platform_region.go
- cache.go
- certificate.go
- database.go
- deploy.go
- dns.go
- droplet.go
- errors.go
- firewall.go
- iam_role.go
- kubernetes.go
- load_balancer.go
- registry.go
- shared.go
- spaces.go
- spaces_key.go
- util.go
- volume.go
- vpc.go