Skip to content

Commit f7481ff

Browse files
committed
select remote namespace name when offloading
1 parent 8a4e9cd commit f7481ff

File tree

7 files changed

+61
-9
lines changed

7 files changed

+61
-9
lines changed

apis/offloading/v1alpha1/namespaceoffloading_types.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ const (
4747
// DefaultNameMappingStrategyType -> the remote namespace is assigned a default name which ensures uniqueness
4848
// and avoids conflicts (localNamespaceName-localClusterID).
4949
DefaultNameMappingStrategyType NamespaceMappingStrategyType = "DefaultName"
50+
// SelectedNameMappingStrategyType -> the remote namespace is assigned a name chosen by the user.
51+
// (the creation may fail in case of conflicts).
52+
SelectedNameMappingStrategyType NamespaceMappingStrategyType = "SelectedName"
5053
)
5154

5255
// PodOffloadingStrategyType represents different strategies to offload pods in this Namespace.
@@ -97,11 +100,15 @@ type NamespaceOffloadingSpec struct {
97100
// NamespaceMappingStrategy allows users to map local and remote namespace names according to two
98101
// different strategies: "DefaultName", which ensures uniqueness and prevents conflicts, and "EnforceSameName",
99102
// which enforces the same name at the cost of possible conflicts.
100-
// +kubebuilder:validation:Enum="EnforceSameName";"DefaultName"
103+
// +kubebuilder:validation:Enum="EnforceSameName";"DefaultName";"SelectedName"
101104
// +kubebuilder:default="DefaultName"
102105
// +kubebuilder:validation:Optional
103106
NamespaceMappingStrategy NamespaceMappingStrategyType `json:"namespaceMappingStrategy"`
104107

108+
// RemoteNamespaceName allows users to choose a specific name for the remote namespace.
109+
// This field is required if NamespaceMappingStrategy is set to "SelectedName". It is ignored otherwise.
110+
RemoteNamespaceName string `json:"remoteNamespaceName,omitempty"`
111+
105112
// PodOffloadingStrategy allows users to configure how pods in this namespace are offloaded, according to three
106113
// different strategies: "Local" (i.e. no pod offloading is performed), "Remote" (i.e. all pods are offloaded
107114
// in remote clusters), "LocalAndRemote" (i.e. no constraints are enforced besides the ones

cmd/liqoctl/cmd/offload.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,12 @@ func newOffloadNamespaceCommand(ctx context.Context, f *factory.Factory) *cobra.
8686

8787
namespaceMappingStrategy := args.NewEnum([]string{
8888
string(offloadingv1alpha1.EnforceSameNameMappingStrategyType),
89-
string(offloadingv1alpha1.DefaultNameMappingStrategyType)},
89+
string(offloadingv1alpha1.DefaultNameMappingStrategyType),
90+
string(offloadingv1alpha1.SelectedNameMappingStrategyType)},
9091
string(offloadingv1alpha1.DefaultNameMappingStrategyType))
9192

93+
var remoteNamespaceName = ""
94+
9295
outputFormat := args.NewEnum([]string{"json", "yaml"}, "")
9396

9497
options := offload.Options{Factory: f}
@@ -104,6 +107,7 @@ func newOffloadNamespaceCommand(ctx context.Context, f *factory.Factory) *cobra.
104107
PreRun: func(cmd *cobra.Command, args []string) {
105108
options.PodOffloadingStrategy = offloadingv1alpha1.PodOffloadingStrategyType(podOffloadingStrategy.Value)
106109
options.NamespaceMappingStrategy = offloadingv1alpha1.NamespaceMappingStrategyType(namespaceMappingStrategy.Value)
110+
options.RemoteNamespaceName = remoteNamespaceName
107111
options.OutputFormat = outputFormat.Value
108112
options.Printer.CheckErr(options.ParseClusterSelectors(selectors))
109113
},
@@ -117,8 +121,11 @@ func newOffloadNamespaceCommand(ctx context.Context, f *factory.Factory) *cobra.
117121
cmd.Flags().Var(podOffloadingStrategy, "pod-offloading-strategy",
118122
"The constraints regarding pods scheduling in this namespace, among Local, Remote and LocalAndRemote")
119123
cmd.Flags().Var(namespaceMappingStrategy, "namespace-mapping-strategy",
120-
"The naming strategy adopted for the creation of remote namespaces, among DefaultName and EnforceSameName")
124+
"The naming strategy adopted for the creation of remote namespaces, among DefaultName, EnforceSameName and SelectedName")
121125
cmd.Flags().DurationVar(&options.Timeout, "timeout", 20*time.Second, "The timeout for the offloading process")
126+
cmd.Flags().StringVar(&remoteNamespaceName, "remote-namespace-name", "",
127+
"The name of the remote namespace, required when using the SelectedName NamespaceMappingStrategy. "+
128+
"Otherwise, it is ignored")
122129

