Skip to content

Commit 438a04c

Browse files
move ensure all the namespaces exists
1 parent 4a68ed2 commit 438a04c

File tree

1 file changed

+68
-0
lines changed
  • cmd/clusterctl/pkg/client/cluster

1 file changed

+68
-0
lines changed

cmd/clusterctl/pkg/client/cluster/mover.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ import (
2222

2323
"github.com/go-logr/logr"
2424
"github.com/pkg/errors"
25+
corev1 "k8s.io/api/core/v1"
2526
apierrors "k8s.io/apimachinery/pkg/api/errors"
2627
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2728
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2829
"k8s.io/apimachinery/pkg/types"
2930
kerrors "k8s.io/apimachinery/pkg/util/errors"
31+
"k8s.io/apimachinery/pkg/util/sets"
3032
"k8s.io/apimachinery/pkg/util/wait"
3133
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
3234
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -94,6 +96,11 @@ func (o *objectMover) move(graph *objectGraph, toProxy Proxy) error {
9496
return err
9597
}
9698

99+
// Ensure all the expected target namespaces are in place before creating objects.
100+
if err := o.ensureNamespaces(graph, toProxy); err != nil {
101+
return err
102+
}
103+
97104
// Define the move sequence by processing the ownerReference chain, so we ensure that a Kubernetes object is moved only after its owners.
98105
// The sequence is bases on object graph nodes, each one representing a Kubernetes object; nodes are grouped, so bulk of nodes can be moved in parallel. e.g.
99106
// - All the Clusters should be moved first (group 1, processed in parallel)
@@ -229,6 +236,67 @@ func setClusterPause(proxy Proxy, clusters []*node, value bool, log logr.Logger)
229236
return nil
230237
}
231238

239+
// ensureNamespaces ensures all the expected target namespaces are in place before creating objects.
240+
func (o *objectMover) ensureNamespaces(graph *objectGraph, toProxy Proxy) error {
241+
cs, err := toProxy.NewClient()
242+
if err != nil {
243+
return err
244+
}
245+
246+
namespaces := sets.NewString()
247+
for _, node := range graph.getNodesWithClusterTenants() {
248+
namespace := node.identity.Namespace
249+
250+
// If the namespace was already processed, skip it.
251+
if namespaces.Has(namespace) {
252+
continue
253+
}
254+
namespaces.Insert(namespace)
255+
256+
// Otherwise check if namespace exists (also dealing with RBAC restrictions).
257+
ns := &corev1.Namespace{}
258+
key := client.ObjectKey{
259+
Name: namespace,
260+
}
261+
262+
if err = cs.Get(ctx, key, ns); err == nil {
263+
return nil
264+
}
265+
if apierrors.IsForbidden(err) {
266+
namespaces := &corev1.NamespaceList{}
267+
if err := cs.List(ctx, namespaces); err != nil {
268+
return err
269+
}
270+
271+
for _, ns := range namespaces.Items {
272+
if ns.Name == namespace {
273+
return nil
274+
}
275+
}
276+
}
277+
if !apierrors.IsNotFound(err) {
278+
return err
279+
}
280+
281+
// If the namespace does not exists, create it.
282+
ns = &corev1.Namespace{
283+
TypeMeta: metav1.TypeMeta{
284+
APIVersion: "v1",
285+
Kind: "Namespace",
286+
},
287+
ObjectMeta: metav1.ObjectMeta{
288+
Name: namespace,
289+
},
290+
}
291+
o.log.V(1).Info("Creating", ns.Kind, ns.Name)
292+
if err = cs.Create(ctx, ns); err != nil && !apierrors.IsAlreadyExists(err) {
293+
return err
294+
}
295+
}
296+
297+
return nil
298+
}
299+
232300
const (
233301
retryCreateTargetObject = 3
234302
retryIntervalCreateTargetObject = 1 * time.Second

0 commit comments

Comments
 (0)