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

google_app_engine_standard_app_version always being updated in-place #9013

Closed
PaddyMann opened this issue Apr 28, 2021 · 9 comments
Closed
Assignees
Labels

Comments

@PaddyMann
Copy link

PaddyMann commented Apr 28, 2021

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request.
  • Please do not leave +1 or me too comments, they generate extra noise for issue followers and do not help prioritize the request.
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment.
  • If an issue is assigned to the modular-magician user, it is either in the process of being autogenerated, or is planned to be autogenerated soon. If an issue is assigned to a user, that user is claiming responsibility for the issue. If an issue is assigned to hashibot, a community member has claimed the issue already.

Terraform Version

Terraform v0.15.1
on darwin_amd64

Affected Resource(s)

  • google_app_engine_standard_app_version

Terraform Configuration Files

resource "google_app_engine_standard_app_version" "gae_default_1_8_0" {
  project                   = google_project.project.project_id
  version_id                = "1-8-0"
  service                   = "default"
  runtime                   = "nodejs14"
  instance_class            = "B2"
  delete_service_on_destroy = false

  basic_scaling {
    max_instances = 1
    idle_timeout  = "300s"
  }

  entrypoint {
    shell = "node ./api/server.js"
  }

  deployment {
    zip {
      source_url = "https://storage.googleapis.com/${google_storage_bucket.api_bucket.name}/app.1.8.0.zip"
    }
  }

  vpc_access_connector {
    name = google_vpc_access_connector.gae_vpc_connector.id
  }

  env_variables = {
    HOST              = "0.0.0.0"
    POSTGRES_HOST     = google_sql_database_instance.master.private_ip_address
    POSTGRES_PORT     = 5432
    POSTGRES_USER     = google_sql_user.db_user.name
    POSTGRES_PASSWORD = google_sql_user.db_user.password
    POSTGRES_DB       = "app-db"
  }

  # _ah routes are health checks run by GAE
  handlers {
    url_regex                   = "/_ah/(.*)"
    security_level              = "SECURE_ALWAYS"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    script {
      script_path = "auto"
    }
  }

  handlers {
    url_regex                   = "/api/(.*)"
    security_level              = "SECURE_ALWAYS"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    script {
      script_path = "auto"
    }
  }

  handlers {
    url_regex                   = "/graphql"
    security_level              = "SECURE_ALWAYS"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    script {
      script_path = "auto"
    }
  }

  handlers {
    url_regex                   = "/static/(.*)"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    security_level              = "SECURE_ALWAYS"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    static_files {
      path                  = "app/static/\\1"
      upload_path_regex     = "app/static/(.*)"
      require_matching_file = true
      expiration            = "0s"
      http_headers = {
        "X-Frame-Options" = "SAMEORIGIN"
        "Strict-Transport-Security" : "max-age=63072000; preload"
      }
    }
  }

  handlers {
    url_regex                   = "/(.*)"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    security_level              = "SECURE_ALWAYS"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"

    static_files {
      path                  = "app/\\1"
      upload_path_regex     = "app/(.*\\.(png|ico|txt|json)$)"
      require_matching_file = true
      expiration            = "0s"
      http_headers = {
        "X-Frame-Options" = "SAMEORIGIN"
        "Strict-Transport-Security" : "max-age=63072000; preload"
      }
    }
  }

  handlers {
    url_regex                   = "/_next/(.*)"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    security_level              = "SECURE_ALWAYS"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    static_files {
      path                  = "site/_next/\\1"
      upload_path_regex     = "site/_next/(.*)"
      require_matching_file = true
      expiration            = "0s"
      http_headers = {
        "X-Frame-Options" = "SAMEORIGIN"
        "Strict-Transport-Security" : "max-age=63072000; preload"
      }
    }
  }

  handlers {
    url_regex                   = "/(.*(png|svg|gif|jpg|jpeg|woff|woff2|ttf|eot|ico))$"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    security_level              = "SECURE_ALWAYS"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    static_files {
      path                  = "site/\\1"
      upload_path_regex     = "site/(.*(png|svg|gif|jpg|jpeg|woff|woff2|ttf|eot|ico))$"
      require_matching_file = true
      expiration            = "0s"
      http_headers = {
        "X-Frame-Options" = "SAMEORIGIN"
        "Strict-Transport-Security" : "max-age=63072000; preload"
      }
    }
  }

  # The homepage
  handlers {
    url_regex                   = "/"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    security_level              = "SECURE_ALWAYS"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    static_files {
      path              = "site/index.html"
      upload_path_regex = "site/index.html"
      expiration        = "0s"
      http_headers = {
        "X-Frame-Options" = "SAMEORIGIN"
        "Strict-Transport-Security" : "max-age=63072000; preload"
      }
    }
  }

  # Other static pages
  handlers {
    url_regex                   = "/(.*)"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    security_level              = "SECURE_ALWAYS"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    static_files {
      path                  = "site/\\1.html"
      upload_path_regex     = "site/(.*)\\.html"
      require_matching_file = true
      expiration            = "0s"
      http_headers = {
        "X-Frame-Options" = "SAMEORIGIN"
        "Strict-Transport-Security" : "max-age=63072000; preload"
      }
    }
  }

  # Catch-all passing all other requests to our SPA
  handlers {
    url_regex                   = ".*"
    redirect_http_response_code = "REDIRECT_HTTP_RESPONSE_CODE_301"
    security_level              = "SECURE_ALWAYS"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    static_files {
      path              = "app/index.html"
      upload_path_regex = "app/index.html"
      expiration        = "0s"
      http_headers = {
        "X-Frame-Options" = "SAMEORIGIN"
        "Strict-Transport-Security" : "max-age=63072000; preload"
      }
    }
  }

  noop_on_destroy = true
}

