integrations / terraform-provider-github

Terraform GitHub provider
https://www.terraform.io/docs/providers/github/
MIT License
912 stars 752 forks source link

[BUG]: github_actions_environment_secret to be created again if secret value had been changed UI #2288

Open magzim21 opened 5 months ago

magzim21 commented 5 months ago

Expected Behavior

resource "github_actions_environment_secret" "terraform_infrastructure_tfe_token" { # TODO / instead github_actions_secret should be github_actions_environment_secret when using TFE paid plan and able to scope token permissions.
  repository      = github_repository.terraform.name
  environment = github_repository_environment.terraform_main.environment
  secret_name     = "TF_TOKEN_APP_TERRAFORM_IO" # https://github.com/hashicorp/terraform/issues/21965#issuecomment-512527481
  plaintext_value = "placeholder"               # TODO / instead of personal token which is org level access, better to create a tfe_team_token per environment. But that requries more that a paid plan and 1 user in TF orgnanization.
  lifecycle {
    ignore_changes = [plaintext_value]
  }
}

This configuration should produce an empty plan when updating plaintext_value in UI

Actual Behavior

github_actions_environment_secret.terraform_infrastructure_tfe_token will be created

Plan: 1 to add, 0 to change, 0 to destroy.

Terraform Version

Terraform v1.8.2 on darwin_arm64

Affected Resource(s)

Terraform Configuration Files

No response

Steps to Reproduce

No response

Debug Output

Desktop/codelaw/terraform/main % ⭐️ TF_LOG=DEBUG  terraform apply -auto-approve
2024-06-10T19:05:17.409-0700 [INFO]  Terraform version: 1.8.2
2024-06-10T19:05:17.410-0700 [DEBUG] using github.com/hashicorp/go-tfe v1.51.0
2024-06-10T19:05:17.410-0700 [DEBUG] using github.com/hashicorp/hcl/v2 v2.20.0
2024-06-10T19:05:17.410-0700 [DEBUG] using github.com/hashicorp/terraform-svchost v0.1.1
2024-06-10T19:05:17.410-0700 [DEBUG] using github.com/zclconf/go-cty v1.14.3
2024-06-10T19:05:17.410-0700 [INFO]  Go runtime version: go1.22.1
2024-06-10T19:05:17.410-0700 [INFO]  CLI args: []string{"terraform", "apply", "-auto-approve"}
2024-06-10T19:05:17.410-0700 [DEBUG] Attempting to open CLI config file: <redacted>.terraformrc
2024-06-10T19:05:17.410-0700 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2024-06-10T19:05:17.411-0700 [DEBUG] checking for credentials in "<redacted>.terraform.d/plugins"
2024-06-10T19:05:17.411-0700 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins
2024-06-10T19:05:17.411-0700 [DEBUG] will search for provider plugins in <redacted>.terraform.d/plugins
2024-06-10T19:05:17.412-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/providers/registry.terraform.io/hashicorp" contains invalid namespace "registry.terraform.io"; ignoring
2024-06-10T19:05:17.412-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/providers/registry.terraform.io/hashicorp/template" contains invalid namespace "registry.terraform.io"; ignoring
2024-06-10T19:05:17.412-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/providers/registry.terraform.io/hashicorp/template/2.2.0" contains invalid namespace "registry.terraform.io"; ignoring
2024-06-10T19:05:17.412-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/providers/registry.terraform.io/hashicorp/template/2.2.0/darwin_arm64" contains invalid namespace "registry.terraform.io"; ignoring
2024-06-10T19:05:17.412-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/providers/registry.terraform.io/hashicorp/template/2.2.0/darwin_arm64/terraform-provider-template" contains invalid namespace "registry.terraform.io"; ignoring
2024-06-10T19:05:17.418-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/terraform-provider-template/providers/registry.terraform.io" contains invalid type "registry.terraform.io"; ignoring
2024-06-10T19:05:17.419-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/terraform-provider-template/providers/registry.terraform.io/hashicorp" contains invalid type "registry.terraform.io"; ignoring
2024-06-10T19:05:17.419-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/terraform-provider-template/providers/registry.terraform.io/hashicorp/template" contains invalid type "registry.terraform.io"; ignoring
2024-06-10T19:05:17.419-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/terraform-provider-template/providers/registry.terraform.io/hashicorp/template/2.2.0" contains invalid type "registry.terraform.io"; ignoring
2024-06-10T19:05:17.419-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/terraform-provider-template/providers/registry.terraform.io/hashicorp/template/2.2.0/darwin_arm64" contains invalid type "registry.terraform.io"; ignoring
2024-06-10T19:05:17.419-0700 [WARN]  local provider path "<redacted>.terraform.d/plugins/terraform-provider-template/providers/registry.terraform.io/hashicorp/template/2.2.0/darwin_arm64/terraform-provider-template" contains invalid type "registry.terraform.io"; ignoring
2024-06-10T19:05:17.419-0700 [DEBUG] ignoring non-existing provider search directory <redacted>Library/Application Support/io.terraform/plugins
2024-06-10T19:05:17.419-0700 [DEBUG] ignoring non-existing provider search directory /Library/Application Support/io.terraform/plugins
2024-06-10T19:05:17.420-0700 [INFO]  CLI command args: []string{"apply", "-auto-approve"}
2024-06-10T19:05:17.442-0700 [DEBUG] Service discovery for app.terraform.io at https://app.terraform.io/.well-known/terraform.json
2024-06-10T19:05:18.383-0700 [DEBUG] Service discovery for app.terraform.io aliased as localterraform.com
2024-06-10T19:05:18.916-0700 [DEBUG] checking for provisioner in "."
2024-06-10T19:05:18.918-0700 [DEBUG] checking for provisioner in "/opt/homebrew/bin"
2024-06-10T19:05:18.919-0700 [DEBUG] checking for provisioner in "<redacted>.terraform.d/plugins"
2024-06-10T19:05:19.090-0700 [INFO]  cloud: starting Apply operation
Running apply in HCP Terraform. Output will stream here. Pressing Ctrl-C
will cancel the remote apply if it's still pending. If the apply started it
will stop streaming the logs, but will not stop the apply running remotely.

