Skip to content

Commit

Permalink
Ansible: add leader election flags, use lease-based election
Browse files Browse the repository at this point in the history
  • Loading branch information
jmrodri committed Jul 18, 2020
1 parent 25b8054 commit d859ddc
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 16 deletions.
9 changes: 9 additions & 0 deletions changelog/fragments/ansible-leader-election.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# entries is a list of entries to include in
# release notes and/or the migration guide
entries:
- description: >
In the Ansible operator, use controller-runtime's lease-based leader
election instead of SDK's leader-for-life mechnism.
kind: "change"
breaking: false
33 changes: 17 additions & 16 deletions cmd/ansible-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import (
"github.com/operator-framework/operator-sdk/pkg/ansible/watches"
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
kubemetrics "github.com/operator-framework/operator-sdk/pkg/kube-metrics"
"github.com/operator-framework/operator-sdk/pkg/leader"
"github.com/operator-framework/operator-sdk/pkg/log/zap"
"github.com/operator-framework/operator-sdk/pkg/metrics"
sdkVersion "github.com/operator-framework/operator-sdk/version"
Expand Down Expand Up @@ -83,11 +82,26 @@ func main() {
os.Exit(1)
}

// Deprecated: OPERATOR_NAME environment variable is an artifact of the
// legacy operator-sdk project scaffolding. Flag `--leader-election-id`
// should be used instead.
if operatorName, found := os.LookupEnv("OPERATOR_NAME"); found {
log.Info("Environment variable OPERATOR_NAME has been deprecated, use --leader-election-id instead.")
if pflag.CommandLine.Lookup("leader-election-id").Changed {
log.Info("Ignoring OPERATOR_NAME environment variable since --leader-election-id is set")
} else {
f.LeaderElectionID = operatorName
}
}

// Set default manager options
// TODO: probably should expose the host & port as an environment variables
options := manager.Options{
HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort),
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
HealthProbeBindAddress: fmt.Sprintf("%s:%d", metricsHost, healthProbePort),
MetricsBindAddress: fmt.Sprintf("%s:%d", metricsHost, metricsPort),
LeaderElection: f.EnableLeaderElection,
LeaderElectionID: f.LeaderElectionID,
LeaderElectionNamespace: f.LeaderElectionNamespace,
NewClient: func(cache cache.Cache, config *rest.Config, options client.Options) (client.Client, error) {
c, err := client.New(config, options)
if err != nil {
Expand Down Expand Up @@ -166,19 +180,6 @@ func main() {
gvks = append(gvks, w.GroupVersionKind)
}

operatorName, err := k8sutil.GetOperatorName()
if err != nil {
log.Error(err, "Failed to get the operator name")
os.Exit(1)
}

// Become the leader before proceeding
err = leader.Become(context.TODO(), operatorName+"-lock")
if err != nil {
log.Error(err, "Failed to become leader.")
os.Exit(1)
}

addMetrics(context.TODO(), cfg, gvks)
err = mgr.AddHealthzCheck("ping", healthz.Ping)
if err != nil {
Expand Down
21 changes: 21 additions & 0 deletions pkg/ansible/flags/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type Flags struct {
AnsibleVerbosity int
AnsibleRolesPath string
AnsibleCollectionsPath string
EnableLeaderElection bool
LeaderElectionID string
LeaderElectionNamespace string
}

const AnsibleRolesPathEnvVar = "ANSIBLE_ROLES_PATH"
Expand Down Expand Up @@ -82,6 +85,24 @@ func (f *Flags) AddTo(flagSet *pflag.FlagSet) error {
"",
"Path to installed Ansible Collections. If set, collections should be located in {{value}}/ansible_collections/. If unset, collections are assumed to be in ~/.ansible/collections or /usr/share/ansible/collections.",
)
flagSet.BoolVar(&f.EnableLeaderElection,
"enable-leader-election",
false,
"Enable leader election for controller manager. Enabling this will"+
" ensure there is only one active controller manager.",
)
flagSet.StringVar(&f.LeaderElectionID,
"leader-election-id",
"",
"Name of the configmap that is used for holding the leader lock.",
)
flagSet.StringVar(&f.LeaderElectionNamespace,
"leader-election-namespace",
"",
"Namespace in which to create the leader election configmap for"+
" holding the leader lock (required if running locally with leader"+
" election enabled).",
)
err := flagSet.MarkDeprecated("max-workers", "use --max-concurrent-reconciles instead.")
if err != nil {
return fmt.Errorf("flag cannot be deprecated %v", err)
Expand Down

0 comments on commit d859ddc

Please sign in to comment.