1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

Merge pull request #174 from nirmata/152_automate_testing

152 automate testing
This commit is contained in:
shuting 2019-06-19 16:36:52 -07:00 committed by GitHub
commit f6ebb056a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 986 additions and 0 deletions

View file

@ -0,0 +1,21 @@
# input
policy: policy-deployment
resource: nginx-deployment
initResources:
# expected
mutation:
mPatchedResource: nginx-deployment
reason: Success
validation:
reason: Success
---
# input
policy: policy-deployment
resource: ghost
initResources:
# expected
mutation:
mPatchedResource: ghost
reason: Success
validation:
reason: Failed

View file

@ -0,0 +1,20 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: config-template
namespace: default
labels:
originalLabel : isHere
data:
ui.properties : |
color.good=green
color.bad=red
game.properties : |
enemies=predators
lives=3
configmap.data: |
ns=default
labels=originalLabel
labelscount=1

View file

@ -0,0 +1,36 @@
apiVersion : kyverno.io/v1alpha1
kind : Policy
metadata :
name : basic-policy
spec :
rules:
- name: "Basic config generator for all namespaces"
resource:
kinds:
- Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
generate:
kind: ConfigMap
name: default-config
clone:
namespace: default
name: config-template
- name: "Basic config generator for all namespaces"
resource:
kinds:
- Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
generate:
kind: Secret
name: mongo-creds
data:
data:
DB_USER: YWJyYWthZGFicmE=
DB_PASSWORD: YXBwc3dvcmQ=
metadata:
labels:
purpose: mongo

View file

@ -0,0 +1,40 @@
# input
policy: basic-policy
resource: ns2
initResources:
- default/config-template
# expected
generation:
resource:
- name: default-config
namespace: ns2
kind: ConfigMap
- name: mongo-creds
namespace: ns2
kind: Secret
---
# input
policy: zk-kafka-address
resource: ns2
initResources:
- default/game-config
# expected
generation:
resource:
- name: copied-cm
namespace: ns2
kind: ConfigMap
- name: zk-kafka-address
namespace: ns2
kind: ConfigMap
---
# input
policy: default
resource: ns2
initResources:
# expected
generation:
resource:
- name: deny-all-traffic
namespace: ns2
kind: NetworkPolicy

View file

@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
creationTimestamp:
labels:
app: nginx
spec:
@ -11,6 +12,7 @@ spec:
app: nginx
template:
metadata:
creationTimestamp:
labels:
app: nginx
spec:

View file

@ -0,0 +1,10 @@
# input
policy: set-image-pull-policy
resource: nginx-deployment
initResources:
# expected
mutation:
mPatchedResource: nginx-deployment
reason: Success
validation:
reason: Success

View file

@ -0,0 +1,21 @@
# input
policy: policy-endpoints
resource: test-endpoint
initResources:
# expected
mutation:
mPatchedResource: test-endpoint
reason: Success
validation:
reason: Success
---
# input
policy: policy-endpoints
resource: test-endpoint
initResources:
# expected
mutation:
mPatchedResource: test-endpoint
reason: Success
validation:
reason: Success

View file

