github.phpd.cn/hashicorp/consul@v1.4.5/agent/consul/operator_autopilot_endpoint.go (about)

     1  package consul
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hashicorp/consul/acl"
     7  	"github.com/hashicorp/consul/agent/consul/autopilot"
     8  	"github.com/hashicorp/consul/agent/structs"
     9  )
    10  
    11  // AutopilotGetConfiguration is used to retrieve the current Autopilot configuration.
    12  func (op *Operator) AutopilotGetConfiguration(args *structs.DCSpecificRequest, reply *autopilot.Config) error {
    13  	if done, err := op.srv.forward("Operator.AutopilotGetConfiguration", args, args, reply); done {
    14  		return err
    15  	}
    16  
    17  	// This action requires operator read access.
    18  	rule, err := op.srv.ResolveToken(args.Token)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	if rule != nil && !rule.OperatorRead() {
    23  		return acl.ErrPermissionDenied
    24  	}
    25  
    26  	state := op.srv.fsm.State()
    27  	_, config, err := state.AutopilotConfig()
    28  	if err != nil {
    29  		return err
    30  	}
    31  	if config == nil {
    32  		return fmt.Errorf("autopilot config not initialized yet")
    33  	}
    34  
    35  	*reply = *config
    36  
    37  	return nil
    38  }
    39  
    40  // AutopilotSetConfiguration is used to set the current Autopilot configuration.
    41  func (op *Operator) AutopilotSetConfiguration(args *structs.AutopilotSetConfigRequest, reply *bool) error {
    42  	if done, err := op.srv.forward("Operator.AutopilotSetConfiguration", args, args, reply); done {
    43  		return err
    44  	}
    45  
    46  	// This action requires operator write access.
    47  	rule, err := op.srv.ResolveToken(args.Token)
    48  	if err != nil {
    49  		return err
    50  	}
    51  	if rule != nil && !rule.OperatorWrite() {
    52  		return acl.ErrPermissionDenied
    53  	}
    54  
    55  	// Apply the update
    56  	resp, err := op.srv.raftApply(structs.AutopilotRequestType, args)
    57  	if err != nil {
    58  		op.srv.logger.Printf("[ERR] consul.operator: Apply failed: %v", err)
    59  		return err
    60  	}
    61  	if respErr, ok := resp.(error); ok {
    62  		return respErr
    63  	}
    64  
    65  	// Check if the return type is a bool.
    66  	if respBool, ok := resp.(bool); ok {
    67  		*reply = respBool
    68  	}
    69  	return nil
    70  }
    71  
    72  // ServerHealth is used to get the current health of the servers.
    73  func (op *Operator) ServerHealth(args *structs.DCSpecificRequest, reply *autopilot.OperatorHealthReply) error {
    74  	// This must be sent to the leader, so we fix the args since we are
    75  	// re-using a structure where we don't support all the options.
    76  	args.RequireConsistent = true
    77  	args.AllowStale = false
    78  	if done, err := op.srv.forward("Operator.ServerHealth", args, args, reply); done {
    79  		return err
    80  	}
    81  
    82  	// This action requires operator read access.
    83  	rule, err := op.srv.ResolveToken(args.Token)
    84  	if err != nil {
    85  		return err
    86  	}
    87  	if rule != nil && !rule.OperatorRead() {
    88  		return acl.ErrPermissionDenied
    89  	}
    90  
    91  	// Exit early if the min Raft version is too low
    92  	minRaftProtocol, err := op.srv.autopilot.MinRaftProtocol()
    93  	if err != nil {
    94  		return fmt.Errorf("error getting server raft protocol versions: %s", err)
    95  	}
    96  	if minRaftProtocol < 3 {
    97  		return fmt.Errorf("all servers must have raft_protocol set to 3 or higher to use this endpoint")
    98  	}
    99  
   100  	*reply = op.srv.autopilot.GetClusterHealth()
   101  
   102  	return nil
   103  }