mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
feat: mutate existing resources (#3669)
* feat: mutate existing, replace GR by UR in webhook server (#3601) * add attributes for post mutation Signed-off-by: ShutingZhao <shuting@nirmata.com> * add UR informer to webhook server Signed-off-by: ShutingZhao <shuting@nirmata.com> * - replace gr with ur in the webhook server; - create ur for mutateExsiting policies Signed-off-by: ShutingZhao <shuting@nirmata.com> * replace gr by ur across entire packages Signed-off-by: ShutingZhao <shuting@nirmata.com> * add YAMLs Signed-off-by: ShutingZhao <shuting@nirmata.com> * update api docs & fix unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * add UR deletion handler Signed-off-by: ShutingZhao <shuting@nirmata.com> * add api docs for v1beta1 Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix clientset method Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix v1beta1 client registration Signed-off-by: ShutingZhao <shuting@nirmata.com> * feat: mutate existing - generates UR for admission requests (#3623) Signed-off-by: ShutingZhao <shuting@nirmata.com> * replace with UR in policy controller generate rules (#3635) Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * - enable mutate engine to process mutateExisting rules; - add unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * implemented ur background reconciliation for mutateExisting policies Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix webhook update error Signed-off-by: ShutingZhao <shuting@nirmata.com> * temporary comment out new unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * feat: mutate existing, replace GR by UR in webhook server (#3601) * add attributes for post mutation Signed-off-by: ShutingZhao <shuting@nirmata.com> * add UR informer to webhook server Signed-off-by: ShutingZhao <shuting@nirmata.com> * - replace gr with ur in the webhook server; - create ur for mutateExsiting policies Signed-off-by: ShutingZhao <shuting@nirmata.com> * replace gr by ur across entire packages Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix missing policy.kyverno.io/policy-name label (#3599) Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * refactor cli code from pkg to cmd (#3591) * refactor cli code from pkg to cmd Signed-off-by: Mritunjay Sharma <mritunjaysharma394@gmail.com> * fixes in imports Signed-off-by: Mritunjay Sharma <mritunjaysharma394@gmail.com> * fixes tests Signed-off-by: Mritunjay Sharma <mritunjaysharma394@gmail.com> * fixed conflicts Signed-off-by: Mritunjay Sharma <mritunjaysharma394@gmail.com> * moved non-commands to utils Signed-off-by: Mritunjay Sharma <mritunjaysharma394@gmail.com> Co-authored-by: Vyankatesh Kudtarkar <vyankateshkd@gmail.com> * add YAMLs Signed-off-by: ShutingZhao <shuting@nirmata.com> * update api docs & fix unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * add UR deletion handler Signed-off-by: ShutingZhao <shuting@nirmata.com> * add api docs for v1beta1 Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix clientset method Signed-off-by: ShutingZhao <shuting@nirmata.com> * add-kms-libraries for cosign (#3603) * add-kms-libraries Signed-off-by: anushkamittal20 <anumittal4641@gmail.com> * Shifted providers to cosign package Signed-off-by: anushkamittal20 <anumittal4641@gmail.com> Signed-off-by: ShutingZhao <shuting@nirmata.com> * Add support for custom image extractors (#3596) Signed-off-by: Sambhav Kothari <skothari44@bloomberg.net> * Update vulnerable dependencies (#3577) Signed-off-by: Shubham Gupta <shubham.gupta2956@gmail.com> Co-authored-by: Jim Bugwadia <jim@nirmata.com> Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix v1beta1 client registration Signed-off-by: ShutingZhao <shuting@nirmata.com> * feat: mutate existing - generates UR for admission requests (#3623) Signed-off-by: ShutingZhao <shuting@nirmata.com> * updating version in Chart.yaml (#3618) * updatimg version in Chart.yaml Signed-off-by: Prateeknandle <prateeknandle@gmail.com> * changes from, make gen-helm Signed-off-by: Prateeknandle <prateeknandle@gmail.com> Co-authored-by: Vyankatesh Kudtarkar <vyankateshkd@gmail.com> Signed-off-by: ShutingZhao <shuting@nirmata.com> * Allow kyverno-policies to have preconditions defined (#3606) * Allow kyverno-policies to have preconditions defined Signed-off-by: Trey Dockendorf <tdockendorf@osc.edu> * Fix docs Signed-off-by: Trey Dockendorf <tdockendorf@osc.edu> Signed-off-by: ShutingZhao <shuting@nirmata.com> * replace with UR in policy controller generate rules (#3635) Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> Signed-off-by: ShutingZhao <shuting@nirmata.com> * - enable mutate engine to process mutateExisting rules; - add unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * implemented ur background reconciliation for mutateExisting policies Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix webhook update error Signed-off-by: ShutingZhao <shuting@nirmata.com> * temporary comment out new unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * Image verify attestors (#3614) * fix logs Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix logs Signed-off-by: Jim Bugwadia <jim@nirmata.com> * support multiple attestors Signed-off-by: Jim Bugwadia <jim@nirmata.com> * rm CLI tests (not currently supported) Signed-off-by: Jim Bugwadia <jim@nirmata.com> * apply attestor repo Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix linter issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix entryError assignment Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * format Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add intermediary certs Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Allow defining imagePullSecrets (#3633) * Allow defining imagePullSecrets Signed-off-by: Trey Dockendorf <tdockendorf@osc.edu> * Use dict for imagePullSecrets Signed-off-by: Trey Dockendorf <tdockendorf@osc.edu> * Simplify how imagePullSecrets is defined Signed-off-by: Trey Dockendorf <tdockendorf@osc.edu> Signed-off-by: ShutingZhao <shuting@nirmata.com> * Fix race condition in pCache (#3632) * fix race condition in pCache Signed-off-by: ShutingZhao <shuting@nirmata.com> * refact: remove unused Run function from generate (#3638) Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * Remove helm mode setting (#3628) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Signed-off-by: ShutingZhao <shuting@nirmata.com> * refactor: image utils (#3630) Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Signed-off-by: ShutingZhao <shuting@nirmata.com> * -resolve lift comments; -fix informer sync issue Signed-off-by: ShutingZhao <shuting@nirmata.com> * refact the update request cleanup controller Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * - fix delete request for mutateExisting; - fix context variable substitution; - improve logging Signed-off-by: ShutingZhao <shuting@nirmata.com> * - enable events; - add last applied annotation Signed-off-by: ShutingZhao <shuting@nirmata.com> * enable mutate existing on policy creation Signed-off-by: ShutingZhao <shuting@nirmata.com> * update autogen code Signed-off-by: ShutingZhao <shuting@nirmata.com> * merge main Signed-off-by: ShutingZhao <shuting@nirmata.com> * add unit tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * address list comments Signed-off-by: ShutingZhao <shuting@nirmata.com> * update api docs Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix "Implicit memory aliasing in for loop" Signed-off-by: ShutingZhao <shuting@nirmata.com> * remove unused definitions Signed-off-by: ShutingZhao <shuting@nirmata.com> * update api docs Signed-off-by: ShutingZhao <shuting@nirmata.com> Co-authored-by: Prateek Pandey <prateek.pandey@nirmata.com> Co-authored-by: Mritunjay Kumar Sharma <mritunjaysharma394@gmail.com> Co-authored-by: Vyankatesh Kudtarkar <vyankateshkd@gmail.com> Co-authored-by: Anushka Mittal <55237170+anushkamittal20@users.noreply.github.com> Co-authored-by: Sambhav Kothari <sambhavs.email@gmail.com> Co-authored-by: Shubham Gupta <shubham.gupta2956@gmail.com> Co-authored-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Prateek Nandle <56027872+Prateeknandle@users.noreply.github.com> Co-authored-by: treydock <tdockendorf@osc.edu> Co-authored-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
This commit is contained in:
parent
cbf93ff004
commit
2a656f6de0
82 changed files with 4239 additions and 1191 deletions
1
Makefile
1
Makefile
|
@ -156,6 +156,7 @@ generate-api-docs: gen-crd-api-reference-docs ## Generate api reference docs
|
|||
rm -rf docs/crd
|
||||
mkdir docs/crd
|
||||
gen-crd-api-reference-docs -v 6 -api-dir ./api/kyverno/v1alpha2 -config docs/config.json -template-dir docs/template -out-file docs/crd/v1alpha2/index.html
|
||||
gen-crd-api-reference-docs -v 6 -api-dir ./api/kyverno/v1beta1 -config docs/config.json -template-dir docs/template -out-file docs/crd/v1beta1/index.html
|
||||
gen-crd-api-reference-docs -v 6 -api-dir ./api/kyverno/v1 -config docs/config.json -template-dir docs/template -out-file docs/crd/v1/index.html
|
||||
|
||||
.PHONY: verify-api-docs
|
||||
|
|
|
@ -215,6 +215,18 @@ type ResourceFilter struct {
|
|||
|
||||
// Mutation defines how resource are modified.
|
||||
type Mutation struct {
|
||||
|
||||
// mutateExisting controls whether to mutate existing resource ONLY
|
||||
// The existing resources will be mutated ONLY if set to "true".
|
||||
// Otherwise all resources including admission requests are mutated.
|
||||
// Optional. Defaults to "false" if not specified.
|
||||
// +optional
|
||||
MutateExisting bool `json:"mutateExisting,omitempty" yaml:"mutatingExisting,omitempty"`
|
||||
|
||||
// Targets defines the target resources to be mutated.
|
||||
// +optional
|
||||
Targets []TargetMutation `json:"targets,omitempty" yaml:"targets,omitempty"`
|
||||
|
||||
// PatchStrategicMerge is a strategic merge patch used to modify resources.
|
||||
// See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
// and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
|
@ -231,6 +243,12 @@ type Mutation struct {
|
|||
ForEachMutation []*ForEachMutation `json:"foreach,omitempty" yaml:"foreach,omitempty"`
|
||||
}
|
||||
|
||||
type TargetMutation struct {
|
||||
// ResourceSpec specifies the target resource information.
|
||||
// +optional
|
||||
ResourceSpec `json:",omitempty" yaml:",omitempty"`
|
||||
}
|
||||
|
||||
func (m *Mutation) GetPatchStrategicMerge() apiextensions.JSON {
|
||||
return FromJSON(m.RawPatchStrategicMerge)
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@ type ResourceDescription struct {
|
|||
|
||||
// Name is the name of the resource. The name supports wildcard characters
|
||||
// "*" (matches zero or many characters) and "?" (at least one character).
|
||||
// NOTE: "Name" is being deprecated in favor of "Names".
|
||||
// +optional
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
|
||||
// Names are the names of the resources. Each name supports wildcard characters
|
||||
// "*" (matches zero or many characters) and "?" (at least one character).
|
||||
// NOTE: "Name" is being deprecated in favor of "Names".
|
||||
// +optional
|
||||
Names []string `json:"names,omitempty" yaml:"names,omitempty"`
|
||||
|
||||
|
|
|
@ -87,6 +87,11 @@ func (r *Rule) HasGenerate() bool {
|
|||
return !reflect.DeepEqual(r.Generation, Generation{})
|
||||
}
|
||||
|
||||
// IsMutatingExisting checks if the mutate rule applies to existing resources
|
||||
func (r *Rule) IsMutateExisting() bool {
|
||||
return r.Mutation.Targets != nil
|
||||
}
|
||||
|
||||
func (r *Rule) GetAnyAllConditions() apiextensions.JSON {
|
||||
return FromJSON(r.RawAnyAllConditions)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ type ValidationFailureAction string
|
|||
const (
|
||||
// Enforce blocks the request on failure
|
||||
Enforce ValidationFailureAction = "enforce"
|
||||
// Audit indicates not to block the request on failure, but report failiures as policy violations
|
||||
// Audit indicates not to block the request on failure, but report failures as policy violations
|
||||
Audit ValidationFailureAction = "audit"
|
||||
)
|
||||
|
||||
|
|
|
@ -745,6 +745,11 @@ func (in *MatchResources) DeepCopy() *MatchResources {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Mutation) DeepCopyInto(out *Mutation) {
|
||||
*out = *in
|
||||
if in.Targets != nil {
|
||||
in, out := &in.Targets, &out.Targets
|
||||
*out = make([]TargetMutation, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.RawPatchStrategicMerge != nil {
|
||||
in, out := &in.RawPatchStrategicMerge, &out.RawPatchStrategicMerge
|
||||
*out = new(apiextensionsv1.JSON)
|
||||
|
@ -1110,6 +1115,22 @@ func (in *StaticKeyAttestor) DeepCopy() *StaticKeyAttestor {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TargetMutation) DeepCopyInto(out *TargetMutation) {
|
||||
*out = *in
|
||||
out.ResourceSpec = in.ResourceSpec
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetMutation.
|
||||
func (in *TargetMutation) DeepCopy() *TargetMutation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TargetMutation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UserInfo) DeepCopyInto(out *UserInfo) {
|
||||
*out = *in
|
||||
|
|
21
api/kyverno/v1beta1/doc.go
Normal file
21
api/kyverno/v1beta1/doc.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package v1beta1 contains API Schema definitions for the policy v1alpha1 API group
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=kyverno.io
|
||||
package v1beta1
|
|
@ -52,7 +52,7 @@ type UpdateRequestStatus struct {
|
|||
// +kubebuilder:printcolumn:name="ResourceNamespace",type="string",JSONPath=".spec.resource.namespace"
|
||||
// +kubebuilder:printcolumn:name="status",type="string",JSONPath=".status.state"
|
||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
|
||||
// +kubebuilder:resource:shortName=gr
|
||||
// +kubebuilder:resource:shortName=ur
|
||||
type UpdateRequest struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
@ -65,8 +65,19 @@ type UpdateRequest struct {
|
|||
Status UpdateRequestStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
type RequestType string
|
||||
|
||||
const (
|
||||
Mutate RequestType = "mutate"
|
||||
Generate RequestType = "generate"
|
||||
)
|
||||
|
||||
// UpdateRequestSpec stores the request specification.
|
||||
type UpdateRequestSpec struct {
|
||||
// Type represents request type for background processing
|
||||
// +kubebuilder:validation:Enum=mutate;generate
|
||||
Type RequestType `json:"requestType,omitempty" yaml:"requestType,omitempty"`
|
||||
|
||||
// Specifies the name of the policy.
|
||||
Policy string `json:"policy" yaml:"policy"`
|
||||
|
||||
|
@ -139,3 +150,7 @@ type UpdateRequestList struct {
|
|||
func init() {
|
||||
SchemeBuilder.Register(&UpdateRequest{}, &UpdateRequestList{})
|
||||
}
|
||||
|
||||
func (s *UpdateRequestSpec) GetRequestType() RequestType {
|
||||
return s.Type
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ metadata:
|
|||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '1'
|
||||
internal.config.kubernetes.io/index: '1'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
|
@ -155,10 +154,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -281,10 +280,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -402,10 +401,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -585,10 +584,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -711,10 +710,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -832,10 +831,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1082,12 +1081,34 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing resource ONLY The existing resources will be mutated ONLY if set to "true". Otherwise all resources including admission requests are mutated. Optional. Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
patchesJson6902:
|
||||
description: PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be unique within the policy.
|
||||
|
@ -1661,10 +1682,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1787,10 +1808,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1908,10 +1929,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2091,10 +2112,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2217,10 +2238,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2338,10 +2359,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2588,12 +2609,34 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing resource ONLY The existing resources will be mutated ONLY if set to "true". Otherwise all resources including admission requests are mutated. Optional. Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
patchesJson6902:
|
||||
description: PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be unique within the policy.
|
||||
|
@ -3000,7 +3043,6 @@ metadata:
|
|||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '2'
|
||||
internal.config.kubernetes.io/index: '2'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
|
@ -3272,7 +3314,6 @@ metadata:
|
|||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '3'
|
||||
internal.config.kubernetes.io/index: '3'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
|
@ -3544,7 +3585,6 @@ metadata:
|
|||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '4'
|
||||
internal.config.kubernetes.io/index: '4'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
|
@ -3728,7 +3768,6 @@ metadata:
|
|||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '5'
|
||||
internal.config.kubernetes.io/index: '5'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
|
@ -3878,10 +3917,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4004,10 +4043,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4125,10 +4164,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4308,10 +4347,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4434,10 +4473,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4555,10 +4594,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4805,12 +4844,34 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing resource ONLY The existing resources will be mutated ONLY if set to "true". Otherwise all resources including admission requests are mutated. Optional. Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
patchesJson6902:
|
||||
description: PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be unique within the policy.
|
||||
|
@ -5384,10 +5445,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -5510,10 +5571,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -5631,10 +5692,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -5814,10 +5875,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -5940,10 +6001,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6061,10 +6122,10 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character). NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6311,12 +6372,34 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing resource ONLY The existing resources will be mutated ONLY if set to "true". Otherwise all resources including admission requests are mutated. Optional. Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
patchesJson6902:
|
||||
description: PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be unique within the policy.
|
||||
|
@ -6723,7 +6806,6 @@ metadata:
|
|||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '6'
|
||||
internal.config.kubernetes.io/index: '6'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
|
@ -6995,7 +7077,6 @@ metadata:
|
|||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '7'
|
||||
internal.config.kubernetes.io/index: '7'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
|
@ -7260,4 +7341,191 @@ status:
|
|||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
config.kubernetes.io/index: '8'
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
app.kubernetes.io/instance: kyverno
|
||||
app.kubernetes.io/name: kyverno
|
||||
app.kubernetes.io/part-of: kyverno
|
||||
app.kubernetes.io/version: latest
|
||||
name: updaterequests.kyverno.io
|
||||
spec:
|
||||
group: kyverno.io
|
||||
names:
|
||||
kind: UpdateRequest
|
||||
listKind: UpdateRequestList
|
||||
plural: updaterequests
|
||||
shortNames:
|
||||
- ur
|
||||
singular: updaterequest
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.policy
|
||||
name: Policy
|
||||
type: string
|
||||
- jsonPath: .spec.resource.kind
|
||||
name: ResourceKind
|
||||
type: string
|
||||
- jsonPath: .spec.resource.name
|
||||
name: ResourceName
|
||||
type: string
|
||||
- jsonPath: .spec.resource.namespace
|
||||
name: ResourceNamespace
|
||||
type: string
|
||||
- jsonPath: .status.state
|
||||
name: status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: UpdateRequestStatus is a request to process mutate and generate rules in background.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec is the information to identify the update request.
|
||||
properties:
|
||||
context:
|
||||
description: Context ...
|
||||
properties:
|
||||
admissionRequestInfo:
|
||||
description: AdmissionRequestInfoObject stores the admission request and operation details
|
||||
properties:
|
||||
admissionRequest:
|
||||
type: string
|
||||
operation:
|
||||
description: Operation is the type of resource operation being checked for admission control
|
||||
type: string
|
||||
type: object
|
||||
userInfo:
|
||||
description: RequestInfo contains permission info carried in an admission request.
|
||||
properties:
|
||||
clusterRoles:
|
||||
description: ClusterRoles is a list of possible clusterRoles send the request.
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
roles:
|
||||
description: Roles is a list of possible role send the request.
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
userInfo:
|
||||
description: UserInfo is the userInfo carried in the admission request.
|
||||
properties:
|
||||
extra:
|
||||
additionalProperties:
|
||||
description: ExtraValue masks the value so protobuf can generate
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
description: Any additional information provided by the authenticator.
|
||||
type: object
|
||||
groups:
|
||||
description: The names of groups this user is a part of.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
uid:
|
||||
description: A unique value that identifies this user across time. If this user is deleted and another user by the same name is added, they will have different UIDs.
|
||||
type: string
|
||||
username:
|
||||
description: The name that uniquely identifies this user among all active users.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
policy:
|
||||
description: Specifies the name of the policy.
|
||||
type: string
|
||||
requestType:
|
||||
description: Type represents request type for background processing
|
||||
enum:
|
||||
- mutate
|
||||
- generate
|
||||
type: string
|
||||
resource:
|
||||
description: ResourceSpec is the information to identify the update request.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- context
|
||||
- policy
|
||||
- resource
|
||||
type: object
|
||||
status:
|
||||
description: Status contains statistics related to update request.
|
||||
properties:
|
||||
generatedResources:
|
||||
description: This will track the resources that are updated by the generate Policy. Will be used during clean up resources.
|
||||
items:
|
||||
description: ResourceSpec contains information to identify a resource.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
message:
|
||||
description: Specifies request status message.
|
||||
type: string
|
||||
state:
|
||||
description: State represents state of the generate request.
|
||||
type: string
|
||||
required:
|
||||
- state
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
{{- end }}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-git/go-billy/v5/memfs"
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
|
@ -246,7 +246,7 @@ func applyCommandHelper(resourcePaths []string, userInfoPath string, cluster boo
|
|||
}
|
||||
|
||||
// get the user info as request info from a different file
|
||||
var userInfo v1.RequestInfo
|
||||
var userInfo v1beta1.RequestInfo
|
||||
if userInfoPath != "" {
|
||||
userInfo, err = common.GetUserInfoFromPath(fs, userInfoPath, false, "")
|
||||
if err != nil {
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/go-git/go-billy/v5/memfs"
|
||||
"github.com/kataras/tablewriter"
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
report "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
|
@ -750,7 +751,7 @@ func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, isGit bool,
|
|||
}
|
||||
|
||||
// get the user info as request info from a different file
|
||||
var userInfo v1.RequestInfo
|
||||
var userInfo v1beta1.RequestInfo
|
||||
if userInfoFile != "" {
|
||||
userInfo, err = common.GetUserInfoFromPath(fs, userInfoFile, isGit, policyResourcePath)
|
||||
if err != nil {
|
||||
|
|
|
@ -13,21 +13,21 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-logr/logr"
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
report "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
ut "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/policymutation"
|
||||
"github.com/kyverno/kyverno/pkg/policyreport"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
|
@ -442,7 +442,7 @@ func MutatePolicies(policies []v1.PolicyInterface) ([]v1.PolicyInterface, error)
|
|||
|
||||
// ApplyPolicyOnResource - function to apply policy on resource
|
||||
func ApplyPolicyOnResource(policy v1.PolicyInterface, resource *unstructured.Unstructured,
|
||||
mutateLogPath string, mutateLogPathIsDir bool, variables map[string]string, userInfo v1.RequestInfo, policyReport bool,
|
||||
mutateLogPath string, mutateLogPathIsDir bool, variables map[string]string, userInfo v1beta1.RequestInfo, policyReport bool,
|
||||
namespaceSelectorMap map[string]map[string]string, stdin bool, rc *ResultCounts,
|
||||
printPatchResource bool) ([]*response.EngineResponse, policyreport.Info, error) {
|
||||
|
||||
|
@ -595,7 +595,7 @@ OuterLoop:
|
|||
JSONContext: context.NewContext(),
|
||||
NamespaceLabels: namespaceLabels,
|
||||
}
|
||||
generateResponse := engine.Generate(policyContext)
|
||||
generateResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
if generateResponse != nil {
|
||||
engineResponses = append(engineResponses, generateResponse)
|
||||
}
|
||||
|
@ -1051,8 +1051,8 @@ func GetPatchedResourceFromPath(fs billy.Filesystem, path string, isGit bool, po
|
|||
}
|
||||
|
||||
//GetUserInfoFromPath - get the request info as user info from a given path
|
||||
func GetUserInfoFromPath(fs billy.Filesystem, path string, isGit bool, policyResourcePath string) (v1.RequestInfo, error) {
|
||||
userInfo := &v1.RequestInfo{}
|
||||
func GetUserInfoFromPath(fs billy.Filesystem, path string, isGit bool, policyResourcePath string) (v1beta1.RequestInfo, error) {
|
||||
userInfo := &v1beta1.RequestInfo{}
|
||||
|
||||
if isGit {
|
||||
filep, err := fs.Open(filepath.Join(policyResourcePath, path))
|
||||
|
|
|
@ -3,7 +3,7 @@ package common
|
|||
import (
|
||||
"testing"
|
||||
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/toggle"
|
||||
ut "github.com/kyverno/kyverno/pkg/utils"
|
||||
"gotest.tools/assert"
|
||||
|
@ -100,7 +100,7 @@ func Test_NamespaceSelector(t *testing.T) {
|
|||
for _, tc := range testcases {
|
||||
policyArray, _ := ut.GetPolicy(tc.policy)
|
||||
resourceArray, _ := GetResource(tc.resource)
|
||||
ApplyPolicyOnResource(policyArray[0], resourceArray[0], "", false, nil, v1.RequestInfo{}, false, tc.namespaceSelectorMap, false, rc, false)
|
||||
ApplyPolicyOnResource(policyArray[0], resourceArray[0], "", false, nil, v1beta1.RequestInfo{}, false, tc.namespaceSelectorMap, false, rc, false)
|
||||
assert.Equal(t, int64(rc.Pass), int64(tc.result.Pass))
|
||||
assert.Equal(t, int64(rc.Fail), int64(tc.result.Fail))
|
||||
// TODO: autogen rules seem to not be present when autogen internals is disabled
|
||||
|
|
|
@ -43,7 +43,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/version"
|
||||
"github.com/kyverno/kyverno/pkg/webhookconfig"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks"
|
||||
webhookgenerate "github.com/kyverno/kyverno/pkg/webhooks/generate"
|
||||
webhookgenerate "github.com/kyverno/kyverno/pkg/webhooks/updaterequest"
|
||||
)
|
||||
|
||||
const resyncPeriod = 15 * time.Minute
|
||||
|
@ -137,10 +137,6 @@ func main() {
|
|||
}
|
||||
|
||||
// KYVERNO CRD CLIENT
|
||||
// access CRD resources
|
||||
// - ClusterPolicy, Policy
|
||||
// - ClusterPolicyReport, PolicyReport
|
||||
// - GenerateRequest
|
||||
pclient, err := kyvernoclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
setupLog.Error(err, "Failed to create client")
|
||||
|
@ -192,12 +188,7 @@ func main() {
|
|||
cosign.ImageSignatureRepository = imageSignatureRepository
|
||||
}
|
||||
|
||||
// KYVERNO CRD INFORMER
|
||||
// watches CRD resources:
|
||||
// - ClusterPolicy, Policy
|
||||
// - ClusterPolicyReport, PolicyReport
|
||||
// - GenerateRequest
|
||||
// - ClusterReportChangeRequest, ReportChangeRequest
|
||||
// KYVERNO CRD INFORMERS
|
||||
pInformer := kyvernoinformer.NewSharedInformerFactoryWithOptions(pclient, policyControllerResyncPeriod)
|
||||
|
||||
// EVENT GENERATOR
|
||||
|
@ -312,6 +303,7 @@ func main() {
|
|||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
pInformer.Kyverno().V1().Policies(),
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
configData,
|
||||
eventGenerator,
|
||||
reportReqGen,
|
||||
|
@ -328,7 +320,11 @@ func main() {
|
|||
}
|
||||
|
||||
// GENERATE REQUEST GENERATOR
|
||||
grgen := webhookgenerate.NewGenerator(pclient, pInformer.Kyverno().V1().GenerateRequests(), stopCh, log.Log.WithName("GenerateRequestGenerator"))
|
||||
grgen := webhookgenerate.NewGenerator(pclient,
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
stopCh,
|
||||
log.Log.WithName("UpdateRequestGenerator"))
|
||||
|
||||
// GENERATE CONTROLLER
|
||||
// - applies generate rules on resources based on generate requests created by webhook
|
||||
|
@ -339,9 +335,10 @@ func main() {
|
|||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
pInformer.Kyverno().V1().Policies(),
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
eventGenerator,
|
||||
kubeInformer.Core().V1().Namespaces(),
|
||||
log.Log.WithName("GenerateController"),
|
||||
log.Log.WithName("BackgroundController"),
|
||||
configData,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -358,6 +355,7 @@ func main() {
|
|||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
pInformer.Kyverno().V1().Policies(),
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
kubeInformer.Core().V1().Namespaces(),
|
||||
log.Log.WithName("GenerateCleanUpController"),
|
||||
)
|
||||
|
@ -399,7 +397,7 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
registerWrapperRetry := common.RetryFunc(time.Second, webhookRegistrationTimeout, webhookCfg.Register, setupLog)
|
||||
registerWrapperRetry := common.RetryFunc(time.Second, webhookRegistrationTimeout, webhookCfg.Register, "failed to register webhook", setupLog)
|
||||
registerWebhookConfigurations := func() {
|
||||
certManager.InitTLSPemPair()
|
||||
webhookCfg.Start()
|
||||
|
@ -460,6 +458,7 @@ func main() {
|
|||
client,
|
||||
tlsPair,
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
pInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
pInformer.Kyverno().V1().ClusterPolicies(),
|
||||
kubeInformer.Rbac().V1().RoleBindings(),
|
||||
kubeInformer.Rbac().V1().ClusterRoleBindings(),
|
||||
|
|
|
@ -7,5 +7,6 @@ resources:
|
|||
- ./kyverno.io_generaterequests.yaml
|
||||
- ./kyverno.io_policies.yaml
|
||||
- ./kyverno.io_reportchangerequests.yaml
|
||||
- ./kyverno.io_updaterequests.yaml
|
||||
- ./wgpolicyk8s.io_clusterpolicyreports.yaml
|
||||
- ./wgpolicyk8s.io_policyreports.yaml
|
|
@ -198,17 +198,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -413,17 +413,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -624,15 +624,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -909,17 +909,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1124,17 +1124,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1335,15 +1335,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1730,6 +1730,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -1740,6 +1747,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -2636,17 +2663,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2851,17 +2878,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3062,15 +3089,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3347,17 +3374,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3562,17 +3589,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3773,15 +3800,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4168,6 +4195,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -4178,6 +4212,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
|
|
@ -199,17 +199,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -414,17 +414,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -625,15 +625,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -910,17 +910,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1125,17 +1125,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1336,15 +1336,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1731,6 +1731,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -1741,6 +1748,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -2638,17 +2665,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2853,17 +2880,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3064,15 +3091,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3349,17 +3376,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3564,17 +3591,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3775,15 +3802,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4170,6 +4197,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -4180,6 +4214,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
|
|
@ -13,7 +13,7 @@ spec:
|
|||
listKind: UpdateRequestList
|
||||
plural: updaterequests
|
||||
shortNames:
|
||||
- gr
|
||||
- ur
|
||||
singular: updaterequest
|
||||
scope: Namespaced
|
||||
versions:
|
||||
|
@ -123,6 +123,12 @@ spec:
|
|||
policy:
|
||||
description: Specifies the name of the policy.
|
||||
type: string
|
||||
requestType:
|
||||
description: Type represents request type for background processing
|
||||
enum:
|
||||
- mutate
|
||||
- generate
|
||||
type: string
|
||||
resource:
|
||||
description: ResourceSpec is the information to identify the update
|
||||
request.
|
||||
|
|
|
@ -215,17 +215,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -430,17 +430,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -641,15 +641,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -926,17 +926,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1141,17 +1141,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1352,15 +1352,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1747,6 +1747,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -1757,6 +1764,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -2653,17 +2680,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2868,17 +2895,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3079,15 +3106,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3364,17 +3391,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3579,17 +3606,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3790,15 +3817,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4185,6 +4212,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -4195,6 +4229,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -5981,17 +6035,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6196,17 +6250,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6407,15 +6461,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6692,17 +6746,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6907,17 +6961,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -7118,15 +7172,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -7513,6 +7567,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -7523,6 +7584,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -8420,17 +8501,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -8635,17 +8716,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -8846,15 +8927,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9131,17 +9212,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9346,17 +9427,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9557,15 +9638,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9952,6 +10033,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -9962,6 +10050,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -11342,6 +11450,210 @@ status:
|
|||
conditions: []
|
||||
storedVersions: []
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app.kubernetes.io/component: kyverno
|
||||
app.kubernetes.io/instance: kyverno
|
||||
app.kubernetes.io/name: kyverno
|
||||
app.kubernetes.io/part-of: kyverno
|
||||
app.kubernetes.io/version: latest
|
||||
name: updaterequests.kyverno.io
|
||||
spec:
|
||||
group: kyverno.io
|
||||
names:
|
||||
kind: UpdateRequest
|
||||
listKind: UpdateRequestList
|
||||
plural: updaterequests
|
||||
shortNames:
|
||||
- ur
|
||||
singular: updaterequest
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.policy
|
||||
name: Policy
|
||||
type: string
|
||||
- jsonPath: .spec.resource.kind
|
||||
name: ResourceKind
|
||||
type: string
|
||||
- jsonPath: .spec.resource.name
|
||||
name: ResourceName
|
||||
type: string
|
||||
- jsonPath: .spec.resource.namespace
|
||||
name: ResourceNamespace
|
||||
type: string
|
||||
- jsonPath: .status.state
|
||||
name: status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: UpdateRequestStatus is a request to process mutate and generate
|
||||
rules in background.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec is the information to identify the update request.
|
||||
properties:
|
||||
context:
|
||||
description: Context ...
|
||||
properties:
|
||||
admissionRequestInfo:
|
||||
description: AdmissionRequestInfoObject stores the admission request
|
||||
and operation details
|
||||
properties:
|
||||
admissionRequest:
|
||||
type: string
|
||||
operation:
|
||||
description: Operation is the type of resource operation being
|
||||
checked for admission control
|
||||
type: string
|
||||
type: object
|
||||
userInfo:
|
||||
description: RequestInfo contains permission info carried in an
|
||||
admission request.
|
||||
properties:
|
||||
clusterRoles:
|
||||
description: ClusterRoles is a list of possible clusterRoles
|
||||
send the request.
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
roles:
|
||||
description: Roles is a list of possible role send the request.
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
userInfo:
|
||||
description: UserInfo is the userInfo carried in the admission
|
||||
request.
|
||||
properties:
|
||||
extra:
|
||||
additionalProperties:
|
||||
description: ExtraValue masks the value so protobuf
|
||||
can generate
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
description: Any additional information provided by the
|
||||
authenticator.
|
||||
type: object
|
||||
groups:
|
||||
description: The names of groups this user is a part of.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
uid:
|
||||
description: A unique value that identifies this user
|
||||
across time. If this user is deleted and another user
|
||||
by the same name is added, they will have different
|
||||
UIDs.
|
||||
type: string
|
||||
username:
|
||||
description: The name that uniquely identifies this user
|
||||
among all active users.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
policy:
|
||||
description: Specifies the name of the policy.
|
||||
type: string
|
||||
requestType:
|
||||
description: Type represents request type for background processing
|
||||
enum:
|
||||
- mutate
|
||||
- generate
|
||||
type: string
|
||||
resource:
|
||||
description: ResourceSpec is the information to identify the update
|
||||
request.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- context
|
||||
- policy
|
||||
- resource
|
||||
type: object
|
||||
status:
|
||||
description: Status contains statistics related to update request.
|
||||
properties:
|
||||
generatedResources:
|
||||
description: This will track the resources that are updated by the
|
||||
generate Policy. Will be used during clean up resources.
|
||||
items:
|
||||
description: ResourceSpec contains information to identify a resource.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
message:
|
||||
description: Specifies request status message.
|
||||
type: string
|
||||
state:
|
||||
description: State represents state of the generate request.
|
||||
type: string
|
||||
required:
|
||||
- state
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
|
@ -11586,6 +11898,8 @@ rules:
|
|||
- clusterpolicies/status
|
||||
- generaterequests
|
||||
- generaterequests/status
|
||||
- updaterequests
|
||||
- updaterequests/status
|
||||
- reportchangerequests
|
||||
- reportchangerequests/status
|
||||
- clusterreportchangerequests
|
||||
|
|
|
@ -204,17 +204,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -419,17 +419,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -630,15 +630,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -915,17 +915,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1130,17 +1130,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1341,15 +1341,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -1736,6 +1736,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -1746,6 +1753,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -2642,17 +2669,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -2857,17 +2884,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3068,15 +3095,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3353,17 +3380,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3568,17 +3595,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -3779,15 +3806,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -4174,6 +4201,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -4184,6 +4218,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -5946,17 +6000,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6161,17 +6215,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6372,15 +6426,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6657,17 +6711,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -6872,17 +6926,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -7083,15 +7137,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -7478,6 +7532,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -7488,6 +7549,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -8385,17 +8466,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -8600,17 +8681,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -8811,15 +8892,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9096,17 +9177,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9311,17 +9392,17 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource.
|
||||
description: 'Name is the name of the resource.
|
||||
The name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character). NOTE: "Name" is being deprecated
|
||||
in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one
|
||||
character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9522,15 +9603,15 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
name:
|
||||
description: Name is the name of the resource. The name
|
||||
supports wildcard characters "*" (matches zero or
|
||||
many characters) and "?" (at least one character).
|
||||
description: 'Name is the name of the resource. The
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
type: string
|
||||
names:
|
||||
description: 'Names are the names of the resources.
|
||||
Each name supports wildcard characters "*" (matches
|
||||
zero or many characters) and "?" (at least one character).
|
||||
NOTE: "Name" is being deprecated in favor of "Names".'
|
||||
description: Names are the names of the resources. Each
|
||||
name supports wildcard characters "*" (matches zero
|
||||
or many characters) and "?" (at least one character).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@ -9917,6 +9998,13 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
mutateExisting:
|
||||
description: mutateExisting controls whether to mutate existing
|
||||
resource ONLY The existing resources will be mutated ONLY
|
||||
if set to "true". Otherwise all resources including admission
|
||||
requests are mutated. Optional. Defaults to "false" if
|
||||
not specified.
|
||||
type: boolean
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge patch
|
||||
used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
|
@ -9927,6 +10015,26 @@ spec:
|
|||
Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.
|
||||
type: string
|
||||
targets:
|
||||
description: Targets defines the target resources to be
|
||||
mutated.
|
||||
items:
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: Name is a label to identify the rule, It must be
|
||||
|
@ -11295,6 +11403,204 @@ status:
|
|||
conditions: []
|
||||
storedVersions: []
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: updaterequests.kyverno.io
|
||||
spec:
|
||||
group: kyverno.io
|
||||
names:
|
||||
kind: UpdateRequest
|
||||
listKind: UpdateRequestList
|
||||
plural: updaterequests
|
||||
shortNames:
|
||||
- ur
|
||||
singular: updaterequest
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.policy
|
||||
name: Policy
|
||||
type: string
|
||||
- jsonPath: .spec.resource.kind
|
||||
name: ResourceKind
|
||||
type: string
|
||||
- jsonPath: .spec.resource.name
|
||||
name: ResourceName
|
||||
type: string
|
||||
- jsonPath: .spec.resource.namespace
|
||||
name: ResourceNamespace
|
||||
type: string
|
||||
- jsonPath: .status.state
|
||||
name: status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: UpdateRequestStatus is a request to process mutate and generate
|
||||
rules in background.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec is the information to identify the update request.
|
||||
properties:
|
||||
context:
|
||||
description: Context ...
|
||||
properties:
|
||||
admissionRequestInfo:
|
||||
description: AdmissionRequestInfoObject stores the admission request
|
||||
and operation details
|
||||
properties:
|
||||
admissionRequest:
|
||||
type: string
|
||||
operation:
|
||||
description: Operation is the type of resource operation being
|
||||
checked for admission control
|
||||
type: string
|
||||
type: object
|
||||
userInfo:
|
||||
description: RequestInfo contains permission info carried in an
|
||||
admission request.
|
||||
properties:
|
||||
clusterRoles:
|
||||
description: ClusterRoles is a list of possible clusterRoles
|
||||
send the request.
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
roles:
|
||||
description: Roles is a list of possible role send the request.
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
userInfo:
|
||||
description: UserInfo is the userInfo carried in the admission
|
||||
request.
|
||||
properties:
|
||||
extra:
|
||||
additionalProperties:
|
||||
description: ExtraValue masks the value so protobuf
|
||||
can generate
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
description: Any additional information provided by the
|
||||
authenticator.
|
||||
type: object
|
||||
groups:
|
||||
description: The names of groups this user is a part of.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
uid:
|
||||
description: A unique value that identifies this user
|
||||
across time. If this user is deleted and another user
|
||||
by the same name is added, they will have different
|
||||
UIDs.
|
||||
type: string
|
||||
username:
|
||||
description: The name that uniquely identifies this user
|
||||
among all active users.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
policy:
|
||||
description: Specifies the name of the policy.
|
||||
type: string
|
||||
requestType:
|
||||
description: Type represents request type for background processing
|
||||
enum:
|
||||
- mutate
|
||||
- generate
|
||||
type: string
|
||||
resource:
|
||||
description: ResourceSpec is the information to identify the update
|
||||
request.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- context
|
||||
- policy
|
||||
- resource
|
||||
type: object
|
||||
status:
|
||||
description: Status contains statistics related to update request.
|
||||
properties:
|
||||
generatedResources:
|
||||
description: This will track the resources that are updated by the
|
||||
generate Policy. Will be used during clean up resources.
|
||||
items:
|
||||
description: ResourceSpec contains information to identify a resource.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: APIVersion specifies resource apiVersion.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind specifies resource kind.
|
||||
type: string
|
||||
name:
|
||||
description: Name specifies the resource name.
|
||||
maxLength: 63
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace specifies resource namespace.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
message:
|
||||
description: Specifies request status message.
|
||||
type: string
|
||||
state:
|
||||
description: State represents state of the generate request.
|
||||
type: string
|
||||
required:
|
||||
- state
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
|
@ -11494,6 +11800,8 @@ rules:
|
|||
- clusterpolicies/status
|
||||
- generaterequests
|
||||
- generaterequests/status
|
||||
- updaterequests
|
||||
- updaterequests/status
|
||||
- reportchangerequests
|
||||
- reportchangerequests/status
|
||||
- clusterreportchangerequests
|
||||
|
|
|
@ -15,6 +15,8 @@ rules:
|
|||
- clusterpolicies/status
|
||||
- generaterequests
|
||||
- generaterequests/status
|
||||
- updaterequests
|
||||
- updaterequests/status
|
||||
- reportchangerequests
|
||||
- reportchangerequests/status
|
||||
- clusterreportchangerequests
|
||||
|
|
|
@ -209,8 +209,8 @@ string
|
|||
<td>
|
||||
<code>conditions</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.*./api/kyverno/v1.AnyAllConditions">
|
||||
[]*./api/kyverno/v1.AnyAllConditions
|
||||
<a href="#kyverno.io/v1.*github.com/realshuting/kyverno/api/kyverno/v1.AnyAllConditions">
|
||||
[]*github.com/realshuting/kyverno/api/kyverno/v1.AnyAllConditions
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
@ -330,8 +330,8 @@ value N, then N must be less than or equal to the size of entries, and at least
|
|||
<td>
|
||||
<code>entries</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.*./api/kyverno/v1.Attestor">
|
||||
[]*./api/kyverno/v1.Attestor
|
||||
<a href="#kyverno.io/v1.*github.com/realshuting/kyverno/api/kyverno/v1.Attestor">
|
||||
[]*github.com/realshuting/kyverno/api/kyverno/v1.Attestor
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
@ -1573,8 +1573,8 @@ Deprecated.</p>
|
|||
<td>
|
||||
<code>attestors</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.*./api/kyverno/v1.AttestorSet">
|
||||
[]*./api/kyverno/v1.AttestorSet
|
||||
<a href="#kyverno.io/v1.*github.com/realshuting/kyverno/api/kyverno/v1.AttestorSet">
|
||||
[]*github.com/realshuting/kyverno/api/kyverno/v1.AttestorSet
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
@ -1586,8 +1586,8 @@ Deprecated.</p>
|
|||
<td>
|
||||
<code>attestations</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.*./api/kyverno/v1.Attestation">
|
||||
[]*./api/kyverno/v1.Attestation
|
||||
<a href="#kyverno.io/v1.*github.com/realshuting/kyverno/api/kyverno/v1.Attestation">
|
||||
[]*github.com/realshuting/kyverno/api/kyverno/v1.Attestation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
@ -1832,6 +1832,35 @@ Please specify under “any” or “all” instead.</p>
|
|||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>mutateExisting</code></br>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>mutateExisting controls whether to mutate existing resource ONLY
|
||||
The existing resources will be mutated ONLY if set to “true”.
|
||||
Otherwise all resources including admission requests are mutated.
|
||||
Optional. Defaults to “false” if not specified.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>targets</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.TargetMutation">
|
||||
[]TargetMutation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Targets defines the target resources to be mutated.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>patchStrategicMerge</code></br>
|
||||
<em>
|
||||
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.JSON
|
||||
|
@ -1861,8 +1890,8 @@ See <a href="https://tools.ietf.org/html/rfc6902">https://tools.ietf.org/html/rf
|
|||
<td>
|
||||
<code>foreach</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.*./api/kyverno/v1.ForEachMutation">
|
||||
[]*./api/kyverno/v1.ForEachMutation
|
||||
<a href="#kyverno.io/v1.*github.com/realshuting/kyverno/api/kyverno/v1.ForEachMutation">
|
||||
[]*github.com/realshuting/kyverno/api/kyverno/v1.ForEachMutation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
@ -2218,7 +2247,8 @@ string
|
|||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Name is the name of the resource. The name supports wildcard characters
|
||||
“*” (matches zero or many characters) and “?” (at least one character).</p>
|
||||
“*” (matches zero or many characters) and “?” (at least one character).
|
||||
NOTE: “Name” is being deprecated in favor of “Names”.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -2231,8 +2261,7 @@ string
|
|||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Names are the names of the resources. Each name supports wildcard characters
|
||||
“*” (matches zero or many characters) and “?” (at least one character).
|
||||
NOTE: “Name” is being deprecated in favor of “Names”.</p>
|
||||
“*” (matches zero or many characters) and “?” (at least one character).</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -2344,7 +2373,7 @@ ResourceDescription
|
|||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1.ResourceFilters">ResourceFilters
|
||||
(<code>[]./api/kyverno/v1.ResourceFilter</code> alias)</p></h3>
|
||||
(<code>[]github.com/realshuting/kyverno/api/kyverno/v1.ResourceFilter</code> alias)</p></h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1.MatchResources">MatchResources</a>)
|
||||
|
@ -2358,7 +2387,8 @@ ResourceDescription
|
|||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1.GenerateRequestSpec">GenerateRequestSpec</a>,
|
||||
<a href="#kyverno.io/v1.GenerateRequestStatus">GenerateRequestStatus</a>,
|
||||
<a href="#kyverno.io/v1.Generation">Generation</a>)
|
||||
<a href="#kyverno.io/v1.Generation">Generation</a>,
|
||||
<a href="#kyverno.io/v1.TargetMutation">TargetMutation</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>ResourceSpec contains information to identify a resource.</p>
|
||||
|
@ -2572,8 +2602,8 @@ Generation
|
|||
<td>
|
||||
<code>verifyImages</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.*./api/kyverno/v1.ImageVerification">
|
||||
[]*./api/kyverno/v1.ImageVerification
|
||||
<a href="#kyverno.io/v1.*github.com/realshuting/kyverno/api/kyverno/v1.ImageVerification">
|
||||
[]*github.com/realshuting/kyverno/api/kyverno/v1.ImageVerification
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
@ -2766,6 +2796,39 @@ If not provided, the system roots are used.</p>
|
|||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1.TargetMutation">TargetMutation
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1.Mutation">Mutation</a>)
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>ResourceSpec</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.ResourceSpec">
|
||||
ResourceSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ResourceSpec specifies the target resource information.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1.UserInfo">UserInfo
|
||||
</h3>
|
||||
<p>
|
||||
|
@ -2858,8 +2921,8 @@ string
|
|||
<td>
|
||||
<code>foreach</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1.*./api/kyverno/v1.ForEachValidation">
|
||||
[]*./api/kyverno/v1.ForEachValidation
|
||||
<a href="#kyverno.io/v1.*github.com/realshuting/kyverno/api/kyverno/v1.ForEachValidation">
|
||||
[]*github.com/realshuting/kyverno/api/kyverno/v1.ForEachValidation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
|
|
436
docs/crd/v1beta1/index.html
Normal file
436
docs/crd/v1beta1/index.html
Normal file
|
@ -0,0 +1,436 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||
<title>Kyverno API</title>
|
||||
<style>
|
||||
.bg-blue {
|
||||
color: #ffffff;
|
||||
background-color: #1589dd;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href="#"><p><b>Packages : </b></p></a>
|
||||
<ul style="list-style:none">
|
||||
<li>
|
||||
<a href="#kyverno.io%2fv1beta1"><b style="color: white">kyverno.io/v1beta1</b></a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<h2 id="kyverno.io/v1beta1">kyverno.io/v1beta1</h2>
|
||||
<p>
|
||||
<p>Package v1beta1 contains API Schema definitions for the policy v1alpha1 API group</p>
|
||||
</p>
|
||||
Resource Types:
|
||||
<ul></ul>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1beta1.AdmissionRequestInfoObject">AdmissionRequestInfoObject
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestSpecContext">UpdateRequestSpecContext</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>AdmissionRequestInfoObject stores the admission request and operation details</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>admissionRequest</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>operation</code></br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#operation-v1-admission">
|
||||
Kubernetes admission/v1.Operation
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1beta1.RequestInfo">RequestInfo
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestSpecContext">UpdateRequestSpecContext</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>RequestInfo contains permission info carried in an admission request.</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>roles</code></br>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Roles is a list of possible role send the request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>clusterRoles</code></br>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ClusterRoles is a list of possible clusterRoles send the request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>userInfo</code></br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#userinfo-v1-authentication">
|
||||
Kubernetes authentication/v1.UserInfo
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>UserInfo is the userInfo carried in the admission request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1beta1.RequestType">RequestType
|
||||
(<code>string</code> alias)</p></h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestSpec">UpdateRequestSpec</a>)
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<h3 id="kyverno.io/v1beta1.UpdateRequest">UpdateRequest
|
||||
</h3>
|
||||
<p>
|
||||
<p>UpdateRequestStatus is a request to process mutate and generate rules in background.</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>metadata</code></br>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#objectmeta-v1-meta">
|
||||
Kubernetes meta/v1.ObjectMeta
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
Refer to the Kubernetes API documentation for the fields of the
|
||||
<code>metadata</code> field.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>spec</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestSpec">
|
||||
UpdateRequestSpec
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Spec is the information to identify the update request.</p>
|
||||
<br/>
|
||||
<br/>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<td>
|
||||
<code>requestType</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.RequestType">
|
||||
RequestType
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Type represents request type for background processing</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>policy</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Specifies the name of the policy.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>resource</code></br>
|
||||
<em>
|
||||
github.com/kyverno/kyverno/api/kyverno/v1.ResourceSpec
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>ResourceSpec is the information to identify the update request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>context</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestSpecContext">
|
||||
UpdateRequestSpecContext
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Context …</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>status</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestStatus">
|
||||
UpdateRequestStatus
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Status contains statistics related to update request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1beta1.UpdateRequestSpec">UpdateRequestSpec
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequest">UpdateRequest</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>UpdateRequestSpec stores the request specification.</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>requestType</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.RequestType">
|
||||
RequestType
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Type represents request type for background processing</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>policy</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Specifies the name of the policy.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>resource</code></br>
|
||||
<em>
|
||||
github.com/kyverno/kyverno/api/kyverno/v1.ResourceSpec
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>ResourceSpec is the information to identify the update request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>context</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestSpecContext">
|
||||
UpdateRequestSpecContext
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Context …</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1beta1.UpdateRequestSpecContext">UpdateRequestSpecContext
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestSpec">UpdateRequestSpec</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>UpdateRequestSpecContext stores the context to be shared.</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>userInfo</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.RequestInfo">
|
||||
RequestInfo
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>admissionRequestInfo</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.AdmissionRequestInfoObject">
|
||||
AdmissionRequestInfoObject
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1beta1.UpdateRequestState">UpdateRequestState
|
||||
(<code>string</code> alias)</p></h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestStatus">UpdateRequestStatus</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>UpdateRequestState defines the state of request.</p>
|
||||
</p>
|
||||
<h3 id="kyverno.io/v1beta1.UpdateRequestStatus">UpdateRequestStatus
|
||||
</h3>
|
||||
<p>
|
||||
(<em>Appears on:</em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequest">UpdateRequest</a>)
|
||||
</p>
|
||||
<p>
|
||||
<p>UpdateRequestStatus defines the observed state of UpdateRequest</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>state</code></br>
|
||||
<em>
|
||||
<a href="#kyverno.io/v1beta1.UpdateRequestState">
|
||||
UpdateRequestState
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>State represents state of the generate request.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>message</code></br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Specifies request status message.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>generatedResources</code></br>
|
||||
<em>
|
||||
[]github.com/kyverno/kyverno/api/kyverno/v1.ResourceSpec
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>This will track the resources that are updated by the generate Policy.
|
||||
Will be used during clean up resources.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
1
go.mod
1
go.mod
|
@ -21,6 +21,7 @@ require (
|
|||
github.com/go-logr/logr v1.2.2
|
||||
github.com/google/go-containerregistry v0.8.1-0.20220209165246-a44adc326839
|
||||
github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220301182634-bfe2ffc6b6bd
|
||||
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible
|
||||
github.com/googleapis/gnostic v0.5.5
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/in-toto/in-toto-golang v0.3.4-0.20211211042327-af1f9fb822bf
|
||||
|
|
118
pkg/background/common/context.go
Normal file
118
pkg/background/common/context.go
Normal file
|
@ -0,0 +1,118 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
utils "github.com/kyverno/kyverno/pkg/utils"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func NewBackgroundContext(dclient *dclient.Client, ur *urkyverno.UpdateRequest,
|
||||
policy kyverno.PolicyInterface, trigger *unstructured.Unstructured,
|
||||
cfg config.Interface, namespaceLabels map[string]string, logger logr.Logger) (*engine.PolicyContext, bool, error) {
|
||||
|
||||
ctx := context.NewContext()
|
||||
requestString := ur.Spec.Context.AdmissionRequestInfo.AdmissionRequest
|
||||
var request admissionv1.AdmissionRequest
|
||||
|
||||
err := json.Unmarshal([]byte(requestString), &request)
|
||||
if err != nil {
|
||||
logger.Error(err, "error parsing the request string")
|
||||
}
|
||||
|
||||
if err := ctx.AddRequest(&request); err != nil {
|
||||
logger.Error(err, "failed to load request in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
new, old, err := utils.ExtractResources(nil, &request)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load request in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(new, unstructured.Unstructured{}) {
|
||||
if !check(&new, trigger) {
|
||||
err := fmt.Errorf("resources don't match")
|
||||
logger.Error(err, "", "resource", ur.Spec.Resource)
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
if trigger == nil {
|
||||
trigger = &old
|
||||
}
|
||||
|
||||
err = ctx.AddResource(trigger.Object)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load resource in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
err = ctx.AddOldResource(old.Object)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load resource in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
err = ctx.AddUserInfo(ur.Spec.Context.UserRequestInfo)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load SA in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
err = ctx.AddServiceAccount(ur.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load UserInfo in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if err := ctx.AddImageInfos(trigger); err != nil {
|
||||
logger.Error(err, "unable to add image info to variables context")
|
||||
}
|
||||
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: *trigger,
|
||||
OldResource: old,
|
||||
Policy: policy,
|
||||
AdmissionInfo: ur.Spec.Context.UserRequestInfo,
|
||||
ExcludeGroupRole: cfg.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: cfg.ToFilter,
|
||||
JSONContext: ctx,
|
||||
NamespaceLabels: namespaceLabels,
|
||||
Client: dclient,
|
||||
AdmissionOperation: false,
|
||||
}
|
||||
|
||||
return policyContext, false, nil
|
||||
}
|
||||
|
||||
func check(admissionRsc, existingRsc *unstructured.Unstructured) bool {
|
||||
if existingRsc == nil {
|
||||
return admissionRsc == nil
|
||||
}
|
||||
|
||||
if admissionRsc.GetName() != existingRsc.GetName() {
|
||||
return false
|
||||
}
|
||||
if admissionRsc.GetNamespace() != existingRsc.GetNamespace() {
|
||||
return false
|
||||
}
|
||||
if admissionRsc.GetKind() != existingRsc.GetKind() {
|
||||
return false
|
||||
}
|
||||
if admissionRsc.GetAPIVersion() != existingRsc.GetAPIVersion() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
34
pkg/background/common/report.go
Normal file
34
pkg/background/common/report.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func FailedEvents(err error, policy, rule string, source event.Source, resource unstructured.Unstructured) []event.Info {
|
||||
re := newEvent(policy, rule, source, resource)
|
||||
|
||||
re.Reason = event.PolicyFailed.String()
|
||||
re.Message = fmt.Sprintf("policy %s/%s failed to apply to %s/%s/%s: %v", policy, rule, resource.GetKind(), resource.GetNamespace(), resource.GetName(), err)
|
||||
|
||||
return []event.Info{re}
|
||||
}
|
||||
|
||||
func SucceedEvents(policy, rule string, source event.Source, resource unstructured.Unstructured) []event.Info {
|
||||
re := newEvent(policy, rule, source, resource)
|
||||
|
||||
re.Reason = event.PolicyApplied.String()
|
||||
re.Message = fmt.Sprintf("policy %s/%s applied to %s/%s/%s successfully", policy, rule, resource.GetKind(), resource.GetNamespace(), resource.GetName())
|
||||
|
||||
return []event.Info{re}
|
||||
}
|
||||
|
||||
func newEvent(policy, rule string, source event.Source, resource unstructured.Unstructured) (re event.Info) {
|
||||
re.Kind = resource.GetKind()
|
||||
re.Namespace = resource.GetNamespace()
|
||||
re.Name = resource.GetName()
|
||||
re.Source = source
|
||||
return
|
||||
}
|
55
pkg/background/common/resource.go
Normal file
55
pkg/background/common/resource.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
logr "github.com/go-logr/logr"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
v1 "k8s.io/api/admission/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func GetResource(client *dclient.Client, urSpec urkyverno.UpdateRequestSpec, log logr.Logger) (*unstructured.Unstructured, error) {
|
||||
resourceSpec := urSpec.Resource
|
||||
|
||||
get := func() (*unstructured.Unstructured, error) {
|
||||
if resourceSpec.Kind == "Namespace" {
|
||||
resourceSpec.Namespace = ""
|
||||
}
|
||||
resource, err := client.GetResource(resourceSpec.APIVersion, resourceSpec.Kind, resourceSpec.Namespace, resourceSpec.Name)
|
||||
if err != nil {
|
||||
if urSpec.Type == urkyverno.Mutate && errors.IsNotFound(err) && urSpec.Context.AdmissionRequestInfo.Operation == v1.Delete {
|
||||
log.V(4).Info("trigger resource does not exist for mutateExisting rule", "operation", urSpec.Context.AdmissionRequestInfo.Operation)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("resource %s/%s/%s/%s: %v", resourceSpec.APIVersion, resourceSpec.Kind, resourceSpec.Namespace, resourceSpec.Name, err)
|
||||
}
|
||||
|
||||
if resource.GetDeletionTimestamp() != nil {
|
||||
log.V(4).Info("trigger resource is in termination", "operation", urSpec.Context.AdmissionRequestInfo.Operation)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
var resource *unstructured.Unstructured
|
||||
var err error
|
||||
retry := func() error {
|
||||
resource, err = get()
|
||||
return err
|
||||
}
|
||||
|
||||
f := common.RetryFunc(time.Second, 5*time.Second, retry, "failed to get resource", log.WithName("getResource"))
|
||||
if err := f(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Info("fetched trigger resource", "resourceSpec", resourceSpec)
|
||||
return resource, err
|
||||
}
|
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
|
@ -10,9 +11,9 @@ import (
|
|||
|
||||
//StatusControlInterface provides interface to update status subresource
|
||||
type StatusControlInterface interface {
|
||||
Failed(gr kyverno.GenerateRequest, message string, genResources []kyverno.ResourceSpec) error
|
||||
Success(gr kyverno.GenerateRequest, genResources []kyverno.ResourceSpec) error
|
||||
Skip(gr kyverno.GenerateRequest, genResources []kyverno.ResourceSpec) error
|
||||
Failed(ur urkyverno.UpdateRequest, message string, genResources []kyverno.ResourceSpec) error
|
||||
Success(ur urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error
|
||||
Skip(gr urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error
|
||||
}
|
||||
|
||||
// StatusControl is default implementaation of GRStatusControlInterface
|
||||
|
@ -21,61 +22,75 @@ type StatusControl struct {
|
|||
}
|
||||
|
||||
//Failed sets gr status.state to failed with message
|
||||
func (sc StatusControl) Failed(gr kyverno.GenerateRequest, message string, genResources []kyverno.ResourceSpec) error {
|
||||
func (sc StatusControl) Failed(gr urkyverno.UpdateRequest, message string, genResources []kyverno.ResourceSpec) error {
|
||||
genR := &urkyverno.UpdateRequestStatus{
|
||||
State: urkyverno.Failed,
|
||||
Message: message,
|
||||
}
|
||||
if genResources != nil {
|
||||
genR.GeneratedResources = genResources
|
||||
}
|
||||
|
||||
patch := jsonutils.NewPatch(
|
||||
"/status",
|
||||
"replace",
|
||||
&kyverno.GenerateRequestStatus{
|
||||
State: kyverno.Failed,
|
||||
Message: message,
|
||||
GeneratedResources: genResources, // Update Generated Resources
|
||||
},
|
||||
genR,
|
||||
)
|
||||
_, err := PatchGenerateRequest(&gr, patch, sc.Client, "status")
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to patch generate request status", "name", gr.Name)
|
||||
log.Log.Error(err, "failed to patch update request status", "name", gr.Name)
|
||||
return err
|
||||
}
|
||||
log.Log.V(3).Info("updated generate request status", "name", gr.Name, "status", string(kyverno.Failed))
|
||||
log.Log.V(3).Info("updated update request status", "name", gr.Name, "status", string(kyverno.Failed))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Success sets the gr status.state to completed and clears message
|
||||
func (sc StatusControl) Success(gr kyverno.GenerateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
func (sc StatusControl) Success(gr urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
genR := &urkyverno.UpdateRequestStatus{
|
||||
State: urkyverno.Completed,
|
||||
Message: "",
|
||||
}
|
||||
|
||||
if genResources != nil {
|
||||
genR.GeneratedResources = genResources
|
||||
}
|
||||
|
||||
patch := jsonutils.NewPatch(
|
||||
"/status",
|
||||
"replace",
|
||||
&kyverno.GenerateRequestStatus{
|
||||
State: kyverno.Completed,
|
||||
Message: "",
|
||||
GeneratedResources: genResources, // Update Generated Resources
|
||||
},
|
||||
genR,
|
||||
)
|
||||
_, err := PatchGenerateRequest(&gr, patch, sc.Client, "status")
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to patch generate request status", "name", gr.Name)
|
||||
log.Log.Error(err, "failed to patch update request status", "name", gr.Name)
|
||||
return err
|
||||
}
|
||||
log.Log.V(3).Info("updated generate request status", "name", gr.Name, "status", string(kyverno.Completed))
|
||||
log.Log.V(3).Info("updated update request status", "name", gr.Name, "status", string(kyverno.Completed))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Success sets the gr status.state to completed and clears message
|
||||
func (sc StatusControl) Skip(gr kyverno.GenerateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
func (sc StatusControl) Skip(gr urkyverno.UpdateRequest, genResources []kyverno.ResourceSpec) error {
|
||||
genR := &urkyverno.UpdateRequestStatus{
|
||||
State: urkyverno.Skip,
|
||||
Message: "",
|
||||
}
|
||||
|
||||
if genResources != nil {
|
||||
genR.GeneratedResources = genResources
|
||||
}
|
||||
|
||||
patch := jsonutils.NewPatch(
|
||||
"/status",
|
||||
"replace",
|
||||
&kyverno.GenerateRequestStatus{
|
||||
State: kyverno.Skip,
|
||||
Message: "",
|
||||
GeneratedResources: genResources, // Update Generated Resources
|
||||
},
|
||||
genR,
|
||||
)
|
||||
_, err := PatchGenerateRequest(&gr, patch, sc.Client, "status")
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
log.Log.Error(err, "failed to patch generate request status", "name", gr.Name)
|
||||
log.Log.Error(err, "failed to update generate request status", "name", gr.Name)
|
||||
return err
|
||||
}
|
||||
log.Log.V(3).Info("updated generate request status", "name", gr.Name, "status", string(kyverno.Skip))
|
||||
log.Log.V(3).Info("updated update request status", "name", gr.Name, "status", string(kyverno.Skip))
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package common
|
|||
import (
|
||||
"context"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
|
@ -12,12 +12,12 @@ import (
|
|||
)
|
||||
|
||||
// PatchGenerateRequest patches a generate request object
|
||||
func PatchGenerateRequest(gr *kyverno.GenerateRequest, patch jsonutils.Patch, client kyvernoclient.Interface, subresources ...string) (*kyverno.GenerateRequest, error) {
|
||||
func PatchGenerateRequest(gr *urkyverno.UpdateRequest, patch jsonutils.Patch, client kyvernoclient.Interface, subresources ...string) (*urkyverno.UpdateRequest, error) {
|
||||
data, err := patch.ToPatchBytes()
|
||||
if nil != err {
|
||||
return gr, err
|
||||
}
|
||||
newGR, err := client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Patch(context.TODO(), gr.Name, types.JSONPatchType, data, metav1.PatchOptions{}, subresources...)
|
||||
newGR, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Patch(context.TODO(), gr.Name, types.JSONPatchType, data, metav1.PatchOptions{}, subresources...)
|
||||
if err != nil {
|
||||
return gr, err
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
||||
func (c *Controller) processGR(gr kyverno.GenerateRequest) error {
|
||||
func (c *Controller) processGR(gr urkyverno.UpdateRequest) error {
|
||||
logger := c.log.WithValues("kind", gr.Kind, "namespace", gr.Namespace, "name", gr.Name)
|
||||
// 1- Corresponding policy has been deleted
|
||||
// then we don't delete the generated resources
|
||||
|
@ -44,7 +44,7 @@ func (c *Controller) processGR(gr kyverno.GenerateRequest) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ownerResourceExists(log logr.Logger, client *dclient.Client, gr kyverno.GenerateRequest) bool {
|
||||
func ownerResourceExists(log logr.Logger, client *dclient.Client, gr urkyverno.UpdateRequest) bool {
|
||||
_, err := client.GetResource("", gr.Spec.Resource.Kind, gr.Spec.Resource.Namespace, gr.Spec.Resource.Name)
|
||||
// trigger resources has been deleted
|
||||
if apierrors.IsNotFound(err) {
|
||||
|
@ -58,7 +58,7 @@ func ownerResourceExists(log logr.Logger, client *dclient.Client, gr kyverno.Gen
|
|||
return true
|
||||
}
|
||||
|
||||
func deleteGeneratedResources(log logr.Logger, client *dclient.Client, gr kyverno.GenerateRequest) error {
|
||||
func deleteGeneratedResources(log logr.Logger, client *dclient.Client, gr urkyverno.UpdateRequest) error {
|
||||
for _, genResource := range gr.Status.GeneratedResources {
|
||||
err := client.DeleteResource("", genResource.Kind, genResource.Namespace, genResource.Name, false)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
|
|
|
@ -3,14 +3,15 @@ package cleanup
|
|||
import (
|
||||
"time"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
pkgCommon "github.com/kyverno/kyverno/pkg/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
|
@ -19,6 +20,7 @@ import (
|
|||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corelister "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
|
@ -55,6 +57,9 @@ type Controller struct {
|
|||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urkyvernolister.UpdateRequestNamespaceLister
|
||||
|
||||
// nsLister can list/get namespaces from the shared informer's store
|
||||
nsLister corelister.NamespaceLister
|
||||
|
||||
|
@ -67,12 +72,12 @@ type Controller struct {
|
|||
// grSynced returns true if the generate request store has been synced at least once
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
// urSynced returns true if the update request store has been synced at least once
|
||||
urSynced cache.InformerSynced
|
||||
|
||||
// nsListerSynced returns true if the namespace store has been synced at least once
|
||||
nsListerSynced cache.InformerSynced
|
||||
|
||||
// namespaceInformer for re-evaluation on namespace updates
|
||||
namespaceInformer coreinformers.NamespaceInformer
|
||||
|
||||
// logger
|
||||
log logr.Logger
|
||||
}
|
||||
|
@ -85,17 +90,17 @@ func NewController(
|
|||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
npInformer kyvernoinformer.PolicyInformer,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urkyvernoinformer.UpdateRequestInformer,
|
||||
namespaceInformer coreinformers.NamespaceInformer,
|
||||
log logr.Logger,
|
||||
) (*Controller, error) {
|
||||
c := Controller{
|
||||
kyvernoClient: kyvernoclient,
|
||||
client: client,
|
||||
pInformer: pInformer,
|
||||
grInformer: grInformer,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "generate-request-cleanup"),
|
||||
namespaceInformer: namespaceInformer,
|
||||
log: log,
|
||||
kyvernoClient: kyvernoclient,
|
||||
client: client,
|
||||
pInformer: pInformer,
|
||||
grInformer: grInformer,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "generate-request-cleanup"),
|
||||
log: log,
|
||||
}
|
||||
|
||||
c.control = Control{client: kyvernoclient}
|
||||
|
@ -108,6 +113,7 @@ func NewController(
|
|||
c.pSynced = pInformer.Informer().HasSynced
|
||||
c.npSynced = npInformer.Informer().HasSynced
|
||||
c.grSynced = grInformer.Informer().HasSynced
|
||||
c.urSynced = urInformer.Informer().HasSynced
|
||||
c.nsListerSynced = namespaceInformer.Informer().HasSynced
|
||||
|
||||
return &c, nil
|
||||
|
@ -163,24 +169,24 @@ func (c *Controller) deletePolicy(obj interface{}) {
|
|||
|
||||
for _, gr := range grs {
|
||||
logger.V(4).Info("enqueue the gr for cleanup", "gr name", gr.Name)
|
||||
c.addGR(gr)
|
||||
c.addUR(gr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) addGR(obj interface{}) {
|
||||
gr := obj.(*kyverno.GenerateRequest)
|
||||
func (c *Controller) addUR(obj interface{}) {
|
||||
gr := obj.(*urkyverno.UpdateRequest)
|
||||
c.enqueue(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) updateGR(old, cur interface{}) {
|
||||
gr := cur.(*kyverno.GenerateRequest)
|
||||
func (c *Controller) updateUR(old, cur interface{}) {
|
||||
gr := cur.(*urkyverno.UpdateRequest)
|
||||
c.enqueue(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) deleteGR(obj interface{}) {
|
||||
func (c *Controller) deleteUR(obj interface{}) {
|
||||
logger := c.log
|
||||
gr, ok := obj.(*kyverno.GenerateRequest)
|
||||
gr, ok := obj.(*urkyverno.UpdateRequest)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
|
@ -188,7 +194,7 @@ func (c *Controller) deleteGR(obj interface{}) {
|
|||
return
|
||||
}
|
||||
|
||||
_, ok = tombstone.Obj.(*kyverno.GenerateRequest)
|
||||
_, ok = tombstone.Obj.(*urkyverno.UpdateRequest)
|
||||
if !ok {
|
||||
logger.Info("ombstone contained object that is not a Generate Request", "obj", obj)
|
||||
return
|
||||
|
@ -215,9 +221,9 @@ func (c *Controller) deleteGR(obj interface{}) {
|
|||
c.enqueue(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) enqueue(gr *kyverno.GenerateRequest) {
|
||||
func (c *Controller) enqueue(gr *urkyverno.UpdateRequest) {
|
||||
// skip enqueueing Pending requests
|
||||
if gr.Status.State == kyverno.Pending {
|
||||
if gr.Status.State == urkyverno.Pending {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -240,7 +246,7 @@ func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
|||
logger.Info("starting")
|
||||
defer logger.Info("shutting down")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, c.pSynced, c.grSynced, c.npSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, c.pSynced, c.grSynced, c.urSynced, c.npSynced, c.nsListerSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
@ -250,9 +256,9 @@ func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
|||
})
|
||||
|
||||
c.grInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addGR,
|
||||
UpdateFunc: c.updateGR,
|
||||
DeleteFunc: c.deleteGR,
|
||||
AddFunc: c.addUR,
|
||||
UpdateFunc: c.updateUR,
|
||||
DeleteFunc: c.deleteUR,
|
||||
})
|
||||
|
||||
for i := 0; i < workers; i++ {
|
||||
|
@ -320,7 +326,7 @@ func (c *Controller) syncGenerateRequest(key string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gr, err := c.grLister.Get(grName)
|
||||
gr, err := c.urLister.Get(grName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -20,5 +20,5 @@ type Control struct {
|
|||
|
||||
//Delete deletes the specified resource
|
||||
func (c Control) Delete(gr string) error {
|
||||
return c.client.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Delete(context.TODO(), gr, metav1.DeleteOptions{})
|
||||
return c.client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Delete(context.TODO(), gr, metav1.DeleteOptions{})
|
||||
}
|
||||
|
|
|
@ -10,29 +10,27 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/background/common"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
pkgcommon "github.com/kyverno/kyverno/pkg/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
corelister "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
@ -75,7 +73,7 @@ func NewGenerateController(
|
|||
npolicyLister kyvernolister.PolicyLister,
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister,
|
||||
eventGen event.Interface,
|
||||
namespaceInformer coreinformers.NamespaceInformer,
|
||||
nsLister corelister.NamespaceLister,
|
||||
log logr.Logger,
|
||||
dynamicConfig config.Interface,
|
||||
) (*GenerateController, error) {
|
||||
|
@ -92,12 +90,12 @@ func NewGenerateController(
|
|||
}
|
||||
|
||||
c.statusControl = common.StatusControl{Client: kyvernoClient}
|
||||
c.nsLister = namespaceInformer.Lister()
|
||||
c.nsLister = nsLister
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
func (c *GenerateController) ProcessGR(gr *kyverno.GenerateRequest) error {
|
||||
func (c *GenerateController) ProcessGR(gr *urkyverno.UpdateRequest) error {
|
||||
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "apiVersion", gr.Spec.Resource.APIVersion, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
|
||||
var err error
|
||||
var resource *unstructured.Unstructured
|
||||
|
@ -105,7 +103,7 @@ func (c *GenerateController) ProcessGR(gr *kyverno.GenerateRequest) error {
|
|||
var precreatedResource bool
|
||||
|
||||
// 1 - Check if the resource exists
|
||||
resource, err = getResource(c.client, gr.Spec.Resource, c.log)
|
||||
resource, err = common.GetResource(c.client, gr.Spec, c.log)
|
||||
if err != nil {
|
||||
// Don't update status
|
||||
// re-queueing the GR by updating the annotation
|
||||
|
@ -142,7 +140,7 @@ func (c *GenerateController) ProcessGR(gr *kyverno.GenerateRequest) error {
|
|||
|
||||
if updateAnnotation {
|
||||
gr.SetAnnotations(grAnnotations)
|
||||
_, err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Update(contextdefault.TODO(), gr, metav1.UpdateOptions{})
|
||||
_, err := c.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(contextdefault.TODO(), gr, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update annotation in generate request for the resource", "generate request", gr.Name)
|
||||
return err
|
||||
|
@ -169,7 +167,7 @@ func (c *GenerateController) ProcessGR(gr *kyverno.GenerateRequest) error {
|
|||
}
|
||||
|
||||
// 3 - Report failure Events
|
||||
events := failedEvents(err, *gr, *resource)
|
||||
events := common.FailedEvents(err, gr.Spec.Policy, "", event.GeneratePolicyController, *resource)
|
||||
c.eventGen.Add(events...)
|
||||
}
|
||||
|
||||
|
@ -179,12 +177,11 @@ func (c *GenerateController) ProcessGR(gr *kyverno.GenerateRequest) error {
|
|||
|
||||
const doesNotApply = "policy does not apply to resource"
|
||||
|
||||
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, gr kyverno.GenerateRequest, namespaceLabels map[string]string) ([]kyverno.ResourceSpec, bool, error) {
|
||||
func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, gr urkyverno.UpdateRequest, namespaceLabels map[string]string) ([]kyverno.ResourceSpec, bool, error) {
|
||||
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "apiVersion", gr.Spec.Resource.APIVersion, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
|
||||
// Get the list of rules to be applied
|
||||
// get policy
|
||||
// build context
|
||||
ctx := context.NewContext()
|
||||
|
||||
logger.V(3).Info("applying generate policy rule")
|
||||
|
||||
|
@ -211,53 +208,9 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, g
|
|||
return nil, false, err
|
||||
}
|
||||
|
||||
requestString := gr.Spec.Context.AdmissionRequestInfo.AdmissionRequest
|
||||
var request admissionv1.AdmissionRequest
|
||||
err = json.Unmarshal([]byte(requestString), &request)
|
||||
policyContext, precreatedResource, err := common.NewBackgroundContext(c.client, &gr, &policy, &resource, c.Config, namespaceLabels, logger)
|
||||
if err != nil {
|
||||
logger.Error(err, "error parsing the request string")
|
||||
}
|
||||
|
||||
if gr.Spec.Context.AdmissionRequestInfo.Operation == admissionv1.Update {
|
||||
request.Operation = gr.Spec.Context.AdmissionRequestInfo.Operation
|
||||
}
|
||||
|
||||
if err := ctx.AddRequest(&request); err != nil {
|
||||
logger.Error(err, "failed to load request in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
err = ctx.AddResource(resource.Object)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load resource in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
err = ctx.AddUserInfo(gr.Spec.Context.UserRequestInfo)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load SA in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
err = ctx.AddServiceAccount(gr.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load UserInfo in context")
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if err := ctx.AddImageInfos(&resource); err != nil {
|
||||
logger.Error(err, "unable to add image info to variables context")
|
||||
}
|
||||
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: resource,
|
||||
Policy: &policy,
|
||||
AdmissionInfo: gr.Spec.Context.UserRequestInfo,
|
||||
ExcludeGroupRole: c.Config.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: c.Config.ToFilter,
|
||||
JSONContext: ctx,
|
||||
NamespaceLabels: namespaceLabels,
|
||||
Client: c.client,
|
||||
return nil, precreatedResource, err
|
||||
}
|
||||
|
||||
// check if the policy still applies to the resource
|
||||
|
@ -300,7 +253,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, g
|
|||
}
|
||||
|
||||
// getPolicySpec gets the policy spec from the ClusterPolicy/Policy
|
||||
func (c *GenerateController) getPolicySpec(gr kyverno.GenerateRequest) (kyverno.ClusterPolicy, error) {
|
||||
func (c *GenerateController) getPolicySpec(gr urkyverno.UpdateRequest) (kyverno.ClusterPolicy, error) {
|
||||
var policy kyverno.ClusterPolicy
|
||||
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(gr.Spec.Policy)
|
||||
|
@ -328,7 +281,7 @@ func (c *GenerateController) getPolicySpec(gr kyverno.GenerateRequest) (kyverno.
|
|||
}
|
||||
}
|
||||
|
||||
func updateStatus(statusControl common.StatusControlInterface, gr kyverno.GenerateRequest, err error, genResources []kyverno.ResourceSpec, precreatedResource bool) error {
|
||||
func updateStatus(statusControl common.StatusControlInterface, gr urkyverno.UpdateRequest, err error, genResources []kyverno.ResourceSpec, precreatedResource bool) error {
|
||||
if err != nil {
|
||||
return statusControl.Failed(gr, err.Error(), genResources)
|
||||
} else if precreatedResource {
|
||||
|
@ -339,7 +292,7 @@ func updateStatus(statusControl common.StatusControlInterface, gr kyverno.Genera
|
|||
return statusControl.Success(gr, genResources)
|
||||
}
|
||||
|
||||
func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, gr kyverno.GenerateRequest, applicableRules []string) (genResources []kyverno.ResourceSpec, processExisting bool, err error) {
|
||||
func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext *engine.PolicyContext, gr urkyverno.UpdateRequest, applicableRules []string) (genResources []kyverno.ResourceSpec, processExisting bool, err error) {
|
||||
// Get the response as the actions to be performed on the resource
|
||||
// - - substitute values
|
||||
policy := policyContext.Policy
|
||||
|
@ -417,7 +370,7 @@ func getResourceInfo(object map[string]interface{}) (kind, name, namespace, apiv
|
|||
return
|
||||
}
|
||||
|
||||
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest) (kyverno.ResourceSpec, error) {
|
||||
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr urkyverno.UpdateRequest) (kyverno.ResourceSpec, error) {
|
||||
var rdata map[string]interface{}
|
||||
var err error
|
||||
var mode ResourceMode
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func failedEvents(err error, gr kyverno.GenerateRequest, resource unstructured.Unstructured) []event.Info {
|
||||
re := event.Info{}
|
||||
re.Kind = resource.GetKind()
|
||||
re.Namespace = resource.GetNamespace()
|
||||
re.Name = resource.GetName()
|
||||
re.Reason = event.PolicyFailed.String()
|
||||
re.Source = event.GeneratePolicyController
|
||||
re.Message = fmt.Sprintf("policy %s failed to apply: %v", gr.Spec.Policy, err)
|
||||
|
||||
return []event.Info{re}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
logr "github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func getResource(client *dclient.Client, resourceSpec kyverno.ResourceSpec, log logr.Logger) (*unstructured.Unstructured, error) {
|
||||
|
||||
get := func() (*unstructured.Unstructured, error) {
|
||||
if resourceSpec.Kind == "Namespace" {
|
||||
resourceSpec.Namespace = ""
|
||||
}
|
||||
resource, err := client.GetResource(resourceSpec.APIVersion, resourceSpec.Kind, resourceSpec.Namespace, resourceSpec.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resource.GetDeletionTimestamp() != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
retry := func() error {
|
||||
_, err := get()
|
||||
return err
|
||||
}
|
||||
|
||||
f := common.RetryFunc(time.Second, 30*time.Second, retry, log.WithName("getResource"))
|
||||
if err := f(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return get()
|
||||
}
|
243
pkg/background/mutate/mutate.go
Normal file
243
pkg/background/mutate/mutate.go
Normal file
|
@ -0,0 +1,243 @@
|
|||
package mutate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/background/common"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urlister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
engineUtils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
yamlv2 "gopkg.in/yaml.v2"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type MutateExistingController struct {
|
||||
client *dclient.Client
|
||||
|
||||
// typed client for Kyverno CRDs
|
||||
kyvernoClient *kyvernoclient.Clientset
|
||||
|
||||
// urStatusControl is used to update UR status
|
||||
statusControl common.StatusControlInterface
|
||||
|
||||
// event generator interface
|
||||
eventGen event.Interface
|
||||
|
||||
log logr.Logger
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urlister.UpdateRequestNamespaceLister
|
||||
|
||||
// policyLister can list/get cluster policy from the shared informer's store
|
||||
policyLister kyvernolister.ClusterPolicyLister
|
||||
|
||||
// policyLister can list/get Namespace policy from the shared informer's store
|
||||
npolicyLister kyvernolister.PolicyLister
|
||||
|
||||
Config config.Interface
|
||||
}
|
||||
|
||||
// NewMutateExistingController returns an instance of the MutateExistingController
|
||||
func NewMutateExistingController(
|
||||
kyvernoClient *kyvernoclient.Clientset,
|
||||
client *dclient.Client,
|
||||
policyLister kyvernolister.ClusterPolicyLister,
|
||||
npolicyLister kyvernolister.PolicyLister,
|
||||
urLister urlister.UpdateRequestNamespaceLister,
|
||||
eventGen event.Interface,
|
||||
log logr.Logger,
|
||||
dynamicConfig config.Interface,
|
||||
) (*MutateExistingController, error) {
|
||||
|
||||
c := MutateExistingController{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
eventGen: eventGen,
|
||||
log: log,
|
||||
policyLister: policyLister,
|
||||
npolicyLister: npolicyLister,
|
||||
urLister: urLister,
|
||||
Config: dynamicConfig,
|
||||
}
|
||||
|
||||
c.statusControl = common.StatusControl{Client: kyvernoClient}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
func (c *MutateExistingController) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
||||
logger := c.log.WithValues("name", ur.Name, "policy", ur.Spec.Policy, "kind", ur.Spec.Resource.Kind, "apiVersion", ur.Spec.Resource.APIVersion, "namespace", ur.Spec.Resource.Namespace, "name", ur.Spec.Resource.Name)
|
||||
var errs []error
|
||||
|
||||
policy, err := c.getPolicy(ur.Spec.Policy)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get policy")
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rule := range policy.GetSpec().Rules {
|
||||
if !rule.IsMutateExisting() {
|
||||
continue
|
||||
}
|
||||
|
||||
trigger, err := common.GetResource(c.client, ur.Spec, c.log)
|
||||
if err != nil {
|
||||
logger.WithName(rule.Name).Error(err, "failed to get trigger resource")
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
policyContext, _, err := common.NewBackgroundContext(c.client, ur, policy, trigger, c.Config, nil, logger)
|
||||
if err != nil {
|
||||
logger.WithName(rule.Name).Error(err, "failed to build policy context")
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
er := engine.Mutate(policyContext)
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
patched := r.PatchedTarget
|
||||
switch r.Status {
|
||||
case response.RuleStatusFail, response.RuleStatusError, response.RuleStatusWarn:
|
||||
err := fmt.Errorf("failed to mutate existing resource, rule response%v: %s", r.Status, r.Message)
|
||||
logger.Error(err, "")
|
||||
errs = append(errs, err)
|
||||
c.report(err, ur.Spec.Policy, rule.Name, patched)
|
||||
|
||||
case response.RuleStatusSkip:
|
||||
logger.Info("mutate existing rule skipped", "rule", r.Name, "message", r.Message)
|
||||
c.report(err, ur.Spec.Policy, rule.Name, patched)
|
||||
|
||||
case response.RuleStatusPass:
|
||||
|
||||
patchedNew, err := addAnnotation(policy, patched, r)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to apply patches")
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
if patchedNew == nil {
|
||||
err := fmt.Errorf("empty resource to patch")
|
||||
logger.Error(err, "", "rule", r.Name, "message", r.Message)
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if r.Status == response.RuleStatusPass {
|
||||
_, updateErr := c.client.UpdateResource(patchedNew.GetAPIVersion(), patchedNew.GetKind(), patchedNew.GetNamespace(), patchedNew.Object, false)
|
||||
if updateErr != nil {
|
||||
errs = append(errs, updateErr)
|
||||
logger.WithName(rule.Name).Error(updateErr, "failed to update target resource", "namespace", patchedNew.GetNamespace(), "name", patchedNew.GetName())
|
||||
} else {
|
||||
logger.WithName(rule.Name).V(4).Info("successfully mutated existing resource", "namespace", patchedNew.GetNamespace(), "name", patchedNew.GetName())
|
||||
}
|
||||
|
||||
c.report(updateErr, ur.Spec.Policy, rule.Name, patched)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updateURStatus(c.statusControl, *ur, engineUtils.CombineErrors(errs))
|
||||
}
|
||||
|
||||
func (c *MutateExistingController) getPolicy(key string) (kyvernov1.PolicyInterface, error) {
|
||||
pNamespace, pName, err := cache.SplitMetaNamespaceKey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pNamespace != "" {
|
||||
return c.npolicyLister.Policies(pNamespace).Get(pName)
|
||||
}
|
||||
|
||||
return c.policyLister.Get(pName)
|
||||
}
|
||||
|
||||
func (c *MutateExistingController) report(err error, policy, rule string, target *unstructured.Unstructured) {
|
||||
var events []event.Info
|
||||
|
||||
if target == nil {
|
||||
c.log.WithName("mutateExisting").Info("cannot generate events for empty target resource", "policy", policy, "rule", rule, "err", err.Error())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
events = common.FailedEvents(err, policy, rule, event.MutateExistingController, *target)
|
||||
} else {
|
||||
events = common.SucceedEvents(policy, rule, event.MutateExistingController, *target)
|
||||
}
|
||||
|
||||
c.eventGen.Add(events...)
|
||||
}
|
||||
|
||||
func updateURStatus(statusControl common.StatusControlInterface, ur urkyverno.UpdateRequest, err error) error {
|
||||
if err != nil {
|
||||
return statusControl.Failed(ur, err.Error(), nil)
|
||||
}
|
||||
|
||||
return statusControl.Success(ur, nil)
|
||||
}
|
||||
|
||||
func addAnnotation(policy kyvernov1.PolicyInterface, patched *unstructured.Unstructured, r response.RuleResponse) (patchedNew *unstructured.Unstructured, err error) {
|
||||
if patched == nil {
|
||||
return
|
||||
}
|
||||
|
||||
patchedNew = patched
|
||||
var rulePatches []utils.RulePatch
|
||||
|
||||
for _, patch := range r.Patches {
|
||||
var patchmap map[string]interface{}
|
||||
if err := json.Unmarshal(patch, &patchmap); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse JSON patch bytes: %v", err)
|
||||
}
|
||||
|
||||
rp := struct {
|
||||
RuleName string `json:"rulename"`
|
||||
Op string `json:"op"`
|
||||
Path string `json:"path"`
|
||||
}{
|
||||
RuleName: r.Name,
|
||||
Op: patchmap["op"].(string),
|
||||
Path: patchmap["path"].(string),
|
||||
}
|
||||
|
||||
rulePatches = append(rulePatches, rp)
|
||||
}
|
||||
|
||||
var annotationContent = make(map[string]string)
|
||||
policyName := policy.GetName()
|
||||
if policy.GetNamespace() != "" {
|
||||
policyName = policy.GetNamespace() + "/" + policy.GetName()
|
||||
}
|
||||
|
||||
for _, rulePatch := range rulePatches {
|
||||
annotationContent[rulePatch.RuleName+"."+policyName+".kyverno.io"] = utils.OperationToPastTense[rulePatch.Op] + " " + rulePatch.Path
|
||||
}
|
||||
|
||||
if len(annotationContent) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
result, _ := yamlv2.Marshal(annotationContent)
|
||||
|
||||
ann := patchedNew.GetAnnotations()
|
||||
if ann == nil {
|
||||
ann = make(map[string]string)
|
||||
}
|
||||
ann[utils.PolicyAnnotation] = string(result)
|
||||
patchedNew.SetAnnotations(ann)
|
||||
|
||||
return
|
||||
}
|
|
@ -1,13 +1,23 @@
|
|||
package background
|
||||
|
||||
import (
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/background/generate"
|
||||
"github.com/kyverno/kyverno/pkg/background/mutate"
|
||||
)
|
||||
|
||||
func (c *Controller) ProcessGR(gr *kyverno.GenerateRequest) error {
|
||||
ctrl, _ := generate.NewGenerateController(c.kyvernoClient, c.client,
|
||||
c.policyLister, c.npolicyLister, c.grLister, c.eventGen, c.namespaceInformer, c.log, c.Config,
|
||||
)
|
||||
return ctrl.ProcessGR(gr)
|
||||
func (c *Controller) ProcessUR(ur *urkyverno.UpdateRequest) error {
|
||||
switch ur.Spec.Type {
|
||||
case urkyverno.Mutate:
|
||||
ctrl, _ := mutate.NewMutateExistingController(c.kyvernoClient, c.client,
|
||||
c.policyLister, c.npolicyLister, c.urLister, c.eventGen, c.log, c.Config)
|
||||
return ctrl.ProcessUR(ur)
|
||||
|
||||
case urkyverno.Generate:
|
||||
ctrl, _ := generate.NewGenerateController(c.kyvernoClient, c.client,
|
||||
c.policyLister, c.npolicyLister, c.grLister, c.eventGen, c.nsLister, c.log, c.Config,
|
||||
)
|
||||
return ctrl.ProcessGR(ur)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,11 +6,14 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
common "github.com/kyverno/kyverno/pkg/background/common"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urlister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
|
@ -57,6 +60,9 @@ type Controller struct {
|
|||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urlister.UpdateRequestNamespaceLister
|
||||
|
||||
// nsLister can list/get namespaces from the shared informer's store
|
||||
nsLister corelister.NamespaceLister
|
||||
|
||||
|
@ -69,8 +75,10 @@ type Controller struct {
|
|||
// grSynced returns true if the Generate Request store has been synced at least once
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
// namespaceInformer for re-evaluation on namespace updates
|
||||
namespaceInformer coreinformers.NamespaceInformer
|
||||
// urSynced returns true if the Update Request store has been synced at least once
|
||||
urSynced cache.InformerSynced
|
||||
|
||||
nsSynced cache.InformerSynced
|
||||
|
||||
log logr.Logger
|
||||
|
||||
|
@ -85,6 +93,7 @@ func NewController(
|
|||
policyInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
npolicyInformer kyvernoinformer.PolicyInformer,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urkyvernoinformer.UpdateRequestInformer,
|
||||
eventGen event.Interface,
|
||||
namespaceInformer coreinformers.NamespaceInformer,
|
||||
log logr.Logger,
|
||||
|
@ -92,14 +101,13 @@ func NewController(
|
|||
) (*Controller, error) {
|
||||
|
||||
c := Controller{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
policyInformer: policyInformer,
|
||||
eventGen: eventGen,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "generate-request"),
|
||||
namespaceInformer: namespaceInformer,
|
||||
log: log,
|
||||
Config: dynamicConfig,
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
policyInformer: policyInformer,
|
||||
eventGen: eventGen,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "generate-request"),
|
||||
log: log,
|
||||
Config: dynamicConfig,
|
||||
}
|
||||
|
||||
c.statusControl = common.StatusControl{Client: kyvernoClient}
|
||||
|
@ -116,10 +124,20 @@ func NewController(
|
|||
DeleteFunc: c.deleteGR,
|
||||
})
|
||||
|
||||
c.urSynced = urInformer.Informer().HasSynced
|
||||
urInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addUR,
|
||||
UpdateFunc: c.updateUR,
|
||||
DeleteFunc: c.deleteUR,
|
||||
})
|
||||
|
||||
c.policyLister = policyInformer.Lister()
|
||||
c.npolicyLister = npolicyInformer.Lister()
|
||||
c.grLister = grInformer.Lister().GenerateRequests(config.KyvernoNamespace)
|
||||
c.urLister = urInformer.Lister().UpdateRequests(config.KyvernoNamespace)
|
||||
|
||||
c.nsLister = namespaceInformer.Lister()
|
||||
c.nsSynced = namespaceInformer.Informer().HasSynced
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
@ -130,7 +148,7 @@ func (c *Controller) Run(workers int, stopCh <-chan struct{}) {
|
|||
defer c.queue.ShutDown()
|
||||
defer c.log.Info("shutting down")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, c.policySynced, c.grSynced, c.npolicySynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, c.policySynced, c.grSynced, c.urSynced, c.npolicySynced, c.nsSynced) {
|
||||
c.log.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
@ -203,7 +221,7 @@ func (c *Controller) syncGenerateRequest(key string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
gr, err := c.grLister.Get(grName)
|
||||
gr, err := c.urLister.Get(grName)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil
|
||||
|
@ -213,7 +231,7 @@ func (c *Controller) syncGenerateRequest(key string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return c.ProcessGR(gr)
|
||||
return c.ProcessUR(gr)
|
||||
}
|
||||
|
||||
// EnqueueGenerateRequestFromWebhook - enqueueing generate requests from webhook
|
||||
|
@ -221,14 +239,14 @@ func (c *Controller) EnqueueGenerateRequestFromWebhook(gr *kyverno.GenerateReque
|
|||
c.enqueueGenerateRequest(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) enqueueGenerateRequest(gr *kyverno.GenerateRequest) {
|
||||
c.log.V(5).Info("enqueuing generate request", "gr", gr.Name)
|
||||
key, err := cache.MetaNamespaceKeyFunc(gr)
|
||||
func (c *Controller) enqueueGenerateRequest(obj interface{}) {
|
||||
key, err := cache.MetaNamespaceKeyFunc(obj)
|
||||
if err != nil {
|
||||
c.log.Error(err, "failed to extract name")
|
||||
return
|
||||
}
|
||||
|
||||
c.log.V(5).Info("enqueued update request", "ur", key)
|
||||
c.queue.Add(key)
|
||||
}
|
||||
|
||||
|
@ -324,7 +342,66 @@ func (c *Controller) deleteGR(obj interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
logger.V(3).Info("deleting generate request", "name", gr.Name)
|
||||
logger.V(3).Info("deleting update request", "name", gr.Name)
|
||||
|
||||
// sync Handler will remove it from the queue
|
||||
c.enqueueGenerateRequest(gr)
|
||||
}
|
||||
|
||||
func (c *Controller) addUR(obj interface{}) {
|
||||
ur := obj.(*urkyverno.UpdateRequest)
|
||||
c.enqueueGenerateRequest(ur)
|
||||
}
|
||||
|
||||
func (c *Controller) updateUR(old, cur interface{}) {
|
||||
oldUr := old.(*urkyverno.UpdateRequest)
|
||||
curUr := cur.(*urkyverno.UpdateRequest)
|
||||
if oldUr.ResourceVersion == curUr.ResourceVersion {
|
||||
// Periodic resync will send update events for all known Namespace.
|
||||
// Two different versions of the same replica set will always have different RVs.
|
||||
return
|
||||
}
|
||||
// only process the ones that are in "Pending"/"Completed" state
|
||||
// if the Generate Request fails due to incorrect policy, it will be requeued during policy update
|
||||
if curUr.Status.State == urkyverno.Failed {
|
||||
return
|
||||
}
|
||||
c.enqueueGenerateRequest(curUr)
|
||||
}
|
||||
|
||||
func (c *Controller) deleteUR(obj interface{}) {
|
||||
logger := c.log
|
||||
gr, ok := obj.(*urkyverno.UpdateRequest)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
logger.Info("Couldn't get object from tombstone", "obj", obj)
|
||||
return
|
||||
}
|
||||
_, ok = tombstone.Obj.(*kyverno.GenerateRequest)
|
||||
if !ok {
|
||||
logger.Info("tombstone contained object that is not a Generate Request CR", "obj", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if gr.Spec.GetRequestType() == urkyverno.Generate {
|
||||
for _, resource := range gr.Status.GeneratedResources {
|
||||
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
if r != nil && r.GetLabels()["policy.kyverno.io/synchronize"] == "enable" {
|
||||
if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil && !apierrors.IsNotFound(err) {
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.V(3).Info("deleting update request", "name", gr.Name)
|
||||
}
|
||||
|
||||
// sync Handler will remove it from the queue
|
||||
c.enqueueGenerateRequest(gr)
|
||||
|
|
|
@ -53,9 +53,9 @@ func (c *Clientset) KyvernoV1() kyvernov1.KyvernoV1Interface {
|
|||
return c.kyvernoV1
|
||||
}
|
||||
|
||||
// KyvernoV1 retrieves the KyvernoV1Client
|
||||
// KyvernoV1beta1 retrieves the KyvernoV1beta1Client
|
||||
func (c *Clientset) KyvernoV1beta1() kyvernov1beta1.KyvernoV1beta1Interface {
|
||||
return c.KyvernoV1beta1()
|
||||
return c.kyvernoV1beta1
|
||||
}
|
||||
|
||||
// KyvernoV1alpha2 retrieves the KyvernoV1alpha2Client
|
||||
|
|
|
@ -87,7 +87,7 @@ func (c *Clientset) KyvernoV1() kyvernov1.KyvernoV1Interface {
|
|||
return &fakekyvernov1.FakeKyvernoV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// KyvernoV1alpha2 retrieves the KyvernoV1alpha2Client
|
||||
// KyvernoV1beta1 retrieves the KyvernoV1beta1Client
|
||||
func (c *Clientset) KyvernoV1beta1() kyvernov1beta1.KyvernoV1beta1Interface {
|
||||
return &fakekyvernov1beta1.FakeKyvernoV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package fake
|
|||
import (
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernov1alpha2 "github.com/kyverno/kyverno/api/kyverno/v1alpha2"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
wgpolicyk8sv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -34,6 +35,7 @@ var codecs = serializer.NewCodecFactory(scheme)
|
|||
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
kyvernov1.AddToScheme,
|
||||
kyvernov1beta1.AddToScheme,
|
||||
kyvernov1alpha2.AddToScheme,
|
||||
wgpolicyk8sv1alpha2.AddToScheme,
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
scheme "github.com/kyverno/kyverno/pkg/client/clientset/versioned/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
@ -52,7 +52,7 @@ func NewForConfig(c *rest.Config) (*KyvernoV1beta1Client, error) {
|
|||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1.SchemeGroupVersion
|
||||
gv := v1beta1.GroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/api/kyverno/v1alpha2"
|
||||
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
|
@ -62,6 +63,9 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
|
|||
case v1.SchemeGroupVersion.WithResource("policies"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Kyverno().V1().Policies().Informer()}, nil
|
||||
|
||||
case v1beta1.GroupVersion.WithResource("updaterequests"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Kyverno().V1beta1().UpdateRequests().Informer()}, nil
|
||||
|
||||
// Group=kyverno.io, Version=v1alpha2
|
||||
case v1alpha2.SchemeGroupVersion.WithResource("clusterreportchangerequests"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Kyverno().V1alpha2().ClusterReportChangeRequests().Informer()}, nil
|
||||
|
|
|
@ -22,12 +22,15 @@ import (
|
|||
internalinterfaces "github.com/kyverno/kyverno/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1 "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
v1alpha2 "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1alpha2"
|
||||
v1beta1 "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1 provides access to shared informers for resources in V1.
|
||||
V1() v1.Interface
|
||||
// V1beta1 provides access to shared informers for resources in V1beta1.
|
||||
V1beta1() v1beta1.Interface
|
||||
// V1alpha2 provides access to shared informers for resources in V1alpha2.
|
||||
V1alpha2() v1alpha2.Interface
|
||||
}
|
||||
|
@ -48,6 +51,11 @@ func (g *group) V1() v1.Interface {
|
|||
return v1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
|
||||
// V1beta1 returns a new v1beta1.Interface.
|
||||
func (g *group) V1beta1() v1beta1.Interface {
|
||||
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
|
||||
// V1alpha2 returns a new v1alpha2.Interface.
|
||||
func (g *group) V1alpha2() v1alpha2.Interface {
|
||||
return v1alpha2.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
|
|
|
@ -101,7 +101,7 @@ func VariableToJSON(key, value string) []byte {
|
|||
}
|
||||
|
||||
// RetryFunc allows retrying a function on error within a given timeout
|
||||
func RetryFunc(retryInterval, timeout time.Duration, run func() error, logger logr.Logger) func() error {
|
||||
func RetryFunc(retryInterval, timeout time.Duration, run func() error, msg string, logger logr.Logger) func() error {
|
||||
return func() error {
|
||||
registerTimeout := time.After(timeout)
|
||||
registerTicker := time.NewTicker(retryInterval)
|
||||
|
@ -114,13 +114,13 @@ func RetryFunc(retryInterval, timeout time.Duration, run func() error, logger lo
|
|||
case <-registerTicker.C:
|
||||
err = run()
|
||||
if err != nil {
|
||||
logger.V(3).Info("Failed to register admission control webhooks", "reason", err.Error())
|
||||
logger.V(3).Info(msg, "reason", err.Error())
|
||||
} else {
|
||||
break loop
|
||||
}
|
||||
|
||||
case <-registerTimeout:
|
||||
return errors.Wrap(err, "Timeout registering admission control webhooks")
|
||||
return errors.Wrap(err, "retry times out")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
143
pkg/engine/background.go
Normal file
143
pkg/engine/background.go
Normal file
|
@ -0,0 +1,143 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/engine/common"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
// ApplyBackgroundChecks checks for validity of generate and mutateExisting rules on the resource
|
||||
// 1. validate variables to be substitute in the general ruleInfo (match,exclude,condition)
|
||||
// - the caller has to check the ruleResponse to determine whether the path exist
|
||||
// 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed
|
||||
func ApplyBackgroundChecks(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
policyStartTime := time.Now()
|
||||
return filterRules(policyContext, policyStartTime)
|
||||
}
|
||||
|
||||
func filterRules(policyContext *PolicyContext, startTime time.Time) *response.EngineResponse {
|
||||
kind := policyContext.NewResource.GetKind()
|
||||
name := policyContext.NewResource.GetName()
|
||||
namespace := policyContext.NewResource.GetNamespace()
|
||||
apiVersion := policyContext.NewResource.GetAPIVersion()
|
||||
resp := &response.EngineResponse{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: response.PolicySpec{
|
||||
Name: policyContext.Policy.GetName(),
|
||||
Namespace: policyContext.Policy.GetNamespace(),
|
||||
},
|
||||
PolicyStats: response.PolicyStats{
|
||||
PolicyExecutionTimestamp: startTime.Unix(),
|
||||
},
|
||||
Resource: response.ResourceSpec{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
APIVersion: apiVersion,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if policyContext.ExcludeResourceFunc(kind, namespace, name) {
|
||||
log.Log.WithName("ApplyBackgroundChecks").Info("resource excluded", "kind", kind, "namespace", namespace, "name", name)
|
||||
return resp
|
||||
}
|
||||
|
||||
for _, rule := range autogen.ComputeRules(policyContext.Policy) {
|
||||
if ruleResp := filterRule(rule, policyContext); ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
}
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func filterRule(rule kyverno.Rule, policyContext *PolicyContext) *response.RuleResponse {
|
||||
if !rule.HasGenerate() && !rule.IsMutateExisting() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ruleType := response.Mutation
|
||||
if rule.HasGenerate() {
|
||||
ruleType = response.Generation
|
||||
}
|
||||
|
||||
var err error
|
||||
startTime := time.Now()
|
||||
|
||||
policy := policyContext.Policy
|
||||
newResource := policyContext.NewResource
|
||||
oldResource := policyContext.OldResource
|
||||
admissionInfo := policyContext.AdmissionInfo
|
||||
ctx := policyContext.JSONContext
|
||||
excludeGroupRole := policyContext.ExcludeGroupRole
|
||||
namespaceLabels := policyContext.NamespaceLabels
|
||||
|
||||
logger := log.Log.WithName(string(ruleType)).WithValues("policy", policy.GetName(),
|
||||
"kind", newResource.GetKind(), "namespace", newResource.GetNamespace(), "name", newResource.GetName())
|
||||
|
||||
if err = MatchesResourceDescription(newResource, rule, admissionInfo, excludeGroupRole, namespaceLabels, ""); err != nil {
|
||||
|
||||
if ruleType == response.Generation {
|
||||
// if the oldResource matched, return "false" to delete GR for it
|
||||
if err = MatchesResourceDescription(oldResource, rule, admissionInfo, excludeGroupRole, namespaceLabels, ""); err == nil {
|
||||
return &response.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: ruleType,
|
||||
Status: response.RuleStatusFail,
|
||||
RuleStats: response.RuleStats{
|
||||
ProcessingTime: time.Since(startTime),
|
||||
RuleExecutionTimestamp: startTime.Unix(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
policyContext.JSONContext.Checkpoint()
|
||||
defer policyContext.JSONContext.Restore()
|
||||
|
||||
if err = LoadContext(logger, rule.Context, policyContext, rule.Name); err != nil {
|
||||
logger.V(4).Info("cannot add external data to the context", "reason", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
ruleCopy := rule.DeepCopy()
|
||||
if after, err := variables.SubstituteAllInPreconditions(logger, ctx, ruleCopy.GetAnyAllConditions()); err != nil {
|
||||
logger.V(4).Info("failed to substitute vars in preconditions, skip current rule", "rule name", ruleCopy.Name)
|
||||
return nil
|
||||
} else {
|
||||
ruleCopy.SetAnyAllConditions(after)
|
||||
}
|
||||
|
||||
// operate on the copy of the conditions, as we perform variable substitution
|
||||
copyConditions, err := common.TransformConditions(ruleCopy.GetAnyAllConditions())
|
||||
if err != nil {
|
||||
logger.V(4).Info("cannot copy AnyAllConditions", "reason", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
// evaluate pre-conditions
|
||||
if !variables.EvaluateConditions(logger, ctx, copyConditions) {
|
||||
logger.V(4).Info("skip rule as preconditions are not met", "rule", ruleCopy.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// build rule Response
|
||||
return &response.RuleResponse{
|
||||
Name: ruleCopy.Name,
|
||||
Type: ruleType,
|
||||
Status: response.RuleStatusPass,
|
||||
RuleStats: response.RuleStats{
|
||||
ProcessingTime: time.Since(startTime),
|
||||
RuleExecutionTimestamp: startTime.Unix(),
|
||||
},
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
"sync"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
pkgcommon "github.com/kyverno/kyverno/pkg/common"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -50,7 +50,7 @@ type Interface interface {
|
|||
AddOldResource(data map[string]interface{}) error
|
||||
|
||||
// AddUserInfo merges userInfo json under kyverno.userInfo
|
||||
AddUserInfo(userInfo kyverno.RequestInfo) error
|
||||
AddUserInfo(userInfo urkyverno.RequestInfo) error
|
||||
|
||||
// AddServiceAccount merges ServiceAccount types
|
||||
AddServiceAccount(userName string) error
|
||||
|
@ -166,7 +166,7 @@ func (ctx *context) AddOldResource(data map[string]interface{}) error {
|
|||
}
|
||||
|
||||
// AddUserInfo adds userInfo at path request.userInfo
|
||||
func (ctx *context) AddUserInfo(userRequestInfo kyverno.RequestInfo) error {
|
||||
func (ctx *context) AddUserInfo(userRequestInfo urkyverno.RequestInfo) error {
|
||||
return addToContext(ctx, userRequestInfo, "request")
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
)
|
||||
|
||||
|
@ -48,7 +48,7 @@ func Test_addResourceAndUserContext(t *testing.T) {
|
|||
Username: "system:serviceaccount:nirmata:user1",
|
||||
UID: "014fbff9a07c",
|
||||
}
|
||||
userRequestInfo := kyverno.RequestInfo{
|
||||
userRequestInfo := urkyverno.RequestInfo{
|
||||
Roles: nil,
|
||||
ClusterRoles: nil,
|
||||
AdmissionUserInfo: userInfo}
|
||||
|
|
|
@ -3,27 +3,15 @@ package engine
|
|||
import (
|
||||
"time"
|
||||
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/engine/common"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
// Generate checks for validity of generate rule on the resource
|
||||
// 1. validate variables to be substitute in the general ruleInfo (match,exclude,condition)
|
||||
// - the caller has to check the ruleResponse to determine whether the path exist
|
||||
// 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed
|
||||
func Generate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
policyStartTime := time.Now()
|
||||
return filterRules(policyContext, policyStartTime)
|
||||
}
|
||||
|
||||
// GenerateResponse checks for validity of generate rule on the resource
|
||||
func GenerateResponse(policyContext *PolicyContext, gr kyverno.GenerateRequest) (resp *response.EngineResponse) {
|
||||
func GenerateResponse(policyContext *PolicyContext, gr urkyverno.UpdateRequest) (resp *response.EngineResponse) {
|
||||
policyStartTime := time.Now()
|
||||
return filterGenerateRules(policyContext, gr.Spec.Policy, policyStartTime)
|
||||
}
|
||||
|
@ -69,118 +57,3 @@ func filterGenerateRules(policyContext *PolicyContext, policyNameKey string, sta
|
|||
|
||||
return resp
|
||||
}
|
||||
|
||||
func filterRules(policyContext *PolicyContext, startTime time.Time) *response.EngineResponse {
|
||||
kind := policyContext.NewResource.GetKind()
|
||||
name := policyContext.NewResource.GetName()
|
||||
namespace := policyContext.NewResource.GetNamespace()
|
||||
apiVersion := policyContext.NewResource.GetAPIVersion()
|
||||
resp := &response.EngineResponse{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: response.PolicySpec{
|
||||
Name: policyContext.Policy.GetName(),
|
||||
Namespace: policyContext.Policy.GetNamespace(),
|
||||
},
|
||||
PolicyStats: response.PolicyStats{
|
||||
PolicyExecutionTimestamp: startTime.Unix(),
|
||||
},
|
||||
Resource: response.ResourceSpec{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
APIVersion: apiVersion,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if policyContext.ExcludeResourceFunc(kind, namespace, name) {
|
||||
log.Log.WithName("Generate").Info("resource excluded", "kind", kind, "namespace", namespace, "name", name)
|
||||
return resp
|
||||
}
|
||||
|
||||
for _, rule := range autogen.ComputeRules(policyContext.Policy) {
|
||||
if ruleResp := filterRule(rule, policyContext); ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
}
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func filterRule(rule kyverno.Rule, policyContext *PolicyContext) *response.RuleResponse {
|
||||
if !rule.HasGenerate() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
startTime := time.Now()
|
||||
|
||||
policy := policyContext.Policy
|
||||
newResource := policyContext.NewResource
|
||||
oldResource := policyContext.OldResource
|
||||
admissionInfo := policyContext.AdmissionInfo
|
||||
ctx := policyContext.JSONContext
|
||||
excludeGroupRole := policyContext.ExcludeGroupRole
|
||||
namespaceLabels := policyContext.NamespaceLabels
|
||||
|
||||
logger := log.Log.WithName("Generate").WithValues("policy", policy.GetName(),
|
||||
"kind", newResource.GetKind(), "namespace", newResource.GetNamespace(), "name", newResource.GetName())
|
||||
|
||||
if err = MatchesResourceDescription(newResource, rule, admissionInfo, excludeGroupRole, namespaceLabels, ""); err != nil {
|
||||
|
||||
// if the oldResource matched, return "false" to delete GR for it
|
||||
if err = MatchesResourceDescription(oldResource, rule, admissionInfo, excludeGroupRole, namespaceLabels, ""); err == nil {
|
||||
return &response.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: "Generation",
|
||||
Status: response.RuleStatusFail,
|
||||
RuleStats: response.RuleStats{
|
||||
ProcessingTime: time.Since(startTime),
|
||||
RuleExecutionTimestamp: startTime.Unix(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
policyContext.JSONContext.Checkpoint()
|
||||
defer policyContext.JSONContext.Restore()
|
||||
|
||||
if err = LoadContext(logger, rule.Context, policyContext, rule.Name); err != nil {
|
||||
logger.V(4).Info("cannot add external data to the context", "reason", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
ruleCopy := rule.DeepCopy()
|
||||
if after, err := variables.SubstituteAllInPreconditions(logger, ctx, ruleCopy.GetAnyAllConditions()); err != nil {
|
||||
logger.V(4).Info("failed to substitute vars in preconditions, skip current rule", "rule name", ruleCopy.Name)
|
||||
return nil
|
||||
} else {
|
||||
ruleCopy.SetAnyAllConditions(after)
|
||||
}
|
||||
|
||||
// operate on the copy of the conditions, as we perform variable substitution
|
||||
copyConditions, err := common.TransformConditions(ruleCopy.GetAnyAllConditions())
|
||||
if err != nil {
|
||||
logger.V(4).Info("cannot copy AnyAllConditions", "reason", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
// evaluate pre-conditions
|
||||
if !variables.EvaluateConditions(logger, ctx, copyConditions) {
|
||||
logger.V(4).Info("skip rule as preconditions are not met", "rule", ruleCopy.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// build rule Response
|
||||
return &response.RuleResponse{
|
||||
Name: ruleCopy.Name,
|
||||
Type: "Generation",
|
||||
Status: response.RuleStatusPass,
|
||||
RuleStats: response.RuleStats{
|
||||
ProcessingTime: time.Since(startTime),
|
||||
RuleExecutionTimestamp: startTime.Unix(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (resp *response.EngineRe
|
|||
}
|
||||
|
||||
func appendError(resp *response.EngineResponse, rule *v1.Rule, msg string, status response.RuleStatus) {
|
||||
rr := ruleResponse(rule, response.ImageVerify, msg, status)
|
||||
rr := ruleResponse(*rule, response.ImageVerify, msg, status, nil)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *rr)
|
||||
incrementErrorCount(resp)
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ func (iv *imageVerifier) verify(imageVerify *v1.ImageVerification, images map[st
|
|||
if imageInfo.Digest == "" && *imageVerify.MutateDigest && ruleResp.Status == response.RuleStatusPass {
|
||||
err := iv.patchDigest(path, imageInfo, digest, ruleResp)
|
||||
if err != nil {
|
||||
ruleResp = ruleResponse(iv.rule, response.ImageVerify, err.Error(), response.RuleStatusFail)
|
||||
ruleResp = ruleResponse(*iv.rule, response.ImageVerify, err.Error(), response.RuleStatusFail, nil)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -177,11 +177,11 @@ func (iv *imageVerifier) verify(imageVerify *v1.ImageVerification, images map[st
|
|||
digest, err := fetchImageDigest(imageInfo.String())
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fetching image digest from registry error: %s", err)
|
||||
ruleResp = ruleResponse(iv.rule, response.ImageVerify, msg, response.RuleStatusFail)
|
||||
ruleResp = ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusFail, nil)
|
||||
} else {
|
||||
err = iv.patchDigest(path, imageInfo, digest, ruleResp)
|
||||
if err != nil {
|
||||
ruleResp = ruleResponse(iv.rule, response.ImageVerify, err.Error(), response.RuleStatusFail)
|
||||
ruleResp = ruleResponse(*iv.rule, response.ImageVerify, err.Error(), response.RuleStatusFail, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,12 +227,12 @@ func (iv *imageVerifier) verifySignatures(imageVerify *v1.ImageVerification, ima
|
|||
if err != nil {
|
||||
iv.logger.Error(err, "failed to verify signature", "attestorSet", attestorSet)
|
||||
msg := fmt.Sprintf("failed to verify signature for %s: %s", image, err.Error())
|
||||
return ruleResponse(iv.rule, response.ImageVerify, msg, response.RuleStatusFail), ""
|
||||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusFail, nil), ""
|
||||
}
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("verified image signatures for %s", image)
|
||||
return ruleResponse(iv.rule, response.ImageVerify, msg, response.RuleStatusPass), digest
|
||||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusPass, nil), digest
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) verifyAttestorSet(attestorSet *v1.AttestorSet, imageVerify *v1.ImageVerification, image, path string) (string, error) {
|
||||
|
@ -418,7 +418,7 @@ func (iv *imageVerifier) attestImage(imageVerify *v1.ImageVerification, imageInf
|
|||
statements := statementsByPredicate[ac.PredicateType]
|
||||
if statements == nil {
|
||||
msg := fmt.Sprintf("predicate type %s not found", ac.PredicateType)
|
||||
return ruleResponse(iv.rule, response.ImageVerify, msg, response.RuleStatusFail)
|
||||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusFail, nil)
|
||||
}
|
||||
|
||||
for _, s := range statements {
|
||||
|
@ -429,14 +429,14 @@ func (iv *imageVerifier) attestImage(imageVerify *v1.ImageVerification, imageInf
|
|||
|
||||
if !val {
|
||||
msg := fmt.Sprintf("attestation checks failed for %s and predicate %s", imageInfo.String(), ac.PredicateType)
|
||||
return ruleResponse(iv.rule, response.ImageVerify, msg, response.RuleStatusFail)
|
||||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusFail, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("attestation checks passed for %s", imageInfo.String())
|
||||
iv.logger.V(2).Info(msg)
|
||||
return ruleResponse(iv.rule, response.ImageVerify, msg, response.RuleStatusPass)
|
||||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusPass, nil)
|
||||
}
|
||||
|
||||
func buildStatementMap(statements []map[string]interface{}) map[string][]map[string]interface{} {
|
||||
|
|
61
pkg/engine/loadtargets.go
Normal file
61
pkg/engine/loadtargets.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
engineUtils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func loadTargets(logger logr.Logger, targets []kyverno.TargetMutation, ctx *PolicyContext) ([]unstructured.Unstructured, error) {
|
||||
targetObjects := make([]unstructured.Unstructured, len(targets))
|
||||
var errors []error
|
||||
|
||||
for i, target := range targets {
|
||||
apiversion, err := variables.SubstituteAll(logger, ctx.JSONContext, target.APIVersion)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("failed to substitute variables in target[%d].APIVersion %s: %v", i, target.APIVersion, err))
|
||||
continue
|
||||
}
|
||||
|
||||
kind, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Kind)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("failed to substitute variables in target[%d].Kind %s: %v", i, target.Kind, err))
|
||||
continue
|
||||
}
|
||||
|
||||
name, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Name)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("failed to substitute variables in target[%d].Name %s: %v", i, target.Name, err))
|
||||
continue
|
||||
}
|
||||
|
||||
namespace, err := variables.SubstituteAll(logger, ctx.JSONContext, target.Namespace)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("failed to substitute variables in target[%d].Namespace %s: %v", i, target.Namespace, err))
|
||||
continue
|
||||
}
|
||||
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
|
||||
obj, err := ctx.Client.GetResource(apiversion.(string), kind.(string), namespace.(string), name.(string))
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("failed to get target %s/%s %s/%s : %v", apiversion, kind, namespace, name, err))
|
||||
continue
|
||||
}
|
||||
|
||||
if obj.GetKind() == "" {
|
||||
obj.SetKind(kind.(string))
|
||||
}
|
||||
|
||||
obj.SetAPIVersion(apiversion.(string))
|
||||
targetObjects = append(targetObjects, *obj)
|
||||
}
|
||||
|
||||
return targetObjects, engineUtils.CombineErrors(errors)
|
||||
}
|
|
@ -218,7 +218,7 @@ func assertEqStringAndData(t *testing.T, str string, data []byte) {
|
|||
json.Unmarshal([]byte(str), &p1)
|
||||
|
||||
var p2 jsonPatch
|
||||
json.Unmarshal([]byte(str), &p2)
|
||||
json.Unmarshal([]byte(data), &p2)
|
||||
|
||||
assert.Equal(t, p1, p2)
|
||||
}
|
||||
|
|
|
@ -22,16 +22,16 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
resp = &response.EngineResponse{
|
||||
Policy: policy,
|
||||
}
|
||||
patchedResource := policyContext.NewResource
|
||||
matchedResource := policyContext.NewResource
|
||||
ctx := policyContext.JSONContext
|
||||
var skippedRules []string
|
||||
|
||||
logger := log.Log.WithName("EngineMutate").WithValues("policy", policy.GetName(), "kind", patchedResource.GetKind(),
|
||||
"namespace", patchedResource.GetNamespace(), "name", patchedResource.GetName())
|
||||
logger := log.Log.WithName("EngineMutate").WithValues("policy", policy.GetName(), "kind", matchedResource.GetKind(),
|
||||
"namespace", matchedResource.GetNamespace(), "name", matchedResource.GetName())
|
||||
|
||||
logger.V(4).Info("start mutate policy processing", "startTime", startTime)
|
||||
|
||||
startMutateResultResponse(resp, policy, patchedResource)
|
||||
startMutateResultResponse(resp, policy, matchedResource)
|
||||
defer endMutateResultResponse(logger, resp, startTime)
|
||||
|
||||
policyContext.JSONContext.Checkpoint()
|
||||
|
@ -50,7 +50,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
excludeResource = policyContext.ExcludeGroupRole
|
||||
}
|
||||
|
||||
if err = MatchesResourceDescription(patchedResource, rule, policyContext.AdmissionInfo, excludeResource, policyContext.NamespaceLabels, policyContext.Policy.GetNamespace()); err != nil {
|
||||
if err = MatchesResourceDescription(matchedResource, rule, policyContext.AdmissionInfo, excludeResource, policyContext.NamespaceLabels, policyContext.Policy.GetNamespace()); err != nil {
|
||||
logger.V(4).Info("rule not matched", "reason", err.Error())
|
||||
skippedRules = append(skippedRules, rule.Name)
|
||||
continue
|
||||
|
@ -78,19 +78,41 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
}
|
||||
|
||||
ruleCopy := rule.DeepCopy()
|
||||
var ruleResp *response.RuleResponse
|
||||
if rule.Mutation.ForEachMutation != nil {
|
||||
ruleResp, patchedResource = mutateForEach(ruleCopy, policyContext, patchedResource, logger)
|
||||
var patchedResources []unstructured.Unstructured
|
||||
if !policyContext.AdmissionOperation && rule.IsMutateExisting() {
|
||||
targets, err := loadTargets(logger, ruleCopy.Mutation.Targets, policyContext)
|
||||
if err != nil {
|
||||
rr := ruleResponse(rule, response.Mutation, err.Error(), response.RuleStatusError, nil)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *rr)
|
||||
} else {
|
||||
patchedResources = append(patchedResources, targets...)
|
||||
}
|
||||
} else {
|
||||
ruleResp, patchedResource = mutateResource(ruleCopy, policyContext, patchedResource, logger)
|
||||
patchedResources = append(patchedResources, matchedResource)
|
||||
}
|
||||
|
||||
if ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
if ruleResp.Status == response.RuleStatusError {
|
||||
incrementErrorCount(resp)
|
||||
for _, patchedResource := range patchedResources {
|
||||
if reflect.DeepEqual(patchedResource, unstructured.Unstructured{}) {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.V(4).Info("apply rule to resource", "rule", rule.Name, "resource namespace", patchedResource.GetNamespace(), "resource name", patchedResource.GetName())
|
||||
var ruleResp *response.RuleResponse
|
||||
if rule.Mutation.ForEachMutation != nil {
|
||||
ruleResp, patchedResource = mutateForEach(ruleCopy, policyContext, patchedResource, logger)
|
||||
} else {
|
||||
incrementAppliedCount(resp)
|
||||
ruleResp, patchedResource = mutateResource(ruleCopy, policyContext, patchedResource, logger)
|
||||
}
|
||||
|
||||
matchedResource = patchedResource
|
||||
|
||||
if ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
if ruleResp.Status == response.RuleStatusError {
|
||||
incrementErrorCount(resp)
|
||||
} else {
|
||||
incrementAppliedCount(resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +126,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
}
|
||||
}
|
||||
|
||||
resp.PatchedResource = patchedResource
|
||||
resp.PatchedResource = matchedResource
|
||||
return resp
|
||||
}
|
||||
|
||||
|
@ -115,11 +137,11 @@ func mutateResource(rule *kyverno.Rule, ctx *PolicyContext, resource unstructure
|
|||
}
|
||||
|
||||
if !preconditionsPassed {
|
||||
return ruleResponse(rule, response.Mutation, "preconditions not met", response.RuleStatusSkip), resource
|
||||
return ruleResponse(*rule, response.Mutation, "preconditions not met", response.RuleStatusSkip, &resource), resource
|
||||
}
|
||||
|
||||
mutateResp := mutate.Mutate(rule, ctx.JSONContext, resource, logger)
|
||||
ruleResp := buildRuleResponse(rule, mutateResp)
|
||||
ruleResp := buildRuleResponse(rule, mutateResp, &mutateResp.PatchedResource)
|
||||
return ruleResp, mutateResp.PatchedResource
|
||||
}
|
||||
|
||||
|
@ -145,7 +167,7 @@ func mutateForEach(rule *kyverno.Rule, ctx *PolicyContext, resource unstructured
|
|||
}
|
||||
|
||||
if !preconditionsPassed {
|
||||
return ruleResponse(rule, response.Mutation, "preconditions not met", response.RuleStatusSkip), resource
|
||||
return ruleResponse(*rule, response.Mutation, "preconditions not met", response.RuleStatusSkip, &patchedResource), resource
|
||||
}
|
||||
|
||||
elements, err := evaluateList(foreach.List, ctx.JSONContext)
|
||||
|
@ -157,7 +179,7 @@ func mutateForEach(rule *kyverno.Rule, ctx *PolicyContext, resource unstructured
|
|||
mutateResp := mutateElements(rule.Name, foreach, ctx, elements, patchedResource, logger)
|
||||
if mutateResp.Status == response.RuleStatusError {
|
||||
logger.Error(err, "failed to mutate elements")
|
||||
return buildRuleResponse(rule, mutateResp), resource
|
||||
return buildRuleResponse(rule, mutateResp, nil), resource
|
||||
}
|
||||
|
||||
if mutateResp.Status != response.RuleStatusSkip {
|
||||
|
@ -170,10 +192,10 @@ func mutateForEach(rule *kyverno.Rule, ctx *PolicyContext, resource unstructured
|
|||
}
|
||||
|
||||
if applyCount == 0 {
|
||||
return ruleResponse(rule, response.Mutation, "0 elements processed", response.RuleStatusSkip), resource
|
||||
return ruleResponse(*rule, response.Mutation, "0 elements processed", response.RuleStatusSkip, &resource), resource
|
||||
}
|
||||
|
||||
r := ruleResponse(rule, response.Mutation, fmt.Sprintf("%d elements processed", applyCount), response.RuleStatusPass)
|
||||
r := ruleResponse(*rule, response.Mutation, fmt.Sprintf("%d elements processed", applyCount), response.RuleStatusPass, &patchedResource)
|
||||
r.Patches = allPatches
|
||||
return r, patchedResource
|
||||
}
|
||||
|
@ -237,8 +259,8 @@ func mutateError(err error, message string) *mutate.Response {
|
|||
}
|
||||
}
|
||||
|
||||
func buildRuleResponse(rule *kyverno.Rule, mutateResp *mutate.Response) *response.RuleResponse {
|
||||
resp := ruleResponse(rule, response.Mutation, mutateResp.Message, mutateResp.Status)
|
||||
func buildRuleResponse(rule *kyverno.Rule, mutateResp *mutate.Response, patchedResource *unstructured.Unstructured) *response.RuleResponse {
|
||||
resp := ruleResponse(*rule, response.Mutation, mutateResp.Message, mutateResp.Status, patchedResource)
|
||||
if resp.Status == response.RuleStatusPass {
|
||||
resp.Patches = mutateResp.Patches
|
||||
resp.Message = buildSuccessMessage(mutateResp.PatchedResource)
|
||||
|
|
|
@ -7,13 +7,15 @@ import (
|
|||
"testing"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"gotest.tools/assert"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
|
||||
|
@ -1027,3 +1029,254 @@ func Test_foreach_order_mutation_(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_mutate_existing_resources(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
policy []byte
|
||||
trigger []byte
|
||||
target []byte
|
||||
targetList string
|
||||
patches []string
|
||||
}{
|
||||
{
|
||||
name: "test-different-trigger-target",
|
||||
policy: []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {
|
||||
"name": "test-post-mutation"
|
||||
},
|
||||
"spec": {
|
||||
"rules": [
|
||||
{
|
||||
"name": "mutate-deploy-on-configmap-update",
|
||||
"match": {
|
||||
"any": [
|
||||
{
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"ConfigMap"
|
||||
],
|
||||
"names": [
|
||||
"dictionary"
|
||||
],
|
||||
"namespaces": [
|
||||
"staging"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"preconditions": {
|
||||
"any": [
|
||||
{
|
||||
"key": "{{ request.object.data.foo }}",
|
||||
"operator": "Equals",
|
||||
"value": "bar"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mutate": {
|
||||
"targets": [
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Deployment",
|
||||
"name": "example-A",
|
||||
"namespace": "staging"
|
||||
}
|
||||
],
|
||||
"patchStrategicMerge": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"foo": "bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`),
|
||||
trigger: []byte(`{
|
||||
"apiVersion": "v1",
|
||||
"data": {
|
||||
"foo": "bar"
|
||||
},
|
||||
"kind": "ConfigMap",
|
||||
"metadata": {
|
||||
"name": "dictionary",
|
||||
"namespace": "staging"
|
||||
}
|
||||
}`),
|
||||
target: []byte(`{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": {
|
||||
"name": "example-A",
|
||||
"namespace": "staging",
|
||||
"labels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"replicas": 1,
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"app": "nginx"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx:1.14.2",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}`),
|
||||
targetList: "DeploymentList",
|
||||
patches: []string{`{"op":"add","path":"/metadata/labels/foo","value":"bar"}`},
|
||||
},
|
||||
{
|
||||
name: "test-same-trigger-target",
|
||||
policy: []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {
|
||||
"name": "test-post-mutation"
|
||||
},
|
||||
"spec": {
|
||||
"rules": [
|
||||
{
|
||||
"name": "mutate-deploy-on-configmap-update",
|
||||
"match": {
|
||||
"any": [
|
||||
{
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"ConfigMap"
|
||||
],
|
||||
"names": [
|
||||
"dictionary"
|
||||
],
|
||||
"namespaces": [
|
||||
"staging"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"preconditions": {
|
||||
"any": [
|
||||
{
|
||||
"key": "{{ request.object.data.foo }}",
|
||||
"operator": "Equals",
|
||||
"value": "bar"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mutate": {
|
||||
"targets": [
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
"name": "dictionary",
|
||||
"namespace": "staging"
|
||||
}
|
||||
],
|
||||
"patchStrategicMerge": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"foo": "bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`),
|
||||
trigger: []byte(`{
|
||||
"apiVersion": "v1",
|
||||
"data": {
|
||||
"foo": "bar"
|
||||
},
|
||||
"kind": "ConfigMap",
|
||||
"metadata": {
|
||||
"name": "dictionary",
|
||||
"namespace": "staging"
|
||||
}
|
||||
}`),
|
||||
target: []byte(`{
|
||||
"apiVersion": "v1",
|
||||
"data": {
|
||||
"foo": "bar"
|
||||
},
|
||||
"kind": "ConfigMap",
|
||||
"metadata": {
|
||||
"name": "dictionary",
|
||||
"namespace": "staging"
|
||||
}
|
||||
}`),
|
||||
targetList: "ComfigMapList",
|
||||
patches: []string{`{"op":"add","path":"/metadata/labels","value":{"foo":"bar"}}`},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var policy kyverno.ClusterPolicy
|
||||
err := json.Unmarshal(test.policy, &policy)
|
||||
assert.NilError(t, err)
|
||||
|
||||
trigger, err := utils.ConvertToUnstructured(test.trigger)
|
||||
assert.NilError(t, err)
|
||||
|
||||
target, err := utils.ConvertToUnstructured(test.target)
|
||||
assert.NilError(t, err)
|
||||
|
||||
ctx := context.NewContext()
|
||||
err = ctx.AddResource(trigger.Object)
|
||||
assert.NilError(t, err)
|
||||
|
||||
gvrToListKind := map[schema.GroupVersionResource]string{
|
||||
{Group: target.GroupVersionKind().Group, Version: target.GroupVersionKind().Version, Resource: target.GroupVersionKind().Kind}: test.targetList,
|
||||
}
|
||||
|
||||
objects := []runtime.Object{target}
|
||||
scheme := runtime.NewScheme()
|
||||
dclient, err := client.NewMockClient(scheme, gvrToListKind, objects...)
|
||||
assert.NilError(t, err)
|
||||
dclient.SetDiscovery(client.NewFakeDiscoveryClient(nil))
|
||||
|
||||
_, err = dclient.GetResource(target.GetAPIVersion(), target.GetKind(), target.GetNamespace(), target.GetName())
|
||||
assert.NilError(t, err)
|
||||
|
||||
policyContext := &PolicyContext{
|
||||
Client: dclient,
|
||||
Policy: &policy,
|
||||
JSONContext: ctx,
|
||||
NewResource: *trigger,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
|
||||
for _, rr := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, test.patches[0], string(rr.Patches[0]))
|
||||
assert.Equal(t, rr.Status, response.RuleStatusPass, rr.Status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package engine
|
|||
|
||||
import (
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -22,9 +23,9 @@ type PolicyContext struct {
|
|||
Element unstructured.Unstructured
|
||||
|
||||
// AdmissionInfo contains the admission request information
|
||||
AdmissionInfo kyverno.RequestInfo
|
||||
AdmissionInfo urkyverno.RequestInfo
|
||||
|
||||
// Dynamic client - used by generate
|
||||
// Dynamic client - used for api lookups
|
||||
Client *client.Client
|
||||
|
||||
// Config handler
|
||||
|
@ -37,6 +38,9 @@ type PolicyContext struct {
|
|||
|
||||
// NamespaceLabels stores the label of namespace to be processed by namespace selector
|
||||
NamespaceLabels map[string]string
|
||||
|
||||
// AdmissionOperation represents if the caller is from the webhook server
|
||||
AdmissionOperation bool
|
||||
}
|
||||
|
||||
func (pc *PolicyContext) Copy() *PolicyContext {
|
||||
|
|
|
@ -109,6 +109,9 @@ type RuleResponse struct {
|
|||
|
||||
// statistics
|
||||
RuleStats `json:",inline"`
|
||||
|
||||
// PatchedTarget is the patched resource for mutate.targets
|
||||
PatchedTarget *unstructured.Unstructured
|
||||
}
|
||||
|
||||
//ToString ...
|
||||
|
|
|
@ -6,18 +6,17 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/engine/common"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
wildcard "github.com/kyverno/go-wildcard"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/common"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
wildcard "github.com/kyverno/go-wildcard"
|
||||
"github.com/kyverno/kyverno/pkg/engine/wildcards"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
|
@ -127,7 +126,7 @@ func checkSelector(labelSelector *metav1.LabelSelector, resourceLabels map[strin
|
|||
// should be: AND across attributes but an OR inside attributes that of type list
|
||||
// To filter out the targeted resources with UserInfo, the check
|
||||
// should be: OR (across & inside) attributes
|
||||
func doesResourceMatchConditionBlock(conditionBlock kyverno.ResourceDescription, userInfo kyverno.UserInfo, admissionInfo kyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
|
||||
func doesResourceMatchConditionBlock(conditionBlock kyverno.ResourceDescription, userInfo kyverno.UserInfo, admissionInfo urkyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
|
||||
var errs []error
|
||||
|
||||
if len(conditionBlock.Kinds) > 0 {
|
||||
|
@ -263,7 +262,7 @@ func matchSubjects(ruleSubjects []rbacv1.Subject, userInfo authenticationv1.User
|
|||
}
|
||||
|
||||
//MatchesResourceDescription checks if the resource matches resource description of the rule or not
|
||||
func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef kyverno.Rule, admissionInfoRef kyverno.RequestInfo, dynamicConfig []string, namespaceLabels map[string]string, policyNamespace string) error {
|
||||
func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef kyverno.Rule, admissionInfoRef urkyverno.RequestInfo, dynamicConfig []string, namespaceLabels map[string]string, policyNamespace string) error {
|
||||
|
||||
rule := ruleRef.DeepCopy()
|
||||
resource := *resourceRef.DeepCopy()
|
||||
|
@ -336,7 +335,7 @@ func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef k
|
|||
return nil
|
||||
}
|
||||
|
||||
func matchesResourceDescriptionMatchHelper(rmr kyverno.ResourceFilter, admissionInfo kyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
|
||||
func matchesResourceDescriptionMatchHelper(rmr kyverno.ResourceFilter, admissionInfo urkyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
|
||||
var errs []error
|
||||
if reflect.DeepEqual(admissionInfo, kyverno.RequestInfo{}) {
|
||||
rmr.UserInfo = kyverno.UserInfo{}
|
||||
|
@ -353,7 +352,7 @@ func matchesResourceDescriptionMatchHelper(rmr kyverno.ResourceFilter, admission
|
|||
return errs
|
||||
}
|
||||
|
||||
func matchesResourceDescriptionExcludeHelper(rer kyverno.ResourceFilter, admissionInfo kyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
|
||||
func matchesResourceDescriptionExcludeHelper(rer kyverno.ResourceFilter, admissionInfo urkyverno.RequestInfo, resource unstructured.Unstructured, dynamicConfig []string, namespaceLabels map[string]string) []error {
|
||||
var errs []error
|
||||
// checking if resource matches the rule
|
||||
if !reflect.DeepEqual(rer.ResourceDescription, kyverno.ResourceDescription{}) ||
|
||||
|
@ -474,16 +473,21 @@ func evaluateList(jmesPath string, ctx context.EvalInterface) ([]interface{}, er
|
|||
|
||||
func ruleError(rule *kyverno.Rule, ruleType response.RuleType, msg string, err error) *response.RuleResponse {
|
||||
msg = fmt.Sprintf("%s: %s", msg, err.Error())
|
||||
return ruleResponse(rule, ruleType, msg, response.RuleStatusError)
|
||||
return ruleResponse(*rule, ruleType, msg, response.RuleStatusError, nil)
|
||||
}
|
||||
|
||||
func ruleResponse(rule *kyverno.Rule, ruleType response.RuleType, msg string, status response.RuleStatus) *response.RuleResponse {
|
||||
return &response.RuleResponse{
|
||||
func ruleResponse(rule kyverno.Rule, ruleType response.RuleType, msg string, status response.RuleStatus, patchedResource *unstructured.Unstructured) *response.RuleResponse {
|
||||
resp := &response.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: ruleType,
|
||||
Message: msg,
|
||||
Status: status,
|
||||
}
|
||||
|
||||
if rule.Mutation.Targets != nil {
|
||||
resp.PatchedTarget = patchedResource
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func incrementAppliedCount(resp *response.EngineResponse) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
v1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"gotest.tools/assert"
|
||||
|
@ -14,14 +15,14 @@ import (
|
|||
func TestMatchesResourceDescription(t *testing.T) {
|
||||
tcs := []struct {
|
||||
Description string
|
||||
AdmissionInfo v1.RequestInfo
|
||||
AdmissionInfo v1beta1.RequestInfo
|
||||
Resource []byte
|
||||
Policy []byte
|
||||
areErrorsExpected bool
|
||||
}{
|
||||
{
|
||||
Description: "Match Any matches the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -106,7 +107,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Match Any does not match the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -191,7 +192,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Match All matches the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -276,7 +277,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Match All does not match the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -361,7 +362,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Exclude Any excludes the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -461,7 +462,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Exclude Any does not exclude the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -561,7 +562,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Exclude All excludes the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -661,7 +662,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Exclude All does not exclude the Pod",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{
|
||||
|
@ -761,7 +762,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should match pod and not exclude it",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"hello-world","labels":{"name":"hello-world"}},"spec":{"containers":[{"name":"hello-world","image":"hello-world","ports":[{"containerPort":81}],"resources":{"limits":{"memory":"30Mi","cpu":"0.2"},"requests":{"memory":"20Mi","cpu":"0.1"}}}]}}`),
|
||||
|
@ -770,7 +771,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should exclude resource since it matches the exclude block",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"system:node"},
|
||||
},
|
||||
Resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"hello-world","labels":{"name":"hello-world"}},"spec":{"containers":[{"name":"hello-world","image":"hello-world","ports":[{"containerPort":81}],"resources":{"limits":{"memory":"30Mi","cpu":"0.2"},"requests":{"memory":"20Mi","cpu":"0.1"}}}]}}`),
|
||||
|
@ -790,7 +791,10 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
areErrorsExpected: true,
|
||||
},
|
||||
{
|
||||
Description: "Should pass since resource matches a name in the names field",
|
||||
Description: "Should pass since resource matches a name in the names field",
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"system:node"},
|
||||
},
|
||||
Resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"hello-world","labels":{"name":"hello-world"}},"spec":{"containers":[{"name":"hello-world","image":"hello-world","ports":[{"containerPort":81}],"resources":{"limits":{"memory":"30Mi","cpu":"0.2"},"requests":{"memory":"20Mi","cpu":"0.1"}}}]}}`),
|
||||
Policy: []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"hello-world-policy"},"spec":{"background":false,"rules":[{"name":"hello-world-policy","match":{"resources":{"kinds":["Pod"],"names": ["dev-*","hello-world"]},"clusterRoles":["system:node"]},"mutate":{"overlay":{"spec":{"containers":[{"(image)":"*","imagePullPolicy":"IfNotPresent"}]}}}}]}}`),
|
||||
areErrorsExpected: false,
|
||||
|
@ -809,7 +813,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should fail since resource does not match policy",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{"apiVersion":"v1","kind":"Service","metadata":{"name":"hello-world","labels":{"name":"hello-world"}},"spec":{"containers":[{"name":"hello-world","image":"hello-world","ports":[{"containerPort":81}],"resources":{"limits":{"memory":"30Mi","cpu":"0.2"},"requests":{"memory":"20Mi","cpu":"0.1"}}}]}}`),
|
||||
|
@ -818,7 +822,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should not fail since resource does not match exclude block",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"system:node"},
|
||||
},
|
||||
Resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"hello-world2","labels":{"name":"hello-world"}},"spec":{"containers":[{"name":"hello-world","image":"hello-world","ports":[{"containerPort":81}],"resources":{"limits":{"memory":"30Mi","cpu":"0.2"},"requests":{"memory":"20Mi","cpu":"0.1"}}}]}}`),
|
||||
|
@ -827,7 +831,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should pass since group, version, kind match",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
|
||||
|
@ -836,7 +840,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should pass since version and kind match",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`),
|
||||
|
@ -845,7 +849,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should fail since resource does not match ",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{"apiVersion":"v1","kind":"Service","metadata":{"name":"hello-world","labels":{"name":"hello-world"}},"spec":{"containers":[{"name":"hello-world","image":"hello-world","ports":[{"containerPort":81}],"resources":{"limits":{"memory":"30Mi","cpu":"0.2"},"requests":{"memory":"20Mi","cpu":"0.1"}}}]}}`),
|
||||
|
@ -854,7 +858,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should fail since version not match",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{ "apiVersion": "apps/v1beta1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
|
||||
|
@ -863,7 +867,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Should fail since cluster role version not match",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{ "kind": "ClusterRole", "apiVersion": "rbac.authorization.k8s.io/v1", "metadata": { "name": "secret-reader-demo", "namespace": "default" }, "rules": [ { "apiGroups": [ "" ], "resources": [ "secrets" ], "verbs": [ "get", "watch", "list" ] } ] }`),
|
||||
|
@ -872,7 +876,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Test for GVK case sensitive",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`),
|
||||
|
@ -881,7 +885,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Description: "Test should pass for GVK case sensitive",
|
||||
AdmissionInfo: v1.RequestInfo{
|
||||
AdmissionInfo: v1beta1.RequestInfo{
|
||||
ClusterRoles: []string{"admin"},
|
||||
},
|
||||
Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
|
||||
|
@ -902,7 +906,7 @@ func TestMatchesResourceDescription(t *testing.T) {
|
|||
err := MatchesResourceDescription(*resource, rule, tc.AdmissionInfo, []string{}, nil, "")
|
||||
if err != nil {
|
||||
if !tc.areErrorsExpected {
|
||||
t.Errorf("Testcase %d Unexpected error: %v", i+1, err)
|
||||
t.Errorf("Testcase %d Unexpected error: %v\nmsg: %s", i+1, err, tc.Description)
|
||||
}
|
||||
} else {
|
||||
if tc.areErrorsExpected {
|
||||
|
@ -967,7 +971,7 @@ func TestResourceDescriptionMatch_MultipleKind(t *testing.T) {
|
|||
}
|
||||
rule := v1.Rule{MatchResources: v1.MatchResources{ResourceDescription: resourceDescription}}
|
||||
|
||||
if err := MatchesResourceDescription(*resource, rule, v1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
if err := MatchesResourceDescription(*resource, rule, v1beta1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
t.Errorf("Testcase has failed due to the following:%v", err)
|
||||
}
|
||||
|
||||
|
@ -1028,7 +1032,7 @@ func TestResourceDescriptionMatch_Name(t *testing.T) {
|
|||
}
|
||||
rule := v1.Rule{MatchResources: v1.MatchResources{ResourceDescription: resourceDescription}}
|
||||
|
||||
if err := MatchesResourceDescription(*resource, rule, v1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
if err := MatchesResourceDescription(*resource, rule, v1beta1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
t.Errorf("Testcase has failed due to the following:%v", err)
|
||||
}
|
||||
}
|
||||
|
@ -1088,7 +1092,7 @@ func TestResourceDescriptionMatch_Name_Regex(t *testing.T) {
|
|||
}
|
||||
rule := v1.Rule{MatchResources: v1.MatchResources{ResourceDescription: resourceDescription}}
|
||||
|
||||
if err := MatchesResourceDescription(*resource, rule, v1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
if err := MatchesResourceDescription(*resource, rule, v1beta1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
t.Errorf("Testcase has failed due to the following:%v", err)
|
||||
}
|
||||
}
|
||||
|
@ -1156,7 +1160,7 @@ func TestResourceDescriptionMatch_Label_Expression_NotMatch(t *testing.T) {
|
|||
}
|
||||
rule := v1.Rule{MatchResources: v1.MatchResources{ResourceDescription: resourceDescription}}
|
||||
|
||||
if err := MatchesResourceDescription(*resource, rule, v1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
if err := MatchesResourceDescription(*resource, rule, v1beta1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
t.Errorf("Testcase has failed due to the following:%v", err)
|
||||
}
|
||||
}
|
||||
|
@ -1225,7 +1229,7 @@ func TestResourceDescriptionMatch_Label_Expression_Match(t *testing.T) {
|
|||
}
|
||||
rule := v1.Rule{MatchResources: v1.MatchResources{ResourceDescription: resourceDescription}}
|
||||
|
||||
if err := MatchesResourceDescription(*resource, rule, v1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
if err := MatchesResourceDescription(*resource, rule, v1beta1.RequestInfo{}, []string{}, nil, ""); err != nil {
|
||||
t.Errorf("Testcase has failed due to the following:%v", err)
|
||||
}
|
||||
}
|
||||
|
@ -1305,7 +1309,7 @@ func TestResourceDescriptionExclude_Label_Expression_Match(t *testing.T) {
|
|||
rule := v1.Rule{MatchResources: v1.MatchResources{ResourceDescription: resourceDescription},
|
||||
ExcludeResources: v1.MatchResources{ResourceDescription: resourceDescriptionExclude}}
|
||||
|
||||
if err := MatchesResourceDescription(*resource, rule, v1.RequestInfo{}, []string{}, nil, ""); err == nil {
|
||||
if err := MatchesResourceDescription(*resource, rule, v1beta1.RequestInfo{}, []string{}, nil, ""); err == nil {
|
||||
t.Errorf("Testcase has failed due to the following:\n Function has returned no error, even though it was supposed to fail")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,7 +208,7 @@ func (v *validator) validate() *response.RuleResponse {
|
|||
}
|
||||
|
||||
if !preconditionsPassed && v.ctx.Policy.GetSpec().ValidationFailureAction != kyverno.Audit {
|
||||
return ruleResponse(v.rule, response.Validation, "preconditions not met", response.RuleStatusSkip)
|
||||
return ruleResponse(*v.rule, response.Validation, "preconditions not met", response.RuleStatusSkip, nil)
|
||||
}
|
||||
|
||||
if v.deny != nil {
|
||||
|
@ -249,7 +249,7 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
|||
if err != nil {
|
||||
return ruleError(v.rule, response.Validation, "failed to evaluate preconditions", err)
|
||||
} else if !preconditionsPassed && v.ctx.Policy.GetSpec().ValidationFailureAction != kyverno.Audit {
|
||||
return ruleResponse(v.rule, response.Validation, "preconditions not met", response.RuleStatusSkip)
|
||||
return ruleResponse(*v.rule, response.Validation, "preconditions not met", response.RuleStatusSkip, nil)
|
||||
}
|
||||
|
||||
foreachList := v.rule.Validation.ForEachValidation
|
||||
|
@ -279,10 +279,10 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
|||
}
|
||||
|
||||
if applyCount == 0 {
|
||||
return ruleResponse(v.rule, response.Validation, "rule skipped", response.RuleStatusSkip)
|
||||
return ruleResponse(*v.rule, response.Validation, "rule skipped", response.RuleStatusSkip, nil)
|
||||
}
|
||||
|
||||
return ruleResponse(v.rule, response.Validation, "rule passed", response.RuleStatusPass)
|
||||
return ruleResponse(*v.rule, response.Validation, "rule passed", response.RuleStatusPass, nil)
|
||||
}
|
||||
|
||||
func (v *validator) validateElements(foreach *kyverno.ForEachValidation, elements []interface{}, elementScope bool) (*response.RuleResponse, int) {
|
||||
|
@ -309,13 +309,13 @@ func (v *validator) validateElements(foreach *kyverno.ForEachValidation, element
|
|||
continue
|
||||
} else if r.Status != response.RuleStatusPass {
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message)
|
||||
return ruleResponse(v.rule, response.Validation, msg, r.Status), applyCount
|
||||
return ruleResponse(*v.rule, response.Validation, msg, r.Status, nil), applyCount
|
||||
}
|
||||
|
||||
applyCount++
|
||||
}
|
||||
|
||||
return ruleResponse(v.rule, response.Validation, "", response.RuleStatusPass), applyCount
|
||||
return ruleResponse(*v.rule, response.Validation, "", response.RuleStatusPass, nil), applyCount
|
||||
}
|
||||
|
||||
func addElementToContext(ctx *PolicyContext, e interface{}, elementIndex int, elementScope bool) error {
|
||||
|
@ -366,10 +366,10 @@ func (v *validator) validateDeny() *response.RuleResponse {
|
|||
|
||||
deny := variables.EvaluateConditions(v.log, v.ctx.JSONContext, denyConditions)
|
||||
if deny {
|
||||
return ruleResponse(v.rule, response.Validation, v.getDenyMessage(deny), response.RuleStatusFail)
|
||||
return ruleResponse(*v.rule, response.Validation, v.getDenyMessage(deny), response.RuleStatusFail, nil)
|
||||
}
|
||||
|
||||
return ruleResponse(v.rule, response.Validation, v.getDenyMessage(deny), response.RuleStatusPass)
|
||||
return ruleResponse(*v.rule, response.Validation, v.getDenyMessage(deny), response.RuleStatusPass, nil)
|
||||
}
|
||||
|
||||
func (v *validator) getDenyMessage(deny bool) string {
|
||||
|
@ -473,22 +473,22 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *respon
|
|||
v.log.V(3).Info("validation error", "path", pe.Path, "error", err.Error())
|
||||
|
||||
if pe.Skip {
|
||||
return ruleResponse(v.rule, response.Validation, pe.Error(), response.RuleStatusSkip)
|
||||
return ruleResponse(*v.rule, response.Validation, pe.Error(), response.RuleStatusSkip, nil)
|
||||
}
|
||||
|
||||
if pe.Path == "" {
|
||||
return ruleResponse(v.rule, response.Validation, v.buildErrorMessage(err, ""), response.RuleStatusError)
|
||||
return ruleResponse(*v.rule, response.Validation, v.buildErrorMessage(err, ""), response.RuleStatusError, nil)
|
||||
}
|
||||
|
||||
return ruleResponse(v.rule, response.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusFail)
|
||||
return ruleResponse(*v.rule, response.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusFail, nil)
|
||||
}
|
||||
|
||||
return ruleResponse(v.rule, response.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusError)
|
||||
return ruleResponse(*v.rule, response.Validation, v.buildErrorMessage(err, pe.Path), response.RuleStatusError, nil)
|
||||
}
|
||||
|
||||
v.log.V(4).Info("successfully processed rule")
|
||||
msg := fmt.Sprintf("validation rule '%s' passed.", v.rule.Name)
|
||||
return ruleResponse(v.rule, response.Validation, msg, response.RuleStatusPass)
|
||||
return ruleResponse(*v.rule, response.Validation, msg, response.RuleStatusPass, nil)
|
||||
}
|
||||
|
||||
if v.anyPattern != nil {
|
||||
|
@ -498,14 +498,14 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *respon
|
|||
anyPatterns, err := deserializeAnyPattern(v.anyPattern)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to deserialize anyPattern, expected type array: %v", err)
|
||||
return ruleResponse(v.rule, response.Validation, msg, response.RuleStatusError)
|
||||
return ruleResponse(*v.rule, response.Validation, msg, response.RuleStatusError, nil)
|
||||
}
|
||||
|
||||
for idx, pattern := range anyPatterns {
|
||||
err := validate.MatchPattern(v.log, resource.Object, pattern)
|
||||
if err == nil {
|
||||
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
|
||||
return ruleResponse(v.rule, response.Validation, msg, response.RuleStatusPass)
|
||||
return ruleResponse(*v.rule, response.Validation, msg, response.RuleStatusPass, nil)
|
||||
}
|
||||
|
||||
if pe, ok := err.(*validate.PatternError); ok {
|
||||
|
@ -529,11 +529,11 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *respon
|
|||
|
||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' failed. %s", v.rule.Name, errorStr))
|
||||
msg := buildAnyPatternErrorMessage(v.rule, errorStr)
|
||||
return ruleResponse(v.rule, response.Validation, msg, response.RuleStatusFail)
|
||||
return ruleResponse(*v.rule, response.Validation, msg, response.RuleStatusFail, nil)
|
||||
}
|
||||
}
|
||||
|
||||
return ruleResponse(v.rule, response.Validation, v.rule.Validation.Message, response.RuleStatusPass)
|
||||
return ruleResponse(*v.rule, response.Validation, v.rule.Validation.Message, response.RuleStatusPass, nil)
|
||||
}
|
||||
|
||||
func deserializeAnyPattern(anyPattern apiextensions.JSON) ([]interface{}, error) {
|
||||
|
|
|
@ -6,10 +6,10 @@ import (
|
|||
"testing"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
utils2 "github.com/kyverno/kyverno/pkg/utils"
|
||||
"gotest.tools/assert"
|
||||
|
@ -2110,7 +2110,7 @@ func executeTest(t *testing.T, err error, test testCase) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var userInfo kyverno.RequestInfo
|
||||
var userInfo urkyverno.RequestInfo
|
||||
err = json.Unmarshal(test.userInfo, &userInfo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -5,12 +5,11 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"gotest.tools/assert"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
)
|
||||
|
||||
func Test_variablesub1(t *testing.T) {
|
||||
|
@ -52,7 +51,7 @@ func Test_variablesub1(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
// userInfo
|
||||
userReqInfo := kyverno.RequestInfo{
|
||||
userReqInfo := urkyverno.RequestInfo{
|
||||
AdmissionUserInfo: authenticationv1.UserInfo{
|
||||
Username: "user1",
|
||||
},
|
||||
|
@ -140,7 +139,7 @@ func Test_variablesub_multiple(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
// userInfo
|
||||
userReqInfo := kyverno.RequestInfo{
|
||||
userReqInfo := urkyverno.RequestInfo{
|
||||
AdmissionUserInfo: authenticationv1.UserInfo{
|
||||
Username: "user1",
|
||||
},
|
||||
|
@ -230,7 +229,7 @@ func Test_variablesubstitution(t *testing.T) {
|
|||
|
||||
resultMap := []byte(`{"data":{"rules":[{"apiGroups":[""],"resourceNames":["temp"],"resources":["namespaces"],"verbs":["*"]}]},"name":"ns-owner-user1"}`)
|
||||
// userInfo
|
||||
userReqInfo := kyverno.RequestInfo{
|
||||
userReqInfo := urkyverno.RequestInfo{
|
||||
AdmissionUserInfo: authenticationv1.UserInfo{
|
||||
Username: "user1",
|
||||
},
|
||||
|
|
|
@ -333,7 +333,7 @@ func substituteVariablesIfAny(log logr.Logger, ctx context.EvalInterface, vr Var
|
|||
return data.Element, nil
|
||||
}
|
||||
|
||||
isDeleteRequest := isDeleteRequest(ctx)
|
||||
isDeleteRequest := IsDeleteRequest(ctx)
|
||||
|
||||
vars := RegexVariables.FindAllString(value, -1)
|
||||
for len(vars) > 0 {
|
||||
|
@ -406,7 +406,7 @@ func substituteVariablesIfAny(log logr.Logger, ctx context.EvalInterface, vr Var
|
|||
})
|
||||
}
|
||||
|
||||
func isDeleteRequest(ctx context.EvalInterface) bool {
|
||||
func IsDeleteRequest(ctx context.EvalInterface) bool {
|
||||
if ctx == nil {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -39,7 +39,10 @@ type Generator struct {
|
|||
admissionCtrRecorder record.EventRecorder
|
||||
// events generated at namespaced policy controller to process 'generate' rule
|
||||
genPolicyRecorder record.EventRecorder
|
||||
log logr.Logger
|
||||
// events generated at mutateExisting controller
|
||||
mutateExistingRecorder record.EventRecorder
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
//Interface to generate event
|
||||
|
@ -50,16 +53,17 @@ type Interface interface {
|
|||
//NewEventGenerator to generate a new event controller
|
||||
func NewEventGenerator(client *client.Client, cpInformer kyvernoinformer.ClusterPolicyInformer, pInformer kyvernoinformer.PolicyInformer, log logr.Logger) *Generator {
|
||||
gen := Generator{
|
||||
client: client,
|
||||
cpLister: cpInformer.Lister(),
|
||||
cpSynced: cpInformer.Informer().HasSynced,
|
||||
pLister: pInformer.Lister(),
|
||||
pSynced: pInformer.Informer().HasSynced,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(rateLimiter(), eventWorkQueueName),
|
||||
policyCtrRecorder: initRecorder(client, PolicyController, log),
|
||||
admissionCtrRecorder: initRecorder(client, AdmissionController, log),
|
||||
genPolicyRecorder: initRecorder(client, GeneratePolicyController, log),
|
||||
log: log,
|
||||
client: client,
|
||||
cpLister: cpInformer.Lister(),
|
||||
cpSynced: cpInformer.Informer().HasSynced,
|
||||
pLister: pInformer.Lister(),
|
||||
pSynced: pInformer.Informer().HasSynced,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(rateLimiter(), eventWorkQueueName),
|
||||
policyCtrRecorder: initRecorder(client, PolicyController, log),
|
||||
admissionCtrRecorder: initRecorder(client, AdmissionController, log),
|
||||
genPolicyRecorder: initRecorder(client, GeneratePolicyController, log),
|
||||
mutateExistingRecorder: initRecorder(client, MutateExistingController, log),
|
||||
log: log,
|
||||
}
|
||||
return &gen
|
||||
}
|
||||
|
@ -223,6 +227,8 @@ func (gen *Generator) syncHandler(key Info) error {
|
|||
gen.policyCtrRecorder.Event(robj, eventType, key.Reason, key.Message)
|
||||
case GeneratePolicyController:
|
||||
gen.genPolicyRecorder.Event(robj, eventType, key.Reason, key.Message)
|
||||
case MutateExistingController:
|
||||
gen.mutateExistingRecorder.Event(robj, eventType, key.Reason, key.Message)
|
||||
default:
|
||||
logger.Info("info.source not defined for the request")
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ const (
|
|||
PolicyController
|
||||
// GeneratePolicyController : event generated in generate policyController
|
||||
GeneratePolicyController
|
||||
// MutateExistingController : event generated for mutateExisting policies
|
||||
MutateExistingController
|
||||
)
|
||||
|
||||
func (s Source) String() string {
|
||||
|
@ -17,5 +19,6 @@ func (s Source) String() string {
|
|||
"admission-controller",
|
||||
"policy-controller",
|
||||
"generate-policy-controller",
|
||||
"mutate-existing-controller",
|
||||
}[s]
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ func (o *Controller) useOpenAPIDocument(doc *openapiv2.Document) error {
|
|||
|
||||
gvk, preferredGVK, err := o.getGVKByDefinitionName(definitionName)
|
||||
if err != nil {
|
||||
log.Log.V(3).Info("unable to cache OpenAPISchema", "definitionName", definitionName, "reason", err.Error())
|
||||
log.Log.V(5).Info("unable to cache OpenAPISchema", "definitionName", definitionName, "reason", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,12 @@ import (
|
|||
|
||||
//ContainsUserVariables returns error if variable that does not start from request.object
|
||||
func containsUserVariables(policy kyverno.PolicyInterface, vars [][]string) error {
|
||||
for _, rule := range policy.GetSpec().Rules {
|
||||
if rule.IsMutateExisting() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range vars {
|
||||
if strings.Contains(s[0], "userInfo") {
|
||||
return fmt.Errorf("variable %s is not allowed", s[0])
|
||||
|
|
|
@ -11,12 +11,15 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned/scheme"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
pkgCommon "github.com/kyverno/kyverno/pkg/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
|
@ -24,6 +27,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/policyreport"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -71,6 +75,9 @@ type PolicyController struct {
|
|||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestLister
|
||||
|
||||
// urLister can list/get update request from the shared informer's store
|
||||
urLister urkyvernolister.UpdateRequestLister
|
||||
|
||||
// nsLister can list/get namespaces from the shared informer's store
|
||||
nsLister listerv1.NamespaceLister
|
||||
|
||||
|
@ -86,6 +93,9 @@ type PolicyController struct {
|
|||
// grListerSynced returns true if the generate request store has been synced at least once
|
||||
grListerSynced cache.InformerSynced
|
||||
|
||||
// urListerSynced returns true if the update request store has been synced at least once
|
||||
urListerSynced cache.InformerSynced
|
||||
|
||||
// Resource manager, manages the mapping for already processed resource
|
||||
rm resourceManager
|
||||
|
||||
|
@ -112,6 +122,7 @@ func NewPolicyController(
|
|||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
npInformer kyvernoinformer.PolicyInformer,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urkyvernoinformer.UpdateRequestInformer,
|
||||
configHandler config.Interface,
|
||||
eventGen event.Interface,
|
||||
prGenerator policyreport.GeneratorInterface,
|
||||
|
@ -152,12 +163,14 @@ func NewPolicyController(
|
|||
|
||||
pc.nsLister = namespaces.Lister()
|
||||
pc.grLister = grInformer.Lister()
|
||||
pc.urLister = urInformer.Lister()
|
||||
|
||||
pc.pListerSynced = pInformer.Informer().HasSynced
|
||||
pc.npListerSynced = npInformer.Informer().HasSynced
|
||||
|
||||
pc.nsListerSynced = namespaces.Informer().HasSynced
|
||||
pc.grListerSynced = grInformer.Informer().HasSynced
|
||||
pc.urListerSynced = urInformer.Informer().HasSynced
|
||||
|
||||
// resource manager
|
||||
// rebuild after 300 seconds/ 5 mins
|
||||
|
@ -415,7 +428,7 @@ func (pc *PolicyController) Run(workers int, reconcileCh <-chan bool, stopCh <-c
|
|||
logger.Info("starting")
|
||||
defer logger.Info("shutting down")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.npListerSynced, pc.nsListerSynced, pc.grListerSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.npListerSynced, pc.nsListerSynced, pc.grListerSynced, pc.urListerSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
@ -486,22 +499,22 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
logger.V(4).Info("finished syncing policy", "key", key, "processingTime", time.Since(startTime).String())
|
||||
}()
|
||||
|
||||
grList, err := pc.grLister.List(labels.Everything())
|
||||
urList, err := pc.urLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to list generate request")
|
||||
logger.Error(err, "failed to list update request")
|
||||
}
|
||||
|
||||
policy, err := pc.getPolicy(key)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
deleteGR(pc.kyvernoClient, key, grList, logger)
|
||||
deleteGR(pc.kyvernoClient, key, urList, logger)
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
updateGR(pc.kyvernoClient, policy.GetName(), grList, logger)
|
||||
pc.updateUR(policy, urList)
|
||||
pc.processExistingResources(policy)
|
||||
return nil
|
||||
}
|
||||
|
@ -520,18 +533,113 @@ func (pc *PolicyController) getPolicy(key string) (policy kyverno.PolicyInterfac
|
|||
return
|
||||
}
|
||||
|
||||
func deleteGR(kyvernoClient *kyvernoclient.Clientset, policyKey string, grList []*kyverno.GenerateRequest, logger logr.Logger) {
|
||||
func (pc *PolicyController) updateUR(policy kyverno.PolicyInterface, urList []*urkyverno.UpdateRequest) {
|
||||
if urList == nil {
|
||||
for _, rule := range policy.GetSpec().Rules {
|
||||
if !rule.IsMutateExisting() {
|
||||
continue
|
||||
}
|
||||
|
||||
triggers := getTriggers(rule)
|
||||
for _, trigger := range triggers {
|
||||
ur := newUR(policy, trigger)
|
||||
new, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), ur, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
pc.log.Error(err, "failed to create new UR for mutateExisting rule on policy update", "policy", policy.GetName(), "rule", rule.Name,
|
||||
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.APIVersion, trigger.Kind, trigger.Namespace, trigger.Name))
|
||||
} else {
|
||||
pc.log.V(4).Info("successfully created UR for mutateExisting on policy update", "policy", policy.GetName(), "rule", rule.Name,
|
||||
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.APIVersion, trigger.Kind, trigger.Namespace, trigger.Name))
|
||||
}
|
||||
|
||||
new.Status.State = urkyverno.Pending
|
||||
if _, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
|
||||
pc.log.Error(err, "failed to set UpdateRequest state to Pending")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
updateUR(pc.kyvernoClient, policy.GetName(), urList, pc.log.WithName("updateUR"))
|
||||
|
||||
}
|
||||
|
||||
func getTriggers(rule kyverno.Rule) []*kyverno.ResourceSpec {
|
||||
var specs []*kyverno.ResourceSpec
|
||||
|
||||
triggers := getTrigger(rule.MatchResources.ResourceDescription)
|
||||
specs = append(specs, triggers...)
|
||||
|
||||
for _, any := range rule.MatchResources.Any {
|
||||
triggers := getTrigger(any.ResourceDescription)
|
||||
specs = append(specs, triggers...)
|
||||
}
|
||||
|
||||
triggers = []*kyverno.ResourceSpec{}
|
||||
for _, all := range rule.MatchResources.All {
|
||||
triggers = getTrigger(all.ResourceDescription)
|
||||
}
|
||||
|
||||
subset := make(map[*kyverno.ResourceSpec]int, len(triggers))
|
||||
for _, trigger := range triggers {
|
||||
c := subset[trigger]
|
||||
subset[trigger] = c + 1
|
||||
}
|
||||
|
||||
for k, v := range subset {
|
||||
if v == len(rule.MatchResources.All) {
|
||||
specs = append(specs, k)
|
||||
}
|
||||
}
|
||||
return specs
|
||||
}
|
||||
|
||||
func getTrigger(rd kyverno.ResourceDescription) []*kyverno.ResourceSpec {
|
||||
if len(rd.Names) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var specs []*kyverno.ResourceSpec
|
||||
|
||||
for _, k := range rd.Kinds {
|
||||
apiVersion, kind := kubeutils.GetKindFromGVK(k)
|
||||
if kind == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ns := range rd.Namespaces {
|
||||
for _, name := range rd.Names {
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
spec := &kyverno.ResourceSpec{
|
||||
APIVersion: apiVersion,
|
||||
Kind: kind,
|
||||
Namespace: ns,
|
||||
Name: name,
|
||||
}
|
||||
specs = append(specs, spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return specs
|
||||
}
|
||||
|
||||
func deleteGR(kyvernoClient *kyvernoclient.Clientset, policyKey string, grList []*urkyverno.UpdateRequest, logger logr.Logger) {
|
||||
for _, v := range grList {
|
||||
if policyKey == v.Spec.Policy {
|
||||
err := kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Delete(context.TODO(), v.GetName(), metav1.DeleteOptions{})
|
||||
err := kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Delete(context.TODO(), v.GetName(), metav1.DeleteOptions{})
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
logger.Error(err, "failed to delete gr", "name", v.GetName())
|
||||
logger.Error(err, "failed to delete ur", "name", v.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateGR(kyvernoClient *kyvernoclient.Clientset, policyKey string, grList []*kyverno.GenerateRequest, logger logr.Logger) {
|
||||
func updateUR(kyvernoClient *kyvernoclient.Clientset, policyKey string, grList []*urkyverno.UpdateRequest, logger logr.Logger) {
|
||||
for _, gr := range grList {
|
||||
if policyKey == gr.Spec.Policy {
|
||||
grLabels := gr.Labels
|
||||
|
@ -546,7 +654,7 @@ func updateGR(kyvernoClient *kyvernoclient.Clientset, policyKey string, grList [
|
|||
grLabels["policy-update"] = fmt.Sprintf("revision-count-%d", nBig.Int64())
|
||||
gr.SetLabels(grLabels)
|
||||
|
||||
_, err = kyvernoClient.KyvernoV1().GenerateRequests(config.KyvernoNamespace).Update(context.TODO(), gr, metav1.UpdateOptions{})
|
||||
_, err = kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), gr, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update gr", "name", gr.GetName())
|
||||
}
|
||||
|
@ -592,3 +700,42 @@ func missingAutoGenRules(policy kyverno.PolicyInterface, log logr.Logger) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func newUR(policy kyverno.PolicyInterface, target *kyverno.ResourceSpec) *urkyverno.UpdateRequest {
|
||||
var policyNameNamespaceKey string
|
||||
|
||||
if policy.GetKind() == "Policy" {
|
||||
policyNameNamespaceKey = policy.GetNamespace() + "/" + policy.GetName()
|
||||
} else {
|
||||
policyNameNamespaceKey = policy.GetName()
|
||||
}
|
||||
|
||||
label := map[string]string{
|
||||
"mutate.updaterequest.kyverno.io/policy-name": policyNameNamespaceKey,
|
||||
"mutate.updaterequest.kyverno.io/trigger-name": target.Name,
|
||||
"mutate.updaterequest.kyverno.io/trigger-namespace": target.Namespace,
|
||||
"mutate.updaterequest.kyverno.io/trigger-kind": target.Kind,
|
||||
}
|
||||
|
||||
if target.APIVersion != "" {
|
||||
label["mutate.updaterequest.kyverno.io/trigger-apiversion"] = target.APIVersion
|
||||
}
|
||||
|
||||
return &urkyverno.UpdateRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "ur-",
|
||||
Namespace: config.KyvernoNamespace,
|
||||
Labels: label,
|
||||
},
|
||||
Spec: urkyverno.UpdateRequestSpec{
|
||||
Type: urkyverno.Mutate,
|
||||
Policy: policyNameNamespaceKey,
|
||||
Resource: kyverno.ResourceSpec{
|
||||
Kind: target.Kind,
|
||||
Namespace: target.Namespace,
|
||||
Name: target.Name,
|
||||
APIVersion: target.APIVersion,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
type Interface interface {
|
||||
// GetPolicies returns all policies that apply to a namespace, including cluster-wide policies
|
||||
// If the namespace is empty, only cluster-wide policies are returned
|
||||
GetPolicies(PolicyType, string, string) []kyverno.PolicyInterface
|
||||
GetPolicies(pType PolicyType, kind string, namespace string) []kyverno.PolicyInterface
|
||||
|
||||
// add adds a policy to the cache
|
||||
add(kyverno.PolicyInterface)
|
||||
|
|
|
@ -191,7 +191,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
JSONContext: context.NewContext(),
|
||||
}
|
||||
|
||||
er = engine.Generate(policyContext)
|
||||
er = engine.ApplyBackgroundChecks(policyContext)
|
||||
t.Log(("---Generation---"))
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Generation.PolicyResponse)
|
||||
// Expected generate resource will be in same namespaces as resource
|
||||
|
|
142
pkg/utils/annotations.go
Normal file
142
pkg/utils/annotations.go
Normal file
|
@ -0,0 +1,142 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
yamlv2 "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
PolicyAnnotation = "policies.kyverno.io/last-applied-patches"
|
||||
policyAnnotation = "policies.kyverno.io~1last-applied-patches"
|
||||
oldAnnotation = "policies.kyverno.io~1patches"
|
||||
)
|
||||
|
||||
type RulePatch struct {
|
||||
RuleName string `json:"rulename"`
|
||||
Op string `json:"op"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
var OperationToPastTense = map[string]string{
|
||||
"add": "added",
|
||||
"remove": "removed",
|
||||
"replace": "replaced",
|
||||
"move": "moved",
|
||||
"copy": "copied",
|
||||
"test": "tested",
|
||||
}
|
||||
|
||||
func GenerateAnnotationPatches(engineResponses []*response.EngineResponse, log logr.Logger) [][]byte {
|
||||
var annotations map[string]string
|
||||
var patchBytes [][]byte
|
||||
for _, er := range engineResponses {
|
||||
if ann := er.PatchedResource.GetAnnotations(); ann != nil {
|
||||
annotations = ann
|
||||
break
|
||||
}
|
||||
}
|
||||
if annotations == nil {
|
||||
annotations = make(map[string]string)
|
||||
}
|
||||
var patchResponse jsonutils.Patch
|
||||
value := annotationFromEngineResponses(engineResponses, log)
|
||||
if value == nil {
|
||||
// no patches or error while processing patches
|
||||
return nil
|
||||
}
|
||||
if _, ok := annotations[strings.ReplaceAll(policyAnnotation, "~1", "/")]; ok {
|
||||
// create update patch string
|
||||
if _, ok := annotations["policies.kyverno.io/patches"]; ok {
|
||||
patchResponse = jsonutils.NewPatch("/metadata/annotations/"+oldAnnotation, "remove", nil)
|
||||
delete(annotations, "policies.kyverno.io/patches")
|
||||
patchByte, _ := json.Marshal(patchResponse)
|
||||
patchBytes = append(patchBytes, patchByte)
|
||||
}
|
||||
patchResponse = jsonutils.NewPatch("/metadata/annotations/"+policyAnnotation, "replace", string(value))
|
||||
patchByte, _ := json.Marshal(patchResponse)
|
||||
patchBytes = append(patchBytes, patchByte)
|
||||
} else {
|
||||
// mutate rule has annotation patches
|
||||
if len(annotations) > 0 {
|
||||
if _, ok := annotations["policies.kyverno.io/patches"]; ok {
|
||||
patchResponse = jsonutils.NewPatch("/metadata/annotations/"+oldAnnotation, "remove", nil)
|
||||
delete(annotations, "policies.kyverno.io/patches")
|
||||
patchByte, _ := json.Marshal(patchResponse)
|
||||
patchBytes = append(patchBytes, patchByte)
|
||||
}
|
||||
patchResponse = jsonutils.NewPatch("/metadata/annotations/"+policyAnnotation, "add", string(value))
|
||||
patchByte, _ := json.Marshal(patchResponse)
|
||||
patchBytes = append(patchBytes, patchByte)
|
||||
} else {
|
||||
// insert 'policies.kyverno.patches' entry in annotation map
|
||||
annotations[strings.ReplaceAll(policyAnnotation, "~1", "/")] = string(value)
|
||||
patchResponse = jsonutils.NewPatch("/metadata/annotations", "add", annotations)
|
||||
patchByte, _ := json.Marshal(patchResponse)
|
||||
patchBytes = append(patchBytes, patchByte)
|
||||
}
|
||||
}
|
||||
for _, patchByte := range patchBytes {
|
||||
err := jsonutils.CheckPatch(patchByte)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to build JSON patch for annotation", "patch", string(patchByte))
|
||||
}
|
||||
}
|
||||
return patchBytes
|
||||
}
|
||||
|
||||
func annotationFromEngineResponses(engineResponses []*response.EngineResponse, log logr.Logger) []byte {
|
||||
var annotationContent = make(map[string]string)
|
||||
for _, engineResponse := range engineResponses {
|
||||
if !engineResponse.IsSuccessful() {
|
||||
log.V(3).Info("skip building annotation; policy failed to apply", "policy", engineResponse.PolicyResponse.Policy.Name)
|
||||
continue
|
||||
}
|
||||
rulePatches := annotationFromPolicyResponse(engineResponse.PolicyResponse, log)
|
||||
if rulePatches == nil {
|
||||
continue
|
||||
}
|
||||
policyName := engineResponse.PolicyResponse.Policy.Name
|
||||
for _, rulePatch := range rulePatches {
|
||||
annotationContent[rulePatch.RuleName+"."+policyName+".kyverno.io"] = OperationToPastTense[rulePatch.Op] + " " + rulePatch.Path
|
||||
}
|
||||
}
|
||||
|
||||
// return nil if there's no patches
|
||||
// otherwise result = null, len(result) = 4
|
||||
if len(annotationContent) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result, _ := yamlv2.Marshal(annotationContent)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func annotationFromPolicyResponse(policyResponse response.PolicyResponse, log logr.Logger) []RulePatch {
|
||||
var RulePatches []RulePatch
|
||||
for _, ruleInfo := range policyResponse.Rules {
|
||||
for _, patch := range ruleInfo.Patches {
|
||||
var patchmap map[string]interface{}
|
||||
if err := json.Unmarshal(patch, &patchmap); err != nil {
|
||||
log.Error(err, "Failed to parse JSON patch bytes")
|
||||
continue
|
||||
}
|
||||
rp := RulePatch{
|
||||
RuleName: ruleInfo.Name,
|
||||
Op: patchmap["op"].(string),
|
||||
Path: patchmap["path"].(string),
|
||||
}
|
||||
RulePatches = append(RulePatches, rp)
|
||||
log.V(4).Info("annotation value prepared", "patches", RulePatches)
|
||||
}
|
||||
}
|
||||
if len(RulePatches) == 0 {
|
||||
return nil
|
||||
}
|
||||
return RulePatches
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package webhooks
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -43,7 +43,7 @@ func newEngineResponse(policy, rule string, patchesStr []string, status response
|
|||
func Test_empty_annotation(t *testing.T) {
|
||||
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, response.RuleStatusPass, nil)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := GenerateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
expectedPatches := `{"path":"/metadata/annotations","op":"add","value":{"policies.kyverno.io/last-applied-patches":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}}`
|
||||
assert.Equal(t, string(annPatches[0]), expectedPatches)
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ func Test_exist_annotation(t *testing.T) {
|
|||
}
|
||||
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, response.RuleStatusPass, annotation)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := GenerateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
expectedPatches := `{"path":"/metadata/annotations/policies.kyverno.io~1last-applied-patches","op":"add","value":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}`
|
||||
assert.Equal(t, string(annPatches[0]), expectedPatches)
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func Test_exist_kyverno_annotation(t *testing.T) {
|
|||
}
|
||||
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, response.RuleStatusPass, annotation)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := GenerateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
expectedPatches := `{"path":"/metadata/annotations/policies.kyverno.io~1last-applied-patches","op":"add","value":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}`
|
||||
assert.Equal(t, string(annPatches[0]), expectedPatches)
|
||||
}
|
||||
|
@ -75,10 +75,10 @@ func Test_annotation_nil_patch(t *testing.T) {
|
|||
"policies.kyverno.patches": "old-annotation",
|
||||
}
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", nil, response.RuleStatusPass, annotation)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := GenerateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
assert.Assert(t, annPatches == nil)
|
||||
engineResponseNew := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{""}, response.RuleStatusPass, annotation)
|
||||
annPatchesNew := generateAnnotationPatches([]*response.EngineResponse{engineResponseNew}, log.Log)
|
||||
annPatchesNew := GenerateAnnotationPatches([]*response.EngineResponse{engineResponseNew}, log.Log)
|
||||
assert.Assert(t, annPatchesNew == nil)
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ func Test_annotation_failed_Patch(t *testing.T) {
|
|||
"policies.kyverno.patches": "old-annotation",
|
||||
}
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", nil, response.RuleStatusFail, annotation)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := GenerateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
assert.Assert(t, annPatches == nil)
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ func Test_exist_patches(t *testing.T) {
|
|||
}
|
||||
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, response.RuleStatusPass, annotation)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := GenerateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
expectedPatches1 := `{"path":"/metadata/annotations/policies.kyverno.io~1patches","op":"remove"}`
|
||||
expectedPatches2 := `{"path":"/metadata/annotations/policies.kyverno.io~1last-applied-patches","op":"add","value":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}`
|
||||
assert.Equal(t, string(annPatches[0]), expectedPatches1)
|
|
@ -108,7 +108,8 @@ func (m *certManager) GetTLSPemPair() (*ktls.PemPair, error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
f := common.RetryFunc(time.Second, time.Minute, retryReadTLS, m.log.WithName("GetTLSPemPair/Retry"))
|
||||
msg := "failed to read TLS pair"
|
||||
f := common.RetryFunc(time.Second, time.Minute, retryReadTLS, msg, m.log.WithName("GetTLSPemPair/Retry"))
|
||||
err = f()
|
||||
|
||||
return tls, err
|
||||
|
|
|
@ -434,7 +434,7 @@ func (m *webhookConfigManager) buildWebhooks(namespace string) (res []*webhook,
|
|||
|
||||
for _, p := range policies {
|
||||
spec := p.GetSpec()
|
||||
if spec.HasValidate() || spec.HasGenerate() {
|
||||
if spec.HasValidate() || spec.HasGenerate() || spec.HasMutate() {
|
||||
if spec.GetFailurePolicy() == kyverno.Ignore {
|
||||
m.mergeWebhook(validateIgnore, p, true)
|
||||
} else {
|
||||
|
@ -525,7 +525,8 @@ func (m *webhookConfigManager) getWebhook(webhookKind, webhookName string) (reso
|
|||
return err
|
||||
}
|
||||
|
||||
retryGetWebhook := common.RetryFunc(time.Second, 10*time.Second, get, m.log)
|
||||
msg := "getWebhook: unable to get webhook configuration"
|
||||
retryGetWebhook := common.RetryFunc(time.Second, 10*time.Second, get, msg, m.log)
|
||||
if err := retryGetWebhook(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -740,7 +741,8 @@ func (m *webhookConfigManager) mergeWebhook(dst *webhook, policy kyverno.PolicyI
|
|||
}
|
||||
|
||||
if (updateValidate && rule.HasValidate()) ||
|
||||
(!updateValidate && rule.HasMutate()) ||
|
||||
(updateValidate && rule.HasMutate() && rule.IsMutateExisting()) ||
|
||||
(!updateValidate && rule.HasMutate()) && !rule.IsMutateExisting() ||
|
||||
(!updateValidate && rule.HasVerifyImages()) {
|
||||
matchedGVK = append(matchedGVK, rule.MatchResources.GetKinds()...)
|
||||
}
|
||||
|
@ -809,9 +811,15 @@ func (m *webhookConfigManager) mergeWebhook(dst *webhook, policy kyverno.PolicyI
|
|||
rsrcs = append(rsrcs, "pods/ephemeralcontainers")
|
||||
}
|
||||
|
||||
dst.rule[apiGroups] = removeDuplicates(groups)
|
||||
dst.rule[apiVersions] = removeDuplicates(versions)
|
||||
dst.rule[resources] = removeDuplicates(rsrcs)
|
||||
if len(groups) > 0 {
|
||||
dst.rule[apiGroups] = removeDuplicates(groups)
|
||||
}
|
||||
if len(versions) > 0 {
|
||||
dst.rule[apiVersions] = removeDuplicates(versions)
|
||||
}
|
||||
if len(rsrcs) > 0 {
|
||||
dst.rule[resources] = removeDuplicates(rsrcs)
|
||||
}
|
||||
|
||||
spec := policy.GetSpec()
|
||||
if spec.WebhookTimeoutSeconds != nil {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
|
@ -157,7 +158,7 @@ func excludeKyvernoResources(kind string) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func newVariablesContext(request *admissionv1.AdmissionRequest, userRequestInfo *kyverno.RequestInfo) (enginectx.Interface, error) {
|
||||
func newVariablesContext(request *admissionv1.AdmissionRequest, userRequestInfo *urkyverno.RequestInfo) (enginectx.Interface, error) {
|
||||
ctx := enginectx.NewContext()
|
||||
if err := ctx.AddRequest(request); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to load incoming request in context")
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/gardener/controller-manager-library/pkg/logger"
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
gencommon "github.com/kyverno/kyverno/pkg/background/common"
|
||||
gen "github.com/kyverno/kyverno/pkg/background/generate"
|
||||
|
@ -18,38 +18,24 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/config"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks/generate"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks/updaterequest"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func (ws *WebhookServer) applyGeneratePolicies(request *admissionv1.AdmissionRequest, policyContext *engine.PolicyContext, policies []kyverno.PolicyInterface, ts int64, logger logr.Logger) {
|
||||
admissionReviewCompletionLatencyChannel := make(chan int64, 1)
|
||||
generateEngineResponsesSenderForAdmissionReviewDurationMetric := make(chan []*response.EngineResponse, 1)
|
||||
generateEngineResponsesSenderForAdmissionRequestsCountMetric := make(chan []*response.EngineResponse, 1)
|
||||
|
||||
go ws.handleGenerate(request, policies, policyContext.JSONContext, policyContext.AdmissionInfo, ws.configHandler, ts, &admissionReviewCompletionLatencyChannel, &generateEngineResponsesSenderForAdmissionReviewDurationMetric, &generateEngineResponsesSenderForAdmissionRequestsCountMetric)
|
||||
go ws.registerAdmissionReviewDurationMetricGenerate(logger, string(request.Operation), &admissionReviewCompletionLatencyChannel, &generateEngineResponsesSenderForAdmissionReviewDurationMetric)
|
||||
go ws.registerAdmissionRequestsMetricGenerate(logger, string(request.Operation), &generateEngineResponsesSenderForAdmissionRequestsCountMetric)
|
||||
}
|
||||
|
||||
//handleGenerate handles admission-requests for policies with generate rules
|
||||
func (ws *WebhookServer) handleGenerate(
|
||||
request *admissionv1.AdmissionRequest,
|
||||
policies []kyverno.PolicyInterface,
|
||||
ctx context.Interface,
|
||||
userRequestInfo kyverno.RequestInfo,
|
||||
dynamicConfig config.Interface,
|
||||
policyContext *engine.PolicyContext,
|
||||
admissionRequestTimestamp int64,
|
||||
latencySender *chan int64,
|
||||
generateEngineResponsesSenderForAdmissionReviewDurationMetric *chan []*response.EngineResponse,
|
||||
|
@ -57,33 +43,17 @@ func (ws *WebhookServer) handleGenerate(
|
|||
) {
|
||||
|
||||
logger := ws.log.WithValues("action", "generation", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation, "gvk", request.Kind.String())
|
||||
logger.V(6).Info("generate request")
|
||||
logger.V(6).Info("update request")
|
||||
|
||||
var engineResponses []*response.EngineResponse
|
||||
if (request.Operation == admissionv1.Create || request.Operation == admissionv1.Update) && len(policies) != 0 {
|
||||
// convert RAW to unstructured
|
||||
new, old, err := kyvernoutils.ExtractResources(nil, request)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to extract resource")
|
||||
}
|
||||
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: new,
|
||||
OldResource: old,
|
||||
AdmissionInfo: userRequestInfo,
|
||||
ExcludeGroupRole: dynamicConfig.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
||||
JSONContext: ctx,
|
||||
Client: ws.client,
|
||||
}
|
||||
|
||||
for _, policy := range policies {
|
||||
var rules []response.RuleResponse
|
||||
policyContext.Policy = policy
|
||||
if request.Kind.Kind != "Namespace" && request.Namespace != "" {
|
||||
policyContext.NamespaceLabels = common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, ws.nsLister, logger)
|
||||
}
|
||||
engineResponse := engine.Generate(policyContext)
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if rule.Status != response.RuleStatusPass {
|
||||
ws.deleteGR(logger, engineResponse)
|
||||
|
@ -105,11 +75,10 @@ func (ws *WebhookServer) handleGenerate(
|
|||
go ws.registerPolicyExecutionDurationMetricGenerate(logger, string(request.Operation), policy, *engineResponse)
|
||||
}
|
||||
|
||||
// Adds Generate Request to a channel(queue size 1000) to generators
|
||||
if failedResponse := applyGenerateRequest(request, ws.grGenerator, userRequestInfo, request.Operation, engineResponses...); err != nil {
|
||||
if failedResponse := applyGenerateRequest(request, urkyverno.Generate, ws.grGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
// report failure event
|
||||
for _, failedGR := range failedResponse {
|
||||
events := failedEvents(fmt.Errorf("failed to create Generate Request: %v", failedGR.err), failedGR.gr, new)
|
||||
events := failedEvents(fmt.Errorf("failed to create Generate Request: %v", failedGR.err), failedGR.gr, policyContext.NewResource)
|
||||
ws.eventGen.Add(events...)
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +135,7 @@ func (ws *WebhookServer) handleUpdateGenerateSourceResource(resLabels map[string
|
|||
"generate.kyverno.io/policy-name": policyName,
|
||||
}))
|
||||
|
||||
grList, err := ws.grLister.List(selector)
|
||||
grList, err := ws.urLister.List(selector)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request for the resource", "label", "generate.kyverno.io/policy-name")
|
||||
return
|
||||
|
@ -182,7 +151,7 @@ func (ws *WebhookServer) handleUpdateGenerateSourceResource(resLabels map[string
|
|||
|
||||
// updateAnnotationInGR - function used to update GR annotation
|
||||
// updating GR will trigger reprocessing of GR and recreation/updation of generated resource
|
||||
func (ws *WebhookServer) updateAnnotationInGR(gr *kyverno.GenerateRequest, logger logr.Logger) {
|
||||
func (ws *WebhookServer) updateAnnotationInGR(gr *urkyverno.UpdateRequest, logger logr.Logger) {
|
||||
grAnnotations := gr.Annotations
|
||||
if len(grAnnotations) == 0 {
|
||||
grAnnotations = make(map[string]string)
|
||||
|
@ -258,7 +227,7 @@ func (ws *WebhookServer) handleUpdateGenerateTargetResource(request *admissionv1
|
|||
|
||||
if enqueueBool {
|
||||
grName := resLabels["policy.kyverno.io/gr-name"]
|
||||
gr, err := ws.grLister.Get(grName)
|
||||
gr, err := ws.urLister.Get(grName)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request", "name", grName)
|
||||
return
|
||||
|
@ -363,7 +332,7 @@ func stripNonPolicyFields(obj, newRes map[string]interface{}, logger logr.Logger
|
|||
return obj, newRes
|
||||
}
|
||||
|
||||
//HandleDelete handles admission-requests for delete
|
||||
//HandleDelete handles DELETE admission-requests for generate policies
|
||||
func (ws *WebhookServer) handleDelete(request *admissionv1.AdmissionRequest) {
|
||||
logger := ws.log.WithValues("action", "generation", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation, "gvk", request.Kind.String())
|
||||
resource, err := enginutils.ConvertToUnstructured(request.OldObject.Raw)
|
||||
|
@ -374,11 +343,15 @@ func (ws *WebhookServer) handleDelete(request *admissionv1.AdmissionRequest) {
|
|||
resLabels := resource.GetLabels()
|
||||
if resLabels["app.kubernetes.io/managed-by"] == "kyverno" && request.Operation == admissionv1.Delete {
|
||||
grName := resLabels["policy.kyverno.io/gr-name"]
|
||||
gr, err := ws.grLister.Get(grName)
|
||||
gr, err := ws.urLister.Get(grName)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get generate request", "name", grName)
|
||||
return
|
||||
}
|
||||
|
||||
if gr.Spec.Type == urkyverno.Mutate {
|
||||
return
|
||||
}
|
||||
ws.updateAnnotationInGR(gr, logger)
|
||||
}
|
||||
}
|
||||
|
@ -406,20 +379,20 @@ func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse *response.E
|
|||
}
|
||||
}
|
||||
|
||||
func applyGenerateRequest(request *admissionv1.AdmissionRequest, gnGenerator generate.GenerateRequests, userRequestInfo kyverno.RequestInfo,
|
||||
func applyGenerateRequest(request *admissionv1.AdmissionRequest, ruleType urkyverno.RequestType, gnGenerator updaterequest.Interface, userRequestInfo urkyverno.RequestInfo,
|
||||
action admissionv1.Operation, engineResponses ...*response.EngineResponse) (failedGenerateRequest []generateRequestResponse) {
|
||||
|
||||
requestBytes, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
logger.Error(err, "error loading request into context")
|
||||
}
|
||||
admissionRequestInfo := kyverno.AdmissionRequestInfoObject{
|
||||
admissionRequestInfo := urkyverno.AdmissionRequestInfoObject{
|
||||
AdmissionRequest: string(requestBytes),
|
||||
Operation: action,
|
||||
}
|
||||
|
||||
for _, er := range engineResponses {
|
||||
gr := transform(admissionRequestInfo, userRequestInfo, er)
|
||||
gr := transform(admissionRequestInfo, userRequestInfo, er, ruleType)
|
||||
if err := gnGenerator.Apply(gr, action); err != nil {
|
||||
failedGenerateRequest = append(failedGenerateRequest, generateRequestResponse{gr: gr, err: err})
|
||||
}
|
||||
|
@ -428,15 +401,16 @@ func applyGenerateRequest(request *admissionv1.AdmissionRequest, gnGenerator gen
|
|||
return
|
||||
}
|
||||
|
||||
func transform(admissionRequestInfo kyverno.AdmissionRequestInfoObject, userRequestInfo kyverno.RequestInfo, er *response.EngineResponse) kyverno.GenerateRequestSpec {
|
||||
func transform(admissionRequestInfo urkyverno.AdmissionRequestInfoObject, userRequestInfo urkyverno.RequestInfo, er *response.EngineResponse, ruleType urkyverno.RequestType) urkyverno.UpdateRequestSpec {
|
||||
var PolicyNameNamespaceKey string
|
||||
if er.PolicyResponse.Policy.Namespace != "" {
|
||||
PolicyNameNamespaceKey = fmt.Sprintf("%s", er.PolicyResponse.Policy.Namespace+"/"+er.PolicyResponse.Policy.Name)
|
||||
PolicyNameNamespaceKey = er.PolicyResponse.Policy.Namespace + "/" + er.PolicyResponse.Policy.Name
|
||||
} else {
|
||||
PolicyNameNamespaceKey = er.PolicyResponse.Policy.Name
|
||||
}
|
||||
|
||||
gr := kyverno.GenerateRequestSpec{
|
||||
gr := urkyverno.UpdateRequestSpec{
|
||||
Type: ruleType,
|
||||
Policy: PolicyNameNamespaceKey,
|
||||
Resource: kyverno.ResourceSpec{
|
||||
Kind: er.PolicyResponse.Resource.Kind,
|
||||
|
@ -444,7 +418,7 @@ func transform(admissionRequestInfo kyverno.AdmissionRequestInfoObject, userRequ
|
|||
Name: er.PolicyResponse.Resource.Name,
|
||||
APIVersion: er.PolicyResponse.Resource.APIVersion,
|
||||
},
|
||||
Context: kyverno.GenerateRequestContext{
|
||||
Context: urkyverno.UpdateRequestSpecContext{
|
||||
UserRequestInfo: userRequestInfo,
|
||||
AdmissionRequestInfo: admissionRequestInfo,
|
||||
},
|
||||
|
@ -454,7 +428,7 @@ func transform(admissionRequestInfo kyverno.AdmissionRequestInfoObject, userRequ
|
|||
}
|
||||
|
||||
type generateRequestResponse struct {
|
||||
gr kyverno.GenerateRequestSpec
|
||||
gr urkyverno.UpdateRequestSpec
|
||||
err error
|
||||
}
|
||||
|
||||
|
@ -466,7 +440,7 @@ func (resp generateRequestResponse) error() string {
|
|||
return resp.err.Error()
|
||||
}
|
||||
|
||||
func failedEvents(err error, gr kyverno.GenerateRequestSpec, resource unstructured.Unstructured) []event.Info {
|
||||
func failedEvents(err error, gr urkyverno.UpdateRequestSpec, resource unstructured.Unstructured) []event.Info {
|
||||
re := event.Info{}
|
||||
re.Kind = resource.GetKind()
|
||||
re.Namespace = resource.GetNamespace()
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
|
@ -56,27 +57,32 @@ func (ws *WebhookServer) admissionHandler(filter bool, inner handlers.AdmissionH
|
|||
if filter {
|
||||
inner = handlers.Filter(ws.configHandler, inner)
|
||||
}
|
||||
return handlers.Monitor(ws.webhookMonitor, handlers.Admission(ws.log, inner))
|
||||
return handlers.Monitor(ws.webhookMonitor, handlers.Admission(ws.log.WithName("handlerFunc"), inner))
|
||||
}
|
||||
|
||||
func (ws *WebhookServer) policyMutation(request *admissionv1.AdmissionRequest) *admissionv1.AdmissionResponse {
|
||||
logger := setupLogger(ws.log, "policy mutation", request)
|
||||
|
||||
policy, oldPolicy, err := admissionutils.GetPolicies(request)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to unmarshal policies from admission request")
|
||||
return admissionutils.ResponseWithMessage(true, fmt.Sprintf("failed to default value, check kyverno controller logs for details: %v", err))
|
||||
}
|
||||
|
||||
if oldPolicy != nil && isStatusUpdate(oldPolicy, policy) {
|
||||
logger.V(4).Info("skip policy mutation on status update")
|
||||
return admissionutils.Response(true)
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
logger.V(3).Info("start policy change mutation")
|
||||
defer logger.V(3).Info("finished policy change mutation", "time", time.Since(startTime).String())
|
||||
|
||||
// Generate JSON Patches for defaults
|
||||
if patches, updateMsgs := policymutation.GenerateJSONPatchesForDefaults(policy, logger); len(patches) != 0 {
|
||||
return admissionutils.ResponseWithMessageAndPatch(true, strings.Join(updateMsgs, "'"), patches)
|
||||
}
|
||||
|
||||
return admissionutils.Response(true)
|
||||
}
|
||||
|
||||
|
@ -88,21 +94,26 @@ func (ws *WebhookServer) policyValidation(request *admissionv1.AdmissionRequest)
|
|||
logger.Error(err, "failed to unmarshal policies from admission request")
|
||||
return admissionutils.ResponseWithMessage(true, fmt.Sprintf("failed to validate policy, check kyverno controller logs for details: %v", err))
|
||||
}
|
||||
|
||||
if oldPolicy != nil && isStatusUpdate(oldPolicy, policy) {
|
||||
logger.V(4).Info("skip policy validation on status update")
|
||||
return admissionutils.Response(true)
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
logger.V(3).Info("start policy change validation")
|
||||
defer logger.V(3).Info("finished policy change validation", "time", time.Since(startTime).String())
|
||||
|
||||
response, err := policyvalidate.Validate(policy, ws.client, false, ws.openAPIController)
|
||||
if err != nil {
|
||||
logger.Error(err, "policy validation errors")
|
||||
return admissionutils.ResponseWithMessage(true, err.Error())
|
||||
}
|
||||
|
||||
if response != nil && len(response.Warnings) != 0 {
|
||||
return response
|
||||
}
|
||||
|
||||
return admissionutils.Response(true)
|
||||
}
|
||||
|
||||
|
@ -112,6 +123,7 @@ func (ws *WebhookServer) resourceMutation(request *admissionv1.AdmissionRequest)
|
|||
if excludeKyvernoResources(request.Kind.Kind) {
|
||||
return admissionutils.ResponseSuccess(true, "")
|
||||
}
|
||||
|
||||
if request.Operation == admissionv1.Delete {
|
||||
resource, err := utils.ConvertResource(request.OldObject.Raw, request.Kind.Group, request.Kind.Version, request.Kind.Kind, request.Namespace)
|
||||
if err == nil {
|
||||
|
@ -120,25 +132,32 @@ func (ws *WebhookServer) resourceMutation(request *admissionv1.AdmissionRequest)
|
|||
logger.Info(fmt.Sprintf("Converting oldObject failed: %v", err))
|
||||
}
|
||||
return admissionutils.ResponseSuccess(true, "")
|
||||
|
||||
}
|
||||
|
||||
logger.V(4).Info("received an admission request in mutating webhook")
|
||||
|
||||
requestTime := time.Now().Unix()
|
||||
mutatePolicies := ws.pCache.GetPolicies(policycache.Mutate, request.Kind.Kind, request.Namespace)
|
||||
verifyImagesPolicies := ws.pCache.GetPolicies(policycache.VerifyImages, request.Kind.Kind, request.Namespace)
|
||||
|
||||
if len(mutatePolicies) == 0 && len(verifyImagesPolicies) == 0 {
|
||||
logger.V(4).Info("no policies matched admission request")
|
||||
return admissionutils.ResponseSuccess(true, "")
|
||||
}
|
||||
|
||||
addRoles := containsRBACInfo(mutatePolicies)
|
||||
policyContext, err := ws.buildPolicyContext(request, addRoles)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to build policy context")
|
||||
return admissionutils.ResponseFailure(false, err.Error())
|
||||
}
|
||||
|
||||
// update container images to a canonical form
|
||||
if err := enginectx.MutateResourceWithImageInfo(request.Object.Raw, policyContext.JSONContext); err != nil {
|
||||
ws.log.Error(err, "failed to patch images info to resource, policies that mutate images may be impacted")
|
||||
}
|
||||
|
||||
mutatePatches := ws.applyMutatePolicies(request, policyContext, mutatePolicies, requestTime, logger)
|
||||
newRequest := patchRequest(mutatePatches, request, logger)
|
||||
imagePatches, err := ws.applyImageVerifyPolicies(newRequest, policyContext, verifyImagesPolicies, logger)
|
||||
|
@ -146,7 +165,9 @@ func (ws *WebhookServer) resourceMutation(request *admissionv1.AdmissionRequest)
|
|||
logger.Error(err, "image verification failed")
|
||||
return admissionutils.ResponseFailure(false, err.Error())
|
||||
}
|
||||
|
||||
var patches = append(mutatePatches, imagePatches...)
|
||||
|
||||
return admissionutils.ResponseSuccessWithPatch(true, "", patches)
|
||||
}
|
||||
|
||||
|
@ -155,21 +176,23 @@ func (ws *WebhookServer) resourceValidation(request *admissionv1.AdmissionReques
|
|||
if request.Operation == admissionv1.Delete {
|
||||
ws.handleDelete(request)
|
||||
}
|
||||
|
||||
if excludeKyvernoResources(request.Kind.Kind) {
|
||||
return admissionutils.ResponseSuccess(true, "")
|
||||
}
|
||||
|
||||
logger.V(6).Info("received an admission request in validating webhook")
|
||||
|
||||
// timestamp at which this admission request got triggered
|
||||
requestTime := time.Now().Unix()
|
||||
policies := ws.pCache.GetPolicies(policycache.ValidateEnforce, request.Kind.Kind, "")
|
||||
// Get namespace policies from the cache for the requested resource namespace
|
||||
nsPolicies := ws.pCache.GetPolicies(policycache.ValidateEnforce, request.Kind.Kind, request.Namespace)
|
||||
policies = append(policies, nsPolicies...)
|
||||
policies := ws.pCache.GetPolicies(policycache.ValidateEnforce, request.Kind.Kind, request.Namespace)
|
||||
mutatePolicies := ws.pCache.GetPolicies(policycache.Mutate, request.Kind.Kind, request.Namespace)
|
||||
generatePolicies := ws.pCache.GetPolicies(policycache.Generate, request.Kind.Kind, request.Namespace)
|
||||
if len(generatePolicies) == 0 && request.Operation == admissionv1.Update {
|
||||
// handle generate source resource updates
|
||||
go ws.handleUpdatesForGenerateRules(request, []kyverno.PolicyInterface{})
|
||||
}
|
||||
|
||||
var roles, clusterRoles []string
|
||||
if containsRBACInfo(policies, generatePolicies) {
|
||||
var err error
|
||||
|
@ -178,26 +201,32 @@ func (ws *WebhookServer) resourceValidation(request *admissionv1.AdmissionReques
|
|||
return errorResponse(logger, err, "failed to fetch RBAC data")
|
||||
}
|
||||
}
|
||||
userRequestInfo := kyverno.RequestInfo{
|
||||
|
||||
userRequestInfo := urkyverno.RequestInfo{
|
||||
Roles: roles,
|
||||
ClusterRoles: clusterRoles,
|
||||
AdmissionUserInfo: *request.UserInfo.DeepCopy(),
|
||||
}
|
||||
|
||||
ctx, err := newVariablesContext(request, &userRequestInfo)
|
||||
if err != nil {
|
||||
return errorResponse(logger, err, "failed create policy rule context")
|
||||
}
|
||||
|
||||
namespaceLabels := make(map[string]string)
|
||||
if request.Kind.Kind != "Namespace" && request.Namespace != "" {
|
||||
namespaceLabels = common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, ws.nsLister, logger)
|
||||
}
|
||||
|
||||
newResource, oldResource, err := utils.ExtractResources(nil, request)
|
||||
if err != nil {
|
||||
return errorResponse(logger, err, "failed create parse resource")
|
||||
}
|
||||
|
||||
if err := ctx.AddImageInfos(&newResource); err != nil {
|
||||
return errorResponse(logger, err, "failed add image information to policy rule context")
|
||||
}
|
||||
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: newResource,
|
||||
OldResource: oldResource,
|
||||
|
@ -206,20 +235,25 @@ func (ws *WebhookServer) resourceValidation(request *admissionv1.AdmissionReques
|
|||
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
||||
JSONContext: ctx,
|
||||
Client: ws.client,
|
||||
AdmissionOperation: true,
|
||||
}
|
||||
|
||||
vh := &validationHandler{
|
||||
log: ws.log,
|
||||
eventGen: ws.eventGen,
|
||||
prGenerator: ws.prGenerator,
|
||||
}
|
||||
|
||||
ok, msg := vh.handleValidation(ws.promConfig, request, policies, policyContext, namespaceLabels, requestTime)
|
||||
if !ok {
|
||||
logger.Info("admission request denied")
|
||||
return admissionutils.ResponseFailure(false, msg)
|
||||
}
|
||||
|
||||
// push admission request to audit handler, this won't block the admission request
|
||||
ws.auditHandler.Add(request.DeepCopy())
|
||||
// process generate policies
|
||||
ws.applyGeneratePolicies(request, policyContext, generatePolicies, requestTime, logger)
|
||||
|
||||
go ws.createUpdateRequests(request, policyContext, generatePolicies, mutatePolicies, requestTime, logger)
|
||||
|
||||
return admissionutils.ResponseSuccess(true, "")
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ func Admission(logger logr.Logger, inner AdmissionHandler) http.HandlerFunc {
|
|||
http.Error(writer, "Can't decode body as AdmissionReview", http.StatusExpectationFailed)
|
||||
return
|
||||
}
|
||||
logger = logger.WithName("handlerFunc").WithValues(
|
||||
logger = logger.WithValues(
|
||||
"kind", admissionReview.Request.Kind,
|
||||
"namespace", admissionReview.Request.Namespace,
|
||||
"name", admissionReview.Request.Name,
|
||||
|
@ -67,7 +67,12 @@ func Admission(logger logr.Logger, inner AdmissionHandler) http.HandlerFunc {
|
|||
if _, err := writer.Write(responseJSON); err != nil {
|
||||
http.Error(writer, fmt.Sprintf("could not write response: %v", err), http.StatusInternalServerError)
|
||||
}
|
||||
logger.V(4).Info("admission review request processed", "time", time.Since(startTime).String())
|
||||
|
||||
if admissionReview.Request.Kind.Kind == "Lease" {
|
||||
logger.V(6).Info("admission review request processed", "time", time.Since(startTime).String())
|
||||
} else {
|
||||
logger.V(4).Info("admission review request processed", "time", time.Since(startTime).String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +87,7 @@ func Filter(c config.Interface, inner AdmissionHandler) AdmissionHandler {
|
|||
|
||||
func Verify(m *webhookconfig.Monitor, logger logr.Logger) AdmissionHandler {
|
||||
return func(request *admissionv1.AdmissionRequest) *admissionv1.AdmissionResponse {
|
||||
logger = logger.WithName("verifyHandler").WithValues(
|
||||
logger = logger.WithValues(
|
||||
"action", "verify",
|
||||
"kind", request.Kind,
|
||||
"namespace", request.Namespace,
|
||||
|
@ -90,7 +95,7 @@ func Verify(m *webhookconfig.Monitor, logger logr.Logger) AdmissionHandler {
|
|||
"operation", request.Operation,
|
||||
"gvk", request.Kind.String(),
|
||||
)
|
||||
logger.V(3).Info("incoming request", "last admission request timestamp", m.Time())
|
||||
logger.V(6).Info("incoming request", "last admission request timestamp", m.Time())
|
||||
return admissionutils.Response(true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ func (ws *WebhookServer) handleMutation(
|
|||
}
|
||||
|
||||
// generate annotations
|
||||
if annPatches := generateAnnotationPatches(engineResponses, logger); annPatches != nil {
|
||||
if annPatches := utils.GenerateAnnotationPatches(engineResponses, logger); annPatches != nil {
|
||||
patches = append(patches, annPatches...)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,13 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/background"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urlister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
|
@ -26,8 +28,8 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/userinfo"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/kyverno/kyverno/pkg/webhookconfig"
|
||||
webhookgenerate "github.com/kyverno/kyverno/pkg/webhooks/generate"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
|
||||
webhookgenerate "github.com/kyverno/kyverno/pkg/webhooks/updaterequest"
|
||||
"github.com/pkg/errors"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
informers "k8s.io/client-go/informers/core/v1"
|
||||
|
@ -49,6 +51,12 @@ type WebhookServer struct {
|
|||
// grSynced returns true if the Generate Request store has been synced at least once
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
// urLister can list/get update requests from the shared informer's store
|
||||
urLister urlister.UpdateRequestNamespaceLister
|
||||
|
||||
// urSynced returns true if the Update Request store has been synced at least once
|
||||
urSynced cache.InformerSynced
|
||||
|
||||
// list/get cluster policy resource
|
||||
pLister kyvernolister.ClusterPolicyLister
|
||||
|
||||
|
@ -101,7 +109,7 @@ type WebhookServer struct {
|
|||
prGenerator policyreport.GeneratorInterface
|
||||
|
||||
// generate request generator
|
||||
grGenerator *webhookgenerate.Generator
|
||||
grGenerator webhookgenerate.Interface
|
||||
|
||||
nsLister listerv1.NamespaceLister
|
||||
|
||||
|
@ -128,6 +136,7 @@ func NewWebhookServer(
|
|||
client *client.Client,
|
||||
tlsPair *tlsutils.PemPair,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
urInformer urinformer.UpdateRequestInformer,
|
||||
pInformer kyvernoinformer.ClusterPolicyInformer,
|
||||
rbInformer rbacinformer.RoleBindingInformer,
|
||||
crbInformer rbacinformer.ClusterRoleBindingInformer,
|
||||
|
@ -140,7 +149,7 @@ func NewWebhookServer(
|
|||
webhookMonitor *webhookconfig.Monitor,
|
||||
configHandler config.Interface,
|
||||
prGenerator policyreport.GeneratorInterface,
|
||||
grGenerator *webhookgenerate.Generator,
|
||||
grGenerator webhookgenerate.Interface,
|
||||
auditHandler AuditHandler,
|
||||
cleanUp chan<- struct{},
|
||||
log logr.Logger,
|
||||
|
@ -160,6 +169,8 @@ func NewWebhookServer(
|
|||
kyvernoClient: kyvernoClient,
|
||||
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
|
||||
grSynced: grInformer.Informer().HasSynced,
|
||||
urLister: urInformer.Lister().UpdateRequests(config.KyvernoNamespace),
|
||||
urSynced: urInformer.Informer().HasSynced,
|
||||
pLister: pInformer.Lister(),
|
||||
pSynced: pInformer.Informer().HasSynced,
|
||||
rbLister: rbInformer.Lister(),
|
||||
|
@ -191,7 +202,7 @@ func NewWebhookServer(
|
|||
mux.HandlerFunc("POST", config.ValidatingWebhookServicePath, ws.admissionHandler(true, ws.resourceValidation))
|
||||
mux.HandlerFunc("POST", config.PolicyMutatingWebhookServicePath, ws.admissionHandler(true, ws.policyMutation))
|
||||
mux.HandlerFunc("POST", config.PolicyValidatingWebhookServicePath, ws.admissionHandler(true, ws.policyValidation))
|
||||
mux.HandlerFunc("POST", config.VerifyMutatingWebhookServicePath, ws.admissionHandler(false, handlers.Verify(ws.webhookMonitor, ws.log)))
|
||||
mux.HandlerFunc("POST", config.VerifyMutatingWebhookServicePath, ws.admissionHandler(false, handlers.Verify(ws.webhookMonitor, ws.log.WithName("verifyHandler"))))
|
||||
mux.HandlerFunc("GET", config.LivenessServicePath, handlers.Probe(ws.webhookRegister.Check))
|
||||
mux.HandlerFunc("GET", config.ReadinessServicePath, handlers.Probe(nil))
|
||||
ws.server = &http.Server{
|
||||
|
@ -205,7 +216,7 @@ func NewWebhookServer(
|
|||
}
|
||||
|
||||
func (ws *WebhookServer) buildPolicyContext(request *admissionv1.AdmissionRequest, addRoles bool) (*engine.PolicyContext, error) {
|
||||
userRequestInfo := v1.RequestInfo{
|
||||
userRequestInfo := v1beta1.RequestInfo{
|
||||
AdmissionUserInfo: *request.UserInfo.DeepCopy(),
|
||||
}
|
||||
|
||||
|
@ -246,6 +257,7 @@ func (ws *WebhookServer) buildPolicyContext(request *admissionv1.AdmissionReques
|
|||
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
||||
JSONContext: ctx,
|
||||
Client: ws.client,
|
||||
AdmissionOperation: true,
|
||||
}
|
||||
|
||||
if request.Operation == admissionv1.Update {
|
||||
|
@ -257,7 +269,7 @@ func (ws *WebhookServer) buildPolicyContext(request *admissionv1.AdmissionReques
|
|||
|
||||
// RunAsync TLS server in separate thread and returns control immediately
|
||||
func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
|
||||
if !cache.WaitForCacheSync(stopCh, ws.grSynced, ws.pSynced, ws.rbSynced, ws.crbSynced, ws.rSynced, ws.crSynced) {
|
||||
if !cache.WaitForCacheSync(stopCh, ws.grSynced, ws.urSynced, ws.pSynced, ws.rbSynced, ws.crbSynced, ws.rSynced, ws.crSynced) {
|
||||
ws.log.Info("failed to sync informer cache")
|
||||
}
|
||||
go func() {
|
||||
|
|
71
pkg/webhooks/updaterequest.go
Normal file
71
pkg/webhooks/updaterequest.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package webhooks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
)
|
||||
|
||||
// createUpdateRequests applies generate and mutateExisting policies, and creates update requests for background reconcile
|
||||
func (ws *WebhookServer) createUpdateRequests(request *admissionv1.AdmissionRequest, policyContext *engine.PolicyContext, generatePolicies, mutatePolicies []kyverno.PolicyInterface, ts int64, logger logr.Logger) {
|
||||
admissionReviewCompletionLatencyChannel := make(chan int64, 1)
|
||||
generateEngineResponsesSenderForAdmissionReviewDurationMetric := make(chan []*response.EngineResponse, 1)
|
||||
generateEngineResponsesSenderForAdmissionRequestsCountMetric := make(chan []*response.EngineResponse, 1)
|
||||
|
||||
go ws.handleMutateExisting(request, mutatePolicies, policyContext, ts)
|
||||
|
||||
go ws.handleGenerate(request, generatePolicies, policyContext, ts, &admissionReviewCompletionLatencyChannel, &generateEngineResponsesSenderForAdmissionReviewDurationMetric, &generateEngineResponsesSenderForAdmissionRequestsCountMetric)
|
||||
go ws.registerAdmissionReviewDurationMetricGenerate(logger, string(request.Operation), &admissionReviewCompletionLatencyChannel, &generateEngineResponsesSenderForAdmissionReviewDurationMetric)
|
||||
go ws.registerAdmissionRequestsMetricGenerate(logger, string(request.Operation), &generateEngineResponsesSenderForAdmissionRequestsCountMetric)
|
||||
}
|
||||
|
||||
func (ws *WebhookServer) handleMutateExisting(request *admissionv1.AdmissionRequest, policies []kyverno.PolicyInterface, policyContext *engine.PolicyContext, admissionRequestTimestamp int64) {
|
||||
|
||||
logger := ws.log.WithValues("action", "mutateExisting", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation, "gvk", request.Kind.String())
|
||||
logger.V(4).Info("update request")
|
||||
|
||||
if request.Operation == admissionv1.Delete {
|
||||
policyContext.NewResource = policyContext.OldResource
|
||||
}
|
||||
|
||||
var engineResponses []*response.EngineResponse
|
||||
for _, policy := range policies {
|
||||
var rules []response.RuleResponse
|
||||
policyContext.Policy = policy
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if rule.Status == response.RuleStatusPass {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
||||
if len(rules) > 0 {
|
||||
engineResponse.PolicyResponse.Rules = rules
|
||||
engineResponses = append(engineResponses, engineResponse)
|
||||
}
|
||||
|
||||
// registering the kyverno_policy_results_total metric concurrently
|
||||
go ws.registerPolicyResultsMetricMutation(logger, string(request.Operation), policy, *engineResponse)
|
||||
|
||||
// registering the kyverno_policy_execution_duration_seconds metric concurrently
|
||||
go ws.registerPolicyExecutionDurationMetricMutate(logger, string(request.Operation), policy, *engineResponse)
|
||||
}
|
||||
|
||||
if failedResponse := applyGenerateRequest(request, urkyverno.Mutate, ws.grGenerator, policyContext.AdmissionInfo, request.Operation, engineResponses...); failedResponse != nil {
|
||||
for _, failedGR := range failedResponse {
|
||||
events := failedEvents(fmt.Errorf("failed to create update request: %v", failedGR.err), failedGR.gr, policyContext.NewResource)
|
||||
ws.eventGen.Add(events...)
|
||||
}
|
||||
}
|
||||
|
||||
admissionReviewLatencyDuration := int64(time.Since(time.Unix(admissionRequestTimestamp, 0)))
|
||||
go ws.registerAdmissionReviewDurationMetricMutate(logger, string(request.Operation), engineResponses, admissionReviewLatencyDuration)
|
||||
go ws.registerAdmissionRequestsMetricMutate(logger, string(request.Operation), engineResponses)
|
||||
}
|
224
pkg/webhooks/updaterequest/generator.go
Normal file
224
pkg/webhooks/updaterequest/generator.go
Normal file
|
@ -0,0 +1,224 @@
|
|||
package updaterequest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
backoff "github.com/cenkalti/backoff"
|
||||
"github.com/gardener/controller-manager-library/pkg/logger"
|
||||
"github.com/go-logr/logr"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||
urkyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1beta1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
urkyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenerateRequests provides interface to manage update requests
|
||||
type Interface interface {
|
||||
Apply(gr urkyverno.UpdateRequestSpec, action admissionv1.Operation) error
|
||||
}
|
||||
|
||||
// info object stores message data to create update request
|
||||
type info struct {
|
||||
spec urkyverno.UpdateRequestSpec
|
||||
action admissionv1.Operation
|
||||
}
|
||||
|
||||
// Generator defines the implementation to mange update request resource
|
||||
type Generator struct {
|
||||
client *kyvernoclient.Clientset
|
||||
stopCh <-chan struct{}
|
||||
log logr.Logger
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestNamespaceLister
|
||||
grSynced cache.InformerSynced
|
||||
|
||||
urLister urkyvernolister.UpdateRequestNamespaceLister
|
||||
urSynced cache.InformerSynced
|
||||
}
|
||||
|
||||
// NewGenerator returns a new instance of UpdateRequest resource generator
|
||||
func NewGenerator(client *kyvernoclient.Clientset, grInformer kyvernoinformer.GenerateRequestInformer, urInformer urkyvernoinformer.UpdateRequestInformer, stopCh <-chan struct{}, log logr.Logger) *Generator {
|
||||
gen := &Generator{
|
||||
client: client,
|
||||
stopCh: stopCh,
|
||||
log: log,
|
||||
grLister: grInformer.Lister().GenerateRequests(config.KyvernoNamespace),
|
||||
grSynced: grInformer.Informer().HasSynced,
|
||||
urLister: urInformer.Lister().UpdateRequests(config.KyvernoNamespace),
|
||||
urSynced: urInformer.Informer().HasSynced,
|
||||
}
|
||||
return gen
|
||||
}
|
||||
|
||||
// Apply creates update request resource
|
||||
func (g *Generator) Apply(gr urkyverno.UpdateRequestSpec, action admissionv1.Operation) error {
|
||||
logger := g.log
|
||||
logger.V(4).Info("reconcile Update Request", "request", gr)
|
||||
|
||||
message := info{
|
||||
action: action,
|
||||
spec: gr,
|
||||
}
|
||||
go g.processApply(message)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run starts the update request spec
|
||||
func (g *Generator) Run(workers int, stopCh <-chan struct{}) {
|
||||
logger := g.log
|
||||
defer utilruntime.HandleCrash()
|
||||
|
||||
logger.V(4).Info("starting")
|
||||
defer func() {
|
||||
logger.V(4).Info("shutting down")
|
||||
}()
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, g.grSynced, g.urSynced) {
|
||||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
||||
<-g.stopCh
|
||||
}
|
||||
|
||||
func (g *Generator) processApply(i info) {
|
||||
if err := g.generate(i); err != nil {
|
||||
logger.Error(err, "failed to update request CR")
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) generate(i info) error {
|
||||
if err := retryApplyResource(g.client, i.spec, g.log, i.action, g.urLister); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func retryApplyResource(client *kyvernoclient.Clientset, urSpec urkyverno.UpdateRequestSpec,
|
||||
log logr.Logger, action admissionv1.Operation, urLister urkyvernolister.UpdateRequestNamespaceLister) error {
|
||||
|
||||
if action == admissionv1.Delete && urSpec.Type == urkyverno.Generate {
|
||||
return nil
|
||||
}
|
||||
|
||||
var i int
|
||||
var err error
|
||||
|
||||
_, policyName, err := cache.SplitMetaNamespaceKey(urSpec.Policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
applyResource := func() error {
|
||||
ur := urkyverno.UpdateRequest{
|
||||
Spec: urSpec,
|
||||
Status: urkyverno.UpdateRequestStatus{
|
||||
State: urkyverno.Pending,
|
||||
},
|
||||
}
|
||||
|
||||
queryLabels := make(map[string]string)
|
||||
if ur.Spec.Type == urkyverno.Mutate {
|
||||
queryLabels := map[string]string{
|
||||
"mutate.updaterequest.kyverno.io/policy-name": ur.Spec.Policy,
|
||||
"mutate.updaterequest.kyverno.io/trigger-name": ur.Spec.Resource.Name,
|
||||
"mutate.updaterequest.kyverno.io/trigger-namespace": ur.Spec.Resource.Namespace,
|
||||
"mutate.updaterequest.kyverno.io/trigger-kind": ur.Spec.Resource.Kind,
|
||||
}
|
||||
|
||||
if ur.Spec.Resource.APIVersion != "" {
|
||||
queryLabels["mutate.updaterequest.kyverno.io/trigger-apiversion"] = ur.Spec.Resource.APIVersion
|
||||
}
|
||||
} else if ur.Spec.Type == urkyverno.Generate {
|
||||
queryLabels = labels.Set(map[string]string{
|
||||
"generate.kyverno.io/policy-name": policyName,
|
||||
"generate.kyverno.io/resource-name": urSpec.Resource.Name,
|
||||
"generate.kyverno.io/resource-kind": urSpec.Resource.Kind,
|
||||
"generate.kyverno.io/resource-namespace": urSpec.Resource.Namespace,
|
||||
})
|
||||
}
|
||||
|
||||
ur.SetNamespace(config.KyvernoNamespace)
|
||||
isExist := false
|
||||
log.V(4).Info("apply UpdateRequest", "ruleType", ur.Spec.Type)
|
||||
|
||||
urList, err := urLister.List(labels.SelectorFromSet(queryLabels))
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to get update request for the resource", "kind", urSpec.Resource.Kind, "name", urSpec.Resource.Name, "namespace", urSpec.Resource.Namespace)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range urList {
|
||||
log.V(4).Info("updating existing update request", "name", v.GetName())
|
||||
|
||||
v.Spec.Context = ur.Spec.Context
|
||||
v.Spec.Policy = ur.Spec.Policy
|
||||
v.Spec.Resource = ur.Spec.Resource
|
||||
v.Status.Message = ""
|
||||
|
||||
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Update(context.TODO(), v, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.V(4).Info("failed to update UpdateRequest, retrying", "retryCount", i, "name", ur.GetName(), "namespace", ur.GetNamespace())
|
||||
i++
|
||||
} else {
|
||||
log.V(4).Info("successfully updated UpdateRequest", "retryCount", i, "name", ur.GetName(), "namespace", ur.GetNamespace())
|
||||
}
|
||||
|
||||
new.Status.State = urkyverno.Pending
|
||||
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
|
||||
log.Error(err, "failed to set UpdateRequest state to Pending")
|
||||
}
|
||||
|
||||
isExist = true
|
||||
}
|
||||
|
||||
if !isExist {
|
||||
log.V(4).Info("creating new UpdateRequest", "type", ur.Spec.Type)
|
||||
|
||||
ur.SetGenerateName("ur-")
|
||||
ur.SetLabels(queryLabels)
|
||||
|
||||
new, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), &ur, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
log.V(4).Info("failed to create UpdateRequest, retrying", "retryCount", i, "name", ur.GetGenerateName(), "namespace", ur.GetNamespace())
|
||||
i++
|
||||
} else {
|
||||
log.V(4).Info("successfully created UpdateRequest", "retryCount", i, "name", new.GetName(), "namespace", ur.GetNamespace())
|
||||
}
|
||||
|
||||
new.Status.State = urkyverno.Pending
|
||||
if _, err := client.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
|
||||
log.Error(err, "failed to set UpdateRequest state to Pending")
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
exbackoff := &backoff.ExponentialBackOff{
|
||||
InitialInterval: 500 * time.Millisecond,
|
||||
RandomizationFactor: 0.5,
|
||||
Multiplier: 1.5,
|
||||
MaxInterval: time.Second,
|
||||
MaxElapsedTime: 3 * time.Second,
|
||||
Clock: backoff.SystemClock,
|
||||
}
|
||||
|
||||
exbackoff.Reset()
|
||||
err = backoff.Retry(applyResource, exbackoff)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -4,22 +4,19 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
client "github.com/kyverno/kyverno/pkg/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/policycache"
|
||||
"github.com/kyverno/kyverno/pkg/policyreport"
|
||||
"github.com/kyverno/kyverno/pkg/userinfo"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
@ -161,7 +158,7 @@ func (h *auditHandler) process(request *admissionv1.AdmissionRequest) error {
|
|||
}
|
||||
}
|
||||
|
||||
userRequestInfo := v1.RequestInfo{
|
||||
userRequestInfo := v1beta1.RequestInfo{
|
||||
Roles: roles,
|
||||
ClusterRoles: clusterRoles,
|
||||
AdmissionUserInfo: request.UserInfo}
|
||||
|
@ -193,6 +190,7 @@ func (h *auditHandler) process(request *admissionv1.AdmissionRequest) error {
|
|||
ExcludeResourceFunc: h.configHandler.ToFilter,
|
||||
JSONContext: ctx,
|
||||
Client: h.client,
|
||||
AdmissionOperation: true,
|
||||
}
|
||||
|
||||
vh := &validationHandler{
|
||||
|
|
Loading…
Add table
Reference in a new issue