-
Notifications
You must be signed in to change notification settings - Fork 38
feat: modifying error message for subobject #607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 4 commits
bc1d6e5
b580325
4023a78
bc4097c
ca0d775
80aa94f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,7 +53,7 @@ func ParseKubeObject(in []byte) (*KubeObject, error) { | |
func (o *SubObject) GetOrDie(ptr interface{}, fields ...string) { | ||
_, err := o.Get(ptr, fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -69,7 +69,7 @@ func (o *SubObject) NestedBool(fields ...string) (bool, bool, error) { | |
func (o *SubObject) NestedBoolOrDie(fields ...string) bool { | ||
val, _, err := o.NestedBool(fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
return val | ||
} | ||
|
@@ -86,7 +86,7 @@ func (o *SubObject) NestedString(fields ...string) (string, bool, error) { | |
func (o *SubObject) NestedStringOrDie(fields ...string) string { | ||
val, _, err := o.NestedString(fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
return val | ||
} | ||
|
@@ -103,7 +103,7 @@ func (o *SubObject) NestedFloat64(fields ...string) (float64, bool, error) { | |
func (o *SubObject) NestedFloat64OrDie(fields ...string) float64 { | ||
val, _, err := o.NestedFloat64(fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
return val | ||
} | ||
|
@@ -120,7 +120,7 @@ func (o *SubObject) NestedInt64(fields ...string) (int64, bool, error) { | |
func (o *SubObject) NestedInt64OrDie(fields ...string) int64 { | ||
val, _, err := o.NestedInt64(fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
return val | ||
} | ||
|
@@ -141,7 +141,7 @@ func (o *SubObject) NestedSlice(fields ...string) (SliceSubObjects, bool, error) | |
} | ||
sliceVal, found, err := mapVariant.GetNestedSlice(fields[len(fields)-1]) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
if !found { | ||
return nil, found, nil | ||
|
@@ -152,7 +152,15 @@ func (o *SubObject) NestedSlice(fields ...string) (SliceSubObjects, bool, error) | |
} | ||
var val []*SubObject | ||
for _, obj := range objects { | ||
val = append(val, &SubObject{obj: obj}) | ||
if o.nodePath == nil { | ||
oGroup, oVersion := ParseGroupVersion(o.GetString("apiVersion")) | ||
val = append(val, &SubObject{obj: obj, gvk: &ResourceIdentifier{ | ||
Group: oGroup, | ||
Version: oVersion, | ||
Kind: o.GetString("kind"), | ||
}, nodePath: append(o.nodePath, fields...)}) | ||
} | ||
val = append(val, &SubObject{obj: obj, gvk: o.gvk, nodePath: append(o.nodePath, fields...)}) | ||
} | ||
return val, true, nil | ||
} | ||
|
@@ -164,7 +172,7 @@ func (o *SubObject) NestedSlice(fields ...string) (SliceSubObjects, bool, error) | |
func (o *SubObject) NestedSliceOrDie(fields ...string) SliceSubObjects { | ||
val, _, err := o.NestedSlice(fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
return val | ||
} | ||
|
@@ -184,7 +192,7 @@ func (o *SubObject) NestedStringMap(fields ...string) (map[string]string, bool, | |
func (o *SubObject) NestedStringMapOrDie(fields ...string) map[string]string { | ||
val, _, err := o.NestedStringMap(fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
return val | ||
} | ||
|
@@ -204,7 +212,7 @@ func (o *SubObject) NestedStringSlice(fields ...string) ([]string, bool, error) | |
func (o *SubObject) NestedStringSliceOrDie(fields ...string) []string { | ||
val, _, err := o.NestedStringSlice(fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
return val | ||
} | ||
|
@@ -213,7 +221,7 @@ func (o *SubObject) NestedStringSliceOrDie(fields ...string) []string { | |
// encounters any error. | ||
func (o *SubObject) RemoveNestedFieldOrDie(fields ...string) { | ||
if _, err := o.RemoveNestedField(fields...); err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -318,7 +326,7 @@ func (o *SubObject) Get(ptr interface{}, fields ...string) (bool, error) { | |
// It will panic if it encounters any error. | ||
func (o *SubObject) SetOrDie(val interface{}, fields ...string) { | ||
if err := o.SetNestedField(val, fields...); err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -419,7 +427,7 @@ func (o *SubObject) SetNestedField(val interface{}, fields ...string) error { | |
func (o *SubObject) SetNestedIntOrDie(value int, fields ...string) { | ||
err := o.SetNestedInt(value, fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -432,7 +440,7 @@ func (o *SubObject) SetNestedInt(value int, fields ...string) error { | |
func (o *SubObject) SetNestedBoolOrDie(value bool, fields ...string) { | ||
err := o.SetNestedBool(value, fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -445,7 +453,7 @@ func (o *SubObject) SetNestedBool(value bool, fields ...string) error { | |
func (o *SubObject) SetNestedStringOrDie(value string, fields ...string) { | ||
err := o.SetNestedString(value, fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -458,7 +466,7 @@ func (o *SubObject) SetNestedString(value string, fields ...string) error { | |
func (o *SubObject) SetNestedStringMapOrDie(value map[string]string, fields ...string) { | ||
err := o.SetNestedStringMap(value, fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -471,7 +479,7 @@ func (o *SubObject) SetNestedStringMap(value map[string]string, fields ...string | |
func (o *SubObject) SetNestedStringSliceOrDie(value []string, fields ...string) { | ||
err := o.SetNestedStringSlice(value, fields...) | ||
if err != nil { | ||
panic(errSubObjectFields{fields: fields}) | ||
panic(errSubObjectFields{obj: o, fields: fields}) | ||
} | ||
} | ||
|
||
|
@@ -532,7 +540,7 @@ func (o *KubeObject) SetHeadComment(comment string, fields ...string) error { | |
// be a pointer to a typed object. It will panic if it encounters an error. | ||
func (o *SubObject) AsOrDie(ptr interface{}) { | ||
if err := o.As(ptr); err != nil { | ||
panic(errSubObjectFields{fields: nil}) | ||
panic(errSubObjectFields{obj: o, fields: nil}) | ||
} | ||
} | ||
|
||
|
@@ -889,11 +897,22 @@ func (o *KubeObject) IsEmpty() bool { | |
} | ||
|
||
func NewEmptyKubeObject() *KubeObject { | ||
return &KubeObject{SubObject{internal.NewMap(nil)}} | ||
return &KubeObject{SubObject: SubObject{obj: internal.NewMap(nil)}} | ||
} | ||
|
||
func asKubeObject(obj *internal.MapVariant) *KubeObject { | ||
return &KubeObject{SubObject{obj}} | ||
kind, _, _ := obj.GetNestedString("kind") | ||
apiVersion, _, _ := obj.GetNestedString("apiVersion") | ||
group, version := ParseGroupVersion(apiVersion) | ||
if kind != "" || group != "" || version != "" { | ||
return &KubeObject{SubObject: SubObject{obj: obj, gvk: &ResourceIdentifier{ | ||
Group: group, | ||
Version: version, | ||
Kind: kind, | ||
}}} | ||
} | ||
// will not go to this line as KubeObject contains GVK for sure | ||
return &KubeObject{SubObject: SubObject{obj: obj}} | ||
} | ||
|
||
func (o *KubeObject) node() *internal.MapVariant { | ||
|
@@ -902,17 +921,20 @@ func (o *KubeObject) node() *internal.MapVariant { | |
|
||
func rnodeToKubeObject(rn *yaml.RNode) *KubeObject { | ||
mapVariant := internal.NewMap(rn.YNode()) | ||
return &KubeObject{SubObject{mapVariant}} | ||
return asKubeObject(mapVariant) | ||
//return &KubeObject{SubObject: SubObject{obj: mapVariant}} | ||
} | ||
|
||
// SubObject represents a map within a KubeObject | ||
type SubObject struct { | ||
obj *internal.MapVariant | ||
obj *internal.MapVariant | ||
gvk *ResourceIdentifier // the identifier | ||
nodePath []string // the relative path to the kubeObject | ||
} | ||
|
||
func (o *SubObject) UpsertMap(k string) *SubObject { | ||
m := o.obj.UpsertMap(k) | ||
return &SubObject{obj: m} | ||
return &SubObject{gvk: o.gvk, nodePath: o.nodePath, obj: m} | ||
} | ||
|
||
// GetMap accepts a single key `k` whose value is expected to be a map. It returns | ||
|
@@ -924,7 +946,21 @@ func (o *SubObject) GetMap(k string) *SubObject { | |
if err != nil || !found { | ||
return nil | ||
} | ||
return &SubObject{obj: internal.NewMap(variant.YNode())} | ||
// this SubObject is the root kubeObject | ||
if o.nodePath == nil { | ||
oGroup, oVersion := ParseGroupVersion(o.GetString("apiVersion")) | ||
|
||
return &SubObject{ | ||
obj: internal.NewMap(variant.YNode()), | ||
gvk: &ResourceIdentifier{ | ||
Group: oGroup, | ||
Version: oVersion, | ||
Kind: o.GetString("kind"), | ||
}, | ||
nodePath: append(o.nodePath, k), | ||
} | ||
} | ||
// otherwise store the SubObject's relative path | ||
return &SubObject{obj: internal.NewMap(variant.YNode()), gvk: o.gvk, nodePath: append(o.nodePath, k)} | ||
} | ||
|
||
// GetBool accepts a single key `k` whose value is expected to be a boolean. It returns | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,89 @@ import ( | |
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
// processError recover the error catch by panic | ||
func processError(t *testing.T, expected string, err error) { | ||
v := recover() | ||
if v != nil { | ||
switch t := v.(type) { | ||
case errKubeObjectFields: | ||
err = &t | ||
case *errKubeObjectFields: | ||
err = t | ||
case errSubObjectFields: | ||
err = &t | ||
case *errSubObjectFields: | ||
err = t | ||
case errResultEnd: | ||
err = &t | ||
case *errResultEnd: | ||
err = t | ||
case ErrAttemptToTouchUpstreamIdentifier: | ||
err = &t | ||
case *ErrAttemptToTouchUpstreamIdentifier: | ||
err = t | ||
case ErrInternalAnnotation: | ||
err = &t | ||
case *ErrInternalAnnotation: | ||
err = t | ||
default: | ||
panic(v) | ||
} | ||
} | ||
assert.Equal(t, err.Error(), expected) | ||
} | ||
|
||
func TestWrongKRM(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Write tests separately instead of using parameterized way because recover panic can only catch error once. Not sure if there is a better way to include all test cases about error messaging testing into one Test function. |
||
input := ` | ||
apiVersion: apps/v1 | ||
kind: StatefulSet | ||
metadata: | ||
name: web | ||
spec: | ||
selector: | ||
matchLabels: | ||
app: nginx # has to match .spec.template.metadata.labels | ||
serviceName: "nginx" | ||
replicas: 3 # by default is 1 | ||
minReadySeconds: 10 # by default is 0 | ||
volumeClaimTemplates: | ||
- metadata: | ||
name: www | ||
labels: | ||
key: www | ||
` | ||
parseInput, err := ParseKubeObject([]byte(input)) | ||
expectedKRMError := "SubObject has unmatched field type: `metadata`, relative path to parent kubeObject(group=apps, version=v1, kind=StatefulSet) is ``" | ||
defer processError(t, expectedKRMError, err) | ||
_, _, err = parseInput.NestedSlice("metadata") | ||
} | ||
|
||
func TestWrongKRMWithSubObject(t *testing.T) { | ||
input := ` | ||
apiVersion: apps/v1 | ||
kind: StatefulSet | ||
metadata: | ||
name: web | ||
spec: | ||
selector: | ||
matchLabels: | ||
app: nginx # has to match .spec.template.metadata.labels | ||
serviceName: "nginx" | ||
replicas: 3 # by default is 1 | ||
minReadySeconds: 10 # by default is 0 | ||
volumeClaimTemplates: | ||
- metadata: | ||
name: www | ||
labels: | ||
key: www | ||
` | ||
parseInput, err := ParseKubeObject([]byte(input)) | ||
expectedKRMError := "SubObject has unmatched field type: `serviceName`, relative path to parent kubeObject(group=apps, version=v1, kind=StatefulSet) is `spec`" | ||
defer processError(t, expectedKRMError, err) | ||
subObj := parseInput.GetMap("spec") | ||
_, _, err = subObj.NestedSlice("serviceName") | ||
} | ||
|
||
func TestIsGVK(t *testing.T) { | ||
input := []byte(` | ||
apiVersion: apps/v3 | ||
|
Uh oh!
There was an error while loading. Please reload this page.