Repository: kubernetes-sigs/security-profiles-operator
Pull request #1258 (2022-10-24 23:07:50)

build(deps): bump github.com/stretchr/testify from 1.8.0 to 1.8.1
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.0 to 1.8.1.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/stretchr/testify/commit/b747d7c5f853d017ddbc5e623d026d7fc2770a58"><code>b747d7c</code></a> Bump github.com/stretchr/objx from 0.4.0 to 0.5.0 (<a href="https://github-redirect.dependabot.com/stretchr/testify/issues/1283">#1283</a>)</li>
<li>See full diff in <a href="https://github.com/stretchr/testify/compare/v1.8.0...v1.8.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/stretchr/testify&package-manager=go_modules&previous-version=1.8.0&new-version=1.8.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

k8s-ci-robot: @dependabot[bot]: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
k8s-ci-robot: Hi @dependabot[bot]. Thanks for your PR.

I'm waiting for a [kubernetes-sigs](https://github.com/orgs/kubernetes-sigs/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fsecurity-profiles-operator).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/1258#" title="Author self-approved">dependabot[bot]</a>*
**Once this PR has been reviewed and has the lgtm label**, please assign saschagrunert for approval by writing `/assign @saschagrunert` in a comment. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fsecurity-profiles-operator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/security-profiles-operator/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["saschagrunert"]} -->
codecov-commenter: # [Codecov](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/1258?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#1258](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/1258?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (ea68660) into [main](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/commit/29d1b6b018093dddf75f7f677378e27da0f97990?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (29d1b6b) will **not change** coverage.
> The diff coverage is `n/a`.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #1258   +/-   ##
=======================================
  Coverage   45.37%   45.37%           
=======================================
  Files          48       48           
  Lines        5366     5366           
=======================================
  Hits         2435     2435           
  Misses       2811     2811           
  Partials      120      120           
```

</details>

Patch:
diff --git a/bundle/manifests/security-profiles-operator.clusterserviceversion.yaml b/bundle/manifests/security-profiles-operator.clusterserviceversion.yaml
index 3ff229bf8..2bc089ca4 100644
--- a/bundle/manifests/security-profiles-operator.clusterserviceversion.yaml
+++ b/bundle/manifests/security-profiles-operator.clusterserviceversion.yaml
@@ -159,6 +159,14 @@ spec:
     spec:
       clusterPermissions:
       - rules:
+        - apiGroups:
+          - ""
+          resources:
+          - nodes
+          verbs:
+          - get
+          - list
+          - watch
         - apiGroups:
           - ""
           resources:
@@ -335,6 +343,7 @@ spec:
           resources:
           - securityprofilenodestatuses
           verbs:
+          - delete
           - get
           - list
           - watch
diff --git a/deploy/base/role.yaml b/deploy/base/role.yaml
index 28b377e0a..f26df8c1a 100644
--- a/deploy/base/role.yaml
+++ b/deploy/base/role.yaml
@@ -5,6 +5,14 @@ metadata:
   creationTimestamp: null
   name: security-profiles-operator
 rules:
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - get
+  - list
+  - watch
 - apiGroups:
   - ""
   resources:
@@ -181,6 +189,7 @@ rules:
   resources:
   - securityprofilenodestatuses
   verbs:
+  - delete
   - get
   - list
   - watch
diff --git a/deploy/helm/templates/static-resources.yaml b/deploy/helm/templates/static-resources.yaml
index dc6e35ff8..2e0ef7c7a 100644
--- a/deploy/helm/templates/static-resources.yaml
+++ b/deploy/helm/templates/static-resources.yaml
@@ -41,6 +41,14 @@ metadata:
     app: security-profiles-operator
   name: security-profiles-operator
 rules:
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - get
+  - list
+  - watch
 - apiGroups:
   - ""
   resources:
@@ -217,6 +225,7 @@ rules:
   resources:
   - securityprofilenodestatuses
   verbs:
+  - delete
   - get
   - list
   - watch
diff --git a/deploy/namespace-operator.yaml b/deploy/namespace-operator.yaml
index ab06e60af..ff31ccc43 100644
--- a/deploy/namespace-operator.yaml
+++ b/deploy/namespace-operator.yaml
@@ -2015,6 +2015,14 @@ metadata:
     app: security-profiles-operator
   name: security-profiles-operator
 rules:
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - get
+  - list
+  - watch
 - apiGroups:
   - ""
   resources:
@@ -2191,6 +2199,7 @@ rules:
   resources:
   - securityprofilenodestatuses
   verbs:
+  - delete
   - get
   - list
   - watch
diff --git a/deploy/openshift-dev.yaml b/deploy/openshift-dev.yaml
index a8e136316..9c8ff07ef 100644
--- a/deploy/openshift-dev.yaml
+++ b/deploy/openshift-dev.yaml
@@ -2015,6 +2015,14 @@ metadata:
     app: security-profiles-operator
   name: security-profiles-operator
 rules:
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - get
+  - list
+  - watch
 - apiGroups:
   - ""
   resources:
@@ -2191,6 +2199,7 @@ rules:
   resources:
   - securityprofilenodestatuses
   verbs:
+  - delete
   - get
   - list
   - watch
diff --git a/deploy/operator.yaml b/deploy/operator.yaml
index 8c3c24334..fd76d6817 100644
--- a/deploy/operator.yaml
+++ b/deploy/operator.yaml
@@ -2015,6 +2015,14 @@ metadata:
     app: security-profiles-operator
   name: security-profiles-operator
 rules:
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - get
+  - list
+  - watch
 - apiGroups:
   - ""
   resources:
@@ -2191,6 +2199,7 @@ rules:
   resources:
   - securityprofilenodestatuses
   verbs:
+  - delete
   - get
   - list
   - watch
diff --git a/deploy/overlays/webhook/role.yaml b/deploy/overlays/webhook/role.yaml
index 97221506b..f5c1444a2 100644
--- a/deploy/overlays/webhook/role.yaml
+++ b/deploy/overlays/webhook/role.yaml
@@ -1,3 +1,3 @@
 ---
-- path: /rules/1
+- path: /rules/2
   op: remove
diff --git a/deploy/webhook-operator.yaml b/deploy/webhook-operator.yaml
index abe58c15d..adef0f16e 100644
--- a/deploy/webhook-operator.yaml
+++ b/deploy/webhook-operator.yaml
@@ -2087,6 +2087,14 @@ metadata:
     app: security-profiles-operator
   name: security-profiles-operator
 rules:
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - get
+  - list
+  - watch
 - apiGroups:
   - ""
   resources:
@@ -2252,6 +2260,7 @@ rules:
   resources:
   - securityprofilenodestatuses
   verbs:
+  - delete
   - get
   - list
   - watch
diff --git a/go.mod b/go.mod
index 426f1517e..476f1ac2f 100644
--- a/go.mod
+++ b/go.mod
@@ -20,7 +20,7 @@ require (
 	github.com/prometheus/client_golang v1.13.0
 	github.com/prometheus/client_model v0.3.0
 	github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921
-	github.com/stretchr/testify v1.8.0
+	github.com/stretchr/testify v1.8.1
 	github.com/urfave/cli/v2 v2.20.2
 	golang.org/x/net v0.0.0-20220909164309-bea034e7d591
 	golang.org/x/sync v0.0.0-20220907140024-f12130a52804
diff --git a/go.sum b/go.sum
index 348c207e8..ead81967b 100644
--- a/go.sum
+++ b/go.sum
@@ -1305,8 +1305,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
-github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -1317,8 +1318,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/sylabs/sif/v2 v2.7.0/go.mod h1:TiyBWsgWeh5yBeQFNuQnvROwswqK7YJT8JA1L53bsXQ=
 github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ=
diff --git a/internal/pkg/manager/nodestatus/nodestatus.go b/internal/pkg/manager/nodestatus/nodestatus.go
index af95f1969..447db98ba 100644
--- a/internal/pkg/manager/nodestatus/nodestatus.go
+++ b/internal/pkg/manager/nodestatus/nodestatus.go
@@ -27,6 +27,7 @@ import (
 	"github.com/crossplane/crossplane-runtime/pkg/event"
 	"github.com/go-logr/logr"
 	appsv1 "k8s.io/api/apps/v1"
+	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/selection"
@@ -98,7 +99,8 @@ func (r *StatusReconciler) Healthz(*http.Request) error {
 
 // Security Profiles Operator RBAC permissions to manage Node Statuses
 //nolint:lll // required for kubebuilder
-// +kubebuilder:rbac:groups=security-profiles-operator.x-k8s.io,resources=securityprofilenodestatuses,verbs=get;list;watch
+// +kubebuilder:rbac:groups=security-profiles-operator.x-k8s.io,resources=securityprofilenodestatuses,verbs=get;list;watch;delete
+// +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
 
 // Reconcile reconciles a NodeStatus.
 func (r *StatusReconciler) Reconcile(_ context.Context, req reconcile.Request) (reconcile.Result, error) {
@@ -167,11 +169,26 @@ func (r *StatusReconciler) Reconcile(_ context.Context, req reconcile.Request) (
 	// make sure we have all the statuses already
 	hasStatuses := len(nodeStatusList.Items)
 	wantsStatuses := spodDS.Status.DesiredNumberScheduled
-	if wantsStatuses != int32(hasStatuses) {
+	if wantsStatuses > int32(hasStatuses) {
 		logger.Info("Not updating policy: not all statuses are ready",
 			"has", hasStatuses, "wants", wantsStatuses)
 		// Don't reconcile again, let's just wait for another update
 		return reconcile.Result{}, nil
+	} else if wantsStatuses < int32(hasStatuses) {
+		// this happens when nodes are removed from the cluster
+		logger.Info("Removing extra statuses", "has", hasStatuses, "wants", wantsStatuses)
+		nodeName, err := r.removeStatusForDeletedNode(ctx, nodeStatusList, lprof)
+		if err != nil {
+			return reconcile.Result{}, fmt.Errorf("cannot remove extra statuses: %w", err)
+		}
+		if nodeName != "" {
+			// remove the deleted node finalizer string from the profile
+			logger.Info("Removing finalizer from profile", "profile", prof.GetName(), "node", nodeName)
+			if err := util.RemoveFinalizer(ctx, r.client, prof, util.GetFinalizerNodeString(nodeName)); err != nil {
+				return reconcile.Result{}, fmt.Errorf("cannot remove finalizer from profile: %w", err)
+			}
+		}
+		return reconcile.Result{Requeue: true}, nil
 	}
 
 	lowestCommonState := statusv1alpha1.LowestState
@@ -183,6 +200,27 @@ func (r *StatusReconciler) Reconcile(_ context.Context, req reconcile.Request) (
 	return r.reconcileStatus(ctx, prof, lowestCommonState, lprof)
 }
 
+// removeStatusForDeletedNode removes the status for a node that has been deleted.
+func (r *StatusReconciler) removeStatusForDeletedNode(ctx context.Context,
+	nodeStatusList *statusv1alpha1.SecurityProfileNodeStatusList, logger logr.Logger,
+) (string, error) {
+	for i := range nodeStatusList.Items {
+		nodeName := nodeStatusList.Items[i].NodeName
+		node := &v1.Node{}
+		if err := r.client.Get(ctx, types.NamespacedName{Name: nodeName}, node); err != nil {
+			if util.IsNotFoundOrConflict(err) {
+				logger.Info("Removing node status for removed node", "node", nodeName)
+				if err := r.client.Delete(ctx, &nodeStatusList.Items[i]); err != nil {
+					return "", fmt.Errorf("cannot delete node status: %w", err)
+				}
+				return nodeName, nil
+			}
+			return "", fmt.Errorf("cannot get node: %w", err)
+		}
+	}
+	return "", nil
+}
+
 func (r *StatusReconciler) getDS(ctx context.Context, namespace string, l logr.Logger) (*appsv1.DaemonSet, error) {
 	dsSelect := labels.NewSelector()
 	spodDSFilter, err := labels.NewRequirement("spod", selection.Exists, []string{})
diff --git a/internal/pkg/manager/recordingmerger/merge_utils.go b/internal/pkg/manager/recordingmerger/merge_utils.go
index 057279914..94fc89284 100644
--- a/internal/pkg/manager/recordingmerger/merge_utils.go
+++ b/internal/pkg/manager/recordingmerger/merge_utils.go
@@ -185,8 +185,19 @@ func addAllow(union, additional selinuxprofileapi.Allow) selinuxprofileapi.Allow
 		if _, ok := union[labelKey]; !ok {
 			union[labelKey] = make(map[selinuxprofileapi.ObjectClassKey]selinuxprofileapi.PermissionSet)
 		}
+
 		for objClass, perms := range permMap {
-			union[labelKey][objClass] = append(union[labelKey][objClass], perms...)
+			allPerms := map[string]bool{}
+			for _, havePerm := range union[labelKey][objClass] {
+				allPerms[havePerm] = true
+			}
+
+			for _, newPerm := range perms {
+				_, ok := allPerms[newPerm]
+				if !ok {
+					union[labelKey][objClass] = append(union[labelKey][objClass], newPerm)
+				}
+			}
 		}
 	}
 
diff --git a/internal/pkg/nodestatus/nodestatus.go b/internal/pkg/nodestatus/nodestatus.go
index 9acc15241..5c29da390 100644
--- a/internal/pkg/nodestatus/nodestatus.go
+++ b/internal/pkg/nodestatus/nodestatus.go
@@ -25,7 +25,6 @@ import (
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
-	"k8s.io/apimachinery/pkg/util/validation"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 
@@ -246,12 +245,7 @@ func getFinalizerString(pol profilebase.SecurityProfileBase, nodeName string) st
 	if pol.IsPartial() {
 		return partialProfileFinalizer
 	}
-
-	finalizerString := nodeName + "-deleted"
-	// Make sure the length of finalizer is not longer than 63 characters
-	if len(nodeName)+len("-deleted") > validation.DNS1123LabelMaxLength {
-		finalizerString = nodeName[:validation.DNS1123LabelMaxLength-len("-deleted")] + "-deleted"
-	}
+	finalizerString := util.GetFinalizerNodeString(nodeName)
 	return finalizerString
 }
 
diff --git a/internal/pkg/util/finalizers.go b/internal/pkg/util/finalizers.go
index 71e30000c..e8daba134 100644
--- a/internal/pkg/util/finalizers.go
+++ b/internal/pkg/util/finalizers.go
@@ -20,6 +20,7 @@ import (
 	"context"
 	"fmt"
 
+	"k8s.io/apimachinery/pkg/util/validation"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
 )
@@ -47,3 +48,13 @@ func RemoveFinalizer(ctx context.Context, c client.Client, pol client.Object, fi
 	controllerutil.RemoveFinalizer(pol, finalizer)
 	return c.Update(ctx, pol)
 }
+
+// GetFinalizerNodeString gets finalizer string from Node Name.
+func GetFinalizerNodeString(nodeName string) string {
+	finalizerString := nodeName + "-deleted"
+	// Make sure the length of finalizer is not longer than 63 characters
+	if len(nodeName)+len("-deleted") > validation.DNS1123LabelMaxLength {
+		finalizerString = nodeName[:validation.DNS1123LabelMaxLength-len("-deleted")] + "-deleted"
+	}
+	return finalizerString
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 694213763..79e0c8d5d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -561,7 +561,7 @@ github.com/spf13/cobra
 # github.com/spf13/pflag v1.0.5
 ## explicit; go 1.12
 github.com/spf13/pflag
-# github.com/stretchr/testify v1.8.0
+# github.com/stretchr/testify v1.8.1
 ## explicit; go 1.13
 github.com/stretchr/testify/assert
 github.com/stretchr/testify/require


Test patch:
diff --git a/internal/pkg/manager/recordingmerger/merge_utils_test.go b/internal/pkg/manager/recordingmerger/merge_utils_test.go
index f035dee17..cf8ac2276 100644
--- a/internal/pkg/manager/recordingmerger/merge_utils_test.go
+++ b/internal/pkg/manager/recordingmerger/merge_utils_test.go
@@ -153,7 +153,7 @@ func TestMergeProfiles(t *testing.T) {
 								},
 							},
 							Allow: selinuxprofileapi.Allow{
-								"label_foo": {"oc_bar2": {"do_bar2"}, "oc_baz2": {"do_baz2"}},
+								"label_foo": {"oc_bar": {"do_bar"}, "oc_bar2": {"do_bar2"}, "oc_baz2": {"do_baz2"}},
 								"label_aaa": {"oc_aaa": {"do_aaa"}, "oc_bbb": {"do_bbb"}},
 							},
 						},
diff --git a/test/tc_delete_profiles_test.go b/test/tc_delete_profiles_test.go
index 06408b56e..5b736f964 100644
--- a/test/tc_delete_profiles_test.go
+++ b/test/tc_delete_profiles_test.go
@@ -34,11 +34,27 @@ apiVersion: security-profiles-operator.x-k8s.io/v1beta1
 kind: SeccompProfile
 metadata:
   name: delete-me
+  finalizers: [fake-node-deleted]
 spec:
   defaultAction: "SCMP_ACT_ALLOW"
 `
