mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
refactor: combine unstructured and resource packages (#8276)
* refactor: introduce userinfo package in the cli Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * refactor: introduce api package in cli Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * refactor: combine unstructured and resource packages Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
34bfb57c08
commit
5360248135
9 changed files with 310 additions and 280 deletions
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource"
|
||||
unstructuredutils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/unstructured"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
|
@ -14,9 +13,9 @@ func getAndCompareResource(actualResource unstructured.Unstructured, fs billy.Fi
|
|||
if err != nil {
|
||||
return false, fmt.Errorf("Error: failed to load resource (%s)", err)
|
||||
}
|
||||
unstructuredutils.FixupGenerateLabels(actualResource)
|
||||
unstructuredutils.FixupGenerateLabels(*expectedResource)
|
||||
equals, err := unstructuredutils.Compare(actualResource, *expectedResource, true)
|
||||
resource.FixupGenerateLabels(actualResource)
|
||||
resource.FixupGenerateLabels(*expectedResource)
|
||||
equals, err := resource.Compare(actualResource, *expectedResource, true)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Error: failed to compare resources (%s)", err)
|
||||
}
|
||||
|
|
46
cmd/cli/kubectl-kyverno/resource/compare.go
Normal file
46
cmd/cli/kubectl-kyverno/resource/compare.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package resource
|
||||
|
||||
import (
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
type (
|
||||
marshaler = func(*unstructured.Unstructured) ([]byte, error)
|
||||
patcher = func(originalJSON, modifiedJSON []byte) ([]byte, error)
|
||||
)
|
||||
|
||||
var (
|
||||
defaultMarshaler = (*unstructured.Unstructured).MarshalJSON
|
||||
defaultPatcher = jsonpatch.CreateMergePatch
|
||||
)
|
||||
|
||||
func Compare(a, e unstructured.Unstructured, tidy bool) (bool, error) {
|
||||
if tidy {
|
||||
a = Tidy(a)
|
||||
e = Tidy(e)
|
||||
}
|
||||
return compare(a, e, defaultMarshaler, defaultPatcher)
|
||||
}
|
||||
|
||||
func compare(a, e unstructured.Unstructured, marshaler marshaler, patcher patcher) (bool, error) {
|
||||
if marshaler == nil {
|
||||
marshaler = defaultMarshaler
|
||||
}
|
||||
actual, err := marshaler(&a)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
expected, err := marshaler(&e)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if patcher == nil {
|
||||
patcher = defaultPatcher
|
||||
}
|
||||
patch, err := patcher(actual, expected)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(patch) == 2, nil
|
||||
}
|
|
@ -1,100 +1,12 @@
|
|||
package unstructured
|
||||
package resource
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func TestTidyObject(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj interface{}
|
||||
want interface{}
|
||||
}{{
|
||||
obj: "string",
|
||||
want: "string",
|
||||
}, {
|
||||
obj: map[string]interface{}{},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: nil,
|
||||
want: nil,
|
||||
}, {
|
||||
obj: []interface{}{},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: map[string]interface{}{
|
||||
"map": nil,
|
||||
},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: map[string]interface{}{
|
||||
"map": map[string]interface{}{},
|
||||
},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
want: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
}, {
|
||||
obj: []interface{}{[]interface{}{}},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: []interface{}{1},
|
||||
want: []interface{}{1},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := TidyObject(tt.obj); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("TidyObject() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTidy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj unstructured.Unstructured
|
||||
want unstructured.Unstructured
|
||||
}{{
|
||||
obj: unstructured.Unstructured{},
|
||||
want: unstructured.Unstructured{},
|
||||
}, {
|
||||
obj: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Tidy(tt.obj); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Tidy() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompare(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -186,83 +98,6 @@ func TestCompare(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFixupGenerateLabels(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj unstructured.Unstructured
|
||||
want unstructured.Unstructured
|
||||
}{{
|
||||
name: "not set",
|
||||
}, {
|
||||
name: "empty",
|
||||
obj: unstructured.Unstructured{Object: map[string]interface{}{}},
|
||||
want: unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
},
|
||||
},
|
||||
}},
|
||||
}, {
|
||||
name: "with label",
|
||||
obj: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
name: "with generate labels",
|
||||
obj: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"generate.kyverno.io/policy-name": "add-networkpolicy",
|
||||
"generate.kyverno.io/policy-namespace": "",
|
||||
"generate.kyverno.io/rule-name": "default-deny",
|
||||
"generate.kyverno.io/trigger-group": "",
|
||||
"generate.kyverno.io/trigger-kind": "Namespace",
|
||||
"generate.kyverno.io/trigger-name": "hello-world-namespace",
|
||||
"generate.kyverno.io/trigger-namespace": "default",
|
||||
"generate.kyverno.io/trigger-version": "v1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
FixupGenerateLabels(tt.obj)
|
||||
if !reflect.DeepEqual(tt.obj, tt.want) {
|
||||
t.Errorf("FixupGenerateLabels() = %v, want %v", tt.obj, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_compare(t *testing.T) {
|
||||
errorMarshaller := func(count int) marshaler {
|
||||
var current = 0
|
21
cmd/cli/kubectl-kyverno/resource/labels.go
Normal file
21
cmd/cli/kubectl-kyverno/resource/labels.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package resource
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func FixupGenerateLabels(obj unstructured.Unstructured) {
|
||||
tidy := map[string]string{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
}
|
||||
if labels := obj.GetLabels(); labels != nil {
|
||||
for k, v := range labels {
|
||||
if !strings.HasPrefix(k, "generate.kyverno.io/") {
|
||||
tidy[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
obj.SetLabels(tidy)
|
||||
}
|
85
cmd/cli/kubectl-kyverno/resource/labels_test.go
Normal file
85
cmd/cli/kubectl-kyverno/resource/labels_test.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
package resource
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func TestFixupGenerateLabels(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj unstructured.Unstructured
|
||||
want unstructured.Unstructured
|
||||
}{{
|
||||
name: "not set",
|
||||
}, {
|
||||
name: "empty",
|
||||
obj: unstructured.Unstructured{Object: map[string]interface{}{}},
|
||||
want: unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
},
|
||||
},
|
||||
}},
|
||||
}, {
|
||||
name: "with label",
|
||||
obj: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
name: "with generate labels",
|
||||
obj: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"generate.kyverno.io/policy-name": "add-networkpolicy",
|
||||
"generate.kyverno.io/policy-namespace": "",
|
||||
"generate.kyverno.io/rule-name": "default-deny",
|
||||
"generate.kyverno.io/trigger-group": "",
|
||||
"generate.kyverno.io/trigger-kind": "Namespace",
|
||||
"generate.kyverno.io/trigger-name": "hello-world-namespace",
|
||||
"generate.kyverno.io/trigger-namespace": "default",
|
||||
"generate.kyverno.io/trigger-version": "v1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
FixupGenerateLabels(tt.obj)
|
||||
if !reflect.DeepEqual(tt.obj, tt.want) {
|
||||
t.Errorf("FixupGenerateLabels() = %v, want %v", tt.obj, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
45
cmd/cli/kubectl-kyverno/resource/tidy.go
Normal file
45
cmd/cli/kubectl-kyverno/resource/tidy.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package resource
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func Tidy(obj unstructured.Unstructured) unstructured.Unstructured {
|
||||
if obj.Object == nil {
|
||||
return obj
|
||||
}
|
||||
return unstructured.Unstructured{
|
||||
Object: tidy(obj.UnstructuredContent()).(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func tidy(obj interface{}) interface{} {
|
||||
switch typedPatternElement := obj.(type) {
|
||||
case map[string]interface{}:
|
||||
out := map[string]interface{}{}
|
||||
for k, v := range typedPatternElement {
|
||||
v = tidy(v)
|
||||
if v != nil {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
if len(out) == 0 {
|
||||
return nil
|
||||
}
|
||||
return out
|
||||
case []interface{}:
|
||||
var out []interface{}
|
||||
for _, v := range typedPatternElement {
|
||||
v = tidy(v)
|
||||
if v != nil {
|
||||
out = append(out, v)
|
||||
}
|
||||
}
|
||||
if len(out) == 0 {
|
||||
return nil
|
||||
}
|
||||
return out
|
||||
default:
|
||||
return obj
|
||||
}
|
||||
}
|
95
cmd/cli/kubectl-kyverno/resource/tidy_test.go
Normal file
95
cmd/cli/kubectl-kyverno/resource/tidy_test.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
package resource
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func Test_tidy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj interface{}
|
||||
want interface{}
|
||||
}{{
|
||||
obj: "string",
|
||||
want: "string",
|
||||
}, {
|
||||
obj: map[string]interface{}{},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: nil,
|
||||
want: nil,
|
||||
}, {
|
||||
obj: []interface{}{},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: map[string]interface{}{
|
||||
"map": nil,
|
||||
},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: map[string]interface{}{
|
||||
"map": map[string]interface{}{},
|
||||
},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
want: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
}, {
|
||||
obj: []interface{}{[]interface{}{}},
|
||||
want: nil,
|
||||
}, {
|
||||
obj: []interface{}{1},
|
||||
want: []interface{}{1},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tidy(tt.obj); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("TidyObject() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTidy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj unstructured.Unstructured
|
||||
want unstructured.Unstructured
|
||||
}{{
|
||||
obj: unstructured.Unstructured{},
|
||||
want: unstructured.Unstructured{},
|
||||
}, {
|
||||
obj: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Tidy(tt.obj); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Tidy() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -12,8 +12,7 @@ import (
|
|||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func Load(fs billy.Filesystem, path string, resourcePath string) (*kyvernov1beta1.RequestInfo, error) {
|
||||
var userInfo kyvernov1beta1.RequestInfo
|
||||
func load(fs billy.Filesystem, path string, resourcePath string) ([]byte, error) {
|
||||
if fs != nil {
|
||||
filep, err := fs.Open(filepath.Join(resourcePath, path))
|
||||
if err != nil {
|
||||
|
@ -23,17 +22,24 @@ func Load(fs billy.Filesystem, path string, resourcePath string) (*kyvernov1beta
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("Error: failed to read file %s: %w", filep.Name(), err)
|
||||
}
|
||||
if err := yaml.UnmarshalStrict(bytes, &userInfo); err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
return bytes, err
|
||||
} else {
|
||||
bytes, err := os.ReadFile(filepath.Clean(filepath.Join(resourcePath, path)))
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("unable to read yaml", err)
|
||||
}
|
||||
if err := yaml.UnmarshalStrict(bytes, &userInfo); err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
return bytes, err
|
||||
}
|
||||
}
|
||||
|
||||
func Load(fs billy.Filesystem, path string, resourcePath string) (*kyvernov1beta1.RequestInfo, error) {
|
||||
bytes, err := load(fs, path, resourcePath)
|
||||
if err != nil {
|
||||
return nil, sanitizederror.NewWithError("unable to read yaml", err)
|
||||
}
|
||||
var userInfo kyvernov1beta1.RequestInfo
|
||||
if err := yaml.UnmarshalStrict(bytes, &userInfo); err != nil {
|
||||
return nil, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
package unstructured
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
type (
|
||||
marshaler = func(*unstructured.Unstructured) ([]byte, error)
|
||||
patcher = func(originalJSON, modifiedJSON []byte) ([]byte, error)
|
||||
)
|
||||
|
||||
var (
|
||||
defaultMarshaler = (*unstructured.Unstructured).MarshalJSON
|
||||
defaultPatcher = jsonpatch.CreateMergePatch
|
||||
)
|
||||
|
||||
func TidyObject(obj interface{}) interface{} {
|
||||
switch typedPatternElement := obj.(type) {
|
||||
case map[string]interface{}:
|
||||
tidy := map[string]interface{}{}
|
||||
for k, v := range typedPatternElement {
|
||||
v = TidyObject(v)
|
||||
if v != nil {
|
||||
tidy[k] = v
|
||||
}
|
||||
}
|
||||
if len(tidy) == 0 {
|
||||
return nil
|
||||
}
|
||||
return tidy
|
||||
case []interface{}:
|
||||
var tidy []interface{}
|
||||
for _, v := range typedPatternElement {
|
||||
v = TidyObject(v)
|
||||
if v != nil {
|
||||
tidy = append(tidy, v)
|
||||
}
|
||||
}
|
||||
if len(tidy) == 0 {
|
||||
return nil
|
||||
}
|
||||
return tidy
|
||||
default:
|
||||
return obj
|
||||
}
|
||||
}
|
||||
|
||||
func Tidy(obj unstructured.Unstructured) unstructured.Unstructured {
|
||||
if obj.Object == nil {
|
||||
return obj
|
||||
}
|
||||
return unstructured.Unstructured{
|
||||
Object: TidyObject(obj.UnstructuredContent()).(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func FixupGenerateLabels(obj unstructured.Unstructured) {
|
||||
tidy := map[string]string{
|
||||
"app.kubernetes.io/managed-by": "kyverno",
|
||||
}
|
||||
if labels := obj.GetLabels(); labels != nil {
|
||||
for k, v := range labels {
|
||||
if !strings.HasPrefix(k, "generate.kyverno.io/") {
|
||||
tidy[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
obj.SetLabels(tidy)
|
||||
}
|
||||
|
||||
func Compare(a, e unstructured.Unstructured, tidy bool) (bool, error) {
|
||||
if tidy {
|
||||
a = Tidy(a)
|
||||
e = Tidy(e)
|
||||
}
|
||||
return compare(a, e, defaultMarshaler, defaultPatcher)
|
||||
}
|
||||
|
||||
func compare(a, e unstructured.Unstructured, marshaler marshaler, patcher patcher) (bool, error) {
|
||||
if marshaler == nil {
|
||||
marshaler = defaultMarshaler
|
||||
}
|
||||
actual, err := marshaler(&a)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
expected, err := marshaler(&e)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if patcher == nil {
|
||||
patcher = defaultPatcher
|
||||
}
|
||||
patch, err := patcher(actual, expected)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(patch) == 2, nil
|
||||
}
|
Loading…
Add table
Reference in a new issue