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

add listSortStringModifier custom PlanModifier #352

Closed davidbloss closed 2 months ago

davidbloss commented 2 months ago

Issues

fix aliases

Changelog

Add listSortStringModifier custom PlanModifier. During the plan, if the proposed changes to a list of strings differs from the current state only by order, then continue using the state's list of strings. This avoids unneeded updates to lists of strings that only serve to shuffle the order of strings

Tophatting

With this config file:

# main.tf
resource "opslevel_infrastructure" "example" {
  aliases = ["123", "bbb", "DDD", "aaa"]
  owner   = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xNzQzMg"
  schema  = "Database"
  data = jsonencode({
    name = "my-database"
  })
}

resource "opslevel_service" "example" {
  name    = "frosting-patrol"
  aliases = ["yellow", "blue", "red"]
}

resource "opslevel_team" "example" {
  name             = "bake-off"
  responsibilities = "Baking cakes"
  aliases          = ["ZZZ", "XXXX", "yyyyy", "4321"]
}

Create infra, service, and team resources with aliases. terraform apply

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_infrastructure.example will be created
  + resource "opslevel_infrastructure" "example" {
      + aliases      = [
          + "123",
          + "DDD",
          + "aaa",
          + "bbb",
        ]
      + data         = jsonencode(
            {
              + name = "my-database"
            }
        )
      + id           = (known after apply)
      + last_updated = (known after apply)
      + owner        = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xNzQzMg"
      + schema       = "Database"
    }

  # opslevel_service.example will be created
  + resource "opslevel_service" "example" {
      + aliases      = [
          + "blue",
          + "red",
          + "yellow",
        ]
      + id           = (known after apply)
      + last_updated = (known after apply)
      + name         = "frosting-patrol"
    }

  # opslevel_team.example will be created
  + resource "opslevel_team" "example" {
      + aliases          = [
          + "4321",
          + "XXXX",
          + "ZZZ",
          + "yyyyy",
        ]
      + id               = (known after apply)
      + last_updated     = (known after apply)
      + name             = "bake-off"
      + responsibilities = "Baking cakes"
    }

Plan: 3 to add, 0 to change, 0 to destroy.
opslevel_service.example: Creating...
opslevel_team.example: Creating...
opslevel_infrastructure.example: Creating...
opslevel_team.example: Creation complete after 2s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA]
opslevel_service.example: Creation complete after 3s [id=Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI]
opslevel_infrastructure.example: Creation complete after 4s [id=Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY]

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

Update the config file, sort all aliases:

# main.tf
resource "opslevel_infrastructure" "example" {
  aliases = sort(["123", "bbb", "DDD", "aaa"])
  owner   = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xNzQzMg"
  schema  = "Database"
  data = jsonencode({
    name = "my-database"
  })
}

resource "opslevel_service" "example" {
  name    = "frosting-patrol"
  aliases = sort(["yellow", "blue", "red"])
}

resource "opslevel_team" "example" {
  name             = "bake-off"
  responsibilities = "Baking cakes"
  aliases          = sort(["ZZZ", "XXXX", "yyyyy", "4321"])
}

task plan shows no change

Update the config file, change contents of aliases:

resource "opslevel_infrastructure" "example" {
  aliases = sort(["123", "bbb", "DDD"])
  owner   = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xNzQzMg"
  schema  = "Database"
  data = jsonencode({
    name = "my-database"
  })
}

resource "opslevel_service" "example" {
  name    = "frosting-patrol"
  aliases = sort(["yellow", "blue", "red", "green"])
}

resource "opslevel_team" "example" {
  name             = "bake-off"
  responsibilities = "Baking cakes"
  aliases          = sort(["ZZZ", "4321", "asdf"])
}

Update aliases. terraform apply

opslevel_infrastructure.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY]
opslevel_team.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA]
opslevel_service.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI]

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_infrastructure.example will be updated in-place
  ~ resource "opslevel_infrastructure" "example" {
      ~ aliases      = [
            # (1 unchanged element hidden)
            "DDD",
          - "aaa",
            "bbb",
        ]
        id           = "Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY"
      + last_updated = (known after apply)
        # (3 unchanged attributes hidden)
    }

  # opslevel_service.example will be updated in-place
  ~ resource "opslevel_service" "example" {
      ~ aliases      = [
            "blue",
          + "green",
            "red",
            # (1 unchanged element hidden)
        ]
        id           = "Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI"
      + last_updated = (known after apply)
        name         = "frosting-patrol"
    }

  # opslevel_team.example will be updated in-place
  ~ resource "opslevel_team" "example" {
      ~ aliases          = [
            "4321",
          - "XXXX",
            "ZZZ",
          - "yyyyy",
          + "asdf",
        ]
        id               = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA"
      + last_updated     = (known after apply)
        name             = "bake-off"
        # (1 unchanged attribute hidden)
    }

Plan: 0 to add, 3 to change, 0 to destroy.
opslevel_team.example: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA]
opslevel_infrastructure.example: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY]
opslevel_service.example: Modifying... [id=Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI]
opslevel_infrastructure.example: Modifications complete after 0s [id=Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY]
opslevel_team.example: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA]
opslevel_service.example: Modifications complete after 1s [id=Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI]

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

Tear down resources, terraform destroy

opslevel_service.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI]
opslevel_infrastructure.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY]
opslevel_team.example: Refreshing state... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA]

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_infrastructure.example will be destroyed
  - resource "opslevel_infrastructure" "example" {
      - aliases = [
          - "123",
          - "DDD",
          - "bbb",
        ] -> null
      - data    = jsonencode(
            {
              - name = "my-database"
            }
        ) -> null
      - id      = "Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY" -> null
      - owner   = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xNzQzMg" -> null
      - schema  = "Database" -> null
    }

  # opslevel_service.example will be destroyed
  - resource "opslevel_service" "example" {
      - aliases = [
          - "blue",
          - "green",
          - "red",
          - "yellow",
        ] -> null
      - id      = "Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI" -> null
      - name    = "frosting-patrol" -> null
    }

  # opslevel_team.example will be destroyed
  - resource "opslevel_team" "example" {
      - aliases          = [
          - "4321",
          - "ZZZ",
          - "asdf",
        ] -> null
      - id               = "Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA" -> null
      - name             = "bake-off" -> null
      - responsibilities = "Baking cakes" -> null
    }

Plan: 0 to add, 0 to change, 3 to destroy.
opslevel_service.example: Destroying... [id=Z2lkOi8vb3BzbGV2ZWwvU2VydmljZS8xMjM5ODI]
opslevel_infrastructure.example: Destroying... [id=Z2lkOi8vb3BzbGV2ZWwvRW50aXR5T2JqZWN0LzI0OTc4NDY]
opslevel_team.example: Destroying... [id=Z2lkOi8vb3BzbGV2ZWwvVGVhbS8xOTE0OA]
opslevel_infrastructure.example: Destruction complete after 1s
opslevel_team.example: Destruction complete after 1s
opslevel_service.example: Destruction complete after 2s

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

This effort is being replaced with this other PR where aliases is converted from a list type to a set type