...

Source file src/edge-infra.dev/pkg/sds/etcd/operator/internal/resources/etcdmember.go

Documentation: edge-infra.dev/pkg/sds/etcd/operator/internal/resources

     1  // Package resources provides handlers for the etcd operator to assist with managing the kubernetes resources
     2  package resources
     3  
     4  import (
     5  	"context"
     6  	"time"
     7  
     8  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
     9  	"k8s.io/apimachinery/pkg/types"
    10  	"sigs.k8s.io/controller-runtime/pkg/client"
    11  
    12  	"edge-infra.dev/pkg/k8s/runtime/conditions"
    13  	"edge-infra.dev/pkg/k8s/runtime/patch"
    14  	v1etcd "edge-infra.dev/pkg/sds/etcd/operator/apis/etcdmember/v1"
    15  
    16  	etcdretryclient "edge-infra.dev/pkg/sds/lib/etcd/client/retry"
    17  	kubeclienttypes "edge-infra.dev/pkg/sds/lib/k8s/retryclient/types"
    18  )
    19  
    20  type EtcdMemberHandler struct {
    21  	*v1etcd.EtcdMember
    22  
    23  	Client    kubeclienttypes.Retrier
    24  	Key       types.NamespacedName
    25  	Found     bool
    26  	IsMember  bool
    27  	IsLearner bool
    28  }
    29  
    30  // Validate will validate the EtcdMember using a DryRun create
    31  func (h *EtcdMemberHandler) Validate(ctx context.Context) error {
    32  	opts := &client.CreateOptions{}
    33  	client.DryRunAll.ApplyToCreate(opts)
    34  	return client.IgnoreAlreadyExists(h.Client.SafeCreate(ctx, h.EtcdMember, opts))
    35  }
    36  
    37  func (h *EtcdMemberHandler) ReconcileMembershipStatus(ctx context.Context, client etcdretryclient.Retrier) error {
    38  	resp, err := client.SafeMemberList(ctx)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	for _, member := range resp.Members {
    43  		if member.PeerURLs[0] == h.PeerURL() {
    44  			h.IsMember = true
    45  			h.IsLearner = member.IsLearner
    46  		}
    47  	}
    48  	return nil
    49  }
    50  
    51  // ReconcileLocal updates the local copy of the EtcdMember with the latest
    52  // version from the API server
    53  func (h *EtcdMemberHandler) ReconcileLocal(ctx context.Context) error {
    54  	return h.Client.SafeGet(ctx, h.Key, h.EtcdMember)
    55  }
    56  
    57  // CreateRemote creates the EtcdMember in the API server
    58  func (h *EtcdMemberHandler) CreateRemote(ctx context.Context) error {
    59  	return h.Client.SafeCreate(ctx, h.EtcdMember)
    60  }
    61  
    62  // DeleteRemote deletes the EtcdMember from the API server
    63  func (h *EtcdMemberHandler) DeleteRemote(ctx context.Context) error {
    64  	return h.Client.SafeDelete(ctx, h.EtcdMember)
    65  }
    66  
    67  // WithReconcileRemote will update the EtcdMember in the API server, after
    68  // applying the provided function to the EtcdMember
    69  func (h *EtcdMemberHandler) WithReconcileRemote(ctx context.Context, fn func(e *v1etcd.EtcdMember)) error {
    70  	patcher := patch.NewSerialPatcher(h.EtcdMember, h.Client.Client())
    71  	fn(h.EtcdMember)
    72  
    73  	return patcher.Patch(ctx, h.EtcdMember)
    74  }
    75  
    76  // DeepCopyFrom copies the contents of the provided EtcdMember into the local
    77  // copy of the EtcdMember
    78  func (h *EtcdMemberHandler) DeepCopyFrom(from *v1etcd.EtcdMember) {
    79  	from.DeepCopyInto(h.EtcdMember)
    80  }
    81  
    82  // ReconfigurationRequired behaves differently depending on whether an
    83  // installation has been attempted.
    84  //
    85  // Case 1 - Installation has been attempted:
    86  //
    87  // returns true if the member has been unhealthy for longer than the
    88  // reconfiguration backoff period, otherwise false.
    89  //
    90  // Case 2 - Installation has not been attempted:
    91  //
    92  // returns true if the member has been unhealthy for longer than 60 minutes,
    93  // otherwise false.
    94  func (h *EtcdMemberHandler) ReconfigurationRequired() bool {
    95  	healthCondition := conditions.Get(h.EtcdMember, v1etcd.Health)
    96  	if healthCondition == nil {
    97  		return false
    98  	}
    99  	installedCondition := conditions.Get(h.EtcdMember, v1etcd.Installed)
   100  	switch installedCondition {
   101  	case nil:
   102  		return healthCondition.Status != metav1.ConditionTrue &&
   103  			healthCondition.LastTransitionTime.Add(60*time.Minute).Before(time.Now())
   104  	default:
   105  		return healthCondition.Status != metav1.ConditionTrue &&
   106  			healthCondition.LastTransitionTime.Add(h.Spec.BackoffPeriod()).Before(time.Now())
   107  	}
   108  }
   109  
   110  // DeletionRequired returns true if the member meets the criteria
   111  // for deletion
   112  func (h *EtcdMemberHandler) DeletionRequired(currentIENVersion string) bool {
   113  	if !h.InstalledForLatestIEN(currentIENVersion) {
   114  		return true
   115  	}
   116  	if !h.DeletionTimestamp.IsZero() {
   117  		return true
   118  	}
   119  	return h.ReconfigurationRequired()
   120  }
   121  
   122  // IsProvisioned returns true if the Secret was successfully prepared
   123  func (h *EtcdMemberHandler) IsProvisioned() bool {
   124  	return conditions.IsTrue(h.EtcdMember, v1etcd.Provisioned)
   125  }
   126  
   127  // IsInstalled returns true if etcd was successfully installed
   128  func (h *EtcdMemberHandler) IsInstalled() bool {
   129  	return conditions.IsTrue(h.EtcdMember, v1etcd.Installed)
   130  }
   131  
   132  // IsSuspended returns true if EtcdMember reconciliation is suspended
   133  func (h *EtcdMemberHandler) IsSuspended() bool {
   134  	return h.Spec.Suspend
   135  }
   136  
   137  // InstallationAttempted returns true if all steps of the configuration
   138  // process have been attempted
   139  func (h *EtcdMemberHandler) InstallationAttempted() bool {
   140  	condition := conditions.Get(h, v1etcd.Installed)
   141  	return condition != nil
   142  }
   143  
   144  // InstalledForLatestIEN returns true if the EtcdMember was installed for the
   145  // latest IEN version
   146  func (h *EtcdMemberHandler) InstalledForLatestIEN(currentVersion string) bool {
   147  	installedVersion := h.EtcdMember.GetLabels()[v1etcd.IENVersionLabel]
   148  	return installedVersion == currentVersion
   149  }
   150  

View as plain text