1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

generate resources

This commit is contained in:
shivdudhani 2019-06-14 14:51:06 -07:00
parent b5782d25d9
commit 0089eb348e
9 changed files with 178 additions and 41 deletions

View file

@ -1,7 +0,0 @@
kind: Namespace
apiVersion: v1
metadata:
name: "ns2"
labels:
LabelForSelector : "namespace2"

View file

@ -1,7 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: game-config
name: config-template
namespace: default
labels:
originalLabel : isHere

View file

@ -2,28 +2,39 @@
policy: basic-policy
resource: ns2
initResources:
- default/config-template
# expected
mutation:
reason: Success
validation:
reason: Success
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
mutation:
reason: Success
validation:
reason: Failed
generation:
resource:
- name: copied-cm
namespace: ns2
kind: ConfigMap
- name: zk-kafka-address
namespace: ns2
kind: ConfigMap
---
# input
policy: default
resource: ns2
initResources:
# expected
mutation:
reason: Success
validation:
reason: Failed
generation:
resource:
- name: deny-all-traffic
namespace: ns2
kind: NetworkPolicy

View file

@ -10,6 +10,7 @@ import (
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"
"k8s.io/sample-controller/pkg/signals"
)
@ -78,8 +79,10 @@ func (f *fixture) setupFixture() {
if err != nil {
f.t.Fatal(err)
}
regresource := map[string]string{"kyverno.io/v1alpha1": "policys"}
fclient.SetDiscovery(client.NewFakeDiscoveryClient(regresource))
regResources := []schema.GroupVersionResource{
schema.GroupVersionResource{Group: "kyverno.io/", Version: "v1alpha1", Resource: "policys"}}
fclient.SetDiscovery(client.NewFakeDiscoveryClient(regResources))
}
func newPolicy(name string) *types.Policy {

View file

@ -9,6 +9,7 @@ import (
meta "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"
)
// GetResource
@ -43,10 +44,12 @@ func newUnstructuredWithSpec(apiVersion, kind, namespace, name string, spec map[
func TestClient(t *testing.T) {
scheme := runtime.NewScheme()
// init groupversion
regresource := map[string]string{"group/version": "thekinds",
"group2/version": "thekinds",
"v1": "namespaces",
"apps/v1": "deployments"}
regResource := []schema.GroupVersionResource{
schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"},
schema.GroupVersionResource{Group: "group2", Version: "version", Resource: "thekinds"},
schema.GroupVersionResource{Group: "", Version: "v1", Resource: "namespaces"},
schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
}
// init resources
objects := []runtime.Object{newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
newUnstructured("group2/version", "TheKind", "ns-foo", "name2-foo"),
@ -63,7 +66,7 @@ func TestClient(t *testing.T) {
}
// set discovery Client
client.SetDiscovery(NewFakeDiscoveryClient(regresource))
client.SetDiscovery(NewFakeDiscoveryClient(regResource))
// Get Resource
res, err := client.GetResource("thekinds", "ns-foo", "name-foo")
if err != nil {

View file

@ -36,16 +36,21 @@ func NewMockClient(scheme *runtime.Scheme, objects ...runtime.Object) (*Client,
}
// NewFakeDiscoveryClient returns a fakediscovery client
func NewFakeDiscoveryClient(regResources map[string]string) *fakeDiscoveryClient {
registeredResources := make([]schema.GroupVersionResource, len(regResources))
for groupVersion, resource := range regResources {
gv, err := schema.ParseGroupVersion(groupVersion)
if err != nil {
continue
}
registeredResources = append(registeredResources, gv.WithResource(resource))
func NewFakeDiscoveryClient(registeredResouces []schema.GroupVersionResource) *fakeDiscoveryClient {
// Load some-preregistd resources
res := []schema.GroupVersionResource{
schema.GroupVersionResource{Version: "v1", Resource: "configmaps"},
schema.GroupVersionResource{Version: "v1", Resource: "endpoints"},
schema.GroupVersionResource{Version: "v1", Resource: "namespaces"},
schema.GroupVersionResource{Version: "v1", Resource: "resourcequotas"},
schema.GroupVersionResource{Version: "v1", Resource: "secrets"},
schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"},
schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "daemonsets"},
schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "statefulsets"},
}
return &fakeDiscoveryClient{registeredResouces: registeredResources}
registeredResouces = append(registeredResouces, res...)
return &fakeDiscoveryClient{registeredResouces: registeredResouces}
}
type fakeDiscoveryClient struct {

View file

@ -9,8 +9,14 @@ import (
"github.com/golang/glog"
policytypes "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
dclient "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/result"
"gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
kscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func NewTestBundle(path string) *testBundle {
@ -143,11 +149,57 @@ type testBundle struct {
scenarios []*tScenario
}
func (tb *testBundle) createClient(t *testing.T, resources []string) *dclient.Client {
scheme := runtime.NewScheme()
objects := []runtime.Object{}
// registered group versions
regResources := []schema.GroupVersionResource{}
for _, resource := range resources {
// get resources
r, ok := tb.resources[resource]
if !ok {
glog.Warningf("Resource %s not found", resource)
continue
}
// get group version resource
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)
if err != nil {
glog.Warning("Unable to deocde")
continue
}
// create unstructured
rdata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&obj)
if err != nil {
fmt.Println(err)
continue
}
unstr := unstructured.Unstructured{Object: rdata}
objects = append(objects, &unstr)
}
// new mock client
// Mock Client
c, err := dclient.NewMockClient(scheme, objects...)
if err != nil {
t.Fatal(err)
}
// set discovery Client
c.SetDiscovery(dclient.NewFakeDiscoveryClient(regResources))
return c
}
func (tb *testBundle) run(t *testing.T, testingapplyTest IApplyTest) {
glog.Infof("Start: test on test bundles %s", tb.path)
// run each scenario
for _, ts := range tb.scenarios {
fmt.Println(tb.path)
// TODO create client only for generate
// If there are init resources defined then load them
c := tb.createClient(t, ts.InitResources)
// get policy
p, ok := tb.policies[ts.Policy]
if !ok {
@ -161,17 +213,42 @@ func (tb *testBundle) run(t *testing.T, testingapplyTest IApplyTest) {
continue
}
// TODO: handle generate
mPatchedResource, mResult, vResult, err := testingapplyTest.applyPolicy(p, r, nil)
if ts.Generation != nil {
// assuming its namespaces creation
decode := kscheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(r.rawResource), nil, nil)
_, err = c.CreateResource(getResourceFromKind(r.gvk.Kind), "", obj)
if err != nil {
t.Fatalf("error while creating namespace %s", ts.Resource)
}
}
mPatchedResource, mResult, vResult, err := testingapplyTest.applyPolicy(p, r, c)
if err != nil {
t.Fatal(err)
}
// check the expected scenario
tb.checkMutationResult(t, ts.Mutation, mPatchedResource, mResult)
tb.checkValidationResult(t, ts.Validation, vResult)
tb.checkGeneration(t, ts.Generation, c)
}
glog.Infof("Done: test on test bundles %s", tb.path)
}
func (tb *testBundle) checkGeneration(t *testing.T, expect *tGeneration, c *dclient.Client) {
if expect == nil {
glog.Info("No Generatin check defined")
return
}
// iterate throught the expected resources and check if the client has them
for _, r := range expect.Resources {
_, err := c.GetResource(getResourceFromKind(r.Kind), r.Namespace, r.Name)
if err != nil {
t.Errorf("Resource %s/%s of kind %s not found", r.Namespace, r.Name, r.Kind)
}
}
}
func (tb *testBundle) checkValidationResult(t *testing.T, expect *tValidation, vResult result.Result) {
if expect == nil {
glog.Info("No Validation check defined")

View file

@ -28,7 +28,7 @@ func TestExamples(t *testing.T) {
// "/Users/shiv/nirmata/code/go/src/github.com/nirmata/kyverno/examples/cli",
// }
folders := []string{
"/Users/shiv/nirmata/code/go/src/github.com/nirmata/kyverno/examples",
"/Users/shiv/nirmata/code/go/src/github.com/nirmata/kyverno/examples/generate",
}
for _, folder := range folders {
runTest(t, folder)

View file

@ -114,6 +114,24 @@ func extractResource(resource string) (map[string]*resourceInfo, error) {
return resources, nil
}
func ParseApiVersionFromObject(bytes []byte) string {
var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON)
if apiVersion, ok := objectJSON["apiVersion"].(string); ok {
return apiVersion
}
return ""
}
func ParseKindFromObject(bytes []byte) string {
var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON)
if kind, ok := objectJSON["kind"].(string); ok {
return kind
}
return ""
}
//ParseNameFromObject extracts resource name from JSON obj
func ParseNameFromObject(bytes []byte) string {
var objectJSON map[string]interface{}
@ -164,8 +182,8 @@ func (tp *testPolicy) applyPolicy(policy *policytypes.Policy, resource *resource
vResult = engine.Validate(*policy, patchedResource, *resource.gvk)
}
// Generate
if client == nil {
glog.Warning("Client is required to test generate")
if client != nil {
engine.Generate(client, *policy, resource.rawResource, *resource.gvk)
}
// transform the patched Resource into resource Info
@ -181,6 +199,17 @@ type tScenario struct {
InitResources []string `yaml:"initResources,omitempty"`
Mutation *tMutation `yaml:"mutation,omitempty"`
Validation *tValidation `yaml:"validation,omitempty"`
Generation *tGeneration `yaml:"generation,omitempty"`
}
type tGeneration struct {
Resources []tResource `yaml:"resource"`
}
type tResource struct {
Name string `yaml:"name"`
Namespace string `yaml:"namespace,omitempty"`
Kind string `yaml:"kind"`
}
type tValidation struct {
@ -263,3 +292,19 @@ func getYAMLfiles(path string) (yamls []string) {
}
return yamls
}
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 ""
}