package consul import ( "fmt" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/autopilot" "github.com/hashicorp/consul/agent/structs" ) // AutopilotGetConfiguration is used to retrieve the current Autopilot configuration. func (op *Operator) AutopilotGetConfiguration(args *structs.DCSpecificRequest, reply *autopilot.Config) error { if done, err := op.srv.forward("Operator.AutopilotGetConfiguration", args, args, reply); done { return err } // This action requires operator read access. identity, rule, err := op.srv.ResolveTokenToIdentityAndAuthorizer(args.Token) if err != nil { return err } if err := op.srv.validateEnterpriseToken(identity); err != nil { return err } if rule != nil && rule.OperatorRead(nil) != acl.Allow { return acl.ErrPermissionDenied } state := op.srv.fsm.State() _, config, err := state.AutopilotConfig() if err != nil { return err } if config == nil { return fmt.Errorf("autopilot config not initialized yet") } *reply = *config return nil } // AutopilotSetConfiguration is used to set the current Autopilot configuration. func (op *Operator) AutopilotSetConfiguration(args *structs.AutopilotSetConfigRequest, reply *bool) error { if done, err := op.srv.forward("Operator.AutopilotSetConfiguration", args, args, reply); done { return err } // This action requires operator write access. identity, rule, err := op.srv.ResolveTokenToIdentityAndAuthorizer(args.Token) if err != nil { return err } if err := op.srv.validateEnterpriseToken(identity); err != nil { return err } if rule != nil && rule.OperatorWrite(nil) != acl.Allow { return acl.ErrPermissionDenied } // Apply the update resp, err := op.srv.raftApply(structs.AutopilotRequestType, args) if err != nil { op.logger.Error("Raft apply failed", "error", err) return err } if respErr, ok := resp.(error); ok { return respErr } // Check if the return type is a bool. if respBool, ok := resp.(bool); ok { *reply = respBool } return nil } // ServerHealth is used to get the current health of the servers. func (op *Operator) ServerHealth(args *structs.DCSpecificRequest, reply *autopilot.OperatorHealthReply) error { // This must be sent to the leader, so we fix the args since we are // re-using a structure where we don't support all the options. args.RequireConsistent = true args.AllowStale = false if done, err := op.srv.forward("Operator.ServerHealth", args, args, reply); done { return err } // This action requires operator read access. identity, rule, err := op.srv.ResolveTokenToIdentityAndAuthorizer(args.Token) if err != nil { return err } if err := op.srv.validateEnterpriseToken(identity); err != nil { return err } if rule != nil && rule.OperatorRead(nil) != acl.Allow { return acl.ErrPermissionDenied } // Exit early if the min Raft version is too low minRaftProtocol, err := op.srv.autopilot.MinRaftProtocol() if err != nil { return fmt.Errorf("error getting server raft protocol versions: %s", err) } if minRaftProtocol < 3 { return fmt.Errorf("all servers must have raft_protocol set to 3 or higher to use this endpoint") } *reply = op.srv.autopilot.GetClusterHealth() return nil }