From 681e29954dc82bb7f3df3aa17613394a507a88da Mon Sep 17 00:00:00 2001 From: Bruno Tavares Date: Sun, 17 Mar 2019 14:33:30 -0300 Subject: [PATCH] Expose IPv6 and IPv4 assigned addresses as computed properties Currently, the `ip_assignments` has a list of the IPs that ZeroTier provided to the member from its assignment pool. It contains a mix of IPv4 and IPv6 addresses. There is some scenarios where having the distiction of wheter it is an IPv4 or IPv6 changes which resource to create. For example using DNS records we are only allowed to create `AAAA` records in the presence of IPv6 addresses, and `A` records to IPv4. Filtering this information on Terraform is cumbersome, using the filter on list operations, while it is much easier to provide this information through the provider. This commit create two extra computed properties, `ipv6_assignments` and `ipv4_assignments`, which separates each address assignment as expected. The `ipv6_assignments` does not include RFC4139 nor 6PLANE addresses as they are always computed on the `member` resource level, even if the `network` is configured to not use those addresses, and their information is not returned by the controller API as an assigned address either. --- README.md | 6 ++++ zerotier/resource_zerotier_member.go | 42 ++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8087fba..179ebfd 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,12 @@ resource "zerotier_member" "hector" { # see ZeroTier Manual section on L2/ethernet bridging allow_ethernet_bridging = true + # Computed properties + + # ipv4_assignments: Computed list of IPv4 assigned by ZeroTier controller assignment pool + # ipv6_assignments: Computed list of IPv6 assigned by ZeroTier controller assignment pool. + # Note: Does not include RFC4193 nor 6PLANE addresses, only those from assignment pool or manually provided, similar to ip_assignments. + } ``` diff --git a/zerotier/resource_zerotier_member.go b/zerotier/resource_zerotier_member.go index 5cd2d42..f86f5a3 100644 --- a/zerotier/resource_zerotier_member.go +++ b/zerotier/resource_zerotier_member.go @@ -3,6 +3,7 @@ package main import ( "fmt" "strconv" + "strings" "github.com/hashicorp/terraform/helper/schema" ) @@ -61,8 +62,25 @@ func resourceZeroTierMember() *schema.Resource { Default: false, }, "ip_assignments": { - Type: schema.TypeList, - Optional: true, + Type: schema.TypeSet, + Description: "List of IP routed and assigned by ZeroTier controller assignment pool. Does not include RFC4193 nor 6PLANE addresses, only those from assignment pool or manually provided.", + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "ipv4_assignments": { + Type: schema.TypeSet, + Description: "Computed list of IPv4 assigned by ZeroTier controller assignment pool.", + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "ipv6_assignments": { + Type: schema.TypeSet, + Description: "Computed list of IPv6 assigned by ZeroTier controller assignment pool. Does not include RFC4193 nor 6PLANE addresses, only those from assignment pool or manually provided.", + Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -148,7 +166,7 @@ func memberFromResourceData(d *schema.ResourceData) (*Member, error) { for i := range capsRaw { caps[i] = capsRaw[i].(int) } - ipsRaw := d.Get("ip_assignments").([]interface{}) + ipsRaw := d.Get("ip_assignments").(*schema.Set).List() ips := make([]string, len(ipsRaw)) for i := range ipsRaw { ips[i] = ipsRaw[i].(string) @@ -172,6 +190,20 @@ func memberFromResourceData(d *schema.ResourceData) (*Member, error) { } return n, nil } + +// Split the list of assigned IPs into IPv6 and IPv4 lists +// Does not include 6PLANE or RFC4193, only those from the assignment pool +func assingnedIpsGrouping(ipAssignments []string) (ipv4s []string, ipv6s []string) { + for _, element := range ipAssignments { + if strings.Contains(element, ":") { + ipv6s = append(ipv6s, element) + } else { + ipv4s = append(ipv4s, element) + } + } + return +} + func resourceMemberRead(d *schema.ResourceData, m interface{}) error { client := m.(*ZeroTierClient) @@ -190,6 +222,8 @@ func resourceMemberRead(d *schema.ResourceData, m interface{}) error { return nil } + ipv4Assignments, ipv6Assignments := assingnedIpsGrouping(member.Config.IpAssignments) + d.SetId(member.Id) d.Set("name", member.Name) d.Set("description", member.Description) @@ -199,6 +233,8 @@ func resourceMemberRead(d *schema.ResourceData, m interface{}) error { d.Set("allow_ethernet_bridging", member.Config.ActiveBridge) d.Set("no_auto_assign_ips", member.Config.NoAutoAssignIps) d.Set("ip_assignments", member.Config.IpAssignments) + d.Set("ipv4_assignments", ipv4Assignments) + d.Set("ipv6_assignments", ipv6Assignments) d.Set("capabilities", member.Config.Capabilities) setTags(d, member)