package provider import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/types" ) type composeModel struct { ID types.String `tfsdk:"id" dokploy:"composeId,id"` Name types.String `tfsdk:"name" dokploy:"name"` AppName types.String `tfsdk:"app_name" dokploy:"appName"` Description types.String `tfsdk:"description" dokploy:"description,nullable"` EnvironmentID types.String `tfsdk:"environment_id" dokploy:"environmentId"` ServerID types.String `tfsdk:"server_id" dokploy:"serverId,create"` ComposeType types.String `tfsdk:"compose_type" dokploy:"composeType"` ComposeFile types.String `tfsdk:"compose_file" dokploy:"composeFile"` ComposePath types.String `tfsdk:"compose_path" dokploy:"composePath"` SourceType types.String `tfsdk:"source_type" dokploy:"sourceType"` Command types.String `tfsdk:"command" dokploy:"command"` Env types.String `tfsdk:"env" dokploy:"env,nullable"` Repository types.String `tfsdk:"repository" dokploy:"repository,nullable"` Owner types.String `tfsdk:"owner" dokploy:"owner,nullable"` Branch types.String `tfsdk:"branch" dokploy:"branch,nullable"` GithubID types.String `tfsdk:"github_id" dokploy:"githubId,nullable"` GitlabID types.String `tfsdk:"gitlab_id" dokploy:"gitlabId,nullable"` GitlabProjectID types.Int64 `tfsdk:"gitlab_project_id" dokploy:"gitlabProjectId,nullable"` GitlabRepository types.String `tfsdk:"gitlab_repository" dokploy:"gitlabRepository,nullable"` GitlabOwner types.String `tfsdk:"gitlab_owner" dokploy:"gitlabOwner,nullable"` GitlabBranch types.String `tfsdk:"gitlab_branch" dokploy:"gitlabBranch,nullable"` GitlabNamespace types.String `tfsdk:"gitlab_path_namespace" dokploy:"gitlabPathNamespace,nullable"` GiteaID types.String `tfsdk:"gitea_id" dokploy:"giteaId,nullable"` GiteaRepository types.String `tfsdk:"gitea_repository" dokploy:"giteaRepository,nullable"` GiteaOwner types.String `tfsdk:"gitea_owner" dokploy:"giteaOwner,nullable"` GiteaBranch types.String `tfsdk:"gitea_branch" dokploy:"giteaBranch,nullable"` BitbucketID types.String `tfsdk:"bitbucket_id" dokploy:"bitbucketId,nullable"` BitbucketRepo types.String `tfsdk:"bitbucket_repository" dokploy:"bitbucketRepository,nullable"` BitbucketSlug types.String `tfsdk:"bitbucket_repository_slug" dokploy:"bitbucketRepositorySlug,nullable"` BitbucketOwner types.String `tfsdk:"bitbucket_owner" dokploy:"bitbucketOwner,nullable"` BitbucketBranch types.String `tfsdk:"bitbucket_branch" dokploy:"bitbucketBranch,nullable"` CustomGitURL types.String `tfsdk:"custom_git_url" dokploy:"customGitUrl,nullable"` CustomGitBranch types.String `tfsdk:"custom_git_branch" dokploy:"customGitBranch,nullable"` CustomGitSSHKey types.String `tfsdk:"custom_git_ssh_key_id" dokploy:"customGitSSHKeyId,nullable"` EnableSubmodules types.Bool `tfsdk:"enable_submodules" dokploy:"enableSubmodules"` AutoDeploy types.Bool `tfsdk:"auto_deploy" dokploy:"autoDeploy,nullable"` TriggerType types.String `tfsdk:"trigger_type" dokploy:"triggerType,nullable"` WatchPaths types.List `tfsdk:"watch_paths" dokploy:"watchPaths,nullable"` Suffix types.String `tfsdk:"suffix" dokploy:"suffix"` Randomize types.Bool `tfsdk:"randomize" dokploy:"randomize"` IsolatedDeployment types.Bool `tfsdk:"isolated_deployment" dokploy:"isolatedDeployment"` IsolatedDeployVolue types.Bool `tfsdk:"isolated_deployments_volume" dokploy:"isolatedDeploymentsVolume"` ComposeStatus types.String `tfsdk:"compose_status" dokploy:"composeStatus,ro"` CreatedAt types.String `tfsdk:"created_at" dokploy:"createdAt,ro"` // Terraform-only: controls the destroy call, never sent on create/update. DeleteVolumes types.Bool `tfsdk:"delete_volumes"` } func composeResource() ResourceSpec { return ResourceSpec{ Name: "compose", CreateProc: "compose.create", ReadProc: "compose.one", UpdateProc: "compose.update", DeleteProc: "compose.delete", UpdateAfterCreate: true, NewModel: func() any { return &composeModel{} }, DeleteBody: func(model any) map[string]any { // Dokploy requires this field on every compose delete. deleteVolumes := false if compose, ok := model.(*composeModel); ok && compose.DeleteVolumes.ValueBool() { deleteVolumes = true } return map[string]any{"deleteVolumes": deleteVolumes} }, Schema: schema.Schema{ MarkdownDescription: "A Docker Compose or Docker Swarm stack managed by Dokploy.\n\n" + "Set `compose_file` to manage the stack definition inline (with `source_type = \"raw\"`), or point " + "the stack at a Git repository and set `compose_path`.\n\n" + "~> Creating this resource does **not** deploy the stack.", Attributes: map[string]schema.Attribute{ "id": computedID("Unique compose identifier."), "name": requiredString("Display name of the stack."), "app_name": optionalComputedReplaceString("Unique Docker stack name. Generated by Dokploy when " + "omitted. Changing it forces a new stack."), "description": optionalString("Free-form description."), "environment_id": requiredReplaceString("Environment this stack belongs to."), "server_id": optionalReplaceString("Remote server to deploy on. Omit to use the Dokploy host itself."), "compose_type": enumString("Whether to run the stack with Docker Compose or Docker Swarm.", composeTypes, false), "compose_file": optionalComputedString("Inline Compose file contents. Used when `source_type` is `raw`."), "compose_path": optionalComputedString("Path to the Compose file within the repository."), "source_type": enumString("Where the Compose file comes from.", composeSources, false), "command": optionalComputedString("Custom `docker compose` command to run."), "env": optionalString("Environment variables in `KEY=value` format, one per line."), "repository": optionalString("GitHub repository name."), "owner": optionalString("GitHub repository owner."), "branch": optionalString("GitHub branch to deploy."), "github_id": optionalString("ID of the configured GitHub provider connection."), "gitlab_id": optionalString("ID of the configured GitLab provider connection."), "gitlab_project_id": schema.Int64Attribute{Optional: true, MarkdownDescription: "Numeric GitLab project ID."}, "gitlab_repository": optionalString("GitLab repository name."), "gitlab_owner": optionalString("GitLab repository owner."), "gitlab_branch": optionalString("GitLab branch to deploy."), "gitlab_path_namespace": optionalString("Full GitLab namespace path."), "gitea_id": optionalString("ID of the configured Gitea provider connection."), "gitea_repository": optionalString("Gitea repository name."), "gitea_owner": optionalString("Gitea repository owner."), "gitea_branch": optionalString("Gitea branch to deploy."), "bitbucket_id": optionalString("ID of the configured Bitbucket provider connection."), "bitbucket_repository": optionalString("Bitbucket repository name."), "bitbucket_repository_slug": optionalString("Bitbucket repository slug."), "bitbucket_owner": optionalString("Bitbucket repository owner."), "bitbucket_branch": optionalString("Bitbucket branch to deploy."), "custom_git_url": optionalString("Git remote URL, when `source_type` is `git`."), "custom_git_branch": optionalString("Branch to deploy for a custom Git remote."), "custom_git_ssh_key_id": optionalString("SSH key used to clone a private custom Git remote."), "enable_submodules": optionalComputedBool("Clone Git submodules when checking out the repository."), "auto_deploy": optionalComputedBool("Deploy automatically when the configured trigger fires."), "trigger_type": enumString("What triggers an automatic deployment.", triggerTypes, false), "watch_paths": optionalComputedStringList("Glob patterns that limit which changed paths trigger " + "an automatic deployment."), "suffix": optionalComputedString("Suffix appended to generated resource names."), "randomize": optionalComputedBool("Append a random suffix to service and volume names."), "isolated_deployment": optionalComputedBool("Run the stack on its own isolated Docker network."), "isolated_deployments_volume": optionalComputedBool("Prefix volume names for isolated deployments. " + "Retained for backwards compatibility."), "compose_status": computedString("Current status reported by Dokploy: `idle`, `running`, `done` or `error`."), "created_at": computedString("RFC 3339 timestamp of when the stack was created."), "delete_volumes": optionalBool("Whether to delete the stack's Docker volumes when this resource is " + "destroyed. Defaults to `false`, which preserves the data."), }, }, } }