Open kurtmc opened 2 years ago
Adding some more context. I am running this against version 6.4.54
And here is a terraform snippet that can reproduce the error:
resource "unifi_site" "customer" {
description = "to_delete"
}
resource "unifi_network" "management" {
site = unifi_site.customer.name
name = "management"
purpose = "vlan-only"
vlan_id = 101
}
Adding in a dummy value for wan_gateway
is the workaround I am currently using. My workaround in production looks like this:
resource "unifi_network" "management" {
site = unifi_site.customer.name
name = "management"
purpose = "vlan-only"
vlan_id = 101
wan_gateway = "0.0.0.0"
lifecycle {
ignore_changes = [
wan_gateway,
]
}
}
Can confirm getting same POST Message (400) on apply.....using provider = 0.34.0 and unifi os 1.11.0-16 (EA) for UDM Pro...can provide screenshots logs if needed...thanks
I added a test for this, but I suspect I need to upgrade the unifi version that it's run against: https://github.com/paultyng/terraform-provider-unifi/pull/197/checks?check_run_id=3887403832
Hmm, the tests should already be running against the latest versions
Good stuff....still super new to terraform, today was the first day I could actually even get any response, I am a software dev, but very green....Thank you guys for your work!!!
I think this is the same issue as #107, but I may not be able to investigate further for another few weeks. In the mean time, if anyone can produce a reproduction case (ideally an acceptance test in the repo), that should help a lot.
I'm running into the same issue at present, however the workaround mentioned above doesn't always work.
adding
lifecycle {
ignore_changes = [
wan_gateway,
]
}
still results in a 400 InvalidPayload error when a change to the network needs to be applied
removing this and having just a dummy "wan_gateway" results in a successful run when another change is needing to be applied (ie IP Range change), but without the lifecycle block it results in wanting to apply the wan_gateway on every run but results in a very misleading "Not Found" error. All API calls return 200 so not sure where that particular error is coming from.
Also on 6.4.54 (Cloud Key) TF snippet that I'm seeing the error with
resource "unifi_network" "Main" {
dhcp_dns = ["172.16.12.102"]
dhcp_enabled = true
dhcp_lease = "3600"
dhcp_start = "172.16.10.6"
dhcp_stop = "172.16.10.254"
name = "Main"
purpose = "corporate"
site = var.site
subnet = "172.16.10.1/24"
vlan_id = 10
wan_gateway = "0.0.0.0"
lifecycle {
ignore_changes = [
wan_gateway,
]
}
}
I have the same issue... Unifi: 6.4.54
Any changes to a network, be it a dhcp scope or a name or other parameter results in:
╷
│ Error: api.err.InvalidPayload (400 ) for PUT https://x.x.x.x:8443/api/s/default/rest/networkconf/6194484b5764540124b3c76e
│
│ with unifi_network.network["iot"],
│ on testing.tf line 49, in resource "unifi_network" "network":
│ 49: resource "unifi_network" "network" {
│
╵
network.tf:
output "network" {
value = local.network
}
locals {
network = defaults(var.network, {
site = "default"
dhcp_dns = ""
dhcp_enabled = true
dhcp_lease = 86400
dhcp_relay_enabled = false
dhcpd_boot_enabled = false
domain_name = "mydomain.com"
igmp_snooping = false
ipv6_interface_type = "none"
ipv6_ra_enable = false
network_group = "LAN"
wan_dns = ""
wan_egress_qos = 0
wan_gateway = "0.0.0.0"
purpose = "corporate"
})
}
resource "unifi_network" "network" {
for_each = { for i, v in local.network : i => v }
name = each.value.name
dhcp_enabled = each.value.dhcp_enabled
dhcp_lease = each.value.dhcp_lease
dhcp_relay_enabled = each.value.dhcp_relay_enabled
dhcp_start = each.value.dhcp_start
dhcp_stop = each.value.dhcp_stop
dhcpd_boot_enabled = each.value.dhcpd_boot_enabled
domain_name = each.value.domain_name
igmp_snooping = each.value.igmp_snooping
ipv6_interface_type = each.value.ipv6_interface_type
ipv6_ra_enable = each.value.ipv6_ra_enable
network_group = each.value.network_group
purpose = each.value.purpose
site = unifi_site.sirfragalot.name
subnet = each.value.subnet
vlan_id = each.value.vlan_id
wan_egress_qos = each.value.wan_egress_qos
wan_gateway = each.value.wan_gateway
wan_dns = each.value.wan_dns
dhcp_dns = each.value.dhcp_dns
lifecycle {
ignore_changes = [
wan_gateway,
]
}
}
network-variables.tf:
variable "network" {
type = map(object({
name = string
site = optional(string)
dhcp_dns = optional(list(string))
dhcp_enabled = optional(bool)
dhcp_lease = optional(number)
dhcp_relay_enabled = optional(bool)
dhcpd_boot_enabled = optional(bool)
domain_name = optional(string)
igmp_snooping = optional(bool)
ipv6_interface_type = optional(string)
ipv6_ra_enable = optional(bool)
network_group = optional(string)
wan_dns = optional(list(string))
wan_egress_qos = optional(number)
wan_gateway = optional(string)
purpose = optional(string)
dhcp_start = string
dhcp_stop = string
subnet = string
vlan_id = number
}))
}
network.auto.tfvars:
network = {
main = {
name = "LAN"
dhcp_start = "192.168.1.6"
dhcp_stop = "192.168.1.254"
subnet = "192.168.1.0/24"
vlan_id = 0
}
iot = {
name = "IoT"
dhcp_start = "10.32.12.10"
dhcp_stop = "10.32.12.100"
subnet = "10.32.12.0/24"
vlan_id = 107
dhcp_dns = ["192.168.1.53", "192.168.1.153"]
wan_dns = []
}
cctv = {
name = "CCTV"
dhcp_start = "10.32.13.10"
dhcp_stop = "10.32.13.100"
subnet = "10.32.13.0/24"
vlan_id = 999
dhcp_dns = []
wan_dns = []
}
}
Did some more investigation here, most of these are already omitempty
. I think explicit null
should probably be used instead of 0.0.0.0
or empty strings. I couldn't get it to fail with exactly the same issues in my testing though, but working on it here: #203
My guess though is this has to do with how certain fields are only roundtripped if the purpose
is WAN, but its having issues with the validation. My understanding was the validation should allow for empty, but I guess its explicitly looking for null
/ unset.
I'm encountering this specific issue as well, in the same way that @kurtmc reports.
Recently I have noticed that we are getting the following error quite a lot:
I turned on trace to see if unifi gives me a better error:
Should we make
wan_gateway
a string pointer so that it's not marshalled to an empty string when this request is made?