Debug Output

https://gist.github.com/PaddyMann/3a7ab6d3a791f3322475bf059a15dd90

Panic Output

n/a

Expected Behavior

  • No changes to the tf should lead to no updates to the app engine instance.

Actual Behavior

  # google_app_engine_standard_app_version.gae_default_1_8_0 will be updated in-place
  ~ resource "google_app_engine_standard_app_version" "gae_default_1_8_0" {
        id                        = "apps/[ProjectNameHidden]/services/default/versions/1-8-0"
        name                      = "apps/[ProjectNameHidden]/services/default/versions/1-8-0"
        # (10 unchanged attributes hidden)

      - handlers {
          - auth_fail_action = "AUTH_FAIL_ACTION_REDIRECT" -> null
          - login            = "LOGIN_OPTIONAL" -> null
          - security_level   = "SECURE_OPTIONAL" -> null
          - url_regex        = ".*" -> null

          - script {
              - script_path = "auto" -> null
            }
        }

        # (14 unchanged blocks hidden)
    }

Steps to Reproduce

  1. Create app engine version with TF above
  2. Make no changes to the TF
  3. terraform apply

Important Factoids

n/a

References

n/a

@PaddyMann PaddyMann added the bug label Apr 28, 2021
@edwardmedia edwardmedia self-assigned this Apr 28, 2021
@edwardmedia
Copy link
Contributor

@PaddyMann what version of provider are you using? I wonder what the api sent back. Can you share the debug log when you first create the resource?

@PaddyMann
Copy link
Author

Sure — I've added it above (https://gist.github.com/PaddyMann/3a7ab6d3a791f3322475bf059a15dd90)

In this debug:

  • Versions 1.5.0 to 1.8.0 end up getting unnecessarily recreated.
  • Version 1.8.1 gets created for the first time

@ghost ghost removed waiting-response labels Apr 28, 2021
@edwardmedia edwardmedia assigned c2thorn and unassigned edwardmedia Apr 28, 2021
@PaddyMann
Copy link
Author

I realize I forgot to state the provider version — we're on the latest (3.63.0)

@PaddyMann
Copy link
Author

Any update on this?

It adds 5–10 minutes to each terraform deploy, including changes that in no way affect app engine. This is particularly painful when updating other areas of the infrastructure, which often takes 5–10 attempts to get right. Hours quickly get lost...

@c2thorn
Copy link
Collaborator

c2thorn commented May 10, 2021

@PaddyMann thanks for your patience. I was able to recreate the perma-diff with you configuration, and I see the problem. The API is setting the handler as a default, and every time Terraform attempts to remove it, it is overwritten/ignored.

Normally we would suppress the diff for this specific scenario, but I haven't been able figure out a safe way to do this without suppressing actual changes to other handlers blocks. It's difficult for Terraform to know the difference between you actually wanting to remove the block and not caring about the block.

Would modifying your config suffice? I was able to stop the perma-diff by adding the block:

  handlers {
    url_regex                   = ".*"
    security_level              = "SECURE_OPTIONAL"
    login                       = "LOGIN_OPTIONAL"
    auth_fail_action            = "AUTH_FAIL_ACTION_REDIRECT"
    script {
      script_path = "auto"
    }
  }

So that the configuration is more aligned to the resource's actual value.

@PaddyMann
Copy link
Author

@c2thorn Thank you — that works!

It's a bit weird having two ".*" blocks, but I'm happy with the solution for now :)

@ghost ghost removed the waiting-response label May 11, 2021
@c2thorn
Copy link
Collaborator

c2thorn commented May 11, 2021

Thanks @PaddyMann for the follow up! I'll close this for now as there is a workaround, and patching this in the provider is nebulous.

@c2thorn c2thorn closed this as completed May 11, 2021
@PaddyMann
Copy link
Author

@c2thorn It's a little worse than I previously shared.

It's not possible to simply include the additional lines when creating a new resource. Instead, you need to add these lines in addition to whatever's there when you first create the resource (!).

This means literally duplicating the lines if you already had them:

  handlers {
    url_regex        = ".*"
    security_level   = "SECURE_OPTIONAL"
    login            = "LOGIN_OPTIONAL"
    auth_fail_action = "AUTH_FAIL_ACTION_REDIRECT"
    script {
      script_path = "auto"
    }
  }

  handlers {
    url_regex        = ".*"
    security_level   = "SECURE_OPTIONAL"
    login            = "LOGIN_OPTIONAL"
    auth_fail_action = "AUTH_FAIL_ACTION_REDIRECT"
    script {
      script_path = "auto"
    }
  }

@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants