Cover what Dokploy v0.30 added
Six new resources, all backed by endpoints that did not exist before v0.30.0
and verified end-to-end against a live v0.30.2 instance:
dokploy_network Docker networks, now first-class. Services attach
through network_ids, which is what deprecates
Compose's isolated_deployment upstream.
dokploy_dns_provider Cloudflare or Route53, so adding a domain creates
its DNS record.
dokploy_vault_provider Env values resolved from HashiCorp Vault, Infisical,
AWS, Doppler, Azure or Scaleway at deploy time, so
the secret never lands in Dokploy or in state.
dokploy_schedule Cron jobs in a container, a stack, or on a server.
dokploy_volume_backup Scheduled backups of a named volume — the companion
to a mount that persists.
dokploy_libsql The sixth managed database engine.
libsql.create is the strictest endpoint in the API: eleven keys required to
be present, several only meaningfully null, no generated service name, and it
returns `true` rather than the row. CreateDefaults and ListIDs absorb all
three so the resource behaves like every other database.
Also filled the gaps a field-by-field diff against the live schema turned up:
domain gains `enabled` (the v0.30.0 park-a-domain toggle), compose gains
create_env_file, icon and service_networks, application gains icon and
preview_require_collaborator_permissions, and mounts accept libsql.
DNS and vault credentials are masked by Dokploy on read, so `config` is
tagged noread and keeps the configured value, as the basic-auth password
already does.
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
// Docker networks became first-class in Dokploy v0.30.0. Services attach to
|
||||
// them through `network_ids` on the application, compose and database
|
||||
// resources.
|
||||
|
||||
type networkModel struct {
|
||||
ID types.String `tfsdk:"id" dokploy:"networkId,id"`
|
||||
Name types.String `tfsdk:"name" dokploy:"name"`
|
||||
Driver types.String `tfsdk:"driver" dokploy:"driver"`
|
||||
Internal types.Bool `tfsdk:"internal" dokploy:"internal"`
|
||||
Attachable types.Bool `tfsdk:"attachable" dokploy:"attachable"`
|
||||
EnableIPv4 types.Bool `tfsdk:"enable_ipv4" dokploy:"enableIPv4"`
|
||||
EnableIPv6 types.Bool `tfsdk:"enable_ipv6" dokploy:"enableIPv6"`
|
||||
MTU types.Int64 `tfsdk:"mtu" dokploy:"mtu,nullable"`
|
||||
|
||||
// IPAM is Docker's address-management block: {"subnet","gateway","ipRange"}.
|
||||
IPAM jsontypes.Normalized `tfsdk:"ipam" dokploy:"ipam,nullable"`
|
||||
|
||||
ServerID types.String `tfsdk:"server_id" dokploy:"serverId,create"`
|
||||
OrganizationID types.String `tfsdk:"organization_id" dokploy:"organizationId,ro"`
|
||||
CreatedAt types.String `tfsdk:"created_at" dokploy:"createdAt,ro"`
|
||||
}
|
||||
|
||||
func networkResource() ResourceSpec {
|
||||
// Dokploy exposes no `network.update`: a Docker network's driver, subnet
|
||||
// and flags are fixed once it exists. Every configurable attribute
|
||||
// therefore forces replacement.
|
||||
return ResourceSpec{
|
||||
Name: "network",
|
||||
CreateProc: "network.create",
|
||||
ReadProc: "network.one",
|
||||
DeleteProc: "network.remove",
|
||||
NewModel: func() any { return &networkModel{} },
|
||||
Schema: schema.Schema{
|
||||
MarkdownDescription: "A Docker network managed by Dokploy.\n\n" +
|
||||
"Attach services to it with `network_ids` on `dokploy_application`, `dokploy_compose` and the " +
|
||||
"database resources. Every service also joins the shared `dokploy-network` unless " +
|
||||
"`detach_dokploy_network` is set.\n\n" +
|
||||
"~> Docker networks are immutable. Dokploy has no update endpoint, so changing any attribute " +
|
||||
"replaces the network — which detaches the services currently using it until they redeploy.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": computedID("Unique network identifier."),
|
||||
"name": requiredReplaceString("Name of the Docker network."),
|
||||
"driver": schema.StringAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
MarkdownDescription: "Network driver. Use `overlay` for multi-node Swarm clusters and `bridge` for a single host. Valid values: `bridge`, `overlay`.",
|
||||
Validators: enumValidator(networkDrivers),
|
||||
PlanModifiers: requiresReplaceString(),
|
||||
},
|
||||
"internal": replaceBool("Isolate the network from external access.", false),
|
||||
"attachable": replaceBool("Allow standalone containers to attach to an overlay network.", false),
|
||||
"enable_ipv4": replaceBool("Enable IPv4 address allocation.", true),
|
||||
"enable_ipv6": replaceBool("Enable IPv6 address allocation.", false),
|
||||
"mtu": schema.Int64Attribute{
|
||||
Optional: true,
|
||||
MarkdownDescription: "Maximum transmission unit for the network. Leave unset to use Docker's default.",
|
||||
PlanModifiers: []planmodifier.Int64{int64planmodifier.RequiresReplace()},
|
||||
},
|
||||
"ipam": schema.StringAttribute{
|
||||
Optional: true,
|
||||
CustomType: jsontypes.NormalizedType{},
|
||||
MarkdownDescription: "Custom IP address management, as a JSON object with `subnet`, `gateway` " +
|
||||
"and `ipRange` keys. Leave unset to let Docker choose a subnet.",
|
||||
PlanModifiers: requiresReplaceString(),
|
||||
},
|
||||
"server_id": optionalReplaceString("Remote server to create the network on. Omit to use the Dokploy host itself."),
|
||||
"organization_id": computedString("Organization that owns the network."),
|
||||
"created_at": computedString("RFC 3339 timestamp of when the network was created."),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// replaceBool is an optional boolean with a fixed default that cannot be
|
||||
// changed in place.
|
||||
func replaceBool(description string, def bool) schema.BoolAttribute {
|
||||
return schema.BoolAttribute{
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
MarkdownDescription: description,
|
||||
Default: booldefault.StaticBool(def),
|
||||
PlanModifiers: []planmodifier.Bool{boolplanmodifier.RequiresReplace()},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user