mirror of https://github.com/status-im/consul.git
Merge pull request #2097 from hashicorp/f-checkid-type
`types` package w/ CheckID
This commit is contained in:
commit
14ec46b3cf
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/hashicorp/consul/consul/state"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/lib"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
)
|
||||
|
@ -74,19 +75,19 @@ type Agent struct {
|
|||
state localState
|
||||
|
||||
// checkMonitors maps the check ID to an associated monitor
|
||||
checkMonitors map[string]*CheckMonitor
|
||||
checkMonitors map[types.CheckID]*CheckMonitor
|
||||
|
||||
// checkHTTPs maps the check ID to an associated HTTP check
|
||||
checkHTTPs map[string]*CheckHTTP
|
||||
checkHTTPs map[types.CheckID]*CheckHTTP
|
||||
|
||||
// checkTCPs maps the check ID to an associated TCP check
|
||||
checkTCPs map[string]*CheckTCP
|
||||
checkTCPs map[types.CheckID]*CheckTCP
|
||||
|
||||
// checkTTLs maps the check ID to an associated check TTL
|
||||
checkTTLs map[string]*CheckTTL
|
||||
checkTTLs map[types.CheckID]*CheckTTL
|
||||
|
||||
// checkDockers maps the check ID to an associated Docker Exec based check
|
||||
checkDockers map[string]*CheckDocker
|
||||
checkDockers map[types.CheckID]*CheckDocker
|
||||
|
||||
// checkLock protects updates to the check* maps
|
||||
checkLock sync.Mutex
|
||||
|
@ -176,11 +177,11 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) {
|
|||
config: config,
|
||||
logger: log.New(logOutput, "", log.LstdFlags),
|
||||
logOutput: logOutput,
|
||||
checkMonitors: make(map[string]*CheckMonitor),
|
||||
checkTTLs: make(map[string]*CheckTTL),
|
||||
checkHTTPs: make(map[string]*CheckHTTP),
|
||||
checkTCPs: make(map[string]*CheckTCP),
|
||||
checkDockers: make(map[string]*CheckDocker),
|
||||
checkMonitors: make(map[types.CheckID]*CheckMonitor),
|
||||
checkTTLs: make(map[types.CheckID]*CheckTTL),
|
||||
checkHTTPs: make(map[types.CheckID]*CheckHTTP),
|
||||
checkTCPs: make(map[types.CheckID]*CheckTCP),
|
||||
checkDockers: make(map[types.CheckID]*CheckDocker),
|
||||
eventCh: make(chan serf.UserEvent, 1024),
|
||||
eventBuf: make([]*UserEvent, 256),
|
||||
shutdownCh: make(chan struct{}),
|
||||
|
@ -696,7 +697,7 @@ func (a *Agent) purgeService(serviceID string) error {
|
|||
|
||||
// persistCheck saves a check definition to the local agent's state directory
|
||||
func (a *Agent) persistCheck(check *structs.HealthCheck, chkType *CheckType) error {
|
||||
checkPath := filepath.Join(a.config.DataDir, checksDir, stringHash(check.CheckID))
|
||||
checkPath := filepath.Join(a.config.DataDir, checksDir, checkIDHash(check.CheckID))
|
||||
|
||||
// Create the persisted check
|
||||
wrapped := persistedCheck{
|
||||
|
@ -724,8 +725,8 @@ func (a *Agent) persistCheck(check *structs.HealthCheck, chkType *CheckType) err
|
|||
}
|
||||
|
||||
// purgeCheck removes a persisted check definition file from the data dir
|
||||
func (a *Agent) purgeCheck(checkID string) error {
|
||||
checkPath := filepath.Join(a.config.DataDir, checksDir, stringHash(checkID))
|
||||
func (a *Agent) purgeCheck(checkID types.CheckID) error {
|
||||
checkPath := filepath.Join(a.config.DataDir, checksDir, checkIDHash(checkID))
|
||||
if _, err := os.Stat(checkPath); err == nil {
|
||||
return os.Remove(checkPath)
|
||||
}
|
||||
|
@ -791,7 +792,7 @@ func (a *Agent) AddService(service *structs.NodeService, chkTypes CheckTypes, pe
|
|||
}
|
||||
check := &structs.HealthCheck{
|
||||
Node: a.config.NodeName,
|
||||
CheckID: checkID,
|
||||
CheckID: types.CheckID(checkID),
|
||||
Name: fmt.Sprintf("Service '%s' check", service.Service),
|
||||
Status: structs.HealthCritical,
|
||||
Notes: chkType.Notes,
|
||||
|
@ -998,7 +999,7 @@ func (a *Agent) AddCheck(check *structs.HealthCheck, chkType *CheckType, persist
|
|||
|
||||
// RemoveCheck is used to remove a health check.
|
||||
// The agent will make a best effort to ensure it is deregistered
|
||||
func (a *Agent) RemoveCheck(checkID string, persist bool) error {
|
||||
func (a *Agent) RemoveCheck(checkID types.CheckID, persist bool) error {
|
||||
// Validate CheckID
|
||||
if checkID == "" {
|
||||
return fmt.Errorf("CheckID missing")
|
||||
|
@ -1041,7 +1042,7 @@ func (a *Agent) RemoveCheck(checkID string, persist bool) error {
|
|||
|
||||
// UpdateCheck is used to update the status of a check.
|
||||
// This can only be used with checks of the TTL type.
|
||||
func (a *Agent) UpdateCheck(checkID, status, output string) error {
|
||||
func (a *Agent) UpdateCheck(checkID types.CheckID, status, output string) error {
|
||||
a.checkLock.Lock()
|
||||
defer a.checkLock.Unlock()
|
||||
|
||||
|
@ -1090,7 +1091,7 @@ func (a *Agent) persistCheckState(check *CheckTTL, status, output string) error
|
|||
}
|
||||
|
||||
// Write the state to the file
|
||||
file := filepath.Join(dir, stringHash(check.CheckID))
|
||||
file := filepath.Join(dir, checkIDHash(check.CheckID))
|
||||
if err := ioutil.WriteFile(file, buf, 0600); err != nil {
|
||||
return fmt.Errorf("failed writing file %q: %s", file, err)
|
||||
}
|
||||
|
@ -1101,7 +1102,7 @@ func (a *Agent) persistCheckState(check *CheckTTL, status, output string) error
|
|||
// loadCheckState is used to restore the persisted state of a check.
|
||||
func (a *Agent) loadCheckState(check *structs.HealthCheck) error {
|
||||
// Try to read the persisted state for this check
|
||||
file := filepath.Join(a.config.DataDir, checkStateDir, stringHash(check.CheckID))
|
||||
file := filepath.Join(a.config.DataDir, checkStateDir, checkIDHash(check.CheckID))
|
||||
buf, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -1129,8 +1130,8 @@ func (a *Agent) loadCheckState(check *structs.HealthCheck) error {
|
|||
}
|
||||
|
||||
// purgeCheckState is used to purge the state of a check from the data dir
|
||||
func (a *Agent) purgeCheckState(checkID string) error {
|
||||
file := filepath.Join(a.config.DataDir, checkStateDir, stringHash(checkID))
|
||||
func (a *Agent) purgeCheckState(checkID types.CheckID) error {
|
||||
file := filepath.Join(a.config.DataDir, checkStateDir, checkIDHash(checkID))
|
||||
err := os.Remove(file)
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
|
@ -1393,22 +1394,22 @@ func (a *Agent) unloadChecks() error {
|
|||
// snapshotCheckState is used to snapshot the current state of the health
|
||||
// checks. This is done before we reload our checks, so that we can properly
|
||||
// restore into the same state.
|
||||
func (a *Agent) snapshotCheckState() map[string]*structs.HealthCheck {
|
||||
func (a *Agent) snapshotCheckState() map[types.CheckID]*structs.HealthCheck {
|
||||
return a.state.Checks()
|
||||
}
|
||||
|
||||
// restoreCheckState is used to reset the health state based on a snapshot.
|
||||
// This is done after we finish the reload to avoid any unnecessary flaps
|
||||
// in health state and potential session invalidations.
|
||||
func (a *Agent) restoreCheckState(snap map[string]*structs.HealthCheck) {
|
||||
func (a *Agent) restoreCheckState(snap map[types.CheckID]*structs.HealthCheck) {
|
||||
for id, check := range snap {
|
||||
a.state.UpdateCheck(id, check.Status, check.Output)
|
||||
}
|
||||
}
|
||||
|
||||
// serviceMaintCheckID returns the ID of a given service's maintenance check
|
||||
func serviceMaintCheckID(serviceID string) string {
|
||||
return fmt.Sprintf("%s:%s", serviceMaintCheckPrefix, serviceID)
|
||||
func serviceMaintCheckID(serviceID string) types.CheckID {
|
||||
return types.CheckID(fmt.Sprintf("%s:%s", serviceMaintCheckPrefix, serviceID))
|
||||
}
|
||||
|
||||
// EnableServiceMaintenance will register a false health check against the given
|
||||
|
|
|
@ -2,12 +2,14 @@ package agent
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
)
|
||||
|
||||
type AgentSelf struct {
|
||||
|
@ -129,7 +131,7 @@ func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Requ
|
|||
}
|
||||
|
||||
func (s *HTTPServer) AgentDeregisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
checkID := strings.TrimPrefix(req.URL.Path, "/v1/agent/check/deregister/")
|
||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/deregister/"))
|
||||
if err := s.agent.RemoveCheck(checkID, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -138,7 +140,7 @@ func (s *HTTPServer) AgentDeregisterCheck(resp http.ResponseWriter, req *http.Re
|
|||
}
|
||||
|
||||
func (s *HTTPServer) AgentCheckPass(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
checkID := strings.TrimPrefix(req.URL.Path, "/v1/agent/check/pass/")
|
||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/pass/"))
|
||||
note := req.URL.Query().Get("note")
|
||||
if err := s.agent.UpdateCheck(checkID, structs.HealthPassing, note); err != nil {
|
||||
return nil, err
|
||||
|
@ -148,7 +150,7 @@ func (s *HTTPServer) AgentCheckPass(resp http.ResponseWriter, req *http.Request)
|
|||
}
|
||||
|
||||
func (s *HTTPServer) AgentCheckWarn(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
checkID := strings.TrimPrefix(req.URL.Path, "/v1/agent/check/warn/")
|
||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/warn/"))
|
||||
note := req.URL.Query().Get("note")
|
||||
if err := s.agent.UpdateCheck(checkID, structs.HealthWarning, note); err != nil {
|
||||
return nil, err
|
||||
|
@ -158,7 +160,7 @@ func (s *HTTPServer) AgentCheckWarn(resp http.ResponseWriter, req *http.Request)
|
|||
}
|
||||
|
||||
func (s *HTTPServer) AgentCheckFail(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
checkID := strings.TrimPrefix(req.URL.Path, "/v1/agent/check/fail/")
|
||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/fail/"))
|
||||
note := req.URL.Query().Get("note")
|
||||
if err := s.agent.UpdateCheck(checkID, structs.HealthCritical, note); err != nil {
|
||||
return nil, err
|
||||
|
@ -211,7 +213,7 @@ func (s *HTTPServer) AgentCheckUpdate(resp http.ResponseWriter, req *http.Reques
|
|||
update.Output[:CheckBufSize], CheckBufSize, total)
|
||||
}
|
||||
|
||||
checkID := strings.TrimPrefix(req.URL.Path, "/v1/agent/check/update/")
|
||||
checkID := types.CheckID(strings.TrimPrefix(req.URL.Path, "/v1/agent/check/update/"))
|
||||
if err := s.agent.UpdateCheck(checkID, update.Status, update.Output); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/testutil"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
)
|
||||
|
||||
|
@ -61,7 +62,7 @@ func TestHTTPAgentChecks(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("Err: %v", err)
|
||||
}
|
||||
val := obj.(map[string]*structs.HealthCheck)
|
||||
val := obj.(map[types.CheckID]*structs.HealthCheck)
|
||||
if len(val) != 1 {
|
||||
t.Fatalf("bad checks: %v", obj)
|
||||
}
|
||||
|
@ -294,21 +295,22 @@ func TestHTTPAgentRegisterCheck(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure we have a check mapping
|
||||
if _, ok := srv.agent.state.Checks()["test"]; !ok {
|
||||
checkID := types.CheckID("test")
|
||||
if _, ok := srv.agent.state.Checks()[checkID]; !ok {
|
||||
t.Fatalf("missing test check")
|
||||
}
|
||||
|
||||
if _, ok := srv.agent.checkTTLs["test"]; !ok {
|
||||
if _, ok := srv.agent.checkTTLs[checkID]; !ok {
|
||||
t.Fatalf("missing test check ttl")
|
||||
}
|
||||
|
||||
// Ensure the token was configured
|
||||
if token := srv.agent.state.CheckToken("test"); token == "" {
|
||||
if token := srv.agent.state.CheckToken(checkID); token == "" {
|
||||
t.Fatalf("missing token")
|
||||
}
|
||||
|
||||
// By default, checks start in critical state.
|
||||
state := srv.agent.state.Checks()["test"]
|
||||
state := srv.agent.state.Checks()[checkID]
|
||||
if state.Status != structs.HealthCritical {
|
||||
t.Fatalf("bad: %v", state)
|
||||
}
|
||||
|
@ -343,15 +345,16 @@ func TestHTTPAgentRegisterCheckPassing(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure we have a check mapping
|
||||
if _, ok := srv.agent.state.Checks()["test"]; !ok {
|
||||
checkID := types.CheckID("test")
|
||||
if _, ok := srv.agent.state.Checks()[checkID]; !ok {
|
||||
t.Fatalf("missing test check")
|
||||
}
|
||||
|
||||
if _, ok := srv.agent.checkTTLs["test"]; !ok {
|
||||
if _, ok := srv.agent.checkTTLs[checkID]; !ok {
|
||||
t.Fatalf("missing test check ttl")
|
||||
}
|
||||
|
||||
state := srv.agent.state.Checks()["test"]
|
||||
state := srv.agent.state.Checks()[checkID]
|
||||
if state.Status != structs.HealthPassing {
|
||||
t.Fatalf("bad: %v", state)
|
||||
}
|
||||
|
|
|
@ -919,7 +919,7 @@ func TestAgent_PersistCheck(t *testing.T) {
|
|||
Interval: 10 * time.Second,
|
||||
}
|
||||
|
||||
file := filepath.Join(agent.config.DataDir, checksDir, stringHash(check.CheckID))
|
||||
file := filepath.Join(agent.config.DataDir, checksDir, checkIDHash(check.CheckID))
|
||||
|
||||
// Not persisted if not requested
|
||||
if err := agent.AddCheck(check, chkType, false, ""); err != nil {
|
||||
|
@ -1014,7 +1014,7 @@ func TestAgent_PurgeCheck(t *testing.T) {
|
|||
Status: structs.HealthPassing,
|
||||
}
|
||||
|
||||
file := filepath.Join(agent.config.DataDir, checksDir, stringHash(check.CheckID))
|
||||
file := filepath.Join(agent.config.DataDir, checksDir, checkIDHash(check.CheckID))
|
||||
if err := agent.AddCheck(check, nil, true, ""); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -1074,7 +1074,7 @@ func TestAgent_PurgeCheckOnDuplicate(t *testing.T) {
|
|||
}
|
||||
defer agent2.Shutdown()
|
||||
|
||||
file := filepath.Join(agent.config.DataDir, checksDir, stringHash(check1.CheckID))
|
||||
file := filepath.Join(agent.config.DataDir, checksDir, checkIDHash(check1.CheckID))
|
||||
if _, err := os.Stat(file); err == nil {
|
||||
t.Fatalf("should have removed persisted check")
|
||||
}
|
||||
|
@ -1465,7 +1465,7 @@ func TestAgent_loadChecks_checkFails(t *testing.T) {
|
|||
}
|
||||
|
||||
// Check to make sure the check was persisted
|
||||
checkHash := stringHash(check.CheckID)
|
||||
checkHash := checkIDHash(check.CheckID)
|
||||
checkPath := filepath.Join(config.DataDir, checksDir, checkHash)
|
||||
if _, err := os.Stat(checkPath); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
docker "github.com/fsouza/go-dockerclient"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/lib"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
)
|
||||
|
||||
|
@ -90,7 +91,7 @@ func (c *CheckType) IsDocker() bool {
|
|||
// to notify when a check has a status update. The update
|
||||
// should take care to be idempotent.
|
||||
type CheckNotifier interface {
|
||||
UpdateCheck(checkID, status, output string)
|
||||
UpdateCheck(checkID types.CheckID, status, output string)
|
||||
}
|
||||
|
||||
// CheckMonitor is used to periodically invoke a script to
|
||||
|
@ -98,7 +99,7 @@ type CheckNotifier interface {
|
|||
// nagios plugins and expects the output in the same format.
|
||||
type CheckMonitor struct {
|
||||
Notify CheckNotifier
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
Script string
|
||||
Interval time.Duration
|
||||
Timeout time.Duration
|
||||
|
@ -231,7 +232,7 @@ func (c *CheckMonitor) check() {
|
|||
// automatically set to critical.
|
||||
type CheckTTL struct {
|
||||
Notify CheckNotifier
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
TTL time.Duration
|
||||
Logger *log.Logger
|
||||
|
||||
|
@ -322,7 +323,7 @@ type persistedCheck struct {
|
|||
// expiration timestamp which is used to determine staleness on later
|
||||
// agent restarts.
|
||||
type persistedCheckState struct {
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
Output string
|
||||
Status string
|
||||
Expires int64
|
||||
|
@ -336,7 +337,7 @@ type persistedCheckState struct {
|
|||
// or if the request returns an error
|
||||
type CheckHTTP struct {
|
||||
Notify CheckNotifier
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
HTTP string
|
||||
Interval time.Duration
|
||||
Timeout time.Duration
|
||||
|
@ -462,7 +463,7 @@ func (c *CheckHTTP) check() {
|
|||
// The check is critical if the connection returns an error
|
||||
type CheckTCP struct {
|
||||
Notify CheckNotifier
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
TCP string
|
||||
Interval time.Duration
|
||||
Timeout time.Duration
|
||||
|
@ -553,7 +554,7 @@ type DockerClient interface {
|
|||
// with nagios plugins and expects the output in the same format.
|
||||
type CheckDocker struct {
|
||||
Notify CheckNotifier
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
Script string
|
||||
DockerContainerID string
|
||||
Shell string
|
||||
|
|
|
@ -18,15 +18,16 @@ import (
|
|||
docker "github.com/fsouza/go-dockerclient"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/testutil"
|
||||
"github.com/hashicorp/consul/types"
|
||||
)
|
||||
|
||||
type MockNotify struct {
|
||||
state map[string]string
|
||||
updates map[string]int
|
||||
output map[string]string
|
||||
state map[types.CheckID]string
|
||||
updates map[types.CheckID]int
|
||||
output map[types.CheckID]string
|
||||
}
|
||||
|
||||
func (m *MockNotify) UpdateCheck(id, status, output string) {
|
||||
func (m *MockNotify) UpdateCheck(id types.CheckID, status, output string) {
|
||||
m.state[id] = status
|
||||
old := m.updates[id]
|
||||
m.updates[id] = old + 1
|
||||
|
@ -35,13 +36,13 @@ func (m *MockNotify) UpdateCheck(id, status, output string) {
|
|||
|
||||
func expectStatus(t *testing.T, script, status string) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckMonitor{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: script,
|
||||
Interval: 10 * time.Millisecond,
|
||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||
|
@ -84,13 +85,13 @@ func TestCheckMonitor_BadCmd(t *testing.T) {
|
|||
|
||||
func TestCheckMonitor_Timeout(t *testing.T) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckMonitor{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: "sleep 1 && exit 0",
|
||||
Interval: 10 * time.Millisecond,
|
||||
Timeout: 5 * time.Millisecond,
|
||||
|
@ -114,13 +115,13 @@ func TestCheckMonitor_Timeout(t *testing.T) {
|
|||
|
||||
func TestCheckMonitor_RandomStagger(t *testing.T) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckMonitor{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: "exit 0",
|
||||
Interval: 25 * time.Millisecond,
|
||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||
|
@ -143,13 +144,13 @@ func TestCheckMonitor_RandomStagger(t *testing.T) {
|
|||
|
||||
func TestCheckMonitor_LimitOutput(t *testing.T) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckMonitor{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: "od -N 81920 /dev/urandom",
|
||||
Interval: 25 * time.Millisecond,
|
||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||
|
@ -168,13 +169,13 @@ func TestCheckMonitor_LimitOutput(t *testing.T) {
|
|||
|
||||
func TestCheckTTL(t *testing.T) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckTTL{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
TTL: 100 * time.Millisecond,
|
||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||
}
|
||||
|
@ -229,13 +230,13 @@ func mockHTTPServer(responseCode int) *httptest.Server {
|
|||
|
||||
func expectHTTPStatus(t *testing.T, url string, status string) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckHTTP{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
HTTP: url,
|
||||
Interval: 10 * time.Millisecond,
|
||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||
|
@ -329,14 +330,14 @@ func TestCheckHTTPTimeout(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
|
||||
check := &CheckHTTP{
|
||||
Notify: mock,
|
||||
CheckID: "bar",
|
||||
CheckID: types.CheckID("bar"),
|
||||
HTTP: server.URL,
|
||||
Timeout: 5 * time.Millisecond,
|
||||
Interval: 10 * time.Millisecond,
|
||||
|
@ -360,7 +361,7 @@ func TestCheckHTTPTimeout(t *testing.T) {
|
|||
|
||||
func TestCheckHTTP_disablesKeepAlives(t *testing.T) {
|
||||
check := &CheckHTTP{
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
HTTP: "http://foo.bar/baz",
|
||||
Interval: 10 * time.Second,
|
||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||
|
@ -395,13 +396,13 @@ func mockTCPServer(network string) net.Listener {
|
|||
|
||||
func expectTCPStatus(t *testing.T, tcp string, status string) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckTCP{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
TCP: tcp,
|
||||
Interval: 10 * time.Millisecond,
|
||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||
|
@ -575,13 +576,13 @@ func (d *fakeDockerClientWithExecInfoErrors) InspectExec(id string) (*docker.Exe
|
|||
|
||||
func expectDockerCheckStatus(t *testing.T, dockerClient DockerClient, status string, output string) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckDocker{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: "/health.sh",
|
||||
DockerContainerID: "54432bad1fc7",
|
||||
Shell: "/bin/sh",
|
||||
|
@ -635,13 +636,13 @@ func TestDockerCheckWhenExecInfoFails(t *testing.T) {
|
|||
func TestDockerCheckDefaultToSh(t *testing.T) {
|
||||
os.Setenv("SHELL", "")
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckDocker{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: "/health.sh",
|
||||
DockerContainerID: "54432bad1fc7",
|
||||
Interval: 10 * time.Millisecond,
|
||||
|
@ -659,14 +660,14 @@ func TestDockerCheckDefaultToSh(t *testing.T) {
|
|||
|
||||
func TestDockerCheckUseShellFromEnv(t *testing.T) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
os.Setenv("SHELL", "/bin/bash")
|
||||
check := &CheckDocker{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: "/health.sh",
|
||||
DockerContainerID: "54432bad1fc7",
|
||||
Interval: 10 * time.Millisecond,
|
||||
|
@ -685,13 +686,13 @@ func TestDockerCheckUseShellFromEnv(t *testing.T) {
|
|||
|
||||
func TestDockerCheckTruncateOutput(t *testing.T) {
|
||||
mock := &MockNotify{
|
||||
state: make(map[string]string),
|
||||
updates: make(map[string]int),
|
||||
output: make(map[string]string),
|
||||
state: make(map[types.CheckID]string),
|
||||
updates: make(map[types.CheckID]int),
|
||||
output: make(map[types.CheckID]string),
|
||||
}
|
||||
check := &CheckDocker{
|
||||
Notify: mock,
|
||||
CheckID: "foo",
|
||||
CheckID: types.CheckID("foo"),
|
||||
Script: "/health.sh",
|
||||
DockerContainerID: "54432bad1fc7",
|
||||
Shell: "/bin/sh",
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/hashicorp/consul/consul"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/lib"
|
||||
"github.com/hashicorp/consul/types"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -56,12 +57,12 @@ type localState struct {
|
|||
serviceTokens map[string]string
|
||||
|
||||
// Checks tracks the local checks
|
||||
checks map[string]*structs.HealthCheck
|
||||
checkStatus map[string]syncStatus
|
||||
checkTokens map[string]string
|
||||
checks map[types.CheckID]*structs.HealthCheck
|
||||
checkStatus map[types.CheckID]syncStatus
|
||||
checkTokens map[types.CheckID]string
|
||||
|
||||
// Used to track checks that are being deferred
|
||||
deferCheck map[string]*time.Timer
|
||||
deferCheck map[types.CheckID]*time.Timer
|
||||
|
||||
// consulCh is used to inform of a change to the known
|
||||
// consul nodes. This may be used to retry a sync run
|
||||
|
@ -79,10 +80,10 @@ func (l *localState) Init(config *Config, logger *log.Logger) {
|
|||
l.services = make(map[string]*structs.NodeService)
|
||||
l.serviceStatus = make(map[string]syncStatus)
|
||||
l.serviceTokens = make(map[string]string)
|
||||
l.checks = make(map[string]*structs.HealthCheck)
|
||||
l.checkStatus = make(map[string]syncStatus)
|
||||
l.checkTokens = make(map[string]string)
|
||||
l.deferCheck = make(map[string]*time.Timer)
|
||||
l.checks = make(map[types.CheckID]*structs.HealthCheck)
|
||||
l.checkStatus = make(map[types.CheckID]syncStatus)
|
||||
l.checkTokens = make(map[types.CheckID]string)
|
||||
l.deferCheck = make(map[types.CheckID]*time.Timer)
|
||||
l.consulCh = make(chan struct{}, 1)
|
||||
l.triggerCh = make(chan struct{}, 1)
|
||||
}
|
||||
|
@ -191,17 +192,17 @@ func (l *localState) Services() map[string]*structs.NodeService {
|
|||
return services
|
||||
}
|
||||
|
||||
// CheckToken is used to return the configured health check token, or
|
||||
// if none is configured, the default agent ACL token.
|
||||
func (l *localState) CheckToken(id string) string {
|
||||
// CheckToken is used to return the configured health check token for a
|
||||
// Check, or if none is configured, the default agent ACL token.
|
||||
func (l *localState) CheckToken(checkID types.CheckID) string {
|
||||
l.RLock()
|
||||
defer l.RUnlock()
|
||||
return l.checkToken(id)
|
||||
return l.checkToken(checkID)
|
||||
}
|
||||
|
||||
// checkToken returns an ACL token associated with a check.
|
||||
func (l *localState) checkToken(id string) string {
|
||||
token := l.checkTokens[id]
|
||||
func (l *localState) checkToken(checkID types.CheckID) string {
|
||||
token := l.checkTokens[checkID]
|
||||
if token == "" {
|
||||
token = l.config.ACLToken
|
||||
}
|
||||
|
@ -226,7 +227,7 @@ func (l *localState) AddCheck(check *structs.HealthCheck, token string) {
|
|||
|
||||
// RemoveCheck is used to remove a health check from the local state.
|
||||
// The agent will make a best effort to ensure it is deregistered
|
||||
func (l *localState) RemoveCheck(checkID string) {
|
||||
func (l *localState) RemoveCheck(checkID types.CheckID) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
|
@ -237,7 +238,7 @@ func (l *localState) RemoveCheck(checkID string) {
|
|||
}
|
||||
|
||||
// UpdateCheck is used to update the status of a check
|
||||
func (l *localState) UpdateCheck(checkID, status, output string) {
|
||||
func (l *localState) UpdateCheck(checkID types.CheckID, status, output string) {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
|
||||
|
@ -282,13 +283,13 @@ func (l *localState) UpdateCheck(checkID, status, output string) {
|
|||
|
||||
// Checks returns the locally registered checks that the
|
||||
// agent is aware of and are being kept in sync with the server
|
||||
func (l *localState) Checks() map[string]*structs.HealthCheck {
|
||||
checks := make(map[string]*structs.HealthCheck)
|
||||
func (l *localState) Checks() map[types.CheckID]*structs.HealthCheck {
|
||||
checks := make(map[types.CheckID]*structs.HealthCheck)
|
||||
l.RLock()
|
||||
defer l.RUnlock()
|
||||
|
||||
for name, check := range l.checks {
|
||||
checks[name] = check
|
||||
for checkID, check := range l.checks {
|
||||
checks[checkID] = check
|
||||
}
|
||||
return checks
|
||||
}
|
||||
|
@ -406,7 +407,7 @@ func (l *localState) setSyncState() error {
|
|||
}
|
||||
|
||||
// Index the remote health checks to improve efficiency
|
||||
checkIndex := make(map[string]*structs.HealthCheck, len(checks))
|
||||
checkIndex := make(map[types.CheckID]*structs.HealthCheck, len(checks))
|
||||
for _, check := range checks {
|
||||
checkIndex[check.CheckID] = check
|
||||
}
|
||||
|
@ -546,7 +547,7 @@ func (l *localState) deleteService(id string) error {
|
|||
}
|
||||
|
||||
// deleteCheck is used to delete a service from the server
|
||||
func (l *localState) deleteCheck(id string) error {
|
||||
func (l *localState) deleteCheck(id types.CheckID) error {
|
||||
if id == "" {
|
||||
return fmt.Errorf("CheckID missing")
|
||||
}
|
||||
|
@ -619,7 +620,7 @@ func (l *localState) syncService(id string) error {
|
|||
}
|
||||
|
||||
// syncCheck is used to sync a check to the server
|
||||
func (l *localState) syncCheck(id string) error {
|
||||
func (l *localState) syncCheck(id types.CheckID) error {
|
||||
// Pull in the associated service if any
|
||||
check := l.checks[id]
|
||||
var service *structs.NodeService
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/consul/consul"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/types"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -38,7 +39,7 @@ func (s *HTTPServer) SessionCreate(resp http.ResponseWriter, req *http.Request)
|
|||
Op: structs.SessionCreate,
|
||||
Session: structs.Session{
|
||||
Node: s.agent.config.NodeName,
|
||||
Checks: []string{consul.SerfCheckID},
|
||||
Checks: []types.CheckID{consul.SerfCheckID},
|
||||
LockDelay: 15 * time.Second,
|
||||
Behavior: structs.SessionKeysRelease,
|
||||
TTL: "",
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/consul/consul"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/types"
|
||||
)
|
||||
|
||||
func TestSessionCreate(t *testing.T) {
|
||||
|
@ -38,7 +39,7 @@ func TestSessionCreate(t *testing.T) {
|
|||
raw := map[string]interface{}{
|
||||
"Name": "my-cool-session",
|
||||
"Node": srv.agent.config.NodeName,
|
||||
"Checks": []string{consul.SerfCheckID, "consul"},
|
||||
"Checks": []types.CheckID{consul.SerfCheckID, "consul"},
|
||||
"LockDelay": "20s",
|
||||
}
|
||||
enc.Encode(raw)
|
||||
|
@ -86,7 +87,7 @@ func TestSessionCreateDelete(t *testing.T) {
|
|||
raw := map[string]interface{}{
|
||||
"Name": "my-cool-session",
|
||||
"Node": srv.agent.config.NodeName,
|
||||
"Checks": []string{consul.SerfCheckID, "consul"},
|
||||
"Checks": []types.CheckID{consul.SerfCheckID, "consul"},
|
||||
"LockDelay": "20s",
|
||||
"Behavior": structs.SessionKeysDelete,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package agent
|
|||
|
||||
import (
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/types"
|
||||
)
|
||||
|
||||
// ServiceDefinition is used to JSON decode the Service definitions
|
||||
|
@ -42,9 +43,9 @@ func (s *ServiceDefinition) CheckTypes() (checks CheckTypes) {
|
|||
return
|
||||
}
|
||||
|
||||
// ChecKDefinition is used to JSON decode the Check definitions
|
||||
// CheckDefinition is used to JSON decode the Check definitions
|
||||
type CheckDefinition struct {
|
||||
ID string
|
||||
ID types.CheckID
|
||||
Name string
|
||||
Notes string
|
||||
ServiceID string
|
||||
|
@ -66,7 +67,7 @@ func (c *CheckDefinition) HealthCheck(node string) *structs.HealthCheck {
|
|||
health.Status = c.Status
|
||||
}
|
||||
if health.CheckID == "" && health.Name != "" {
|
||||
health.CheckID = health.Name
|
||||
health.CheckID = types.CheckID(health.Name)
|
||||
}
|
||||
return health
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/go-msgpack/codec"
|
||||
)
|
||||
|
||||
|
@ -71,6 +72,11 @@ func stringHash(s string) string {
|
|||
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
|
||||
}
|
||||
|
||||
// checkIDHash returns a simple md5sum for a types.CheckID.
|
||||
func checkIDHash(checkID types.CheckID) string {
|
||||
return stringHash(string(checkID))
|
||||
}
|
||||
|
||||
// FilePermissions is an interface which allows a struct to set
|
||||
// ownership and permissions easily on a file it describes.
|
||||
type FilePermissions interface {
|
||||
|
|
|
@ -117,7 +117,7 @@ func (c *MaintCommand) Run(args []string) int {
|
|||
c.Ui.Output(" Name: " + nodeName)
|
||||
c.Ui.Output(" Reason: " + check.Notes)
|
||||
c.Ui.Output("")
|
||||
} else if strings.HasPrefix(check.CheckID, "_service_maintenance:") {
|
||||
} else if strings.HasPrefix(string(check.CheckID), "_service_maintenance:") {
|
||||
c.Ui.Output("Service:")
|
||||
c.Ui.Output(" ID: " + check.ServiceID)
|
||||
c.Ui.Output(" Reason: " + check.Notes)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/armon/go-metrics"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/types"
|
||||
)
|
||||
|
||||
// Catalog endpoint is used to manipulate the service catalog
|
||||
|
@ -57,7 +58,7 @@ func (c *Catalog) Register(args *structs.RegisterRequest, reply *struct{}) error
|
|||
}
|
||||
for _, check := range args.Checks {
|
||||
if check.CheckID == "" && check.Name != "" {
|
||||
check.CheckID = check.Name
|
||||
check.CheckID = types.CheckID(check.Name)
|
||||
}
|
||||
if check.Node == "" {
|
||||
check.Node = args.Node
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/hashicorp/consul/consul/state"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/lib"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/raft"
|
||||
)
|
||||
|
@ -860,7 +861,7 @@ func TestFSM_SessionCreate_Destroy(t *testing.T) {
|
|||
Session: structs.Session{
|
||||
ID: generateUUID(),
|
||||
Node: "foo",
|
||||
Checks: []string{"web"},
|
||||
Checks: []types.CheckID{"web"},
|
||||
},
|
||||
}
|
||||
buf, err := structs.Encode(structs.SessionRequestType, req)
|
||||
|
|
|
@ -10,18 +10,19 @@ import (
|
|||
"github.com/armon/go-metrics"
|
||||
"github.com/hashicorp/consul/consul/agent"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/raft"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
)
|
||||
|
||||
const (
|
||||
SerfCheckID = "serfHealth"
|
||||
SerfCheckName = "Serf Health Status"
|
||||
SerfCheckAliveOutput = "Agent alive and reachable"
|
||||
SerfCheckFailedOutput = "Agent not live or unreachable"
|
||||
ConsulServiceID = "consul"
|
||||
ConsulServiceName = "consul"
|
||||
newLeaderEvent = "consul:new-leader"
|
||||
SerfCheckID types.CheckID = "serfHealth"
|
||||
SerfCheckName = "Serf Health Status"
|
||||
SerfCheckAliveOutput = "Agent alive and reachable"
|
||||
SerfCheckFailedOutput = "Agent not live or unreachable"
|
||||
ConsulServiceID = "consul"
|
||||
ConsulServiceName = "consul"
|
||||
newLeaderEvent = "consul:new-leader"
|
||||
)
|
||||
|
||||
// monitorLeadership is used to monitor if we acquire or lose our role
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/go-memdb"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
)
|
||||
|
@ -82,7 +83,7 @@ type IndexEntry struct {
|
|||
// store and thus it is not exported.
|
||||
type sessionCheck struct {
|
||||
Node string
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
Session string
|
||||
}
|
||||
|
||||
|
@ -594,7 +595,7 @@ func (s *StateStore) deleteNodeTxn(tx *memdb.Txn, idx uint64, nodeID string) err
|
|||
if err != nil {
|
||||
return fmt.Errorf("failed check lookup: %s", err)
|
||||
}
|
||||
var cids []string
|
||||
var cids []types.CheckID
|
||||
for check := checks.Next(); check != nil; check = checks.Next() {
|
||||
cids = append(cids, check.(*structs.HealthCheck).CheckID)
|
||||
}
|
||||
|
@ -917,7 +918,7 @@ func (s *StateStore) deleteServiceTxn(tx *memdb.Txn, idx uint64, watches *DumbWa
|
|||
if err != nil {
|
||||
return fmt.Errorf("failed service check lookup: %s", err)
|
||||
}
|
||||
var cids []string
|
||||
var cids []types.CheckID
|
||||
for check := checks.Next(); check != nil; check = checks.Next() {
|
||||
cids = append(cids, check.(*structs.HealthCheck).CheckID)
|
||||
}
|
||||
|
@ -968,7 +969,7 @@ func (s *StateStore) EnsureCheck(idx uint64, hc *structs.HealthCheck) error {
|
|||
func (s *StateStore) ensureCheckTxn(tx *memdb.Txn, idx uint64, watches *DumbWatchManager,
|
||||
hc *structs.HealthCheck) error {
|
||||
// Check if we have an existing health check
|
||||
existing, err := tx.First("checks", "id", hc.Node, hc.CheckID)
|
||||
existing, err := tx.First("checks", "id", hc.Node, string(hc.CheckID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed health check lookup: %s", err)
|
||||
}
|
||||
|
@ -1013,7 +1014,7 @@ func (s *StateStore) ensureCheckTxn(tx *memdb.Txn, idx uint64, watches *DumbWatc
|
|||
|
||||
// Delete any sessions for this check if the health is critical.
|
||||
if hc.Status == structs.HealthCritical {
|
||||
mappings, err := tx.Get("session_checks", "node_check", hc.Node, hc.CheckID)
|
||||
mappings, err := tx.Get("session_checks", "node_check", hc.Node, string(hc.CheckID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed session checks lookup: %s", err)
|
||||
}
|
||||
|
@ -1119,13 +1120,13 @@ func (s *StateStore) parseChecks(idx uint64, iter memdb.ResultIterator) (uint64,
|
|||
}
|
||||
|
||||
// DeleteCheck is used to delete a health check registration.
|
||||
func (s *StateStore) DeleteCheck(idx uint64, node, id string) error {
|
||||
func (s *StateStore) DeleteCheck(idx uint64, node string, checkID types.CheckID) error {
|
||||
tx := s.db.Txn(true)
|
||||
defer tx.Abort()
|
||||
|
||||
// Call the check deletion
|
||||
watches := NewDumbWatchManager(s.tableWatches)
|
||||
if err := s.deleteCheckTxn(tx, idx, watches, node, id); err != nil {
|
||||
if err := s.deleteCheckTxn(tx, idx, watches, node, checkID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1136,9 +1137,9 @@ func (s *StateStore) DeleteCheck(idx uint64, node, id string) error {
|
|||
|
||||
// deleteCheckTxn is the inner method used to call a health
|
||||
// check deletion within an existing transaction.
|
||||
func (s *StateStore) deleteCheckTxn(tx *memdb.Txn, idx uint64, watches *DumbWatchManager, node, id string) error {
|
||||
func (s *StateStore) deleteCheckTxn(tx *memdb.Txn, idx uint64, watches *DumbWatchManager, node string, checkID types.CheckID) error {
|
||||
// Try to retrieve the existing health check.
|
||||
hc, err := tx.First("checks", "id", node, id)
|
||||
hc, err := tx.First("checks", "id", node, string(checkID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("check lookup failed: %s", err)
|
||||
}
|
||||
|
@ -1155,7 +1156,7 @@ func (s *StateStore) deleteCheckTxn(tx *memdb.Txn, idx uint64, watches *DumbWatc
|
|||
}
|
||||
|
||||
// Delete any sessions for this check.
|
||||
mappings, err := tx.Get("session_checks", "node_check", node, id)
|
||||
mappings, err := tx.Get("session_checks", "node_check", node, string(checkID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed session checks lookup: %s", err)
|
||||
}
|
||||
|
@ -1412,7 +1413,7 @@ func (s *StateStore) sessionCreateTxn(tx *memdb.Txn, idx uint64, sess *structs.S
|
|||
|
||||
// Go over the session checks and ensure they exist.
|
||||
for _, checkID := range sess.Checks {
|
||||
check, err := tx.First("checks", "id", sess.Node, checkID)
|
||||
check, err := tx.First("checks", "id", sess.Node, string(checkID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed check lookup: %s", err)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/lib"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
)
|
||||
|
||||
|
@ -82,7 +83,7 @@ func testRegisterService(t *testing.T, s *StateStore, idx uint64, nodeID, servic
|
|||
}
|
||||
|
||||
func testRegisterCheck(t *testing.T, s *StateStore, idx uint64,
|
||||
nodeID, serviceID, checkID, state string) {
|
||||
nodeID string, serviceID string, checkID types.CheckID, state string) {
|
||||
chk := &structs.HealthCheck{
|
||||
Node: nodeID,
|
||||
CheckID: checkID,
|
||||
|
@ -95,7 +96,7 @@ func testRegisterCheck(t *testing.T, s *StateStore, idx uint64,
|
|||
|
||||
tx := s.db.Txn(false)
|
||||
defer tx.Abort()
|
||||
c, err := tx.First("checks", "id", nodeID, checkID)
|
||||
c, err := tx.First("checks", "id", nodeID, string(checkID))
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
@ -2150,7 +2151,7 @@ func TestStateStore_SessionCreate_SessionGet(t *testing.T) {
|
|||
sess = &structs.Session{
|
||||
ID: testUUID(),
|
||||
Node: "node1",
|
||||
Checks: []string{"check1"},
|
||||
Checks: []types.CheckID{"check1"},
|
||||
}
|
||||
err = s.SessionCreate(3, sess)
|
||||
if err == nil || !strings.Contains(err.Error(), "Missing check") {
|
||||
|
@ -2175,7 +2176,7 @@ func TestStateStore_SessionCreate_SessionGet(t *testing.T) {
|
|||
sess2 := &structs.Session{
|
||||
ID: testUUID(),
|
||||
Node: "node1",
|
||||
Checks: []string{"check1", "check2"},
|
||||
Checks: []types.CheckID{"check1", "check2"},
|
||||
}
|
||||
if err := s.SessionCreate(6, sess2); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
@ -2209,7 +2210,7 @@ func TestStateStore_SessionCreate_SessionGet(t *testing.T) {
|
|||
for i, check := 0, checks.Next(); check != nil; i, check = i+1, checks.Next() {
|
||||
expectCheck := &sessionCheck{
|
||||
Node: "node1",
|
||||
CheckID: fmt.Sprintf("check%d", i+1),
|
||||
CheckID: types.CheckID(fmt.Sprintf("check%d", i+1)),
|
||||
Session: sess2.ID,
|
||||
}
|
||||
if actual := check.(*sessionCheck); !reflect.DeepEqual(actual, expectCheck) {
|
||||
|
@ -2407,7 +2408,7 @@ func TestStateStore_Session_Snapshot_Restore(t *testing.T) {
|
|||
ID: session1,
|
||||
Node: "node1",
|
||||
Behavior: structs.SessionKeysDelete,
|
||||
Checks: []string{"check1"},
|
||||
Checks: []types.CheckID{"check1"},
|
||||
},
|
||||
&structs.Session{
|
||||
ID: testUUID(),
|
||||
|
@ -2624,7 +2625,7 @@ func TestStateStore_Session_Invalidate_DeleteService(t *testing.T) {
|
|||
session := &structs.Session{
|
||||
ID: testUUID(),
|
||||
Node: "foo",
|
||||
Checks: []string{"api"},
|
||||
Checks: []types.CheckID{"api"},
|
||||
}
|
||||
if err := s.SessionCreate(14, session); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
|
@ -2672,7 +2673,7 @@ func TestStateStore_Session_Invalidate_Critical_Check(t *testing.T) {
|
|||
session := &structs.Session{
|
||||
ID: testUUID(),
|
||||
Node: "foo",
|
||||
Checks: []string{"bar"},
|
||||
Checks: []types.CheckID{"bar"},
|
||||
}
|
||||
if err := s.SessionCreate(14, session); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
|
@ -2719,7 +2720,7 @@ func TestStateStore_Session_Invalidate_DeleteCheck(t *testing.T) {
|
|||
session := &structs.Session{
|
||||
ID: testUUID(),
|
||||
Node: "foo",
|
||||
Checks: []string{"bar"},
|
||||
Checks: []types.CheckID{"bar"},
|
||||
}
|
||||
if err := s.SessionCreate(14, session); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/go-msgpack/codec"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
)
|
||||
|
@ -181,7 +182,7 @@ type DeregisterRequest struct {
|
|||
Datacenter string
|
||||
Node string
|
||||
ServiceID string
|
||||
CheckID string
|
||||
CheckID types.CheckID
|
||||
WriteRequest
|
||||
}
|
||||
|
||||
|
@ -367,13 +368,13 @@ type NodeServices struct {
|
|||
// HealthCheck represents a single check on a given node
|
||||
type HealthCheck struct {
|
||||
Node string
|
||||
CheckID string // Unique per-node ID
|
||||
Name string // Check name
|
||||
Status string // The current check status
|
||||
Notes string // Additional notes with the status
|
||||
Output string // Holds output of script runs
|
||||
ServiceID string // optional associated service
|
||||
ServiceName string // optional service name
|
||||
CheckID types.CheckID // Unique per-node ID
|
||||
Name string // Check name
|
||||
Status string // The current check status
|
||||
Notes string // Additional notes with the status
|
||||
Output string // Holds output of script runs
|
||||
ServiceID string // optional associated service
|
||||
ServiceName string // optional service name
|
||||
|
||||
RaftIndex
|
||||
}
|
||||
|
@ -617,7 +618,7 @@ type Session struct {
|
|||
ID string
|
||||
Name string
|
||||
Node string
|
||||
Checks []string
|
||||
Checks []types.CheckID
|
||||
LockDelay time.Duration
|
||||
Behavior SessionBehavior // What to do when session is invalidated
|
||||
TTL string
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/types"
|
||||
)
|
||||
|
||||
func TestEncodeDecode(t *testing.T) {
|
||||
|
@ -184,7 +186,7 @@ func TestStructs_HealthCheck_IsSame(t *testing.T) {
|
|||
t.Fatalf("should not care about Raft fields")
|
||||
}
|
||||
|
||||
check := func(field *string) {
|
||||
checkCheckIDField := func(field *types.CheckID) {
|
||||
if !hc.IsSame(other) || !other.IsSame(hc) {
|
||||
t.Fatalf("should be the same")
|
||||
}
|
||||
|
@ -201,14 +203,31 @@ func TestStructs_HealthCheck_IsSame(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
check(&other.Node)
|
||||
check(&other.CheckID)
|
||||
check(&other.Name)
|
||||
check(&other.Status)
|
||||
check(&other.Notes)
|
||||
check(&other.Output)
|
||||
check(&other.ServiceID)
|
||||
check(&other.ServiceName)
|
||||
checkStringField := func(field *string) {
|
||||
if !hc.IsSame(other) || !other.IsSame(hc) {
|
||||
t.Fatalf("should be the same")
|
||||
}
|
||||
|
||||
old := *field
|
||||
*field = "XXX"
|
||||
if hc.IsSame(other) || other.IsSame(hc) {
|
||||
t.Fatalf("should not be the same")
|
||||
}
|
||||
*field = old
|
||||
|
||||
if !hc.IsSame(other) || !other.IsSame(hc) {
|
||||
t.Fatalf("should be the same")
|
||||
}
|
||||
}
|
||||
|
||||
checkStringField(&other.Node)
|
||||
checkCheckIDField(&other.CheckID)
|
||||
checkStringField(&other.Name)
|
||||
checkStringField(&other.Status)
|
||||
checkStringField(&other.Notes)
|
||||
checkStringField(&other.Output)
|
||||
checkStringField(&other.ServiceID)
|
||||
checkStringField(&other.ServiceName)
|
||||
}
|
||||
|
||||
func TestStructs_HealthCheck_Clone(t *testing.T) {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# Consul `types` Package
|
||||
|
||||
The Go language has a strong type system built into the language. The
|
||||
`types` package corrals named types into a single package that is terminal in
|
||||
`go`'s import graph. The `types` package should not have any downstream
|
||||
dependencies. Each subsystem that defines its own set of types exists in its
|
||||
own file, but all types are defined in the same package.
|
||||
|
||||
# Why
|
||||
|
||||
> Everything should be made as simple as possible, but not simpler.
|
||||
|
||||
`string` is a useful container and underlying type for identifiers, however
|
||||
the `string` type is effectively opaque to the compiler in terms of how a
|
||||
given string is intended to be used. For instance, there is nothing
|
||||
preventing the following from happening:
|
||||
|
||||
```go
|
||||
// `map` of Widgets, looked up by ID
|
||||
var widgetLookup map[string]*Widget
|
||||
// ...
|
||||
var widgetID string = "widgetID"
|
||||
w, found := widgetLookup[widgetID]
|
||||
|
||||
// Bad!
|
||||
var widgetName string = "name of widget"
|
||||
w, found := widgetLookup[widgetName]
|
||||
```
|
||||
|
||||
but this class of problem is entirely preventable:
|
||||
|
||||
```go
|
||||
type WidgetID string
|
||||
var widgetLookup map[WidgetID]*Widget
|
||||
var widgetName
|
||||
```
|
||||
|
||||
TL;DR: intentions and idioms aren't statically checked by compilers. The
|
||||
`types` package uses Go's strong type system to prevent this class of bug.
|
|
@ -0,0 +1,5 @@
|
|||
package types
|
||||
|
||||
// CheckID is a strongly typed string used to uniquely represent a Consul
|
||||
// Check on an Agent (a CheckID is not globally unique).
|
||||
type CheckID string
|
Loading…
Reference in New Issue