forked from rancher/backup-restore-operator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprune.go
More file actions
120 lines (108 loc) · 3.94 KB
/
prune.go
File metadata and controls
120 lines (108 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package restore
import (
"path/filepath"
"strings"
"time"
v1 "github.com/rancher/backup-restore-operator/pkg/apis/resources.cattle.io/v1"
"github.com/rancher/backup-restore-operator/pkg/resourcesets"
"github.com/rancher/backup-restore-operator/pkg/util"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
apierrors "k8s.io/apimachinery/pkg/api/errors"
k8sv1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
k8sEncryptionconfig "k8s.io/apiserver/pkg/server/options/encryptionconfig"
"k8s.io/client-go/dynamic"
)
type pruneResourceInfo struct {
name string
namespace string
gvr schema.GroupVersionResource
}
func (h *handler) prune(resourceSelectors []v1.ResourceSelector, transformerMap k8sEncryptionconfig.StaticTransformers,
cr ObjectsFromBackupCR, deleteTimeout int) error {
var resourcesToDelete []pruneResourceInfo
rh := resourcesets.ResourceHandler{
DiscoveryClient: h.discoveryClient,
DynamicClient: h.dynamicClient,
TransformerMap: transformerMap,
}
if err := rh.GatherResources(h.ctx, resourceSelectors); err != nil {
return err
}
for gvResource, resObjects := range rh.GVResourceToObjects {
for _, resObj := range resObjects {
metadata := resObj.Object["metadata"].(map[string]interface{})
objName := metadata["name"].(string)
objNs, _ := metadata["namespace"].(string)
gv := gvResource.GroupVersion
resourcePath := gvResource.Name + "." + gv.Group + "#" + gv.Version
if gvResource.Namespaced {
resourcePath = filepath.Join(resourcePath, objNs)
}
resourceFilePath := filepath.Join(resourcePath, objName+".json")
logrus.Debugf("resourceFilePath: %v", resourceFilePath)
if !cr.resourcesFromBackup[resourceFilePath] {
logrus.Infof("Marking resource %v for deletion", strings.TrimSuffix(resourceFilePath, ".json"))
resourcesToDelete = append(resourcesToDelete, pruneResourceInfo{
name: objName,
namespace: objNs,
gvr: gv.WithResource(gvResource.Name),
})
}
}
}
return h.pruneClusterScopedResources(resourcesToDelete, deleteTimeout)
}
func (h *handler) pruneClusterScopedResources(resourcesToDelete []pruneResourceInfo, pruneTimeout int) error {
err := h.deleteResources(resourcesToDelete, false)
if err != nil {
// don't return this error, let the second call retry
logrus.Errorf("Error pruning resources: %v", err)
}
logrus.Infof("Will retry pruning resources by removing finalizers in %vs", pruneTimeout)
time.Sleep(time.Duration(pruneTimeout) * time.Second)
logrus.Infof("Retrying pruning resources by removing finalizers")
return h.deleteResources(resourcesToDelete, true)
}
func (h *handler) deleteResources(resourcesToDelete []pruneResourceInfo, removeFinalizers bool) error {
var errgrp errgroup.Group
resourceQueue := util.GetObjectQueue(resourcesToDelete, len(resourcesToDelete))
for w := 0; w < util.WorkerThreads; w++ {
errgrp.Go(func() error {
var errList []error
for res := range resourceQueue {
resource := res.(pruneResourceInfo)
var dr dynamic.ResourceInterface
dr = h.dynamicClient.Resource(resource.gvr)
if resource.namespace != "" {
dr = h.dynamicClient.Resource(resource.gvr).Namespace(resource.namespace)
}
if removeFinalizers {
obj, err := dr.Get(h.ctx, resource.name, k8sv1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) || apierrors.IsGone(err) {
continue
}
errList = append(errList, err)
continue
}
delete(obj.Object[metadataMapKey].(map[string]interface{}), "finalizers")
if _, err := dr.Update(h.ctx, obj, k8sv1.UpdateOptions{}); err != nil {
errList = append(errList, err)
continue
}
}
if err := dr.Delete(h.ctx, resource.name, k8sv1.DeleteOptions{}); err != nil {
if apierrors.IsNotFound(err) || apierrors.IsGone(err) {
continue
}
errList = append(errList, err)
}
}
return util.ErrList(errList)
})
}
close(resourceQueue)
return errgrp.Wait()
}