-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NETOBSERV-1314: cleanup old objects after upgrade (#427)
* NETOBSERV-1314: cleanup old objects after upgrade * Deleting old objects: make sure we only delete owned objects Add more tests Also fixes an issue with the kube client mock assertions: some assertions on function calls didn't have the intended effect when used with the wrong number of arguments
- Loading branch information
Showing
7 changed files
with
236 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package cleanup | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/netobserv/network-observability-operator/pkg/helper" | ||
corev1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/log" | ||
) | ||
|
||
var ( | ||
// Add to this list any object that we used to generate in past versions, and stopped doing so. | ||
// For instance, with any object that was renamed between two releases of the operator: | ||
// The old version with a different name could therefor remain on the cluster after an upgrade. | ||
cleanupList = []cleanupItem{ | ||
{ | ||
// Old name of NetObserv grafana dashboard / configmap (noo 1.3) | ||
ref: client.ObjectKey{Name: "grafana-dashboard-netobserv", Namespace: "openshift-config-managed"}, | ||
placeholder: &corev1.ConfigMap{}, | ||
}, | ||
} | ||
// Need to run only once, at operator startup, this is not part of the reconcile loop | ||
didRun = false | ||
) | ||
|
||
type cleanupItem struct { | ||
ref client.ObjectKey | ||
placeholder client.Object | ||
} | ||
|
||
func CleanPastReferences(ctx context.Context, cl client.Client, defaultNamespace string) error { | ||
if didRun { | ||
return nil | ||
} | ||
log := log.FromContext(ctx) | ||
log.Info("Check and clean old objects") | ||
// Search for all past references to clean up. If one is found, delete it. | ||
for _, item := range cleanupList { | ||
if item.ref.Namespace == "" { | ||
item.ref.Namespace = defaultNamespace | ||
} | ||
if err := cl.Get(ctx, item.ref, item.placeholder); err != nil { | ||
if errors.IsNotFound(err) { | ||
continue | ||
} | ||
return err | ||
} | ||
// Make sure we own that object | ||
if helper.IsOwned(item.placeholder) { | ||
log. | ||
WithValues("name", item.ref.Name). | ||
WithValues("namespace", item.ref.Namespace). | ||
Info("Deleting old object") | ||
if err := cl.Delete(ctx, item.placeholder); err != nil { | ||
return err | ||
} | ||
} else { | ||
log. | ||
WithValues("name", item.ref.Name). | ||
WithValues("namespace", item.ref.Namespace). | ||
Info("An object was found, but we don't own it - skip deletion") | ||
} | ||
} | ||
didRun = true | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package cleanup | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/netobserv/network-observability-operator/pkg/test" | ||
"github.com/stretchr/testify/assert" | ||
corev1 "k8s.io/api/core/v1" | ||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
"k8s.io/utils/pointer" | ||
) | ||
|
||
var oldDashboard = corev1.ConfigMap{ | ||
ObjectMeta: v1.ObjectMeta{ | ||
Name: "grafana-dashboard-netobserv", | ||
Namespace: "openshift-config-managed", | ||
OwnerReferences: []v1.OwnerReference{{ | ||
APIVersion: "flows.netobserv.io/v1beta1", | ||
Kind: "FlowCollector", | ||
Name: "cluster", | ||
Controller: pointer.Bool(true), | ||
}}, | ||
}, | ||
Data: map[string]string{}, | ||
} | ||
|
||
func TestCleanPastReferences(t *testing.T) { | ||
assert := assert.New(t) | ||
clientMock := test.ClientMock{} | ||
clientMock.MockConfigMap(&oldDashboard) | ||
assert.Equal(1, clientMock.Len()) | ||
didRun = false | ||
|
||
err := CleanPastReferences(context.Background(), &clientMock, "netobserv") | ||
assert.NoError(err) | ||
clientMock.AssertGetCalledWith(t, types.NamespacedName{Name: "grafana-dashboard-netobserv", Namespace: "openshift-config-managed"}) | ||
clientMock.AssertDeleteCalled(t) | ||
assert.Equal(0, clientMock.Len()) | ||
} | ||
|
||
func TestCleanPastReferences_Empty(t *testing.T) { | ||
assert := assert.New(t) | ||
clientMock := test.ClientMock{} | ||
clientMock.MockNonExisting(types.NamespacedName{Name: "grafana-dashboard-netobserv", Namespace: "openshift-config-managed"}) | ||
assert.Equal(0, clientMock.Len()) | ||
didRun = false | ||
|
||
err := CleanPastReferences(context.Background(), &clientMock, "netobserv") | ||
assert.NoError(err) | ||
clientMock.AssertGetCalledWith(t, types.NamespacedName{Name: "grafana-dashboard-netobserv", Namespace: "openshift-config-managed"}) | ||
clientMock.AssertDeleteNotCalled(t) | ||
} | ||
|
||
func TestCleanPastReferences_NotManaged(t *testing.T) { | ||
assert := assert.New(t) | ||
clientMock := test.ClientMock{} | ||
unmanaged := oldDashboard | ||
unmanaged.OwnerReferences = nil | ||
clientMock.MockConfigMap(&unmanaged) | ||
assert.Equal(1, clientMock.Len()) | ||
didRun = false | ||
|
||
err := CleanPastReferences(context.Background(), &clientMock, "netobserv") | ||
assert.NoError(err) | ||
clientMock.AssertGetCalledWith(t, types.NamespacedName{Name: "grafana-dashboard-netobserv", Namespace: "openshift-config-managed"}) | ||
clientMock.AssertDeleteNotCalled(t) | ||
assert.Equal(1, clientMock.Len()) | ||
} | ||
|
||
func TestCleanPastReferences_DifferentOwner(t *testing.T) { | ||
assert := assert.New(t) | ||
clientMock := test.ClientMock{} | ||
unmanaged := oldDashboard | ||
unmanaged.OwnerReferences = []v1.OwnerReference{{ | ||
APIVersion: "something/v1beta1", | ||
Kind: "SomethingElse", | ||
Name: "SomethingElse", | ||
}} | ||
clientMock.MockConfigMap(&unmanaged) | ||
assert.Equal(1, clientMock.Len()) | ||
didRun = false | ||
|
||
err := CleanPastReferences(context.Background(), &clientMock, "netobserv") | ||
assert.NoError(err) | ||
clientMock.AssertGetCalledWith(t, types.NamespacedName{Name: "grafana-dashboard-netobserv", Namespace: "openshift-config-managed"}) | ||
clientMock.AssertDeleteNotCalled(t) | ||
assert.Equal(1, clientMock.Len()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters