terraform-provider-bigip icon indicating copy to clipboard operation
terraform-provider-bigip copied to clipboard

Utilizing `tenant_filter` shows removing all other tenants during plan

Open jakauppila opened this issue 5 years ago • 10 comments

In testing v1.2.1 from v1.1.1, I have switched config_name to tenant_filter and now in the plan it is showing that all other tenants will be removed.

The value I specify in as3_json contains only the definition for the tenant I am configuring; so I would expect that the tenant_filter should only retrieve the AS3 document for that particular tenant at https://github.com/terraform-providers/terraform-provider-bigip/blob/master/bigip/resource_bigip_as3.go#L103 rather than pulling the entire AS3 document back.

It would appear that filtering is done on the Update function (https://github.com/terraform-providers/terraform-provider-bigip/blob/master/bigip/resource_bigip_as3.go#L174), but I guess I would expect that filtering would also be done on the Read so we get an accurate representation of the change that is going to occur.

To further illustrate, assume that this is currently on the appliance:

{
     "class": "AS3",
     "action": "deploy",
     "persist": true,
     "declaration": {
         "class": "ADC",
         "schemaVersion": "3.0.0",
         "id": "example-declaration-01",
         "label": "Sample 1",
         "remark": "Simple HTTP application with round robin pool",
         "Sample_02": {
             "class": "Tenant",
             "defaultRouteDomain": 0,
             "Application_2": {
                 "class": "Application",
                 "template": "http",
             "serviceMain": {
                 "class": "Service_HTTP",
                 "virtualAddresses": [
                     "10.2.2.10"
                 ],
                 "pool": "web_pool2"
                 },
                 "web_pool2": {
                     "class": "Pool",
                     "monitors": [
                         "http"
                     ],
                     "members": [
                         {
                             "servicePort": 80,
                             "serverAddresses": [
                                 "192.2.1.100",
                                 "192.2.1.110"
                             ]
                         }
                     ]
                 }
             }
         },
         "Sample_03": {
             "class": "Tenant",
             "defaultRouteDomain": 0,
             "Application_3": {
                 "class": "Application",
                 "template": "http",
             "serviceMain": {
                 "class": "Service_HTTP",
                 "virtualAddresses": [
                     "10.1.2.10"
                 ],
                 "pool": "web_pool3"
                 },
                 "web_pool3": {
                     "class": "Pool",
                     "monitors": [
                         "http"
                     ],
                     "members": [
                         {
                             "servicePort": 80,
                             "serverAddresses": [
                                 "192.3.1.100",
                                 "192.3.1.110"
                             ]
                         }
                     ]
                 }
             }
         }
     }
 }

My as3_json file is scoped per tenant, so it would only contain the following:

{
  "class": "AS3",
  "action": "deploy",
  "persist": true,
  "declaration": {
      "class": "ADC",
      "schemaVersion": "3.0.0",
      "id": "example-declaration-01",
      "label": "Sample 1",
      "remark": "Simple HTTP application with round robin pool",
      "Sample_03": {
          "class": "Tenant",
          "defaultRouteDomain": 0,
          "Application_3": {
              "class": "Application",
              "template": "http",
          "serviceMain": {
              "class": "Service_HTTP",
              "virtualAddresses": [
                  "10.1.2.10"
              ],
              "pool": "web_pool3"
              },
              "web_pool3": {
                  "class": "Pool",
                  "monitors": [
                      "http"
                  ],
                  "members": [
                      {
                          "servicePort": 80,
                          "serverAddresses": [
                              "192.3.1.100",
                              "192.3.1.110"
                          ]
                      }
                  ]
              }
          }
      }
  }
}

With my Terraform configuration like this:

resource "bigip_as3"  "as3-example1" {
  as3_json = "${file("example2.json")}"
  tenant_filter = "Sample_03"
}

The resulting plan shows that the Sample_02 tenant will be removed.

jakauppila avatar Jun 18 '20 16:06 jakauppila

To get clarity on the scenario

I have example1.json which has tenant 2 and tenant 3 and there is no tenant filter. So both tenants 2 and 3 are posted in bigip.

Now using the same as3 resource and same json ( example1.json ), you have modified json having only tenant 3 along with tenant filter specifying as tenant 3. Is this is the scenario you are trying please clarify ? and if this is the scenario, are you expecting terraform should not show any plan difference ?( bcoz of tenant filter )

papineni87 avatar Jun 19 '20 06:06 papineni87

@jakauppila to give clarity one current behaviour even through it shows plan difference in your scenario, update call be placed for only tenant specified using tenant_filter

RavinderReddyF5 avatar Jun 19 '20 06:06 RavinderReddyF5

@papineni87 Correct; so Tenant 2 already exists on the appliance, but since my as3_json declaration only specifies Tenant 3, since the Read is pulling back the entire AS3 declaration, the Terraform plan shows Tenant 2 as being removed.

@RavinderReddyF5 That's what I figured; but our workflow runs a Plan and we decide whether or not to actually execute Apply depending on what the plan returns. So as-is, we would execute on every execution despite no changes actually needed to be made since the plan says there are changes.

My other concern would be that we will end up having hundreds of tenants on these appliances, so pulling back the entire declaration then filtering feels unnecessary, since the tenant_filter is already specified, shouldn't the Read filter the tenants to retrieve in the first place?

jakauppila avatar Jun 19 '20 12:06 jakauppila

Thank for you the clarification. Tracking with TER-375

The concerns around polling tenants that are not part of the current resource makes perfect sense. For the comment above around Tenant2 and Tenant3. If a resource previously owned state for both Tenants, then it would need to poll both to know what to remove from that given resource.

focrensh avatar Jun 22 '20 16:06 focrensh

@focrensh Just curious if there's an anticipated completion date for this issue?

jakauppila avatar Jul 15 '20 19:07 jakauppila

This issue is going into a sprint starting next week. It would then be in the release following that (around 6 weeks). The scope is to investigate/test filtering tenants retrieved via as3. This is to avoid pulling all tenants down and then comparing to TF tracked tenants.

focrensh avatar Jul 15 '20 19:07 focrensh

Sounds good, thanks.

I'd be happy to test things out once things are in a workable state.

jakauppila avatar Jul 15 '20 19:07 jakauppila

Posted the following json to the bigip using postman and this Sample_04 has nothing to do with terraform { "class": "AS3", "action": "deploy", "persist": true, "declaration": { "class": "ADC", "schemaVersion": "3.0.0", "id": "example-declaration-01", "label": "Sample 1", "remark": "Simple HTTP application with round robin pool", "Sample_04": { "class": "Tenant", "defaultRouteDomain": 0, "Application_4": { "class": "Application", "template": "http", "serviceMain": { "class": "Service_HTTP", "virtualAddresses": [ "10.4.2.10" ], "pool": "web_pool4" }, "web_pool4": { "class": "Pool", "monitors": [ "http" ], "members": [ { "servicePort": 80, "serverAddresses": [ "192.4.1.101", "192.4.1.110" ] } ] } } } } }

Now applying a terraform as3 resource as follows

resource "bigip_as3" "as3-example2" { as3_json = "${file("cs.json")}" }

where cs.json contains

{ "class": "AS3", "action": "deploy", "persist": true, "declaration": { "class": "ADC", "schemaVersion": "3.0.0", "id": "example-declaration-01", "label": "Sample 1", "remark": "Simple HTTP application with round robin pool", "Sample_03": { "class": "Tenant", "defaultRouteDomain": 0, "Application_3": { "class": "Application", "template": "http", "serviceMain": { "class": "Service_HTTP", "virtualAddresses": [ "10.1.2.10" ], "pool": "web_pool3" }, "web_pool3": { "class": "Pool", "monitors": [ "http" ], "members": [ { "servicePort": 80, "serverAddresses": [ "192.3.1.100", "192.3.2.110" ] } ] } } } }

}

Here in the GET call client.GetAs3(name, applicationList), name contains Sample_03 so it will only pull the Sample_03 tenant from bigip ignoring Sample_04 which has nothing to do with terraform

Thus the response json from the GET call is as follows:

{"action":"deploy","class":"AS3","declaration":{"Sample_03":{"Application_3":{"class":"Application","serviceMain":{"class":"Service_HTTP","pool":"web_pool3","virtualAddresses":["10.1.2.10"]},"template":"http","web_pool3":{"class":"Pool","members":[{"serverAddresses":["192.3.1.100","192.3.2.110"],"servicePort":80}],"monitors":["http"]}},"class":"Tenant","defaultRouteDomain":0},"class":"ADC","id":"example-declaration-01","label":"Sample 1","remark":"Simple HTTP application with round robin pool","schemaVersion":"3.0.0"},"persist":true}

Similarly also when I update Sample_03

[INFO] Updating As3 Config :{ "class": "AS3", "action": "deploy", "persist": true, "declaration": { "class": "ADC", "schemaVersion": "3.0.0", "id": "example-declaration-01", "label": "Sample 1", "remark": "Simple HTTP application with round robin pool", "Sample_03": { "class": "Tenant", "defaultRouteDomain": 0, "Application_3": { "class": "Application", "template": "http", "serviceMain": { "class": "Service_HTTP", "virtualAddresses": [ "10.1.2.10" ], }, "web_pool3": { "class": "Pool", "monitors": [ "http" ], "members": [ { "servicePort": 80, "serverAddresses": [ "192.3.1.100", "192.3.2.110" ]
} ] } } } } }

It will only try to modify Sample_03 and and has nothing concerned with Sample_04 @jakauppila Does this behaviour reach your expectation?

GaddamSaketha avatar Aug 03 '20 03:08 GaddamSaketha

@GaddamSaketha Yes, I believe how you described it is how I would expect it to behave.

If there's a particular branch that I could build and try it out, I could do that.

jakauppila avatar Aug 03 '20 17:08 jakauppila

@jakauppila The present code in master branch goes with this behaviour. Our latest release v 1.3.0 also contains the same logic. Can you please try it out and let us know if you face any issues

GaddamSaketha avatar Aug 04 '20 07:08 GaddamSaketha