diff --git a/routeros/mikrotik_serialize.go b/routeros/mikrotik_serialize.go index b4b8b26b..3f6bfa14 100644 --- a/routeros/mikrotik_serialize.go +++ b/routeros/mikrotik_serialize.go @@ -194,6 +194,11 @@ func TerraformResourceDataToMikrotik(s map[string]*schema.Schema, d *schema.Reso switch terraformMetadata.Type { case schema.TypeString: + if _, ok := setUnsetFields[terraformSnakeName]; ok && value.(string) == "" { + // Unset + item["!"+mikrotikKebabName] = "" + continue + } item[mikrotikKebabName] = value.(string) case schema.TypeFloat: item[mikrotikKebabName] = strconv.FormatFloat(value.(float64), 'f', -1, 64) diff --git a/routeros/resource_ip_firewall_filter.go b/routeros/resource_ip_firewall_filter.go index 670cde6d..1a26ad0b 100644 --- a/routeros/resource_ip_firewall_filter.go +++ b/routeros/resource_ip_firewall_filter.go @@ -12,9 +12,10 @@ import ( // ResourceIPFirewallFilter https://wiki.mikrotik.com/wiki/Manual:IP/Firewall/Filter func ResourceIPFirewallFilter() *schema.Resource { resSchema := map[string]*schema.Schema{ - MetaResourcePath: PropResourcePath("/ip/firewall/filter"), - MetaId: PropId(Id), - MetaSkipFields: PropSkipFields(`"bytes","packets"`), + MetaResourcePath: PropResourcePath("/ip/firewall/filter"), + MetaId: PropId(Id), + MetaSkipFields: PropSkipFields(`"bytes","packets"`), + MetaSetUnsetFields: PropSetUnsetFields(`"dst_address_list","src_address_list","in_interface_list","out_interface_list","in_bridge_port_list","out_bridge_port_list"`), "action": { Type: schema.TypeString, diff --git a/routeros/resource_ip_firewall_mangle.go b/routeros/resource_ip_firewall_mangle.go index 1a7c99ea..89122c0f 100644 --- a/routeros/resource_ip_firewall_mangle.go +++ b/routeros/resource_ip_firewall_mangle.go @@ -27,9 +27,10 @@ import ( // ResourceIPFirewallMangle https://wiki.mikrotik.com/wiki/Manual:IP/Firewall/Mangle func ResourceIPFirewallMangle() *schema.Resource { resSchema := map[string]*schema.Schema{ - MetaResourcePath: PropResourcePath("/ip/firewall/mangle"), - MetaId: PropId(Id), - MetaSkipFields: PropSkipFields(`"bytes","packets"`), + MetaResourcePath: PropResourcePath("/ip/firewall/mangle"), + MetaId: PropId(Id), + MetaSkipFields: PropSkipFields(`"bytes","packets"`), + MetaSetUnsetFields: PropSetUnsetFields(`"dst_address_list","src_address_list","in_interface_list","out_interface_list","in_bridge_port_list","out_bridge_port_list"`), "action": { Type: schema.TypeString, diff --git a/routeros/resource_ip_firewall_nat.go b/routeros/resource_ip_firewall_nat.go index 1870e33e..1be60206 100644 --- a/routeros/resource_ip_firewall_nat.go +++ b/routeros/resource_ip_firewall_nat.go @@ -29,9 +29,10 @@ import ( // ResourceIPFirewallNat https://wiki.mikrotik.com/wiki/Manual:IP/Firewall/NAT func ResourceIPFirewallNat() *schema.Resource { resSchema := map[string]*schema.Schema{ - MetaResourcePath: PropResourcePath("/ip/firewall/nat"), - MetaId: PropId(Id), - MetaSkipFields: PropSkipFields(`"bytes","packets"`), + MetaResourcePath: PropResourcePath("/ip/firewall/nat"), + MetaId: PropId(Id), + MetaSkipFields: PropSkipFields(`"bytes","packets"`), + MetaSetUnsetFields: PropSetUnsetFields(`"dst_address_list","src_address_list","in_interface_list","out_interface_list","in_bridge_port_list","out_bridge_port_list"`), "action": { Type: schema.TypeString, diff --git a/routeros/resource_move.go b/routeros/resource_move.go index cdadede1..f52f36bf 100644 --- a/routeros/resource_move.go +++ b/routeros/resource_move.go @@ -31,14 +31,21 @@ func ResourceMoveItems() *schema.Resource { AtLeastOneOf: []string{"resource_name", "resource_path"}, }, "sequence": { - Type: schema.TypeList, - Required: true, - Description: "List identifiers in the required sequence.", + Type: schema.TypeList, + Required: true, + Description: "List identifiers in the required sequence. To locate the ```sequence``` before an " + + "existing rule, add its ```id``` to the last element of the ```sequence```.", Elem: &schema.Schema{ Type: schema.TypeString, MinItems: 2, }, }, + // "anchor_rule": { + // Type: schema.TypeString, + // Optional: true, + // Description: "The rule before which the ```sequence``` of rules will be placed. If this field is not specified, " + + // "the rules will be placed before the last element of the ```sequence```.", + // }, } resRead := func(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { path, ok := d.GetOk("resource_path") @@ -65,6 +72,9 @@ func ResourceMoveItems() *schema.Resource { conf[v.(string)] = struct{}{} } + // TODO It is necessary to sometime transfer the logic for monotonous reading of the sequence, so that it is possible + // to control the correctness of the position of the rules and possibly introduce an anchor rule. + // This check will not work in all cases!!! var list []string for _, r := range *res { if id, ok := r[".id"]; ok { @@ -84,10 +94,18 @@ func ResourceMoveItems() *schema.Resource { list = append(list, v.(string)) } - item := MikrotikItem{ + var item MikrotikItem + // if anchor, ok := d.GetOk("anchor_rule"); ok { + // item = MikrotikItem{ + // "numbers": strings.Join(list, ","), + // "destination": anchor.(string), + // } + // } else { + item = MikrotikItem{ "numbers": strings.Join(list[:len(list)-1], ","), "destination": list[len(list)-1], } + // } path, ok := d.GetOk("resource_path") if !ok {