OpsLevel / terraform-provider-opslevel

Terraform provider for OpsLevel.com
https://registry.terraform.io/providers/OpsLevel/opslevel/latest/docs
MIT License
8 stars 5 forks source link

handle `opslevel_team` team members without conflicting with non-terraform members, fix non-default alias handling on `parent` #337

Closed taimoorgit closed 3 months ago

taimoorgit commented 4 months ago

Issues

https://github.com/OpsLevel/terraform-provider-opslevel/issues/183

Approach

Changelog

Tophatting

main.tf

# main.tf

resource "opslevel_team" "team_1" {
  name = "Team One"

  parent = "team_platform3"

  # is required, can be []
  member = [
    {
      email = "kyle+pat@opslevel.com"
      role  = "manager"
    },
    {
      email = "taimoor+pat@opslevel.com"
      role  = "manager"
    },
  ]
}

For each step, I am making sure to run terraform plan afterwards to check for infinite loops.

Create a team with no members, no parent

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:

  # opslevel_team.team_1 will be created
  + resource "opslevel_team" "team_1" {
      + id           = (known after apply)
      + last_updated = (known after apply)
      + member       = []
      + name         = "Team One"
    }

Plan: 1 to add, 0 to change, 0 to destroy.
opslevel_team.team_1: Creating...
opslevel_team.team_1: Creation complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]

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

Assign 2x members and a parent (use primary alias)

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
      + last_updated = (known after apply)
      ~ member       = [
          + {
              + email = "kyle+pat@opslevel.com"
              + role  = "manager"
            },
          + {
              + email = "taimoor+pat@opslevel.com"
              + role  = "manager"
            },
        ]
        name         = "Team One"
      + parent       = "team_platform3"
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]
opslevel_team.team_1: Modifications complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]

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

Unassign 1x member and set the same parent, but with non-default alias

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
      + last_updated = (known after apply)
      ~ member       = [
          - {
              - email = "kyle+pat@opslevel.com" -> null
              - role  = "manager" -> null
            },
            # (1 unchanged element hidden)
        ]
        name         = "Team One"
      ~ parent       = "team_platform3" -> "team_platform_3_a"
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]
opslevel_team.team_1: Modifications complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]

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

Unassign 1x remaining member and unset the parent

opslevel_team.team_1: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
      + last_updated = (known after apply)
      ~ member       = [
          - {
              - email = "taimoor+pat@opslevel.com" -> null
              - role  = "manager" -> null
            },
        ]
        name         = "Team One"
      - parent       = "team_platform_3_a" -> null
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]
opslevel_team.team_1: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]

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

State:

# opslevel_team.team_1:
resource "opslevel_team" "team_1" {
    id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
    last_updated = "Thursday, 09-May-24 15:25:56 EDT"
    member       = []
    name         = "Team One"
}

Add 1x member on the website - should not be visible.

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
      + last_updated = (known after apply)
        name         = "Team One"
      - parent       = "team_platform_3_a" -> null
        # (1 unchanged attribute hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]
opslevel_team.team_1: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]

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

State:

# opslevel_team.team_1:
resource "opslevel_team" "team_1" {
    id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
    last_updated = "Thursday, 09-May-24 15:39:22 EDT"
    member       = []
    name         = "Team One"
}

Add back in 2 members in terraform

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
      + last_updated = (known after apply)
      ~ member       = [
          + {
              + email = "kyle+pat@opslevel.com"
              + role  = "manager"
            },
          + {
              + email = "taimoor+pat@opslevel.com"
              + role  = "manager"
            },
        ]
        name         = "Team One"
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]
opslevel_team.team_1: Modifications complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ]

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

State:

# opslevel_team.team_1:
resource "opslevel_team" "team_1" {
    id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg2NQ"
    last_updated = "Thursday, 09-May-24 15:40:21 EDT"
    member       = [
        {
            email = "kyle+pat@opslevel.com"
            role  = "manager"
        },
        {
            email = "taimoor+pat@opslevel.com"
            role  = "manager"
        },
    ]
    name         = "Team One"
}