-		deleteProfileName = "delete-me"
-		deletePod         = `
+		deleteProfileName  = "delete-me"
+		fakeNodeStatusName = "delete-me-fake-node"
+		fakeNodeStatus     = `
+apiVersion: security-profiles-operator.x-k8s.io/v1alpha1
+kind: SecurityProfileNodeStatus
+metadata:
+  name: delete-me-fake-node
+  labels:
+    spo.x-k8s.io/node-name: fake-node
+    spo.x-k8s.io/profile-id: SeccompProfile-delete-me
+    spo.x-k8s.io/profile-kind: SeccompProfile
+    spo.x-k8s.io/profile-state: Installed
+nodeName: fake-node
+spec: {}
+status: Installed
+`
+		deletePod = `
 apiVersion: v1
 kind: Pod
 metadata:
@@ -113,6 +129,9 @@ spec:
 	for _, node := range nodes {
 		e.execNode(node, "test", "-f", profileOperatorPath)
 	}
+	e.logf("Create fake node status for profile")
+	e.writeAndCreate(fakeNodeStatus, "fake-node-status*.yaml")
+	time.Sleep(time.Second)
 	e.logf("Verifying profile deleted")
 	e.kubectl("delete", "seccompprofile", deleteProfileName)
 	time.Sleep(time.Second)
@@ -146,6 +165,8 @@ spec:
 		profileCleanup := e.writeAndCreate(deleteProfile, "delete-profile*.yaml")
 		defer profileCleanup() //nolint:gocritic // TODO: is this intentional?
 		e.waitFor("condition=ready", "seccompprofile", deleteProfileName)
+		e.logf("Create fake node status for profile")
+		e.writeAndCreate(fakeNodeStatus, "fake-node-status*.yaml")
 		podCleanup := e.writeAndCreate(fmt.Sprintf(testCase.podManifest, namespace), "delete-pod*.yaml")
 		defer podCleanup() //nolint:gocritic // TODO: is this intention?
 		e.waitFor("condition=ready", "pod", deletePodName)