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
|
||||
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:
|
||||
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/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a
|
||||
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/pkg/errors v0.9.1
|
||||
github.com/prometheus/common v0.4.1
|
||||
|
|
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