@@ -4,7 +4,11 @@ import (
4
4
"strings"
5
5
6
6
appsv1 "k8s.io/api/apps/v1"
7
+ batchv1 "k8s.io/api/batch/v1"
7
8
v1 "k8s.io/api/core/v1"
9
+ networkingv1 "k8s.io/api/networking/v1"
10
+ policyv1 "k8s.io/api/policy/v1"
11
+ rbacv1 "k8s.io/api/rbac/v1"
8
12
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9
13
)
10
14
@@ -20,6 +24,46 @@ func CleanObject(obj interface{}) {
20
24
case * appsv1.Deployment :
21
25
CleanDeployment (typedObj )
22
26
27
+ // StatefulSet
28
+ case * appsv1.StatefulSet :
29
+ CleanStatefulSet (typedObj )
30
+
31
+ // DaemonSet
32
+ case * appsv1.DaemonSet :
33
+ CleanDaemonSet (typedObj )
34
+
35
+ // ReplicaSet
36
+ case * appsv1.ReplicaSet :
37
+ CleanReplicaSet (typedObj )
38
+
39
+ // Job
40
+ case * batchv1.Job :
41
+ CleanJob (typedObj )
42
+
43
+ // CronJob
44
+ case * batchv1.CronJob :
45
+ CleanCronJob (typedObj )
46
+
47
+ // Ingress
48
+ case * networkingv1.Ingress :
49
+ CleanIngress (typedObj )
50
+
51
+ // PodDisruptionBudget
52
+ case * policyv1.PodDisruptionBudget :
53
+ CleanPDB (typedObj )
54
+
55
+ // Role and ClusterRole
56
+ case * rbacv1.Role :
57
+ CleanRole (typedObj )
58
+ case * rbacv1.ClusterRole :
59
+ CleanClusterRole (typedObj )
60
+
61
+ // RoleBinding and ClusterRoleBinding
62
+ case * rbacv1.RoleBinding :
63
+ CleanRoleBinding (typedObj )
64
+ case * rbacv1.ClusterRoleBinding :
65
+ CleanClusterRoleBinding (typedObj )
66
+
23
67
// Service
24
68
case * v1.Service :
25
69
CleanService (typedObj )
@@ -209,7 +253,6 @@ func inferAPIVersionAndKind(obj map[string]interface{}) {
209
253
// IsSystemAnnotation checks if an annotation is system-managed
210
254
func IsSystemAnnotation (key string ) bool {
211
255
systemPrefixes := []string {
212
- "kubernetes.io/" ,
213
256
"k8s.io/" ,
214
257
"control-plane.alpha.kubernetes.io/" ,
215
258
"app.kubernetes.io/" ,
@@ -396,7 +439,6 @@ func CleanMetadata(meta *metav1.ObjectMeta) {
396
439
meta .DeletionGracePeriodSeconds = nil
397
440
meta .Generation = 0
398
441
meta .ResourceVersion = ""
399
- meta .SelfLink = ""
400
442
meta .UID = ""
401
443
meta .ManagedFields = nil
402
444
@@ -410,18 +452,203 @@ func CleanMetadata(meta *metav1.ObjectMeta) {
410
452
meta .Name = name
411
453
meta .Namespace = namespace
412
454
meta .Labels = labels
413
-
414
455
// Clean annotations but keep user ones
415
- if annotations != nil {
416
- for k := range annotations {
417
- if IsSystemAnnotation (k ) {
418
- delete (annotations , k )
456
+ // if annotations != nil {
457
+ // for k := range annotations {
458
+ // if IsSystemAnnotation(k) {
459
+ // delete(annotations, k)
460
+ // }
461
+ // }
462
+ if len (annotations ) == 0 {
463
+ meta .Annotations = nil
464
+ } else {
465
+ meta .Annotations = annotations
466
+ }
467
+ // }
468
+ }
469
+
470
+ // CleanStatefulSet removes server-side fields from a StatefulSet
471
+ func CleanStatefulSet (statefulset * appsv1.StatefulSet ) {
472
+ // Remove status
473
+ statefulset .Status = appsv1.StatefulSetStatus {}
474
+
475
+ // Clean metadata
476
+ CleanMetadata (& statefulset .ObjectMeta )
477
+
478
+ // Clean template metadata but preserve essential fields
479
+ CleanMetadata (& statefulset .Spec .Template .ObjectMeta )
480
+
481
+ // Set API version and kind for valid Kubernetes manifests
482
+ statefulset .APIVersion = "apps/v1"
483
+ statefulset .Kind = "StatefulSet"
484
+
485
+ // Ensure selector is preserved (it's required for statefulsets)
486
+ if statefulset .Spec .Selector == nil || len (statefulset .Spec .Selector .MatchLabels ) == 0 {
487
+ // If no selector, create one that matches template labels
488
+ if statefulset .Spec .Template .Labels != nil && len (statefulset .Spec .Template .Labels ) > 0 {
489
+ if statefulset .Spec .Selector == nil {
490
+ statefulset .Spec .Selector = & metav1.LabelSelector {}
491
+ }
492
+ statefulset .Spec .Selector .MatchLabels = statefulset .Spec .Template .Labels
493
+ }
494
+ }
495
+ }
496
+
497
+ // CleanDaemonSet removes server-side fields from a DaemonSet
498
+ func CleanDaemonSet (daemonset * appsv1.DaemonSet ) {
499
+ // Remove status
500
+ daemonset .Status = appsv1.DaemonSetStatus {}
501
+
502
+ // Clean metadata
503
+ CleanMetadata (& daemonset .ObjectMeta )
504
+
505
+ // Clean template metadata but preserve essential fields
506
+ CleanMetadata (& daemonset .Spec .Template .ObjectMeta )
507
+
508
+ // Set API version and kind for valid Kubernetes manifests
509
+ daemonset .APIVersion = "apps/v1"
510
+ daemonset .Kind = "DaemonSet"
511
+
512
+ // Ensure selector is preserved (it's required for daemonsets)
513
+ if daemonset .Spec .Selector == nil || len (daemonset .Spec .Selector .MatchLabels ) == 0 {
514
+ // If no selector, create one that matches template labels
515
+ if daemonset .Spec .Template .Labels != nil && len (daemonset .Spec .Template .Labels ) > 0 {
516
+ if daemonset .Spec .Selector == nil {
517
+ daemonset .Spec .Selector = & metav1.LabelSelector {}
419
518
}
519
+ daemonset .Spec .Selector .MatchLabels = daemonset .Spec .Template .Labels
420
520
}
421
- if len (annotations ) == 0 {
422
- meta .Annotations = nil
423
- } else {
424
- meta .Annotations = annotations
521
+ }
522
+ }
523
+
524
+ // CleanReplicaSet removes server-side fields from a ReplicaSet
525
+ func CleanReplicaSet (replicaset * appsv1.ReplicaSet ) {
526
+ // Remove status
527
+ replicaset .Status = appsv1.ReplicaSetStatus {}
528
+
529
+ // Clean metadata
530
+ CleanMetadata (& replicaset .ObjectMeta )
531
+
532
+ // Clean template metadata but preserve essential fields
533
+ CleanMetadata (& replicaset .Spec .Template .ObjectMeta )
534
+
535
+ // Set API version and kind for valid Kubernetes manifests
536
+ replicaset .APIVersion = "apps/v1"
537
+ replicaset .Kind = "ReplicaSet"
538
+
539
+ // Ensure selector is preserved (it's required for replicasets)
540
+ if replicaset .Spec .Selector == nil || len (replicaset .Spec .Selector .MatchLabels ) == 0 {
541
+ // If no selector, create one that matches template labels
542
+ if replicaset .Spec .Template .Labels != nil && len (replicaset .Spec .Template .Labels ) > 0 {
543
+ if replicaset .Spec .Selector == nil {
544
+ replicaset .Spec .Selector = & metav1.LabelSelector {}
545
+ }
546
+ replicaset .Spec .Selector .MatchLabels = replicaset .Spec .Template .Labels
425
547
}
426
548
}
427
549
}
550
+
551
+ // CleanJob removes server-side fields from a Job
552
+ func CleanJob (job * batchv1.Job ) {
553
+ // Remove status
554
+ job .Status = batchv1.JobStatus {}
555
+
556
+ // Clean metadata
557
+ CleanMetadata (& job .ObjectMeta )
558
+
559
+ // Clean template metadata but preserve essential fields
560
+ CleanMetadata (& job .Spec .Template .ObjectMeta )
561
+
562
+ // Set API version and kind for valid Kubernetes manifests
563
+ job .APIVersion = "batch/v1"
564
+ job .Kind = "Job"
565
+
566
+ // Reset fields that are typically server-assigned
567
+ job .Spec .Selector = nil // Selector is automatically generated for Jobs
568
+ }
569
+
570
+ // CleanCronJob removes server-side fields from a CronJob
571
+ func CleanCronJob (cronjob * batchv1.CronJob ) {
572
+ // Remove status
573
+ cronjob .Status = batchv1.CronJobStatus {}
574
+
575
+ // Clean metadata
576
+ CleanMetadata (& cronjob .ObjectMeta )
577
+
578
+ // Clean template metadata but preserve essential fields
579
+ CleanMetadata (& cronjob .Spec .JobTemplate .ObjectMeta )
580
+ CleanMetadata (& cronjob .Spec .JobTemplate .Spec .Template .ObjectMeta )
581
+
582
+ // Set API version and kind for valid Kubernetes manifests
583
+ cronjob .APIVersion = "batch/v1"
584
+ cronjob .Kind = "CronJob"
585
+
586
+ // Reset fields that are typically server-assigned
587
+ cronjob .Spec .JobTemplate .Spec .Selector = nil // Selector is automatically generated for Jobs
588
+ }
589
+
590
+ // CleanIngress removes server-side fields from an Ingress
591
+ func CleanIngress (ingress * networkingv1.Ingress ) {
592
+ // Remove status
593
+ ingress .Status = networkingv1.IngressStatus {}
594
+
595
+ // Clean metadata
596
+ CleanMetadata (& ingress .ObjectMeta )
597
+
598
+ // Set API version and kind for valid Kubernetes manifests
599
+ ingress .APIVersion = "networking.k8s.io/v1"
600
+ ingress .Kind = "Ingress"
601
+ }
602
+
603
+ // CleanPDB removes server-side fields from a PodDisruptionBudget
604
+ func CleanPDB (pdb * policyv1.PodDisruptionBudget ) {
605
+ // Remove status
606
+ pdb .Status = policyv1.PodDisruptionBudgetStatus {}
607
+
608
+ // Clean metadata
609
+ CleanMetadata (& pdb .ObjectMeta )
610
+
611
+ // Set API version and kind for valid Kubernetes manifests
612
+ pdb .APIVersion = "policy/v1"
613
+ pdb .Kind = "PodDisruptionBudget"
614
+ }
615
+
616
+ // CleanRole removes server-side fields from a Role
617
+ func CleanRole (role * rbacv1.Role ) {
618
+ // Clean metadata
619
+ CleanMetadata (& role .ObjectMeta )
620
+
621
+ // Set API version and kind for valid Kubernetes manifests
622
+ role .APIVersion = "rbac.authorization.k8s.io/v1"
623
+ role .Kind = "Role"
624
+ }
625
+
626
+ // CleanClusterRole removes server-side fields from a ClusterRole
627
+ func CleanClusterRole (clusterRole * rbacv1.ClusterRole ) {
628
+ // Clean metadata
629
+ CleanMetadata (& clusterRole .ObjectMeta )
630
+
631
+ // Set API version and kind for valid Kubernetes manifests
632
+ clusterRole .APIVersion = "rbac.authorization.k8s.io/v1"
633
+ clusterRole .Kind = "ClusterRole"
634
+ }
635
+
636
+ // CleanRoleBinding removes server-side fields from a RoleBinding
637
+ func CleanRoleBinding (roleBinding * rbacv1.RoleBinding ) {
638
+ // Clean metadata
639
+ CleanMetadata (& roleBinding .ObjectMeta )
640
+
641
+ // Set API version and kind for valid Kubernetes manifests
642
+ roleBinding .APIVersion = "rbac.authorization.k8s.io/v1"
643
+ roleBinding .Kind = "RoleBinding"
644
+ }
645
+
646
+ // CleanClusterRoleBinding removes server-side fields from a ClusterRoleBinding
647
+ func CleanClusterRoleBinding (clusterRoleBinding * rbacv1.ClusterRoleBinding ) {
648
+ // Clean metadata
649
+ CleanMetadata (& clusterRoleBinding .ObjectMeta )
650
+
651
+ // Set API version and kind for valid Kubernetes manifests
652
+ clusterRoleBinding .APIVersion = "rbac.authorization.k8s.io/v1"
653
+ clusterRoleBinding .Kind = "ClusterRoleBinding"
654
+ }
0 commit comments