mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
distributed labels in group, version, and resource so it doesn't exceed (#11620)
* change label to hash if exceed 63 limit char Signed-off-by: Mohd Kamaal <mohdkamaal2019@gmail.com> * Distribute GVR labels into 'group', 'version', and 'resource' to avoid exceeding character limits Signed-off-by: Mohd Kamaal <mohdkamaal2019@gmail.com> --------- Signed-off-by: Mohd Kamaal <mohdkamaal2019@gmail.com> Co-authored-by: Kamaal <kamaal@macs-MacBook-Air.local> Co-authored-by: Vishal Choudhary <vishal.choudhary@nirmata.com>
This commit is contained in:
parent
3b6f4bdc2c
commit
e771896541
8 changed files with 188 additions and 6 deletions
|
@ -115,7 +115,13 @@ func SetResourceUid(report reportsv1.ReportInterface, uid types.UID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetResourceGVR(report reportsv1.ReportInterface, gvr schema.GroupVersionResource) {
|
func SetResourceGVR(report reportsv1.ReportInterface, gvr schema.GroupVersionResource) {
|
||||||
if gvr.Group != "" {
|
gvrString := gvr.Resource + "." + gvr.Version + "." + gvr.Group
|
||||||
|
|
||||||
|
if len(gvrString) > 63 {
|
||||||
|
controllerutils.SetLabel(report, LabelResourceGroup, gvr.Group)
|
||||||
|
controllerutils.SetLabel(report, LabelResourceVersion, gvr.Version)
|
||||||
|
controllerutils.SetLabel(report, AnnotationResourceName, gvr.Resource)
|
||||||
|
} else if gvr.Group != "" {
|
||||||
controllerutils.SetLabel(report, LabelResourceGVR, gvr.Resource+"."+gvr.Version+"."+gvr.Group)
|
controllerutils.SetLabel(report, LabelResourceGVR, gvr.Resource+"."+gvr.Version+"."+gvr.Group)
|
||||||
} else {
|
} else {
|
||||||
controllerutils.SetLabel(report, LabelResourceGVR, gvr.Resource+"."+gvr.Version)
|
controllerutils.SetLabel(report, LabelResourceGVR, gvr.Resource+"."+gvr.Version)
|
||||||
|
@ -181,16 +187,29 @@ func GetResourceUid(report metav1.Object) types.UID {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetResourceGVR(report metav1.Object) schema.GroupVersionResource {
|
func GetResourceGVR(report metav1.Object) schema.GroupVersionResource {
|
||||||
arg := controllerutils.GetLabel(report, LabelResourceGVR)
|
group := controllerutils.GetLabel(report, LabelResourceGroup)
|
||||||
dots := strings.Count(arg, ".")
|
version := controllerutils.GetLabel(report, LabelResourceVersion)
|
||||||
|
resource := controllerutils.GetLabel(report, AnnotationResourceName)
|
||||||
|
GVRstring := group + version + resource
|
||||||
|
|
||||||
|
// If all three parts exist, return the GVR
|
||||||
|
if group != "" && version != "" && resource != "" {
|
||||||
|
if len(GVRstring) > 63 {
|
||||||
|
return schema.GroupVersionResource{Group: group, Version: version, Resource: resource}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to the old combined label
|
||||||
|
combinedGVR := controllerutils.GetLabel(report, LabelResourceGVR)
|
||||||
|
dots := strings.Count(combinedGVR, ".")
|
||||||
if dots >= 2 {
|
if dots >= 2 {
|
||||||
s := strings.SplitN(arg, ".", 3)
|
s := strings.SplitN(combinedGVR, ".", 3)
|
||||||
return schema.GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]}
|
return schema.GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]}
|
||||||
} else if dots == 1 {
|
} else if dots == 1 {
|
||||||
s := strings.SplitN(arg, ".", 2)
|
s := strings.SplitN(combinedGVR, ".", 2)
|
||||||
return schema.GroupVersionResource{Version: s[1], Resource: s[0]}
|
return schema.GroupVersionResource{Version: s[1], Resource: s[0]}
|
||||||
}
|
}
|
||||||
return schema.GroupVersionResource{Resource: arg}
|
return schema.GroupVersionResource{Resource: combinedGVR}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetResourceNamespaceAndName(report metav1.Object) (string, string) {
|
func GetResourceNamespaceAndName(report metav1.Object) (string, string) {
|
||||||
|
|
20
test/conformance/chainsaw/reports/admission/label/README.md
Normal file
20
test/conformance/chainsaw/reports/admission/label/README.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This test ensures that the EphemeralReport is generated successfully at admission, even when long GVR (Group, Version, Resource) labels are used. Kyverno handles this by distributing the GVR components (group, version, resource) into separate labels, ensuring they fit within Kubernetes' 63-character limit.
|
||||||
|
|
||||||
|
Kubernetes enforces the 63-character label limit during resource creation, and Kyverno ensures that the GVR components are split appropriately into distinct labels to avoid exceeding this limit.
|
||||||
|
|
||||||
|
## Why It's Important
|
||||||
|
|
||||||
|
If the combined length of GVR identifiers exceeds the 63-character limit, Kubernetes won't create the EphemeralReport at admission. Kyverno addresses this by:
|
||||||
|
Splitting the GVR components into separate labels, ensuring no label exceeds the size limit.
|
||||||
|
This approach enables the successful creation of EphemeralReport at admission.
|
||||||
|
|
||||||
|
## Expected Behavior
|
||||||
|
|
||||||
|
- Kyverno splits the GVR components (group, version, resource) into separate labels.
|
||||||
|
- The creation of EphemeralReport at admission will proceed successfully with the labels preserved within size limits.
|
||||||
|
|
||||||
|
## Reference Issue(s)
|
||||||
|
|
||||||
|
- Kyverno Issue #11547
|
|
@ -0,0 +1,30 @@
|
||||||
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||||
|
kind: Test
|
||||||
|
metadata:
|
||||||
|
name: test-long-resource-labels
|
||||||
|
spec:
|
||||||
|
steps:
|
||||||
|
- name: create crd
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: crd-definition.yaml
|
||||||
|
|
||||||
|
- name: create permission
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: crd-permission.yaml
|
||||||
|
|
||||||
|
- name: apply policy
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: policy.yaml
|
||||||
|
|
||||||
|
- name: create resource
|
||||||
|
try:
|
||||||
|
- apply:
|
||||||
|
file: resource.yaml
|
||||||
|
|
||||||
|
- name: check report
|
||||||
|
try:
|
||||||
|
- assert:
|
||||||
|
file: ephemeral-report.yaml
|
|
@ -0,0 +1,25 @@
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: verylongresources.verylonggggggggggggggggggggggggggggggggggggggggroup.example.com
|
||||||
|
spec:
|
||||||
|
group: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com
|
||||||
|
names:
|
||||||
|
kind: VeryLongResource
|
||||||
|
listKind: VeryLongResourceList
|
||||||
|
plural: verylongresources
|
||||||
|
singular: verylongresource
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: verylongversion
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
spec:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
exampleField:
|
||||||
|
type: string
|
|
@ -0,0 +1,22 @@
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: kyverno-reports-controller
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["verylonggggggggggggggggggggggggggggggggggggggggroup.example.com"]
|
||||||
|
resources: ["verylongresources"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kyverno-reports-controller-rolebinding
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kyverno-reports-controller
|
||||||
|
namespace: kyverno
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: kyverno-reports-controller
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
|
@ -0,0 +1,39 @@
|
||||||
|
apiVersion: v1
|
||||||
|
items:
|
||||||
|
- apiVersion: reports.kyverno.io/v1
|
||||||
|
kind: EphemeralReport
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
audit.kyverno.io/resource.name: very-long-resource-name-testing-label-length
|
||||||
|
generation: 1
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/managed-by: kyverno
|
||||||
|
audit.kyverno.io/resource.group: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com
|
||||||
|
audit.kyverno.io/resource.name: verylongresources
|
||||||
|
audit.kyverno.io/resource.kind: VeryLongResource
|
||||||
|
audit.kyverno.io/resource.version: verylongversion
|
||||||
|
audit.kyverno.io/source: admission
|
||||||
|
ownerReferences:
|
||||||
|
- apiVersion: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com/verylongversion
|
||||||
|
kind: VeryLongResource
|
||||||
|
name: very-long-resource-name-testing-label-length
|
||||||
|
spec:
|
||||||
|
owner:
|
||||||
|
apiVersion: ""
|
||||||
|
kind: ""
|
||||||
|
name: ""
|
||||||
|
uid: ""
|
||||||
|
results:
|
||||||
|
- message: 'validation error: Resource must have valid labels. rule check-label-length
|
||||||
|
failed at path /metadata/labels/team/'
|
||||||
|
policy: validate-long-resource-labels
|
||||||
|
result: fail
|
||||||
|
rule: check-label-length
|
||||||
|
scored: true
|
||||||
|
source: kyverno
|
||||||
|
summary:
|
||||||
|
error: 0
|
||||||
|
fail: 1
|
||||||
|
pass: 0
|
||||||
|
skip: 0
|
||||||
|
warn: 0
|
|
@ -0,0 +1,19 @@
|
||||||
|
apiVersion: kyverno.io/v1
|
||||||
|
kind: ClusterPolicy
|
||||||
|
metadata:
|
||||||
|
name: validate-long-resource-labels
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- name: check-label-length
|
||||||
|
match:
|
||||||
|
resources:
|
||||||
|
kinds:
|
||||||
|
- VeryLongResource
|
||||||
|
validate:
|
||||||
|
message: "Resource must have valid labels."
|
||||||
|
pattern:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
env: "?*"
|
||||||
|
team: "?*"
|
||||||
|
failureAction: Audit
|
|
@ -0,0 +1,8 @@
|
||||||
|
apiVersion: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com/verylongversion
|
||||||
|
kind: VeryLongResource
|
||||||
|
metadata:
|
||||||
|
name: very-long-resource-name-testing-label-length
|
||||||
|
labels:
|
||||||
|
env: "test-environment"
|
||||||
|
spec:
|
||||||
|
exampleField: "exampleValue"
|
Loading…
Add table
Reference in a new issue