F5Networks / terraform-provider-bigip-version0.12

Terraform resources that can configure F5 BIGIP products
Mozilla Public License 2.0
18 stars 11 forks source link

declaring virtual addresses in /Common/Shared via AS3 fails #48

Closed sporky closed 4 years ago

sporky commented 4 years ago

Terraform v0.12.20 provider.bigip v1.1.1 bigip version: 15.0.1 AS3 version: 3.17.0

Applying the first plan with an address in /Common/Shared deploys fine (200 response). Applying a second plan with a different address in /Common/Shared fails (207 response).

My first declaration:

{
  "class": "AS3",
  "action": "deploy",
  "persist": true,
  "declaration": {
    "class": "ADC",
    "schemaVersion": "3.17.0",
    "remark": "template version 1.0 - 2/11/2020",
    "Common": {
      "class": "Tenant",
      "Shared": {
        "class": "Application",
        "template": "shared",
        "my10.11.12.13": {
          "class": "Service_Address",
          "virtualAddress": "10.11.12.13"
        }
      }
    },
    "simple": {
      "class": "Tenant",
      "app": {
        "class": "Application",
        "template": "generic",
        "tcp_app": {
          "class": "Service_TCP",
          "virtualAddresses": [
            {
              "use": "/Common/Shared/my10.11.12.13"
            }
          ],
          "virtualPort": 80,
          "snat": "none",
          "pool": "simple_pool"
        },
        "simple_pool": {
          "class": "Pool",
          "members": [
            {
              "serverAddresses": [
                "10.10.10.11"
              ],
              "servicePort": 80,
              "shareNodes": true
            }
          ]
        }
      }
    }
  }
}

Second declaration:

{
  "class": "AS3",
  "action": "deploy",
  "persist": true,
  "declaration": {
    "class": "ADC",
    "schemaVersion": "3.17.0",
    "remark": "template version 1.0 - 2/11/2020",
    "Common": {
      "class": "Tenant",
      "Shared": {
        "class": "Application",
        "template": "shared",
        "my10.11.12.15": {
          "class": "Service_Address",
          "virtualAddress": "10.11.12.15"
        }
      }
    },
    "simpletoo": {
      "class": "Tenant",
      "app": {
        "class": "Application",
        "template": "generic",
        "tcp_app": {
          "class": "Service_TCP",
          "virtualAddresses": [
            {
              "use": "/Common/Shared/my10.11.12.15"
            }
          ],
          "virtualPort": 80,
          "snat": "none",
          "pool": "simple_pool"
        },
        "simple_pool": {
          "class": "Pool",
          "members": [
            {
              "serverAddresses": [
                "10.10.10.11"
              ],
              "servicePort": 80,
              "shareNodes": true
            }
          ]
        }
      }
    }
  }
}

Response from the second declaration:

{
  "results": [
    {
      "code": 200,
      "message": "success",
      "lineCount": 17,
      "host": "localhost",
      "tenant": "Common",
      "runTime": 3512
    },
    {
      "code": 200,
      "message": "success",
      "lineCount": 25,
      "host": "localhost",
      "tenant": "simpletoo",
      "runTime": 1412
    },
    {
      "code": 422,
      "message": "declaration failed",
      "response": "01070344:3: Cannot delete referenced virtual address /Common/Shared/my10.11.12.13.",
      "host": "localhost",
      "tenant": "Common",
      "runTime": 4172
    }
  ],
  "declaration": {
    "Common": {
      "class": "Tenant",
      "Shared": {
        "class": "Application",
        "template": "shared",
        "my10.11.12.13": {
          "class": "Service_Address",
          "virtualAddress": "10.11.12.13"
        }
      }
    },
    "class": "ADC",
    "schemaVersion": "3.17.0",
    "remark": "template version 1.0 - 2/11/2020",
    "simpletoo": {
      "class": "Tenant",
      "app": {
        "class": "Application",
        "template": "generic",
        "tcp_app": {
          "class": "Service_TCP",
          "virtualAddresses": [
            {
              "use": "/Common/Shared/my10.11.12.15"
            }
          ],
          "virtualPort": 80,
          "snat": "none",
          "pool": "simple_pool"
        },
        "simple_pool": {
          "class": "Pool",
          "members": [
            {
              "serverAddresses": [
                "10.10.10.11"
              ],
              "servicePort": 80,
              "shareNodes": true
            }
          ]
        }
      }
    },
    "id": "autogen_ed0d14ef-922e-4e5e-80da-379159d6bbdf",
    "updateMode": "selective",
    "controls": {
      "archiveTimestamp": "2020-02-13T01:07:50.002Z"
    }
  },
  "code": 207
}

What I expected to happen

Two virtual servers should have been created on the BIGIP and the tfstate should reflect work completed on the BIGIP.

What actually happened

Two virtual servers were created on the remote BIGIP. Terraform declared the second attempt a failure. The state file was incorrectly updated as though the whole deployment actually failed. Cleaning up the virtual servers on the bigip is now a manual effort since tfstate and device state are out of sync.

My speculation

Taking a guess here, but in resourceBigipAs3Create it appears that anything but a 200 response will be flagged as failure. In the case of a 207 response, it should probably evaluate the result list in the response body and update tfstate accordingly. Personally, I'd be ok with just marking 207 responses as "ok" and moving on but that's probably not "good form".

focrensh commented 4 years ago

Tracking with TF-271

nmenant commented 4 years ago

We did some testing with our latest TF provider and we couldn't reproduce this issue.

Some things worth highlighting:

Here is the terraform apply output when processing your second declaration:

`PAR-ML-00026375:AS3_Declaration menant$ terraform apply bigip_as3.as3-declaration: Refreshing state... [id=Common,simple]

An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place

Terraform will perform the following actions:

bigip_as3.as3-declaration will be updated in-place

~ resource "bigip_as3" "as3-declaration" { ~ as3_json = jsonencode( ~ { action = "deploy" class = "AS3" ~ declaration = { ~ Common = { ~ Shared = { class = "Application"

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

Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve.

Enter a value: yes

bigip_as3.as3-declaration: Modifying... [id=Common,simple] bigip_as3.as3-declaration: Still modifying... [id=Common,simple, 10s elapsed] bigip_as3.as3-declaration: Still modifying... [id=Common,simple, 20s elapsed] bigip_as3.as3-declaration: Modifications complete after 22s [id=Common,simple]

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

This is the state of my resource once it's done:

{ "version": 4, "terraform_version": "0.12.0", "serial": 36, "lineage": "a4a2ca97-d615-f9f9-fc27-c42514c7950a", "outputs": {}, "resources": [ { "mode": "managed", "type": "bigip_as3", "name": "as3-declaration", "provider": "provider.bigip", "instances": [ { "schema_version": 0, "attributes": { "as3_json": "{\"action\":\"deploy\",\"class\":\"AS3\",\"declaration\":{\"Common\":{\"Shared\":{\"class\":\"Application\",\"my10.11.12.15\":{\"class\":\"Service_Address\",\"virtualAddress\":\"10.11.12.15\"},\"template\":\"shared\"},\"class\":\"Tenant\"},\"class\":\"ADC\",\"id\":\"test2\",\"remark\":\"template version 1.0 - 2/11/2020\",\"schemaVersion\":\"3.17.0\",\"simpletoo\":{\"app\":{\"class\":\"Application\",\"simple_pool\":{\"class\":\"Pool\",\"members\":[{\"serverAddresses\":[\"10.10.10.11\"],\"servicePort\":80,\"shareNodes\":true}]},\"tcp_app\":{\"class\":\"Service_TCP\",\"pool\":\"simple_pool\",\"snat\":\"none\",\"virtualAddresses\":[{\"use\":\"/Common/Shared/my10.11.12.15\"}],\"virtualPort\":80},\"template\":\"generic\"},\"class\":\"Tenant\"}},\"persist\":true}", "id": "Common,simple", "tenant_filter": null, "tenant_list": "Common,simpletoo", "tenant_name": null } } ] } ] }