diff --git a/pkg/state/filter.go b/pkg/state/filter.go index b98133068a..083a93dc84 100644 --- a/pkg/state/filter.go +++ b/pkg/state/filter.go @@ -73,12 +73,11 @@ func filterOutDynamicAttributes(iface map[string]interface{}) { delete(options, "hello-timer") } -func filterOutInterfaces(ifaces []interface{}, interfacesFilterGlob glob.Glob) []interface{} { - filteredInterfaces := []interface{}{} - for _, iface := range ifaces { - name := iface.(map[string]interface{})["name"] - if !interfacesFilterGlob.Match(name.(string)) { - filterOutDynamicAttributes(iface.(map[string]interface{})) +func filterOutInterfaces(ifacesState []interfaceState, interfacesFilterGlob glob.Glob) []interfaceState { + filteredInterfaces := []interfaceState{} + for _, iface := range ifacesState { + if !interfacesFilterGlob.Match(iface.Name) { + filterOutDynamicAttributes(iface.Data) filteredInterfaces = append(filteredInterfaces, iface) } } @@ -87,8 +86,7 @@ func filterOutInterfaces(ifaces []interface{}, interfacesFilterGlob glob.Glob) [ func filterOut(currentState shared.State, interfacesFilterGlob glob.Glob) (shared.State, error) { var state rootState - err := yaml.Unmarshal(currentState.Raw, &state) - if err != nil { + if err := yaml.Unmarshal(currentState.Raw, &state); err != nil { return currentState, err } diff --git a/pkg/state/filter_test.go b/pkg/state/filter_test.go index c87149ffef..0f5913b3bd 100644 --- a/pkg/state/filter_test.go +++ b/pkg/state/filter_test.go @@ -331,4 +331,51 @@ interfaces: }) }) + Context("when the interfaces have (only) numeric characters", func() { + BeforeEach(func() { + state = nmstate.NewState(` +interfaces: +- name: eth0 +- name: 0 +- name: 1101010 +`) + filteredState = nmstate.NewState(` +interfaces: +- name: eth0 +- name: "1101010" +`) + interfacesFilterGlob = glob.MustCompile("0*") + }) + + It("should filter out interfaces correctly", func() { + returnedState, err := filterOut(state, interfacesFilterGlob) + Expect(err).NotTo(HaveOccurred()) + Expect(returnedState).To(MatchYAML(filteredState)) + }) + }) + + Context("when the interfaces have special numeric characters", func() { + BeforeEach(func() { + state = nmstate.NewState(` +interfaces: +- name: eth0 +- name: 0.0 +- name: 1.0 +- name: 0xfe +`) + filteredState = nmstate.NewState(` +interfaces: +- name: eth0 +- name: "0" +- name: "254" +`) + interfacesFilterGlob = glob.MustCompile("1*") + }) + + It("should filter out interfaces correctly but they are not represented correctly", func() { + returnedState, err := filterOut(state, interfacesFilterGlob) + Expect(err).NotTo(HaveOccurred()) + Expect(returnedState).To(MatchYAML(filteredState)) + }) + }) }) diff --git a/pkg/state/type.go b/pkg/state/type.go index 12d1709d3b..09b84dde93 100644 --- a/pkg/state/type.go +++ b/pkg/state/type.go @@ -1,11 +1,47 @@ package state +import ( + "encoding/json" + "fmt" + + "sigs.k8s.io/yaml" +) + type rootState struct { - Interfaces []interface{} `json:"interfaces"` - Routes *routesState `json:"routes,omitempty"` + Interfaces []interfaceState `json:"interfaces"` + Routes *routesState `json:"routes,omitempty"` } type routesState struct { Config []interface{} `json:"config"` Running []interface{} `json:"running"` } + +type interfaceState struct { + interfaceFields + Data map[string]interface{} +} + +// interfaceFields allows unmarshaling directly into the defined fields +type interfaceFields struct { + Name string `json:"name"` +} + +func (i interfaceState) MarshalJSON() (output []byte, err error) { + i.Data["name"] = i.Name + return json.Marshal(i.Data) +} + +func (i *interfaceState) UnmarshalJSON(b []byte) error { + if err := yaml.Unmarshal(b, &i.Data); err != nil { + return fmt.Errorf("failed Unmarshaling b: %w", err) + } + + var ifaceFields interfaceFields + if err := yaml.Unmarshal(b, &ifaceFields); err != nil { + return fmt.Errorf("failed Unmarshaling raw: %w", err) + } + i.Data["name"] = ifaceFields.Name + i.Name = ifaceFields.Name + return nil +}