github.com/DerekStrickland/consul@v1.4.5/agent/consul/autopilot.go (about)

     1  package consul
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"strconv"
     8  
     9  	"github.com/armon/go-metrics"
    10  	"github.com/hashicorp/consul/agent/consul/autopilot"
    11  	"github.com/hashicorp/consul/agent/metadata"
    12  	"github.com/hashicorp/raft"
    13  	"github.com/hashicorp/serf/serf"
    14  )
    15  
    16  // AutopilotDelegate is a Consul delegate for autopilot operations.
    17  type AutopilotDelegate struct {
    18  	server *Server
    19  }
    20  
    21  func (d *AutopilotDelegate) AutopilotConfig() *autopilot.Config {
    22  	return d.server.getOrCreateAutopilotConfig()
    23  }
    24  
    25  func (d *AutopilotDelegate) FetchStats(ctx context.Context, servers []serf.Member) map[string]*autopilot.ServerStats {
    26  	return d.server.statsFetcher.Fetch(ctx, servers)
    27  }
    28  
    29  func (d *AutopilotDelegate) IsServer(m serf.Member) (*autopilot.ServerInfo, error) {
    30  	if m.Tags["role"] != "consul" {
    31  		return nil, nil
    32  	}
    33  
    34  	portStr := m.Tags["port"]
    35  	port, err := strconv.Atoi(portStr)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	buildVersion, err := metadata.Build(&m)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	server := &autopilot.ServerInfo{
    46  		Name:   m.Name,
    47  		ID:     m.Tags["id"],
    48  		Addr:   &net.TCPAddr{IP: m.Addr, Port: port},
    49  		Build:  *buildVersion,
    50  		Status: m.Status,
    51  	}
    52  	return server, nil
    53  }
    54  
    55  // Heartbeat a metric for monitoring if we're the leader
    56  func (d *AutopilotDelegate) NotifyHealth(health autopilot.OperatorHealthReply) {
    57  	if d.server.raft.State() == raft.Leader {
    58  		metrics.SetGauge([]string{"autopilot", "failure_tolerance"}, float32(health.FailureTolerance))
    59  		if health.Healthy {
    60  			metrics.SetGauge([]string{"autopilot", "healthy"}, 1)
    61  		} else {
    62  			metrics.SetGauge([]string{"autopilot", "healthy"}, 0)
    63  		}
    64  	}
    65  }
    66  
    67  func (d *AutopilotDelegate) PromoteNonVoters(conf *autopilot.Config, health autopilot.OperatorHealthReply) ([]raft.Server, error) {
    68  	future := d.server.raft.GetConfiguration()
    69  	if err := future.Error(); err != nil {
    70  		return nil, fmt.Errorf("failed to get raft configuration: %v", err)
    71  	}
    72  
    73  	return autopilot.PromoteStableServers(conf, health, future.Configuration().Servers), nil
    74  }
    75  
    76  func (d *AutopilotDelegate) Raft() *raft.Raft {
    77  	return d.server.raft
    78  }
    79  
    80  func (d *AutopilotDelegate) Serf() *serf.Serf {
    81  	return d.server.serfLAN
    82  }