...

Source file src/k8s.io/client-go/tools/leaderelection/resourcelock/multilock.go

Documentation: k8s.io/client-go/tools/leaderelection/resourcelock

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package resourcelock
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/json"
    23  
    24  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    25  )
    26  
    27  const (
    28  	UnknownLeader = "leaderelection.k8s.io/unknown"
    29  )
    30  
    31  // MultiLock is used for lock's migration
    32  type MultiLock struct {
    33  	Primary   Interface
    34  	Secondary Interface
    35  }
    36  
    37  // Get returns the older election record of the lock
    38  func (ml *MultiLock) Get(ctx context.Context) (*LeaderElectionRecord, []byte, error) {
    39  	primary, primaryRaw, err := ml.Primary.Get(ctx)
    40  	if err != nil {
    41  		return nil, nil, err
    42  	}
    43  
    44  	secondary, secondaryRaw, err := ml.Secondary.Get(ctx)
    45  	if err != nil {
    46  		// Lock is held by old client
    47  		if apierrors.IsNotFound(err) && primary.HolderIdentity != ml.Identity() {
    48  			return primary, primaryRaw, nil
    49  		}
    50  		return nil, nil, err
    51  	}
    52  
    53  	if primary.HolderIdentity != secondary.HolderIdentity {
    54  		primary.HolderIdentity = UnknownLeader
    55  		primaryRaw, err = json.Marshal(primary)
    56  		if err != nil {
    57  			return nil, nil, err
    58  		}
    59  	}
    60  	return primary, ConcatRawRecord(primaryRaw, secondaryRaw), nil
    61  }
    62  
    63  // Create attempts to create both primary lock and secondary lock
    64  func (ml *MultiLock) Create(ctx context.Context, ler LeaderElectionRecord) error {
    65  	err := ml.Primary.Create(ctx, ler)
    66  	if err != nil && !apierrors.IsAlreadyExists(err) {
    67  		return err
    68  	}
    69  	return ml.Secondary.Create(ctx, ler)
    70  }
    71  
    72  // Update will update and existing annotation on both two resources.
    73  func (ml *MultiLock) Update(ctx context.Context, ler LeaderElectionRecord) error {
    74  	err := ml.Primary.Update(ctx, ler)
    75  	if err != nil {
    76  		return err
    77  	}
    78  	_, _, err = ml.Secondary.Get(ctx)
    79  	if err != nil && apierrors.IsNotFound(err) {
    80  		return ml.Secondary.Create(ctx, ler)
    81  	}
    82  	return ml.Secondary.Update(ctx, ler)
    83  }
    84  
    85  // RecordEvent in leader election while adding meta-data
    86  func (ml *MultiLock) RecordEvent(s string) {
    87  	ml.Primary.RecordEvent(s)
    88  	ml.Secondary.RecordEvent(s)
    89  }
    90  
    91  // Describe is used to convert details on current resource lock
    92  // into a string
    93  func (ml *MultiLock) Describe() string {
    94  	return ml.Primary.Describe()
    95  }
    96  
    97  // Identity returns the Identity of the lock
    98  func (ml *MultiLock) Identity() string {
    99  	return ml.Primary.Identity()
   100  }
   101  
   102  func ConcatRawRecord(primaryRaw, secondaryRaw []byte) []byte {
   103  	return bytes.Join([][]byte{primaryRaw, secondaryRaw}, []byte(","))
   104  }
   105  

View as plain text