Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a Postgresql role to a database after the RDS instance was created via Terraform

I am trying to add a role to a Postgresql database after creating it in RDS via Terraform.

I have two separate modules, one creating the RDS instance, one adding the new role to it. The database address is an output of the persistence module and an input of the persistenceApplicationRole module. The problem seems to be that the Postgresql provider is ran before the RDS instance is created, so the address is empty.
The error I am getting is:

Error: Error initializing PostgreSQL client: error detecting capabilities: error PostgreSQL version: dial tcp :5432: connect: connection refused

  on ../modules/persistenceApplicationRole/main.tf line 9, in provider "postgresql":
   9: provider postgresql {

Running the modules separately via the -target=module.persistence flag works, since persistenceApplicationRole picks up the database address once it is created. I have found an example with this exact scenario for the MySQL Provider in their documentation here.

# module.persistenceApplicationRole
provider postgresql {
  host      = var.databaseAddress
  username  = data.external.root_credentials.result["username"]
  password  = data.external.root_credentials.result["password"]
  superuser = false
}

resource "postgresql_role" "application_role" {
  name     = data.external.application_credentials.result["username"]
  password = data.external.application_credentials.result["password"]

  login               = true
  encrypted_password  = true
  skip_reassign_owned = true
  skip_drop_role      = true
}
like image 649
vladvel Avatar asked Jan 25 '23 10:01

vladvel


1 Answers

The 1.4.0 release of the Postgresql provider added expected_version which you can use to avoid the feature detection at plan time that attempts to connect to the database. This was introduced in the 0.1.1 release a while back and broke people being able to create the underlying instance and configure the database at the same time.

To use the expected_version you would do something like this:

provider postgresql {
  host      = var.databaseAddress
  username  = data.external.root_credentials.result["username"]
  password  = data.external.root_credentials.result["password"]
  superuser = false

  expected_version = "10.1"
}

The more common use case would be creating an RDS instance or something else and interpolating that across:

resource "aws_db_instance" "database" {
  # ...
}

provider "postgresql" {
  version = ">=1.4.0"

  host             = aws_db_instance.database.address
  port             = aws_db_instance.database.port
  username         = aws_db_instance.database.user
  password         = aws_db_instance.database.password
  sslmode          = "require"
  connect_timeout  = 15
  superuser        = false
  expected_version = aws_db_instance.database.engine_version
}
like image 197
ydaetskcoR Avatar answered Jan 30 '23 03:01

ydaetskcoR