-
Notifications
You must be signed in to change notification settings - Fork 99
/
finalizer.go
147 lines (120 loc) · 5.12 KB
/
finalizer.go
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
package datadogagent
import (
"context"
datadoghqv1alpha1 "github.com/DataDog/datadog-operator/apis/datadoghq/v1alpha1"
datadoghqv2alpha1 "github.com/DataDog/datadog-operator/apis/datadoghq/v2alpha1"
"github.com/DataDog/datadog-operator/controllers/datadogagent/dependencies"
"github.com/DataDog/datadog-operator/controllers/datadogagent/feature"
"github.com/DataDog/datadog-operator/controllers/datadogagent/override"
"github.com/DataDog/datadog-operator/pkg/controller/utils"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"github.com/go-logr/logr"
)
const (
datadogAgentFinalizer = "finalizer.agent.datadoghq.com"
)
type finalizerDadFunc func(reqLogger logr.Logger, dda client.Object)
func (r *Reconciler) handleFinalizer(reqLogger logr.Logger, dda client.Object, finalizerDad finalizerDadFunc) (reconcile.Result, error) {
// Check if the DatadogAgent instance is marked to be deleted, which is
// indicated by the deletion timestamp being set.
isDadMarkedToBeDeleted := dda.GetDeletionTimestamp() != nil
if isDadMarkedToBeDeleted {
if utils.ContainsString(dda.GetFinalizers(), datadogAgentFinalizer) {
// Run finalization logic for datadogAgentFinalizer. If the
// finalization logic fails, don't remove the finalizer so
// that we can retry during the next reconciliation.
finalizerDad(reqLogger, dda)
// Remove datadogAgentFinalizer. Once all finalizers have been
// removed, the object will be deleted.
dda.SetFinalizers(utils.RemoveString(dda.GetFinalizers(), datadogAgentFinalizer))
err := r.client.Update(context.TODO(), dda)
if err != nil {
return reconcile.Result{}, err
}
}
return reconcile.Result{Requeue: true}, nil
}
// Add finalizer for this CR
if !utils.ContainsString(dda.GetFinalizers(), datadogAgentFinalizer) {
if err := r.addFinalizer(reqLogger, dda); err != nil {
return reconcile.Result{}, err
}
return reconcile.Result{Requeue: true}, nil
}
return reconcile.Result{}, nil
}
func (r *Reconciler) finalizeDadV1(reqLogger logr.Logger, obj client.Object) {
dda := obj.(*datadoghqv1alpha1.DatadogAgent)
_, err := r.cleanupMetricsServerAPIService(reqLogger, dda)
if err != nil {
reqLogger.Error(err, "Could not delete Metrics Server API Service")
}
for _, rbacName := range rbacNamesForDda(dda, r.versionInfo) {
if _, err = r.cleanupClusterRoleBinding(reqLogger, dda, rbacName); err != nil {
reqLogger.Error(err, "Could not delete cluster role binding", "name", rbacName)
}
if _, err = r.cleanupClusterRole(reqLogger, dda, rbacName); err != nil {
reqLogger.Error(err, "Could not delete cluster role", "name", rbacName)
}
}
r.forwarders.Unregister(dda)
reqLogger.Info("Successfully finalized DatadogAgent")
}
func (r *Reconciler) finalizeDadV2(reqLogger logr.Logger, obj client.Object) {
// We need to apply the defaults to be able to delete the resources
// associated with those defaults.
dda := obj.(*datadoghqv2alpha1.DatadogAgent).DeepCopy()
datadoghqv2alpha1.DefaultDatadogAgent(dda)
if r.options.OperatorMetricsEnabled {
r.forwarders.Unregister(dda)
}
// To delete the resources associated with the DatadogAgent that we need to
// delete, we figure out its dependencies, store them in the dependencies
// store, and then call the DeleteAll function of the store.
features, requiredComponents := feature.BuildFeatures(
dda, reconcilerOptionsToFeatureOptions(&r.options, reqLogger))
storeOptions := &dependencies.StoreOptions{
SupportCilium: r.options.SupportCilium,
Logger: reqLogger,
Scheme: r.scheme,
PlatformInfo: r.platformInfo,
}
depsStore := dependencies.NewStore(dda, storeOptions)
resourceManagers := feature.NewResourceManagers(depsStore)
var errs []error
// Set up dependencies required by enabled features
for _, feat := range features {
if featErr := feat.ManageDependencies(resourceManagers, requiredComponents); featErr != nil {
errs = append(errs, featErr)
}
}
// Examine user configuration to override any external dependencies (e.g. RBACs)
errs = append(errs, override.Dependencies(reqLogger, resourceManagers, dda)...)
if len(errs) > 0 {
reqLogger.Info("Errors calculating dependencies while finalizing the DatadogAgent", "errors", errs)
}
deleteErrs := depsStore.DeleteAll(context.TODO(), r.client)
if len(deleteErrs) == 0 {
reqLogger.Info("Successfully finalized DatadogAgent")
} else {
for _, deleteErr := range deleteErrs {
reqLogger.Error(deleteErr, "Error deleting dependencies while finalizing the DatadogAgent")
}
}
}
func (r *Reconciler) addFinalizer(reqLogger logr.Logger, dda client.Object) error {
reqLogger.Info("Adding Finalizer for the DatadogAgent")
dda.SetFinalizers(append(dda.GetFinalizers(), datadogAgentFinalizer))
// Update CR
err := r.client.Update(context.TODO(), dda)
if err != nil {
reqLogger.Error(err, "Failed to update DatadogAgent with finalizer")
return err
}
return nil
}