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/types" ) // The five managed databases share almost their entire surface. The Terraform // Plugin Framework cannot reflect into embedded structs, so each model is // written out flat, but the schema attributes are assembled from one place. // databaseCommonSchema returns the attributes every database resource exposes. // engine is used to word the descriptions. func databaseCommonSchema(engine string) map[string]schema.Attribute { return map[string]schema.Attribute{ "id": computedID("Unique " + engine + " identifier."), "name": requiredString("Display name of the database."), "app_name": optionalComputedReplaceString("Unique Docker service name. Generated by Dokploy when omitted. " + "Changing it forces a new database."), "description": optionalString("Free-form description."), "environment_id": requiredReplaceString("Environment this database belongs to."), "server_id": optionalReplaceString("Remote server to deploy on. Omit to use the Dokploy host itself."), "command": optionalString("Override the container entrypoint command."), "args": optionalComputedStringList("Arguments appended to the container command."), "env": optionalString("Environment variables in `KEY=value` format, one per line."), "memory_reservation": optionalString("Soft memory reservation, for example `256m`."), "memory_limit": optionalString("Hard memory limit, for example `512m`."), "cpu_reservation": optionalString("Soft CPU reservation, for example `0.5`."), "cpu_limit": optionalString("Hard CPU limit, for example `1`."), "external_port": schema.Int64Attribute{ Optional: true, MarkdownDescription: "Host port to expose the database on. Leave unset to keep the database reachable " + "only from inside the Docker network.", }, "replicas": optionalComputedInt("Number of replicas to run."), "network_ids": optionalComputedStringList("IDs of additional Docker networks to attach."), "detach_dokploy_network": optionalComputedBool("Detach the service from the shared `dokploy-network`."), "health_check_swarm": optionalJSON("Docker Swarm health check configuration, as a JSON object."), "restart_policy_swarm": optionalJSON("Docker Swarm restart policy, as a JSON object."), "placement_swarm": optionalJSON("Docker Swarm placement constraints, as a JSON object."), "update_config_swarm": optionalJSON("Docker Swarm rolling update configuration, as a JSON object."), "rollback_config_swarm": optionalJSON("Docker Swarm rollback configuration, as a JSON object."), "mode_swarm": optionalJSON("Docker Swarm service mode, as a JSON object."), "labels_swarm": optionalJSON("Docker Swarm service labels, as a JSON object."), "network_swarm": optionalJSON("Docker Swarm network attachments, as a JSON array."), "endpoint_spec_swarm": optionalJSON("Docker Swarm endpoint specification, as a JSON object."), "ulimits_swarm": optionalJSON("Docker Swarm ulimits, as a JSON object."), "stop_grace_period_swarm": schema.Int64Attribute{Optional: true, MarkdownDescription: "Grace period in nanoseconds before a container is killed."}, "application_status": computedString("Current status reported by Dokploy: `idle`, `running`, `done` or `error`."), "created_at": computedString("RFC 3339 timestamp of when the database was created."), } } func withAttributes(base map[string]schema.Attribute, extra map[string]schema.Attribute) map[string]schema.Attribute { for name, attribute := range extra { base[name] = attribute } return base } func databaseNote(engine string) string { return "A managed " + engine + " instance running on Dokploy.\n\n" + "~> Creating this resource provisions the service definition but does **not** start a deployment. " + "Deploy it from the Dokploy UI or CLI.\n\n" + "~> Credentials are stored in Terraform state. Use a state backend with encryption at rest." } // ---------------------------------------------------------------- PostgreSQL type postgresModel struct { ID types.String `tfsdk:"id" dokploy:"postgresId,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"` DatabaseName types.String `tfsdk:"database_name" dokploy:"databaseName"` DatabaseUser types.String `tfsdk:"database_user" dokploy:"databaseUser"` DatabasePassword types.String `tfsdk:"database_password" dokploy:"databasePassword"` DockerImage types.String `tfsdk:"docker_image" dokploy:"dockerImage"` Command types.String `tfsdk:"command" dokploy:"command,nullable"` Args types.List `tfsdk:"args" dokploy:"args,nullable"` Env types.String `tfsdk:"env" dokploy:"env,nullable"` MemoryReserve types.String `tfsdk:"memory_reservation" dokploy:"memoryReservation,nullable"` MemoryLimit types.String `tfsdk:"memory_limit" dokploy:"memoryLimit,nullable"` CPUReserve types.String `tfsdk:"cpu_reservation" dokploy:"cpuReservation,nullable"` CPULimit types.String `tfsdk:"cpu_limit" dokploy:"cpuLimit,nullable"` ExternalPort types.Int64 `tfsdk:"external_port" dokploy:"externalPort,nullable"` Replicas types.Int64 `tfsdk:"replicas" dokploy:"replicas"` NetworkIDs types.List `tfsdk:"network_ids" dokploy:"networkIds"` DetachDokployNetwork types.Bool `tfsdk:"detach_dokploy_network" dokploy:"detachDokployNetwork"` HealthCheckSwarm jsontypes.Normalized `tfsdk:"health_check_swarm" dokploy:"healthCheckSwarm,nullable"` RestartPolicySwarm jsontypes.Normalized `tfsdk:"restart_policy_swarm" dokploy:"restartPolicySwarm,nullable"` PlacementSwarm jsontypes.Normalized `tfsdk:"placement_swarm" dokploy:"placementSwarm,nullable"` UpdateConfigSwarm jsontypes.Normalized `tfsdk:"update_config_swarm" dokploy:"updateConfigSwarm,nullable"` RollbackConfigSwarm jsontypes.Normalized `tfsdk:"rollback_config_swarm" dokploy:"rollbackConfigSwarm,nullable"` ModeSwarm jsontypes.Normalized `tfsdk:"mode_swarm" dokploy:"modeSwarm,nullable"` LabelsSwarm jsontypes.Normalized `tfsdk:"labels_swarm" dokploy:"labelsSwarm,nullable"` NetworkSwarm jsontypes.Normalized `tfsdk:"network_swarm" dokploy:"networkSwarm,nullable"` EndpointSpecSwarm jsontypes.Normalized `tfsdk:"endpoint_spec_swarm" dokploy:"endpointSpecSwarm,nullable"` UlimitsSwarm jsontypes.Normalized `tfsdk:"ulimits_swarm" dokploy:"ulimitsSwarm,nullable"` StopGracePeriodSwarm types.Int64 `tfsdk:"stop_grace_period_swarm" dokploy:"stopGracePeriodSwarm,nullable"` ApplicationStatus types.String `tfsdk:"application_status" dokploy:"applicationStatus,ro"` CreatedAt types.String `tfsdk:"created_at" dokploy:"createdAt,ro"` } func postgresResource() ResourceSpec { return ResourceSpec{ Name: "postgres", // The create endpoint accepts only the core fields; everything else // (limits, env, swarm settings) has to be written through update. UpdateAfterCreate: true, CreateProc: "postgres.create", ReadProc: "postgres.one", UpdateProc: "postgres.update", DeleteProc: "postgres.remove", NewModel: func() any { return &postgresModel{} }, Schema: schema.Schema{ MarkdownDescription: databaseNote("PostgreSQL"), Attributes: withAttributes(databaseCommonSchema("postgres"), map[string]schema.Attribute{ "database_name": requiredString("Name of the database to create."), "database_user": requiredString("Database user to create."), "database_password": sensitiveString("Password for the database user.", true), "docker_image": requiredString("PostgreSQL image to run, for example `postgres:16`."), }), }, } } // --------------------------------------------------------------------- MySQL type mysqlModel struct { ID types.String `tfsdk:"id" dokploy:"mysqlId,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"` DatabaseName types.String `tfsdk:"database_name" dokploy:"databaseName"` DatabaseUser types.String `tfsdk:"database_user" dokploy:"databaseUser"` DatabasePassword types.String `tfsdk:"database_password" dokploy:"databasePassword"` DatabaseRootPass types.String `tfsdk:"database_root_password" dokploy:"databaseRootPassword"` DockerImage types.String `tfsdk:"docker_image" dokploy:"dockerImage"` Command types.String `tfsdk:"command" dokploy:"command,nullable"` Args types.List `tfsdk:"args" dokploy:"args,nullable"` Env types.String `tfsdk:"env" dokploy:"env,nullable"` MemoryReserve types.String `tfsdk:"memory_reservation" dokploy:"memoryReservation,nullable"` MemoryLimit types.String `tfsdk:"memory_limit" dokploy:"memoryLimit,nullable"` CPUReserve types.String `tfsdk:"cpu_reservation" dokploy:"cpuReservation,nullable"` CPULimit types.String `tfsdk:"cpu_limit" dokploy:"cpuLimit,nullable"` ExternalPort types.Int64 `tfsdk:"external_port" dokploy:"externalPort,nullable"` Replicas types.Int64 `tfsdk:"replicas" dokploy:"replicas"` NetworkIDs types.List `tfsdk:"network_ids" dokploy:"networkIds"` DetachDokployNetwork types.Bool `tfsdk:"detach_dokploy_network" dokploy:"detachDokployNetwork"` HealthCheckSwarm jsontypes.Normalized `tfsdk:"health_check_swarm" dokploy:"healthCheckSwarm,nullable"` RestartPolicySwarm jsontypes.Normalized `tfsdk:"restart_policy_swarm" dokploy:"restartPolicySwarm,nullable"` PlacementSwarm jsontypes.Normalized `tfsdk:"placement_swarm" dokploy:"placementSwarm,nullable"` UpdateConfigSwarm jsontypes.Normalized `tfsdk:"update_config_swarm" dokploy:"updateConfigSwarm,nullable"` RollbackConfigSwarm jsontypes.Normalized `tfsdk:"rollback_config_swarm" dokploy:"rollbackConfigSwarm,nullable"` ModeSwarm jsontypes.Normalized `tfsdk:"mode_swarm" dokploy:"modeSwarm,nullable"` LabelsSwarm jsontypes.Normalized `tfsdk:"labels_swarm" dokploy:"labelsSwarm,nullable"` NetworkSwarm jsontypes.Normalized `tfsdk:"network_swarm" dokploy:"networkSwarm,nullable"` EndpointSpecSwarm jsontypes.Normalized `tfsdk:"endpoint_spec_swarm" dokploy:"endpointSpecSwarm,nullable"` UlimitsSwarm jsontypes.Normalized `tfsdk:"ulimits_swarm" dokploy:"ulimitsSwarm,nullable"` StopGracePeriodSwarm types.Int64 `tfsdk:"stop_grace_period_swarm" dokploy:"stopGracePeriodSwarm,nullable"` ApplicationStatus types.String `tfsdk:"application_status" dokploy:"applicationStatus,ro"` CreatedAt types.String `tfsdk:"created_at" dokploy:"createdAt,ro"` } func mysqlResource() ResourceSpec { return ResourceSpec{ Name: "mysql", // The create endpoint accepts only the core fields; everything else // (limits, env, swarm settings) has to be written through update. UpdateAfterCreate: true, CreateProc: "mysql.create", ReadProc: "mysql.one", UpdateProc: "mysql.update", DeleteProc: "mysql.remove", NewModel: func() any { return &mysqlModel{} }, Schema: schema.Schema{ MarkdownDescription: databaseNote("MySQL"), Attributes: withAttributes(databaseCommonSchema("mysql"), map[string]schema.Attribute{ "database_name": requiredString("Name of the database to create."), "database_user": requiredString("Database user to create."), "database_password": sensitiveString("Password for the database user.", true), "database_root_password": sensitiveString("Password for the MySQL `root` user.", true), "docker_image": requiredString("MySQL image to run, for example `mysql:8`."), }), }, } } // ------------------------------------------------------------------- MariaDB type mariadbModel struct { ID types.String `tfsdk:"id" dokploy:"mariadbId,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"` DatabaseName types.String `tfsdk:"database_name" dokploy:"databaseName"` DatabaseUser types.String `tfsdk:"database_user" dokploy:"databaseUser"` DatabasePassword types.String `tfsdk:"database_password" dokploy:"databasePassword"` DatabaseRootPass types.String `tfsdk:"database_root_password" dokploy:"databaseRootPassword"` DockerImage types.String `tfsdk:"docker_image" dokploy:"dockerImage"` Command types.String `tfsdk:"command" dokploy:"command,nullable"` Args types.List `tfsdk:"args" dokploy:"args,nullable"` Env types.String `tfsdk:"env" dokploy:"env,nullable"` MemoryReserve types.String `tfsdk:"memory_reservation" dokploy:"memoryReservation,nullable"` MemoryLimit types.String `tfsdk:"memory_limit" dokploy:"memoryLimit,nullable"` CPUReserve types.String `tfsdk:"cpu_reservation" dokploy:"cpuReservation,nullable"` CPULimit types.String `tfsdk:"cpu_limit" dokploy:"cpuLimit,nullable"` ExternalPort types.Int64 `tfsdk:"external_port" dokploy:"externalPort,nullable"` Replicas types.Int64 `tfsdk:"replicas" dokploy:"replicas"` NetworkIDs types.List `tfsdk:"network_ids" dokploy:"networkIds"` DetachDokployNetwork types.Bool `tfsdk:"detach_dokploy_network" dokploy:"detachDokployNetwork"` HealthCheckSwarm jsontypes.Normalized `tfsdk:"health_check_swarm" dokploy:"healthCheckSwarm,nullable"` RestartPolicySwarm jsontypes.Normalized `tfsdk:"restart_policy_swarm" dokploy:"restartPolicySwarm,nullable"` PlacementSwarm jsontypes.Normalized `tfsdk:"placement_swarm" dokploy:"placementSwarm,nullable"` UpdateConfigSwarm jsontypes.Normalized `tfsdk:"update_config_swarm" dokploy:"updateConfigSwarm,nullable"` RollbackConfigSwarm jsontypes.Normalized `tfsdk:"rollback_config_swarm" dokploy:"rollbackConfigSwarm,nullable"` ModeSwarm jsontypes.Normalized `tfsdk:"mode_swarm" dokploy:"modeSwarm,nullable"` LabelsSwarm jsontypes.Normalized `tfsdk:"labels_swarm" dokploy:"labelsSwarm,nullable"` NetworkSwarm jsontypes.Normalized `tfsdk:"network_swarm" dokploy:"networkSwarm,nullable"` EndpointSpecSwarm jsontypes.Normalized `tfsdk:"endpoint_spec_swarm" dokploy:"endpointSpecSwarm,nullable"` UlimitsSwarm jsontypes.Normalized `tfsdk:"ulimits_swarm" dokploy:"ulimitsSwarm,nullable"` StopGracePeriodSwarm types.Int64 `tfsdk:"stop_grace_period_swarm" dokploy:"stopGracePeriodSwarm,nullable"` ApplicationStatus types.String `tfsdk:"application_status" dokploy:"applicationStatus,ro"` CreatedAt types.String `tfsdk:"created_at" dokploy:"createdAt,ro"` } func mariadbResource() ResourceSpec { return ResourceSpec{ Name: "mariadb", // The create endpoint accepts only the core fields; everything else // (limits, env, swarm settings) has to be written through update. UpdateAfterCreate: true, CreateProc: "mariadb.create", ReadProc: "mariadb.one", UpdateProc: "mariadb.update", DeleteProc: "mariadb.remove", NewModel: func() any { return &mariadbModel{} }, Schema: schema.Schema{ MarkdownDescription: databaseNote("MariaDB"), Attributes: withAttributes(databaseCommonSchema("mariadb"), map[string]schema.Attribute{ "database_name": requiredString("Name of the database to create."), "database_user": requiredString("Database user to create."), "database_password": sensitiveString("Password for the database user.", true), "database_root_password": sensitiveString("Password for the MariaDB `root` user.", true), "docker_image": requiredString("MariaDB image to run, for example `mariadb:11`."), }), }, } } // ------------------------------------------------------------------- MongoDB type mongoModel struct { ID types.String `tfsdk:"id" dokploy:"mongoId,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"` DatabaseUser types.String `tfsdk:"database_user" dokploy:"databaseUser"` DatabasePassword types.String `tfsdk:"database_password" dokploy:"databasePassword"` DockerImage types.String `tfsdk:"docker_image" dokploy:"dockerImage"` ReplicaSets types.Bool `tfsdk:"replica_sets" dokploy:"replicaSets,nullable"` Command types.String `tfsdk:"command" dokploy:"command,nullable"` Args types.List `tfsdk:"args" dokploy:"args,nullable"` Env types.String `tfsdk:"env" dokploy:"env,nullable"` MemoryReserve types.String `tfsdk:"memory_reservation" dokploy:"memoryReservation,nullable"` MemoryLimit types.String `tfsdk:"memory_limit" dokploy:"memoryLimit,nullable"` CPUReserve types.String `tfsdk:"cpu_reservation" dokploy:"cpuReservation,nullable"` CPULimit types.String `tfsdk:"cpu_limit" dokploy:"cpuLimit,nullable"` ExternalPort types.Int64 `tfsdk:"external_port" dokploy:"externalPort,nullable"` Replicas types.Int64 `tfsdk:"replicas" dokploy:"replicas"` NetworkIDs types.List `tfsdk:"network_ids" dokploy:"networkIds"` DetachDokployNetwork types.Bool `tfsdk:"detach_dokploy_network" dokploy:"detachDokployNetwork"` HealthCheckSwarm jsontypes.Normalized `tfsdk:"health_check_swarm" dokploy:"healthCheckSwarm,nullable"` RestartPolicySwarm jsontypes.Normalized `tfsdk:"restart_policy_swarm" dokploy:"restartPolicySwarm,nullable"` PlacementSwarm jsontypes.Normalized `tfsdk:"placement_swarm" dokploy:"placementSwarm,nullable"` UpdateConfigSwarm jsontypes.Normalized `tfsdk:"update_config_swarm" dokploy:"updateConfigSwarm,nullable"` RollbackConfigSwarm jsontypes.Normalized `tfsdk:"rollback_config_swarm" dokploy:"rollbackConfigSwarm,nullable"` ModeSwarm jsontypes.Normalized `tfsdk:"mode_swarm" dokploy:"modeSwarm,nullable"` LabelsSwarm jsontypes.Normalized `tfsdk:"labels_swarm" dokploy:"labelsSwarm,nullable"` NetworkSwarm jsontypes.Normalized `tfsdk:"network_swarm" dokploy:"networkSwarm,nullable"` EndpointSpecSwarm jsontypes.Normalized `tfsdk:"endpoint_spec_swarm" dokploy:"endpointSpecSwarm,nullable"` UlimitsSwarm jsontypes.Normalized `tfsdk:"ulimits_swarm" dokploy:"ulimitsSwarm,nullable"` StopGracePeriodSwarm types.Int64 `tfsdk:"stop_grace_period_swarm" dokploy:"stopGracePeriodSwarm,nullable"` ApplicationStatus types.String `tfsdk:"application_status" dokploy:"applicationStatus,ro"` CreatedAt types.String `tfsdk:"created_at" dokploy:"createdAt,ro"` } func mongoResource() ResourceSpec { return ResourceSpec{ Name: "mongo", // The create endpoint accepts only the core fields; everything else // (limits, env, swarm settings) has to be written through update. UpdateAfterCreate: true, CreateProc: "mongo.create", ReadProc: "mongo.one", UpdateProc: "mongo.update", DeleteProc: "mongo.remove", NewModel: func() any { return &mongoModel{} }, Schema: schema.Schema{ MarkdownDescription: databaseNote("MongoDB"), Attributes: withAttributes(databaseCommonSchema("mongo"), map[string]schema.Attribute{ "database_user": requiredString("Root username to create."), "database_password": sensitiveString("Password for the root user.", true), "docker_image": optionalComputedString("MongoDB image to run. Defaults to `mongo:8`."), "replica_sets": optionalComputedBool("Start the instance as a single-node replica set."), }), }, } } // --------------------------------------------------------------------- Redis type redisModel struct { ID types.String `tfsdk:"id" dokploy:"redisId,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"` DatabasePassword types.String `tfsdk:"database_password" dokploy:"databasePassword"` DockerImage types.String `tfsdk:"docker_image" dokploy:"dockerImage"` Command types.String `tfsdk:"command" dokploy:"command,nullable"` Args types.List `tfsdk:"args" dokploy:"args,nullable"` Env types.String `tfsdk:"env" dokploy:"env,nullable"` MemoryReserve types.String `tfsdk:"memory_reservation" dokploy:"memoryReservation,nullable"` MemoryLimit types.String `tfsdk:"memory_limit" dokploy:"memoryLimit,nullable"` CPUReserve types.String `tfsdk:"cpu_reservation" dokploy:"cpuReservation,nullable"` CPULimit types.String `tfsdk:"cpu_limit" dokploy:"cpuLimit,nullable"` ExternalPort types.Int64 `tfsdk:"external_port" dokploy:"externalPort,nullable"` Replicas types.Int64 `tfsdk:"replicas" dokploy:"replicas"` NetworkIDs types.List `tfsdk:"network_ids" dokploy:"networkIds"` DetachDokployNetwork types.Bool `tfsdk:"detach_dokploy_network" dokploy:"detachDokployNetwork"` HealthCheckSwarm jsontypes.Normalized `tfsdk:"health_check_swarm" dokploy:"healthCheckSwarm,nullable"` RestartPolicySwarm jsontypes.Normalized `tfsdk:"restart_policy_swarm" dokploy:"restartPolicySwarm,nullable"` PlacementSwarm jsontypes.Normalized `tfsdk:"placement_swarm" dokploy:"placementSwarm,nullable"` UpdateConfigSwarm jsontypes.Normalized `tfsdk:"update_config_swarm" dokploy:"updateConfigSwarm,nullable"` RollbackConfigSwarm jsontypes.Normalized `tfsdk:"rollback_config_swarm" dokploy:"rollbackConfigSwarm,nullable"` ModeSwarm jsontypes.Normalized `tfsdk:"mode_swarm" dokploy:"modeSwarm,nullable"` LabelsSwarm jsontypes.Normalized `tfsdk:"labels_swarm" dokploy:"labelsSwarm,nullable"` NetworkSwarm jsontypes.Normalized `tfsdk:"network_swarm" dokploy:"networkSwarm,nullable"` EndpointSpecSwarm jsontypes.Normalized `tfsdk:"endpoint_spec_swarm" dokploy:"endpointSpecSwarm,nullable"` UlimitsSwarm jsontypes.Normalized `tfsdk:"ulimits_swarm" dokploy:"ulimitsSwarm,nullable"` StopGracePeriodSwarm types.Int64 `tfsdk:"stop_grace_period_swarm" dokploy:"stopGracePeriodSwarm,nullable"` ApplicationStatus types.String `tfsdk:"application_status" dokploy:"applicationStatus,ro"` CreatedAt types.String `tfsdk:"created_at" dokploy:"createdAt,ro"` } func redisResource() ResourceSpec { return ResourceSpec{ Name: "redis", // The create endpoint accepts only the core fields; everything else // (limits, env, swarm settings) has to be written through update. UpdateAfterCreate: true, CreateProc: "redis.create", ReadProc: "redis.one", UpdateProc: "redis.update", DeleteProc: "redis.remove", NewModel: func() any { return &redisModel{} }, Schema: schema.Schema{ MarkdownDescription: databaseNote("Redis"), Attributes: withAttributes(databaseCommonSchema("redis"), map[string]schema.Attribute{ "database_password": sensitiveString("Password used to authenticate to Redis.", true), "docker_image": requiredString("Redis image to run, for example `redis:7`."), }), }, } }