Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible regression on resource postgresql_function, suddenly causing errors related to database not found. #291

Open
dmaspataud opened this issue Mar 21, 2023 · 5 comments

Comments

@dmaspataud
Copy link

dmaspataud commented Mar 21, 2023

Hi there,

Thank you for opening an issue. Please provide the following information:

Terraform Version

Terraform v1.4.2
on darwin_amd64

  • provider registry.terraform.io/cyrilgdn/postgresql v1.19.0
  • provider registry.terraform.io/hashicorp/aws v4.59.0
  • provider registry.terraform.io/hashicorp/random v3.4.3

Affected Resource(s)

postgresql_function as far as I can tell.

Terraform Configuration Files

Abridged version of our terraform files containing only the impacted resource (function).

variable "datadog_user" {
  type        = string
  description = "The user used by Datadog checks to log onto AWS RDS instance for PostgreSQL monitoring."
  default     = "datadog"
}

variable "database" {
  type        = string
  description = "The name of the default database."
  default     = "postgres"
}

resource "postgresql_schema" "this" {
  name     = var.datadog_user
  database = var.database
  owner    = var.datadog_user
}

resource "postgresql_function" "datadog_explain_statement" {
  database = var.database
  schema   = postgresql_schema.this.name
  name     = "datadog.explain_statement"
  arg {
    name = "l_query"
    type = "TEXT"
  }

  returns = "SETOF JSON "
  body    = file("${path.module}/function.sql")
}

function.sql

AS 
$$
DECLARE
curs REFCURSOR;
plan JSON;

BEGIN
   OPEN curs FOR EXECUTE pg_catalog.concat('EXPLAIN (FORMAT JSON) ', l_query);
   FETCH curs INTO plan;
   CLOSE curs;
   RETURN QUERY SELECT plan;
END;
$$
LANGUAGE 'plpgsql'
RETURNS NULL ON NULL INPUT
SECURITY DEFINER;

Expected Behavior

This stack was already applied, so I expected

No changes. Your infrastructure matches the configuration.

Actual Behavior

Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: error detecting capabilities: error PostgreSQL version: pq: database ""datadog"" does not exist
│
│   with module.rds_user_datadog[0].postgresql_function.datadog_explain_statement,
│   on .terraform/modules/rds_user_datadog/main.tf line 52, in resource "postgresql_function" "datadog_explain_statement":
│   52: resource "postgresql_function" "datadog_explain_statement" {
│

Steps to Reproduce

  1. terraform apply should do the trick.

Important Factoids

The issue disappeared once I forced the use of version 1.18 instead of 1.19:

postgresql = {
      source  = "cyrilgdn/postgresql"
      version = "1.18"
}

instead of :

postgresql = {
      source  = "cyrilgdn/postgresql"
      version = "~> 1.18"
}

References

Could be related to this MR:

#275

@dmaspataud dmaspataud changed the title Regression on resource postgresql_function, suddenly causing errors related to database not found. Possible regression on resource postgresql_function, suddenly causing errors related to database not found. Mar 21, 2023
@dmaspataud
Copy link
Author

dmaspataud commented Mar 22, 2023

The issue seems to come from the fact that in 1.18, you could create Postgres function with a . in the name. By doing so, it was then stored in the tfstate as such:

"id": "\"datadog\".\"datadog.explain_statement\"(TEXT)",

id: <schema>.<function name>

Version 1.19 introduced a new parsing function to enable resource importing, under the form:

id: <database>.<schema>.<function name>

However, if one of your function contained a ., it will be misinterpreted.

In my case, to refresh its state, it tries to get :

function explain_statement in schema datadog in database datadog, when the function exists as datadog. explain_statement in schema datadog in database postgres.

For the sake of argument, note that the function should have been created as explain_statement in schema datadog in database postgres, it was a mistake on my side, but the point still stands, if anyone had function with a . in the function name, this change would be a breaking change.

@soudaburger
Copy link

I had to remove the offending datadog.explain_statement from state. Then import with database:postgres, schema:datadog, name:explain_statement and it appears to be happy now.

@kylejohnson
Copy link
Contributor

Not clear to me -
Since datadog expects the name of the function to be datadog.explain_statement, but that format (with the .) is not compatible with 1.19, is there a workaround?

@kylejohnson
Copy link
Contributor

I just noticed that datadog has a way to override the function name: explain_function. For now I think I'll leave the function name as datadog_explain_statement, and just update that option in my datadog config.

@kylefuhrmanncalm
Copy link

The issue seems to come from the fact that in 1.18, you could create Postgres function with a . in the name. By doing so, it was then stored in the tfstate as such:

"id": "\"datadog\".\"datadog.explain_statement\"(TEXT)",

id: <schema>.<function name>

Version 1.19 introduced a new parsing function to enable resource importing, under the form:

id: <database>.<schema>.<function name>

However, if one of your function contained a ., it will be misinterpreted.

In my case, to refresh its state, it tries to get :

function explain_statement in schema datadog in database datadog, when the function exists as datadog. explain_statement in schema datadog in database postgres.

For the sake of argument, note that the function should have been created as explain_statement in schema datadog in database postgres, it was a mistake on my side, but the point still stands, if anyone had function with a . in the function name, this change would be a breaking change.

This was helpful. We were running into an issue where Terraform was trying to create new function resources even though they already existed causing it to fail out.
Ended up modifying state and updating the id to prepend the database name (default: postgres).
Note: If you try to push the state back up with the escaped quotes, it will end up failing. You'd want to use:
"dbname.datadog.explain_statement(TEXT)", instead of "\"dbname\".\"datadog.explain_statement\"(TEXT)", following the example above of database.schema.function_name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants