From 059de305bcc829fb9be16c49c9903049f074cb13 Mon Sep 17 00:00:00 2001 From: Vaerh Date: Sun, 1 Sep 2024 22:27:45 +0300 Subject: [PATCH] fix: Add a validator for map name keys. Closes #552 --- routeros/provider_schema_helpers.go | 33 ++++++++++++++++--- routeros/resource_capsman_configuration.go | 4 +++ routeros/resource_capsman_configuration_v0.go | 4 +++ routeros/resource_capsman_interface.go | 5 +++ routeros/resource_wifi.go | 7 ++++ routeros/resource_wifi_configuration.go | 6 ++++ 6 files changed, 55 insertions(+), 4 deletions(-) diff --git a/routeros/provider_schema_helpers.go b/routeros/provider_schema_helpers.go index 07c3772d..71b71299 100644 --- a/routeros/provider_schema_helpers.go +++ b/routeros/provider_schema_helpers.go @@ -298,10 +298,11 @@ var ( "and cannot be directly modified.", } PropFilterRw = &schema.Schema{ - Type: schema.TypeMap, - Optional: true, - Elem: schema.TypeString, - Description: "Additional request filtering options.", + Type: schema.TypeMap, + Optional: true, + Elem: schema.TypeString, + Description: "Additional request filtering options.", + ValidateDiagFunc: ValidationMapKeyNames, } PropInactiveRo = &schema.Schema{ Type: schema.TypeBool, @@ -618,6 +619,30 @@ var ( return } } + + reTerraformField = regexp.MustCompile("^[a-z0-9_]+$") + // ValidationMapKeyNames, A function to check map names for compliance with the TF standard. + // When copying keys from a real configuration it is easy to make a mistake and transfer a key + // containing dashes instead of underscores. This validator is added to prevent such errors. + ValidationMapKeyNames = func(v interface{}, path cty.Path) diag.Diagnostics { + var diags diag.Diagnostics + + for key := range v.(map[string]interface{}) { + if reTerraformField.MatchString(key) { + continue + } + + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Invalid attribute name", + Detail: fmt.Sprintf("%s: Attribute name may only contain lowercase alphanumeric characters & "+ + "underscores.", key), + AttributePath: append(path, cty.IndexStep{Key: cty.StringVal(key)}), + }) + } + + return diags + } ) // Properties DiffSuppressFunc. diff --git a/routeros/resource_capsman_configuration.go b/routeros/resource_capsman_configuration.go index c5c9052c..4283a6d8 100644 --- a/routeros/resource_capsman_configuration.go +++ b/routeros/resource_capsman_configuration.go @@ -49,6 +49,7 @@ func ResourceCapsManConfiguration() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyComment: PropCommentRw, @@ -65,6 +66,7 @@ func ResourceCapsManConfiguration() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "disconnect_timeout": { @@ -167,6 +169,7 @@ func ResourceCapsManConfiguration() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "rx_chains": { @@ -185,6 +188,7 @@ func ResourceCapsManConfiguration() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "ssid": { diff --git a/routeros/resource_capsman_configuration_v0.go b/routeros/resource_capsman_configuration_v0.go index 294a0663..606bd32c 100644 --- a/routeros/resource_capsman_configuration_v0.go +++ b/routeros/resource_capsman_configuration_v0.go @@ -20,6 +20,7 @@ func ResourceCapsManConfigurationV0() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, }, KeyComment: PropCommentRw, "country": { @@ -35,6 +36,7 @@ func ResourceCapsManConfigurationV0() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, }, "disconnect_timeout": { Type: schema.TypeString, @@ -136,6 +138,7 @@ func ResourceCapsManConfigurationV0() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, }, "rx_chains": { Type: schema.TypeList, @@ -153,6 +156,7 @@ func ResourceCapsManConfigurationV0() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + ValidateDiagFunc: ValidationMapKeyNames, }, "ssid": { Type: schema.TypeString, diff --git a/routeros/resource_capsman_interface.go b/routeros/resource_capsman_interface.go index dd5a4bd2..135445cd 100644 --- a/routeros/resource_capsman_interface.go +++ b/routeros/resource_capsman_interface.go @@ -50,6 +50,7 @@ func ResourceCapsManInterface() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Channel inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "configuration": { @@ -57,6 +58,7 @@ func ResourceCapsManInterface() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Configuration inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyComment: PropCommentRw, @@ -65,6 +67,7 @@ func ResourceCapsManInterface() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Datapath inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyDisabled: PropDisabledRw, @@ -109,6 +112,7 @@ func ResourceCapsManInterface() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Rates inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "running": { @@ -121,6 +125,7 @@ func ResourceCapsManInterface() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Security inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, } diff --git a/routeros/resource_wifi.go b/routeros/resource_wifi.go index f5e2493b..8a9e979b 100644 --- a/routeros/resource_wifi.go +++ b/routeros/resource_wifi.go @@ -42,6 +42,7 @@ func ResourceWifi() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "AAA inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyArp: PropArpRw, @@ -56,6 +57,7 @@ func ResourceWifi() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Channel inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "configuration": { @@ -63,6 +65,7 @@ func ResourceWifi() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Configuration inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "datapath": { @@ -70,6 +73,7 @@ func ResourceWifi() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Datapath inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyComment: PropCommentRw, @@ -91,6 +95,7 @@ func ResourceWifi() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Interworking inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyL2Mtu: PropL2MtuRw, @@ -133,6 +138,7 @@ func ResourceWifi() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Security inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "steering": { @@ -140,6 +146,7 @@ func ResourceWifi() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Steering inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, } diff --git a/routeros/resource_wifi_configuration.go b/routeros/resource_wifi_configuration.go index 674cfd41..a0be3e37 100644 --- a/routeros/resource_wifi_configuration.go +++ b/routeros/resource_wifi_configuration.go @@ -46,6 +46,7 @@ func ResourceWifiConfiguration() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "AAA inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "antenna_gain": { @@ -74,6 +75,7 @@ func ResourceWifiConfiguration() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Channel inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyComment: PropCommentRw, @@ -87,6 +89,7 @@ func ResourceWifiConfiguration() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Datapath inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, KeyDisabled: PropDisabledRw, @@ -108,6 +111,7 @@ func ResourceWifiConfiguration() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Interworking inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "manager": { @@ -140,6 +144,7 @@ func ResourceWifiConfiguration() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Security inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "ssid": { @@ -152,6 +157,7 @@ func ResourceWifiConfiguration() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: "Steering inline settings.", + ValidateDiagFunc: ValidationMapKeyNames, DiffSuppressFunc: AlwaysPresentNotUserProvided, }, "tx_chains": {