1
16
17 package apply
18
19 import (
20 "context"
21 "fmt"
22 "io"
23
24 corev1 "k8s.io/api/core/v1"
25 "k8s.io/apimachinery/pkg/api/meta"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/types"
28 "k8s.io/apimachinery/pkg/util/sets"
29 "k8s.io/cli-runtime/pkg/printers"
30 "k8s.io/client-go/dynamic"
31 cmdutil "k8s.io/kubectl/pkg/cmd/util"
32 "k8s.io/kubectl/pkg/util/prune"
33 )
34
35 type pruner struct {
36 mapper meta.RESTMapper
37 dynamicClient dynamic.Interface
38
39 visitedUids sets.Set[types.UID]
40 visitedNamespaces sets.Set[string]
41 labelSelector string
42 fieldSelector string
43
44 cascadingStrategy metav1.DeletionPropagation
45 dryRunStrategy cmdutil.DryRunStrategy
46 gracePeriod int
47
48 toPrinter func(string) (printers.ResourcePrinter, error)
49
50 out io.Writer
51 }
52
53 func newPruner(o *ApplyOptions) pruner {
54 return pruner{
55 mapper: o.Mapper,
56 dynamicClient: o.DynamicClient,
57
58 labelSelector: o.Selector,
59 visitedUids: o.VisitedUids,
60 visitedNamespaces: o.VisitedNamespaces,
61
62 cascadingStrategy: o.DeleteOptions.CascadingStrategy,
63 dryRunStrategy: o.DryRunStrategy,
64 gracePeriod: o.DeleteOptions.GracePeriod,
65
66 toPrinter: o.ToPrinter,
67
68 out: o.Out,
69 }
70 }
71
72 func (p *pruner) pruneAll(o *ApplyOptions) error {
73
74 namespacedRESTMappings, nonNamespacedRESTMappings, err := prune.GetRESTMappings(o.Mapper, o.PruneResources, o.Namespace != "")
75 if err != nil {
76 return fmt.Errorf("error retrieving RESTMappings to prune: %v", err)
77 }
78
79 for n := range p.visitedNamespaces {
80 for _, m := range namespacedRESTMappings {
81 if err := p.prune(n, m); err != nil {
82 return fmt.Errorf("error pruning namespaced object %v: %v", m.GroupVersionKind, err)
83 }
84 }
85 }
86
87 for _, m := range nonNamespacedRESTMappings {
88 if err := p.prune(metav1.NamespaceNone, m); err != nil {
89 return fmt.Errorf("error pruning nonNamespaced object %v: %v", m.GroupVersionKind, err)
90 }
91 }
92
93 return nil
94 }
95
96 func (p *pruner) prune(namespace string, mapping *meta.RESTMapping) error {
97 objList, err := p.dynamicClient.Resource(mapping.Resource).
98 Namespace(namespace).
99 List(context.TODO(), metav1.ListOptions{
100 LabelSelector: p.labelSelector,
101 FieldSelector: p.fieldSelector,
102 })
103 if err != nil {
104 return err
105 }
106
107 objs, err := meta.ExtractList(objList)
108 if err != nil {
109 return err
110 }
111
112 for _, obj := range objs {
113 metadata, err := meta.Accessor(obj)
114 if err != nil {
115 return err
116 }
117 annots := metadata.GetAnnotations()
118 if _, ok := annots[corev1.LastAppliedConfigAnnotation]; !ok {
119
120 continue
121 }
122 uid := metadata.GetUID()
123 if p.visitedUids.Has(uid) {
124 continue
125 }
126 name := metadata.GetName()
127 if p.dryRunStrategy != cmdutil.DryRunClient {
128 if err := p.delete(namespace, name, mapping); err != nil {
129 return err
130 }
131 }
132
133 printer, err := p.toPrinter("pruned")
134 if err != nil {
135 return err
136 }
137 printer.PrintObj(obj, p.out)
138 }
139 return nil
140 }
141
142 func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping) error {
143 ctx := context.TODO()
144 return runDelete(ctx, namespace, name, mapping, p.dynamicClient, p.cascadingStrategy, p.gracePeriod, p.dryRunStrategy == cmdutil.DryRunServer)
145 }
146
147 func runDelete(ctx context.Context, namespace, name string, mapping *meta.RESTMapping, c dynamic.Interface, cascadingStrategy metav1.DeletionPropagation, gracePeriod int, serverDryRun bool) error {
148 options := asDeleteOptions(cascadingStrategy, gracePeriod)
149 if serverDryRun {
150 options.DryRun = []string{metav1.DryRunAll}
151 }
152 return c.Resource(mapping.Resource).Namespace(namespace).Delete(ctx, name, options)
153 }
154
155 func asDeleteOptions(cascadingStrategy metav1.DeletionPropagation, gracePeriod int) metav1.DeleteOptions {
156 options := metav1.DeleteOptions{}
157 if gracePeriod >= 0 {
158 options = *metav1.NewDeleteOptions(int64(gracePeriod))
159 }
160 options.PropagationPolicy = &cascadingStrategy
161 return options
162 }
163
View as plain text