Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement leaderelection type getter via restmapper #1

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkg/client/apiutil/apimachinery.go
Expand Up @@ -36,6 +36,9 @@ import (
func NewDiscoveryRESTMapper(c *rest.Config) (meta.RESTMapper, error) {
// Get a mapper
dc := discovery.NewDiscoveryClientForConfigOrDie(c)

// TODO(mszostok): here we have useful info about all supported groups and resource
// in api-server
gr, err := restmapper.GetAPIGroupResources(dc)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here we have info about all supported groups that we could use for checking if Lease is available, but it's not exposed, so I decided to use the RESTMapping method from mapper and assert error via IsNoMatchError

if err != nil {
return nil, err
Expand Down
6 changes: 5 additions & 1 deletion pkg/leaderelection/leader_election.go
Expand Up @@ -43,6 +43,10 @@ type Options struct {
// LeaderElectionID determines the name of the configmap that leader election
// will use for holding the leader lock.
LeaderElectionID string

// LeaderElectionLockType determines leader election lock type for holding
// the leader lock information.
LeaderElectionLockType LockType
}

// NewResourceLock creates a new config map resource lock for use in a leader
Expand Down Expand Up @@ -80,7 +84,7 @@ func NewResourceLock(config *rest.Config, recorderProvider recorder.Provider, op
}

// TODO(JoelSpeed): switch to leaderelection object in 1.12
return resourcelock.New(resourcelock.ConfigMapsResourceLock,
return resourcelock.New(options.LeaderElectionLockType.Name(),
options.LeaderElectionNamespace,
options.LeaderElectionID,
client.CoreV1(),
Expand Down
50 changes: 50 additions & 0 deletions pkg/leaderelection/leader_lock_types.go
@@ -0,0 +1,50 @@
package leaderelection

import (
"fmt"

coordinationv1 "k8s.io/api/coordination/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/leaderelection/resourcelock"
)

type LockType int

const (
UndefinedResourceLock LockType = iota
ConfigMapsResourceLock
LeasesResourceLock
EndpointsResourceLock
)

func (l LockType) Name() string {
switch l {
case EndpointsResourceLock:
return resourcelock.EndpointsResourceLock
case ConfigMapsResourceLock:
return resourcelock.ConfigMapsResourceLock
case LeasesResourceLock:
return resourcelock.LeasesResourceLock
default:
return ""
}
}

// GetPreferredLockType chooses the Lease lock if `lease.coordination.k8s.io` is available.
// Otherwise, the ConfigMap resource lock is used.
func GetPreferredLockType(mapper meta.RESTMapper) (LockType, error) {
// check if new leader election api is available
_, err := mapper.RESTMapping(schema.GroupKind{
Kind: "Lease",
Group: coordinationv1.GroupName,
})
switch {
case err == nil:
return LeasesResourceLock, nil
case meta.IsNoMatchError(err):
return ConfigMapsResourceLock, nil
default:
return UndefinedResourceLock, fmt.Errorf("unable to retrieve supported server groups: %v", err)
}
}
13 changes: 13 additions & 0 deletions pkg/manager/manager.go
Expand Up @@ -118,6 +118,10 @@ type Options struct {
// will use for holding the leader lock.
LeaderElectionID string

// LeaderElectionLockType determines leader election lock type for holding
// the leader lock information.
LeaderElectionLockType leaderelection.LockType

// LeaseDuration is the duration that non-leader candidates will
// wait to force acquire leadership. This is measured against time of
// last observed ack. Default is 15 seconds.
Expand Down Expand Up @@ -245,10 +249,19 @@ func New(config *rest.Config, options Options) (Manager, error) {
}

// Create the resource lock to enable leader election)
if options.LeaderElectionLockType == leaderelection.UndefinedResourceLock { // this should be moved somehow into `setOptionsDefaults` func
lockType, err := leaderelection.GetPreferredLockType(mapper)
if err != nil {
return nil, err
}
options.LeaderElectionLockType = lockType
}

resourceLock, err := options.newResourceLock(config, recorderProvider, leaderelection.Options{
LeaderElection: options.LeaderElection,
LeaderElectionID: options.LeaderElectionID,
LeaderElectionNamespace: options.LeaderElectionNamespace,
LeaderElectionLockType: options.LeaderElectionLockType,
})
if err != nil {
return nil, err
Expand Down