Preparing the remote apply...

To view this run in a browser, visit:
https://app.terraform.io/app/<redacted>/main/runs/run-mESc8zwRkEnxFuEY

Waiting for the plan to start...

Terraform v1.8.5
on linux_amd64
Initializing plugins and modules...
data.tls_certificate.terraform_cloud: Refreshing...
data.tls_certificate.github: Refreshing...
data.tls_certificate.github: Refresh complete after 0s [id=<redacted>]
data.tls_certificate.terraform_cloud: Refresh complete after 0s [id=<redacted>]
tfe_variable_set.global: Refreshing state... [id=<redacted>]
data.tfe_workspace.main: Refreshing...
tfe_project.infrastructure: Refreshing state... [id=<redacted>]
tfe_variable_set.applications: Refreshing state... [id=<redacted>]
tfe_project.applications: Refreshing state... [id=<redacted>]
data.tfe_organization.this: Refreshing...
data.tfe_project.default: Refreshing...
data.tfe_workspace.main: Refresh complete after 0s [id=<redacted>]
github_team.argocd_admins: Refreshing state... [id=<redacted>]
github_repository.lang: Refreshing state... [id=<redacted>]
github_repository.terraform: Refreshing state... [id=<redacted>]
github_repository.template: Refreshing state... [id=<redacted>]
github_repository.argocd_apps: Refreshing state... [id=<redacted>]
github_actions_organization_variable.aws_region: Refreshing state... [id=<redacted>]
data.tfe_organization.this: Refresh complete after 1s [id=<redacted>]
data.github_user.current: Refreshing...
tfe_variable.github_token: Refreshing state... [id=<redacted>]
tfe_variable.datadog_app_key: Refreshing state... [id=<redacted>]
data.tfe_project.default: Refresh complete after 1s [id=<redacted>]
tfe_variable.tfc_aws_run_role_arn: Refreshing state... [id=<redacted>]
tfe_variable.tfc_aws_provider_auth: Refreshing state... [id=<redacted>]
tfe_variable.datadog_api_key: Refreshing state... [id=<redacted>]
tfe_project_variable_set.applications: Refreshing state... [id=<redacted>]
tfe_workspace.dev: Refreshing state... [id=<redacted>]
tfe_workspace.prod: Refreshing state... [id=<redacted>]
tfe_workspace.infrastructure: Refreshing state... [id=<redacted>]
aws_ram_sharing_with_organization.this: Refreshing state... [id=<redacted>]
aws_organizations_organization.this: Refreshing state... [id=<redacted>]
aws_route53_zone.this_dev: Refreshing state... [id=<redacted>]
data.aws_region.current: Refreshing...
data.aws_region.current: Refresh complete after 0s [id=<redacted>]
aws_iam_openid_connect_provider.github: Refreshing state... [id=<redacted>]
aws_iam_openid_connect_provider.terraform_cloud: Refreshing state... [id=<redacted>]
aws_route53_zone.this_infrastructure: Refreshing state... [id=<redacted>]
data.aws_route53_zone.this_prod: Refreshing...
github_branch_default.lang: Refreshing state... [id=<redacted>]
tfe_variable.dev_openai_api_key: Refreshing state... [id=<redacted>]
github_repository_environment.terraform_main: Refreshing state... [id=<redacted>]
github_repository_environment.terraform_prod: Refreshing state... [id=<redacted>]
github_repository_environment.terraform_infrastructure: Refreshing state... [id=<redacted>]
github_branch_default.terraform: Refreshing state... [id=<redacted>]
data.aws_route53_zone.this_prod: Refresh complete after 0s [id=<redacted>]
github_repository_environment.terraform_dev: Refreshing state... [id=<redacted>]
tfe_variable.prod_openai_api_key: Refreshing state... [id=<redacted>]
aws_iam_role.github_actions_agent_ecr: Refreshing state... [id=<redacted>]
aws_iam_role.terraform_cloud: Refreshing state... [id=<redacted>]
tfe_variable.argocd_admin_password: Refreshing state... [id=<redacted>]
tfe_variable.github_argocd_token: Refreshing state... [id=<redacted>]
tfe_variable.github_oauth_app_client_id: Refreshing state... [id=<redacted>]
tfe_variable.github_oauth_app_client_secret: Refreshing state... [id=<redacted>]
github_branch_default.template: Refreshing state... [id=<redacted>]
aws_route53_record.this_infrastructure_ns: Refreshing state... [id=<redacted>]
aws_route53_record.this_dev_ns: Refreshing state... [id=<redacted>]
github_branch_default.argocd_apps: Refreshing state... [id=<redacted>]
aws_organizations_organizational_unit.security: Refreshing state... [id=<redacted>]
aws_iam_role.route53_manager_role_dev: Refreshing state... [id=<redacted>]
aws_organizations_organizational_unit.infrastructure: Refreshing state... [id=<redacted>]
aws_organizations_organizational_unit.applications: Refreshing state... [id=<redacted>]
aws_organizations_organizational_unit.shared_services: Refreshing state... [id=<redacted>]
github_actions_organization_variable.aws_ecr_role_arn: Refreshing state... [id=<redacted>]
github_actions_environment_secret.terraform_infrastructure_tfe_token: Refreshing state... [id=<redacted>]
aws_organizations_account.security: Refreshing state... [id=<redacted>]
aws_organizations_account.infrastructure: Refreshing state... [id=<redacted>]
aws_organizations_account.prod: Refreshing state... [id=<redacted>]
aws_organizations_account.dev: Refreshing state... [id=<redacted>]
aws_organizations_account.shared_services: Refreshing state... [id=<redacted>]
data.github_user.current: Refresh complete after 2s [id=<redacted>]
aws_vpc_ipam_organization_admin_account.this: Refreshing state... [id=<redacted>]
github_team_members.argocd_admins: Refreshing state... [id=<redacted>]
aws_iam_role.route53_manager_role_infrastructure: Refreshing state... [id=<redacted>]
aws_iam_role.route53_manager_role_prod: Refreshing state... [id=<redacted>]
aws_ecr_repository.this["lang"]: Refreshing state... [id=<redacted>]
aws_ecr_repository.this["helm-generic-chart"]: Refreshing state... [id=<redacted>]
aws_ecr_registry_scanning_configuration.this: Refreshing state... [id=<redacted>]
aws_ecr_repository_policy.this["lang"]: Refreshing state... [id=<redacted>]
aws_ecr_lifecycle_policy.this["helm-generic-chart"]: Refreshing state... [id=<redacted>]
aws_ecr_lifecycle_policy.this["lang"]: Refreshing state... [id=<redacted>]
aws_ecr_repository_policy.this["helm-generic-chart"]: Refreshing state... [id=<redacted>]
github_repository.helm_generic_chart: Refreshing state... [id=<redacted>]
github_branch_default.helm_generic_chart: Refreshing state... [id=<redacted>]
github_actions_environment_secret.terraform_infrastructure_tfe_token: Drift detected (delete)
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "DATADOG_API_KEY" but a
│ value was found in file
│ "/home/tfc-agent/.tfc-agent/component/terraform/runs/run-mESc8zwRkEnxFuEY/terraform.tfvars".
│ If you meant to use this value, add a "variable" block to the
│ configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "DATADOG_APP_KEY" but a
│ value was found in file
│ "/home/tfc-agent/.tfc-agent/component/terraform/runs/run-mESc8zwRkEnxFuEY/terraform.tfvars".
│ If you meant to use this value, add a "variable" block to the
│ configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
2024-06-10T19:05:58.527-0700 [DEBUG] performing request: method=GET url=https://app.terraform.io/api/v2/plans/plan-whuwc1VwNo9PC61u/json-output-redacted

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # github_actions_environment_secret.terraform_infrastructure_tfe_token will be created
  + resource "github_actions_environment_secret" "terraform_infrastructure_tfe_token" {
      + created_at      = (known after apply)
      + environment     = "main"
      + id              = (known after apply)
      + plaintext_value = (sensitive value)
      + repository      = "terraform"
      + secret_name     = "TF_TOKEN_APP_TERRAFORM_IO"
      + updated_at      = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Cost Estimation:

Resources: 0 of 46 estimated
           $0.0/mo +$0.0

------------------------------------------------------------------------

github_actions_environment_secret.terraform_infrastructure_tfe_token: Creating...
github_actions_environment_secret.terraform_infrastructure_tfe_token: Creation complete after 2s [id=<redacted>]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:
<redacted>

Panic Output

No response

Code of Conduct

lanni-energinet commented 2 months ago

@magzim21

Why would you want a "empty" plan when the secret value in tfstate doesn't match the newly supplied?

I agree that a "1 to add" plan is incorrect - but wouldn't it be better with a "1 to change"

magzim21 commented 2 months ago

This configuration should produce an empty plan when updating plaintext_value in UI

The emphasize is "updating value in UI" It should be empty because

  lifecycle {
    ignore_changes = [plaintext_value]
  }
nbali commented 1 week ago

So this is the logic that is responsible for this behaviour:

    if updatedAt, ok := d.GetOk("updated_at"); ok && updatedAt != secret.UpdatedAt.String() {
        log.Printf("[INFO] The secret %s has been externally updated in GitHub", d.Id())
        d.SetId("")
    } else if !ok {
        if err = d.Set("updated_at", secret.UpdatedAt.String()); err != nil {
            return err
        }
    }

Wouldn't this solve our issue, but keep the original functionality as well?

    if updatedAt, ok := d.GetOk("updated_at"); ok && updatedAt != secret.UpdatedAt.String() {
        log.Printf("[INFO] The secret %s has been externally updated in GitHub", d.Id())
        d.Set("encrypted_value", "")
        d.Set("plaintext_value", "")
    } else if !ok {
        if err = d.Set("updated_at", secret.UpdatedAt.String()); err != nil {
            return err
        }
    }
nbali commented 1 week ago

seems to be duplicate of #1383