Remove ALL 2 members in web 1 from terraform, 1 from web - should see terraform realize one of the TF managed members was realized

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
      + last_updated = (known after apply)
      ~ member       = [
          + {
              + email = "kyle+pat@opslevel.com"
              + role  = "manager"
            },
            # (1 unchanged element hidden)
        ]
        name         = "Team One"
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]
opslevel_team.team_1: Modifications complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]

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

State:

# opslevel_team.team_1:
resource "opslevel_team" "team_1" {
    id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
    last_updated = "Friday, 10-May-24 13:22:17 EDT"
    member       = [
        {
            email = "kyle+pat@opslevel.com"
            role  = "manager"
        },
        {
            email = "taimoor+pat@opslevel.com"
            role  = "manager"
        },
    ]
    name         = "Team One"
}

Add web member to terraform, also flip terraform member roles from manager to contributors

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
      + last_updated = (known after apply)
      ~ member       = [
          - {
              - email = "kyle+pat@opslevel.com" -> null
              - role  = "manager" -> null
            },
          - {
              - email = "taimoor+pat@opslevel.com" -> null
              - role  = "manager" -> null
            },
          + {
              + email = "david+pat@opslevel.com"
              + role  = "contributor"
            },
          + {
              + email = "kyle+pat@opslevel.com"
              + role  = "contributor"
            },
          + {
              + email = "taimoor+pat@opslevel.com"
              + role  = "contributor"
            },
        ]
        name         = "Team One"
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]
opslevel_team.team_1: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]

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

State:

# opslevel_team.team_1:
resource "opslevel_team" "team_1" {
    id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
    last_updated = "Friday, 10-May-24 13:23:43 EDT"
    member       = [
        {
            email = "david+pat@opslevel.com"
            role  = "contributor"
        },
        {
            email = "kyle+pat@opslevel.com"
            role  = "contributor"
        },
        {
            email = "taimoor+pat@opslevel.com"
            role  = "contributor"
        },
    ]
    name         = "Team One"
}

Set 2x in web to be a manager, TF should detect this and make them contributors again.

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
      + last_updated = (known after apply)
      ~ member       = [
          + {
              + email = "david+pat@opslevel.com"
              + role  = "contributor"
            },
          + {
              + email = "kyle+pat@opslevel.com"
              + role  = "contributor"
            },
            # (1 unchanged element hidden)
        ]
        name         = "Team One"
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]
opslevel_team.team_1: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]

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

State:

# opslevel_team.team_1:
resource "opslevel_team" "team_1" {
    id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
    last_updated = "Friday, 10-May-24 13:25:54 EDT"
    member       = [
        {
            email = "david+pat@opslevel.com"
            role  = "contributor"
        },
        {
            email = "kyle+pat@opslevel.com"
            role  = "contributor"
        },
        {
            email = "taimoor+pat@opslevel.com"
            role  = "contributor"
        },
    ]
    name         = "Team One"
}

Remove all members using terraform

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be updated in-place
  ~ resource "opslevel_team" "team_1" {
        id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
      + last_updated = (known after apply)
      ~ member       = [
          - {
              - email = "david+pat@opslevel.com" -> null
              - role  = "contributor" -> null
            },
          - {
              - email = "kyle+pat@opslevel.com" -> null
              - role  = "contributor" -> null
            },
          - {
              - email = "taimoor+pat@opslevel.com" -> null
              - role  = "contributor" -> null
            },
        ]
        name         = "Team One"
    }

Plan: 0 to add, 1 to change, 0 to destroy.
opslevel_team.team_1: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]
opslevel_team.team_1: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]

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

State:

# opslevel_team.team_1:
resource "opslevel_team" "team_1" {
    id           = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw"
    last_updated = "Friday, 10-May-24 13:26:53 EDT"
    member       = []
    name         = "Team One"
}

Destroy

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

Terraform will perform the following actions:

  # opslevel_team.team_1 will be destroyed
  - resource "opslevel_team" "team_1" {
      - id     = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw" -> null
      - member = [] -> null
      - name   = "Team One" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.
opslevel_team.team_1: Destroying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xODg3Mw]
opslevel_team.team_1: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.
davidbloss commented 3 months ago

Closing after getting better context and resolving in this PR