1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00
kyverno/pkg/cel/libs/context/impl_test.go
Frank Jogeleit 5f42a0bad8
feat: context function to request resources from api server (#12181)
* feat: context function to request resources from api server

Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>

* add chainsaw test

Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>

* replace dclient with dynamic client

Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>

* update test case

Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>

---------

Signed-off-by: Frank Jogeleit <frank.jogeleit@web.de>
Co-authored-by: shuting <shuting@nirmata.com>
2025-02-27 13:31:03 +00:00

227 lines
6.5 KiB
Go

package context
import (
"context"
"strings"
"testing"
"github.com/google/cel-go/cel"
"github.com/kyverno/kyverno/pkg/imageverification/imagedataloader"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
type ctx struct {
GetConfigMapFunc func(string, string) (unstructured.Unstructured, error)
GetGlobalReferenceFunc func(string) (any, error)
GetImageDataFunc func(string) (*imagedataloader.ImageData, error)
ListResourcesFunc func(string, string, string) (*unstructured.UnstructuredList, error)
GetResourcesFunc func(string, string, string, string) (*unstructured.Unstructured, error)
}
func (mock *ctx) GetConfigMap(ns string, n string) (unstructured.Unstructured, error) {
return mock.GetConfigMapFunc(ns, n)
}
func (mock *ctx) GetGlobalReference(n string) (any, error) {
return mock.GetGlobalReferenceFunc(n)
}
func (mock *ctx) GetImageData(n string) (*imagedataloader.ImageData, error) {
return mock.GetImageDataFunc(n)
}
func (mock *ctx) ListResource(apiVersion, resource, namespace string) (*unstructured.UnstructuredList, error) {
return mock.ListResourcesFunc(apiVersion, resource, namespace)
}
func (mock *ctx) GetResource(apiVersion, resource, namespace, name string) (*unstructured.Unstructured, error) {
return mock.GetResourcesFunc(apiVersion, resource, namespace, name)
}
func Test_impl_get_configmap_string_string(t *testing.T) {
opts := Lib()
base, err := cel.NewEnv(opts)
assert.NoError(t, err)
assert.NotNil(t, base)
options := []cel.EnvOption{
cel.Variable("context", ContextType),
}
env, err := base.Extend(options...)
assert.NoError(t, err)
assert.NotNil(t, env)
ast, issues := env.Compile(`context.GetConfigMap("foo","bar")`)
assert.Nil(t, issues)
assert.NotNil(t, ast)
prog, err := env.Program(ast)
assert.NoError(t, err)
assert.NotNil(t, prog)
called := false
data := map[string]any{
"context": Context{&ctx{
GetConfigMapFunc: func(string, string) (unstructured.Unstructured, error) {
called = true
return unstructured.Unstructured{}, nil
},
}},
}
out, _, err := prog.Eval(data)
assert.NoError(t, err)
assert.NotNil(t, out)
assert.True(t, called)
}
func Test_impl_get_globalreference_string(t *testing.T) {
opts := Lib()
base, err := cel.NewEnv(opts)
assert.NoError(t, err)
assert.NotNil(t, base)
options := []cel.EnvOption{
cel.Variable("context", ContextType),
}
env, err := base.Extend(options...)
assert.NoError(t, err)
assert.NotNil(t, env)
ast, issues := env.Compile(`context.GetGlobalReference("foo")`)
assert.Nil(t, issues)
assert.NotNil(t, ast)
prog, err := env.Program(ast)
assert.NoError(t, err)
assert.NotNil(t, prog)
called := false
data := map[string]any{
"context": Context{&ctx{
GetGlobalReferenceFunc: func(string) (any, error) {
type foo struct {
s string
}
called = true
return foo{"bar"}, nil
},
}},
}
out, _, err := prog.Eval(data)
assert.NoError(t, err)
assert.NotNil(t, out)
assert.True(t, called)
}
func Test_impl_get_imagedata_string(t *testing.T) {
opts := Lib()
base, err := cel.NewEnv(opts)
assert.NoError(t, err)
assert.NotNil(t, base)
options := []cel.EnvOption{
cel.Variable("context", ContextType),
}
env, err := base.Extend(options...)
assert.NoError(t, err)
assert.NotNil(t, env)
ast, issues := env.Compile(`context.GetImageData("ghcr.io/kyverno/kyverno:latest")`)
assert.Nil(t, issues)
assert.NotNil(t, ast)
prog, err := env.Program(ast)
assert.NoError(t, err)
assert.NotNil(t, prog)
data := map[string]any{
"context": Context{&ctx{
GetImageDataFunc: func(image string) (*imagedataloader.ImageData, error) {
idl, err := imagedataloader.New(nil)
assert.NoError(t, err)
return idl.FetchImageData(context.TODO(), image)
},
}},
}
out, _, err := prog.Eval(data)
assert.NoError(t, err)
img := out.Value().(*imagedataloader.ImageData)
assert.Equal(t, img.Tag, "latest")
assert.True(t, strings.HasPrefix(img.ResolvedImage, "ghcr.io/kyverno/kyverno:latest@sha256:"))
assert.True(t, img.ConfigData != nil)
assert.True(t, img.Manifest != nil)
assert.True(t, img.ImageIndex != nil)
}
func Test_impl_get_resource_string(t *testing.T) {
opts := Lib()
base, err := cel.NewEnv(opts)
assert.NoError(t, err)
assert.NotNil(t, base)
options := []cel.EnvOption{
cel.Variable("context", ContextType),
}
env, err := base.Extend(options...)
assert.NoError(t, err)
assert.NotNil(t, env)
ast, issues := env.Compile(`context.GetResource("apps/v1", "Deployment", "default", "nginx")`)
assert.Nil(t, issues)
assert.NotNil(t, ast)
prog, err := env.Program(ast)
assert.NoError(t, err)
assert.NotNil(t, prog)
data := map[string]any{
"context": Context{&ctx{
GetResourcesFunc: func(apiVersion, resource, namespace, name string) (*unstructured.Unstructured, error) {
return &unstructured.Unstructured{
Object: map[string]any{
"apiVersion": apiVersion,
"kind": resource,
"metadata": map[string]any{
"name": name,
"namespace": namespace,
},
},
}, nil
},
}},
}
out, _, err := prog.Eval(data)
assert.NoError(t, err)
object := out.Value().(map[string]any)
assert.Equal(t, object["apiVersion"].(string), "apps/v1")
assert.Equal(t, object["kind"].(string), "Deployment")
}
func Test_impl_list_resource_string(t *testing.T) {
opts := Lib()
base, err := cel.NewEnv(opts)
assert.NoError(t, err)
assert.NotNil(t, base)
options := []cel.EnvOption{
cel.Variable("context", ContextType),
}
env, err := base.Extend(options...)
assert.NoError(t, err)
assert.NotNil(t, env)
ast, issues := env.Compile(`context.ListResource("apps/v1", "Deployment", "default")`)
assert.Nil(t, issues)
assert.NotNil(t, ast)
prog, err := env.Program(ast)
assert.NoError(t, err)
assert.NotNil(t, prog)
data := map[string]any{
"context": Context{&ctx{
ListResourcesFunc: func(apiVersion, resource, namespace string) (*unstructured.UnstructuredList, error) {
return &unstructured.UnstructuredList{
Items: []unstructured.Unstructured{
{
Object: map[string]any{
"apiVersion": apiVersion,
"kind": resource,
"metadata": map[string]any{
"name": "nginx",
"namespace": namespace,
},
},
},
},
}, nil
},
}},
}
out, _, err := prog.Eval(data)
assert.NoError(t, err)
object := out.Value().(map[string]any)
assert.Equal(t, object["items"].([]any)[0].(map[string]any)["apiVersion"].(string), "apps/v1")
assert.Equal(t, object["items"].([]any)[0].(map[string]any)["kind"].(string), "Deployment")
}