From 4db577f2118b78d6b9d95f21834729717d7cc7e4 Mon Sep 17 00:00:00 2001 From: Edward Haas Date: Wed, 3 Mar 2021 10:27:21 +0200 Subject: [PATCH] state, filter: Fix interpretation of scientific numeric iface names This change solves the problem of incorrectly representing valid scientific numeric valuesi without a dot in them (e.g. `10e20`) as strings (e.g. represented back as `1000`). The problem originates from the YAML-to-JSON conversion which does not obey to the defined member type. Fixed by using the go-yaml package (which does not perform such a conversion from YAML to JSON). The go-yaml is used just to unmarshal the name from the original raw byte stream and update the state structure with the proper name string. Signed-off-by: Edward Haas --- pkg/state/filter.go | 18 ++++++++++++++++++ pkg/state/filter_test.go | 3 +-- pkg/state/type.go | 17 ++++++++--------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/pkg/state/filter.go b/pkg/state/filter.go index 083a93dc8..2b5a0a218 100644 --- a/pkg/state/filter.go +++ b/pkg/state/filter.go @@ -7,6 +7,7 @@ import ( "github.com/nmstate/kubernetes-nmstate/api/shared" "github.com/nmstate/kubernetes-nmstate/pkg/environment" + goyaml "gopkg.in/yaml.v2" yaml "sigs.k8s.io/yaml" ) @@ -90,6 +91,10 @@ func filterOut(currentState shared.State, interfacesFilterGlob glob.Glob) (share return currentState, err } + if err := normalizeInterfacesNames(currentState.Raw, &state); err != nil { + return currentState, err + } + state.Interfaces = filterOutInterfaces(state.Interfaces, interfacesFilterGlob) if state.Routes != nil { state.Routes.Running = filterOutRoutes(state.Routes.Running, interfacesFilterGlob) @@ -102,3 +107,16 @@ func filterOut(currentState shared.State, interfacesFilterGlob glob.Glob) (share return shared.NewState(string(filteredState)), nil } + +// normalizeInterfacesNames fixes the unmarshal of numeric values in the interfaces names +// Numeric values, including the ones with a base prefix (e.g. 0x123) should be stringify. +func normalizeInterfacesNames(rawState []byte, state *rootState) error { + var stateForNormalization rootState + if err := goyaml.Unmarshal(rawState, &stateForNormalization); err != nil { + return err + } + for i, iface := range stateForNormalization.Interfaces { + state.Interfaces[i].Name = iface.Name + } + return nil +} diff --git a/pkg/state/filter_test.go b/pkg/state/filter_test.go index 7f59ae20b..8e771001a 100644 --- a/pkg/state/filter_test.go +++ b/pkg/state/filter_test.go @@ -372,8 +372,7 @@ interfaces: filteredState = nmstate.NewState(` interfaces: - name: eth0 -- name: "1000" -- name: "6000" +- name: "60e+02" `) interfacesFilterGlob = glob.MustCompile("10e*") }) diff --git a/pkg/state/type.go b/pkg/state/type.go index 09b84dde9..7d18053e4 100644 --- a/pkg/state/type.go +++ b/pkg/state/type.go @@ -3,28 +3,27 @@ package state import ( "encoding/json" "fmt" - "sigs.k8s.io/yaml" ) type rootState struct { - Interfaces []interfaceState `json:"interfaces"` - Routes *routesState `json:"routes,omitempty"` + Interfaces []interfaceState `json:"interfaces" yaml:"interfaces"` + Routes *routesState `json:"routes,omitempty" yaml:"routes,omitempty"` } type routesState struct { - Config []interface{} `json:"config"` - Running []interface{} `json:"running"` + Config []interface{} `json:"config" yaml:"config"` + Running []interface{} `json:"running" yaml:"running"` } type interfaceState struct { - interfaceFields - Data map[string]interface{} + interfaceFields `yaml:",inline"` + Data map[string]interface{} } // interfaceFields allows unmarshaling directly into the defined fields type interfaceFields struct { - Name string `json:"name"` + Name string `json:"name" yaml:"name"` } func (i interfaceState) MarshalJSON() (output []byte, err error) { @@ -42,6 +41,6 @@ func (i *interfaceState) UnmarshalJSON(b []byte) error { return fmt.Errorf("failed Unmarshaling raw: %w", err) } i.Data["name"] = ifaceFields.Name - i.Name = ifaceFields.Name + i.interfaceFields = ifaceFields return nil }