diff --git a/bigip/resource_bigip_fast_tcp.go b/bigip/resource_bigip_fast_tcp.go index 4469054e8..ddaad754f 100644 --- a/bigip/resource_bigip_fast_tcp.go +++ b/bigip/resource_bigip_fast_tcp.go @@ -3,6 +3,7 @@ Copyright 2021 F5 Networks Inc. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + package bigip import ( @@ -62,6 +63,32 @@ func resourceBigipFastTcpApp() *schema.Resource { }, }, }, + "persistence_profile": { + Type: schema.TypeString, + Optional: true, + Description: "Select an existing BIG-IP persistence profile.", + ConflictsWith: []string{ + "persistence_type", + }, + }, + "persistence_type": { + Type: schema.TypeString, + Optional: true, + Description: "Type of persistence profile to be created.", + // Default: "source-address", + ValidateFunc: validation.StringInSlice([]string{ + "destination-address", + "source-address"}, false), + ConflictsWith: []string{"persistence_profile"}, + }, + "fallback_persistence": { + Type: schema.TypeString, + Optional: true, + Description: "Type of fallback persistence record to be created for each new client connection.", + ValidateFunc: validation.StringInSlice([]string{ + "destination-address", + "source-address"}, false), + }, "existing_snat_pool": { Type: schema.TypeString, Optional: true, @@ -229,10 +256,16 @@ func resourceBigipFastTcpAppRead(ctx context.Context, d *schema.ResourceData, me log.Printf("[INFO] Reading FAST TCP Application config") fastJson, err := client.GetFastApp(tenant, appName) - log.Printf("[DEBUG] FAST json retreived from the GET call in Read function : %s", fastJson) if err != nil { log.Printf("[ERROR] Unable to retrieve json ") - if err.Error() == "unexpected end of JSON input" { + err_msg := err.Error() + appNotFound := fmt.Sprintf("Client Error: Could not find application %s/%s", tenant, appName) + if err_msg == appNotFound { + log.Printf("[INFO] %v", err) + d.SetId("") + return nil + } + if err_msg == "unexpected end of JSON input" { log.Printf("[ERROR] %v", err) d.SetId("") return nil @@ -244,7 +277,8 @@ func resourceBigipFastTcpAppRead(ctx context.Context, d *schema.ResourceData, me d.SetId("") return nil } - _ = d.Set("fast_json", fastJson) + log.Printf("[DEBUG] FAST json retreived from the GET call in Read function : %s", fastJson) + _ = d.Set("fast_tcp_json", fastJson) err = json.Unmarshal([]byte(fastJson), &fastTcp) if err != nil { return diag.FromErr(err) @@ -287,7 +321,7 @@ func resourceBigipFastTcpAppDelete(ctx context.Context, d *schema.ResourceData, if err != nil { return diag.FromErr(err) } - d.SetId("") + // d.SetId("") return resourceBigipFastTcpAppRead(ctx, d, meta) } @@ -309,13 +343,18 @@ func setFastTcpData(d *schema.ResourceData, data bigip.FastTCPJson) error { } _ = d.Set("existing_monitor", data.TCPMonitor) monitorData := make(map[string]interface{}) - monitorData["enable"] = data.MonitorEnable monitorData["interval"] = data.MonitorInterval if _, ok := d.GetOk("monitor"); ok { if err := d.Set("monitor", []interface{}{monitorData}); err != nil { return fmt.Errorf("error setting monitor: %w", err) } } + if data.PersistenceProfile != "" { + d.Set("persistence_profile", data.PersistenceProfile) + } else { + d.Set("persistence_type", data.PersistenceType) + } + _ = d.Set("fallback_persistence", data.FallbackPersistenceType) return nil } @@ -342,6 +381,21 @@ func getParamsConfigMap(d *schema.ResourceData) (string, error) { tcpJson.SnatAutomap = false tcpJson.MakeSnatPool = false } + + tcpJson.EnablePersistence = true + if v, ok := d.GetOk("persistence_profile"); ok { + tcpJson.UseExistingPersistenceProfile = true + tcpJson.PersistenceProfile = v.(string) + } else { + tcpJson.PersistenceType = d.Get("persistence_type").(string) + tcpJson.UseExistingPersistenceProfile = false + } + + if v, ok := d.GetOk("fallback_persistence"); ok { + tcpJson.EnableFallbackPersistence = true + tcpJson.FallbackPersistenceType = v.(string) + } + if s, ok := d.GetOk("snat_pool_address"); ok { tcpJson.SnatAutomap = false tcpJson.MakeSnatPool = true diff --git a/bigip/resource_bigip_fast_tcp_test.go b/bigip/resource_bigip_fast_tcp_test.go index 437059dc6..fee08fae4 100644 --- a/bigip/resource_bigip_fast_tcp_test.go +++ b/bigip/resource_bigip_fast_tcp_test.go @@ -44,6 +44,29 @@ resource "bigip_fast_tcp_app" "fast_tcp_app" { } `, appName, tenantName) +var cfg3 = fmt.Sprintf(` +resource "bigip_fast_tcp_app" "fast-tcp-app" { + application = "%v" + tenant = "%v" + + virtual_server { + ip = "11.12.16.30" + port = 443 + } + + persistence_profile = "/Common/source_addr" + fallback_persistence = "destination-address" + + pool_members { + addresses = ["10.11.34.65", "56.43.23.76"] + port = 443 + priority_group = 1 + connection_limit = 4 + share_nodes = true + } +} +`, appName, tenantName) + func TestAccFastTCPAppCreateOnBigip(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { @@ -78,6 +101,28 @@ func TestAccFastTCPAppCreateOnBigip(t *testing.T) { }) } +func TestAccFastTCPAppPersistenceAttributes(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAcctPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testCheckFastTCPAppDestroyed, + Steps: []resource.TestStep{ + { + Config: cfg3, + Check: resource.ComposeTestCheckFunc( + testCheckFastAppExists(appName, tenantName, true), + resource.TestCheckResourceAttr("bigip_fast_tcp_app.fast-tcp-app", "application", "fast_tcp_app"), + resource.TestCheckResourceAttr("bigip_fast_tcp_app.fast-tcp-app", "tenant", "fast_tcp_tenant"), + resource.TestCheckResourceAttr("bigip_fast_tcp_app.fast-tcp-app", "persistence_profile", "/Common/source_addr"), + resource.TestCheckResourceAttr("bigip_fast_tcp_app.fast-tcp-app", "fallback_persistence", "destination-address"), + ), + }, + }, + }) +} + func testCheckFastTCPAppDestroyed(s *terraform.State) error { client := testAccProvider.Meta().(*bigip.BigIP) for _, rs := range s.RootModule().Resources { @@ -86,6 +131,10 @@ func testCheckFastTCPAppDestroyed(s *terraform.State) error { } name := rs.Primary.ID template, err := client.GetFastApp(tenant, name) + appNotFound := fmt.Sprintf("Client Error: Could not find application %s/%s", tenantName, appName) + if err != nil && err.Error() != appNotFound { + return nil + } if err != nil { return err } diff --git a/bigip/resource_bigip_fast_udp.go b/bigip/resource_bigip_fast_udp.go index 7574737c3..3022e376a 100644 --- a/bigip/resource_bigip_fast_udp.go +++ b/bigip/resource_bigip_fast_udp.go @@ -310,7 +310,7 @@ func resourceBigipFastUdpAppRead(ctx context.Context, d *schema.ResourceData, me d.SetId("") return nil } - _ = d.Set("fast_json", fastJson) + _ = d.Set("fast_udp_json", fastJson) err = json.Unmarshal([]byte(fastJson), &fastUdp) if err != nil { return diag.FromErr(err) diff --git a/docs/resources/bigip_fast_tcp_app.md b/docs/resources/bigip_fast_tcp_app.md index 0d3332ce7..20b898c0a 100644 --- a/docs/resources/bigip_fast_tcp_app.md +++ b/docs/resources/bigip_fast_tcp_app.md @@ -63,6 +63,12 @@ See [Pool Members](#pool-members) below for more details. * `monitor` - (Optional,`set`) `monitor` block takes input for FAST-Generated Pool Monitor. See [Pool Monitor](#pool-monitor) below for more details. +* `persistence_profile` - (Optional,`string`) Name of an existing BIG-IP persistence profile to be used. + +* `persistence_type` - (Optional,`string`) Type of persistence profile to be created. Using this option will enable use of FAST generated persistence profiles. + +* `fallback_persistence` - (Optional,`string`) Type of fallback persistence record to be created for each new client connection. + ### virtual server This IP address, combined with the port you specify below, becomes the BIG-IP virtual server address and port, which clients use to access the application diff --git a/docs/resources/bigip_ltm_profile_web_acceleration.md b/docs/resources/bigip_ltm_profile_web_acceleration.md index 7fbf958ca..270123e40 100644 --- a/docs/resources/bigip_ltm_profile_web_acceleration.md +++ b/docs/resources/bigip_ltm_profile_web_acceleration.md @@ -17,9 +17,9 @@ For resources should be named with their "full path". The full path is the combi ```hcl resource "bigip_ltm_profile_web_acceleration" "sample-resource" { - name = "/Common/sample-resource" - defaults_from = "/Common/test2" - cache_size = 101 + name = "/Common/sample-resource" + defaults_from = "/Common/test2" + cache_size = 101 cache_max_entries = 201 } ``` diff --git a/vendor/github.com/f5devcentral/go-bigip/fastbigip.go b/vendor/github.com/f5devcentral/go-bigip/fastbigip.go index 2dde0f228..8c31f22f3 100644 --- a/vendor/github.com/f5devcentral/go-bigip/fastbigip.go +++ b/vendor/github.com/f5devcentral/go-bigip/fastbigip.go @@ -46,25 +46,31 @@ type TmplArrType struct { } type FastTCPJson struct { - Tenant string `json:"tenant_name,omitempty"` - Application string `json:"app_name,omitempty"` - VirtualAddress string `json:"virtual_address,omitempty"` - VirtualPort interface{} `json:"virtual_port,omitempty"` - SnatEnable bool `json:"enable_snat,omitempty"` - SnatAutomap bool `json:"snat_automap"` - MakeSnatPool bool `json:"make_snatpool"` - SnatPoolName string `json:"snatpool_name,omitempty"` - SnatAddresses []string `json:"snat_addresses,omitempty"` - PoolEnable bool `json:"enable_pool"` - MakePool bool `json:"make_pool"` - PoolName string `json:"pool_name,omitempty"` - PoolMembers []FastHttpPool `json:"pool_members,omitempty"` - LoadBalancingMode string `json:"load_balancing_mode,omitempty"` - SlowRampTime int `json:"slow_ramp_time,omitempty"` - MonitorEnable bool `json:"enable_monitor,omitempty"` - MakeMonitor bool `json:"make_monitor"` - TCPMonitor string `json:"monitor_name,omitempty"` - MonitorInterval int `json:"monitor_interval,omitempty"` + Tenant string `json:"tenant_name,omitempty"` + Application string `json:"app_name,omitempty"` + VirtualAddress string `json:"virtual_address,omitempty"` + VirtualPort interface{} `json:"virtual_port,omitempty"` + SnatEnable bool `json:"enable_snat,omitempty"` + SnatAutomap bool `json:"snat_automap"` + MakeSnatPool bool `json:"make_snatpool"` + SnatPoolName string `json:"snatpool_name,omitempty"` + SnatAddresses []string `json:"snat_addresses,omitempty"` + PoolEnable bool `json:"enable_pool"` + MakePool bool `json:"make_pool"` + PoolName string `json:"pool_name,omitempty"` + PoolMembers []FastHttpPool `json:"pool_members,omitempty"` + LoadBalancingMode string `json:"load_balancing_mode,omitempty"` + SlowRampTime int `json:"slow_ramp_time,omitempty"` + MonitorEnable bool `json:"enable_monitor,omitempty"` + MakeMonitor bool `json:"make_monitor"` + TCPMonitor string `json:"monitor_name,omitempty"` + MonitorInterval int `json:"monitor_interval,omitempty"` + EnablePersistence bool `json:"enable_persistence"` + PersistenceProfile string `json:"persistence_profile,omitempty"` + PersistenceType string `json:"persistence_type,omitempty"` + UseExistingPersistenceProfile bool `json:"use_existing_persistence_profile,omitempty"` + EnableFallbackPersistence bool `json:"enable_fallback_persistence"` + FallbackPersistenceType string `json:"fallback_persistence_type,omitempty"` } type FastUDPJson struct {