github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/agent/consul/version_checker.go (about)

     1  package consul
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  	"time"
     7  
     8  	log "github.com/hashicorp/go-hclog"
     9  	version "github.com/hashicorp/go-version"
    10  	"github.com/hashicorp/nomad/helper"
    11  )
    12  
    13  // checkConsulTLSSkipVerify logs if Consul does not support TLSSkipVerify on
    14  // checks and is intended to be run in a goroutine.
    15  func checkConsulTLSSkipVerify(ctx context.Context, logger log.Logger, client AgentAPI, done chan struct{}) {
    16  	const (
    17  		baseline = time.Second
    18  		limit    = 20 * time.Second
    19  	)
    20  
    21  	defer close(done)
    22  
    23  	i := uint64(0)
    24  
    25  	timer, stop := helper.NewSafeTimer(limit)
    26  	defer stop()
    27  
    28  	for {
    29  		self, err := client.Self()
    30  		if err == nil {
    31  			if supportsTLSSkipVerify(self) {
    32  				logger.Trace("Consul supports TLSSkipVerify")
    33  			} else {
    34  				logger.Warn("Consul does NOT support TLSSkipVerify; please upgrade Consul",
    35  					"min_version", consulTLSSkipVerifyMinVersion)
    36  			}
    37  			return
    38  		}
    39  
    40  		backoff := (1 << (2 * i)) * baseline
    41  		if backoff > limit {
    42  			backoff = limit
    43  		} else {
    44  			i++
    45  		}
    46  
    47  		timer.Reset(backoff)
    48  
    49  		select {
    50  		case <-ctx.Done():
    51  			return
    52  		case <-timer.C:
    53  		}
    54  	}
    55  }
    56  
    57  var consulTLSSkipVerifyMinVersion = version.Must(version.NewVersion("0.7.2"))
    58  
    59  // supportsTLSSkipVerify returns true if Consul supports TLSSkipVerify.
    60  func supportsTLSSkipVerify(self map[string]map[string]interface{}) bool {
    61  	member, ok := self["Member"]
    62  	if !ok {
    63  		return false
    64  	}
    65  	tagsI, ok := member["Tags"]
    66  	if !ok {
    67  		return false
    68  	}
    69  	tags, ok := tagsI.(map[string]interface{})
    70  	if !ok {
    71  		return false
    72  	}
    73  	buildI, ok := tags["build"]
    74  	if !ok {
    75  		return false
    76  	}
    77  	build, ok := buildI.(string)
    78  	if !ok {
    79  		return false
    80  	}
    81  	parts := strings.SplitN(build, ":", 2)
    82  	if len(parts) != 2 {
    83  		return false
    84  	}
    85  	v, err := version.NewVersion(parts[0])
    86  	if err != nil {
    87  		return false
    88  	}
    89  	if v.LessThan(consulTLSSkipVerifyMinVersion) {
    90  		return false
    91  	}
    92  	return true
    93  }