@ -79,6 +79,7 @@ func (f *fixture) setupFixture() {
if err != nil {
f.t.Fatal(err)
}
regresource := []schema.GroupVersionResource{
schema.GroupVersionResource{Group: "kyverno.io",
Version: "v1alpha1",

View file

@ -34,6 +34,7 @@ func newFixture(t *testing.T) *fixture {
schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"},
schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
}
objects := []runtime.Object{newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
newUnstructured("group2/version", "TheKind", "ns-foo", "name2-foo"),
newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
@ -51,6 +52,7 @@ func newFixture(t *testing.T) *fixture {
// set discovery Client
client.SetDiscovery(NewFakeDiscoveryClient(regResource))
f := fixture{
t: t,
objects: objects,

180
pkg/testrunner/test.go Normal file
View file

@ -0,0 +1,180 @@
package testrunner
import (
"fmt"
"testing"
ospath "path"
"github.com/golang/glog"
pt "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/engine"
"github.com/nirmata/kyverno/pkg/result"
kscheme "k8s.io/client-go/kubernetes/scheme"
)
type test struct {
ap string
t *testing.T
testCase *testCase
// input
policy *pt.Policy
tResource *resourceInfo
loadResources []*resourceInfo
// expected
genResources []*resourceInfo
patchedResource *resourceInfo
}
func (t *test) run() {
var client *client.Client
var err error
//mock client is used if generate is defined
if t.testCase.Expected.Generation != nil {
// create mock client & load resources
client, err = createClient(t.loadResources)
if err != nil {
t.t.Errorf("Unable to create client. err %s", err)
}
// TODO: handle generate
// assuming its namespaces creation
decode := kscheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(t.tResource.rawResource), nil, nil)
_, err = client.CreateResource(getResourceFromKind(t.tResource.gvk.Kind), "", obj, false)
if err != nil {
t.t.Errorf("error while creating namespace %s", err)
}
}
// apply the policy engine
pr, mResult, vResult, err := t.applyPolicy(t.policy, t.tResource, client)
if err != nil {
t.t.Error(err)
return
}
// Expected Result
t.checkMutationResult(pr, mResult)
t.checkValidationResult(vResult)
t.checkGenerationResult(client)
}
func (t *test) checkMutationResult(pr *resourceInfo, result result.Result) {
if t.testCase.Expected.Mutation == nil {
glog.Info("No Mutation check defined")
return
}
// patched resource
if !compareResource(pr, t.patchedResource) {
fmt.Printf("Expected Resource %s \n", string(t.patchedResource.rawResource))
fmt.Printf("Patched Resource %s \n", string(pr.rawResource))
glog.Warningf("Expected resource %s ", string(pr.rawResource))
t.t.Error("Patched resources not as expected")
}
// reason
reason := t.testCase.Expected.Mutation.Reason
if len(reason) > 0 && result.GetReason().String() != reason {
t.t.Error("Reason not matching")
}
}
func (t *test) checkValidationResult(result result.Result) {
if t.testCase.Expected.Validation == nil {
glog.Info("No Validation check defined")
return
}
// reason
reason := t.testCase.Expected.Validation.Reason
if len(reason) > 0 && result.GetReason().String() != reason {
t.t.Error("Reason not matching")
}
}
func (t *test) checkGenerationResult(client *client.Client) {
if t.testCase.Expected.Generation == nil {
glog.Info("No Generate check defined")
return
}
if client == nil {
glog.Info("client needs to be configured")
}
// check if the expected resources are generated
for _, r := range t.genResources {
n := ParseNameFromObject(r.rawResource)
ns := ParseNamespaceFromObject(r.rawResource)
_, err := client.GetResource(getResourceFromKind(r.gvk.Kind), ns, n)
if err != nil {
t.t.Errorf("Resource %s/%s of kinf %s not found", ns, n, r.gvk.Kind)
}
// compare if the resources are same
//TODO: comapre []bytes vs unstrcutured resource
}
}
func (t *test) applyPolicy(policy *pt.Policy,
tresource *resourceInfo,
client *client.Client) (*resourceInfo, result.Result, result.Result, error) {
// apply policy on the trigger resource
// Mutate
var vResult result.Result
var patchedResource []byte
mPatches, mResult := engine.Mutate(*policy, tresource.rawResource, *tresource.gvk)
// TODO: only validate if there are no errors in mutate, why?
err := mResult.ToError()
if err == nil && len(mPatches) != 0 {
patchedResource, err = engine.ApplyPatches(tresource.rawResource, mPatches)
if err != nil {
return nil, nil, nil, err
}
// Validate
vResult = engine.Validate(*policy, patchedResource, *tresource.gvk)
}
// Generate
if client != nil {
engine.Generate(client, *policy, tresource.rawResource, *tresource.gvk)
}
// transform the patched Resource into resource Info
ri, err := extractResourceRaw(patchedResource)
if err != nil {
return nil, nil, nil, err
}
// return the results
return ri, mResult, vResult, nil
}
func NewTest(ap string, t *testing.T, tc *testCase) (*test, error) {
//---INPUT---
p, err := tc.loadPolicy(ospath.Join(ap, tc.Input.Policy))
if err != nil {
return nil, err
}
r, err := tc.loadTriggerResource(ap)
if err != nil {
return nil, err
}
lr, err := tc.loadPreloadedResources(ap)
if err != nil {
return nil, err
}
//---EXPECTED---
pr, err := tc.loadPatchedResource(ap)
if err != nil {
return nil, err
}
gr, err := tc.loadGeneratedResources(ap)
if err != nil {
return nil, err
}
return &test{
ap: ap,
t: t,
testCase: tc,
policy: p,
tResource: r,
loadResources: lr,
genResources: gr,
patchedResource: pr,
}, nil
}

178
pkg/testrunner/testcase.go Normal file
View file

@ -0,0 +1,178 @@
package testrunner
import (
"bytes"
"encoding/json"
"fmt"
ospath "path"
"github.com/golang/glog"
pt "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
yaml "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/kubernetes/scheme"
)
//testCase defines the input and the expected result
// it stores the path to the files that are to be loaded
// for references
type testCase struct {
Input *tInput `yaml:"input"`
Expected *tExpected `yaml:"expected"`
}
// load resources store the resources that are pre-requisite
// for the test case and are pre-loaded in the client before
/// test case in evaluated
type tInput struct {
Policy string `yaml:"policy"`
Resource string `yaml:"resource"`
LoadResources []string `yaml:"load_resources,omitempty"`
}
type tExpected struct {
Mutation *tMutation `yaml:"mutation,omitempty"`
Validation *tValidation `yaml:"validation,omitempty"`
Generation *tGeneration `yaml:"generation,omitempty"`
}
type tMutation struct {
Patched_Resource string `yaml:"patched_resource,omitempty"`
tResult
}
type tValidation struct {
tResult
}
type tGeneration struct {
Resources []string `yaml:"resources"`
}
type tResult struct {
Reason string `yaml:"reason, omitempty"`
}
func (tc *testCase) policyEngineTest() {
}
func (tc *testCase) loadPreloadedResources(ap string) ([]*resourceInfo, error) {
return loadResources(ap, tc.Input.LoadResources...)
// return loadResources(ap, tc.Input.LoadResources...)
}
func (tc *testCase) loadGeneratedResources(ap string) ([]*resourceInfo, error) {
if tc.Expected.Generation == nil {
return nil, nil
}
return loadResources(ap, tc.Expected.Generation.Resources...)
}
func (tc *testCase) loadPatchedResource(ap string) (*resourceInfo, error) {
if tc.Expected.Mutation == nil {
return nil, nil
}
rs, err := loadResources(ap, tc.Expected.Mutation.Patched_Resource)
if err != nil {
return nil, err
}
if len(rs) != 1 {
glog.Warning("expects single resource mutation but multiple defined, will use first one")
}
return rs[0], nil
}
func (tc *testCase) loadResources(files []string) ([]*resourceInfo, error) {
lr := []*resourceInfo{}
for _, r := range files {
rs, err := loadResources(r)
if err != nil {
// return as test case will be invalid if a resource cannot be loaded
return nil, err
}
lr = append(lr, rs...)
}
return lr, nil
}
func (tc *testCase) loadTriggerResource(ap string) (*resourceInfo, error) {
rs, err := loadResources(ap, tc.Input.Resource)
if err != nil {
return nil, err
}
if len(rs) != 1 {
glog.Warning("expects single resource trigger but multiple defined, will use first one")
}
return rs[0], nil
}
// Loads a single policy
func (tc *testCase) loadPolicy(file string) (*pt.Policy, error) {
p := &pt.Policy{}
data, err := LoadFile(file)
if err != nil {
return nil, err
}
pBytes, err := yaml.ToJSON(data)
if err != nil {
return nil, err
}
if err := json.Unmarshal(pBytes, p); err != nil {
return nil, err
}
if p.TypeMeta.Kind != "Policy" {
return nil, fmt.Errorf("failed to parse policy")
}
return p, nil
}
// loads multiple resources
func loadResources(ap string, args ...string) ([]*resourceInfo, error) {
ris := []*resourceInfo{}
for _, file := range args {
data, err := LoadFile(ospath.Join(ap, file))
if err != nil {
return nil, err
}
dd := bytes.Split(data, []byte(defaultYamlSeparator))
// resources seperated by yaml seperator
for _, d := range dd {
ri, err := extractResourceRaw(d)
if err != nil {
glog.Errorf("unable to load resource. err: %s ", err)
continue
}
ris = append(ris, ri)
}
}
return ris, nil
}
func extractResourceRaw(d []byte) (*resourceInfo, error) {
// decode := scheme.Codecs.UniversalDeserializer().Decode
// obj, gvk, err := decode(d, nil, nil)
// if err != nil {
// return nil, err
// }
obj, gvk, err := extractResourceUnMarshalled(d)
// runtime.object to JSON
raw, err := json.Marshal(obj)
if err != nil {
return nil, err
}
return &resourceInfo{rawResource: raw,
gvk: gvk}, nil
}
func extractResourceUnMarshalled(d []byte) (runtime.Object, *metav1.GroupVersionKind, error) {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, gvk, err := decode(d, nil, nil)
if err != nil {
return nil, nil, err
}
return obj, &metav1.GroupVersionKind{Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind}, nil
}

View file

@ -0,0 +1,98 @@
package testrunner
import (
"bytes"
"io/ioutil"
"path/filepath"
"testing"
"os"
ospath "path"
"github.com/golang/glog"
"gopkg.in/yaml.v2"
)
func runner(t *testing.T, relpath string) {
gp := os.Getenv("GOPATH")
ap := ospath.Join(gp, projectPath)
// build load scenarios
path := ospath.Join(ap, relpath)
// Load the scenario files
scenarioFiles := getYAMLfiles(path)
for _, secenarioFile := range scenarioFiles {
sc := newScenario(t, ap, secenarioFile)
if err := sc.load(); err != nil {
t.Error(err)
return
}
// run test cases
sc.run()
}
}
type scenario struct {
ap string
t *testing.T
path string
tcs []*testCase
}
func newScenario(t *testing.T, ap string, path string) *scenario {
return &scenario{
ap: ap,
t: t,
path: path,
}
}
func getYAMLfiles(path string) (yamls []string) {
fileInfo, err := ioutil.ReadDir(path)
if err != nil {
return nil
}
for _, file := range fileInfo {
if filepath.Ext(file.Name()) == ".yml" || filepath.Ext(file.Name()) == ".yaml" {
yamls = append(yamls, ospath.Join(path, file.Name()))
}
}
return yamls
}
func (sc *scenario) load() error {
// read file
data, err := LoadFile(sc.path)
if err != nil {
return err
}
tcs := []*testCase{}
// load test cases seperated by '---'
// each test case defines an input & expected result
dd := bytes.Split(data, []byte(defaultYamlSeparator))
for _, d := range dd {
tc := &testCase{}
err := yaml.Unmarshal([]byte(d), tc)
if err != nil {
glog.Warningf("Error while decoding YAML object, err: %s", err)
continue
}
tcs = append(tcs, tc)
}
sc.tcs = tcs
return nil
}
func (sc *scenario) run() {
if len(sc.tcs) == 0 {
sc.t.Error("No test cases to load")
return
}
for _, tc := range sc.tcs {
t, err := NewTest(sc.ap, sc.t, tc)
if err != nil {
sc.t.Error(err)
continue
}
t.run()
}
}

View file

@ -0,0 +1,7 @@
package testrunner
import "testing"
func TestExamples(t *testing.T) {
runner(t, "/test/scenarios")
}

123
pkg/testrunner/utils.go Normal file
View file

@ -0,0 +1,123 @@
package testrunner
import (
"bytes"
"encoding/json"
"io/ioutil"
"os"
"github.com/golang/glog"
client "github.com/nirmata/kyverno/pkg/dclient"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
kscheme "k8s.io/client-go/kubernetes/scheme"
)
const (
defaultYamlSeparator = "---"
projectPath = "src/github.com/nirmata/kyverno"
)
// LoadFile loads file in byte buffer
func LoadFile(path string) ([]byte, error) {
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil, err
}
return ioutil.ReadFile(path)
}
type resourceInfo struct {
rawResource []byte
gvk *metav1.GroupVersionKind
}
func (ri resourceInfo) isSame(other resourceInfo) bool {
// compare gvk
if *ri.gvk != *other.gvk {
return false
}
// compare rawResource
return bytes.Equal(ri.rawResource, other.rawResource)
}
// compare patched resources
func compareResource(er *resourceInfo, pr *resourceInfo) bool {
if !er.isSame(*pr) {
return false
}
return true
}
func createClient(resources []*resourceInfo) (*client.Client, error) {
scheme := runtime.NewScheme()
objects := []runtime.Object{}
// registered group versions
regResources := []schema.GroupVersionResource{}
for _, r := range resources {
// registered gvr
gv := schema.GroupVersion{Group: r.gvk.Group, Version: r.gvk.Version}
gvr := gv.WithResource(getResourceFromKind(r.gvk.Kind))
regResources = append(regResources, gvr)
decode := kscheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(r.rawResource), nil, nil)
rdata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&obj)
if err != nil {
glog.Errorf("failed to load resource. err %s", err)
}
unstr := unstructured.Unstructured{Object: rdata}
objects = append(objects, &unstr)
}
// Mock Client
c, err := client.NewMockClient(scheme, objects...)
if err != nil {
return nil, err
}
c.SetDiscovery(client.NewFakeDiscoveryClient(regResources))
return c, nil
}
var kindToResource = map[string]string{
"ConfigMap": "configmaps",
"Endpoints": "endpoints",
"Namespace": "namespaces",
"Secret": "secrets",
"Deployment": "deployments",
"NetworkPolicy": "networkpolicies",
}
func getResourceFromKind(kind string) string {
if resource, ok := kindToResource[kind]; ok {
return resource
}
return ""
}
//ParseNameFromObject extracts resource name from JSON obj
func ParseNameFromObject(bytes []byte) string {
var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON)
meta := objectJSON["metadata"].(map[string]interface{})
if name, ok := meta["name"].(string); ok {
return name
}
return ""
}
// ParseNamespaceFromObject extracts the namespace from the JSON obj
func ParseNamespaceFromObject(bytes []byte) string {
var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON)
meta := objectJSON["metadata"].(map[string]interface{})
if namespace, ok := meta["namespace"].(string); ok {
return namespace
}
return ""
}

