@@ -31,147 +31,163 @@ import (
3131)
3232
3333// NestedFieldCopy returns a deep copy of the value of a nested field.
34- // false is returned if the value is missing.
35- // nil, true is returned for a nil field.
36- func NestedFieldCopy (obj map [string ]interface {}, fields ... string ) (interface {}, bool ) {
37- val , ok := nestedFieldNoCopy (obj , fields ... )
38- if ! ok {
39- return nil , false
40- }
41- return runtime .DeepCopyJSONValue (val ), true
34+ // Returns false if the value is missing.
35+ // No error is returned for a nil field.
36+ func NestedFieldCopy (obj map [string ]interface {}, fields ... string ) (interface {}, bool , error ) {
37+ val , found , err := nestedFieldNoCopy (obj , fields ... )
38+ if ! found || err != nil {
39+ return nil , found , err
40+ }
41+ return runtime .DeepCopyJSONValue (val ), true , nil
4242}
4343
44- func nestedFieldNoCopy (obj map [string ]interface {}, fields ... string ) (interface {}, bool ) {
44+ func nestedFieldNoCopy (obj map [string ]interface {}, fields ... string ) (interface {}, bool , error ) {
4545 var val interface {} = obj
4646 for _ , field := range fields {
4747 if m , ok := val .(map [string ]interface {}); ok {
4848 val , ok = m [field ]
4949 if ! ok {
50- return nil , false
50+ return nil , false , nil
5151 }
5252 } else {
53- // Expected map[string]interface{}, got something else
54- return nil , false
53+ return nil , false , fmt .Errorf ("%v is of the type %T, expected map[string]interface{}" , val , val )
5554 }
5655 }
57- return val , true
56+ return val , true , nil
5857}
5958
6059// NestedString returns the string value of a nested field.
61- // Returns false if value is not found or is not a string.
62- func NestedString (obj map [string ]interface {}, fields ... string ) (string , bool ) {
63- val , ok := nestedFieldNoCopy (obj , fields ... )
64- if ! ok {
65- return "" , false
60+ // Returns false if value is not found and an error if not a string.
61+ func NestedString (obj map [string ]interface {}, fields ... string ) (string , bool , error ) {
62+ val , found , err := nestedFieldNoCopy (obj , fields ... )
63+ if ! found || err != nil {
64+ return "" , found , err
6665 }
6766 s , ok := val .(string )
68- return s , ok
67+ if ! ok {
68+ return "" , false , fmt .Errorf ("%v is of the type %T, expected string" , val , val )
69+ }
70+ return s , true , nil
6971}
7072
7173// NestedBool returns the bool value of a nested field.
72- // Returns false if value is not found or is not a bool.
73- func NestedBool (obj map [string ]interface {}, fields ... string ) (bool , bool ) {
74- val , ok := nestedFieldNoCopy (obj , fields ... )
75- if ! ok {
76- return false , false
74+ // Returns false if value is not found and an error if not a bool.
75+ func NestedBool (obj map [string ]interface {}, fields ... string ) (bool , bool , error ) {
76+ val , found , err := nestedFieldNoCopy (obj , fields ... )
77+ if ! found || err != nil {
78+ return false , found , err
7779 }
7880 b , ok := val .(bool )
79- return b , ok
81+ if ! ok {
82+ return false , false , fmt .Errorf ("%v is of the type %T, expected bool" , val , val )
83+ }
84+ return b , true , nil
8085}
8186
82- // NestedFloat64 returns the bool value of a nested field.
83- // Returns false if value is not found or is not a float64.
84- func NestedFloat64 (obj map [string ]interface {}, fields ... string ) (float64 , bool ) {
85- val , ok := nestedFieldNoCopy (obj , fields ... )
86- if ! ok {
87- return 0 , false
87+ // NestedFloat64 returns the float64 value of a nested field.
88+ // Returns false if value is not found and an error if not a float64.
89+ func NestedFloat64 (obj map [string ]interface {}, fields ... string ) (float64 , bool , error ) {
90+ val , found , err := nestedFieldNoCopy (obj , fields ... )
91+ if ! found || err != nil {
92+ return 0 , found , err
8893 }
8994 f , ok := val .(float64 )
90- return f , ok
95+ if ! ok {
96+ return 0 , false , fmt .Errorf ("%v is of the type %T, expected float64" , val , val )
97+ }
98+ return f , true , nil
9199}
92100
93101// NestedInt64 returns the int64 value of a nested field.
94- // Returns false if value is not found or is not an int64.
95- func NestedInt64 (obj map [string ]interface {}, fields ... string ) (int64 , bool ) {
96- val , ok := nestedFieldNoCopy (obj , fields ... )
97- if ! ok {
98- return 0 , false
102+ // Returns false if value is not found and an error if not an int64.
103+ func NestedInt64 (obj map [string ]interface {}, fields ... string ) (int64 , bool , error ) {
104+ val , found , err := nestedFieldNoCopy (obj , fields ... )
105+ if ! found || err != nil {
106+ return 0 , found , err
99107 }
100108 i , ok := val .(int64 )
101- return i , ok
109+ if ! ok {
110+ return 0 , false , fmt .Errorf ("%v is of the type %T, expected int64" , val , val )
111+ }
112+ return i , true , nil
102113}
103114
104115// NestedStringSlice returns a copy of []string value of a nested field.
105- // Returns false if value is not found, is not a []interface{} or contains non-string items in the slice.
106- func NestedStringSlice (obj map [string ]interface {}, fields ... string ) ([]string , bool ) {
107- val , ok := nestedFieldNoCopy (obj , fields ... )
116+ // Returns false if value is not found and an error if not a []interface{} or contains non-string items in the slice.
117+ func NestedStringSlice (obj map [string ]interface {}, fields ... string ) ([]string , bool , error ) {
118+ val , found , err := nestedFieldNoCopy (obj , fields ... )
119+ if ! found || err != nil {
120+ return nil , found , err
121+ }
122+ m , ok := val .([]interface {})
108123 if ! ok {
109- return nil , false
124+ return nil , false , fmt . Errorf ( "%v is of the type %T, expected []interface{}" , val , val )
110125 }
111- if m , ok := val .([]interface {}); ok {
112- strSlice := make ([]string , 0 , len (m ))
113- for _ , v := range m {
114- if str , ok := v .(string ); ok {
115- strSlice = append (strSlice , str )
116- } else {
117- return nil , false
118- }
126+ strSlice := make ([]string , 0 , len (m ))
127+ for _ , v := range m {
128+ if str , ok := v .(string ); ok {
129+ strSlice = append (strSlice , str )
130+ } else {
131+ return nil , false , fmt .Errorf ("contains non-string key in the slice: %v is of the type %T, expected string" , v , v )
119132 }
120- return strSlice , true
121133 }
122- return nil , false
134+ return strSlice , true , nil
123135}
124136
125137// NestedSlice returns a deep copy of []interface{} value of a nested field.
126- // Returns false if value is not found or is not a []interface{}.
127- func NestedSlice (obj map [string ]interface {}, fields ... string ) ([]interface {}, bool ) {
128- val , ok := nestedFieldNoCopy (obj , fields ... )
129- if ! ok {
130- return nil , false
138+ // Returns false if value is not found and an error if not a []interface{}.
139+ func NestedSlice (obj map [string ]interface {}, fields ... string ) ([]interface {}, bool , error ) {
140+ val , found , err := nestedFieldNoCopy (obj , fields ... )
141+ if ! found || err != nil {
142+ return nil , found , err
131143 }
132- if _ , ok := val .([]interface {}); ok {
133- return runtime .DeepCopyJSONValue (val ).([]interface {}), true
144+ _ , ok := val .([]interface {})
145+ if ! ok {
146+ return nil , false , fmt .Errorf ("%v is of the type %T, expected []interface{}" , val , val )
134147 }
135- return nil , false
148+ return runtime . DeepCopyJSONValue ( val ).([] interface {}), true , nil
136149}
137150
138151// NestedStringMap returns a copy of map[string]string value of a nested field.
139- // Returns false if value is not found, is not a map[string]interface{} or contains non-string values in the map.
140- func NestedStringMap (obj map [string ]interface {}, fields ... string ) (map [string ]string , bool ) {
141- m , ok := nestedMapNoCopy (obj , fields ... )
142- if ! ok {
143- return nil , false
152+ // Returns false if value is not found and an error if not a map[string]interface{} or contains non-string values in the map.
153+ func NestedStringMap (obj map [string ]interface {}, fields ... string ) (map [string ]string , bool , error ) {
154+ m , found , err := nestedMapNoCopy (obj , fields ... )
155+ if ! found || err != nil {
156+ return nil , found , err
144157 }
145158 strMap := make (map [string ]string , len (m ))
146159 for k , v := range m {
147160 if str , ok := v .(string ); ok {
148161 strMap [k ] = str
149162 } else {
150- return nil , false
163+ return nil , false , fmt . Errorf ( "contains non-string key in the map: %v is of the type %T, expected string" , v , v )
151164 }
152165 }
153- return strMap , true
166+ return strMap , true , nil
154167}
155168
156169// NestedMap returns a deep copy of map[string]interface{} value of a nested field.
157- // Returns false if value is not found or is not a map[string]interface{}.
158- func NestedMap (obj map [string ]interface {}, fields ... string ) (map [string ]interface {}, bool ) {
159- m , ok := nestedMapNoCopy (obj , fields ... )
160- if ! ok {
161- return nil , false
170+ // Returns false if value is not found and an error if not a map[string]interface{}.
171+ func NestedMap (obj map [string ]interface {}, fields ... string ) (map [string ]interface {}, bool , error ) {
172+ m , found , err := nestedMapNoCopy (obj , fields ... )
173+ if ! found || err != nil {
174+ return nil , found , err
162175 }
163- return runtime .DeepCopyJSON (m ), true
176+ return runtime .DeepCopyJSON (m ), true , nil
164177}
165178
166179// nestedMapNoCopy returns a map[string]interface{} value of a nested field.
167- // Returns false if value is not found or is not a map[string]interface{}.
168- func nestedMapNoCopy (obj map [string ]interface {}, fields ... string ) (map [string ]interface {}, bool ) {
169- val , ok := nestedFieldNoCopy (obj , fields ... )
170- if ! ok {
171- return nil , false
180+ // Returns false if value is not found and an error if not a map[string]interface{}.
181+ func nestedMapNoCopy (obj map [string ]interface {}, fields ... string ) (map [string ]interface {}, bool , error ) {
182+ val , found , err := nestedFieldNoCopy (obj , fields ... )
183+ if ! found || err != nil {
184+ return nil , found , err
172185 }
173186 m , ok := val .(map [string ]interface {})
174- return m , ok
187+ if ! ok {
188+ return nil , false , fmt .Errorf ("%v is of the type %T, expected map[string]interface{}" , val , val )
189+ }
190+ return m , true , nil
175191}
176192
177193// SetNestedField sets the value of a nested field to a deep copy of the value provided.
@@ -245,8 +261,8 @@ func RemoveNestedField(obj map[string]interface{}, fields ...string) {
245261}
246262
247263func getNestedString (obj map [string ]interface {}, fields ... string ) string {
248- val , ok := NestedString (obj , fields ... )
249- if ! ok {
264+ val , found , err := NestedString (obj , fields ... )
265+ if ! found || err != nil {
250266 return ""
251267 }
252268 return val
@@ -256,11 +272,11 @@ func extractOwnerReference(v map[string]interface{}) metav1.OwnerReference {
256272 // though this field is a *bool, but when decoded from JSON, it's
257273 // unmarshalled as bool.
258274 var controllerPtr * bool
259- if controller , ok := NestedBool (v , "controller" ); ok {
275+ if controller , found , err := NestedBool (v , "controller" ); err == nil && found {
260276 controllerPtr = & controller
261277 }
262278 var blockOwnerDeletionPtr * bool
263- if blockOwnerDeletion , ok := NestedBool (v , "blockOwnerDeletion" ); ok {
279+ if blockOwnerDeletion , found , err := NestedBool (v , "blockOwnerDeletion" ); err == nil && found {
264280 blockOwnerDeletionPtr = & blockOwnerDeletion
265281 }
266282 return metav1.OwnerReference {
0 commit comments