OctopusDeployLabs / terraform-provider-octopusdeploy

Terraform Provider for Octopus Deploy :octopus:
https://registry.terraform.io/providers/OctopusDeployLabs/octopusdeploy
Mozilla Public License 2.0
83 stars 67 forks source link

Cannot delete Environment which is part of Lifecycle #499

Open ArturDorochowicz opened 1 year ago

ArturDorochowicz commented 1 year ago

Describe the bug Deleting an Environment which is part of a Lifecycle fails with message This environment cannot be deleted because it is being used by the following lifecycles: [...].

The provider attempts to delete the environment before modifying the lifecycle.

Steps to reproduce

  1. Create resources
resource "octopusdeploy_lifecycle" "test" {
  name = "Test"
  phase {
    name                        = "test"
    optional_deployment_targets = [
      octopusdeploy_environment.env-1.id,
      octopusdeploy_environment.env-2.id
    ]
  }
}

resource "octopusdeploy_environment" "env-1" {
  name = "env-1"
}

resource "octopusdeploy_environment" "env-2" {
  name = "env-2"
}
$> terraform apply -auto-approve

[...]

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:

  # octopusdeploy_environment.env-1 will be created
  + resource "octopusdeploy_environment" "env-1" {
      + id         = (known after apply)
      + name       = "env-1"
      + slug       = (known after apply)
      + sort_order = (known after apply)
      + space_id   = (known after apply)
    }

  # octopusdeploy_environment.env-2 will be created
  + resource "octopusdeploy_environment" "env-2" {
      + id         = (known after apply)
      + name       = "env-2"
      + slug       = (known after apply)
      + sort_order = (known after apply)
      + space_id   = (known after apply)
    }

  # octopusdeploy_lifecycle.test will be created
  + resource "octopusdeploy_lifecycle" "test" {
      + id       = (known after apply)
      + name     = "Test"
      + space_id = (known after apply)

      + phase {
          + id                                    = (known after apply)
          + is_optional_phase                     = false
          + minimum_environments_before_promotion = 0
          + name                                  = "test"
          + optional_deployment_targets           = (known after apply)
        }

      + release_retention_policy {
          + quantity_to_keep    = (known after apply)
          + should_keep_forever = (known after apply)
          + unit                = (known after apply)
        }

      + tentacle_retention_policy {
          + quantity_to_keep    = (known after apply)
          + should_keep_forever = (known after apply)
          + unit                = (known after apply)
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.
octopusdeploy_environment.env-2: Creating...
octopusdeploy_environment.env-1: Creating...
octopusdeploy_environment.env-2: Creation complete after 1s [id=Environments-109]
octopusdeploy_environment.env-1: Creation complete after 1s [id=Environments-90]
octopusdeploy_lifecycle.test: Creating...
octopusdeploy_lifecycle.test: Creation complete after 0s [id=Lifecycles-44]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
  1. Try to remove resources
resource "octopusdeploy_lifecycle" "test" {
  name = "Test"
  phase {
    name                        = "test"
    optional_deployment_targets = [
      octopusdeploy_environment.env-1.id,
#      octopusdeploy_environment.env-2.id
    ]
  }
}

resource "octopusdeploy_environment" "env-1" {
  name = "env-1"
}

# resource "octopusdeploy_environment" "env-2" {
#   name = "env-2"
# }
$> terraform apply -auto-approve

[...]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following    
symbols:
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # octopusdeploy_environment.env-2 will be destroyed
  # (because octopusdeploy_environment.env-2 is not in configuration)
  - resource "octopusdeploy_environment" "env-2" {
      - allow_dynamic_infrastructure = false -> null
      - id                           = "Environments-109" -> null
      - name                         = "env-2" -> null
      - slug                         = "env-2" -> null
      - sort_order                   = 3 -> null
      - space_id                     = "Spaces-22" -> null
      - use_guided_failure           = false -> null
    }

  # octopusdeploy_lifecycle.test will be updated in-place
  ~ resource "octopusdeploy_lifecycle" "test" {
        id       = "Lifecycles-44"
        name     = "Test"
        # (1 unchanged attribute hidden)

      ~ phase {
            id                                    = "23c5a13a-e963-4f1f-8fc0-35ea46a00406"
            name                                  = "test"
          ~ optional_deployment_targets           = [
                "Environments-90",
              - "Environments-109",
            ]
            # (3 unchanged attributes hidden)
        }

        # (2 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 1 to destroy.
octopusdeploy_environment.env-2: Destroying... [id=Environments-109]
╷
│ Errr: octopus deploy api returned an error on endpoint /api/Spaces-22/environments/Environments-109 - [This environment cannot be deleted because it is being used by the following lifecycles: Test]
│
│

Expected behavior The lifecycle should be modified before deleting the environment. Environment should be successfully deleted.

Logs and other supporting information Add the output of running tf plan or tf apply along with any errors in the Octopus Server logs.

Environment and versions:

zentron commented 6 months ago

A workaround for this in the meantime is possible by setting the create_before_destroy property to true. This will force TF update the lifecycle before deleting the environment.

resource "octopusdeploy_lifecycle" "test" {
...
  lifecycle {
     create_before_destroy = true
  }
}

Further upgrades are required to upgrade the provider to use the Terraform Provider Framework which will expose some additional hooks to potentially control the lifecycle a little more automatically.