mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
Feature/e2e 575 (#1018)
* added api templates * E2E test for generate roles, rolebindings, clusterrole and clusterrolebindings * table driven e2e tests * table driven e2e tests and go fmt * removed unwanted vars * increased sleep time * removed role generation clone * increated sleep time * added rolebinding clone and retry mechanism for get resources * modified test for clone * added namespace to role * added namespace variable * added git actions job * changed build name * removed docker login * added role verbs * removed github actions job and rbac file * added clusterrole test with clone * fixed travis issue
This commit is contained in:
parent
39de46fe39
commit
6e827f912f
10 changed files with 791 additions and 342 deletions
72
.github/workflows/release.yaml
vendored
72
.github/workflows/release.yaml
vendored
|
@ -1,72 +0,0 @@
|
||||||
name: prereleaser
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
releaser:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
-
|
|
||||||
name: Unshallow
|
|
||||||
run: git fetch --prune --unshallow
|
|
||||||
-
|
|
||||||
name: Set up Go
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: 1.14
|
|
||||||
- uses: creekorful/goreportcard-action@v1.0
|
|
||||||
-
|
|
||||||
name: Run GoReleaser
|
|
||||||
uses: goreleaser/goreleaser-action@v2
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
args: release --rm-dist
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
|
||||||
|
|
||||||
- name : binary build & kustomize
|
|
||||||
run: |
|
|
||||||
make kyverno
|
|
||||||
make initContainer
|
|
||||||
|
|
||||||
-
|
|
||||||
uses: docker/build-push-action@v1
|
|
||||||
name: kyverno docker build and publish
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERIO_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERIO_PASSWORD }}
|
|
||||||
repository: "nirmata/kyverno"
|
|
||||||
tag_with_sha: true
|
|
||||||
push: true
|
|
||||||
path: cmd/kyverno/
|
|
||||||
dockerfile: cmd/kyverno/Dockerfile
|
|
||||||
|
|
||||||
-
|
|
||||||
uses: docker/build-push-action@v1
|
|
||||||
name: kyvernopre docker build and publish
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERIO_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERIO_PASSWORD }}
|
|
||||||
repository: "nirmata/kyvernopre"
|
|
||||||
tag_with_sha: true
|
|
||||||
push: true
|
|
||||||
path: cmd/initContainer/
|
|
||||||
dockerfile: cmd/initContainer/Dockerfile
|
|
||||||
|
|
||||||
- uses: J12934/helm-gh-pages-action@master
|
|
||||||
name: Run Helm Publish
|
|
||||||
with:
|
|
||||||
access-token: ${{ secrets.ACCESS_TOKEN }}
|
|
||||||
deploy-branch: gh-pages
|
|
||||||
charts-folder: charts
|
|
||||||
|
|
||||||
- name: Update new version in krew-index
|
|
||||||
uses: rajatjindal/krew-release-bot@v0.0.38
|
|
||||||
|
|
||||||
|
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -123,6 +123,12 @@ code-cov-report: $(CODE_COVERAGE_FILE_TXT)
|
||||||
go tool cover -html=coverage.txt
|
go tool cover -html=coverage.txt
|
||||||
if [ -a $(CODE_COVERAGE_FILE_HTML) ]; then open $(CODE_COVERAGE_FILE_HTML); fi;
|
if [ -a $(CODE_COVERAGE_FILE_HTML) ]; then open $(CODE_COVERAGE_FILE_HTML); fi;
|
||||||
|
|
||||||
|
# Test E2E
|
||||||
|
test-e2e:
|
||||||
|
$(eval export E2E="ok")
|
||||||
|
go test ./test/e2e/... -v
|
||||||
|
$(eval export E2E="")
|
||||||
|
|
||||||
# godownloader create downloading script for kyverno-cli
|
# godownloader create downloading script for kyverno-cli
|
||||||
godownloader:
|
godownloader:
|
||||||
godownloader .goreleaser.yml --repo nirmata/kyverno -o ./scripts/install-cli.sh --source="raw"
|
godownloader .goreleaser.yml --repo nirmata/kyverno -o ./scripts/install-cli.sh --source="raw"
|
||||||
|
|
|
@ -1,268 +0,0 @@
|
||||||
---
|
|
||||||
kind: Namespace
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: "kyverno"
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
namespace: kyverno
|
|
||||||
name: kyverno-svc
|
|
||||||
labels:
|
|
||||||
app: kyverno
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- port: 443
|
|
||||||
targetPort: 443
|
|
||||||
selector:
|
|
||||||
app: kyverno
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: kyverno-service-account
|
|
||||||
namespace: kyverno
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:policyviolations
|
|
||||||
rules:
|
|
||||||
- apiGroups: ["kyverno.io"]
|
|
||||||
resources:
|
|
||||||
- policyviolations
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: kyverno:webhook
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: kyverno:webhook
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kyverno-service-account
|
|
||||||
namespace: kyverno
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: kyverno:userinfo
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: kyverno:userinfo
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kyverno-service-account
|
|
||||||
namespace: kyverno
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: kyverno:customresources
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: kyverno:customresources
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kyverno-service-account
|
|
||||||
namespace: kyverno
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: kyverno:policycontroller
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: kyverno:policycontroller
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kyverno-service-account
|
|
||||||
namespace: kyverno
|
|
||||||
---
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
name: kyverno:generatecontroller
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: kyverno:generatecontroller
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: kyverno-service-account
|
|
||||||
namespace: kyverno
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:webhook
|
|
||||||
rules:
|
|
||||||
# Dynamic creation of webhooks, events & certs
|
|
||||||
- apiGroups:
|
|
||||||
- '*'
|
|
||||||
resources:
|
|
||||||
- events
|
|
||||||
- mutatingwebhookconfigurations
|
|
||||||
- validatingwebhookconfigurations
|
|
||||||
- certificatesigningrequests
|
|
||||||
- certificatesigningrequests/approval
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- patch
|
|
||||||
- update
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- certificates.k8s.io
|
|
||||||
resources:
|
|
||||||
- certificatesigningrequests
|
|
||||||
- certificatesigningrequests/approval
|
|
||||||
- certificatesigningrequests/status
|
|
||||||
resourceNames:
|
|
||||||
- kubernetes.io/legacy-unknown
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- update
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- certificates.k8s.io
|
|
||||||
resources:
|
|
||||||
- signers
|
|
||||||
resourceNames:
|
|
||||||
- kubernetes.io/legacy-unknown
|
|
||||||
verbs:
|
|
||||||
- approve
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:userinfo
|
|
||||||
rules:
|
|
||||||
# get the roleRef for incoming api-request user
|
|
||||||
- apiGroups:
|
|
||||||
- "*"
|
|
||||||
resources:
|
|
||||||
- roles
|
|
||||||
- clusterroles
|
|
||||||
- rolebindings
|
|
||||||
- clusterrolebindings
|
|
||||||
- configmaps
|
|
||||||
verbs:
|
|
||||||
- watch
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:customresources
|
|
||||||
rules:
|
|
||||||
# Kyverno CRs
|
|
||||||
- apiGroups:
|
|
||||||
- '*'
|
|
||||||
resources:
|
|
||||||
- clusterpolicies
|
|
||||||
- clusterpolicies/status
|
|
||||||
- clusterpolicyviolations
|
|
||||||
- clusterpolicyviolations/status
|
|
||||||
- policyviolations
|
|
||||||
- policyviolations/status
|
|
||||||
- generaterequests
|
|
||||||
- generaterequests/status
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- patch
|
|
||||||
- update
|
|
||||||
- watch
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:policycontroller
|
|
||||||
rules:
|
|
||||||
# background processing, identify all existing resources
|
|
||||||
- apiGroups:
|
|
||||||
- '*'
|
|
||||||
resources:
|
|
||||||
- '*'
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- update
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:generatecontroller
|
|
||||||
rules:
|
|
||||||
# process generate rules to generate resources
|
|
||||||
- apiGroups:
|
|
||||||
- "*"
|
|
||||||
resources:
|
|
||||||
- namespaces
|
|
||||||
- networkpolicies
|
|
||||||
- secrets
|
|
||||||
- configmaps
|
|
||||||
- resourcequotas
|
|
||||||
- limitranges
|
|
||||||
- clusterroles
|
|
||||||
- rolebindings
|
|
||||||
- clusterrolebindings
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- update
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
# dynamic watches on trigger resources for generate rules
|
|
||||||
# re-evaluate the policy if the resource is updated
|
|
||||||
- apiGroups:
|
|
||||||
- '*'
|
|
||||||
resources:
|
|
||||||
- namespaces
|
|
||||||
verbs:
|
|
||||||
- watch
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: init-config
|
|
||||||
namespace: kyverno
|
|
||||||
data:
|
|
||||||
# resource types to be skipped by kyverno policy engine
|
|
||||||
resourceFilters: "[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][*,kyverno,*][Binding,*,*][ReplicaSet,*,*]"
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:view-policyviolations
|
|
||||||
labels:
|
|
||||||
rbac.authorization.k8s.io/aggregate-to-view: "true"
|
|
||||||
rules:
|
|
||||||
- apiGroups: ["kyverno.io"]
|
|
||||||
resources:
|
|
||||||
- policyviolations
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
||||||
---
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: kyverno:view-clusterpolicyviolations
|
|
||||||
labels:
|
|
||||||
rbac.authorization.k8s.io/aggregate-to-admin: "true"
|
|
||||||
rules:
|
|
||||||
- apiGroups: ["kyverno.io"]
|
|
||||||
resources:
|
|
||||||
- clusterpolicyviolations
|
|
||||||
verbs: ["get", "list", "watch"]
|
|
2
go.mod
2
go.mod
|
@ -20,6 +20,8 @@ require (
|
||||||
github.com/julienschmidt/httprouter v1.3.0
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a
|
github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a
|
||||||
github.com/minio/minio v0.0.0-20200114012931-30922148fbb5
|
github.com/minio/minio v0.0.0-20200114012931-30922148fbb5
|
||||||
|
github.com/onsi/ginkgo v1.11.0
|
||||||
|
github.com/onsi/gomega v1.8.1
|
||||||
github.com/ory/go-acc v0.2.1 // indirect
|
github.com/ory/go-acc v0.2.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/common v0.4.1
|
github.com/prometheus/common v0.4.1
|
||||||
|
|
|
@ -133,7 +133,7 @@ func validateArray(log logr.Logger, resourceArray, patternArray []interface{}, o
|
||||||
return path, err
|
return path, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
return "", fmt.Errorf("Validate Array failed, array length mismatch, resource Array len is %d and pattern Array len is %d", len(resourceArray), len(patternArray))
|
return "", fmt.Errorf("Validate Array failed, array length mismatch, resource Array len is %d and pattern Array len is %d", len(resourceArray), len(patternArray))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ func (o *Controller) ValidatePolicyMutation(policy v1.ClusterPolicy) error {
|
||||||
newPolicy := *policy.DeepCopy()
|
newPolicy := *policy.DeepCopy()
|
||||||
newPolicy.Spec.Rules = rules
|
newPolicy.Spec.Rules = rules
|
||||||
resource, _ := o.generateEmptyResource(o.definitions[o.kindToDefinitionName[kind]]).(map[string]interface{})
|
resource, _ := o.generateEmptyResource(o.definitions[o.kindToDefinitionName[kind]]).(map[string]interface{})
|
||||||
if resource == nil || len(resource) == 0 {
|
if resource == nil || len(resource) == 0 {
|
||||||
log.Log.V(2).Info("unable to validate resource. OpenApi definition not found", "kind", kind)
|
log.Log.V(2).Info("unable to validate resource. OpenApi definition not found", "kind", kind)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
117
test/e2e/generate/config.go
Normal file
117
test/e2e/generate/config.go
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
package generate
|
||||||
|
|
||||||
|
// E2E Test Config for Role and RoleBinding
|
||||||
|
// TODO:- Clone for Role and RoleBinding
|
||||||
|
var RoleTests = []struct {
|
||||||
|
//TestName - Name of the Test
|
||||||
|
TestName string
|
||||||
|
// RoleName - Name of the Role to be Created
|
||||||
|
RoleName string
|
||||||
|
// RoleBindingName - Name of the RoleBindingName
|
||||||
|
RoleBindingName string
|
||||||
|
// ResourceNamespace - Namespace for which Role and ReleBinding are Created
|
||||||
|
ResourceNamespace string
|
||||||
|
// Clone - Set Clone Value
|
||||||
|
Clone bool
|
||||||
|
// CloneSourceRoleData - Source Role Name from which Role is Cloned
|
||||||
|
CloneSourceRoleData []byte
|
||||||
|
// CloneSourceRoleBindingData - Source RoleBinding Name from which RoleBinding is Cloned
|
||||||
|
CloneSourceRoleBindingData []byte
|
||||||
|
// CloneNamespace - Namespace where Roles are Cloned
|
||||||
|
CloneNamespace string
|
||||||
|
// Sync - Set Synchronize
|
||||||
|
Sync bool
|
||||||
|
// Data - The Yaml file of the ClusterPolicy of the ROle and RoleBinding - ([]byte{})
|
||||||
|
Data []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
TestName: "test-role-rolebinding-without-clone",
|
||||||
|
RoleName: "ns-role",
|
||||||
|
RoleBindingName: "ns-role-binding",
|
||||||
|
ResourceNamespace: "test",
|
||||||
|
Clone: false,
|
||||||
|
Sync: false,
|
||||||
|
Data: roleRoleBindingYamlWithSync,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestName: "test-role-rolebinding-withsync-without-clone",
|
||||||
|
RoleName: "ns-role",
|
||||||
|
RoleBindingName: "ns-role-binding",
|
||||||
|
ResourceNamespace: "test",
|
||||||
|
Clone: false,
|
||||||
|
Sync: true,
|
||||||
|
Data: roleRoleBindingYamlWithSync,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestName: "test-role-rolebinding-with-clone",
|
||||||
|
RoleName: "ns-role",
|
||||||
|
RoleBindingName: "ns-role-binding",
|
||||||
|
ResourceNamespace: "test",
|
||||||
|
Clone: true,
|
||||||
|
CloneSourceRoleData: sourceRoleYaml,
|
||||||
|
CloneSourceRoleBindingData: sourceRoleBindingYaml,
|
||||||
|
CloneNamespace: "default",
|
||||||
|
Sync: false,
|
||||||
|
Data: roleRoleBindingYamlWithClone,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// E2E Test Config for ClusterRole and ClusterRoleBinding
|
||||||
|
var ClusterRoleTests = []struct {
|
||||||
|
//TestName - Name of the Test
|
||||||
|
TestName string
|
||||||
|
// ClusterRoleName - Name of the ClusterRole to be Created
|
||||||
|
ClusterRoleName string
|
||||||
|
// ClusterRoleBindingName - Name of the ClusterRoleBinding
|
||||||
|
ClusterRoleBindingName string
|
||||||
|
// ResourceNamespace - Namespace for which Resources are Created
|
||||||
|
ResourceNamespace string
|
||||||
|
// Clone - Set Clone Value
|
||||||
|
Clone bool
|
||||||
|
// CloneClusterRoleName
|
||||||
|
ClonerClusterRoleName string
|
||||||
|
// CloneClusterRoleBindingName
|
||||||
|
ClonerClusterRoleBindingName string
|
||||||
|
// CloneSourceRoleData - Source ClusterRole Name from which ClusterRole is Cloned
|
||||||
|
CloneSourceClusterRoleData []byte
|
||||||
|
// CloneSourceRoleBindingData - Source ClusterRoleBinding Name from which ClusterRoleBinding is Cloned
|
||||||
|
CloneSourceClusterRoleBindingData []byte
|
||||||
|
// CloneNamespace - Namespace where Roles are Cloned
|
||||||
|
CloneNamespace string
|
||||||
|
// Sync - Set Synchronize
|
||||||
|
Sync bool
|
||||||
|
// Data - The Yaml file of the ClusterPolicy of the ClusterRole and ClusterRoleBinding - ([]byte{})
|
||||||
|
Data []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
TestName: "test-clusterrole-clusterrolebinding-without-clone",
|
||||||
|
ClusterRoleName: "ns-cluster-role",
|
||||||
|
ClusterRoleBindingName: "ns-cluster-role-binding",
|
||||||
|
ResourceNamespace: "test",
|
||||||
|
Clone: false,
|
||||||
|
Sync: false,
|
||||||
|
Data: genClusterRoleYamlWithSync,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestName: "test-clusterrole-clusterrolebinding-with-sync-without-clone",
|
||||||
|
ClusterRoleName: "ns-cluster-role",
|
||||||
|
ClusterRoleBindingName: "ns-cluster-role-binding",
|
||||||
|
ResourceNamespace: "test",
|
||||||
|
Clone: false,
|
||||||
|
Sync: true,
|
||||||
|
Data: genClusterRoleYamlWithSync,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
TestName: "test-clusterrole-clusterrolebinding-with-sync-with-clone",
|
||||||
|
ClusterRoleName: "ns-cluster-role",
|
||||||
|
ClusterRoleBindingName: "ns-cluster-role-binding",
|
||||||
|
ResourceNamespace: "test",
|
||||||
|
Clone: true,
|
||||||
|
ClonerClusterRoleName: "base-cluster-role",
|
||||||
|
ClonerClusterRoleBindingName: "base-cluster-role-binding",
|
||||||
|
CloneSourceClusterRoleData: baseClusterRoleData,
|
||||||
|
CloneSourceClusterRoleBindingData: baseClusterRoleBindingData,
|
||||||
|
Sync: false,
|
||||||
|
Data: genClusterRoleYamlWithSync,
|
||||||
|
},
|
||||||
|
}
|
294
test/e2e/generate/generate_test.go
Normal file
294
test/e2e/generate/generate_test.go
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
package generate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Cluster Polict GVR
|
||||||
|
clPolGVR = GetGVR("kyverno.io", "v1", "clusterpolicies")
|
||||||
|
// Namespace GVR
|
||||||
|
nsGVR = GetGVR("", "v1", "namespaces")
|
||||||
|
// ClusterRole GVR
|
||||||
|
crGVR = GetGVR("rbac.authorization.k8s.io", "v1", "clusterroles")
|
||||||
|
// ClusterRoleBinding GVR
|
||||||
|
crbGVR = GetGVR("rbac.authorization.k8s.io", "v1", "clusterrolebindings")
|
||||||
|
// Role GVR
|
||||||
|
rGVR = GetGVR("rbac.authorization.k8s.io", "v1", "roles")
|
||||||
|
// RoleBinding GVR
|
||||||
|
rbGVR = GetGVR("rbac.authorization.k8s.io", "v1", "rolebindings")
|
||||||
|
|
||||||
|
// ClusterPolicy Namespace
|
||||||
|
clPolNS = ""
|
||||||
|
// Namespace Name
|
||||||
|
// Hardcoded in YAML Definition
|
||||||
|
nspace = "test"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_ClusterRole_ClusterRoleBinding_Sets(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
if os.Getenv("E2E") == "" {
|
||||||
|
t.Skip("Skipping E2E Test")
|
||||||
|
}
|
||||||
|
// Generate E2E Client ==================
|
||||||
|
e2eClient, err := NewE2EClient()
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
// ======================================
|
||||||
|
|
||||||
|
// ====== Range Over ClusterRoleTests ==================
|
||||||
|
for _, tests := range ClusterRoleTests {
|
||||||
|
By(fmt.Sprintf("Test to generate ClusterRole and ClusterRoleBinding : %s", tests.TestName))
|
||||||
|
By(fmt.Sprintf("synchronize = %v\t clone = %v", tests.Sync, tests.Clone))
|
||||||
|
|
||||||
|
// ======= CleanUp Resources =====
|
||||||
|
By(fmt.Sprintf("Cleaning Cluster Policies"))
|
||||||
|
e2eClient.CleanClusterPolicies(clPolGVR)
|
||||||
|
|
||||||
|
// If Clone is true Clear Source Resource and Recreate
|
||||||
|
if tests.Clone {
|
||||||
|
By("Clone = true, Deleting Source ClusterRole and ClusterRoleBinding")
|
||||||
|
// Delete ClusterRole to be cloned
|
||||||
|
e2eClient.DeleteClusteredResource(crGVR, tests.ClonerClusterRoleName)
|
||||||
|
// Delete ClusterRoleBinding to be cloned
|
||||||
|
e2eClient.DeleteClusteredResource(crbGVR, tests.ClonerClusterRoleBindingName)
|
||||||
|
}
|
||||||
|
// ====================================
|
||||||
|
|
||||||
|
// Clear Namespace
|
||||||
|
By(fmt.Sprintf("Deleting Namespace : %s\n", tests.ResourceNamespace))
|
||||||
|
e2eClient.DeleteClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
|
||||||
|
// Wait Till Deletion of Namespace
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("Deleting Namespace")
|
||||||
|
})
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
// ======== Create ClusterRole Policy =============
|
||||||
|
By(fmt.Sprintf("Creating Generate Role Policy in %s", clPolNS))
|
||||||
|
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.Data)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// == If Clone is true Create Source Resources ======
|
||||||
|
if tests.Clone {
|
||||||
|
By(fmt.Sprintf("Clone = true, Creating Cloner Resources in Namespace : %s", tests.CloneNamespace))
|
||||||
|
// Create ClusterRole to be cloned
|
||||||
|
_, err := e2eClient.CreateClusteredResourceYaml(crGVR, tests.CloneSourceClusterRoleData)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
// Create ClusterRoleBinding to be cloned
|
||||||
|
_, err = e2eClient.CreateClusteredResourceYaml(crbGVR, tests.CloneSourceClusterRoleBindingData)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================================================
|
||||||
|
|
||||||
|
// ======= Create Namespace ==================
|
||||||
|
By(fmt.Sprintf("Creating Namespace which triggers generate %s \n", clPolNS))
|
||||||
|
_, err = e2eClient.CreateClusteredResourceYaml(nsGVR, namespaceYaml)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Wait Till Creation of Namespace
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
// ===========================================
|
||||||
|
|
||||||
|
// ======== Verify ClusterRole Creation =====
|
||||||
|
By("Verifying ClusterRole")
|
||||||
|
// Wait Till Creation of ClusterRole
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetClusteredResource(crGVR, tests.ClusterRoleName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
rRes, err := e2eClient.GetClusteredResource(crGVR, tests.ClusterRoleName)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(rRes.GetName()).To(Equal(tests.ClusterRoleName))
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// ======= Verify ClusterRoleBinding Creation ========
|
||||||
|
By("Verifying ClusterRoleBinding")
|
||||||
|
rbRes, err := e2eClient.GetClusteredResource(crbGVR, tests.ClusterRoleBindingName)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(rbRes.GetName()).To(Equal(tests.ClusterRoleBindingName))
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// If Sync=true, Verify that an Error will occour on deletion of created resources
|
||||||
|
if tests.Sync {
|
||||||
|
// Delete generated ClusterRoleBinding and It'll Fail
|
||||||
|
err = e2eClient.DeleteClusteredResource(crbGVR, tests.ClusterRoleBindingName)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
// Delete generated ClusterRole and It'll Fail
|
||||||
|
err = e2eClient.DeleteClusteredResource(crGVR, tests.ClusterRoleName)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======= CleanUp Resources =====
|
||||||
|
e2eClient.CleanClusterPolicies(clPolGVR)
|
||||||
|
// Clear Namespace
|
||||||
|
e2eClient.DeleteClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
// Wait Till Deletion of Namespace
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("Deleting Namespace")
|
||||||
|
})
|
||||||
|
By(fmt.Sprintf("Test %s Completed \n\n\n", tests.TestName))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Role_RoleBinding_Sets(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
if os.Getenv("E2E") == "" {
|
||||||
|
t.Skip("Skipping E2E Test")
|
||||||
|
}
|
||||||
|
// Generate E2E Client ==================
|
||||||
|
e2eClient, err := NewE2EClient()
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
// ======================================
|
||||||
|
|
||||||
|
// ====== Range Over RuleTest ==================
|
||||||
|
for _, tests := range RoleTests {
|
||||||
|
By(fmt.Sprintf("Test to generate Role and RoleBinding : %s", tests.TestName))
|
||||||
|
By(fmt.Sprintf("synchronize = %v\t clone = %v", tests.Sync, tests.Clone))
|
||||||
|
|
||||||
|
// ======= CleanUp Resources =====
|
||||||
|
By(fmt.Sprintf("Cleaning Cluster Policies"))
|
||||||
|
e2eClient.CleanClusterPolicies(clPolGVR)
|
||||||
|
// Clear Namespace
|
||||||
|
By(fmt.Sprintf("Deleting Namespace : %s", tests.ResourceNamespace))
|
||||||
|
e2eClient.DeleteClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
// If Clone is true Clear Source Resource and Recreate
|
||||||
|
if tests.Clone {
|
||||||
|
By(fmt.Sprintf("Clone = true, Deleting Source Role and RoleBinding from Clone Namespace : %s", tests.CloneNamespace))
|
||||||
|
// Delete Role to be cloned
|
||||||
|
e2eClient.DeleteNamespacedResource(rGVR, tests.CloneNamespace, tests.RoleName)
|
||||||
|
// Delete RoleBinding to be cloned
|
||||||
|
e2eClient.DeleteNamespacedResource(rbGVR, tests.CloneNamespace, tests.RoleBindingName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait Till Deletion of Namespace
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("Deleting Namespace")
|
||||||
|
})
|
||||||
|
// ====================================
|
||||||
|
|
||||||
|
// ======== Create Role Policy =============
|
||||||
|
By(fmt.Sprintf("\nCreating Generate Role Policy in %s", clPolNS))
|
||||||
|
_, err = e2eClient.CreateNamespacedResourceYaml(clPolGVR, clPolNS, tests.Data)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// === If Clone is true Create Source Resources ==
|
||||||
|
if tests.Clone {
|
||||||
|
By(fmt.Sprintf("Clone = true, Creating Cloner Resources in Namespace : %s", tests.CloneNamespace))
|
||||||
|
_, err := e2eClient.CreateNamespacedResourceYaml(rGVR, tests.CloneNamespace, tests.CloneSourceRoleData)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
_, err = e2eClient.CreateNamespacedResourceYaml(rbGVR, tests.CloneNamespace, tests.CloneSourceRoleBindingData)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
// ================================================
|
||||||
|
|
||||||
|
// ======= Create Namespace ==================
|
||||||
|
By(fmt.Sprintf("Creating Namespace which triggers generate %s", clPolNS))
|
||||||
|
_, err = e2eClient.CreateClusteredResourceYaml(nsGVR, namespaceYaml)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Wait Till Creation of Namespace
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
// ===========================================
|
||||||
|
|
||||||
|
// ======== Verify Role Creation =====
|
||||||
|
By(fmt.Sprintf("Verifying Role in the Namespace : %s", tests.ResourceNamespace))
|
||||||
|
// Wait Till Creation of Role
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetNamespacedResource(rGVR, tests.ResourceNamespace, tests.RoleName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
rRes, err := e2eClient.GetNamespacedResource(rGVR, tests.ResourceNamespace, tests.RoleName)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(rRes.GetName()).To(Equal(tests.RoleName))
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// ======= Verify RoleBinding Creation ========
|
||||||
|
By(fmt.Sprintf("Verifying RoleBinding in the Namespace : %s", tests.ResourceNamespace))
|
||||||
|
rbRes, err := e2eClient.GetNamespacedResource(rbGVR, tests.ResourceNamespace, tests.RoleBindingName)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(rbRes.GetName()).To(Equal(tests.RoleBindingName))
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// If Sync=true, Verify that an Error will occour on deletion of created resources
|
||||||
|
if tests.Sync {
|
||||||
|
|
||||||
|
// Delete generated RoleBinding and It'll Fail
|
||||||
|
By(fmt.Sprintf("Sync : Delete RoleBinding as Namespace %s", tests.ResourceNamespace))
|
||||||
|
err = e2eClient.DeleteNamespacedResource(rbGVR, tests.ResourceNamespace, tests.RoleBindingName)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
|
||||||
|
// Delete generated Role and It'll Fail
|
||||||
|
By(fmt.Sprintf("Sync : Delete Role as Namespace %s", tests.ResourceNamespace))
|
||||||
|
err = e2eClient.DeleteNamespacedResource(rGVR, tests.ResourceNamespace, tests.RoleName)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======= CleanUp Resources =====
|
||||||
|
e2eClient.CleanClusterPolicies(clPolGVR)
|
||||||
|
|
||||||
|
// === If Clone is true Delete Source Resources ==
|
||||||
|
if tests.Clone {
|
||||||
|
By(fmt.Sprintf("Clone = true, Deleting Cloner Resources in Namespace : %s", tests.CloneNamespace))
|
||||||
|
e2eClient.DeleteNamespacedResource(rGVR, tests.CloneNamespace, tests.RoleName)
|
||||||
|
e2eClient.DeleteNamespacedResource(rbGVR, tests.CloneNamespace, tests.RoleBindingName)
|
||||||
|
}
|
||||||
|
// ================================================
|
||||||
|
|
||||||
|
// Clear Namespace
|
||||||
|
e2eClient.DeleteClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
// Wait Till Deletion of Namespace
|
||||||
|
GetWithRetry(time.Duration(1), 15, func() error {
|
||||||
|
_, err := e2eClient.GetClusteredResource(nsGVR, tests.ResourceNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("Deleting Namespace")
|
||||||
|
})
|
||||||
|
// ====================================
|
||||||
|
|
||||||
|
By(fmt.Sprintf("Test %s Completed \n\n\n", tests.TestName))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
247
test/e2e/generate/resources.go
Normal file
247
test/e2e/generate/resources.go
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
package generate
|
||||||
|
|
||||||
|
// Namespace Description
|
||||||
|
var namespaceYaml = []byte(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: test
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Cluster Policy to generate Role and RoleBinding with synchronize=true
|
||||||
|
var roleRoleBindingYamlWithSync = []byte(`
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: "gen-role-policy"
|
||||||
|
spec:
|
||||||
|
background: false
|
||||||
|
rules:
|
||||||
|
- name: "gen-role"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: Role
|
||||||
|
name: "ns-role"
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize: true
|
||||||
|
data:
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "watch", "list"]
|
||||||
|
- name: "gen-role-binding"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: RoleBinding
|
||||||
|
name: "ns-role-binding"
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize: true
|
||||||
|
data:
|
||||||
|
subjects:
|
||||||
|
- apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: User
|
||||||
|
name: minikube-user
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: ns-role
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Cluster Policy to generate Role and RoleBinding with Clone
|
||||||
|
var roleRoleBindingYamlWithClone = []byte(`
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: "gen-role-policy"
|
||||||
|
spec:
|
||||||
|
background: false
|
||||||
|
rules:
|
||||||
|
- name: "gen-role"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: Role
|
||||||
|
name: "ns-role"
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize: true
|
||||||
|
clone:
|
||||||
|
kind: Role
|
||||||
|
name: "ns-role"
|
||||||
|
namespace: "default"
|
||||||
|
- name: "gen-role-binding"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: RoleBinding
|
||||||
|
name: "ns-role-binding"
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize: true
|
||||||
|
clone:
|
||||||
|
kind: RoleBinding
|
||||||
|
name: "ns-role-binding"
|
||||||
|
namespace: default
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Source Role from which ROle is Cloned by generate
|
||||||
|
var sourceRoleYaml = []byte(`
|
||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
namespace: default
|
||||||
|
name: ns-role
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["*"]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: ["get", "watch", "list", "delete", "create"]
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Source RoleBinding from which RoleBinding is Cloned by generate
|
||||||
|
var sourceRoleBindingYaml = []byte(`
|
||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: ns-role-binding
|
||||||
|
namespace: default
|
||||||
|
subjects:
|
||||||
|
- apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: User
|
||||||
|
name: minikube-user
|
||||||
|
roleRef:
|
||||||
|
kind: Role
|
||||||
|
name: ns-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
`)
|
||||||
|
|
||||||
|
// ClusterPolicy to generate ClusterRole and ClusterRoleBinding with synchronize = true
|
||||||
|
var genClusterRoleYamlWithSync = []byte(`
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: "gen-cluster-policy"
|
||||||
|
spec:
|
||||||
|
background: false
|
||||||
|
rules:
|
||||||
|
- name: "gen-cluster-role"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: ns-cluster-role
|
||||||
|
synchronize: true
|
||||||
|
data:
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: ["pods"]
|
||||||
|
verbs: ["get", "watch", "list"]
|
||||||
|
- name: "gen-cluster-role-binding"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
name: ns-cluster-role-binding
|
||||||
|
synchronize: true
|
||||||
|
data:
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: ns-cluster-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: "kyverno-service-account"
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
// ClusterPolicy to generate ClusterRole and ClusterRoleBinding with clone = true
|
||||||
|
var genClusterRoleYamlWithClone = []byte(`
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: "gen-cluster-policy"
|
||||||
|
spec:
|
||||||
|
background: false
|
||||||
|
rules:
|
||||||
|
- name: "gen-cluster-role"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: ns-cluster-role
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize: true
|
||||||
|
clone:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: base-cluster-role
|
||||||
|
namespace: default
|
||||||
|
- name: "gen-cluster-role-binding"
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- Namespace
|
||||||
|
generate:
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
name: ns-cluster-role-binding
|
||||||
|
namespace: "{{request.object.metadata.name}}"
|
||||||
|
synchronize: true
|
||||||
|
clone:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: base-cluster-role-binding
|
||||||
|
namespace: default
|
||||||
|
`)
|
||||||
|
|
||||||
|
var baseClusterRoleData = []byte(`
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: base-cluster-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- "*"
|
||||||
|
resources:
|
||||||
|
- namespaces
|
||||||
|
- networkpolicies
|
||||||
|
- secrets
|
||||||
|
- configmaps
|
||||||
|
- resourcequotas
|
||||||
|
- limitranges
|
||||||
|
- roles
|
||||||
|
- clusterroles
|
||||||
|
- rolebindings
|
||||||
|
- clusterrolebindings
|
||||||
|
verbs:
|
||||||
|
- create # generate new resources
|
||||||
|
- get # check the contents of exiting resources
|
||||||
|
- update # update existing resource, if required configuration defined in policy is not present
|
||||||
|
- delete # clean-up, if the generate trigger resource is deleted
|
||||||
|
`)
|
||||||
|
|
||||||
|
var baseClusterRoleBindingData = []byte(`
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: base-cluster-role-binding
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: base-cluster-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kyverno-service-account
|
||||||
|
namespace: kyverno
|
||||||
|
`)
|
123
test/e2e/generate/utils.go
Normal file
123
test/e2e/generate/utils.go
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
package generate
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"os"
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type E2EClient struct {
|
||||||
|
Client dynamic.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewE2EClient() (*E2EClient, error) {
|
||||||
|
kubeconfig := os.Getenv("KUBECONFIG")
|
||||||
|
if kubeconfig == "" {
|
||||||
|
kubeconfig = os.Getenv("HOME") + "/.kube/config"
|
||||||
|
}
|
||||||
|
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
e2eClient := new(E2EClient)
|
||||||
|
dClient, err := dynamic.NewForConfig(config)
|
||||||
|
e2eClient.Client = dClient
|
||||||
|
return e2eClient, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGVR :- gets GroupVersionResource for dynamic client
|
||||||
|
func GetGVR(group, version, resource string) schema.GroupVersionResource {
|
||||||
|
return schema.GroupVersionResource{Group: group, Version: version, Resource: resource}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanClusterPolicies ;- Deletes all the cluster policies
|
||||||
|
func (e2e *E2EClient) CleanClusterPolicies(gvr schema.GroupVersionResource) error {
|
||||||
|
namespace := ""
|
||||||
|
res, err := e2e.ListNamespacedResources(gvr, namespace)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, r := range res.Items {
|
||||||
|
err = e2e.DeleteNamespacedResource(gvr, namespace, r.GetName())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNamespacedResource ...
|
||||||
|
func (e2e *E2EClient) GetNamespacedResource(gvr schema.GroupVersionResource, namespace, name string) (*unstructured.Unstructured, error) {
|
||||||
|
return e2e.Client.Resource(gvr).Namespace(namespace).Get(name, metav1.GetOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetClusterResource ...
|
||||||
|
func (e2e *E2EClient) GetClusteredResource(gvr schema.GroupVersionResource, name string) (*unstructured.Unstructured, error) {
|
||||||
|
return e2e.Client.Resource(gvr).Get(name, metav1.GetOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWithRetry :- Retry Operation till the end of retry or until it is Passed, retryCount is the Wait duration after each retry,
|
||||||
|
func GetWithRetry(sleepInterval time.Duration, retryCount int, retryFunc func() error) error {
|
||||||
|
var err error
|
||||||
|
for i := 0; i < retryCount; i++ {
|
||||||
|
err = retryFunc()
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(sleepInterval * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNamespacedResource ...
|
||||||
|
func (e2e *E2EClient) DeleteNamespacedResource(gvr schema.GroupVersionResource, namespace, name string) error {
|
||||||
|
return e2e.Client.Resource(gvr).Namespace(namespace).Delete(name, &metav1.DeleteOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteClusterResource ...
|
||||||
|
func (e2e *E2EClient) DeleteClusteredResource(gvr schema.GroupVersionResource, name string) error {
|
||||||
|
return e2e.Client.Resource(gvr).Delete(name, &metav1.DeleteOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNamespacedResource ...
|
||||||
|
func (e2e *E2EClient) CreateNamespacedResource(gvr schema.GroupVersionResource, namespace string, resourceData *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||||
|
return e2e.Client.Resource(gvr).Namespace(namespace).Create(resourceData, metav1.CreateOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateClusteredResource ...
|
||||||
|
func (e2e *E2EClient) CreateClusteredResource(gvr schema.GroupVersionResource, resourceData *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||||
|
return e2e.Client.Resource(gvr).Create(resourceData, metav1.CreateOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNamespacedResources ...
|
||||||
|
func (e2e *E2EClient) ListNamespacedResources(gvr schema.GroupVersionResource, namespace string) (*unstructured.UnstructuredList, error) {
|
||||||
|
return e2e.Client.Resource(gvr).Namespace(namespace).List(metav1.ListOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNamespacedResource creates namespaced resources like Pods, Services, Deployments etc
|
||||||
|
func (e2e *E2EClient) CreateNamespacedResourceYaml(gvr schema.GroupVersionResource, namespace string, resourceData []byte) (*unstructured.Unstructured, error) {
|
||||||
|
resource := unstructured.Unstructured{}
|
||||||
|
err := yaml.Unmarshal(resourceData, &resource)
|
||||||
|
// fmt.Println(resource)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result, err := e2e.Client.Resource(gvr).Namespace(namespace).Create(&resource, metav1.CreateOptions{})
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateClusteredResource creates cluster resources from YAML like Namespace, ClusterRole, ClusterRoleBinding etc ...
|
||||||
|
func (e2e *E2EClient) CreateClusteredResourceYaml(gvr schema.GroupVersionResource, resourceData []byte) (*unstructured.Unstructured, error) {
|
||||||
|
resource := unstructured.Unstructured{}
|
||||||
|
err := yaml.Unmarshal(resourceData, &resource)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result, err := e2e.CreateClusteredResource(gvr, &resource)
|
||||||
|
return result, err
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue