mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
feat: enhance global context (#9710)
* feat(globalcontext): add event handling Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * feat(globalcontext): handle cache sync error Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * feat(globalcontext): ensure api is called during init Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * design(events): decouple events from policies a bit Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * feat(globalcontext): use status Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): make status optional Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): status update Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): codegen Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): delete yaml annotations Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): fix status in tests Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcotext): update enqueue func Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): error Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): rbac Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): retry logic Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): unknown api call in test Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * bump Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix: set unique name for each testing resource Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: update readme Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: log msg Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: add delays Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix: delay gctce creation Signed-off-by: ShutingZhao <shuting@nirmata.com> * debug: check Kyverno status Signed-off-by: ShutingZhao <shuting@nirmata.com> * debug: update chainsaw config Signed-off-by: ShutingZhao <shuting@nirmata.com> * debug: revert chainsaw config Signed-off-by: ShutingZhao <shuting@nirmata.com> * test(globalcontext): print actual status Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): add necessary delays and check status before applying Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * test(globalcontext): long refreshInterval Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * debug: log success Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * debug: print informer data Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): use client instead of informer Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * debug: print status after update Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * debug: print ResourceVersion Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * debug: remove gcecontroller from other controllers Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): update status only once Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore: remove excess logs Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): add store to cleanup controller Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> --------- Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> Signed-off-by: ShutingZhao <shuting@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com> Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
7a93dcdbc9
commit
2b2587469d
62 changed files with 417 additions and 155 deletions
api/kyverno/v2alpha1
charts/kyverno
charts/crds/templates/kyverno.io
templates
admission-controller
background-controller
cleanup-controller
reports-controller
cmd
config
pkg
controllers
event
globalcontext
validation/policy
webhooks/policy
test/conformance/chainsaw/globalcontext
apicall-correct
chainsaw-test.yamlclusterpolicy-ready.yamlclusterpolicy.yamlgctxentry.yamlmain-deployment.yamlnamespace.yamlnew-deployment-exists.yamlnew-deployment.yaml
apicall-failed
gctxentry-not-exist
README.mdchainsaw-test.yamlclusterpolicy.yamlgctxentry.yamlmain-deployment.yamlnamespace.yamlnew-deployment.yaml
not-ready
README.mdchainsaw-test.yamlclusterpolicy-failed.yamlclusterpolicy-ready.yamlclusterpolicy.yamlgctxentry-exists.yamlgctxentry.yamlmain-deployment.yamlnamespace.yamlnew-deployment-exists.yamlnew-deployment.yaml
resource-correct
|
@ -28,6 +28,8 @@ import (
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
// +kubebuilder:resource:shortName=gctxentry,categories=kyverno,scope="Cluster"
|
// +kubebuilder:resource:shortName=gctxentry,categories=kyverno,scope="Cluster"
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status`
|
||||||
|
|
||||||
// GlobalContextEntry declares resources to be cached.
|
// GlobalContextEntry declares resources to be cached.
|
||||||
type GlobalContextEntry struct {
|
type GlobalContextEntry struct {
|
||||||
|
|
|
@ -24,7 +24,11 @@ spec:
|
||||||
singular: globalcontextentry
|
singular: globalcontextentry
|
||||||
scope: Cluster
|
scope: Cluster
|
||||||
versions:
|
versions:
|
||||||
- name: v2alpha1
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .status.conditions[?(@.type == "Ready")].status
|
||||||
|
name: READY
|
||||||
|
type: string
|
||||||
|
name: v2alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
description: GlobalContextEntry declares resources to be cached.
|
description: GlobalContextEntry declares resources to be cached.
|
||||||
|
@ -199,4 +203,6 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
storage: true
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
@ -60,6 +60,8 @@ rules:
|
||||||
- clusterpolicies/status
|
- clusterpolicies/status
|
||||||
- updaterequests
|
- updaterequests
|
||||||
- updaterequests/status
|
- updaterequests/status
|
||||||
|
- globalcontextentries
|
||||||
|
- globalcontextentries/status
|
||||||
- admissionreports
|
- admissionreports
|
||||||
- clusteradmissionreports
|
- clusteradmissionreports
|
||||||
- backgroundscanreports
|
- backgroundscanreports
|
||||||
|
@ -74,13 +76,6 @@ rules:
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
- deletecollection
|
- deletecollection
|
||||||
- apiGroups:
|
|
||||||
- kyverno.io
|
|
||||||
resources:
|
|
||||||
- globalcontextentries
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- reports.kyverno.io
|
- reports.kyverno.io
|
||||||
resources:
|
resources:
|
||||||
|
|
|
@ -50,6 +50,8 @@ spec:
|
||||||
resources:
|
resources:
|
||||||
- clusterpolicies
|
- clusterpolicies
|
||||||
- clusterpolicies/status
|
- clusterpolicies/status
|
||||||
|
- globalcontextentries
|
||||||
|
- globalcontextentries/status
|
||||||
- clusteradmissionreports
|
- clusteradmissionreports
|
||||||
- clusterbackgroundscanreports
|
- clusterbackgroundscanreports
|
||||||
verbs:
|
verbs:
|
||||||
|
|
|
@ -32,6 +32,8 @@ rules:
|
||||||
- policyexceptions
|
- policyexceptions
|
||||||
- updaterequests
|
- updaterequests
|
||||||
- updaterequests/status
|
- updaterequests/status
|
||||||
|
- globalcontextentries
|
||||||
|
- globalcontextentries/status
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
- create
|
||||||
- delete
|
- delete
|
||||||
|
@ -41,13 +43,6 @@ rules:
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
- deletecollection
|
- deletecollection
|
||||||
- apiGroups:
|
|
||||||
- kyverno.io
|
|
||||||
resources:
|
|
||||||
- globalcontextentries
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- ''
|
- ''
|
||||||
resources:
|
resources:
|
||||||
|
|
|
@ -55,9 +55,16 @@ rules:
|
||||||
- kyverno.io
|
- kyverno.io
|
||||||
resources:
|
resources:
|
||||||
- globalcontextentries
|
- globalcontextentries
|
||||||
|
- globalcontextentries/status
|
||||||
verbs:
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
- list
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
- watch
|
- watch
|
||||||
|
- deletecollection
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- kyverno.io
|
- kyverno.io
|
||||||
resources:
|
resources:
|
||||||
|
|
|
@ -38,12 +38,7 @@ rules:
|
||||||
- kyverno.io
|
- kyverno.io
|
||||||
resources:
|
resources:
|
||||||
- globalcontextentries
|
- globalcontextentries
|
||||||
verbs:
|
- globalcontextentries/status
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- kyverno.io
|
|
||||||
resources:
|
|
||||||
- admissionreports
|
- admissionreports
|
||||||
- clusteradmissionreports
|
- clusteradmissionreports
|
||||||
- backgroundscanreports
|
- backgroundscanreports
|
||||||
|
|
|
@ -160,8 +160,11 @@ func main() {
|
||||||
globalcontextcontroller.NewController(
|
globalcontextcontroller.NewController(
|
||||||
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
||||||
setup.KyvernoDynamicClient,
|
setup.KyvernoDynamicClient,
|
||||||
|
setup.KyvernoClient,
|
||||||
gcstore,
|
gcstore,
|
||||||
|
eventGenerator,
|
||||||
maxAPICallResponseLength,
|
maxAPICallResponseLength,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
globalcontextcontroller.Workers,
|
globalcontextcontroller.Workers,
|
||||||
) // this controller only subscribe to events, nothing is returned...
|
) // this controller only subscribe to events, nothing is returned...
|
||||||
|
|
|
@ -166,8 +166,11 @@ func main() {
|
||||||
globalcontextcontroller.NewController(
|
globalcontextcontroller.NewController(
|
||||||
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
||||||
setup.KyvernoDynamicClient,
|
setup.KyvernoDynamicClient,
|
||||||
|
setup.KyvernoClient,
|
||||||
gcstore,
|
gcstore,
|
||||||
|
eventGenerator,
|
||||||
maxAPICallResponseLength,
|
maxAPICallResponseLength,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
globalcontextcontroller.Workers,
|
globalcontextcontroller.Workers,
|
||||||
)
|
)
|
||||||
|
@ -305,6 +308,7 @@ func main() {
|
||||||
cmResolver,
|
cmResolver,
|
||||||
setup.Jp,
|
setup.Jp,
|
||||||
eventGenerator,
|
eventGenerator,
|
||||||
|
gcstore,
|
||||||
),
|
),
|
||||||
cleanup.Workers,
|
cleanup.Workers,
|
||||||
)
|
)
|
||||||
|
|
|
@ -362,8 +362,11 @@ func main() {
|
||||||
globalcontextcontroller.NewController(
|
globalcontextcontroller.NewController(
|
||||||
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
||||||
setup.KyvernoDynamicClient,
|
setup.KyvernoDynamicClient,
|
||||||
|
setup.KyvernoClient,
|
||||||
gcstore,
|
gcstore,
|
||||||
|
eventGenerator,
|
||||||
maxAPICallResponseLength,
|
maxAPICallResponseLength,
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
globalcontextcontroller.Workers,
|
globalcontextcontroller.Workers,
|
||||||
)
|
)
|
||||||
|
@ -508,7 +511,7 @@ func main() {
|
||||||
)
|
)
|
||||||
policyHandlers := webhookspolicy.NewHandlers(
|
policyHandlers := webhookspolicy.NewHandlers(
|
||||||
setup.KyvernoDynamicClient,
|
setup.KyvernoDynamicClient,
|
||||||
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
setup.KyvernoClient,
|
||||||
backgroundServiceAccountName,
|
backgroundServiceAccountName,
|
||||||
)
|
)
|
||||||
resourceHandlers := webhooksresource.NewHandlers(
|
resourceHandlers := webhooksresource.NewHandlers(
|
||||||
|
|
|
@ -278,8 +278,11 @@ func main() {
|
||||||
globalcontextcontroller.NewController(
|
globalcontextcontroller.NewController(
|
||||||
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
kyvernoInformer.Kyverno().V2alpha1().GlobalContextEntries(),
|
||||||
setup.KyvernoDynamicClient,
|
setup.KyvernoDynamicClient,
|
||||||
|
setup.KyvernoClient,
|
||||||
gcstore,
|
gcstore,
|
||||||
|
eventGenerator,
|
||||||
maxAPICallResponseLength,
|
maxAPICallResponseLength,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
globalcontextcontroller.Workers,
|
globalcontextcontroller.Workers,
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,7 +18,11 @@ spec:
|
||||||
singular: globalcontextentry
|
singular: globalcontextentry
|
||||||
scope: Cluster
|
scope: Cluster
|
||||||
versions:
|
versions:
|
||||||
- name: v2alpha1
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .status.conditions[?(@.type == "Ready")].status
|
||||||
|
name: READY
|
||||||
|
type: string
|
||||||
|
name: v2alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
description: GlobalContextEntry declares resources to be cached.
|
description: GlobalContextEntry declares resources to be cached.
|
||||||
|
@ -193,3 +197,5 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
storage: true
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
|
|
@ -28569,7 +28569,11 @@ spec:
|
||||||
singular: globalcontextentry
|
singular: globalcontextentry
|
||||||
scope: Cluster
|
scope: Cluster
|
||||||
versions:
|
versions:
|
||||||
- name: v2alpha1
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .status.conditions[?(@.type == "Ready")].status
|
||||||
|
name: READY
|
||||||
|
type: string
|
||||||
|
name: v2alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
description: GlobalContextEntry declares resources to be cached.
|
description: GlobalContextEntry declares resources to be cached.
|
||||||
|
@ -28744,6 +28748,8 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
storage: true
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
---
|
---
|
||||||
apiVersion: apiextensions.k8s.io/v1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
|
@ -51279,6 +51285,8 @@ rules:
|
||||||
- clusterpolicies/status
|
- clusterpolicies/status
|
||||||
- updaterequests
|
- updaterequests
|
||||||
- updaterequests/status
|
- updaterequests/status
|
||||||
|
- globalcontextentries
|
||||||
|
- globalcontextentries/status
|
||||||
- admissionreports
|
- admissionreports
|
||||||
- clusteradmissionreports
|
- clusteradmissionreports
|
||||||
- backgroundscanreports
|
- backgroundscanreports
|
||||||
|
@ -51293,13 +51301,6 @@ rules:
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
- deletecollection
|
- deletecollection
|
||||||
- apiGroups:
|
|
||||||
- kyverno.io
|
|
||||||
resources:
|
|
||||||
- globalcontextentries
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- reports.kyverno.io
|
- reports.kyverno.io
|
||||||
resources:
|
resources:
|
||||||
|
@ -51414,6 +51415,8 @@ rules:
|
||||||
- policyexceptions
|
- policyexceptions
|
||||||
- updaterequests
|
- updaterequests
|
||||||
- updaterequests/status
|
- updaterequests/status
|
||||||
|
- globalcontextentries
|
||||||
|
- globalcontextentries/status
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
- create
|
||||||
- delete
|
- delete
|
||||||
|
@ -51423,13 +51426,6 @@ rules:
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
- deletecollection
|
- deletecollection
|
||||||
- apiGroups:
|
|
||||||
- kyverno.io
|
|
||||||
resources:
|
|
||||||
- globalcontextentries
|
|
||||||
verbs:
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- ''
|
- ''
|
||||||
resources:
|
resources:
|
||||||
|
@ -51556,9 +51552,16 @@ rules:
|
||||||
- kyverno.io
|
- kyverno.io
|
||||||
resources:
|
resources:
|
||||||
- globalcontextentries
|
- globalcontextentries
|
||||||
|
- globalcontextentries/status
|
||||||
verbs:
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
- list
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
- watch
|
- watch
|
||||||
|
- deletecollection
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- kyverno.io
|
- kyverno.io
|
||||||
resources:
|
resources:
|
||||||
|
@ -51867,12 +51870,7 @@ rules:
|
||||||
- kyverno.io
|
- kyverno.io
|
||||||
resources:
|
resources:
|
||||||
- globalcontextentries
|
- globalcontextentries
|
||||||
verbs:
|
- globalcontextentries/status
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- kyverno.io
|
|
||||||
resources:
|
|
||||||
- admissionreports
|
- admissionreports
|
||||||
- clusteradmissionreports
|
- clusteradmissionreports
|
||||||
- backgroundscanreports
|
- backgroundscanreports
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/kyverno/kyverno/pkg/controllers"
|
"github.com/kyverno/kyverno/pkg/controllers"
|
||||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
|
"github.com/kyverno/kyverno/pkg/engine/context/loaders"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/factories"
|
"github.com/kyverno/kyverno/pkg/engine/factories"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/jmespath"
|
"github.com/kyverno/kyverno/pkg/engine/jmespath"
|
||||||
"github.com/kyverno/kyverno/pkg/event"
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
|
@ -57,6 +58,7 @@ type controller struct {
|
||||||
eventGen event.Interface
|
eventGen event.Interface
|
||||||
jp jmespath.Interface
|
jp jmespath.Interface
|
||||||
metrics cleanupMetrics
|
metrics cleanupMetrics
|
||||||
|
gctxStore loaders.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
type cleanupMetrics struct {
|
type cleanupMetrics struct {
|
||||||
|
@ -80,6 +82,7 @@ func NewController(
|
||||||
cmResolver engineapi.ConfigmapResolver,
|
cmResolver engineapi.ConfigmapResolver,
|
||||||
jp jmespath.Interface,
|
jp jmespath.Interface,
|
||||||
eventGen event.Interface,
|
eventGen event.Interface,
|
||||||
|
gctxStore loaders.Store,
|
||||||
) controllers.Controller {
|
) controllers.Controller {
|
||||||
queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), ControllerName)
|
queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), ControllerName)
|
||||||
keyFunc := controllerutils.MetaNamespaceKeyT[kyvernov2alpha1.CleanupPolicyInterface]
|
keyFunc := controllerutils.MetaNamespaceKeyT[kyvernov2alpha1.CleanupPolicyInterface]
|
||||||
|
@ -112,6 +115,7 @@ func NewController(
|
||||||
eventGen: eventGen,
|
eventGen: eventGen,
|
||||||
metrics: newCleanupMetrics(logger),
|
metrics: newCleanupMetrics(logger),
|
||||||
jp: jp,
|
jp: jp,
|
||||||
|
gctxStore: gctxStore,
|
||||||
}
|
}
|
||||||
if _, err := controllerutils.AddEventHandlersT(
|
if _, err := controllerutils.AddEventHandlersT(
|
||||||
cpolInformer.Informer(),
|
cpolInformer.Informer(),
|
||||||
|
@ -181,7 +185,7 @@ func (c *controller) cleanup(ctx context.Context, logger logr.Logger, policy kyv
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
enginectx := enginecontext.NewContext(c.jp)
|
enginectx := enginecontext.NewContext(c.jp)
|
||||||
ctxFactory := factories.DefaultContextLoaderFactory(c.cmResolver)
|
ctxFactory := factories.DefaultContextLoaderFactory(c.cmResolver, factories.WithGlobalContextStore(c.gctxStore))
|
||||||
|
|
||||||
loader := ctxFactory(nil, kyvernov1.Rule{})
|
loader := ctxFactory(nil, kyvernov1.Rule{})
|
||||||
if err := loader.Load(
|
if err := loader.Load(
|
||||||
|
|
|
@ -6,17 +6,21 @@ import (
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||||
|
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||||
kyvernov2alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2alpha1"
|
kyvernov2alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2alpha1"
|
||||||
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
"github.com/kyverno/kyverno/pkg/controllers"
|
"github.com/kyverno/kyverno/pkg/controllers"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/adapters"
|
"github.com/kyverno/kyverno/pkg/engine/adapters"
|
||||||
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
"github.com/kyverno/kyverno/pkg/globalcontext/externalapi"
|
"github.com/kyverno/kyverno/pkg/globalcontext/externalapi"
|
||||||
"github.com/kyverno/kyverno/pkg/globalcontext/k8sresource"
|
"github.com/kyverno/kyverno/pkg/globalcontext/k8sresource"
|
||||||
"github.com/kyverno/kyverno/pkg/globalcontext/store"
|
"github.com/kyverno/kyverno/pkg/globalcontext/store"
|
||||||
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||||
|
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,29 +39,66 @@ type controller struct {
|
||||||
queue workqueue.RateLimitingInterface
|
queue workqueue.RateLimitingInterface
|
||||||
|
|
||||||
// state
|
// state
|
||||||
dclient dclient.Interface
|
dclient dclient.Interface
|
||||||
store store.Store
|
kyvernoClient versioned.Interface
|
||||||
maxResponseLength int64
|
store store.Store
|
||||||
|
eventGen event.Interface
|
||||||
|
maxResponseLength int64
|
||||||
|
shouldUpdateStatus bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewController(
|
func NewController(
|
||||||
gceInformer kyvernov2alpha1informers.GlobalContextEntryInformer,
|
gceInformer kyvernov2alpha1informers.GlobalContextEntryInformer,
|
||||||
dclient dclient.Interface,
|
dclient dclient.Interface,
|
||||||
|
kyvernoClient versioned.Interface,
|
||||||
storage store.Store,
|
storage store.Store,
|
||||||
|
eventGen event.Interface,
|
||||||
maxResponseLength int64,
|
maxResponseLength int64,
|
||||||
|
shouldUpdateStatus bool,
|
||||||
) controllers.Controller {
|
) controllers.Controller {
|
||||||
queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), ControllerName)
|
queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), ControllerName)
|
||||||
_, _, err := controllerutils.AddDefaultEventHandlers(logger, gceInformer.Informer(), queue)
|
c := &controller{
|
||||||
if err != nil {
|
gceLister: gceInformer.Lister(),
|
||||||
|
queue: queue,
|
||||||
|
dclient: dclient,
|
||||||
|
kyvernoClient: kyvernoClient,
|
||||||
|
store: storage,
|
||||||
|
eventGen: eventGen,
|
||||||
|
maxResponseLength: maxResponseLength,
|
||||||
|
shouldUpdateStatus: shouldUpdateStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := controllerutils.AddEventHandlersT(gceInformer.Informer(), c.addGTXEntry, c.updateGTXEntry, c.deleteGTXEntry); err != nil {
|
||||||
logger.Error(err, "failed to register event handlers")
|
logger.Error(err, "failed to register event handlers")
|
||||||
}
|
}
|
||||||
return &controller{
|
|
||||||
gceLister: gceInformer.Lister(),
|
return c
|
||||||
queue: queue,
|
}
|
||||||
dclient: dclient,
|
|
||||||
store: storage,
|
func (c *controller) addGTXEntry(obj *kyvernov2alpha1.GlobalContextEntry) {
|
||||||
maxResponseLength: maxResponseLength,
|
logger.Info("globalcontextentry created", "uid", obj.GetUID(), "kind", obj.Kind, "name", obj.GetName())
|
||||||
|
c.enqueueGCTXEntry(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) updateGTXEntry(old, obj *kyvernov2alpha1.GlobalContextEntry) {
|
||||||
|
if datautils.DeepEqual(old.Spec, obj.Spec) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
logger.Info("globalcontextentry updated", "uid", obj.GetUID(), "kind", obj.Kind, "name", obj.GetName())
|
||||||
|
c.enqueueGCTXEntry(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) deleteGTXEntry(obj *kyvernov2alpha1.GlobalContextEntry) {
|
||||||
|
c.enqueueGCTXEntry(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) enqueueGCTXEntry(gctxentry *kyvernov2alpha1.GlobalContextEntry) {
|
||||||
|
key, err := cache.MetaNamespaceKeyFunc(gctxentry)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "failed to enqueue global context entry")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.queue.Add(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) Run(ctx context.Context, workers int) {
|
func (c *controller) Run(ctx context.Context, workers int) {
|
||||||
|
@ -95,14 +136,29 @@ func (c *controller) makeStoreEntry(ctx context.Context, gce *kyvernov2alpha1.Gl
|
||||||
Version: gce.Spec.KubernetesResource.Version,
|
Version: gce.Spec.KubernetesResource.Version,
|
||||||
Resource: gce.Spec.KubernetesResource.Resource,
|
Resource: gce.Spec.KubernetesResource.Resource,
|
||||||
}
|
}
|
||||||
return k8sresource.New(ctx, c.dclient.GetDynamicInterface(), gvr, gce.Spec.KubernetesResource.Namespace)
|
return k8sresource.New(
|
||||||
|
ctx,
|
||||||
|
gce,
|
||||||
|
c.eventGen,
|
||||||
|
c.dclient.GetDynamicInterface(),
|
||||||
|
c.kyvernoClient,
|
||||||
|
logger,
|
||||||
|
gvr,
|
||||||
|
gce.Spec.KubernetesResource.Namespace,
|
||||||
|
c.shouldUpdateStatus,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return externalapi.New(
|
return externalapi.New(
|
||||||
ctx,
|
ctx,
|
||||||
|
gce,
|
||||||
|
c.eventGen,
|
||||||
|
c.kyvernoClient,
|
||||||
|
c.gceLister,
|
||||||
logger,
|
logger,
|
||||||
adapters.Client(c.dclient),
|
adapters.Client(c.dclient),
|
||||||
gce.Spec.APICall.APICall,
|
gce.Spec.APICall.APICall,
|
||||||
gce.Spec.APICall.RefreshInterval.Duration,
|
gce.Spec.APICall.RefreshInterval.Duration,
|
||||||
c.maxResponseLength,
|
c.maxResponseLength,
|
||||||
|
c.shouldUpdateStatus,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -426,7 +426,7 @@ func (c *controller) reconcileMutatingWebhookConfiguration(ctx context.Context,
|
||||||
func (c *controller) isGlobalContextEntryReady(name string, gctxentries []*kyvernov2alpha1.GlobalContextEntry) bool {
|
func (c *controller) isGlobalContextEntryReady(name string, gctxentries []*kyvernov2alpha1.GlobalContextEntry) bool {
|
||||||
for _, gctxentry := range gctxentries {
|
for _, gctxentry := range gctxentries {
|
||||||
if gctxentry.Name == name {
|
if gctxentry.Name == name {
|
||||||
return true
|
return gctxentry.Status.IsReady()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -135,7 +135,9 @@ func (gen *controller) processNextWorkItem(ctx context.Context) bool {
|
||||||
func (gen *controller) emitEvent(key Info) {
|
func (gen *controller) emitEvent(key Info) {
|
||||||
logger := gen.logger
|
logger := gen.logger
|
||||||
eventType := corev1.EventTypeWarning
|
eventType := corev1.EventTypeWarning
|
||||||
if key.Reason == PolicyApplied || key.Reason == PolicySkipped {
|
if key.Type != "" {
|
||||||
|
eventType = key.Type
|
||||||
|
} else if key.Reason == PolicyApplied || key.Reason == PolicySkipped {
|
||||||
eventType = corev1.EventTypeNormal
|
eventType = corev1.EventTypeNormal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ type Info struct {
|
||||||
Message string
|
Message string
|
||||||
Action Action
|
Action Action
|
||||||
Source Source
|
Source Source
|
||||||
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Info) Resource() string {
|
func (i *Info) Resource() string {
|
||||||
|
|
22
pkg/globalcontext/event/event.go
Normal file
22
pkg/globalcontext/event/event.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package event
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
source = "globalcontext-controller"
|
||||||
|
action = "Retrying"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewErrorEvent(regarding corev1.ObjectReference, reason event.Reason, err error) event.Info {
|
||||||
|
return event.Info{
|
||||||
|
Regarding: regarding,
|
||||||
|
Source: source,
|
||||||
|
Reason: reason,
|
||||||
|
Message: err.Error(),
|
||||||
|
Action: action,
|
||||||
|
Type: corev1.EventTypeWarning,
|
||||||
|
}
|
||||||
|
}
|
7
pkg/globalcontext/event/reason.go
Normal file
7
pkg/globalcontext/event/reason.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package event
|
||||||
|
|
||||||
|
const (
|
||||||
|
ReasonResourceListFailure = "FailedToList"
|
||||||
|
ReasonAPICallFailure = "FailedToCallAPI"
|
||||||
|
ReasonCacheSyncFailure = "FailedToWaitForCacheSync"
|
||||||
|
)
|
|
@ -8,8 +8,18 @@ import (
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
|
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||||
|
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||||
|
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/apicall"
|
"github.com/kyverno/kyverno/pkg/engine/apicall"
|
||||||
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
|
entryevent "github.com/kyverno/kyverno/pkg/globalcontext/event"
|
||||||
|
"github.com/kyverno/kyverno/pkg/globalcontext/store"
|
||||||
|
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/client-go/util/retry"
|
||||||
)
|
)
|
||||||
|
|
||||||
type entry struct {
|
type entry struct {
|
||||||
|
@ -21,12 +31,17 @@ type entry struct {
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
gce *kyvernov2alpha1.GlobalContextEntry,
|
||||||
|
eventGen event.Interface,
|
||||||
|
kyvernoClient versioned.Interface,
|
||||||
|
gceLister kyvernov2alpha1listers.GlobalContextEntryLister,
|
||||||
logger logr.Logger,
|
logger logr.Logger,
|
||||||
client apicall.ClientInterface,
|
client apicall.ClientInterface,
|
||||||
call kyvernov1.APICall,
|
call kyvernov1.APICall,
|
||||||
period time.Duration,
|
period time.Duration,
|
||||||
maxResponseLength int64,
|
maxResponseLength int64,
|
||||||
) (*entry, error) {
|
shouldUpdateStatus bool,
|
||||||
|
) (store.Entry, error) {
|
||||||
var group wait.Group
|
var group wait.Group
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
stop := func() {
|
stop := func() {
|
||||||
|
@ -38,19 +53,42 @@ func New(
|
||||||
e := &entry{
|
e := &entry{
|
||||||
stop: stop,
|
stop: stop,
|
||||||
}
|
}
|
||||||
|
|
||||||
group.StartWithContext(ctx, func(ctx context.Context) {
|
group.StartWithContext(ctx, func(ctx context.Context) {
|
||||||
// TODO: make sure we have called it at least once before returning
|
|
||||||
config := apicall.NewAPICallConfiguration(maxResponseLength)
|
config := apicall.NewAPICallConfiguration(maxResponseLength)
|
||||||
caller := apicall.NewCaller(logger, "globalcontext", client, config)
|
caller := apicall.NewCaller(logger, "globalcontext", client, config)
|
||||||
|
|
||||||
wait.UntilWithContext(ctx, func(ctx context.Context) {
|
wait.UntilWithContext(ctx, func(ctx context.Context) {
|
||||||
if data, err := doCall(ctx, caller, call); err != nil {
|
if data, err := doCall(ctx, caller, call); err != nil {
|
||||||
logger.Error(err, "failed to get data from api caller")
|
|
||||||
e.setData(nil, err)
|
e.setData(nil, err)
|
||||||
|
|
||||||
|
logger.Error(err, "failed to get data from api caller")
|
||||||
|
|
||||||
|
eventGen.Add(entryevent.NewErrorEvent(corev1.ObjectReference{
|
||||||
|
APIVersion: gce.APIVersion,
|
||||||
|
Kind: gce.Kind,
|
||||||
|
Name: gce.Name,
|
||||||
|
Namespace: gce.Namespace,
|
||||||
|
UID: gce.UID,
|
||||||
|
}, entryevent.ReasonAPICallFailure, err))
|
||||||
|
|
||||||
|
if shouldUpdateStatus {
|
||||||
|
if updateErr := updateStatus(ctx, gce.Name, kyvernoClient, false, entryevent.ReasonAPICallFailure); updateErr != nil {
|
||||||
|
logger.Error(updateErr, "failed to update status")
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
e.setData(data, nil)
|
e.setData(data, nil)
|
||||||
|
|
||||||
|
if shouldUpdateStatus {
|
||||||
|
if updateErr := updateStatus(ctx, gce.Name, kyvernoClient, true, "APICallSuccess"); updateErr != nil {
|
||||||
|
logger.Error(updateErr, "failed to update status")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, period)
|
}, period)
|
||||||
})
|
})
|
||||||
|
|
||||||
return e, nil
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,3 +127,24 @@ func (e *entry) setData(data any, err error) {
|
||||||
func doCall(ctx context.Context, caller apicall.Caller, call kyvernov1.APICall) (any, error) {
|
func doCall(ctx context.Context, caller apicall.Caller, call kyvernov1.APICall) (any, error) {
|
||||||
return caller.Execute(ctx, &call)
|
return caller.Execute(ctx, &call)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateStatus(ctx context.Context, gceName string, kyvernoClient versioned.Interface, ready bool, reason string) error {
|
||||||
|
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||||
|
latestGCE, getErr := kyvernoClient.KyvernoV2alpha1().GlobalContextEntries().Get(ctx, gceName, metav1.GetOptions{})
|
||||||
|
if getErr != nil {
|
||||||
|
return getErr
|
||||||
|
}
|
||||||
|
|
||||||
|
_, updateErr := controllerutils.UpdateStatus(ctx, latestGCE, kyvernoClient.KyvernoV2alpha1().GlobalContextEntries(), func(latest *kyvernov2alpha1.GlobalContextEntry) error {
|
||||||
|
if latest == nil {
|
||||||
|
return fmt.Errorf("failed to update status: %s", latestGCE.Name)
|
||||||
|
}
|
||||||
|
latest.Status.SetReady(ready, reason)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return updateErr
|
||||||
|
})
|
||||||
|
|
||||||
|
return retryErr
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,15 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||||
|
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||||
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
|
entryevent "github.com/kyverno/kyverno/pkg/globalcontext/event"
|
||||||
|
"github.com/kyverno/kyverno/pkg/globalcontext/invalid"
|
||||||
|
"github.com/kyverno/kyverno/pkg/globalcontext/store"
|
||||||
|
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
@ -14,11 +23,24 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type entry struct {
|
type entry struct {
|
||||||
lister cache.GenericLister
|
lister cache.GenericLister
|
||||||
stop func()
|
stop func()
|
||||||
|
gce *kyvernov2alpha1.GlobalContextEntry
|
||||||
|
eventGen event.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, client dynamic.Interface, gvr schema.GroupVersionResource, namespace string) (*entry, error) {
|
// TODO: Handle Kyverno Pod Ready State
|
||||||
|
func New(
|
||||||
|
ctx context.Context,
|
||||||
|
gce *kyvernov2alpha1.GlobalContextEntry,
|
||||||
|
eventGen event.Interface,
|
||||||
|
client dynamic.Interface,
|
||||||
|
kyvernoClient versioned.Interface,
|
||||||
|
logger logr.Logger,
|
||||||
|
gvr schema.GroupVersionResource,
|
||||||
|
namespace string,
|
||||||
|
shouldUpdateStatus bool,
|
||||||
|
) (store.Entry, error) {
|
||||||
indexers := cache.Indexers{
|
indexers := cache.Indexers{
|
||||||
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
|
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
|
||||||
}
|
}
|
||||||
|
@ -39,17 +61,48 @@ func New(ctx context.Context, client dynamic.Interface, gvr schema.GroupVersionR
|
||||||
})
|
})
|
||||||
if !cache.WaitForCacheSync(ctx.Done(), informer.Informer().HasSynced) {
|
if !cache.WaitForCacheSync(ctx.Done(), informer.Informer().HasSynced) {
|
||||||
stop()
|
stop()
|
||||||
return nil, fmt.Errorf("failed to wait for cache sync: %s", gvr.Resource)
|
|
||||||
|
if shouldUpdateStatus {
|
||||||
|
if err := updateStatus(ctx, gce, kyvernoClient, false, "CacheSyncFailure"); err != nil {
|
||||||
|
logger.Error(err, "failed to update status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := fmt.Errorf("failed to sync cache for %s", gvr)
|
||||||
|
eventGen.Add(entryevent.NewErrorEvent(corev1.ObjectReference{
|
||||||
|
APIVersion: gce.APIVersion,
|
||||||
|
Kind: gce.Kind,
|
||||||
|
Name: gce.Name,
|
||||||
|
Namespace: gce.Namespace,
|
||||||
|
UID: gce.UID,
|
||||||
|
}, entryevent.ReasonCacheSyncFailure, err))
|
||||||
|
|
||||||
|
return invalid.New(err), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if shouldUpdateStatus {
|
||||||
|
if err := updateStatus(ctx, gce, kyvernoClient, true, "CacheSyncSuccess"); err != nil {
|
||||||
|
logger.Error(err, "failed to update status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &entry{
|
return &entry{
|
||||||
lister: informer.Lister(),
|
lister: informer.Lister(),
|
||||||
stop: stop,
|
stop: stop,
|
||||||
|
eventGen: eventGen,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *entry) Get() (any, error) {
|
func (e *entry) Get() (any, error) {
|
||||||
obj, err := e.lister.List(labels.Everything())
|
obj, err := e.lister.List(labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
e.eventGen.Add(entryevent.NewErrorEvent(corev1.ObjectReference{
|
||||||
|
APIVersion: e.gce.APIVersion,
|
||||||
|
Kind: e.gce.Kind,
|
||||||
|
Name: e.gce.Name,
|
||||||
|
Namespace: e.gce.Namespace,
|
||||||
|
UID: e.gce.UID,
|
||||||
|
}, entryevent.ReasonResourceListFailure, err))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj, nil
|
return obj, nil
|
||||||
|
@ -58,3 +111,14 @@ func (e *entry) Get() (any, error) {
|
||||||
func (e *entry) Stop() {
|
func (e *entry) Stop() {
|
||||||
e.stop()
|
e.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateStatus(ctx context.Context, gce *kyvernov2alpha1.GlobalContextEntry, kyvernoClient versioned.Interface, ready bool, reason string) error {
|
||||||
|
_, err := controllerutils.UpdateStatus(ctx, gce, kyvernoClient.KyvernoV2alpha1().GlobalContextEntries(), func(latest *kyvernov2alpha1.GlobalContextEntry) error {
|
||||||
|
if latest == nil {
|
||||||
|
return fmt.Errorf("failed to update status: %s", gce.Name)
|
||||||
|
}
|
||||||
|
latest.Status.SetReady(ready, reason)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package policy
|
package policy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -19,7 +20,7 @@ import (
|
||||||
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||||
"github.com/kyverno/kyverno/ext/wildcard"
|
"github.com/kyverno/kyverno/ext/wildcard"
|
||||||
"github.com/kyverno/kyverno/pkg/autogen"
|
"github.com/kyverno/kyverno/pkg/autogen"
|
||||||
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||||
|
@ -33,7 +34,6 @@ import (
|
||||||
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
"k8s.io/apimachinery/pkg/util/yaml"
|
"k8s.io/apimachinery/pkg/util/yaml"
|
||||||
|
@ -128,7 +128,7 @@ func checkValidationFailureAction(spec *kyvernov1.Spec) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks the policy and rules declarations for required configurations
|
// Validate checks the policy and rules declarations for required configurations
|
||||||
func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interface, gctxentryLister kyvernov2alpha1listers.GlobalContextEntryLister, mock bool, username string) ([]string, error) {
|
func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interface, kyvernoClient versioned.Interface, mock bool, username string) ([]string, error) {
|
||||||
var warnings []string
|
var warnings []string
|
||||||
spec := policy.GetSpec()
|
spec := policy.GetSpec()
|
||||||
background := spec.BackgroundProcessingEnabled()
|
background := spec.BackgroundProcessingEnabled()
|
||||||
|
@ -404,8 +404,8 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
||||||
}
|
}
|
||||||
|
|
||||||
// global context entry validation
|
// global context entry validation
|
||||||
if gctxentryLister != nil {
|
if kyvernoClient != nil {
|
||||||
gctxentries, err := gctxentryLister.List(labels.Everything())
|
gctxentries, err := kyvernoClient.KyvernoV2alpha1().GlobalContextEntries().List(context.Background(), metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,7 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
||||||
for _, ctxEntry := range rule.Context {
|
for _, ctxEntry := range rule.Context {
|
||||||
if ctxEntry.GlobalReference != nil {
|
if ctxEntry.GlobalReference != nil {
|
||||||
if !isGlobalContextEntryReady(ctxEntry.GlobalReference.Name, gctxentries) {
|
if !isGlobalContextEntryReady(ctxEntry.GlobalReference.Name, gctxentries) {
|
||||||
return nil, fmt.Errorf("global context entry %s is not ready", ctxEntry.Name)
|
return nil, fmt.Errorf("global context entry %s is not ready", ctxEntry.GlobalReference.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,10 +473,10 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
||||||
return warnings, nil
|
return warnings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGlobalContextEntryReady(name string, gctxentries []*kyvernov2alpha1.GlobalContextEntry) bool {
|
func isGlobalContextEntryReady(name string, gctxentries *kyvernov2alpha1.GlobalContextEntryList) bool {
|
||||||
for _, gctxentry := range gctxentries {
|
for _, gctxentry := range gctxentries.Items {
|
||||||
if gctxentry.Name == name {
|
if gctxentry.Name == name {
|
||||||
return true
|
return gctxentry.Status.IsReady()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -5,8 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyvernov2alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2alpha1"
|
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||||
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||||
policyvalidate "github.com/kyverno/kyverno/pkg/validation/policy"
|
policyvalidate "github.com/kyverno/kyverno/pkg/validation/policy"
|
||||||
|
@ -16,14 +15,14 @@ import (
|
||||||
|
|
||||||
type policyHandlers struct {
|
type policyHandlers struct {
|
||||||
client dclient.Interface
|
client dclient.Interface
|
||||||
gctxentryLister kyvernov2alpha1listers.GlobalContextEntryLister
|
kyvernoClient versioned.Interface
|
||||||
backgroundServiceAccountName string
|
backgroundServiceAccountName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandlers(client dclient.Interface, gctxentryInformer kyvernov2alpha1informers.GlobalContextEntryInformer, serviceaccount string) webhooks.PolicyHandlers {
|
func NewHandlers(client dclient.Interface, kyvernoClient versioned.Interface, serviceaccount string) webhooks.PolicyHandlers {
|
||||||
return &policyHandlers{
|
return &policyHandlers{
|
||||||
client: client,
|
client: client,
|
||||||
gctxentryLister: gctxentryInformer.Lister(),
|
kyvernoClient: kyvernoClient,
|
||||||
backgroundServiceAccountName: serviceaccount,
|
backgroundServiceAccountName: serviceaccount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +33,7 @@ func (h *policyHandlers) Validate(ctx context.Context, logger logr.Logger, reque
|
||||||
logger.Error(err, "failed to unmarshal policies from admission request")
|
logger.Error(err, "failed to unmarshal policies from admission request")
|
||||||
return admissionutils.Response(request.UID, err)
|
return admissionutils.Response(request.UID, err)
|
||||||
}
|
}
|
||||||
warnings, err := policyvalidate.Validate(policy, oldPolicy, h.client, h.gctxentryLister, false, h.backgroundServiceAccountName)
|
warnings, err := policyvalidate.Validate(policy, oldPolicy, h.client, h.kyvernoClient, false, h.backgroundServiceAccountName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "policy validation errors")
|
logger.Error(err, "policy validation errors")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
kind: Test
|
kind: Test
|
||||||
metadata:
|
metadata:
|
||||||
creationTimestamp: null
|
creationTimestamp: null
|
||||||
name: resource-correct
|
name: apicall-correct
|
||||||
spec:
|
spec:
|
||||||
steps:
|
steps:
|
||||||
- name: scenario
|
- name: scenario
|
||||||
|
@ -13,11 +13,13 @@ spec:
|
||||||
file: main-deployment.yaml
|
file: main-deployment.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: gctxentry.yaml
|
file: gctxentry.yaml
|
||||||
|
- sleep:
|
||||||
|
duration: 15s
|
||||||
- apply:
|
- apply:
|
||||||
file: clusterpolicy.yaml
|
file: clusterpolicy.yaml
|
||||||
|
- assert:
|
||||||
|
file: clusterpolicy-ready.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: new-deployment.yaml
|
file: new-deployment.yaml
|
||||||
- assert:
|
|
||||||
file: clusterpolicy-succeeded.yaml
|
|
||||||
- assert:
|
- assert:
|
||||||
file: new-deployment-exists.yaml
|
file: new-deployment-exists.yaml
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: kyverno.io/v1
|
apiVersion: kyverno.io/v1
|
||||||
kind: ClusterPolicy
|
kind: ClusterPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: namespace-has-coordinator
|
name: cpol-apicall-correct
|
||||||
status:
|
status:
|
||||||
conditions:
|
conditions:
|
||||||
- reason: Succeeded
|
- reason: Succeeded
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: kyverno.io/v1
|
apiVersion: kyverno.io/v1
|
||||||
kind: ClusterPolicy
|
kind: ClusterPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: namespace-has-coordinator
|
name: cpol-apicall-correct
|
||||||
spec:
|
spec:
|
||||||
validationFailureAction: Enforce
|
validationFailureAction: Enforce
|
||||||
failurePolicy: Fail
|
failurePolicy: Fail
|
||||||
|
@ -10,7 +10,7 @@ spec:
|
||||||
context:
|
context:
|
||||||
- name: deploymentCount
|
- name: deploymentCount
|
||||||
globalReference:
|
globalReference:
|
||||||
name: deployments
|
name: gctxentry-apicall-correct
|
||||||
jmesPath: "items | length(@)"
|
jmesPath: "items | length(@)"
|
||||||
match:
|
match:
|
||||||
all:
|
all:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
apiVersion: kyverno.io/v2alpha1
|
apiVersion: kyverno.io/v2alpha1
|
||||||
kind: GlobalContextEntry
|
kind: GlobalContextEntry
|
||||||
metadata:
|
metadata:
|
||||||
name: deployments
|
name: gctxentry-apicall-correct
|
||||||
spec:
|
spec:
|
||||||
apiCall:
|
apiCall:
|
||||||
urlPath: "/apis/apps/v1/namespaces/test-globalcontext/deployments"
|
urlPath: "/apis/apps/v1/namespaces/test-globalcontext-apicall-correct/deployments"
|
||||||
refreshInterval: 10s
|
refreshInterval: 1h
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: main-deployment
|
name: main-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-apicall-correct
|
||||||
labels:
|
labels:
|
||||||
app: main-deployment
|
app: main-deployment
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: test-globalcontext
|
name: test-globalcontext-apicall-correct
|
||||||
|
|
|
@ -2,6 +2,6 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: new-deployment
|
name: new-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-apicall-correct
|
||||||
labels:
|
labels:
|
||||||
app: new-deployment
|
app: new-deployment
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: new-deployment
|
name: new-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-apicall-correct
|
||||||
labels:
|
labels:
|
||||||
app: new-deployment
|
app: new-deployment
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This test verifies that Global Context Entries are evaluated correctly.
|
||||||
|
|
||||||
|
## Expected Behavior
|
||||||
|
|
||||||
|
`new-deployment` should be created.
|
||||||
|
|
||||||
|
## Reference Issues
|
||||||
|
|
||||||
|
|
13
test/conformance/chainsaw/globalcontext/apicall-failed/chainsaw-test.yaml
Executable file
13
test/conformance/chainsaw/globalcontext/apicall-failed/chainsaw-test.yaml
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
|
kind: Test
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: apicall-failed
|
||||||
|
spec:
|
||||||
|
steps:
|
||||||
|
- name: scenario
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: gctxentry.yaml
|
||||||
|
- assert:
|
||||||
|
file: gctxentry-not-ready.yaml
|
|
@ -0,0 +1,8 @@
|
||||||
|
apiVersion: kyverno.io/v2alpha1
|
||||||
|
kind: GlobalContextEntry
|
||||||
|
metadata:
|
||||||
|
name: gctxentry-apicall-failed
|
||||||
|
status:
|
||||||
|
conditions:
|
||||||
|
- status: "False"
|
||||||
|
type: Ready
|
8
test/conformance/chainsaw/globalcontext/apicall-failed/gctxentry.yaml
Executable file
8
test/conformance/chainsaw/globalcontext/apicall-failed/gctxentry.yaml
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
apiVersion: kyverno.io/v2alpha1
|
||||||
|
kind: GlobalContextEntry
|
||||||
|
metadata:
|
||||||
|
name: gctxentry-apicall-failed
|
||||||
|
spec:
|
||||||
|
apiCall:
|
||||||
|
urlPath: "/apis/apps/v1/namespaces/default/unknown"
|
||||||
|
refreshInterval: 10s
|
|
@ -1,10 +1,10 @@
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
This test verifies that policies are not ready if referenced Global Context Entries don't exist.
|
This test verifies that policies cannot be created if referenced Global Context Entries don't exist.
|
||||||
|
|
||||||
## Expected Behavior
|
## Expected Behavior
|
||||||
|
|
||||||
`new-deployment` should not be created because the policy is not ready.
|
The clusterpolicy ` cpol-gctxentry-not-exist` should not be created because the globalcontextentry does not exist.
|
||||||
|
|
||||||
## Reference Issues
|
## Reference Issues
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ spec:
|
||||||
file: namespace.yaml
|
file: namespace.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: main-deployment.yaml
|
file: main-deployment.yaml
|
||||||
- apply:
|
|
||||||
file: gctxentry.yaml
|
|
||||||
- name: negative
|
- name: negative
|
||||||
try:
|
try:
|
||||||
- apply:
|
- apply:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: kyverno.io/v1
|
apiVersion: kyverno.io/v1
|
||||||
kind: ClusterPolicy
|
kind: ClusterPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: namespace-has-coordinator
|
name: cpol-gctxentry-not-exist
|
||||||
spec:
|
spec:
|
||||||
validationFailureAction: Enforce
|
validationFailureAction: Enforce
|
||||||
failurePolicy: Fail
|
failurePolicy: Fail
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
apiVersion: kyverno.io/v2alpha1
|
apiVersion: kyverno.io/v2alpha1
|
||||||
kind: GlobalContextEntry
|
kind: GlobalContextEntry
|
||||||
metadata:
|
metadata:
|
||||||
name: deployments
|
name: non-existent-gctx
|
||||||
spec:
|
spec:
|
||||||
kubernetesResource:
|
kubernetesResource:
|
||||||
group: apps
|
group: apps
|
||||||
version: v1
|
version: v1
|
||||||
resource: deployments
|
resource: deployments
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-gctxentry-not-exist
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: main-deployment
|
name: main-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-gctxentry-not-exist
|
||||||
labels:
|
labels:
|
||||||
app: main-deployment
|
app: main-deployment
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: test-globalcontext
|
name: test-globalcontext-gctxentry-not-exist
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: new-deployment
|
|
||||||
namespace: test-globalcontext
|
|
||||||
labels:
|
|
||||||
app: new-deployment
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: new-deployment
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: new-deployment
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx:1.14.2
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
|
@ -1,6 +1,6 @@
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
This test verifies that policies are not ready if referenced Global Context Entries don't exist.
|
This test verifies that the policy becomes not ready if the referenced Global Context Entries don't exist anymore.
|
||||||
|
|
||||||
## Expected Behavior
|
## Expected Behavior
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,19 @@ spec:
|
||||||
file: main-deployment.yaml
|
file: main-deployment.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: gctxentry.yaml
|
file: gctxentry.yaml
|
||||||
- assert:
|
- sleep:
|
||||||
file: gctxentry-exists.yaml
|
duration: 15s
|
||||||
- apply:
|
- apply:
|
||||||
file: clusterpolicy.yaml
|
file: clusterpolicy.yaml
|
||||||
|
- assert:
|
||||||
|
file: clusterpolicy-ready.yaml
|
||||||
- delete:
|
- delete:
|
||||||
ref:
|
ref:
|
||||||
apiVersion: kyverno.io/v2alpha1
|
apiVersion: kyverno.io/v2alpha1
|
||||||
kind: GlobalContextEntry
|
kind: GlobalContextEntry
|
||||||
name: deployments
|
name: gctx-not-ready
|
||||||
|
- sleep:
|
||||||
|
duration: 5s
|
||||||
- assert:
|
- assert:
|
||||||
file: clusterpolicy-failed.yaml
|
file: clusterpolicy-failed.yaml
|
||||||
- apply:
|
- apply:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: kyverno.io/v1
|
apiVersion: kyverno.io/v1
|
||||||
kind: ClusterPolicy
|
kind: ClusterPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: namespace-has-coordinator
|
name: cpol-not-ready
|
||||||
status:
|
status:
|
||||||
conditions:
|
conditions:
|
||||||
- reason: Failed
|
- reason: Failed
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: kyverno.io/v1
|
apiVersion: kyverno.io/v1
|
||||||
kind: ClusterPolicy
|
kind: ClusterPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: namespace-has-coordinator
|
name: cpol-not-ready
|
||||||
status:
|
status:
|
||||||
conditions:
|
conditions:
|
||||||
- reason: Succeeded
|
- reason: Succeeded
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: kyverno.io/v1
|
apiVersion: kyverno.io/v1
|
||||||
kind: ClusterPolicy
|
kind: ClusterPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: namespace-has-coordinator
|
name: cpol-not-ready
|
||||||
spec:
|
spec:
|
||||||
validationFailureAction: Enforce
|
validationFailureAction: Enforce
|
||||||
failurePolicy: Fail
|
failurePolicy: Fail
|
||||||
|
@ -10,7 +10,7 @@ spec:
|
||||||
context:
|
context:
|
||||||
- name: deploymentCount
|
- name: deploymentCount
|
||||||
globalReference:
|
globalReference:
|
||||||
name: deployments
|
name: gctx-not-ready
|
||||||
jmesPath: "items | length(@)"
|
jmesPath: "items | length(@)"
|
||||||
match:
|
match:
|
||||||
all:
|
all:
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
apiVersion: kyverno.io/v2alpha1
|
|
||||||
kind: GlobalContextEntry
|
|
||||||
metadata:
|
|
||||||
name: deployments
|
|
|
@ -1,8 +1,8 @@
|
||||||
apiVersion: kyverno.io/v2alpha1
|
apiVersion: kyverno.io/v2alpha1
|
||||||
kind: GlobalContextEntry
|
kind: GlobalContextEntry
|
||||||
metadata:
|
metadata:
|
||||||
name: deployments
|
name: gctx-not-ready
|
||||||
spec:
|
spec:
|
||||||
apiCall:
|
apiCall:
|
||||||
urlPath: "/apis/apps/v1/namespaces/test-globalcontext/deployments"
|
urlPath: "/apis/apps/v1/namespaces/test-globalcontext-not-ready/deployments"
|
||||||
refreshInterval: 10s
|
refreshInterval: 10s
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: main-deployment
|
name: main-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-not-ready
|
||||||
labels:
|
labels:
|
||||||
app: main-deployment
|
app: main-deployment
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: test-globalcontext
|
name: test-globalcontext-not-ready
|
||||||
|
|
|
@ -2,6 +2,6 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: new-deployment
|
name: new-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-not-ready
|
||||||
labels:
|
labels:
|
||||||
app: new-deployment
|
app: new-deployment
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: new-deployment
|
name: new-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-not-ready
|
||||||
labels:
|
labels:
|
||||||
app: new-deployment
|
app: new-deployment
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -13,11 +13,13 @@ spec:
|
||||||
file: main-deployment.yaml
|
file: main-deployment.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: gctxentry.yaml
|
file: gctxentry.yaml
|
||||||
|
- sleep:
|
||||||
|
duration: 5s
|
||||||
- apply:
|
- apply:
|
||||||
file: clusterpolicy.yaml
|
file: clusterpolicy.yaml
|
||||||
|
- assert:
|
||||||
|
file: clusterpolicy-ready.yaml
|
||||||
- apply:
|
- apply:
|
||||||
file: new-deployment.yaml
|
file: new-deployment.yaml
|
||||||
- assert:
|
|
||||||
file: clusterpolicy-succeeded.yaml
|
|
||||||
- assert:
|
- assert:
|
||||||
file: new-deployment-exists.yaml
|
file: new-deployment-exists.yaml
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: cpol-resource-correct
|
||||||
|
status:
|
||||||
|
conditions:
|
||||||
|
- reason: Succeeded
|
||||||
|
status: "True"
|
||||||
|
type: Ready
|
|
@ -1,7 +1,7 @@
|
||||||
apiVersion: kyverno.io/v1
|
apiVersion: kyverno.io/v1
|
||||||
kind: ClusterPolicy
|
kind: ClusterPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: namespace-has-coordinator
|
name: cpol-resource-correct
|
||||||
spec:
|
spec:
|
||||||
validationFailureAction: Enforce
|
validationFailureAction: Enforce
|
||||||
failurePolicy: Fail
|
failurePolicy: Fail
|
||||||
|
@ -10,7 +10,7 @@ spec:
|
||||||
context:
|
context:
|
||||||
- name: deploymentCount
|
- name: deploymentCount
|
||||||
globalReference:
|
globalReference:
|
||||||
name: deployments
|
name: gctxentry-resource-correct
|
||||||
jmesPath: "length(@)"
|
jmesPath: "length(@)"
|
||||||
match:
|
match:
|
||||||
all:
|
all:
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
apiVersion: kyverno.io/v2alpha1
|
apiVersion: kyverno.io/v2alpha1
|
||||||
kind: GlobalContextEntry
|
kind: GlobalContextEntry
|
||||||
metadata:
|
metadata:
|
||||||
name: deployments
|
name: gctxentry-resource-correct
|
||||||
spec:
|
spec:
|
||||||
kubernetesResource:
|
kubernetesResource:
|
||||||
group: apps
|
group: apps
|
||||||
version: v1
|
version: v1
|
||||||
resource: deployments
|
resource: deployments
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-resource-correct
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: main-deployment
|
name: main-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-resource-correct
|
||||||
labels:
|
labels:
|
||||||
app: main-deployment
|
app: main-deployment
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: test-globalcontext
|
name: test-globalcontext-resource-correct
|
||||||
|
|
|
@ -2,6 +2,6 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: new-deployment
|
name: new-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-resource-correct
|
||||||
labels:
|
labels:
|
||||||
app: new-deployment
|
app: new-deployment
|
||||||
|
|
|
@ -2,7 +2,7 @@ apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: new-deployment
|
name: new-deployment
|
||||||
namespace: test-globalcontext
|
namespace: test-globalcontext-resource-correct
|
||||||
labels:
|
labels:
|
||||||
app: new-deployment
|
app: new-deployment
|
||||||
spec:
|
spec:
|
||||||
|
|
Loading…
Add table
Reference in a new issue