@@ -21,7 +21,6 @@ import (
21
21
"fmt"
22
22
"io"
23
23
"net/http"
24
- "strings"
25
24
"time"
26
25
27
26
"github.com/jonboulle/clockwork"
@@ -282,6 +281,13 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
282
281
return err
283
282
}
284
283
284
+ if o .Prune {
285
+ o .PruneResources , err = parsePruneResources (o .Mapper , o .PruneWhitelist )
286
+ if err != nil {
287
+ return err
288
+ }
289
+ }
290
+
285
291
return nil
286
292
}
287
293
@@ -302,37 +308,6 @@ func validatePruneAll(prune, all bool, selector string) error {
302
308
return nil
303
309
}
304
310
305
- func parsePruneResources (mapper meta.RESTMapper , gvks []string ) ([]pruneResource , error ) {
306
- pruneResources := []pruneResource {}
307
- for _ , groupVersionKind := range gvks {
308
- gvk := strings .Split (groupVersionKind , "/" )
309
- if len (gvk ) != 3 {
310
- return nil , fmt .Errorf ("invalid GroupVersionKind format: %v, please follow <group/version/kind>" , groupVersionKind )
311
- }
312
-
313
- if gvk [0 ] == "core" {
314
- gvk [0 ] = ""
315
- }
316
- mapping , err := mapper .RESTMapping (schema.GroupKind {Group : gvk [0 ], Kind : gvk [2 ]}, gvk [1 ])
317
- if err != nil {
318
- return pruneResources , err
319
- }
320
- var namespaced bool
321
- namespaceScope := mapping .Scope .Name ()
322
- switch namespaceScope {
323
- case meta .RESTScopeNameNamespace :
324
- namespaced = true
325
- case meta .RESTScopeNameRoot :
326
- namespaced = false
327
- default :
328
- return pruneResources , fmt .Errorf ("Unknown namespace scope: %q" , namespaceScope )
329
- }
330
-
331
- pruneResources = append (pruneResources , pruneResource {gvk [0 ], gvk [1 ], gvk [2 ], namespaced })
332
- }
333
- return pruneResources , nil
334
- }
335
-
336
311
func isIncompatibleServerError (err error ) bool {
337
312
// 415: Unsupported media type means we're talking to a server which doesn't
338
313
// support server-side apply.
@@ -387,14 +362,6 @@ func (o *ApplyOptions) Run() error {
387
362
OpenAPIGetter : o .DiscoveryClient ,
388
363
}
389
364
390
- var err error
391
- if o .Prune {
392
- o .PruneResources , err = parsePruneResources (o .Mapper , o .PruneWhitelist )
393
- if err != nil {
394
- return err
395
- }
396
- }
397
-
398
365
visitedUids := sets .NewString ()
399
366
visitedNamespaces := sets .NewString ()
400
367
@@ -606,46 +573,9 @@ See http://k8s.io/docs/reference/using-api/api-concepts/#conflicts`, err)
606
573
return err
607
574
}
608
575
609
- if ! o .Prune {
610
- return nil
611
- }
612
-
613
- p := pruner {
614
- mapper : o .Mapper ,
615
- dynamicClient : o .DynamicClient ,
616
-
617
- labelSelector : o .Selector ,
618
- visitedUids : visitedUids ,
619
-
620
- cascade : o .DeleteOptions .Cascade ,
621
- dryRun : o .DryRun ,
622
- serverDryRun : o .ServerDryRun ,
623
- gracePeriod : o .DeleteOptions .GracePeriod ,
624
-
625
- toPrinter : o .ToPrinter ,
626
-
627
- out : o .Out ,
628
- }
629
-
630
- namespacedRESTMappings , nonNamespacedRESTMappings , err := getRESTMappings (o .Mapper , & (o .PruneResources ))
631
- if err != nil {
632
- return fmt .Errorf ("error retrieving RESTMappings to prune: %v" , err )
633
- }
634
-
635
- for n := range visitedNamespaces {
636
- if len (o .Namespace ) != 0 && n != o .Namespace {
637
- continue
638
- }
639
- for _ , m := range namespacedRESTMappings {
640
- if err := p .prune (n , m ); err != nil {
641
- return fmt .Errorf ("error pruning namespaced object %v: %v" , m .GroupVersionKind , err )
642
- }
643
- }
644
- }
645
- for _ , m := range nonNamespacedRESTMappings {
646
- if err := p .prune (metav1 .NamespaceNone , m ); err != nil {
647
- return fmt .Errorf ("error pruning nonNamespaced object %v: %v" , m .GroupVersionKind , err )
648
- }
576
+ if o .Prune {
577
+ p := newPruner (o , visitedUids , visitedNamespaces )
578
+ return p .pruneAll (o )
649
579
}
650
580
651
581
return nil
@@ -706,140 +636,6 @@ func (o *ApplyOptions) printObjects() error {
706
636
return nil
707
637
}
708
638
709
- type pruneResource struct {
710
- group string
711
- version string
712
- kind string
713
- namespaced bool
714
- }
715
-
716
- func (pr pruneResource ) String () string {
717
- return fmt .Sprintf ("%v/%v, Kind=%v, Namespaced=%v" , pr .group , pr .version , pr .kind , pr .namespaced )
718
- }
719
-
720
- func getRESTMappings (mapper meta.RESTMapper , pruneResources * []pruneResource ) (namespaced , nonNamespaced []* meta.RESTMapping , err error ) {
721
- if len (* pruneResources ) == 0 {
722
- // default whitelist
723
- // TODO: need to handle the older api versions - e.g. v1beta1 jobs. Github issue: #35991
724
- * pruneResources = []pruneResource {
725
- {"" , "v1" , "ConfigMap" , true },
726
- {"" , "v1" , "Endpoints" , true },
727
- {"" , "v1" , "Namespace" , false },
728
- {"" , "v1" , "PersistentVolumeClaim" , true },
729
- {"" , "v1" , "PersistentVolume" , false },
730
- {"" , "v1" , "Pod" , true },
731
- {"" , "v1" , "ReplicationController" , true },
732
- {"" , "v1" , "Secret" , true },
733
- {"" , "v1" , "Service" , true },
734
- {"batch" , "v1" , "Job" , true },
735
- {"batch" , "v1beta1" , "CronJob" , true },
736
- {"extensions" , "v1beta1" , "Ingress" , true },
737
- {"apps" , "v1" , "DaemonSet" , true },
738
- {"apps" , "v1" , "Deployment" , true },
739
- {"apps" , "v1" , "ReplicaSet" , true },
740
- {"apps" , "v1" , "StatefulSet" , true },
741
- }
742
- }
743
-
744
- for _ , resource := range * pruneResources {
745
- addedMapping , err := mapper .RESTMapping (schema.GroupKind {Group : resource .group , Kind : resource .kind }, resource .version )
746
- if err != nil {
747
- return nil , nil , fmt .Errorf ("invalid resource %v: %v" , resource , err )
748
- }
749
- if resource .namespaced {
750
- namespaced = append (namespaced , addedMapping )
751
- } else {
752
- nonNamespaced = append (nonNamespaced , addedMapping )
753
- }
754
- }
755
-
756
- return namespaced , nonNamespaced , nil
757
- }
758
-
759
- type pruner struct {
760
- mapper meta.RESTMapper
761
- dynamicClient dynamic.Interface
762
-
763
- visitedUids sets.String
764
- labelSelector string
765
- fieldSelector string
766
-
767
- cascade bool
768
- serverDryRun bool
769
- dryRun bool
770
- gracePeriod int
771
-
772
- toPrinter func (string ) (printers.ResourcePrinter , error )
773
-
774
- out io.Writer
775
- }
776
-
777
- func (p * pruner ) prune (namespace string , mapping * meta.RESTMapping ) error {
778
- objList , err := p .dynamicClient .Resource (mapping .Resource ).
779
- Namespace (namespace ).
780
- List (metav1.ListOptions {
781
- LabelSelector : p .labelSelector ,
782
- FieldSelector : p .fieldSelector ,
783
- })
784
- if err != nil {
785
- return err
786
- }
787
-
788
- objs , err := meta .ExtractList (objList )
789
- if err != nil {
790
- return err
791
- }
792
-
793
- for _ , obj := range objs {
794
- metadata , err := meta .Accessor (obj )
795
- if err != nil {
796
- return err
797
- }
798
- annots := metadata .GetAnnotations ()
799
- if _ , ok := annots [corev1 .LastAppliedConfigAnnotation ]; ! ok {
800
- // don't prune resources not created with apply
801
- continue
802
- }
803
- uid := metadata .GetUID ()
804
- if p .visitedUids .Has (string (uid )) {
805
- continue
806
- }
807
- name := metadata .GetName ()
808
- if ! p .dryRun {
809
- if err := p .delete (namespace , name , mapping ); err != nil {
810
- return err
811
- }
812
- }
813
-
814
- printer , err := p .toPrinter ("pruned" )
815
- if err != nil {
816
- return err
817
- }
818
- printer .PrintObj (obj , p .out )
819
- }
820
- return nil
821
- }
822
-
823
- func (p * pruner ) delete (namespace , name string , mapping * meta.RESTMapping ) error {
824
- return runDelete (namespace , name , mapping , p .dynamicClient , p .cascade , p .gracePeriod , p .serverDryRun )
825
- }
826
-
827
- func runDelete (namespace , name string , mapping * meta.RESTMapping , c dynamic.Interface , cascade bool , gracePeriod int , serverDryRun bool ) error {
828
- options := & metav1.DeleteOptions {}
829
- if gracePeriod >= 0 {
830
- options = metav1 .NewDeleteOptions (int64 (gracePeriod ))
831
- }
832
- if serverDryRun {
833
- options .DryRun = []string {metav1 .DryRunAll }
834
- }
835
- policy := metav1 .DeletePropagationForeground
836
- if ! cascade {
837
- policy = metav1 .DeletePropagationOrphan
838
- }
839
- options .PropagationPolicy = & policy
840
- return c .Resource (mapping .Resource ).Namespace (namespace ).Delete (name , options )
841
- }
842
-
843
639
func (p * Patcher ) delete (namespace , name string ) error {
844
640
return runDelete (namespace , name , p .Mapping , p .DynamicClient , p .Cascade , p .GracePeriod , p .ServerDryRun )
845
641
}
0 commit comments