Skip to content

Commit 12c4ae4

Browse files
authored
NETOBSERV-1418: make namespace immutable (#1229)
* NETOBSERV-1418: make namespace immutable * remove unused functions
1 parent 762f37b commit 12c4ae4

19 files changed

+65
-331
lines changed

apis/flowcollector/v1beta1/flowcollector_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type FlowCollectorSpec struct {
4949

5050
// Namespace where NetObserv pods are deployed.
5151
// +kubebuilder:default:=netobserv
52+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Namespace is immutable. If you need to change it, delete and recreate the resource."
5253
Namespace string `json:"namespace,omitempty"`
5354

5455
// Agent configuration for flows extraction.

apis/flowcollector/v1beta2/flowcollector_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type FlowCollectorSpec struct {
4949

5050
// Namespace where NetObserv pods are deployed.
5151
// +kubebuilder:default:=netobserv
52+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Namespace is immutable. If you need to change it, delete and recreate the resource."
5253
Namespace string `json:"namespace,omitempty"`
5354

5455
// Agent configuration for flows extraction.

bundle/manifests/flows.netobserv.io_flowcollectors.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,10 @@ spec:
18351835
default: netobserv
18361836
description: Namespace where NetObserv pods are deployed.
18371837
type: string
1838+
x-kubernetes-validations:
1839+
- message: Namespace is immutable. If you need to change it, delete
1840+
and recreate the resource.
1841+
rule: self == oldSelf
18381842
processor:
18391843
description: |-
18401844
`processor` defines the settings of the component that receives the flows from the agent,
@@ -7066,6 +7070,10 @@ spec:
70667070
default: netobserv
70677071
description: Namespace where NetObserv pods are deployed.
70687072
type: string
7073+
x-kubernetes-validations:
7074+
- message: Namespace is immutable. If you need to change it, delete
7075+
and recreate the resource.
7076+
rule: self == oldSelf
70697077
networkPolicy:
70707078
description: '`networkPolicy` defines ingress network policy settings
70717079
for NetObserv components isolation.'

config/crd/bases/flows.netobserv.io_flowcollectors.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,9 @@ spec:
16571657
default: netobserv
16581658
description: Namespace where NetObserv pods are deployed.
16591659
type: string
1660+
x-kubernetes-validations:
1661+
- message: Namespace is immutable. If you need to change it, delete and recreate the resource.
1662+
rule: self == oldSelf
16601663
processor:
16611664
description: |-
16621665
`processor` defines the settings of the component that receives the flows from the agent,
@@ -6476,6 +6479,9 @@ spec:
64766479
default: netobserv
64776480
description: Namespace where NetObserv pods are deployed.
64786481
type: string
6482+
x-kubernetes-validations:
6483+
- message: Namespace is immutable. If you need to change it, delete and recreate the resource.
6484+
rule: self == oldSelf
64796485
networkPolicy:
64806486
description: '`networkPolicy` defines ingress network policy settings for NetObserv components isolation.'
64816487
properties:

controllers/consoleplugin/consoleplugin_reconciler.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,6 @@ func NewReconciler(cmn *reconcilers.Instance) CPReconciler {
5252
return rec
5353
}
5454

55-
// CleanupNamespace cleans up old namespace
56-
func (r *CPReconciler) CleanupNamespace(ctx context.Context) {
57-
r.Managed.CleanupPreviousNamespace(ctx)
58-
}
59-
6055
// Reconcile is the reconciler entry point to reconcile the current plugin state with the desired configuration
6156
func (r *CPReconciler) Reconcile(ctx context.Context, desired *flowslatest.FlowCollector) error {
6257
l := log.FromContext(ctx).WithName("console-plugin")

controllers/ebpf/agent_controller.go

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -145,30 +145,6 @@ func (c *AgentController) Reconcile(ctx context.Context, target *flowslatest.Flo
145145
return err
146146
}
147147

148-
if c.PreviousPrivilegedNamespace() != c.PrivilegedNamespace() {
149-
c.Managed.TryDeleteAll(ctx)
150-
151-
if current == nil {
152-
rlog.Info("nothing to do, namespace already cleaned up", "currentAgent", target.Spec.Agent)
153-
return nil
154-
}
155-
rlog.Info("namespace cleanup: deleting eBPF agent", "currentAgent", target.Spec.Agent)
156-
if helper.IsAgentFeatureEnabled(&target.Spec.Agent.EBPF, flowslatest.EbpfManager) {
157-
if err := c.bpfmanDetachNetobserv(ctx); err != nil {
158-
rlog.Error(err, "failed to delete bpfapplication object")
159-
// continue with eBPF agent deletion
160-
}
161-
}
162-
if err := c.Delete(ctx, current); err != nil {
163-
if errors.IsNotFound(err) {
164-
return nil
165-
}
166-
return fmt.Errorf("deleting eBPF agent: %w", err)
167-
}
168-
// Current now has been deleted. Set it to nil to that it triggers actionCreate if we are changing namespace
169-
current = nil
170-
}
171-
172148
if err := c.permissions.Reconcile(ctx, &target.Spec.Agent.EBPF); err != nil {
173149
return fmt.Errorf("reconciling permissions: %w", err)
174150
}
@@ -212,12 +188,12 @@ func (c *AgentController) current(ctx context.Context) (*v1.DaemonSet, error) {
212188
agentDS := v1.DaemonSet{}
213189
if err := c.Get(ctx, types.NamespacedName{
214190
Name: constants.EBPFAgentName,
215-
Namespace: c.PreviousPrivilegedNamespace(),
191+
Namespace: c.PrivilegedNamespace(),
216192
}, &agentDS); err != nil {
217193
if errors.IsNotFound(err) {
218194
return nil, nil
219195
}
220-
return nil, fmt.Errorf("can't read DaemonSet %s/%s: %w", c.PreviousPrivilegedNamespace(), constants.EBPFAgentName, err)
196+
return nil, fmt.Errorf("can't read DaemonSet %s/%s: %w", c.PrivilegedNamespace(), constants.EBPFAgentName, err)
221197
}
222198
return &agentDS, nil
223199
}

controllers/ebpf/bpfmanager-controller.go

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"github.com/sirupsen/logrus"
1414
"k8s.io/apimachinery/pkg/api/errors"
1515
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16-
"k8s.io/klog"
1716
"k8s.io/utils/ptr"
1817
"sigs.k8s.io/controller-runtime/pkg/client"
1918
)
@@ -22,31 +21,6 @@ const (
2221
netobservApp = "netobserv"
2322
)
2423

25-
// bpfmanDetachNetobserv find BpfmanApplication object with all required ebpf hooks and detaches them using bpfman manager
26-
func (c *AgentController) bpfmanDetachNetobserv(ctx context.Context) error {
27-
bpfApp := bpfmaniov1alpha1.ClusterBpfApplication{
28-
ObjectMeta: v1.ObjectMeta{
29-
Name: netobservApp,
30-
},
31-
TypeMeta: v1.TypeMeta{
32-
Kind: "BpfApplication",
33-
},
34-
}
35-
36-
key := client.ObjectKey{Name: netobservApp}
37-
38-
err := c.Get(ctx, key, &bpfApp)
39-
if err != nil {
40-
return fmt.Errorf("failed to get BpfApplication: %w", err)
41-
}
42-
43-
err = c.deleteBpfApplication(ctx, &bpfApp)
44-
if err != nil {
45-
return fmt.Errorf("failed to delete BpfApplication: %w", err)
46-
}
47-
return nil
48-
}
49-
5024
// bpfmanAttachNetobserv Creates BpfmanApplication object with all required ebpf hooks and attaches them using bpfman manager
5125
func (c *AgentController) bpfmanAttachNetobserv(ctx context.Context, fc *flowslatest.FlowCollector) error {
5226
var err error
@@ -254,11 +228,6 @@ func prepareBpfApplication(bpfApp *bpfmaniov1alpha1.ClusterBpfApplication, fc *f
254228
}
255229
}
256230

257-
func (c *AgentController) deleteBpfApplication(ctx context.Context, bpfApp *bpfmaniov1alpha1.ClusterBpfApplication) error {
258-
klog.Info("Deleting BpfApplication Object")
259-
return c.Delete(ctx, bpfApp)
260-
}
261-
262231
func (c *AgentController) createBpfApplication(ctx context.Context, bpfApp *bpfmaniov1alpha1.ClusterBpfApplication) error {
263232
return c.CreateOwned(ctx, bpfApp)
264233
}

controllers/ebpf/internal/permissions/permissions.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,6 @@ func (c *Reconciler) Reconcile(ctx context.Context, desired *flowslatest.FlowCol
5454

5555
func (c *Reconciler) reconcileNamespace(ctx context.Context) error {
5656
ns := c.PrivilegedNamespace()
57-
if ns != c.PreviousPrivilegedNamespace() {
58-
if err := c.cleanupPreviousNamespace(ctx); err != nil {
59-
return err
60-
}
61-
}
6257
rlog := log.FromContext(ctx, "PrivilegedNamespace", ns)
6358
actual := &v1.Namespace{}
6459
if err := c.Get(ctx, client.ObjectKey{Name: ns}, actual); err != nil {
@@ -201,44 +196,3 @@ func (c *Reconciler) reconcileOpenshiftPermissions(
201196
rlog.Info("SecurityContextConstraints already reconciled. Doing nothing")
202197
return nil
203198
}
204-
205-
func (c *Reconciler) cleanupPreviousNamespace(ctx context.Context) error {
206-
rlog := log.FromContext(ctx, "PreviousPrivilegedNamespace", c.PreviousPrivilegedNamespace())
207-
208-
// Delete service account
209-
if err := c.Delete(ctx, &v1.ServiceAccount{
210-
ObjectMeta: metav1.ObjectMeta{
211-
Name: constants.EBPFServiceAccount,
212-
Namespace: c.PreviousPrivilegedNamespace(),
213-
},
214-
}); err != nil {
215-
if errors.IsNotFound(err) {
216-
return nil
217-
}
218-
return fmt.Errorf("deleting eBPF agent ServiceAccount: %w", err)
219-
}
220-
// Do not delete SCC as it's not namespace-scoped (it will be reconciled "as usual")
221-
222-
previous := &v1.Namespace{}
223-
if err := c.Get(ctx, client.ObjectKey{Name: c.PreviousPrivilegedNamespace()}, previous); err != nil {
224-
if errors.IsNotFound(err) {
225-
// Not found => return without error
226-
rlog.Info("Previous privileged namespace not found, skipping cleanup")
227-
return nil
228-
}
229-
return fmt.Errorf("can't retrieve previous namespace: %w", err)
230-
}
231-
// Make sure we own that namespace
232-
if helper.IsOwned(previous) {
233-
rlog.Info("Owning previous privileged namespace: deleting it")
234-
if err := c.Delete(ctx, previous); err != nil {
235-
if errors.IsNotFound(err) {
236-
return nil
237-
}
238-
return fmt.Errorf("deleting privileged namespace: %w", err)
239-
}
240-
} else {
241-
rlog.Info("Not owning previous privileged namespace: delete related content only")
242-
}
243-
return nil
244-
}

controllers/flowcollector_controller.go

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func (r *FlowCollectorReconciler) reconcile(ctx context.Context, clh *helper.Cli
121121
ns := helper.GetNamespace(&desired.Spec)
122122
previousNamespace := r.status.GetDeployedNamespace(desired)
123123
loki := helper.NewLokiConfig(&desired.Spec.Loki, ns)
124-
reconcilersInfo := r.newCommonInfo(clh, ns, previousNamespace, &loki)
124+
reconcilersInfo := r.newCommonInfo(clh, ns, &loki)
125125

126126
if err := r.checkFinalizer(ctx, desired); err != nil {
127127
return err
@@ -137,13 +137,6 @@ func (r *FlowCollectorReconciler) reconcile(ctx context.Context, clh *helper.Cli
137137

138138
// Check namespace changed
139139
if ns != previousNamespace {
140-
if previousNamespace != "" {
141-
// Namespace updated, clean up previous namespace
142-
log.FromContext(ctx).
143-
Info("FlowCollector namespace change detected: cleaning up previous namespace", "old", previousNamespace, "new", ns)
144-
cpReconciler.CleanupNamespace(ctx)
145-
}
146-
147140
// Update namespace in status
148141
if err := r.status.SetDeployedNamespace(ctx, r.Client, ns); err != nil {
149142
return r.status.Error("ChangeNamespaceError", err)
@@ -176,14 +169,13 @@ func (r *FlowCollectorReconciler) checkFinalizer(ctx context.Context, desired *f
176169
return nil
177170
}
178171

179-
func (r *FlowCollectorReconciler) newCommonInfo(clh *helper.Client, ns, prevNs string, loki *helper.LokiConfig) reconcilers.Common {
172+
func (r *FlowCollectorReconciler) newCommonInfo(clh *helper.Client, ns string, loki *helper.LokiConfig) reconcilers.Common {
180173
return reconcilers.Common{
181-
Client: *clh,
182-
Namespace: ns,
183-
PreviousNamespace: prevNs,
184-
ClusterInfo: r.mgr.ClusterInfo,
185-
Watcher: r.watcher,
186-
Loki: loki,
187-
IsDownstream: r.mgr.Config.DownstreamDeployment,
174+
Client: *clh,
175+
Namespace: ns,
176+
ClusterInfo: r.mgr.ClusterInfo,
177+
Watcher: r.watcher,
178+
Loki: loki,
179+
IsDownstream: r.mgr.Config.DownstreamDeployment,
188180
}
189181
}

controllers/flowcollector_controller_console_test.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -356,52 +356,6 @@ func flowCollectorConsolePluginSpecs() {
356356
})
357357
})
358358

359-
Context("Changing namespace", func() {
360-
const otherNamespace = "other-namespace"
361-
cpKey2 := types.NamespacedName{
362-
Name: "netobserv-plugin",
363-
Namespace: otherNamespace,
364-
}
365-
366-
It("Should update namespace successfully", func() {
367-
updateCR(crKey, func(fc *flowslatest.FlowCollector) {
368-
fc.Spec.Namespace = otherNamespace
369-
})
370-
})
371-
372-
It("Should redeploy console plugin in new namespace", func() {
373-
By("Expecting deployment in previous namespace to be deleted")
374-
Eventually(func() interface{} {
375-
return k8sClient.Get(ctx, cpKey, &appsv1.Deployment{})
376-
}, timeout, interval).Should(MatchError(`deployments.apps "netobserv-plugin" not found`))
377-
378-
By("Expecting service in previous namespace to be deleted")
379-
Eventually(func() interface{} {
380-
return k8sClient.Get(ctx, cpKey, &v1.Service{})
381-
}, timeout, interval).Should(MatchError(`services "netobserv-plugin" not found`))
382-
383-
By("Expecting service account in previous namespace to be deleted")
384-
Eventually(func() interface{} {
385-
return k8sClient.Get(ctx, cpKey, &v1.ServiceAccount{})
386-
}, timeout, interval).Should(MatchError(`serviceaccounts "netobserv-plugin" not found`))
387-
388-
By("Expecting deployment to be created in new namespace")
389-
Eventually(func() interface{} {
390-
return k8sClient.Get(ctx, cpKey2, &appsv1.Deployment{})
391-
}, timeout, interval).Should(Succeed())
392-
393-
By("Expecting service to be created in new namespace")
394-
Eventually(func() interface{} {
395-
return k8sClient.Get(ctx, cpKey2, &v1.Service{})
396-
}, timeout, interval).Should(Succeed())
397-
398-
By("Expecting service account to be created in new namespace")
399-
Eventually(func() interface{} {
400-
return k8sClient.Get(ctx, cpKey2, &v1.ServiceAccount{})
401-
}, timeout, interval).Should(Succeed())
402-
})
403-
})
404-
405359
Context("Cleanup", func() {
406360
It("Should delete CR", func() {
407361
cleanupCR(crKey)

0 commit comments

Comments
 (0)