Repository: metal3-io/baremetal-operator
Pull request #1051 (2021-12-11 18:47:19)

Handle HostFirmwareSettings non-numeric string set for Integer type
For HostFirmwareSettings, handle the case where a non-numeric string is set for an integer type.


Patch:
diff --git a/apis/metal3.io/v1alpha1/firmwareschema_types.go b/apis/metal3.io/v1alpha1/firmwareschema_types.go
index 67620b88..e68b50b0 100644
--- a/apis/metal3.io/v1alpha1/firmwareschema_types.go
+++ b/apis/metal3.io/v1alpha1/firmwareschema_types.go
@@ -18,6 +18,7 @@ package v1alpha1
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -87,11 +88,16 @@ func (schema *SettingSchema) Validate(name string, value intstr.IntOrString) err
 		return SchemaSettingError{name: name, message: fmt.Sprintf("unknown enumeration value - %s", value.String())}
 
 	case "Integer":
+		if value.Type == intstr.String {
+			if _, err := strconv.Atoi(value.String()); err != nil {
+				return SchemaSettingError{name: name, message: fmt.Sprintf("String %s entered while integer expected", value.String())}
+			}
+		}
 		if schema.LowerBound != nil && value.IntValue() < *schema.LowerBound {
-			return SchemaSettingError{name: name, message: fmt.Sprintf("integer %s is below minimum value %d", value.String(), *schema.LowerBound)}
+			return SchemaSettingError{name: name, message: fmt.Sprintf("integer %d is below minimum value %d", value.IntValue(), *schema.LowerBound)}
 		}
 		if schema.UpperBound != nil && value.IntValue() > *schema.UpperBound {
-			return SchemaSettingError{name: name, message: fmt.Sprintf("integer %s is above maximum value %d", value.String(), *schema.UpperBound)}
+			return SchemaSettingError{name: name, message: fmt.Sprintf("integer %d is above maximum value %d", value.IntValue(), *schema.UpperBound)}
 		}
 		return nil
 


Test patch:
diff --git a/controllers/metal3.io/hostfirmwaresettings_test.go b/controllers/metal3.io/hostfirmwaresettings_test.go
index ec44ae0a..a296100f 100644
--- a/controllers/metal3.io/hostfirmwaresettings_test.go
+++ b/controllers/metal3.io/hostfirmwaresettings_test.go
@@ -435,7 +435,7 @@ func TestStoreHostFirmwareSettings(t *testing.T) {
 					ResourceVersion: "1"},
 				Spec: metal3v1alpha1.HostFirmwareSettingsSpec{
 					Settings: metal3v1alpha1.DesiredSettingsMap{
-						"NetworkBootRetryCount": intstr.FromString("1000"),
+						"NetworkBootRetryCount": intstr.FromInt(1000),
 						"ProcVirtualization":    intstr.FromString("Enabled"),
 					},
 				},
@@ -455,7 +455,7 @@ func TestStoreHostFirmwareSettings(t *testing.T) {
 			ExpectedSettings: &metal3v1alpha1.HostFirmwareSettings{
 				Spec: metal3v1alpha1.HostFirmwareSettingsSpec{
 					Settings: metal3v1alpha1.DesiredSettingsMap{
-						"NetworkBootRetryCount": intstr.FromString("1000"),
+						"NetworkBootRetryCount": intstr.FromInt(1000),
 						"ProcVirtualization":    intstr.FromString("Enabled"),
 					},
 				},
@@ -567,7 +567,7 @@ func TestValidateHostFirmwareSettings(t *testing.T) {
 				Settings: metal3v1alpha1.DesiredSettingsMap{
 					"CustomPostMessage":     intstr.FromString("All tests passed"),
 					"ProcVirtualization":    intstr.FromString("Disabled"),
-					"NetworkBootRetryCount": intstr.FromString("20"),
+					"NetworkBootRetryCount": intstr.FromInt(20),
 				},
 			},
 			ExpectedError: "",
@@ -578,7 +578,7 @@ func TestValidateHostFirmwareSettings(t *testing.T) {
 				Settings: metal3v1alpha1.DesiredSettingsMap{
 					"CustomPostMessage":     intstr.FromString("A really long POST message"),
 					"ProcVirtualization":    intstr.FromString("Disabled"),
-					"NetworkBootRetryCount": intstr.FromString("20"),
+					"NetworkBootRetryCount": intstr.FromInt(20),
 				},
 			},
 			ExpectedError: "Setting CustomPostMessage is invalid, string A really long POST message length is above maximum length 20",
@@ -626,6 +626,17 @@ func TestValidateHostFirmwareSettings(t *testing.T) {
 			},
 			ExpectedError: "Cannot set Password field",
 		},
+		{
+			Scenario: "string instead of int",
+			SpecSettings: metal3v1alpha1.HostFirmwareSettingsSpec{
+				Settings: metal3v1alpha1.DesiredSettingsMap{
+					"CustomPostMessage":     intstr.FromString("All tests passed"),
+					"ProcVirtualization":    intstr.FromString("Disabled"),
+					"NetworkBootRetryCount": intstr.FromString("foo"),
+				},
+			},
+			ExpectedError: "Setting NetworkBootRetryCount is invalid, String foo entered while integer expected",
+		},
 	}
 
 	for _, tc := range testCases {