Skip to content

Commit

Permalink
Merge pull request #988 from F5Networks/devel
Browse files Browse the repository at this point in the history
devel sync to master
  • Loading branch information
RavinderReddyF5 committed Jun 19, 2024
2 parents 9e6b93d + a97a4e6 commit 5d6ed54
Show file tree
Hide file tree
Showing 19 changed files with 596 additions and 61 deletions.
1 change: 1 addition & 0 deletions bigip/datasource_bigip_ltm_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func dataSourceBigipLtmNodeRead(ctx context.Context, d *schema.ResourceData, met

_ = d.Set("name", node.Name)
_ = d.Set("partition", node.Partition)
_ = d.Set("description", node.Description)
_ = d.Set("full_path", node.FullPath)
_ = d.Set("connection_limit", node.ConnectionLimit)
_ = d.Set("dynamic_ratio", node.DynamicRatio)
Expand Down
79 changes: 58 additions & 21 deletions bigip/resource_bigip_as3.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ func resourceBigipAs3Read(ctx context.Context, d *schema.ResourceData, meta inte
as3Json := d.Get("as3_json").(string)
perappMode := d.Get("per_app_mode").(bool)
log.Printf("[INFO] AS3 config:%+v", as3Json)
if d.Get("as3_json") != nil && !perappMode {
if d.Get("as3_json") != nil && !perappMode && d.Get("tenant_filter") == "" {
tList, _, _ = client.GetTenantList(as3Json)
if createdTenants != "" && createdTenants != tList {
tList = createdTenants
Expand All @@ -310,17 +310,7 @@ func resourceBigipAs3Read(ctx context.Context, d *schema.ResourceData, meta inte
log.Printf("[DEBUG] Applications in AS3 get call : %s", applicationList)
if name != "" {
as3Resp, err := client.GetAs3(name, applicationList, d.Get("per_app_mode").(bool))
if d.Get("per_app_mode").(bool) {
as3Json := make(map[string]interface{})
_ = json.Unmarshal([]byte(as3Resp), &as3Json)
out, _ := json.Marshal(as3Json)
as3Dec := string(out)
applicationList = client.GetAppsList(fmt.Sprintf("%v", as3Dec))
log.Printf("[DEBUG] Application List from retreived the GET call in Read function : %s", applicationList)
_ = d.Set("application_list", applicationList)
}

log.Printf("[DEBUG] AS3 json retreived from the GET call in Read function : %s", as3Resp)
if err != nil {
log.Printf("[ERROR] Unable to retrieve json ")
if err.Error() == "unexpected end of JSON input" {
Expand All @@ -336,7 +326,24 @@ func resourceBigipAs3Read(ctx context.Context, d *schema.ResourceData, meta inte
// d.SetId("")
return nil
}
_ = d.Set("as3_json", as3Resp)

if d.Get("per_app_mode").(bool) {
as3Json := make(map[string]interface{})
filteredAs3Json := make(map[string]interface{})
_ = json.Unmarshal([]byte(as3Resp), &as3Json)
for _, value := range strings.Split(applicationList, ",") {
log.Printf("[DEBUG] Fetching AS3 get for Application : %s", value)
filteredAs3Json[value] = as3Json[value]
}
filteredAs3Json["schemaVersion"] = as3Json["schemaVersion"]
out, _ := json.Marshal(filteredAs3Json)
filteredAs3String := string(out)
log.Printf("[DEBUG] AS3 GET call in Read function : %s", filteredAs3Json)
_ = d.Set("as3_json", filteredAs3String)
} else {
_ = d.Set("as3_json", as3Resp)
}

_ = d.Set("tenant_list", name)
} else if d.Get("task_id") != nil {
taskResponse, err := client.Getas3TaskResponse(d.Get("task_id").(string))
Expand All @@ -356,6 +363,7 @@ func resourceBigipAs3Update(ctx context.Context, d *schema.ResourceData, meta in
defer m.Unlock()
as3Json := d.Get("as3_json").(string)
log.Printf("[INFO] Updating As3 Config :%s", as3Json)
oldApplicationList := d.Get("application_list").(string)
tenantList, _, applicationList := client.GetTenantList(as3Json)
_ = d.Set("application_list", applicationList)
perApplication, err := client.CheckSetting()
Expand All @@ -366,6 +374,20 @@ func resourceBigipAs3Update(ctx context.Context, d *schema.ResourceData, meta in
if d.Get("per_app_mode").(bool) {
if perApplication && len(tenantList) == 0 {
oldTenantList := d.Id()
log.Printf("[INFO] oldApplicationList :%s", oldApplicationList)
curApplicationList := client.GetAppsList(as3Json)
log.Printf("[INFO] curApplicationList :%s", curApplicationList)
for _, appName := range strings.Split(oldApplicationList, ",") {
if !strings.Contains(curApplicationList, appName) {
log.Printf("[INFO] Deleting As3 Config for Application:%s in Tenant:%v", appName, oldTenantList)
err := client.DeletePerApplicationAs3Bigip(oldTenantList, appName)
if err != nil {
log.Printf("[ERROR] Unable to DeleteContext: %v :", err)
return diag.FromErr(err)
}
}
}

log.Printf("[INFO] Updating As3 Config for tenant:%s with Per-Application Mode:%v", oldTenantList, perApplication)
err, task_id := client.PostPerAppBigIp(as3Json, oldTenantList)
log.Printf("[DEBUG] task_id from PostPerAppBigIp:%+v", task_id)
Expand All @@ -376,6 +398,8 @@ func resourceBigipAs3Update(ctx context.Context, d *schema.ResourceData, meta in
_ = d.Set("tenant_list", oldTenantList)
_ = d.Set("task_id", task_id)
_ = d.Set("tenant_filter", oldTenantList)
_ = d.Set("application_list", curApplicationList)

} else {
if !perApplication {
return diag.FromErr(fmt.Errorf("Per-Application should be true in Big-IP Setting"))
Expand Down Expand Up @@ -445,20 +469,33 @@ func resourceBigipAs3Delete(ctx context.Context, d *schema.ResourceData, meta in
tList, _, _ = client.GetTenantList(d.Get("as3_json").(string))
}

if d.Id() != "" && tList != "" {
if d.Id() != "" && tList != "" && d.Get("tenant_filter") == "" {
name = tList
} else {
name = d.Id()
}
log.Printf("[INFO] Deleting As3 config for tenants:%+v", name)
err, failedTenants := client.DeleteAs3Bigip(name)
if err != nil {
log.Printf("[ERROR] Unable to DeleteContext: %v :", err)
return diag.FromErr(err)
}
if failedTenants != "" {
_ = d.Set("tenant_list", name)
return resourceBigipAs3Read(ctx, d, meta)
if d.Get("per_app_mode").(bool) {
applicationList := d.Get("application_list").(string)
log.Printf("[INFO] Deleting As3 config for Applications:%+v", applicationList)
for _, appName := range strings.Split(applicationList, ",") {
log.Printf("[INFO] Deleting AS3 for Application : %s", appName)
err := client.DeletePerApplicationAs3Bigip(name, appName)
if err != nil {
log.Printf("[ERROR] Unable to DeleteContext: %v :", err)
return diag.FromErr(err)
}
}
} else {
err, failedTenants := client.DeleteAs3Bigip(name)
if err != nil {
log.Printf("[ERROR] Unable to DeleteContext: %v :", err)
return diag.FromErr(err)
}
if failedTenants != "" {
_ = d.Set("tenant_list", name)
return resourceBigipAs3Read(ctx, d, meta)
}
}
d.SetId("")
return nil
Expand Down
163 changes: 163 additions & 0 deletions bigip/resource_bigip_as3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"net/http"
"os"
"regexp"
"strings"
"testing"

bigip "github.com/f5devcentral/go-bigip"
Expand Down Expand Up @@ -98,6 +99,35 @@ resource "bigip_as3" "perapp2" {
ignore_metadata = true
}
`
var TestAs3PerAppResource = `
resource "bigip_as3" "as3-example" {
tenant_name = "dmz"
as3_json = "${file("` + dir + `/../examples/as3/perApplication_example.json")}"
}
`
var TestAs3PerAppResource1 = `
resource "bigip_as3" "as3-example1" {
tenant_name = "dmz"
as3_json = "${file("` + dir + `/../examples/as3/as3_per_app_example1.json")}"
}
`
var TestAs3PerAppResource2 = `
resource "bigip_as3" "as3-example1" {
tenant_name = "dmz"
as3_json = "${file("` + dir + `/../examples/as3/as3_per_app_example1.json")}"
}
resource "bigip_as3" "as3-example2" {
tenant_name = "dmz"
as3_json = "${file("` + dir + `/../examples/as3/as3_per_app_example2.json")}"
}
`

var TestAs3PerAppResource3 = `
resource "bigip_as3" "as3-example1" {
tenant_name = "dmz"
as3_json = "${file("` + dir + `/../examples/as3/as3_per_app_example3.json")}"
}
`

func TestAccBigipAs3_create_SingleTenant(t *testing.T) {
resource.Test(t, resource.TestCase{
Expand Down Expand Up @@ -434,6 +464,45 @@ func testCheckAs3Exists(name string, exists bool) resource.TestCheckFunc {
}
}

func testCheckAS3AppExists(tenantName, appNames string, exists bool) resource.TestCheckFunc {
return func(s *terraform.State) error {
clientBigip := testAccProvider.Meta().(*bigip.BigIP)
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
client := &http.Client{Transport: tr}
for _, appName := range strings.Split(appNames, ",") {
url := clientBigip.Host + "/mgmt/shared/appsvcs/declare/" + tenantName + "/applications/" + appName
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return fmt.Errorf("[ERROR] Error while creating http request with AS3 json: %v", err)
}
req.SetBasicAuth(clientBigip.User, clientBigip.Password)
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")

resp, err := client.Do(req)
if err != nil {
return err
}

defer func() {
if err := resp.Body.Close(); err != nil {
log.Printf("[DEBUG] Could not close the request to %s", url)
}
}()
var body bytes.Buffer
_, err = io.Copy(&body, resp.Body)
// body, err := ioutil.ReadAll(resp.Body)
bodyString := body.String()
if (resp.Status == "204 No Content" || err != nil || resp.StatusCode == 404) && exists {
return fmt.Errorf("[ERROR] Error while checking as3resource present in bigip :%s %v", bodyString, err)
}
}

return nil
}
}

func TestAccBigipAs3_badJSON(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
Expand Down Expand Up @@ -464,3 +533,97 @@ func testCheckAs3Destroy(s *terraform.State) error {
}
return nil
}

func TestAccBigipPer_AppAs3_SingleTenant(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAcctPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testCheckAs3Destroy,
Steps: []resource.TestStep{
{
Config: TestAs3PerAppResource,
Check: resource.ComposeTestCheckFunc(
testCheckAs3Exists("dmz", true),
testCheckAS3AppExists("dmz", "Application1,Application2", true),
),
},
},
})
}

func TestAccBigipPer_AppAs3_update_addApplication(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAcctPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testCheckAs3Destroy,
Steps: []resource.TestStep{
{
Config: TestAs3PerAppResource1,

Check: resource.ComposeTestCheckFunc(
testCheckAs3Exists("dmz", true),
testCheckAS3AppExists("dmz", "path_app1", true),
testCheckAs3Exists("dmztest", false),
testCheckAS3AppExists("dmztest", "path_app1", false),
),
},
{
Config: TestAs3PerAppResource2,
Check: resource.ComposeTestCheckFunc(
testCheckAs3Exists("dmz", true),
testCheckAS3AppExists("dmz", "path_app1,path_app2", true),
),
},
},
})
}

func TestAccBigipPer_AppAs3_remove_Application(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAcctPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testCheckAs3Destroy,
Steps: []resource.TestStep{
{
Config: TestAs3PerAppResource3,

Check: resource.ComposeTestCheckFunc(
testCheckAs3Exists("dmz", true),
testCheckAS3AppExists("dmz", "path_app1", true),
testCheckAS3AppExists("dmz", "path_app2", true),
),
},
{
Config: TestAs3PerAppResource1,
Check: resource.ComposeTestCheckFunc(
testCheckAs3Exists("dmz", true),
testCheckAS3AppExists("dmz", "path_app1", true),
testCheckAS3AppExists("dmz", "path_app2", false),
),
},
},
})
}

// Per-App mode is disabled
func TestAccBigipPer_AppAs3_update_invalidJson(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAcctPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testCheckAs3Destroy,
Steps: []resource.TestStep{
{
Config: TestAs3PerAppResource1,
ExpectError: regexp.MustCompile("Invalid request value"),
},
},
})
}
11 changes: 11 additions & 0 deletions bigip/resource_bigip_awaf_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"fmt"
"log"
"os"
"reflect"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -344,6 +345,16 @@ func resourceBigipAwafPolicy() *schema.Resource {
Type: schema.TypeString,
Optional: true,
//Computed: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
oldResp := []byte(old)
newResp := []byte(new)
oldJsonref := make(map[string]interface{})
newJsonref := make(map[string]interface{})
_ = json.Unmarshal(oldResp, &oldJsonref)
_ = json.Unmarshal(newResp, &newJsonref)
jsonEqualityBefore := reflect.DeepEqual(oldJsonref, newJsonref)
return jsonEqualityBefore
},
Description: "The payload of the WAF Policy to be used for IMPORT on to BIGIP",
},
"policy_export_json": {
Expand Down
8 changes: 4 additions & 4 deletions bigip/resource_bigip_ltm_profile_request_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func resourceBigipLtmProfileRequestLogRead(ctx context.Context, d *schema.Resour
_ = d.Set("requestlog_error_pool", pp.RequestLogErrorPool)
}
if _, ok := d.GetOk("requestlog_template"); ok {
_ = d.Set("requestlog_template", pp.RequestLogTemplate)
_ = d.Set("requestlog_template", strings.ReplaceAll(pp.RequestLogTemplate, `\"`, `"`))
}
if _, ok := d.GetOk("requestlog_protocol"); ok {
_ = d.Set("requestlog_protocol", pp.RequestLogProtocol)
Expand Down Expand Up @@ -262,7 +262,7 @@ func resourceBigipLtmProfileRequestLogRead(ctx context.Context, d *schema.Resour
_ = d.Set("response_logging", pp.ResponseLogging)
}
if _, ok := d.GetOk("responselog_template"); ok {
_ = d.Set("responselog_template", pp.ResponseLogTemplate)
_ = d.Set("responselog_template", strings.ReplaceAll(pp.ResponseLogTemplate, `\"`, `"`))
}
if _, ok := d.GetOk("requestlog_error_template"); ok {
_ = d.Set("requestlog_error_template", pp.RequestLogErrorTemplate)
Expand Down Expand Up @@ -341,9 +341,9 @@ func getRequestLogProfileConfig(d *schema.ResourceData, config *bigip.RequestLog
config.ResponseLogErrorProtocol = d.Get("responselog_error_protocol").(string)
config.RequestLogging = d.Get("request_logging").(string)
config.ResponseLogging = d.Get("response_logging").(string)
config.RequestLogTemplate = d.Get("requestlog_template").(string)
config.RequestLogTemplate = strings.ReplaceAll(d.Get("requestlog_template").(string), `"`, `\"`)
config.RequestLogErrorTemplate = d.Get("requestlog_error_template").(string)
config.ResponseLogTemplate = d.Get("responselog_template").(string)
config.ResponseLogTemplate = strings.ReplaceAll(d.Get("responselog_template").(string), `"`, `\"`)
config.ResponseLogErrorTemplate = d.Get("responselog_error_template").(string)
config.ProxyResponse = d.Get("proxy_response").(string)
config.ProxyCloseOnError = d.Get("proxyclose_on_error").(string)
Expand Down
Loading

0 comments on commit 5d6ed54

Please sign in to comment.