From 1abc3f5e2175ddc601ddf252d20898c6eb7c61ca Mon Sep 17 00:00:00 2001 From: Tommi2Day Date: Tue, 7 Sep 2021 20:41:44 +0200 Subject: [PATCH] allow using id or name for unifi_network data source Add sample and update docs along implements #174 --- docs/data-sources/network.md | 44 ++++++++++------- .../data-sources/unifi_network/data-source.tf | 12 +++++ internal/provider/data_network.go | 48 +++++++++++-------- internal/provider/data_network_test.go | 32 +++++++++++-- 4 files changed, 97 insertions(+), 39 deletions(-) create mode 100644 examples/data-sources/unifi_network/data-source.tf diff --git a/docs/data-sources/network.md b/docs/data-sources/network.md index d9374caf1..4cad71b90 100644 --- a/docs/data-sources/network.md +++ b/docs/data-sources/network.md @@ -3,47 +3,59 @@ page_title: "unifi_network Data Source - terraform-provider-unifi" subcategory: "" description: |- - unifi_network data source can be used to retrieve settings for a network by name. + unifi_network data source can be used to retrieve settings for a network by name or id. --- # unifi_network (Data Source) -`unifi_network` data source can be used to retrieve settings for a network by name. +`unifi_network` data source can be used to retrieve settings for a network by name or id. +## Example Usage +```terraform +#retrieve network data by unifi network name +data "unifi_network" "byName" { + name="LAN" +} + +#retrieve network data from user record +data "unifi_user" "byMac" { + mac = "01:23:45:67:89:ab" +} +data "unifi_network" "byID" { + id = data.unifi_user.byMac.network_id +} +``` ## Schema -### Required - -- **name** (String) The name of the network. - ### Optional +- **id** (String) The ID of the network. One of `id` OR `name` is required. +- **name** (String) The name of the network. One of `id` OR `name` is required. - **site** (String) The name of the site to associate the network with. ### Read-Only -- **dhcp_dns** (List of String) Specifies the IPv4 addresses for the DNS server to be returned from the DHCP server. Leave blank to disable this feature. -- **dhcp_enabled** (Boolean) Specifies whether DHCP is enabled or not on this network. -- **dhcp_lease** (Number) Specifies the lease time for DHCP addresses. +- **dhcp_dns** (List of String) IPv4 addresses for the DNS server to be returned from the DHCP server. +- **dhcp_enabled** (Boolean) whether DHCP is enabled or not on this network. +- **dhcp_lease** (Number) lease time for DHCP addresses. - **dhcp_start** (String) The IPv4 address where the DHCP range of addresses starts. - **dhcp_stop** (String) The IPv4 address where the DHCP range of addresses stops. -- **dhcpd_boot_enabled** (Boolean) Toggles on the DHCP boot options. Should be set to true when you want to have dhcpd_boot_filename, and dhcpd_boot_server to take effect. -- **dhcpd_boot_filename** (String) Specifies the file to PXE boot from on the dhcpd_boot_server. -- **dhcpd_boot_server** (String) Specifies the IPv4 address of a TFTP server to network boot from. +- **dhcpd_boot_enabled** (Boolean) Toggles on the DHCP boot options. will be set to true if you have dhcpd_boot_filename, and dhcpd_boot_server set. +- **dhcpd_boot_filename** (String) the file to PXE boot from on the dhcpd_boot_server. +- **dhcpd_boot_server** (String) IPv4 address of a TFTP server to network boot from. - **domain_name** (String) The domain name of this network. -- **id** (String) The ID of the network. - **igmp_snooping** (Boolean) Specifies whether IGMP snooping is enabled or not. - **ipv6_interface_type** (String) Specifies which type of IPv6 connection to use. -- **ipv6_pd_interface** (String) Specifies which WAN interface to use for IPv6 PD. +- **ipv6_pd_interface** (String) Specifies which WAN interface is used for IPv6 Prefix Delegation. - **ipv6_pd_prefixid** (String) Specifies the IPv6 Prefix ID. - **ipv6_ra_enable** (Boolean) Specifies whether to enable router advertisements or not. -- **ipv6_static_subnet** (String) Specifies the static IPv6 subnet when ipv6_interface_type is 'static'. +- **ipv6_static_subnet** (String) Specifies the static IPv6 subnet (when ipv6_interface_type is 'static'). - **network_group** (String) The group of the network. - **purpose** (String) The purpose of the network. One of `corporate`, `guest`, `wan`, or `vlan-only`. -- **subnet** (String) The subnet of the network. Must be a valid CIDR address. +- **subnet** (String) The subnet of the network (CIDR address). - **vlan_id** (Number) The VLAN ID of the network. - **wan_dns** (List of String) DNS servers IPs of the WAN. - **wan_egress_qos** (Number) Specifies the WAN egress quality of service. diff --git a/examples/data-sources/unifi_network/data-source.tf b/examples/data-sources/unifi_network/data-source.tf new file mode 100644 index 000000000..15e2c6380 --- /dev/null +++ b/examples/data-sources/unifi_network/data-source.tf @@ -0,0 +1,12 @@ +#retrieve network data by unifi network name +data "unifi_network" "lan_network" { + name = "LAN" +} + +#retrieve network data from user record +data "unifi_user" "my_device" { + mac = "01:23:45:67:89:ab" +} +data "unifi_network" "my_network" { + id = data.unifi_user.my_device.network_id +} diff --git a/internal/provider/data_network.go b/internal/provider/data_network.go index 656b48e8f..d3c49bce2 100644 --- a/internal/provider/data_network.go +++ b/internal/provider/data_network.go @@ -9,11 +9,18 @@ import ( func dataNetwork() *schema.Resource { return &schema.Resource{ - Description: "`unifi_network` data source can be used to retrieve settings for a network by name.", + Description: "`unifi_network` data source can be used to retrieve settings for a network by name or ID.", ReadContext: dataNetworkRead, Schema: map[string]*schema.Schema{ + "id": { + Description: "The ID of the network.", + Type: schema.TypeString, + Computed: true, + Optional: true, + ConflictsWith: []string{"name"}, + }, "site": { Description: "The name of the site to associate the network with.", Type: schema.TypeString, @@ -21,17 +28,14 @@ func dataNetwork() *schema.Resource { Optional: true, }, "name": { - Description: "The name of the network.", - Type: schema.TypeString, - Required: true, + Description: "The name of the network.", + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"id"}, }, // read-only / computed - "id": { - Description: "The ID of the network.", - Type: schema.TypeString, - Computed: true, - }, "purpose": { Description: "The purpose of the network. One of `corporate`, `guest`, `wan`, or `vlan-only`.", Type: schema.TypeString, @@ -43,7 +47,7 @@ func dataNetwork() *schema.Resource { Computed: true, }, "subnet": { - Description: "The subnet of the network. Must be a valid CIDR address.", + Description: "The subnet of the network (CIDR address).", Type: schema.TypeString, Computed: true, }, @@ -63,19 +67,19 @@ func dataNetwork() *schema.Resource { Computed: true, }, "dhcp_enabled": { - Description: "Specifies whether DHCP is enabled or not on this network.", + Description: "whether DHCP is enabled or not on this network.", Type: schema.TypeBool, Computed: true, }, "dhcp_lease": { - Description: "Specifies the lease time for DHCP addresses.", + Description: "lease time for DHCP addresses.", Type: schema.TypeInt, Computed: true, }, "dhcp_dns": { - Description: "Specifies the IPv4 addresses for the DNS server to be returned from the DHCP " + - "server. Leave blank to disable this feature.", + Description: "IPv4 addresses for the DNS server to be returned from the DHCP " + + "server.", Type: schema.TypeList, Computed: true, Elem: &schema.Schema{ @@ -84,17 +88,17 @@ func dataNetwork() *schema.Resource { }, "dhcpd_boot_enabled": { - Description: "Toggles on the DHCP boot options. Should be set to true when you want to have dhcpd_boot_filename, and dhcpd_boot_server to take effect.", + Description: "Toggles on the DHCP boot options. will be set to true if you have dhcpd_boot_filename, and dhcpd_boot_server set.", Type: schema.TypeBool, Computed: true, }, "dhcpd_boot_server": { - Description: "Specifies the IPv4 address of a TFTP server to network boot from.", + Description: "IPv4 address of a TFTP server to network boot from.", Type: schema.TypeString, Computed: true, }, "dhcpd_boot_filename": { - Description: "Specifies the file to PXE boot from on the dhcpd_boot_server.", + Description: "the file to PXE boot from on the dhcpd_boot_server.", Type: schema.TypeString, Computed: true, }, @@ -114,12 +118,12 @@ func dataNetwork() *schema.Resource { Computed: true, }, "ipv6_static_subnet": { - Description: "Specifies the static IPv6 subnet when ipv6_interface_type is 'static'.", + Description: "Specifies the static IPv6 subnet (when ipv6_interface_type is 'static').", Type: schema.TypeString, Computed: true, }, "ipv6_pd_interface": { - Description: "Specifies which WAN interface to use for IPv6 PD.", + Description: "Specifies which WAN interface is used for IPv6 Prefix Delegation.", Type: schema.TypeString, Computed: true, }, @@ -190,16 +194,20 @@ func dataNetworkRead(ctx context.Context, d *schema.ResourceData, meta interface name := d.Get("name").(string) site := d.Get("site").(string) + id := d.Get("id").(string) if site == "" { site = c.site } + if (name == "" && id == "") || (name != "" && id != "") { + return diag.Errorf("One of 'name' OR 'id' is required") + } networks, err := c.c.ListNetwork(ctx, site) if err != nil { return diag.FromErr(err) } for _, n := range networks { - if n.Name == name { + if (name != "" && n.Name == name) || (id != "" && n.ID == id) { dhcpDNS := []string{} for _, dns := range []string{ n.DHCPDDNS1, diff --git a/internal/provider/data_network_test.go b/internal/provider/data_network_test.go index 3e10080e4..9b02284d1 100644 --- a/internal/provider/data_network_test.go +++ b/internal/provider/data_network_test.go @@ -6,14 +6,14 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) -func TestAccDataNetwork_default(t *testing.T) { +func TestAccDataNetwork_byName(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { preCheck(t) }, ProviderFactories: providerFactories, // TODO: CheckDestroy: , Steps: []resource.TestStep{ { - Config: testAccDataNetworkConfig_default, + Config: testAccDataNetworkConfig_byName, Check: resource.ComposeTestCheckFunc( // testCheckNetworkExists(t, "name"), ), @@ -22,8 +22,34 @@ func TestAccDataNetwork_default(t *testing.T) { }) } -const testAccDataNetworkConfig_default = ` +func TestAccDataNetwork_byID(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { preCheck(t) }, + ProviderFactories: providerFactories, + // TODO: CheckDestroy: , + Steps: []resource.TestStep{ + { + Config: testAccDataNetworkConfig_byID, + Check: resource.ComposeTestCheckFunc( + // testCheckNetworkExists(t, "name"), + ), + }, + }, + }) +} + +const testAccDataNetworkConfig_byName = ` +data "unifi_network" "lan" { + name = "LAN" +} +` + +const testAccDataNetworkConfig_byID = ` data "unifi_network" "lan" { name = "LAN" } + +data "unifi_network" "lan_id" { + id = data.unifi_network.lan.id +} `