123130
cmd.Flags().StringArrayVarP(&selectors, "selector", "l", []string{},
124131
"The selector to filter the target clusters. Can be specified multiple times, defining alternative requirements (i.e., in logical OR)")

deployments/liqo/crds/offloading.liqo.io_namespaceoffloadings.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ spec:
152152
enum:
153153
- EnforceSameName
154154
- DefaultName
155+
- SelectedName
155156
type: string
156157
podOffloadingStrategy:
157158
default: LocalAndRemote
@@ -166,6 +167,11 @@ spec:
166167
- Remote
167168
- LocalAndRemote
168169
type: string
170+
remoteNamespaceName:
171+
description: RemoteNamespaceName allows users to choose a specific
172+
name for the remote namespace. This field is required if NamespaceMappingStrategy
173+
is set to "SelectedName". It is ignored otherwise.
174+
type: string
169175
type: object
170176
status:
171177
description: NamespaceOffloadingStatus defines the observed state of NamespaceOffloading.

docs/usage/namespace-offloading.md

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ The accepted values are:
4444
* **EnforceSameName**: remote namespaces are named after the local cluster's namespace.
4545
This approach ensures **naming transparency**, which is required by certain applications, as well as guarantees that **cross-namespace DNS queries** referring to reflected services work out of the box (i.e., without adapting the target namespace name).
4646
Yet, it can lead to **conflicts** in case a namespace with the same name already exists inside the selected remote clusters, ultimately causing the remote namespace creation request to be rejected.
47+
* **SelectedName**: you can specify the name of the remote namespace through the `--emote-namespace-name` flag.
48+
This flag is ignored in case the *namespace mapping strategy* is set to *DefaultName* or *EnforceSameName*.
4749

