Skip to content

Commit

Permalink
fix: Better migration path from the ngrok kuberntes-ingress-controlle…
Browse files Browse the repository at this point in the history
…r to the ngrok-operator (#495)

* fix: Better migration path from the ngrok kuberntes-ingress-controller to the ngrok-operator

* chore: rename k8sClinet -> k8sClient
  • Loading branch information
jonstacks authored Nov 8, 2024
1 parent 91363e8 commit 6e2c6e7
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 5 deletions.
17 changes: 12 additions & 5 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,12 @@ func runController(ctx context.Context, opts managerOpts) error {

// create default config and clientset for use outside the mgr.Start() blocking loop
k8sConfig := ctrl.GetConfigOrDie()
k8sClinet, err := client.New(k8sConfig, client.Options{Scheme: scheme})
k8sClient, err := client.New(k8sConfig, client.Options{Scheme: scheme})
if err != nil {
return fmt.Errorf("unable to create k8s client: %w", err)
}

if err := createKubernetesOperator(ctx, k8sClinet, opts); err != nil {
if err := createKubernetesOperator(ctx, k8sClient, opts); err != nil {
return fmt.Errorf("unable to create KubernetesOperator: %w", err)
}

Expand All @@ -236,11 +236,18 @@ func runController(ctx context.Context, opts managerOpts) error {
var k8sResourceDriver *store.Driver
if opts.enableFeatureIngress || opts.enableFeatureGateway {
// we only need a driver if these features are enabled
if driver, err := getK8sResourceDriver(ctx, mgr, opts); err != nil {
k8sResourceDriver, err = getK8sResourceDriver(ctx, mgr, opts)
if err != nil {
return fmt.Errorf("unable to create Driver: %w", err)
} else {
k8sResourceDriver = driver
}

// Run a migration for migrating from the old ingress controller to the operator
// TODO: Delete me after the initial releae of the ngrok-operator
setupLog.Info("Migrating Kubernetes Ingress Controller labels to ngrok operator")
if err := k8sResourceDriver.MigrateKubernetesIngressControllerLabelsToNgrokOperator(ctx, k8sClient); err != nil {
return fmt.Errorf("unable to migrate Kubernetes Ingress Controller labels to ngrok operator: %w", err)
}
setupLog.Info("Kubernetes Ingress controller labels migrated to ngrok operator")
}

if opts.enableFeatureIngress {
Expand Down
63 changes: 63 additions & 0 deletions internal/store/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1941,3 +1941,66 @@ func (d *Driver) ngrokLabels(namespace, serviceUID, serviceName string, port int
labelPort: strconv.Itoa(int(port)),
}
}

// MigrateKubernetesIngressControllerLabelsToNgrokOperator migrates the labels from the old Kubernetes Ingress Controller to the new ngrok operator labels
// so that the ngrok operator can take over management of items previously managed by the Kubernetes Ingress Controller.
// TODO: Delete this function after users have migrated from the ngrok Kubernetes Ingress Controller to the ngrok Operator.
func (d *Driver) MigrateKubernetesIngressControllerLabelsToNgrokOperator(ctx context.Context, k8sClient client.Client) error {
typesToMigrate := []interface{}{
&ingressv1alpha1.Domain{},
&ingressv1alpha1.Tunnel{},
&ingressv1alpha1.HTTPSEdge{},
}

for _, t := range typesToMigrate {
objs, err := listObjectsForType(ctx, k8sClient, t)
if err != nil {
return err
}

for _, obj := range objs {

name := obj.GetName()
namespace := obj.GetNamespace()
kind := obj.GetObjectKind().GroupVersionKind().Kind

log := d.log.WithValues("name", name, "namespace", namespace, "kind", kind)

labels := obj.GetLabels()

controllerName, controllerNameOk := labels[labelControllerName]
controllerNamespace, controllerNamespaceOk := labels[labelControllerNamespace]

// If it doesn't have both of the controller name and namespace labels, skip it
if !controllerNameOk || !controllerNamespaceOk {
log.V(1).Info("Skipping object without controller name and namespace labels")
continue
}

// If the controller name and namespace are the same as the current controller name and namespace, skip it
if controllerName == d.managerName.Name && controllerNamespace == d.managerName.Namespace {
log.V(1).Info("Skipping object with matching controller name and namespace labels")
continue
}

// Deep copy the object so we can modify it.
// We must also re-assign the labels to the new object so that
// we don't modify the original object's labels.
newObj := obj.DeepCopyObject().(client.Object)
labels = newObj.GetLabels()

// Now we know it has both labels and at least one of the two labels doesn't match
// so we can update the labels to match what the new operator expects.
labels[labelControllerName] = d.managerName.Name
labels[labelControllerNamespace] = d.managerName.Namespace

newObj.SetLabels(labels)

if err := k8sClient.Patch(ctx, newObj, client.MergeFrom(obj)); err != nil {
return err
}
log.V(1).Info("Migrated labels")
}
}
return nil
}

0 comments on commit 6e2c6e7

Please sign in to comment.