Update schedule support for typed API field (#284)
* Test removing schedule * Use new schedule API field * fix attribute name * Bump go-unifi
This commit is contained in:
@@ -53,14 +53,14 @@ resource "unifi_network" "wan" {
|
||||
|
||||
- `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. Defaults to `86400`.
|
||||
- `dhcp_lease` (Number) Specifies the lease time for DHCP addresses in seconds. Defaults to `86400`.
|
||||
- `dhcp_relay_enabled` (Boolean) Specifies whether DHCP relay is enabled or not on this network.
|
||||
- `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.
|
||||
- `dhcp_v6_dns` (List of String) Specifies the IPv6 addresses for the DNS server to be returned from the DHCP server. Used if `dhcp_v6_dns_auto` is set to `false`.
|
||||
- `dhcp_v6_dns_auto` (Boolean) Specifies DNS source to propagate. If set `false` the entries in `dhcp_v6_dns` are used, the upstream entries otherwise Defaults to `true`.
|
||||
- `dhcp_v6_enabled` (Boolean) Enable stateful DHCPv6 for static configuration.
|
||||
- `dhcp_v6_lease` (Number) Specifies the lease time for DHCPv6 addresses. Defaults to `86400`.
|
||||
- `dhcp_v6_lease` (Number) Specifies the lease time for DHCPv6 addresses in seconds. Defaults to `86400`.
|
||||
- `dhcp_v6_start` (String) Start address of the DHCPv6 range. Used in static DHCPv6 configuration.
|
||||
- `dhcp_v6_stop` (String) End address of the DHCPv6 range. Used in static DHCPv6 configuration.
|
||||
- `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.
|
||||
@@ -78,7 +78,7 @@ resource "unifi_network" "wan" {
|
||||
- `ipv6_ra_enable` (Boolean) Specifies whether to enable router advertisements or not.
|
||||
- `ipv6_ra_preferred_lifetime` (Number) Lifetime in which the address can be used. Address becomes deprecated afterwards. Must be lower than or equal to `ipv6_ra_valid_lifetime` Defaults to `14400`.
|
||||
- `ipv6_ra_priority` (String) IPv6 router advertisement priority. Must be one of either `high`, `medium`, or `low`
|
||||
- `ipv6_ra_valid_lifetime` (Number) Total lifetime in which the adress can be used. Must be equal to or greater than `ipv6_ra_preferred_lifetime`. Defaults to `86400`.
|
||||
- `ipv6_ra_valid_lifetime` (Number) Total lifetime in which the address can be used. Must be equal to or greater than `ipv6_ra_preferred_lifetime`. Defaults to `86400`.
|
||||
- `ipv6_static_subnet` (String) Specifies the static IPv6 subnet when `ipv6_interface_type` is 'static'.
|
||||
- `network_group` (String) The group of the network. Defaults to `LAN`.
|
||||
- `site` (String) The name of the site to associate the network with.
|
||||
|
||||
@@ -92,9 +92,14 @@ resource "unifi_wlan" "wifi" {
|
||||
|
||||
Required:
|
||||
|
||||
- `block_end` (String) Time of day to end the block.
|
||||
- `block_start` (String) Time of day to start the block.
|
||||
- `day_of_week` (String) Day of week for the block. Valid values are `sun`, `mon`, `tue`, `wed`, `thu`, `fri`, `sat`.
|
||||
- `duration` (Number) Length of the block in minutes.
|
||||
- `start_hour` (Number) Start hour for the block (0-23).
|
||||
|
||||
Optional:
|
||||
|
||||
- `name` (String) Name of the block.
|
||||
- `start_minute` (Number) Start minute for the block (0-59). Defaults to `0`.
|
||||
|
||||
## Import
|
||||
|
||||
|
||||
4
go.mod
4
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/paultyng/terraform-provider-unifi
|
||||
|
||||
go 1.18
|
||||
go 1.19
|
||||
|
||||
// replace github.com/paultyng/go-unifi => ../go-unifi
|
||||
// replace github.com/hashicorp/terraform-plugin-docs => ../../hashicorp/terraform-plugin-docs
|
||||
@@ -10,7 +10,7 @@ require (
|
||||
github.com/hashicorp/go-version v1.6.0
|
||||
github.com/hashicorp/terraform-plugin-docs v0.13.0
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0
|
||||
github.com/paultyng/go-unifi v1.27.0
|
||||
github.com/paultyng/go-unifi v1.28.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
4
go.sum
4
go.sum
@@ -207,8 +207,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
|
||||
github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/paultyng/go-unifi v1.27.0 h1:rCh3LgSDLfsYnlH67VWTN+j0lPCqM0bgSG0wYevPAuI=
|
||||
github.com/paultyng/go-unifi v1.27.0/go.mod h1:X8D1nofAy/G171iLaId4TRkO/UApbkEMTR97o6ECgcg=
|
||||
github.com/paultyng/go-unifi v1.28.0 h1:MeDgwVjWowysDwDesKdhOYMwcGTk1JfANyeSRSh4e6I=
|
||||
github.com/paultyng/go-unifi v1.28.0/go.mod h1:X8D1nofAy/G171iLaId4TRkO/UApbkEMTR97o6ECgcg=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
||||
@@ -3,8 +3,6 @@ package provider
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
@@ -137,19 +135,29 @@ func resourceWLAN() *schema.Resource {
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{"sun", "mon", "tue", "wed", "thu", "fri", "sat", "sun"}, false),
|
||||
},
|
||||
"block_start": {
|
||||
Description: "Time of day to start the block.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringMatch(timeOfDayRegexp, "Time of day is invalid"),
|
||||
DiffSuppressFunc: timeOfDayDiffSuppress,
|
||||
"start_hour": {
|
||||
Description: "Start hour for the block (0-23).",
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ValidateFunc: validation.IntBetween(0, 23),
|
||||
},
|
||||
"block_end": {
|
||||
Description: "Time of day to end the block.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringMatch(timeOfDayRegexp, "Time of day is invalid"),
|
||||
DiffSuppressFunc: timeOfDayDiffSuppress,
|
||||
"start_minute": {
|
||||
Description: "Start minute for the block (0-59).",
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Default: 0,
|
||||
ValidateFunc: validation.IntBetween(0, 59),
|
||||
},
|
||||
"duration": {
|
||||
Description: "Length of the block in minutes.",
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ValidateFunc: validation.IntAtLeast(1),
|
||||
},
|
||||
"name": {
|
||||
Description: "Name of the block.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -263,7 +271,7 @@ func resourceWLANGetResourceData(d *schema.ResourceData, meta interface{}) (*uni
|
||||
}
|
||||
wlanBand := d.Get("wlan_band").(string)
|
||||
|
||||
schedule, err := listToScheduleStrings(d.Get("schedule").([]interface{}))
|
||||
schedule, err := listToSchedules(d.Get("schedule").([]interface{}))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to process schedule block: %w", err)
|
||||
}
|
||||
@@ -293,7 +301,7 @@ func resourceWLANGetResourceData(d *schema.ResourceData, meta interface{}) (*uni
|
||||
MACFilterList: macFilterList,
|
||||
MACFilterPolicy: d.Get("mac_filter_policy").(string),
|
||||
RADIUSProfileID: d.Get("radius_profile_id").(string),
|
||||
Schedule: schedule,
|
||||
ScheduleWithDuration: schedule,
|
||||
ScheduleEnabled: len(schedule) > 0,
|
||||
WLANBand: wlanBand,
|
||||
PMFMode: pmf,
|
||||
@@ -367,11 +375,7 @@ func resourceWLANSetResourceData(resp *unifi.WLAN, d *schema.ResourceData, meta
|
||||
|
||||
apGroupIDs := stringSliceToSet(resp.ApGroupIDs)
|
||||
|
||||
log.Printf("[TRACE] API Schedule: %#v", resp.Schedule)
|
||||
schedule, err := listFromScheduleStrings(resp.Schedule)
|
||||
if err != nil {
|
||||
return diag.Errorf("unable to parse schedule: %s", err)
|
||||
}
|
||||
schedule := listFromSchedules(resp.ScheduleWithDuration)
|
||||
|
||||
d.Set("site", site)
|
||||
d.Set("name", resp.Name)
|
||||
@@ -469,59 +473,54 @@ func resourceWLANDelete(ctx context.Context, d *schema.ResourceData, meta interf
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
func listToScheduleStrings(list []interface{}) ([]string, error) {
|
||||
schedStrings := make([]string, 0, len(list))
|
||||
func listToSchedules(list []interface{}) ([]unifi.WLANScheduleWithDuration, error) {
|
||||
schedules := make([]unifi.WLANScheduleWithDuration, 0, len(list))
|
||||
for _, item := range list {
|
||||
data, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected data in block")
|
||||
}
|
||||
ss, err := toScheduleString(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create schedule string: %w", err)
|
||||
}
|
||||
schedStrings = append(schedStrings, ss)
|
||||
ss := toSchedule(data)
|
||||
schedules = append(schedules, ss)
|
||||
}
|
||||
return schedStrings, nil
|
||||
return schedules, nil
|
||||
}
|
||||
|
||||
func toScheduleString(data map[string]interface{}) (string, error) {
|
||||
func toSchedule(data map[string]interface{}) unifi.WLANScheduleWithDuration {
|
||||
// TODO: error check these?
|
||||
dow := data["day_of_week"].(string)
|
||||
start := timeFromConfig(data["block_start"].(string))
|
||||
end := timeFromConfig(data["block_end"].(string))
|
||||
startHour := data["start_hour"].(int)
|
||||
startMinute := data["start_minute"].(int)
|
||||
duration := data["duration"].(int)
|
||||
name := data["name"].(string)
|
||||
|
||||
return fmt.Sprintf("%s|%s-%s", dow, start, end), nil
|
||||
return unifi.WLANScheduleWithDuration{
|
||||
StartDaysOfWeek: []string{dow},
|
||||
StartHour: startHour,
|
||||
StartMinute: startMinute,
|
||||
DurationMinutes: duration,
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func fromScheduleString(s string) (map[string]interface{}, error) {
|
||||
parts := strings.Split(s, "|")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("malformed schedule string %q", s)
|
||||
}
|
||||
dow, times := parts[0], parts[1]
|
||||
timeParts := strings.Split(times, "-")
|
||||
if len(timeParts) != 2 {
|
||||
return nil, fmt.Errorf("malformed schedule times %q", s)
|
||||
}
|
||||
|
||||
start, end := timeFromUnifi(timeParts[0]), timeFromUnifi(timeParts[1])
|
||||
|
||||
func fromSchedule(dow string, s unifi.WLANScheduleWithDuration) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"day_of_week": dow,
|
||||
"block_start": start,
|
||||
"block_end": end,
|
||||
}, nil
|
||||
"day_of_week": dow,
|
||||
"start_hour": s.StartHour,
|
||||
"start_minute": s.StartMinute,
|
||||
"duration": s.DurationMinutes,
|
||||
"name": s.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func listFromScheduleStrings(ss []string) ([]interface{}, error) {
|
||||
func listFromSchedules(ss []unifi.WLANScheduleWithDuration) []interface{} {
|
||||
// this explodes days of week lists in to individual schedules
|
||||
list := make([]interface{}, 0, len(ss))
|
||||
for _, s := range ss {
|
||||
v, err := fromScheduleString(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse schedule string %q: %w", s, err)
|
||||
for _, dow := range s.StartDaysOfWeek {
|
||||
v := fromSchedule(dow, s)
|
||||
list = append(list, v)
|
||||
}
|
||||
list = append(list, v)
|
||||
}
|
||||
return list, nil
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -179,6 +179,14 @@ func TestAccWLAN_schedule(t *testing.T) {
|
||||
),
|
||||
},
|
||||
importStep("unifi_wlan.test"),
|
||||
// remove schedule
|
||||
{
|
||||
Config: testAccWLANConfig_open(vlanID),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
),
|
||||
},
|
||||
importStep("unifi_wlan.test"),
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -502,14 +510,28 @@ resource "unifi_wlan" "test" {
|
||||
|
||||
schedule {
|
||||
day_of_week = "mon"
|
||||
block_start = "03:00"
|
||||
block_end = "9:00"
|
||||
start_hour = 3
|
||||
duration = 60*6
|
||||
}
|
||||
|
||||
schedule {
|
||||
day_of_week = "wed"
|
||||
block_start = "13:00"
|
||||
block_end = "17:00"
|
||||
start_hour = 13
|
||||
start_minute = 30
|
||||
duration = (60*3)+30
|
||||
name = "minute"
|
||||
}
|
||||
|
||||
schedule {
|
||||
day_of_week = "thu"
|
||||
start_hour = 19
|
||||
duration = 60*1
|
||||
}
|
||||
|
||||
schedule {
|
||||
day_of_week = "fri"
|
||||
start_hour = 19
|
||||
duration = 60*1
|
||||
}
|
||||
}
|
||||
`, vlanID)
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
var timeOfDayRegexp = regexp.MustCompile(`^\d{1,2}:\d{2}$`)
|
||||
|
||||
func timeOfDayDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
|
||||
return timeFromConfig(old) == timeFromConfig(new)
|
||||
}
|
||||
|
||||
func timeFromConfig(t string) string {
|
||||
if len(t) == 0 {
|
||||
return ""
|
||||
}
|
||||
s := "0" + strings.ReplaceAll(t, ":", "")
|
||||
return s[len(s)-4:]
|
||||
}
|
||||
|
||||
func timeFromUnifi(t string) string {
|
||||
i := len(t) - 2
|
||||
return strings.TrimPrefix(t[0:i], "0") + ":" + t[i:]
|
||||
}
|
||||
Reference in New Issue
Block a user