...

Source file src/edge-infra.dev/pkg/sds/lib/etcd/server/reset.go

Documentation: edge-infra.dev/pkg/sds/lib/etcd/server

     1  package server
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"slices"
     7  
     8  	corev1 "k8s.io/api/core/v1"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"k8s.io/apimachinery/pkg/runtime"
    11  
    12  	"edge-infra.dev/pkg/sds/lib/containerd"
    13  	"edge-infra.dev/pkg/sds/lib/dbus/systemd"
    14  	"edge-infra.dev/pkg/sds/lib/k8s/manifest"
    15  )
    16  
    17  var (
    18  	FNCFlag = "--force-new-cluster=true"
    19  )
    20  
    21  // EnterNewClusterMode creates a new etcd cluster with the current node as the only member.
    22  // Always run ExitNewClusterMode after you have finished configuring your new cluster
    23  // after using EnterNewClusterMode. Failure to do so will result in the cluster being reset
    24  // every time the etcd container restarts.
    25  func EnterNewClusterMode(ctx context.Context, m *manifest.Manifest, restarter systemd.Restarter, terminator containerd.Terminator) error {
    26  	return WithRestart(ctx, restarter, terminator, func() error {
    27  		return m.WithUpdate(func(obj runtime.Object) error {
    28  			pod, ok := obj.(*corev1.Pod)
    29  			if !ok {
    30  				return fmt.Errorf("current content of the etcd manifest is not a valid pod")
    31  			}
    32  			return SetFNCFlag(pod)
    33  		})
    34  	})
    35  }
    36  
    37  // ExitNewClusterMode prevents the etcd cluster from being restarted when the etcd
    38  // container restarts.
    39  func ExitNewClusterMode(ctx context.Context, m *manifest.Manifest, restarter systemd.Restarter, terminator containerd.Terminator) error {
    40  	return WithRestart(ctx, restarter, terminator, func() error {
    41  		return m.WithUpdate(func(obj runtime.Object) error {
    42  			pod, ok := obj.(*corev1.Pod)
    43  			if !ok {
    44  				return fmt.Errorf("current content of the etcd manifest is not a valid pod")
    45  			}
    46  			return ClearFNCFlag(pod)
    47  		})
    48  	})
    49  }
    50  
    51  // WithRestart takes a function and adds functionality to restart the etcd
    52  // container and kubelet service.
    53  func WithRestart(ctx context.Context, restarter systemd.Restarter, terminator containerd.Terminator, fn func() error) error {
    54  	labelFilters := containerd.NewLabelFiltersBuilder().WithContainerName("etcd").WithPodNamespace(metav1.NamespaceSystem).Build()
    55  	err := terminator.WithTerminate(ctx, *labelFilters, func() error {
    56  		return fn()
    57  	})
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	return restarter.Restart(ctx, "kubelet.service", systemd.Replace, false)
    63  }
    64  
    65  // SetFNCFlag adds the --force-new-cluster=true flag to the etcd container command if
    66  // it does not already exist.
    67  func SetFNCFlag(pod *corev1.Pod) error {
    68  	if len(pod.Spec.Containers) == 0 {
    69  		return fmt.Errorf("etcd container not found in etcd manifest")
    70  	}
    71  
    72  	if !slices.Contains(pod.Spec.Containers[0].Command, FNCFlag) {
    73  		pod.Spec.Containers[0].Command = append(pod.Spec.Containers[0].Command, FNCFlag)
    74  	}
    75  
    76  	return nil
    77  }
    78  
    79  // ClearFNCFlag removes the --force-new-cluster=true flag from the etcd container command
    80  // if it exists.
    81  func ClearFNCFlag(pod *corev1.Pod) error {
    82  	if len(pod.Spec.Containers) == 0 {
    83  		return fmt.Errorf("etcd container not found in etcd manifest")
    84  	}
    85  
    86  	updatedCommand := make([]string, 0, len(pod.Spec.Containers[0].Command))
    87  	for _, value := range pod.Spec.Containers[0].Command {
    88  		if value != FNCFlag {
    89  			// Value doesn't match the forceNewClusterFlag, keep it in the updatedCommand array
    90  			updatedCommand = append(updatedCommand, value)
    91  		}
    92  	}
    93  	pod.Spec.Containers[0].Command = updatedCommand
    94  
    95  	return nil
    96  }
    97  

View as plain text