4850
```{admonition} Note
4951
Once configured for a given namespace, the *namespace mapping strategy* is **immutable**, and any modification is prevented by a dedicated Liqo webhook.

pkg/liqo-controller-manager/namespaceoffloading-controller/status.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,18 @@ func (r *NamespaceOffloadingReconciler) enforceStatus(ctx context.Context, nsoff
5454

5555
// remoteNamespaceName returns the remapped name corresponding to a given namespace.
5656
func (r *NamespaceOffloadingReconciler) remoteNamespaceName(nsoff *offv1alpha1.NamespaceOffloading) string {
57-
if nsoff.Spec.NamespaceMappingStrategy == offv1alpha1.EnforceSameNameMappingStrategyType {
57+
switch nsoff.Spec.NamespaceMappingStrategy {
58+
case offv1alpha1.EnforceSameNameMappingStrategyType:
5859
return nsoff.Namespace
60+
case offv1alpha1.DefaultNameMappingStrategyType:
61+
return nsoff.Namespace + "-" + foreignclusterutils.UniqueName(&r.LocalCluster)
62+
case offv1alpha1.SelectedNameMappingStrategyType:
63+
return nsoff.Spec.RemoteNamespaceName
64+
default:
65+
klog.Errorf("NamespaceOffloading %q: unknown NamespaceMappingStrategy %q, falling back to %q",
66+
klog.KObj(nsoff), nsoff.Spec.NamespaceMappingStrategy, offv1alpha1.DefaultNameMappingStrategyType)
67+
return nsoff.Namespace + "-" + foreignclusterutils.UniqueName(&r.LocalCluster)
5968
}
60-
61-
return nsoff.Namespace + "-" + foreignclusterutils.UniqueName(&r.LocalCluster)
6269
}
6370

6471
// ensureRemoteConditionsConsistence checks for every remote condition of the NamespaceOffloading resource that the

pkg/liqo-controller-manager/webhooks/namespaceoffloading/nsoff.go

+23-3
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ func (w *nsoffwh) DecodeNamespaceOffloading(obj runtime.RawExtension) (*offv1alp
5050
//
5151
//nolint:gocritic // The signature of this method is imposed by controller runtime.
5252
func (w *nsoffwh) Handle(ctx context.Context, req admission.Request) admission.Response {
53-
var warnings []string
54-
5553
nsoff, err := w.DecodeNamespaceOffloading(req.Object)
5654
if err != nil {
5755
klog.Errorf("Failed decoding NamespaceOffloading object: %v", err)
@@ -63,9 +61,27 @@ func (w *nsoffwh) Handle(ctx context.Context, req admission.Request) admission.R
6361
return admission.Denied("NamespaceOffloading name must match " + consts.DefaultNamespaceOffloadingName)
6462
}
6563

66-
if req.Operation != admissionv1.Update {
64+
switch req.Operation {
65+
case admissionv1.Create:
66+
return w.handleCreate(ctx, &req, nsoff)
67+
case admissionv1.Update:
68+
return w.handleUpdate(ctx, &req, nsoff)
69+
default:
6770
return admission.Allowed("")
6871
}
72+
}
73+
74+
func (w *nsoffwh) handleCreate(_ context.Context, _ *admission.Request, nsoff *offv1alpha1.NamespaceOffloading) admission.Response {
75+
if nsoff.Spec.NamespaceMappingStrategy == offv1alpha1.SelectedNameMappingStrategyType &&
76+
nsoff.Spec.RemoteNamespaceName == "" {
77+
return admission.Denied("The RemoteNamespaceName value cannot be empty when using the SelectedName NamespaceMappingStrategy")
78+
}
79+
80+
return admission.Allowed("")
81+
}
82+
83+
func (w *nsoffwh) handleUpdate(_ context.Context, req *admission.Request, nsoff *offv1alpha1.NamespaceOffloading) admission.Response {
84+
var warnings []string
6985

7086
// In case of updates, validate the modified fields.
7187
old, err := w.DecodeNamespaceOffloading(req.OldObject)
@@ -78,6 +94,10 @@ func (w *nsoffwh) Handle(ctx context.Context, req admission.Request) admission.R
7894
return admission.Denied("The NamespaceMappingStrategy value cannot be modified after creation")
7995
}
8096

97+
if old.Spec.RemoteNamespaceName != nsoff.Spec.RemoteNamespaceName {
98+
return admission.Denied("The RemoteNamespaceName value cannot be modified after creation")
99+
}
100+
81101
if nsoff.Spec.PodOffloadingStrategy != offv1alpha1.LocalAndRemotePodOffloadingStrategyType &&
82102
old.Spec.PodOffloadingStrategy != nsoff.Spec.PodOffloadingStrategy {
83103
const msg = "The PodOffloadingStrategy was mutated to a more restrictive setting: existing pods violating this policy might still be running"

pkg/liqoctl/offload/handler.go

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type Options struct {
3939
Namespace string
4040
PodOffloadingStrategy offloadingv1alpha1.PodOffloadingStrategyType
4141
NamespaceMappingStrategy offloadingv1alpha1.NamespaceMappingStrategyType
42+
RemoteNamespaceName string
4243
ClusterSelector [][]metav1.LabelSelectorRequirement
4344

4445
OutputFormat string
@@ -87,6 +88,7 @@ func (o *Options) Run(ctx context.Context) error {
8788
oldStrategy = nsoff.Spec.PodOffloadingStrategy
8889
nsoff.Spec.PodOffloadingStrategy = o.PodOffloadingStrategy
8990
nsoff.Spec.NamespaceMappingStrategy = o.NamespaceMappingStrategy
91+
nsoff.Spec.RemoteNamespaceName = o.RemoteNamespaceName
9092
nsoff.Spec.ClusterSelector = toNodeSelector(o.ClusterSelector)
9193
return nil
9294
})
@@ -132,6 +134,7 @@ func (o *Options) output() error {
132134
Spec: offloadingv1alpha1.NamespaceOffloadingSpec{
133135
PodOffloadingStrategy: o.PodOffloadingStrategy,
134136
NamespaceMappingStrategy: o.NamespaceMappingStrategy,
137+
RemoteNamespaceName: o.RemoteNamespaceName,
135138
ClusterSelector: toNodeSelector(o.ClusterSelector),
136139
},
137140
}

0 commit comments

Comments
 (0)