Skip to content

Commit

Permalink
Add new -server-label-selector flag
Browse files Browse the repository at this point in the history
This flag removes the implicit reliance on the -release-name and
-resource-prefix flags for selecting the Consul server statefulsets.
With this flag, users explicitly specify the label selector used to
identify the server statefulset and its underlying pods.

The deprecated -release-name flag is still supported. If using the
-resource-prefix flag, we also require the new -server-label-selector
flag.
  • Loading branch information
lkysow committed Dec 17, 2019
1 parent 36d2c97 commit 679fe9e
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 75 deletions.
44 changes: 33 additions & 11 deletions subcommand/server-acl-init/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Command struct {
flags *flag.FlagSet
k8s *k8sflags.K8SFlags
flagReleaseName string
flagServerLabelSelector string
flagResourcePrefix string
flagReplicas int
flagNamespace string
Expand All @@ -54,7 +55,9 @@ type Command struct {
func (c *Command) init() {
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
c.flags.StringVar(&c.flagReleaseName, "release-name", "",
"Name of Consul Helm release")
"Name of Consul Helm release. Deprecated: Use -server-label-selector=release=<release-name> instead")
c.flags.StringVar(&c.flagServerLabelSelector, "server-label-selector", "",
"Selector (label query) to select Consul server statefulset pods, supports '=', '==', and '!='. (e.g. -l key1=value1,key2=value2)")
c.flags.StringVar(&c.flagResourcePrefix, "resource-prefix", "",
"Prefix to use for Kubernetes resources. If not set, the \"<release-name>-consul\" prefix is used, where <release-name> is the value set by the -release-name flag.")
c.flags.IntVar(&c.flagReplicas, "expected-replicas", 1,
Expand Down Expand Up @@ -118,10 +121,23 @@ func (c *Command) Run(args []string) int {
c.UI.Error(fmt.Sprintf("%q is not a valid timeout: %s", c.flagTimeout, err))
return 1
}
if c.flagReleaseName == "" {
c.UI.Error("-release-name must be set")
if c.flagReleaseName != "" && c.flagServerLabelSelector != "" {
c.UI.Error("-release-name and -server-label-selector cannot both be set")
return 1
}
if c.flagServerLabelSelector != "" && c.flagResourcePrefix == "" {
c.UI.Error("if -server-label-selector is set -resource-prefix must also be set")
return 1
}
if c.flagReleaseName == "" && c.flagServerLabelSelector == "" {
c.UI.Error("-release-name or -server-label-selector must be set")
return 1
}
// If only the -release-name is set, we use it as the label selector.
if c.flagReleaseName != "" {
c.flagServerLabelSelector = fmt.Sprintf("app=consul,component=server,release=%s", c.flagReleaseName)
}

var cancel context.CancelFunc
c.cmdTimeout, cancel = context.WithTimeout(context.Background(), timeout)
// The context will only ever be intentionally ended by the timeout.
Expand Down Expand Up @@ -149,15 +165,19 @@ func (c *Command) Run(args []string) int {
// Wait if there's a rollout of servers.
ssName := c.withPrefix("server")
err = c.untilSucceeds(fmt.Sprintf("waiting for rollout of statefulset %s", ssName), func() error {
ss, err := c.clientset.AppsV1().StatefulSets(c.flagNamespace).Get(ssName, metav1.GetOptions{})
// Note: We can't use the -server-label-selector flag to find the statefulset
// because in older versions of consul-helm it wasn't labeled with
// component: server. We also can't drop that label because it's required
// for targeting the right server Pods.
statefulset, err := c.clientset.AppsV1().StatefulSets(c.flagNamespace).Get(ssName, metav1.GetOptions{})
if err != nil {
return err
}
if ss.Status.CurrentRevision == ss.Status.UpdateRevision {
if statefulset.Status.CurrentRevision == statefulset.Status.UpdateRevision {
return nil
}
return fmt.Errorf("rollout is in progress (CurrentRevision=%s UpdateRevision=%s)",
ss.Status.CurrentRevision, ss.Status.UpdateRevision)
statefulset.Status.CurrentRevision, statefulset.Status.UpdateRevision)
}, logger)
if err != nil {
logger.Error(err.Error())
Expand Down Expand Up @@ -296,15 +316,14 @@ func (c *Command) getConsulServers(logger hclog.Logger, n int) ([]podAddr, error
var serverPods *apiv1.PodList
err := c.untilSucceeds("discovering Consul server pods",
func() error {
labelSelector := fmt.Sprintf("component=server, app=consul, release=%s", c.flagReleaseName)
var err error
serverPods, err = c.clientset.CoreV1().Pods(c.flagNamespace).List(metav1.ListOptions{LabelSelector: labelSelector})
serverPods, err = c.clientset.CoreV1().Pods(c.flagNamespace).List(metav1.ListOptions{LabelSelector: c.flagServerLabelSelector})
if err != nil {
return err
}

if len(serverPods.Items) == 0 {
return fmt.Errorf("no server pods with labels %q found", labelSelector)
return fmt.Errorf("no server pods with labels %q found", c.flagServerLabelSelector)
}

if len(serverPods.Items) < n {
Expand Down Expand Up @@ -664,7 +683,7 @@ func (c *Command) configureConnectInject(logger hclog.Logger, consulClient *api.
// Now we're ready to set up Consul's auth method.
authMethodTmpl := api.ACLAuthMethod{
Name: authMethodName,
Description: fmt.Sprintf("Consul %s default Kubernetes AuthMethod", c.flagReleaseName),
Description: "Kubernetes AuthMethod",
Type: "kubernetes",
Config: map[string]interface{}{
"Host": fmt.Sprintf("https://%s:443", kubeSvc.Spec.ClusterIP),
Expand All @@ -685,7 +704,7 @@ func (c *Command) configureConnectInject(logger hclog.Logger, consulClient *api.

// Create the binding rule.
abr := api.ACLBindingRule{
Description: fmt.Sprintf("Consul %s default binding rule", c.flagReleaseName),
Description: "Kubernetes binding rule",
AuthMethod: authMethod.Name,
BindType: api.BindingRuleBindTypeService,
BindName: "${serviceaccount.name}",
Expand Down Expand Up @@ -727,6 +746,9 @@ func (c *Command) withPrefix(resource string) string {
if c.flagResourcePrefix != "" {
return fmt.Sprintf("%s-%s", c.flagResourcePrefix, resource)
}
// This is to support an older version of the Helm chart that only specified
// the -release-name flag. We ensure that this is set if -resource-prefix
// is not set when parsing the flags.
return fmt.Sprintf("%s-consul-%s", c.flagReleaseName, resource)
}

Expand Down
Loading

0 comments on commit 679fe9e

Please sign in to comment.