From e8e3df1e3c4fe0d16f2727501f6e9891c6094a37 Mon Sep 17 00:00:00 2001 From: George Nikolopoulos Date: Thu, 30 Jul 2020 16:58:59 +0300 Subject: [PATCH 1/2] Add resource sslvserver_sslpolicy_binding with examples Signed-off-by: George Nikolopoulos --- citrixadc/provider.go | 1 + ..._citrixadc_sslvserver_sslpolicy_binding.go | 211 +++++++++++++++ ...ixadc_sslvserver_sslpolicy_binding_test.go | 256 ++++++++++++++++++ .../sslvserver_sslpolicy_binding/provider.tf | 3 + .../sslvserver_sslpolicy_binding/resources.tf | 38 +++ 5 files changed, 509 insertions(+) create mode 100644 citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding.go create mode 100644 citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding_test.go create mode 100644 examples/sslvserver_sslpolicy_binding/provider.tf create mode 100644 examples/sslvserver_sslpolicy_binding/resources.tf diff --git a/citrixadc/provider.go b/citrixadc/provider.go index 33d9d1be2..aee677c0d 100644 --- a/citrixadc/provider.go +++ b/citrixadc/provider.go @@ -138,6 +138,7 @@ func providerResources() map[string]*schema.Resource { "citrixadc_netprofile": resourceCitrixAdcNetprofile(), "citrixadc_servicegroup_lbmonitor_binding": resourceCitrixAdcServicegroup_lbmonitor_binding(), "citrixadc_nsparam": resourceCitrixAdcNsparam(), + "citrixadc_sslvserver_sslpolicy_binding": resourceCitrixAdcSslvserver_sslpolicy_binding(), } } diff --git a/citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding.go b/citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding.go new file mode 100644 index 000000000..15088db23 --- /dev/null +++ b/citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding.go @@ -0,0 +1,211 @@ +package citrixadc + +import ( + "github.com/chiradeep/go-nitro/config/ssl" + + "github.com/chiradeep/go-nitro/netscaler" + "github.com/hashicorp/terraform/helper/schema" + + "fmt" + "log" + "strings" +) + +func resourceCitrixAdcSslvserver_sslpolicy_binding() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + Create: createSslvserver_sslpolicy_bindingFunc, + Read: readSslvserver_sslpolicy_bindingFunc, + Delete: deleteSslvserver_sslpolicy_bindingFunc, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "gotopriorityexpression": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "invoke": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "labelname": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "labeltype": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "policyname": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "priority": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + ForceNew: true, + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "vservername": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func createSslvserver_sslpolicy_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In createSslvserver_sslpolicy_bindingFunc") + client := meta.(*NetScalerNitroClient).client + vservername := d.Get("vservername") + policyname := d.Get("policyname") + + // Use `,` as the separator since it is invalid character for adc entity strings + bindingId := fmt.Sprintf("%s,%s", vservername, policyname) + + sslvserver_sslpolicy_binding := ssl.Sslvserversslpolicybinding{ + Gotopriorityexpression: d.Get("gotopriorityexpression").(string), + Invoke: d.Get("invoke").(bool), + Labelname: d.Get("labelname").(string), + Labeltype: d.Get("labeltype").(string), + Policyname: d.Get("policyname").(string), + Priority: d.Get("priority").(int), + Type: d.Get("type").(string), + Vservername: d.Get("vservername").(string), + } + + err := client.UpdateUnnamedResource(netscaler.Sslvserver_sslpolicy_binding.Type(), &sslvserver_sslpolicy_binding) + if err != nil { + return err + } + + d.SetId(bindingId) + + err = readSslvserver_sslpolicy_bindingFunc(d, meta) + if err != nil { + log.Printf("[ERROR] netscaler-provider: ?? we just created this sslvserver_sslpolicy_binding but we can't read it ?? %s", bindingId) + return nil + } + return nil +} + +func readSslvserver_sslpolicy_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In readSslvserver_sslpolicy_bindingFunc") + client := meta.(*NetScalerNitroClient).client + + bindingId := d.Id() + idSlice := strings.Split(bindingId, ",") + + if len(idSlice) < 2 { + return fmt.Errorf("Cannot deduce policyname from id string") + } + + if len(idSlice) > 2 { + return fmt.Errorf("Too many separators \",\" in id string") + } + + vservername := idSlice[0] + policyname := idSlice[1] + + log.Printf("[DEBUG] citrixadc-provider: Reading sslvserver_sslpolicy_binding state %s", bindingId) + findParams := netscaler.FindParams{ + ResourceType: "sslvserver_sslpolicy_binding", + ResourceName: vservername, + ResourceMissingErrorCode: 461, + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + + // Unexpected error + if err != nil { + log.Printf("[DEBUG] citrixadc-provider: Error during FindResourceArrayWithParams %s", err.Error()) + return err + } + + // Resource is missing + if len(dataArr) == 0 { + log.Printf("[DEBUG] citrixadc-provider: FindResourceArrayWithParams returned empty array") + log.Printf("[WARN] citrixadc-provider: Clearing sslvserver_sslpolicy_binding state %s", bindingId) + d.SetId("") + return nil + } + + // Iterate through results to find the one with the right policy name + foundIndex := -1 + for i, v := range dataArr { + if v["policyname"].(string) == policyname { + foundIndex = i + break + } + } + + // Resource is missing + if foundIndex == -1 { + log.Printf("[DEBUG] citrixadc-provider: FindResourceArrayWithParams monitor name not found in array") + log.Printf("[WARN] citrixadc-provider: Clearing sslvserver_sslpolicy_binding state %s", bindingId) + d.SetId("") + return nil + } + // Fallthrough + + data := dataArr[foundIndex] + + d.Set("name", data["name"]) + d.Set("gotopriorityexpression", data["gotopriorityexpression"]) + d.Set("invoke", data["invoke"]) + d.Set("labelname", data["labelname"]) + d.Set("labeltype", data["labeltype"]) + d.Set("policyname", data["policyname"]) + d.Set("priority", data["priority"]) + d.Set("type", data["type"]) + d.Set("vservername", data["vservername"]) + + return nil + +} + +func deleteSslvserver_sslpolicy_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In deleteSslvserver_sslpolicy_bindingFunc") + client := meta.(*NetScalerNitroClient).client + bindingId := d.Id() + idSlice := strings.Split(bindingId, ",") + + vservername := idSlice[0] + policyname := idSlice[1] + + args := make([]string, 0) + args = append(args, fmt.Sprintf("policyname:%v", policyname)) + + if v, ok := d.GetOk("priority"); ok { + args = append(args, fmt.Sprintf("priority:%v", v)) + } + + if v, ok := d.GetOk("type"); ok { + args = append(args, fmt.Sprintf("type:%v", v)) + } + + err := client.DeleteResourceWithArgs(netscaler.Sslvserver_sslpolicy_binding.Type(), vservername, args) + if err != nil { + return err + } + + d.SetId("") + + return nil +} diff --git a/citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding_test.go b/citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding_test.go new file mode 100644 index 000000000..9b366b709 --- /dev/null +++ b/citrixadc/resource_citrixadc_sslvserver_sslpolicy_binding_test.go @@ -0,0 +1,256 @@ +/* +Copyright 2016 Citrix Systems, Inc + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package citrixadc + +import ( + "fmt" + "github.com/chiradeep/go-nitro/netscaler" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "strings" + "testing" +) + +func TestAccSslvserver_sslpolicy_binding_lbvserver(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckSslvserver_sslpolicy_bindingDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccSslvserver_sslpolicy_binding_lbvserver_step1, + Check: resource.ComposeTestCheckFunc( + testAccCheckSslvserver_sslpolicy_bindingExist("citrixadc_sslvserver_sslpolicy_binding.tf_binding_lb", nil), + ), + }, + resource.TestStep{ + Config: testAccSslvserver_sslpolicy_binding_lbvserver_step2, + Check: resource.ComposeTestCheckFunc( + testAccCheckSslvserver_sslpolicy_bindingExist("citrixadc_sslvserver_sslpolicy_binding.tf_binding_lb", nil), + ), + }, + }, + }) +} + +func TestAccSslvserver_sslpolicy_binding_csvserver(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckSslvserver_sslpolicy_bindingDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccSslvserver_sslpolicy_binding_csvserver_step1, + Check: resource.ComposeTestCheckFunc( + testAccCheckSslvserver_sslpolicy_bindingExist("citrixadc_sslvserver_sslpolicy_binding.tf_binding_cs", nil), + ), + }, + resource.TestStep{ + Config: testAccSslvserver_sslpolicy_binding_csvserver_step2, + Check: resource.ComposeTestCheckFunc( + testAccCheckSslvserver_sslpolicy_bindingExist("citrixadc_sslvserver_sslpolicy_binding.tf_binding_cs", nil), + ), + }, + }, + }) +} + +func testAccCheckSslvserver_sslpolicy_bindingExist(n string, id *string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No lb vserver name is set") + } + + if id != nil { + if *id != "" && *id != rs.Primary.ID { + return fmt.Errorf("Resource ID has changed!") + } + + *id = rs.Primary.ID + } + + idSlice := strings.Split(rs.Primary.ID, ",") + + vservername := idSlice[0] + policyname := idSlice[1] + + client := testAccProvider.Meta().(*NetScalerNitroClient).client + findParams := netscaler.FindParams{ + ResourceType: "sslvserver_sslpolicy_binding", + ResourceName: vservername, + ResourceMissingErrorCode: 461, + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + if err != nil { + return err + } + + if len(dataArr) == 0 { + return fmt.Errorf("sslvserver sslpolicy binding zero array result") + } + + foundIndex := -1 + for i, v := range dataArr { + if v["policyname"].(string) == policyname { + foundIndex = i + break + } + } + + if foundIndex == -1 { + return fmt.Errorf("sslvserver sslpolicy binding does not exist") + } + + return nil + } +} + +func testAccCheckSslvserver_sslpolicy_bindingDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*NetScalerNitroClient).client + + for _, rs := range s.RootModule().Resources { + if rs.Type != "citrixadc_sslvserver_sslpolicy_binding" { + continue + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No name is set") + } + + idSlice := strings.Split(rs.Primary.ID, ",") + + vservername := idSlice[0] + + findParams := netscaler.FindParams{ + ResourceType: "sslvserver_sslpolicy_binding", + ResourceName: vservername, + ResourceMissingErrorCode: 461, + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + + if err != nil { + return err + } + + if len(dataArr) > 0 { + return fmt.Errorf("sslvserver sslpolicy binding still exists") + } + + } + + return nil +} + +const testAccSslvserver_sslpolicy_binding_lbvserver_step1 = ` +resource "citrixadc_lbvserver" "tf_lbvserver" { + name = "tf_lbvserver" + ipv46 = "192.168.34.21" + port = "443" + servicetype = "SSL" + sslprofile = "ns_default_ssl_profile_frontend" +} + + +resource "citrixadc_sslpolicy" "tf_sslpolicy" { + name = "tf_sslpolicy" + rule = "true" + action = "NOOP" +} + +resource "citrixadc_sslvserver_sslpolicy_binding" "tf_binding_lb" { + vservername = citrixadc_lbvserver.tf_lbvserver.name + policyname = citrixadc_sslpolicy.tf_sslpolicy.name + priority = 333 + type = "REQUEST" +} +` + +const testAccSslvserver_sslpolicy_binding_lbvserver_step2 = ` +resource "citrixadc_lbvserver" "tf_lbvserver" { + name = "tf_lbvserver" + ipv46 = "192.168.34.21" + port = "443" + servicetype = "SSL" + sslprofile = "ns_default_ssl_profile_frontend" +} + + +resource "citrixadc_sslpolicy" "tf_sslpolicy" { + name = "tf_sslpolicy" + rule = "true" + action = "NOOP" +} + +resource "citrixadc_sslvserver_sslpolicy_binding" "tf_binding_lb" { + vservername = citrixadc_lbvserver.tf_lbvserver.name + policyname = citrixadc_sslpolicy.tf_sslpolicy.name + priority = 444 + type = "REQUEST" +} +` + +const testAccSslvserver_sslpolicy_binding_csvserver_step1 = ` +resource "citrixadc_csvserver" "tf_csvserver" { + + name = "tf_csvserver" + ipv46 = "10.202.11.11" + port = 9090 + servicetype = "SSL" + sslprofile = "ns_default_ssl_profile_frontend" +} + +resource "citrixadc_sslpolicy" "tf_sslpolicy" { + name = "tf_sslpolicy" + rule = "true" + action = "NOOP" +} + +resource "citrixadc_sslvserver_sslpolicy_binding" "tf_binding_cs" { + vservername = citrixadc_csvserver.tf_csvserver.name + policyname = citrixadc_sslpolicy.tf_sslpolicy.name + priority = 333 + type = "REQUEST" +} +` + +const testAccSslvserver_sslpolicy_binding_csvserver_step2 = ` +resource "citrixadc_csvserver" "tf_csvserver" { + + name = "tf_csvserver" + ipv46 = "10.202.11.11" + port = 9090 + servicetype = "SSL" + sslprofile = "ns_default_ssl_profile_frontend" +} + +resource "citrixadc_sslpolicy" "tf_sslpolicy" { + name = "tf_sslpolicy" + rule = "true" + action = "NOOP" +} + +resource "citrixadc_sslvserver_sslpolicy_binding" "tf_binding_cs" { + vservername = citrixadc_csvserver.tf_csvserver.name + policyname = citrixadc_sslpolicy.tf_sslpolicy.name + priority = 444 + type = "REQUEST" +} +` diff --git a/examples/sslvserver_sslpolicy_binding/provider.tf b/examples/sslvserver_sslpolicy_binding/provider.tf new file mode 100644 index 000000000..3d4508593 --- /dev/null +++ b/examples/sslvserver_sslpolicy_binding/provider.tf @@ -0,0 +1,3 @@ +provider "citrixadc" { + endpoint = "http://localhost:8080" +} diff --git a/examples/sslvserver_sslpolicy_binding/resources.tf b/examples/sslvserver_sslpolicy_binding/resources.tf new file mode 100644 index 000000000..f4048809d --- /dev/null +++ b/examples/sslvserver_sslpolicy_binding/resources.tf @@ -0,0 +1,38 @@ +resource "citrixadc_lbvserver" "tf_lbvserver" { + name = "tf_lbvserver" + ipv46 = "192.168.34.21" + port = "443" + servicetype = "SSL" + sslprofile = "ns_default_ssl_profile_frontend" +} + +resource "citrixadc_csvserver" "tf_csvserver" { + + name = "tf_csvserver" + ipv46 = "10.202.11.11" + port = 9090 + servicetype = "SSL" + sslprofile = "ns_default_ssl_profile_frontend" +} + + +resource "citrixadc_sslpolicy" "tf_sslpolicy" { + name = "tf_sslpolicy" + rule = "true" + action = "NOOP" +} + +# Import id is , +resource "citrixadc_sslvserver_sslpolicy_binding" "tf_binding_lb" { + vservername = citrixadc_lbvserver.tf_lbvserver.name + policyname = citrixadc_sslpolicy.tf_sslpolicy.name + priority = 333 + type = "REQUEST" +} + +resource "citrixadc_sslvserver_sslpolicy_binding" "tf_binding_cs" { + vservername = citrixadc_csvserver.tf_csvserver.name + policyname = citrixadc_sslpolicy.tf_sslpolicy.name + priority = 333 + type = "REQUEST" +} From 2f35653013dbecbf5441324d049eb2be493b778d Mon Sep 17 00:00:00 2001 From: George Nikolopoulos Date: Thu, 30 Jul 2020 17:27:22 +0300 Subject: [PATCH 2/2] Ignore sslpolicybinding blocks unless explicitely defined. Signed-off-by: George Nikolopoulos --- citrixadc/sslvserver_utils.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/citrixadc/sslvserver_utils.go b/citrixadc/sslvserver_utils.go index 5adea0de6..114ba0e1b 100644 --- a/citrixadc/sslvserver_utils.go +++ b/citrixadc/sslvserver_utils.go @@ -383,6 +383,12 @@ func readSslpolicyBindings(d *schema.ResourceData, meta interface{}, sslvserverN log.Printf("[DEBUG] citrixadc-provider: In readSslpolicyBindings") client := meta.(*NetScalerNitroClient).client + // Ignore sslpolicy bindings unless explicitely in configuration + // If not it is confused with binding defined by the explicit sslvserver_sslpolicy_binding resource + if _, ok := d.GetOk("sslpolicybinding"); !ok { + return nil + } + findParams := netscaler.FindParams{ ResourceType: "sslvserver_sslpolicy_binding", ResourceName: sslvserverName,