diff --git a/CHANGELOG.md b/CHANGELOG.md index 6396737dd..42b388a14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +## 1.4.0 (July 13, 2021) + +FEATURES + +* **New Resource** `vlan_nsip_binding` +* **New Resource** `vlan_interface_binding` +* **New Resource** `nsmode` + +ENHANCEMENTS + +* Extra cluster configuration options. Now a SNIP and vtysh commands can be added per node added to the cluster. +* Update to latest adc-nitro-go library. + +BUG FIXES + +* Correct the way the `route` resource is read from the ADC. Now takes into account the `ownergroup` attribute. +* Correct `ownernode` argument of `nsip` resource to TypeString. Now ownernode will be applied correctly. + ## 1.3.0 (July 6, 2021) ENHANCEMENTS diff --git a/citrixadc/provider.go b/citrixadc/provider.go index e8af723e1..07c1f1002 100644 --- a/citrixadc/provider.go +++ b/citrixadc/provider.go @@ -190,6 +190,9 @@ func providerResources() map[string]*schema.Resource { "citrixadc_lbparameter": resourceCitrixAdcLbparameter(), "citrixadc_iptunnel": resourceCitrixAdcIptunnel(), "citrixadc_vlan": resourceCitrixAdcVlan(), + "citrixadc_vlan_interface_binding": resourceCitrixAdcVlan_interface_binding(), + "citrixadc_vlan_nsip_binding": resourceCitrixAdcVlan_nsip_binding(), + "citrixadc_nsmode": resourceCitrixAdcNsmode(), } } diff --git a/citrixadc/resource_citrixadc_cluster.go b/citrixadc/resource_citrixadc_cluster.go index 7fdc16506..e87d30608 100644 --- a/citrixadc/resource_citrixadc_cluster.go +++ b/citrixadc/resource_citrixadc_cluster.go @@ -3,6 +3,7 @@ package citrixadc import ( "github.com/citrix/adc-nitro-go/resource/config/cluster" "github.com/citrix/adc-nitro-go/resource/config/ns" + "github.com/citrix/adc-nitro-go/resource/config/router" "github.com/citrix/adc-nitro-go/service" "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" @@ -256,6 +257,33 @@ func resourceCitrixAdcCluster() *schema.Resource { Description: "Ignore validity of endpoint TLS certificate if true", Default: false, }, + // Flags for adding node SNIP to CLIP before joining + "snip_netmask": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: false, + }, + "snip_ipaddress": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: false, + }, + "addsnip": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + // Optional VTYSH commands + "vtysh_enable": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "vtysh": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, }, }, @@ -1352,6 +1380,38 @@ func addSingleClusterNode(d *schema.ResourceData, meta interface{}, nodeData map return err } + // Register node ip to the CLIP if flag is set + if nodeData["addsnip"].(bool) { + nodeNsip := nsip{ + Ownernode: strconv.Itoa(nodeData["nodeid"].(int)), + Ipaddress: nodeData["snip_ipaddress"].(string), + Mgmtaccess: "ENABLED", + Netmask: nodeData["snip_netmask"].(string), + Type: "SNIP", + } + log.Printf("[DEBUG] citrixadc-provider: registering node ip %v", nodeNsip) + _, err := client.AddResource(service.Nsip.Type(), nodeData["ipaddress"].(string), &nodeNsip) + if err != nil { + return err + } + } + + // Do the VTYSH commands if flag is set + if nodeData["vtysh_enable"].(bool) { + cmdList := nodeData["vtysh"].([]interface{}) + for _, val := range cmdList { + vtyshCmdString := val.(string) + + routerdynamicrouting := router.Routerdynamicrouting{ + Commandstring: vtyshCmdString, + } + err := client.ActOnResource("routerdynamicrouting", &routerdynamicrouting, "apply") + if err != nil { + return err + } + } + } + // Instantiate node client nodeClient, err := instantiateNodeClient(d, meta, nodeData) if err != nil { diff --git a/citrixadc/resource_citrixadc_nsip.go b/citrixadc/resource_citrixadc_nsip.go index 763a5e082..fb69825eb 100644 --- a/citrixadc/resource_citrixadc_nsip.go +++ b/citrixadc/resource_citrixadc_nsip.go @@ -41,7 +41,7 @@ type nsip struct { Ospfareaval int `json:"ospfareaval,omitempty"` Ospflsatype string `json:"ospflsatype,omitempty"` Ownerdownresponse string `json:"ownerdownresponse,omitempty"` - Ownernode int `json:"ownernode,omitempty"` + Ownernode string `json:"ownernode,omitempty"` Restrictaccess string `json:"restrictaccess,omitempty"` Rip string `json:"rip,omitempty"` Riserhimsgcode int `json:"riserhimsgcode,omitempty"` @@ -183,7 +183,7 @@ func resourceCitrixAdcNsip() *schema.Resource { Computed: true, }, "ownernode": &schema.Schema{ - Type: schema.TypeInt, + Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, @@ -295,7 +295,7 @@ func createNsipFunc(d *schema.ResourceData, meta interface{}) error { Ospfarea: d.Get("ospfarea").(int), Ospflsatype: d.Get("ospflsatype").(string), Ownerdownresponse: d.Get("ownerdownresponse").(string), - Ownernode: d.Get("ownernode").(int), + Ownernode: d.Get("ownernode").(string), Restrictaccess: d.Get("restrictaccess").(string), Rip: d.Get("rip").(string), Snmp: d.Get("snmp").(string), @@ -497,7 +497,7 @@ func updateNsipFunc(d *schema.ResourceData, meta interface{}) error { } if d.HasChange("ownernode") { log.Printf("[DEBUG] citrixadc-provider: Ownernode has changed for nsip %s, starting update", ipaddress) - nsip.Ownernode = d.Get("ownernode").(int) + nsip.Ownernode = d.Get("ownernode").(string) hasChange = true } if d.HasChange("restrictaccess") { diff --git a/citrixadc/resource_citrixadc_nsmode.go b/citrixadc/resource_citrixadc_nsmode.go new file mode 100644 index 000000000..c778d55e0 --- /dev/null +++ b/citrixadc/resource_citrixadc_nsmode.go @@ -0,0 +1,272 @@ +package citrixadc + +import ( + "fmt" + + "github.com/citrix/adc-nitro-go/service" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + + "log" +) + +func resourceCitrixAdcNsmode() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + Create: createNsmodeFunc, + Read: readNsmodeFunc, + Delete: deleteNsmodeFunc, + Schema: map[string]*schema.Schema{ + "fr": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "l2": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "usip": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "cka": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "tcpb": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "mbf": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "edge": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "usnip": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "l3": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "pmtud": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "mediaclassification": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "sradv": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "dradv": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "iradv": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "sradv6": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "dradv6": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "bridgebpdus": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + "ulfd": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + } +} + +var modesList = [...]string{ + "fr", + "l2", + "usip", + "cka", + "tcpb", + "mbf", + "edge", + "usnip", + "l3", + "pmtud", + "mediaclassification", + "sradv", + "dradv", + "iradv", + "sradv6", + "dradv6", + "bridgebpdus", + "ulfd", +} + +func createNsmodeFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In createNsmodeFunc") + nsmodeName := resource.PrefixedUniqueId("tf-nsmode-") + + err := syncNsmode(d, meta) + if err != nil { + return err + } + + d.SetId(nsmodeName) + + err = readNsmodeFunc(d, meta) + if err != nil { + log.Printf("[ERROR] netscaler-provider: ?? we just created this nsmode but we can't read it ?? %s", nsmodeName) + return nil + } + return nil +} + +func readNsmodeFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In readNsmodeFunc") + client := meta.(*NetScalerNitroClient).client + nsmodeName := d.Id() + log.Printf("[DEBUG] citrixadc-provider: Reading nsmode state %s", nsmodeName) + findParams := service.FindParams{ + ResourceType: "nsmode", + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + if err != nil { + log.Printf("[WARN] citrixadc-provider: Error during read %s", err) + log.Printf("[WARN] citrixadc-provider: Clearing nsmode state %s", nsmodeName) + d.SetId("") + return nil + } + if len(dataArr) != 1 { + return fmt.Errorf("Unexpected fetched nsmode result %v", dataArr) + } + data := dataArr[0] + + for _, mode := range modesList { + if val, ok := data[mode]; ok { + if val.(bool) { + d.Set(mode, true) + } else { + d.Set(mode, false) + } + } + } + + return nil + +} + +func deleteNsmodeFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In deleteNsmodeFunc") + + d.SetId("") + + return nil +} + +func syncNsmode(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In syncNsmode") + enableList := make([]string, 0, len(modesList)) + disableList := make([]string, 0, len(modesList)) + + for _, modeName := range modesList { + if val, ok := d.GetOkExists(modeName); ok { + if val.(bool) { + enableList = append(enableList, modeName) + } else { + disableList = append(disableList, modeName) + } + } + } + + if len(enableList) > 0 { + if err := enableNsModeList(meta, enableList); err != nil { + return err + } + } + + if len(disableList) > 0 { + if err := disableNsModeList(meta, disableList); err != nil { + return err + } + } + + return nil +} + +type nsfeature struct { + Mode []string `json:"mode"` +} + +func enableNsModeList(meta interface{}, enableList []string) error { + log.Printf("[DEBUG] citrixadc-provider: In enableNsModeList") + client := meta.(*NetScalerNitroClient).client + features := nsfeature{ + Mode: enableList, + } + err := client.ActOnResource("nsmode", &features, "enable") + if err != nil { + return err + } + return nil +} + +func disableNsModeList(meta interface{}, disableList []string) error { + log.Printf("[DEBUG] citrixadc-provider: In disableNsModeList") + client := meta.(*NetScalerNitroClient).client + features := nsfeature{ + Mode: disableList, + } + err := client.ActOnResource("nsmode", &features, "disable") + if err != nil { + return err + } + return nil +} diff --git a/citrixadc/resource_citrixadc_nsmode_test.go b/citrixadc/resource_citrixadc_nsmode_test.go new file mode 100644 index 000000000..529e8157c --- /dev/null +++ b/citrixadc/resource_citrixadc_nsmode_test.go @@ -0,0 +1,90 @@ +/* +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" + "testing" + + "github.com/citrix/adc-nitro-go/service" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +const testAccNsmode_basic_step1 = ` +resource "citrixadc_nsmode" "tf_nsmode" { + usip = true + cka = true +} +` + +const testAccNsmode_basic_step2 = ` +resource "citrixadc_nsmode" "tf_nsmode" { + usip = false + cka = false +} +` + +func TestAccNsmode_basic(t *testing.T) { + if adcTestbed != "STANDALONE" { + t.Skipf("ADC testbed is %s. Expected STANDALONE.", adcTestbed) + } + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccNsmode_basic_step1, + Check: resource.ComposeTestCheckFunc( + testEnsureNsmodes([]string{"usip", "cka"}, true), + ), + }, + resource.TestStep{ + Config: testAccNsmode_basic_step2, + Check: resource.ComposeTestCheckFunc( + testEnsureNsmodes([]string{"usip", "cka"}, false), + ), + }, + }, + }) +} + +func testEnsureNsmodes(modes []string, expectedState bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(*NetScalerNitroClient).client + findParams := service.FindParams{ + ResourceType: "nsmode", + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + if err != nil { + return err + } + if len(dataArr) != 1 { + return fmt.Errorf("Unexpected fetched nsmode result %v", dataArr) + } + data := dataArr[0] + for _, mode := range modes { + if val, ok := data[mode]; ok { + if val.(bool) != expectedState { + return fmt.Errorf("Wrong mode value for %s. Expected %v, found %v", mode, expectedState, val.(bool)) + } + } else { + return fmt.Errorf("Cannot find mode %s in retrieved modes list", mode) + } + } + return nil + } +} diff --git a/citrixadc/resource_citrixadc_route.go b/citrixadc/resource_citrixadc_route.go index 7d41856c5..da3ac97c9 100644 --- a/citrixadc/resource_citrixadc_route.go +++ b/citrixadc/resource_citrixadc_route.go @@ -144,14 +144,10 @@ func readRouteFunc(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] citrixadc-provider: In readRouteFunc") client := meta.(*NetScalerNitroClient).client routeName := d.Id() + log.Printf("[DEBUG] citrixadc-provider: Reading route state %s", routeName) - argsMap := make(map[string]string) - argsMap["network"] = url.QueryEscape(d.Get("network").(string)) - argsMap["netmask"] = url.QueryEscape(d.Get("netmask").(string)) - argsMap["gateway"] = url.QueryEscape(d.Get("gateway").(string)) findParams := service.FindParams{ ResourceType: service.Route.Type(), - ArgsMap: argsMap, } dataArray, err := client.FindResourceArrayWithParams(findParams) if err != nil { @@ -165,11 +161,36 @@ func readRouteFunc(d *schema.ResourceData, meta interface{}) error { return nil } - if len(dataArray) > 1 { - return fmt.Errorf("multiple entries found for route") + foundIndex := -1 + for i, route := range dataArray { + match := true + if route["network"] != d.Get("network").(string) { + match = false + } + if route["netmask"] != d.Get("netmask").(string) { + match = false + } + if route["gateway"] != d.Get("gateway").(string) { + match = false + } + if val, ok := d.GetOk("ownergroup"); ok { + if route["ownergroup"] != val.(string) { + match = false + } + } + if match { + foundIndex = i + break + } + } + if foundIndex == -1 { + log.Printf("[DEBUG] citrixadc-provider: FindResourceArrayWithParams route not found in array") + log.Printf("[WARN] citrixadc-provider: Clearing route state %s", routeName) + d.SetId("") + return nil } - data := dataArray[0] + data := dataArray[foundIndex] d.Set("advertise", data["advertise"]) d.Set("cost", data["cost"]) @@ -295,8 +316,11 @@ func deleteRouteFunc(d *schema.ResourceData, meta interface{}) error { argsMap["network"] = url.QueryEscape(d.Get("network").(string)) argsMap["netmask"] = url.QueryEscape(d.Get("netmask").(string)) argsMap["gateway"] = url.QueryEscape(d.Get("gateway").(string)) + if val, ok := d.GetOk("ownergroup"); ok { + argsMap["ownergroup"] = url.QueryEscape(val.(string)) + } - err := client.DeleteResourceWithArgsMap(service.Route.Type(), d.Get("network").(string), argsMap) + err := client.DeleteResourceWithArgsMap(service.Route.Type(), "", argsMap) if err != nil { return err } diff --git a/citrixadc/resource_citrixadc_vlan_interface_binding.go b/citrixadc/resource_citrixadc_vlan_interface_binding.go new file mode 100644 index 000000000..37d6fe436 --- /dev/null +++ b/citrixadc/resource_citrixadc_vlan_interface_binding.go @@ -0,0 +1,162 @@ +package citrixadc + +import ( + "fmt" + "net/url" + "strconv" + "strings" + + "github.com/citrix/adc-nitro-go/resource/config/network" + + "github.com/citrix/adc-nitro-go/service" + "github.com/hashicorp/terraform/helper/schema" + + "log" +) + +func resourceCitrixAdcVlan_interface_binding() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + Create: createVlan_interface_bindingFunc, + Read: readVlan_interface_bindingFunc, + Delete: deleteVlan_interface_bindingFunc, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "vlanid": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + }, + "ifnum": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "ownergroup": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "tagged": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + } +} + +func createVlan_interface_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In createVlan_interface_bindingFunc") + client := meta.(*NetScalerNitroClient).client + vlanid := strconv.Itoa(d.Get("vlanid").(int)) + ifnum := d.Get("ifnum").(string) + bindingId := fmt.Sprintf("%s,%s", vlanid, ifnum) + vlan_interface_binding := network.Vlaninterfacebinding{ + Id: d.Get("vlanid").(int), + Ifnum: d.Get("ifnum").(string), + Ownergroup: d.Get("ownergroup").(string), + Tagged: d.Get("tagged").(bool), + } + + err := client.UpdateUnnamedResource(service.Vlan_interface_binding.Type(), &vlan_interface_binding) + if err != nil { + return err + } + + d.SetId(bindingId) + + err = readVlan_interface_bindingFunc(d, meta) + if err != nil { + log.Printf("[ERROR] netscaler-provider: ?? we just created this vlan_interface_binding but we can't read it ?? %s", bindingId) + return nil + } + return nil +} + +func readVlan_interface_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In readVlan_interface_bindingFunc") + client := meta.(*NetScalerNitroClient).client + vlan_interface_bindingName := d.Id() + log.Printf("[DEBUG] citrixadc-provider: Reading vlan_interface_binding state %s", vlan_interface_bindingName) + bindingId := d.Id() + + idSlice := strings.SplitN(bindingId, ",", 2) + + vlanid := idSlice[0] + ifnum := idSlice[1] + + log.Printf("[DEBUG] citrixadc-provider: Reading vlan_interface_bindingName state %s", bindingId) + findParams := service.FindParams{ + ResourceType: "vlan_interface_binding", + ResourceName: vlanid, + ResourceMissingErrorCode: 258, + } + 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 vlan_interface_binding state %s", bindingId) + d.SetId("") + return nil + } + + // Iterate through results to find the one with the right monitor name + foundIndex := -1 + for i, v := range dataArr { + if v["ifnum"].(string) == ifnum { + 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 vlan_interface_binding state %s", bindingId) + d.SetId("") + return nil + } + // Fallthrough + + data := dataArr[foundIndex] + + d.Set("name", data["name"]) + d.Set("vlanid", data["id"]) + d.Set("ifnum", data["ifnum"]) + d.Set("ownergroup", data["ownergroup"]) + d.Set("tagged", data["tagged"]) + + return nil + +} + +func deleteVlan_interface_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In deleteVlan_interface_bindingFunc") + client := meta.(*NetScalerNitroClient).client + bindingId := d.Id() + idSlice := strings.SplitN(bindingId, ",", 2) + vlanid := idSlice[0] + ifnum := idSlice[1] + args := make([]string, 1) + args[0] = fmt.Sprintf("ifnum:%s", url.QueryEscape(ifnum)) + err := client.DeleteResourceWithArgs(service.Vlan_interface_binding.Type(), vlanid, args) + if err != nil { + return err + } + + d.SetId("") + + return nil +} diff --git a/citrixadc/resource_citrixadc_vlan_interface_binding_test.go b/citrixadc/resource_citrixadc_vlan_interface_binding_test.go new file mode 100644 index 000000000..cdbfdb8ac --- /dev/null +++ b/citrixadc/resource_citrixadc_vlan_interface_binding_test.go @@ -0,0 +1,199 @@ +/* +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" + "log" + "strings" + "testing" + + "github.com/citrix/adc-nitro-go/service" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +const testAccVlan_interface_binding_basic_step1 = ` +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 50 + aliasname = "Management VLAN" +} + +resource "citrixadc_vlan_interface_binding" "tf_bind" { + vlanid = citrixadc_vlan.tf_vlan.vlanid + ifnum = "1/1" +} + +` + +const testAccVlan_interface_binding_basic_step2 = ` +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 50 + aliasname = "Management VLAN" +} +` + +func TestAccVlan_interface_binding_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVlan_interface_bindingDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccVlan_interface_binding_basic_step1, + Check: resource.ComposeTestCheckFunc( + testAccCheckVlan_interface_bindingExist("citrixadc_vlan_interface_binding.tf_bind", nil), + ), + }, + resource.TestStep{ + Config: testAccVlan_interface_binding_basic_step2, + Check: resource.ComposeTestCheckFunc( + testAccCheckVlan_interface_bindingNotExist("50,1/1"), + ), + }, + }, + }) +} + +func testAccCheckVlan_interface_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 vlan_interface_binding name is set") + } + + if id != nil { + if *id != "" && *id != rs.Primary.ID { + return fmt.Errorf("Resource ID has changed!") + } + + *id = rs.Primary.ID + } + + client := testAccProvider.Meta().(*NetScalerNitroClient).client + + idSlice := strings.SplitN(rs.Primary.ID, ",", 2) + + vlanid := idSlice[0] + ifnum := idSlice[1] + + log.Printf("[DEBUG] citrixadc-provider: Reading vlan_interface_binding state %s", rs.Primary.ID) + findParams := service.FindParams{ + ResourceType: "vlan_interface_binding", + ResourceName: vlanid, + ResourceMissingErrorCode: 258, + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + + // Unexpected error + if err != nil { + return err + } + + // Resource is missing + if len(dataArr) == 0 { + return fmt.Errorf("Could not retrieve any entries for vlan_interface_binding %s", vlanid) + } + + // Iterate through results to find the one with the right monitor name + foundIndex := -1 + for i, v := range dataArr { + if v["ifnum"].(string) == ifnum { + foundIndex = i + break + } + } + + // Resource is missing + if foundIndex == -1 { + return fmt.Errorf("Did not find vlan_interface_binding with id %s", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckVlan_interface_bindingNotExist(bindingId string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + client := testAccProvider.Meta().(*NetScalerNitroClient).client + + idSlice := strings.SplitN(bindingId, ",", 2) + + vlanid := idSlice[0] + ifnum := idSlice[1] + + log.Printf("[DEBUG] citrixadc-provider: Reading vlan_interface_binding state %s", bindingId) + findParams := service.FindParams{ + ResourceType: "vlan_interface_binding", + ResourceName: vlanid, + ResourceMissingErrorCode: 258, + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + + // Unexpected error + if err != nil { + return err + } + + // Resource is missing + if len(dataArr) == 0 { + return nil + } + + // Iterate through results to find the one with the right monitor name + foundIndex := -1 + for i, v := range dataArr { + if v["ifnum"].(string) == ifnum { + foundIndex = i + break + } + } + + // Resource is missing + if foundIndex == -1 { + return nil + } + + return fmt.Errorf("vlan_interface_binding %s still exists", bindingId) + } +} + +func testAccCheckVlan_interface_bindingDestroy(s *terraform.State) error { + nsClient := testAccProvider.Meta().(*NetScalerNitroClient).client + + for _, rs := range s.RootModule().Resources { + if rs.Type != "citrixadc_vlan_interface_binding" { + continue + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No name is set") + } + + _, err := nsClient.FindResource(service.Vlan_interface_binding.Type(), rs.Primary.ID) + if err == nil { + return fmt.Errorf("vlan_interface_binding %s still exists", rs.Primary.ID) + } + + } + + return nil +} diff --git a/citrixadc/resource_citrixadc_vlan_nsip_binding.go b/citrixadc/resource_citrixadc_vlan_nsip_binding.go new file mode 100644 index 000000000..5e5c89138 --- /dev/null +++ b/citrixadc/resource_citrixadc_vlan_nsip_binding.go @@ -0,0 +1,180 @@ +package citrixadc + +import ( + "fmt" + "net/url" + "strconv" + "strings" + + "github.com/citrix/adc-nitro-go/resource/config/network" + + "github.com/citrix/adc-nitro-go/service" + "github.com/hashicorp/terraform/helper/schema" + + "log" +) + +func resourceCitrixAdcVlan_nsip_binding() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + Create: createVlan_nsip_bindingFunc, + Read: readVlan_nsip_bindingFunc, + Delete: deleteVlan_nsip_bindingFunc, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "vlanid": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ForceNew: true, + }, + "ipaddress": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "netmask": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "ownergroup": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "td": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + } +} + +func createVlan_nsip_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In createVlan_nsip_bindingFunc") + client := meta.(*NetScalerNitroClient).client + vlanid := strconv.Itoa(d.Get("vlanid").(int)) + ipaddress := d.Get("ipaddress").(string) + bindingId := fmt.Sprintf("%s,%s", vlanid, ipaddress) + vlan_nsip_binding := network.Vlanipbinding{ + Id: uint32(d.Get("vlanid").(int)), + Ipaddress: d.Get("ipaddress").(string), + Netmask: d.Get("netmask").(string), + Ownergroup: d.Get("ownergroup").(string), + Td: uint32(d.Get("td").(int)), + } + + err := client.UpdateUnnamedResource(service.Vlan_nsip_binding.Type(), &vlan_nsip_binding) + if err != nil { + return err + } + + d.SetId(bindingId) + + err = readVlan_nsip_bindingFunc(d, meta) + if err != nil { + log.Printf("[ERROR] netscaler-provider: ?? we just created this vlan_nsip_binding but we can't read it ?? %s", bindingId) + return nil + } + return nil +} + +func readVlan_nsip_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In readVlan_nsip_bindingFunc") + client := meta.(*NetScalerNitroClient).client + + bindingId := d.Id() + + idSlice := strings.SplitN(bindingId, ",", 2) + + vlanid := idSlice[0] + ipaddress := idSlice[1] + + log.Printf("[DEBUG] citrixadc-provider: Reading vlan_nsip_bindingName state %s", bindingId) + findParams := service.FindParams{ + ResourceType: "vlan_nsip_binding", + ResourceName: vlanid, + ResourceMissingErrorCode: 258, + } + 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 vlan_nsip_binding state %s", bindingId) + d.SetId("") + return nil + } + + // Iterate through results to find the one with the right monitor name + foundIndex := -1 + for i, v := range dataArr { + if v["ipaddress"].(string) == ipaddress { + 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 vlan_nsip_binding state %s", bindingId) + d.SetId("") + return nil + } + + // Fallthrough + data := dataArr[foundIndex] + + d.Set("name", data["name"]) + d.Set("vlanid", data["id"]) + d.Set("ipaddress", data["ipaddress"]) + d.Set("netmask", data["netmask"]) + d.Set("ownergroup", data["ownergroup"]) + d.Set("td", data["td"]) + + return nil + +} + +func deleteVlan_nsip_bindingFunc(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] citrixadc-provider: In deleteVlan_nsip_bindingFunc") + client := meta.(*NetScalerNitroClient).client + bindingId := d.Id() + idSlice := strings.SplitN(bindingId, ",", 2) + vlanid := idSlice[0] + ipaddress := idSlice[1] + args := make([]string, 0, 4) + + args = append(args, fmt.Sprintf("ipaddress:%s", url.QueryEscape(ipaddress))) + if val, ok := d.GetOk("netmask"); ok { + args = append(args, fmt.Sprintf("netmask:%s", url.QueryEscape(val.(string)))) + } + if val, ok := d.GetOk("td"); ok { + args = append(args, fmt.Sprintf("td:%s", url.QueryEscape(strconv.Itoa(val.(int))))) + } + if val, ok := d.GetOk("ownergroup"); ok { + args = append(args, fmt.Sprintf("ownergroup:%s", url.QueryEscape(val.(string)))) + } + + err := client.DeleteResourceWithArgs(service.Vlan_nsip_binding.Type(), vlanid, args) + if err != nil { + return err + } + + d.SetId("") + + return nil +} diff --git a/citrixadc/resource_citrixadc_vlan_nsip_binding_test.go b/citrixadc/resource_citrixadc_vlan_nsip_binding_test.go new file mode 100644 index 000000000..e190ce757 --- /dev/null +++ b/citrixadc/resource_citrixadc_vlan_nsip_binding_test.go @@ -0,0 +1,218 @@ +/* +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" + "log" + "strings" + "testing" + + "github.com/citrix/adc-nitro-go/service" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +const testAccVlan_nsip_binding_basic_step1 = ` +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 40 + aliasname = "Management VLAN" +} + +resource "citrixadc_nsip" "tf_snip" { + ipaddress = "10.222.74.145" + type = "SNIP" + netmask = "255.255.255.0" + icmp = "ENABLED" + state = "ENABLED" +} + +resource "citrixadc_vlan_nsip_binding" "tf_bind" { + vlanid = citrixadc_vlan.tf_vlan.vlanid + ipaddress = citrixadc_nsip.tf_snip.ipaddress + netmask = citrixadc_nsip.tf_snip.netmask + td = 0 +} +` + +const testAccVlan_nsip_binding_basic_step2 = ` +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 40 + aliasname = "Management VLAN" +} + +resource "citrixadc_nsip" "tf_snip" { + ipaddress = "10.222.74.145" + type = "SNIP" + netmask = "255.255.255.0" + icmp = "ENABLED" + state = "ENABLED" +} +` + +func TestAccVlan_nsip_binding_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVlan_nsip_bindingDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccVlan_nsip_binding_basic_step1, + Check: resource.ComposeTestCheckFunc( + testAccCheckVlan_nsip_bindingExist("citrixadc_vlan_nsip_binding.tf_bind", nil), + ), + }, + resource.TestStep{ + Config: testAccVlan_nsip_binding_basic_step2, + Check: resource.ComposeTestCheckFunc( + testAccCheckVlan_nsip_bindingNotExist("40,10.222.74.145"), + ), + }, + }, + }) +} + +func testAccCheckVlan_nsip_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 vlan_nsip_binding name is set") + } + + if id != nil { + if *id != "" && *id != rs.Primary.ID { + return fmt.Errorf("Resource ID has changed!") + } + + *id = rs.Primary.ID + } + + client := testAccProvider.Meta().(*NetScalerNitroClient).client + + bindingId := rs.Primary.ID + + idSlice := strings.SplitN(bindingId, ",", 2) + + vlanid := idSlice[0] + ipaddress := idSlice[1] + + log.Printf("[DEBUG] citrixadc-provider: Reading vlan_nsip_bindingName state %s", bindingId) + findParams := service.FindParams{ + ResourceType: "vlan_nsip_binding", + ResourceName: vlanid, + ResourceMissingErrorCode: 258, + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + + // Unexpected error + if err != nil { + return err + } + + // Resource is missing + if len(dataArr) == 0 { + return fmt.Errorf("Cannot find vlan_nsip_binding %s", bindingId) + } + + // Iterate through results to find the one with the right monitor name + foundIndex := -1 + for i, v := range dataArr { + if v["ipaddress"].(string) == ipaddress { + foundIndex = i + break + } + } + + // Resource is missing + if foundIndex == -1 { + return fmt.Errorf("Resource missing vlan_nsip_binding %s", bindingId) + } + + return nil + } +} + +func testAccCheckVlan_nsip_bindingNotExist(bindingId string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + client := testAccProvider.Meta().(*NetScalerNitroClient).client + + idSlice := strings.SplitN(bindingId, ",", 2) + + vlanid := idSlice[0] + ipaddress := idSlice[1] + + log.Printf("[DEBUG] citrixadc-provider: Reading vlan_nsip_bindingName state %s", bindingId) + findParams := service.FindParams{ + ResourceType: "vlan_nsip_binding", + ResourceName: vlanid, + ResourceMissingErrorCode: 258, + } + dataArr, err := client.FindResourceArrayWithParams(findParams) + + // Unexpected error + if err != nil { + return err + } + + // Resource is missing + if len(dataArr) == 0 { + return nil + } + + // Iterate through results to find the one with the right monitor name + foundIndex := -1 + for i, v := range dataArr { + if v["ipaddress"].(string) == ipaddress { + foundIndex = i + break + } + } + + // Resource is missing + if foundIndex == -1 { + return nil + } + + return fmt.Errorf("Resource still exists vlan_nsip_binding %s", bindingId) + } +} + +func testAccCheckVlan_nsip_bindingDestroy(s *terraform.State) error { + nsClient := testAccProvider.Meta().(*NetScalerNitroClient).client + + for _, rs := range s.RootModule().Resources { + if rs.Type != "citrixadc_vlan_nsip_binding" { + continue + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No name is set") + } + + _, err := nsClient.FindResource(service.Vlan_nsip_binding.Type(), rs.Primary.ID) + if err == nil { + return fmt.Errorf("vlan_nsip_binding %s still exists", rs.Primary.ID) + } + + } + + return nil +} diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md index 4b574fc8c..ee4d4daf2 100644 --- a/docs/resources/cluster.md +++ b/docs/resources/cluster.md @@ -164,6 +164,11 @@ Cluster node supports the following: * `username` - (Optional) Defines the username that will be used by the NITRO API for authentication. Defaults to the value of the same argument of the provider currently in effect. * `password` - (Required) Defines the password that will be used by the NITRO API for authentication. Defaults to the value of the same argument of the provider currently in effect. * `insecure_skip_verify` - (Optional) Boolean variable that defines if an error should be thrown if the target ADC's TLS certificate is not trusted. When `true` the error will be ignored. When `false` such an error will cause the failure of any provider operation. Defaults to `false`. +* `addsnip` - (Optional) Boolean variable that determines if a node SNIP should be added to the CLIP before joining the cluster. +* `snip_ipaddress` - (Optional) Node SNIP address to add to the CLIP. Applied only when `addsnip=true`. +* `snip_netmask` - (Optional) Node SNIP netmask to add to the CLIP. Applied only when `addsnip=true`. +* `vtysh_enable` - (Optional) Boolean variable that determines if vtysh commands should be applied to the CLIP before node joins the custer. +* `vtysh` - (Optional) Vtysh commands to add to the CLIP before node joins the cluster. Applied only when `vtysh_enable=true`. Cluster nodegroup supports the following: diff --git a/docs/resources/nsmode.md b/docs/resources/nsmode.md new file mode 100644 index 000000000..a4fd6026d --- /dev/null +++ b/docs/resources/nsmode.md @@ -0,0 +1,48 @@ +--- +subcategory: "NS" +--- + +# Resource: nsmode + +The nsmode resource is used to enable or disable ADC modes. + + +## Example usage + +```hcl +resource "citrixadc_nsmode" "tf_nsmode" { + usip = true + cka = false +} +``` + + +## Argument Reference + +The following arguments can set to `true` or `false` to enable or disable the corresponding mode. + +* `fr` - (Optional) +* `l2` - (Optional) +* `usip` - (Optional) +* `cka` - (Optional) +* `tcpb` - (Optional) +* `mbf` - (Optional) +* `edge` - (Optional) +* `usnip` - (Optional) +* `l3` - (Optional) +* `pmtud` - (Optional) +* `mediaclassification` - (Optional) +* `sradv` - (Optional) +* `dradv` - (Optional) +* `iradv` - (Optional) +* `sradv6` - (Optional) +* `dradv6` - (Optional) +* `bridgebpdus` - (Optional) +* `ulfd` - (Optional) + + +## Attribute Reference + +In addition to the arguments, the following attributes are available: + +* `id` - The id of the nsmode resource. It is a random string prefixed with "tf-nsmode-" diff --git a/docs/resources/vlan_interface_binding.md b/docs/resources/vlan_interface_binding.md new file mode 100644 index 000000000..c64bc6d38 --- /dev/null +++ b/docs/resources/vlan_interface_binding.md @@ -0,0 +1,46 @@ +--- +subcategory: "Network" +--- + +# Resource: vlan\_interface\_binding + +The vlan\_interface\_binding resource is used to bind a vlan to an interface. + + +## Example usage + +```hcl +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 40 + aliasname = "Management VLAN" +} + +resource "citrixadc_vlan_interface_binding" "tf_bind" { + vlanid = citrixadc_vlan.tf_vlan.vlanid + ifnum = "1/1" +} +``` + + +## Argument Reference + +* `ifnum` - (Required) The interface to be bound to the VLAN, specified in slot/port notation (for example, 1/3). +* `tagged` - (Optional) Make the interface an 802.1q tagged interface. Packets sent on this interface on this VLAN have an additional 4-byte 802.1q tag, which identifies the VLAN. To use 802.1q tagging, you must also configure the switch connected to the appliance's interfaces. +* `vlanid` - (Required) Specifies the virtual LAN ID. +* `ownergroup` - (Optional) The owner node group in a Cluster for this vlan. + + +## Attribute Reference + +In addition to the arguments, the following attributes are available: + +* `id` - The id of the vlan\_interface\_binding. It is the concatenation of the vlanid and ifnum attributes separated by a comma. + + +## Import + +A vlan\_interface\_binding can be imported using its id, e.g. + +```shell +terraform import citrixadc_vlan_interface_binding.tf_bind 40,1/1 +``` diff --git a/docs/resources/vlan_nsip_binding.md b/docs/resources/vlan_nsip_binding.md new file mode 100644 index 000000000..e6651a140 --- /dev/null +++ b/docs/resources/vlan_nsip_binding.md @@ -0,0 +1,56 @@ +--- +subcategory: "Network" +--- + +# Resource: vlan\_nsip\_binding + +The vlan\_nsip\_binding resource is used to bind vlan to ipv4 nsip address. + + +## Example usage + +```hcl +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 40 + aliasname = "Management VLAN" +} + +resource "citrixadc_nsip" "tf_snip" { + ipaddress = "10.222.74.146" + type = "SNIP" + netmask = "255.255.255.0" + icmp = "ENABLED" + state = "ENABLED" +} + +resource "citrixadc_vlan_nsip_binding" "tf_bind" { + vlanid = citrixadc_vlan.tf_vlan.vlanid + ipaddress = citrixadc_nsip.tf_snip.ipaddress + netmask = citrixadc_nsip.tf_snip.netmask +} +``` + + +## Argument Reference + +* `ipaddress` - (Required) The IP address assigned to the VLAN. +* `netmask` - (Optional) Subnet mask for the network address defined for this VLAN. +* `td` - (Optional) Integer value that uniquely identifies the traffic domain in which you want to configure the entity. If you do not specify an ID, the entity becomes part of the default traffic domain, which has an ID of 0. +* `ownergroup` - (Optional) The owner node group in a Cluster for this vlan. +* `vlanid` - (Required) Specifies the virtual LAN ID. + + +## Attribute Reference + +In addition to the arguments, the following attributes are available: + +* `id` - The id of the vlan\_nsip\_binding. It is the concatenation of the `vlanid` and `ipaddress` attributes separated by a comma. + + +## Import + +A vlan\_nsip\_binding can be imported using its id, e.g. + +```shell +terraform import citrixadc_vlan_nsip_binding.tf_bind 40,10.222.74.146 +``` diff --git a/examples/nsmode/provider.tf b/examples/nsmode/provider.tf new file mode 100644 index 000000000..dac61ae23 --- /dev/null +++ b/examples/nsmode/provider.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + citrixadc = { + source = "citrix/citrixadc" + } + } +} +provider "citrixadc" { + endpoint = "http://localhost:8080" +} diff --git a/examples/nsmode/resources.tf b/examples/nsmode/resources.tf new file mode 100644 index 000000000..246bc8e5b --- /dev/null +++ b/examples/nsmode/resources.tf @@ -0,0 +1,4 @@ +resource "citrixadc_nsmode" "tf_nsmode" { + l3 = true + usip = false +} diff --git a/examples/vlan_interface_binding/provider.tf b/examples/vlan_interface_binding/provider.tf new file mode 100644 index 000000000..dac61ae23 --- /dev/null +++ b/examples/vlan_interface_binding/provider.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + citrixadc = { + source = "citrix/citrixadc" + } + } +} +provider "citrixadc" { + endpoint = "http://localhost:8080" +} diff --git a/examples/vlan_interface_binding/resources.tf b/examples/vlan_interface_binding/resources.tf new file mode 100644 index 000000000..8435e1d59 --- /dev/null +++ b/examples/vlan_interface_binding/resources.tf @@ -0,0 +1,9 @@ +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 40 + aliasname = "Management VLAN" +} + +resource "citrixadc_vlan_interface_binding" "tf_bind" { + vlanid = citrixadc_vlan.tf_vlan.vlanid + ifnum = "1/1" +} diff --git a/examples/vlan_nsip_binding/provider.tf b/examples/vlan_nsip_binding/provider.tf new file mode 100644 index 000000000..dac61ae23 --- /dev/null +++ b/examples/vlan_nsip_binding/provider.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + citrixadc = { + source = "citrix/citrixadc" + } + } +} +provider "citrixadc" { + endpoint = "http://localhost:8080" +} diff --git a/examples/vlan_nsip_binding/resources.tf b/examples/vlan_nsip_binding/resources.tf new file mode 100644 index 000000000..921f0f86d --- /dev/null +++ b/examples/vlan_nsip_binding/resources.tf @@ -0,0 +1,18 @@ +resource "citrixadc_vlan" "tf_vlan" { + vlanid = 40 + aliasname = "Management VLAN" +} + +resource "citrixadc_nsip" "tf_snip" { + ipaddress = "10.222.74.146" + type = "SNIP" + netmask = "255.255.255.0" + icmp = "ENABLED" + state = "ENABLED" +} + +resource "citrixadc_vlan_nsip_binding" "tf_bind" { + vlanid = citrixadc_vlan.tf_vlan.vlanid + ipaddress = citrixadc_nsip.tf_snip.ipaddress + netmask = citrixadc_nsip.tf_snip.netmask +} diff --git a/go.mod b/go.mod index 911cb8064..09b86ecfc 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/citrix/terraform-provider-citrixadc go 1.13 require ( - github.com/citrix/adc-nitro-go v0.0.0-20210706081452-0ff4869771a4 + github.com/citrix/adc-nitro-go v0.0.0-20210709140558-a367b67b58f6 github.com/hashicorp/terraform v0.12.20 github.com/hashicorp/terraform-plugin-sdk v1.6.0 github.com/mitchellh/mapstructure v1.1.2 diff --git a/go.sum b/go.sum index 90ad93542..c1d34e51b 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/citrix/adc-nitro-go v0.0.0-20210706081452-0ff4869771a4 h1:fRZI2/P0fma04RFwT/dQuA+nitBuJG/GgBIzLtLum0s= github.com/citrix/adc-nitro-go v0.0.0-20210706081452-0ff4869771a4/go.mod h1:1SPLFfIOtWnKiNWEuLhRqGrEi6VxGkXt4gpWa+mhaCg= +github.com/citrix/adc-nitro-go v0.0.0-20210709140558-a367b67b58f6 h1:XHeiJRcBJ5dePgCtgeJDKjr7T2PVJB4JHrl/aAIq/pk= +github.com/citrix/adc-nitro-go v0.0.0-20210709140558-a367b67b58f6/go.mod h1:1SPLFfIOtWnKiNWEuLhRqGrEi6VxGkXt4gpWa+mhaCg= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= diff --git a/vendor/github.com/citrix/adc-nitro-go/service/netscaler_resource.go b/vendor/github.com/citrix/adc-nitro-go/service/netscaler_resource.go index 9cd3073d9..2768ed97f 100644 --- a/vendor/github.com/citrix/adc-nitro-go/service/netscaler_resource.go +++ b/vendor/github.com/citrix/adc-nitro-go/service/netscaler_resource.go @@ -30,7 +30,7 @@ import ( ) // Idempotent flag can't be added for these resources -var idempotentInvalidResources = []string{"login", "logout", "reboot", "shutdown", "ping", "ping6", "traceroute", "traceroute6", "install", "appfwjsoncontenttype", "appfwxmlcontenttype", "dnsnsrec", "transformaction"} +var idempotentInvalidResources = []string{"login", "logout", "reboot", "shutdown", "ping", "ping6", "traceroute", "traceroute6", "install", "appfwjsoncontenttype", "appfwxmlcontenttype", "dnsnsrec", "transformaction", "route"} // HTTP Headers to be masked and not shown in logs var headersToBeMasked = []string{"X-NITRO-USER", "X-NITRO-PASS", "Set-Cookie"} diff --git a/vendor/modules.txt b/vendor/modules.txt index 37c231b58..132d211bb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -60,7 +60,7 @@ github.com/bgentry/speakeasy github.com/blang/semver # github.com/bmatcuk/doublestar v1.1.5 github.com/bmatcuk/doublestar -# github.com/citrix/adc-nitro-go v0.0.0-20210706081452-0ff4869771a4 +# github.com/citrix/adc-nitro-go v0.0.0-20210709140558-a367b67b58f6 github.com/citrix/adc-nitro-go/resource/config/appfw github.com/citrix/adc-nitro-go/resource/config/audit github.com/citrix/adc-nitro-go/resource/config/basic