View file

@ -0,0 +1,16 @@
apiVersion: v1
data:
configmap.data: |
ns=default
labels=originalLabel
labelscount=1
game.properties: |
enemies=predators
lives=3
ui.properties: "color.good=green\ncolor.bad=red \n"
kind: ConfigMap
metadata:
labels:
originalLabel: isHere
name: copied-cm
namespace: ns2

View file

@ -0,0 +1,16 @@
apiVersion: v1
data:
configmap.data: |
ns=default
labels=originalLabel
labelscount=1
game.properties: |
enemies=predators
lives=3
ui.properties: "color.good=green\ncolor.bad=red \n"
kind: ConfigMap
metadata:
labels:
originalLabel: isHere
name: default-config
namespace: ns2

View file

@ -0,0 +1,8 @@
data:
KAFKA_ADDRESS: 192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092
ZK_ADDRESS: 192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181
kind: ConfigMap
apiVersion: v1
metadata:
name: zk-kafka-address
namespace: ns2

40
test/output/ghost.yaml Normal file
View file

@ -0,0 +1,40 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: ghost
creationTimestamp:
labels:
app: nginx_is_mutated
cli: test
isMutated: 'true'
nirmata.io/application.name: ghost
nirmata.io/component: ghost
nirmata.io/deployment.name: ghost
spec:
replicas: 1
selector:
matchLabels:
nirmata.io/application.name: ghost
nirmata.io/component: ghost
template:
metadata:
creationTimestamp:
labels:
nirmata.io/application.name: ghost
nirmata.io/component: ghost
nirmata.io/deployment.name: ghost
spec:
containers:
- name: ghost
image: nginx:latest
ports:
- containerPort: 8080
protocol: TCP
resources: {}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
revisionHistoryLimit: 5
status: {}

