terraform-provider-digitalocean
terraform-provider-digitalocean copied to clipboard
digitalocean_database_cluster password is always empty
Bug Report
Describe the bug
When creating a digitalocean_database_cluster resource, the password attribute for the admin user (doadmin) is always returned as empty.
Affected Resource(s)
- digitalocean_database_cluster
Expected Behavior
I expect the password attribute to return the actual value.
Actual Behavior
It is not returning the password.
Steps to Reproduce
terraform apply
Terraform Configuration Files
terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.38.0"
}
null = {
source = "hashicorp/null"
version = "~> 3.1.0"
}
}
}
provider "digitalocean" {
token = var.do_token
}
variable "do_token" {}
variable "region" {
description = "DO region"
type = string
default = "fra1"
}
variable "services_names" {
description = "Name of the services you want to create"
type = object({
web = string
api = string
})
default = {
"web" = "web"
"api" = "api"
}
}
variable "app_name" {
description = "Name of the app"
type = string
default = "your-app-name"
}
variable "environments" {
description = "Map of environment names and their attributes"
type = map(any)
default = {
"prod" = {
"domain" : "your-domain.com",
"db" : {
"production" : true,
"size" : "db-s-1vcpu-1gb",
"node_count" : 1,
},
"api" : {
"instance_count" : 1,
"size_slug" : "apps-s-1vcpu-0.5gb",
"port" : 80
},
"web" : {
"instance_count" : 1,
"size_slug" : "basic-xxs",
"port" : 80
}
}
}
}
resource "digitalocean_database_cluster" "db-cluster" {
for_each = var.environments
name = "${each.key}-cluster"
engine = "pg"
version = "15"
size = var.environments[each.key].db.size
region = var.region
node_count = var.environments[each.key].db.node_count
}
resource "digitalocean_database_user" "api-user" {
for_each = var.environments
cluster_id = digitalocean_database_cluster.db-cluster[each.key].id
name = "${var.services_names.api}-user"
}
resource "digitalocean_database_db" "api-db" {
for_each = var.environments
cluster_id = digitalocean_database_cluster.db-cluster[each.key].id
name = "${var.services_names.api}-db"
}
resource "null_resource" "grant_permissions" {
for_each = var.environments
provisioner "local-exec" {
command = <<EOT
docker run --rm -e PGPASSWORD=${digitalocean_database_cluster.db-cluster[each.key].password} postgres:13 psql -h ${digitalocean_database_cluster.db-cluster[each.key].host} -U ${digitalocean_database_cluster.db-cluster[each.key].user} -p ${digitalocean_database_cluster.db-cluster[each.key].port} -d ${digitalocean_database_db.api-db[each.key].name} -c "GRANT ALL PRIVILEGES ON DATABASE ${digitalocean_database_db.api-db[each.key].name} TO ${digitalocean_database_user.api-user[each.key].name};"
EOT
environment = {
PGPASSWORD = digitalocean_database_cluster.db-cluster[each.key].password
}
}
depends_on = [
digitalocean_database_cluster.db-cluster,
digitalocean_database_user.api-user,
digitalocean_database_db.api-db
]
}
resource "digitalocean_database_firewall" "db-cluster-fw" {
for_each = var.environments
cluster_id = digitalocean_database_cluster.db-cluster[each.key].id
rule {
type = "app"
value = digitalocean_app.do-app[each.key].id
}
depends_on = [null_resource.grant_permissions]
}
resource "digitalocean_app" "do-app" {
for_each = var.environments
lifecycle {
ignore_changes = [
spec.0.features,
spec.0.region,
spec.0.service.0.image,
spec.0.service.1.image
]
}
spec {
name = "${var.app_name}-${each.key}"
region = var.region
domain {
name = var.environments[each.key].domain
}
alert {
rule = "DEPLOYMENT_FAILED"
}
service {
name = var.services_names.api
instance_count = var.environments[each.key].api.instance_count
instance_size_slug = var.environments[each.key].api.size_slug
image {
registry_type = "DOCKER_HUB"
repository = "nginx"
tag = "latest"
}
http_port = var.environments[each.key].api.port
env {
key = "DB_PASSWORD"
value = digitalocean_database_user.api-user[each.key].password
}
env {
key = "DB_HOST"
value = digitalocean_database_cluster.db-cluster[each.key].private_host
}
env {
key = "DB_PORT"
value = digitalocean_database_cluster.db-cluster[each.key].port
}
env {
key = "DB_NAME"
value = digitalocean_database_db.api-db[each.key].name
}
env {
key = "DB_USER"
value = digitalocean_database_user.api-user[each.key].name
}
}
service {
name = var.services_names.web
instance_count = var.environments[each.key].web.instance_count
instance_size_slug = var.environments[each.key].web.size_slug
image {
registry_type = "DOCKER_HUB"
repository = "nginx"
tag = "latest"
}
http_port = var.environments[each.key].web.port
}
database {
name = digitalocean_database_db.api-db[each.key].name
db_name = digitalocean_database_db.api-db[each.key].name
cluster_name = digitalocean_database_cluster.db-cluster[each.key].name
production = var.environments[each.key].db.production
}
ingress {
rule {
component {
name = var.services_names.api
}
match {
path {
prefix = "/api"
}
}
}
rule {
component {
name = var.services_names.web
}
match {
path {
prefix = "/"
}
}
}
}
}
}
Terraform version 1.8.4
Debug Output https://gist.github.com/razum90/780047c0f021b02832b8a67e6be84490
Additional context
I have also tried to save digitalocean_database_cluster.db-cluster[each.key].password
as an env variable to my service, and it shows empty there too.
Important Factoids
It seems like the initial call POST /v2/databases
returns the password. But the subsequent GET /v2/databases/{id}
does not. I guess the GET calls is used for some sort of polling. I suppose it would be an issue in case the response of the GET request is used to build the output of the digitalocean_database_cluster
resource.
BR