29
test/output/nginx.yaml Normal file
View file

@ -0,0 +1,29 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx-deployment
creationTimestamp:
labels:
app: nginx_is_mutated
cli: test
isMutated: 'true'
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
resources: {}
imagePullPolicy: Always
strategy: {}
status: {}

View file

@ -0,0 +1,13 @@
metadata:
annotations: {}
labels:
policyname: default
name: deny-all-traffic
namespace: ns2
podSelector:
matchExpressions: []
matchLabels: {}
policyTypes: []
spec:
kind: NetworkPolicy
apiVersion: extensions/v1beta1

View file

@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
creationTimestamp:
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources: {}
imagePullPolicy: Always
- name: ghost
image: ghost:latest
resources: {}
imagePullPolicy: Always
strategy: {}
status: {}

View file

@ -0,0 +1,20 @@
kind: Endpoints
apiVersion: v1
metadata:
name: test-endpoint
creationTimestamp:
labels:
label: test
subsets:
- addresses:
- ip: 192.168.10.172
ports:
- name: load-balancer-connection
port: 80
protocol: UDP
- addresses:
- ip: 192.168.10.171
ports:
- name: secure-connection
port: 9663
protocol: TCP

View file

@ -0,0 +1,8 @@
data:
DB_PASSWORD: YXBwc3dvcmQ=
DB_USER: YWJyYWthZGFicmE=
metadata:
name: mongo-creds
namespace: ns2
kind: Secret
apiVersion: v1

20
test/scenarios/cli.yaml Normal file
View file

@ -0,0 +1,20 @@
# file path relative to project root
input:
policy: examples/cli/policy_deployment.yaml
resource: examples/cli/nginx.yaml
expected:
mutation:
patched_resource: test/output/nginx.yaml
reason: Success
validation:
reason: Success
---
input:
policy: examples/cli/policy_deployment.yaml
resource: examples/cli/ghost.yaml
expected:
mutation:
patched_resource: test/output/ghost.yaml
reason: Success
validation:
reason: Success

View file

@ -0,0 +1,30 @@
# file path relative to project root
input:
policy: examples/generate/policy_basic.yaml
resource: examples/generate/namespace.yaml
load_resources:
- examples/generate/configMap_default.yaml
expected:
generation:
resources:
- test/output/cm_default_config.yaml
- test/output/sc_mongo_cred.yaml
---
input:
policy: examples/generate/policy_generate.yaml
resource: examples/generate/namespace.yaml
load_resources:
- examples/generate/configMap.yaml
expected:
generation:
resources:
- test/output/cm_copied_cm.yaml
- test/output/cm_zk-kafka-address.yaml
---
input:
policy: examples/generate/policy_networkPolicy.yaml
resource: examples/generate/namespace.yaml
expected:
generation:
resources:
- test/output/np_deny-all-traffic.yaml

View file

@ -0,0 +1,8 @@
# file path relative to project root
input:
policy: examples/mutate/overlay/policy_imagePullPolicy.yaml
resource: examples/mutate/overlay/nginx.yaml
expected:
mutation:
patched_resource: test/output/op_overlay_nginx.yaml
reason: Success

View file

@ -0,0 +1,8 @@
# file path relative to project root
input:
policy: examples/mutate/patches/policy_endpoints.yaml
resource: examples/mutate/patches/endpoints.yaml
expected:
mutation:
patched_resource: test/output/op_patches_endpoints.yaml
reason: Success