Revert "Move `structs.CheckID` to a new top-level package, `types`."

This reverts commit 2bbd52e3b44ff1b60939a8400264d534662d6d51.
This commit is contained in:
Sean Chittenden 2016-06-06 13:19:31 -07:00
parent a4554b945c
commit ff45f8c8ff
No known key found for this signature in database
GPG Key ID: 4EBC9DC16C2E5E16
13 changed files with 175 additions and 124 deletions

View File

@ -19,6 +19,7 @@ import (
"github.com/hashicorp/consul/consul/state" "github.com/hashicorp/consul/consul/state"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
"github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/coordinate"
"github.com/hashicorp/serf/serf" "github.com/hashicorp/serf/serf"
) )
@ -74,19 +75,19 @@ type Agent struct {
state localState state localState
// checkMonitors maps the check ID to an associated monitor // checkMonitors maps the check ID to an associated monitor
checkMonitors map[structs.CheckID]*CheckMonitor checkMonitors map[types.CheckID]*CheckMonitor
// checkHTTPs maps the check ID to an associated HTTP check // checkHTTPs maps the check ID to an associated HTTP check
checkHTTPs map[structs.CheckID]*CheckHTTP checkHTTPs map[types.CheckID]*CheckHTTP
// checkTCPs maps the check ID to an associated TCP check // checkTCPs maps the check ID to an associated TCP check
checkTCPs map[structs.CheckID]*CheckTCP checkTCPs map[types.CheckID]*CheckTCP
// checkTTLs maps the check ID to an associated check TTL // checkTTLs maps the check ID to an associated check TTL
checkTTLs map[structs.CheckID]*CheckTTL checkTTLs map[types.CheckID]*CheckTTL
// checkDockers maps the check ID to an associated Docker Exec based check // checkDockers maps the check ID to an associated Docker Exec based check
checkDockers map[structs.CheckID]*CheckDocker checkDockers map[types.CheckID]*CheckDocker
// checkLock protects updates to the check* maps // checkLock protects updates to the check* maps
checkLock sync.Mutex checkLock sync.Mutex
@ -176,11 +177,11 @@ func Create(config *Config, logOutput io.Writer) (*Agent, error) {
config: config, config: config,
logger: log.New(logOutput, "", log.LstdFlags), logger: log.New(logOutput, "", log.LstdFlags),
logOutput: logOutput, logOutput: logOutput,
checkMonitors: make(map[structs.CheckID]*CheckMonitor), checkMonitors: make(map[types.CheckID]*CheckMonitor),
checkTTLs: make(map[structs.CheckID]*CheckTTL), checkTTLs: make(map[types.CheckID]*CheckTTL),
checkHTTPs: make(map[structs.CheckID]*CheckHTTP), checkHTTPs: make(map[types.CheckID]*CheckHTTP),
checkTCPs: make(map[structs.CheckID]*CheckTCP), checkTCPs: make(map[types.CheckID]*CheckTCP),
checkDockers: make(map[structs.CheckID]*CheckDocker), checkDockers: make(map[types.CheckID]*CheckDocker),
eventCh: make(chan serf.UserEvent, 1024), eventCh: make(chan serf.UserEvent, 1024),
eventBuf: make([]*UserEvent, 256), eventBuf: make([]*UserEvent, 256),
shutdownCh: make(chan struct{}), shutdownCh: make(chan struct{}),
@ -724,7 +725,7 @@ func (a *Agent) persistCheck(check *structs.HealthCheck, chkType *CheckType) err
} }
// purgeCheck removes a persisted check definition file from the data dir // purgeCheck removes a persisted check definition file from the data dir
func (a *Agent) purgeCheck(checkID structs.CheckID) error { func (a *Agent) purgeCheck(checkID types.CheckID) error {
checkPath := filepath.Join(a.config.DataDir, checksDir, checkIDHash(checkID)) checkPath := filepath.Join(a.config.DataDir, checksDir, checkIDHash(checkID))
if _, err := os.Stat(checkPath); err == nil { if _, err := os.Stat(checkPath); err == nil {
return os.Remove(checkPath) return os.Remove(checkPath)
@ -791,7 +792,7 @@ func (a *Agent) AddService(service *structs.NodeService, chkTypes CheckTypes, pe
} }
check := &structs.HealthCheck{ check := &structs.HealthCheck{
Node: a.config.NodeName, Node: a.config.NodeName,
CheckID: structs.CheckID(checkID), CheckID: types.CheckID(checkID),
Name: fmt.Sprintf("Service '%s' check", service.Service), Name: fmt.Sprintf("Service '%s' check", service.Service),
Status: structs.HealthCritical, Status: structs.HealthCritical,
Notes: chkType.Notes, 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. // RemoveCheck is used to remove a health check.
// The agent will make a best effort to ensure it is deregistered // The agent will make a best effort to ensure it is deregistered
func (a *Agent) RemoveCheck(checkID structs.CheckID, persist bool) error { func (a *Agent) RemoveCheck(checkID types.CheckID, persist bool) error {
// Validate CheckID // Validate CheckID
if checkID == "" { if checkID == "" {
return fmt.Errorf("CheckID missing") return fmt.Errorf("CheckID missing")
@ -1041,7 +1042,7 @@ func (a *Agent) RemoveCheck(checkID structs.CheckID, persist bool) error {
// UpdateCheck is used to update the status of a check. // UpdateCheck is used to update the status of a check.
// This can only be used with checks of the TTL type. // This can only be used with checks of the TTL type.
func (a *Agent) UpdateCheck(checkID structs.CheckID, status, output string) error { func (a *Agent) UpdateCheck(checkID types.CheckID, status, output string) error {
a.checkLock.Lock() a.checkLock.Lock()
defer a.checkLock.Unlock() defer a.checkLock.Unlock()
@ -1129,7 +1130,7 @@ func (a *Agent) loadCheckState(check *structs.HealthCheck) error {
} }
// purgeCheckState is used to purge the state of a check from the data dir // purgeCheckState is used to purge the state of a check from the data dir
func (a *Agent) purgeCheckState(checkID structs.CheckID) error { func (a *Agent) purgeCheckState(checkID types.CheckID) error {
file := filepath.Join(a.config.DataDir, checkStateDir, checkIDHash(checkID)) file := filepath.Join(a.config.DataDir, checkStateDir, checkIDHash(checkID))
err := os.Remove(file) err := os.Remove(file)
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -1393,22 +1394,22 @@ func (a *Agent) unloadChecks() error {
// snapshotCheckState is used to snapshot the current state of the health // 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 // checks. This is done before we reload our checks, so that we can properly
// restore into the same state. // restore into the same state.
func (a *Agent) snapshotCheckState() map[structs.CheckID]*structs.HealthCheck { func (a *Agent) snapshotCheckState() map[types.CheckID]*structs.HealthCheck {
return a.state.Checks() return a.state.Checks()
} }
// restoreCheckState is used to reset the health state based on a snapshot. // 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 // This is done after we finish the reload to avoid any unnecessary flaps
// in health state and potential session invalidations. // in health state and potential session invalidations.
func (a *Agent) restoreCheckState(snap map[structs.CheckID]*structs.HealthCheck) { func (a *Agent) restoreCheckState(snap map[types.CheckID]*structs.HealthCheck) {
for id, check := range snap { for id, check := range snap {
a.state.UpdateCheck(id, check.Status, check.Output) a.state.UpdateCheck(id, check.Status, check.Output)
} }
} }
// serviceMaintCheckID returns the ID of a given service's maintenance check // serviceMaintCheckID returns the ID of a given service's maintenance check
func serviceMaintCheckID(serviceID string) structs.CheckID { func serviceMaintCheckID(serviceID string) types.CheckID {
return structs.CheckID(fmt.Sprintf("%s:%s", serviceMaintCheckPrefix, serviceID)) return types.CheckID(fmt.Sprintf("%s:%s", serviceMaintCheckPrefix, serviceID))
} }
// EnableServiceMaintenance will register a false health check against the given // EnableServiceMaintenance will register a false health check against the given

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/types"
"github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/coordinate"
"github.com/hashicorp/serf/serf" "github.com/hashicorp/serf/serf"
) )
@ -130,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) { func (s *HTTPServer) AgentDeregisterCheck(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
checkID := structs.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 { if err := s.agent.RemoveCheck(checkID, true); err != nil {
return nil, err return nil, err
} }
@ -139,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) { func (s *HTTPServer) AgentCheckPass(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
checkID := structs.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") note := req.URL.Query().Get("note")
if err := s.agent.UpdateCheck(checkID, structs.HealthPassing, note); err != nil { if err := s.agent.UpdateCheck(checkID, structs.HealthPassing, note); err != nil {
return nil, err return nil, err
@ -149,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) { func (s *HTTPServer) AgentCheckWarn(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
checkID := structs.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") note := req.URL.Query().Get("note")
if err := s.agent.UpdateCheck(checkID, structs.HealthWarning, note); err != nil { if err := s.agent.UpdateCheck(checkID, structs.HealthWarning, note); err != nil {
return nil, err return nil, err
@ -159,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) { func (s *HTTPServer) AgentCheckFail(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
checkID := structs.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") note := req.URL.Query().Get("note")
if err := s.agent.UpdateCheck(checkID, structs.HealthCritical, note); err != nil { if err := s.agent.UpdateCheck(checkID, structs.HealthCritical, note); err != nil {
return nil, err return nil, err
@ -212,7 +213,7 @@ func (s *HTTPServer) AgentCheckUpdate(resp http.ResponseWriter, req *http.Reques
update.Output[:CheckBufSize], CheckBufSize, total) update.Output[:CheckBufSize], CheckBufSize, total)
} }
checkID := structs.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 { if err := s.agent.UpdateCheck(checkID, update.Status, update.Output); err != nil {
return nil, err return nil, err
} }

View File

@ -16,6 +16,7 @@ import (
docker "github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
"github.com/hashicorp/go-cleanhttp" "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 // to notify when a check has a status update. The update
// should take care to be idempotent. // should take care to be idempotent.
type CheckNotifier interface { type CheckNotifier interface {
UpdateCheck(checkID structs.CheckID, status, output string) UpdateCheck(checkID types.CheckID, status, output string)
} }
// CheckMonitor is used to periodically invoke a script to // 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. // nagios plugins and expects the output in the same format.
type CheckMonitor struct { type CheckMonitor struct {
Notify CheckNotifier Notify CheckNotifier
CheckID structs.CheckID CheckID types.CheckID
Script string Script string
Interval time.Duration Interval time.Duration
Timeout time.Duration Timeout time.Duration
@ -231,7 +232,7 @@ func (c *CheckMonitor) check() {
// automatically set to critical. // automatically set to critical.
type CheckTTL struct { type CheckTTL struct {
Notify CheckNotifier Notify CheckNotifier
CheckID structs.CheckID CheckID types.CheckID
TTL time.Duration TTL time.Duration
Logger *log.Logger Logger *log.Logger
@ -322,7 +323,7 @@ type persistedCheck struct {
// expiration timestamp which is used to determine staleness on later // expiration timestamp which is used to determine staleness on later
// agent restarts. // agent restarts.
type persistedCheckState struct { type persistedCheckState struct {
CheckID structs.CheckID CheckID types.CheckID
Output string Output string
Status string Status string
Expires int64 Expires int64
@ -336,7 +337,7 @@ type persistedCheckState struct {
// or if the request returns an error // or if the request returns an error
type CheckHTTP struct { type CheckHTTP struct {
Notify CheckNotifier Notify CheckNotifier
CheckID structs.CheckID CheckID types.CheckID
HTTP string HTTP string
Interval time.Duration Interval time.Duration
Timeout time.Duration Timeout time.Duration
@ -462,7 +463,7 @@ func (c *CheckHTTP) check() {
// The check is critical if the connection returns an error // The check is critical if the connection returns an error
type CheckTCP struct { type CheckTCP struct {
Notify CheckNotifier Notify CheckNotifier
CheckID structs.CheckID CheckID types.CheckID
TCP string TCP string
Interval time.Duration Interval time.Duration
Timeout time.Duration Timeout time.Duration
@ -553,7 +554,7 @@ type DockerClient interface {
// with nagios plugins and expects the output in the same format. // with nagios plugins and expects the output in the same format.
type CheckDocker struct { type CheckDocker struct {
Notify CheckNotifier Notify CheckNotifier
CheckID structs.CheckID CheckID types.CheckID
Script string Script string
DockerContainerID string DockerContainerID string
Shell string Shell string

View File

@ -18,15 +18,16 @@ import (
docker "github.com/fsouza/go-dockerclient" docker "github.com/fsouza/go-dockerclient"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/testutil"
"github.com/hashicorp/consul/types"
) )
type MockNotify struct { type MockNotify struct {
state map[structs.CheckID]string state map[types.CheckID]string
updates map[structs.CheckID]int updates map[types.CheckID]int
output map[structs.CheckID]string output map[types.CheckID]string
} }
func (m *MockNotify) UpdateCheck(id structs.CheckID, status, output string) { func (m *MockNotify) UpdateCheck(id types.CheckID, status, output string) {
m.state[id] = status m.state[id] = status
old := m.updates[id] old := m.updates[id]
m.updates[id] = old + 1 m.updates[id] = old + 1
@ -35,13 +36,13 @@ func (m *MockNotify) UpdateCheck(id structs.CheckID, status, output string) {
func expectStatus(t *testing.T, script, status string) { func expectStatus(t *testing.T, script, status string) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckMonitor{ check := &CheckMonitor{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: script, Script: script,
Interval: 10 * time.Millisecond, Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags), Logger: log.New(os.Stderr, "", log.LstdFlags),
@ -84,13 +85,13 @@ func TestCheckMonitor_BadCmd(t *testing.T) {
func TestCheckMonitor_Timeout(t *testing.T) { func TestCheckMonitor_Timeout(t *testing.T) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckMonitor{ check := &CheckMonitor{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: "sleep 1 && exit 0", Script: "sleep 1 && exit 0",
Interval: 10 * time.Millisecond, Interval: 10 * time.Millisecond,
Timeout: 5 * time.Millisecond, Timeout: 5 * time.Millisecond,
@ -114,13 +115,13 @@ func TestCheckMonitor_Timeout(t *testing.T) {
func TestCheckMonitor_RandomStagger(t *testing.T) { func TestCheckMonitor_RandomStagger(t *testing.T) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckMonitor{ check := &CheckMonitor{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: "exit 0", Script: "exit 0",
Interval: 25 * time.Millisecond, Interval: 25 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags), Logger: log.New(os.Stderr, "", log.LstdFlags),
@ -143,13 +144,13 @@ func TestCheckMonitor_RandomStagger(t *testing.T) {
func TestCheckMonitor_LimitOutput(t *testing.T) { func TestCheckMonitor_LimitOutput(t *testing.T) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckMonitor{ check := &CheckMonitor{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: "od -N 81920 /dev/urandom", Script: "od -N 81920 /dev/urandom",
Interval: 25 * time.Millisecond, Interval: 25 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags), Logger: log.New(os.Stderr, "", log.LstdFlags),
@ -168,13 +169,13 @@ func TestCheckMonitor_LimitOutput(t *testing.T) {
func TestCheckTTL(t *testing.T) { func TestCheckTTL(t *testing.T) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckTTL{ check := &CheckTTL{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
TTL: 100 * time.Millisecond, TTL: 100 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags), 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) { func expectHTTPStatus(t *testing.T, url string, status string) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckHTTP{ check := &CheckHTTP{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
HTTP: url, HTTP: url,
Interval: 10 * time.Millisecond, Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags), Logger: log.New(os.Stderr, "", log.LstdFlags),
@ -329,14 +330,14 @@ func TestCheckHTTPTimeout(t *testing.T) {
defer server.Close() defer server.Close()
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckHTTP{ check := &CheckHTTP{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("bar"), CheckID: types.CheckID("bar"),
HTTP: server.URL, HTTP: server.URL,
Timeout: 5 * time.Millisecond, Timeout: 5 * time.Millisecond,
Interval: 10 * time.Millisecond, Interval: 10 * time.Millisecond,
@ -360,7 +361,7 @@ func TestCheckHTTPTimeout(t *testing.T) {
func TestCheckHTTP_disablesKeepAlives(t *testing.T) { func TestCheckHTTP_disablesKeepAlives(t *testing.T) {
check := &CheckHTTP{ check := &CheckHTTP{
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
HTTP: "http://foo.bar/baz", HTTP: "http://foo.bar/baz",
Interval: 10 * time.Second, Interval: 10 * time.Second,
Logger: log.New(os.Stderr, "", log.LstdFlags), 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) { func expectTCPStatus(t *testing.T, tcp string, status string) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckTCP{ check := &CheckTCP{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
TCP: tcp, TCP: tcp,
Interval: 10 * time.Millisecond, Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags), 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) { func expectDockerCheckStatus(t *testing.T, dockerClient DockerClient, status string, output string) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckDocker{ check := &CheckDocker{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: "/health.sh", Script: "/health.sh",
DockerContainerID: "54432bad1fc7", DockerContainerID: "54432bad1fc7",
Shell: "/bin/sh", Shell: "/bin/sh",
@ -635,13 +636,13 @@ func TestDockerCheckWhenExecInfoFails(t *testing.T) {
func TestDockerCheckDefaultToSh(t *testing.T) { func TestDockerCheckDefaultToSh(t *testing.T) {
os.Setenv("SHELL", "") os.Setenv("SHELL", "")
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckDocker{ check := &CheckDocker{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: "/health.sh", Script: "/health.sh",
DockerContainerID: "54432bad1fc7", DockerContainerID: "54432bad1fc7",
Interval: 10 * time.Millisecond, Interval: 10 * time.Millisecond,
@ -659,14 +660,14 @@ func TestDockerCheckDefaultToSh(t *testing.T) {
func TestDockerCheckUseShellFromEnv(t *testing.T) { func TestDockerCheckUseShellFromEnv(t *testing.T) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
os.Setenv("SHELL", "/bin/bash") os.Setenv("SHELL", "/bin/bash")
check := &CheckDocker{ check := &CheckDocker{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: "/health.sh", Script: "/health.sh",
DockerContainerID: "54432bad1fc7", DockerContainerID: "54432bad1fc7",
Interval: 10 * time.Millisecond, Interval: 10 * time.Millisecond,
@ -685,13 +686,13 @@ func TestDockerCheckUseShellFromEnv(t *testing.T) {
func TestDockerCheckTruncateOutput(t *testing.T) { func TestDockerCheckTruncateOutput(t *testing.T) {
mock := &MockNotify{ mock := &MockNotify{
state: make(map[structs.CheckID]string), state: make(map[types.CheckID]string),
updates: make(map[structs.CheckID]int), updates: make(map[types.CheckID]int),
output: make(map[structs.CheckID]string), output: make(map[types.CheckID]string),
} }
check := &CheckDocker{ check := &CheckDocker{
Notify: mock, Notify: mock,
CheckID: structs.CheckID("foo"), CheckID: types.CheckID("foo"),
Script: "/health.sh", Script: "/health.sh",
DockerContainerID: "54432bad1fc7", DockerContainerID: "54432bad1fc7",
Shell: "/bin/sh", Shell: "/bin/sh",

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/consul/consul" "github.com/hashicorp/consul/consul"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
) )
const ( const (
@ -56,12 +57,12 @@ type localState struct {
serviceTokens map[string]string serviceTokens map[string]string
// Checks tracks the local checks // Checks tracks the local checks
checks map[structs.CheckID]*structs.HealthCheck checks map[types.CheckID]*structs.HealthCheck
checkStatus map[structs.CheckID]syncStatus checkStatus map[types.CheckID]syncStatus
checkTokens map[structs.CheckID]string checkTokens map[types.CheckID]string
// Used to track checks that are being deferred // Used to track checks that are being deferred
deferCheck map[structs.CheckID]*time.Timer deferCheck map[types.CheckID]*time.Timer
// consulCh is used to inform of a change to the known // consulCh is used to inform of a change to the known
// consul nodes. This may be used to retry a sync run // 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.services = make(map[string]*structs.NodeService)
l.serviceStatus = make(map[string]syncStatus) l.serviceStatus = make(map[string]syncStatus)
l.serviceTokens = make(map[string]string) l.serviceTokens = make(map[string]string)
l.checks = make(map[structs.CheckID]*structs.HealthCheck) l.checks = make(map[types.CheckID]*structs.HealthCheck)
l.checkStatus = make(map[structs.CheckID]syncStatus) l.checkStatus = make(map[types.CheckID]syncStatus)
l.checkTokens = make(map[structs.CheckID]string) l.checkTokens = make(map[types.CheckID]string)
l.deferCheck = make(map[structs.CheckID]*time.Timer) l.deferCheck = make(map[types.CheckID]*time.Timer)
l.consulCh = make(chan struct{}, 1) l.consulCh = make(chan struct{}, 1)
l.triggerCh = make(chan struct{}, 1) l.triggerCh = make(chan struct{}, 1)
} }
@ -193,14 +194,14 @@ func (l *localState) Services() map[string]*structs.NodeService {
// CheckToken is used to return the configured health check token, or // CheckToken is used to return the configured health check token, or
// if none is configured, the default agent ACL token. // if none is configured, the default agent ACL token.
func (l *localState) CheckToken(id structs.CheckID) string { func (l *localState) CheckToken(id types.CheckID) string {
l.RLock() l.RLock()
defer l.RUnlock() defer l.RUnlock()
return l.checkToken(id) return l.checkToken(id)
} }
// checkToken returns an ACL token associated with a check. // checkToken returns an ACL token associated with a check.
func (l *localState) checkToken(id structs.CheckID) string { func (l *localState) checkToken(id types.CheckID) string {
token := l.checkTokens[id] token := l.checkTokens[id]
if token == "" { if token == "" {
token = l.config.ACLToken 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. // RemoveCheck is used to remove a health check from the local state.
// The agent will make a best effort to ensure it is deregistered // The agent will make a best effort to ensure it is deregistered
func (l *localState) RemoveCheck(checkID structs.CheckID) { func (l *localState) RemoveCheck(checkID types.CheckID) {
l.Lock() l.Lock()
defer l.Unlock() defer l.Unlock()
@ -237,7 +238,7 @@ func (l *localState) RemoveCheck(checkID structs.CheckID) {
} }
// UpdateCheck is used to update the status of a check // UpdateCheck is used to update the status of a check
func (l *localState) UpdateCheck(checkID structs.CheckID, status, output string) { func (l *localState) UpdateCheck(checkID types.CheckID, status, output string) {
l.Lock() l.Lock()
defer l.Unlock() defer l.Unlock()
@ -282,8 +283,8 @@ func (l *localState) UpdateCheck(checkID structs.CheckID, status, output string)
// Checks returns the locally registered checks that the // Checks returns the locally registered checks that the
// agent is aware of and are being kept in sync with the server // agent is aware of and are being kept in sync with the server
func (l *localState) Checks() map[structs.CheckID]*structs.HealthCheck { func (l *localState) Checks() map[types.CheckID]*structs.HealthCheck {
checks := make(map[structs.CheckID]*structs.HealthCheck) checks := make(map[types.CheckID]*structs.HealthCheck)
l.RLock() l.RLock()
defer l.RUnlock() defer l.RUnlock()
@ -406,7 +407,7 @@ func (l *localState) setSyncState() error {
} }
// Index the remote health checks to improve efficiency // Index the remote health checks to improve efficiency
checkIndex := make(map[structs.CheckID]*structs.HealthCheck, len(checks)) checkIndex := make(map[types.CheckID]*structs.HealthCheck, len(checks))
for _, check := range checks { for _, check := range checks {
checkIndex[check.CheckID] = check 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 // deleteCheck is used to delete a service from the server
func (l *localState) deleteCheck(id structs.CheckID) error { func (l *localState) deleteCheck(id types.CheckID) error {
if id == "" { if id == "" {
return fmt.Errorf("CheckID missing") 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 // syncCheck is used to sync a check to the server
func (l *localState) syncCheck(id structs.CheckID) error { func (l *localState) syncCheck(id types.CheckID) error {
// Pull in the associated service if any // Pull in the associated service if any
check := l.checks[id] check := l.checks[id]
var service *structs.NodeService var service *structs.NodeService

View File

@ -2,6 +2,7 @@ package agent
import ( import (
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/types"
) )
// ServiceDefinition is used to JSON decode the Service definitions // ServiceDefinition is used to JSON decode the Service definitions
@ -44,7 +45,7 @@ func (s *ServiceDefinition) CheckTypes() (checks CheckTypes) {
// ChecKDefinition is used to JSON decode the Check definitions // ChecKDefinition is used to JSON decode the Check definitions
type CheckDefinition struct { type CheckDefinition struct {
ID structs.CheckID ID types.CheckID
Name string Name string
Notes string Notes string
ServiceID string ServiceID string
@ -66,7 +67,7 @@ func (c *CheckDefinition) HealthCheck(node string) *structs.HealthCheck {
health.Status = c.Status health.Status = c.Status
} }
if health.CheckID == "" && health.Name != "" { if health.CheckID == "" && health.Name != "" {
health.CheckID = structs.CheckID(health.Name) health.CheckID = types.CheckID(health.Name)
} }
return health return health
} }

View File

@ -12,7 +12,7 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/types"
"github.com/hashicorp/go-msgpack/codec" "github.com/hashicorp/go-msgpack/codec"
) )
@ -72,9 +72,9 @@ func stringHash(s string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(s))) return fmt.Sprintf("%x", md5.Sum([]byte(s)))
} }
// checkIDHash returns a simple md5sum for a structs.CheckID. // checkIDHash returns a simple md5sum for a types.CheckID.
func checkIDHash(checkID structs.CheckID) string { func checkIDHash(checkID types.CheckID) string {
return fmt.Sprintf("%x", md5.Sum([]byte(string(checkID)))) return stringHash(string(checkID))
} }
// FilePermissions is an interface which allows a struct to set // FilePermissions is an interface which allows a struct to set

View File

@ -6,6 +6,7 @@ import (
"github.com/armon/go-metrics" "github.com/armon/go-metrics"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/types"
) )
// Catalog endpoint is used to manipulate the service catalog // 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 { for _, check := range args.Checks {
if check.CheckID == "" && check.Name != "" { if check.CheckID == "" && check.Name != "" {
check.CheckID = structs.CheckID(check.Name) check.CheckID = types.CheckID(check.Name)
} }
if check.Node == "" { if check.Node == "" {
check.Node = args.Node check.Node = args.Node

View File

@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/types"
"github.com/hashicorp/go-memdb" "github.com/hashicorp/go-memdb"
"github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/coordinate"
) )
@ -594,7 +595,7 @@ func (s *StateStore) deleteNodeTxn(tx *memdb.Txn, idx uint64, nodeID string) err
if err != nil { if err != nil {
return fmt.Errorf("failed check lookup: %s", err) return fmt.Errorf("failed check lookup: %s", err)
} }
var cids []structs.CheckID var cids []types.CheckID
for check := checks.Next(); check != nil; check = checks.Next() { for check := checks.Next(); check != nil; check = checks.Next() {
cids = append(cids, check.(*structs.HealthCheck).CheckID) 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 { if err != nil {
return fmt.Errorf("failed service check lookup: %s", err) return fmt.Errorf("failed service check lookup: %s", err)
} }
var cids []structs.CheckID var cids []types.CheckID
for check := checks.Next(); check != nil; check = checks.Next() { for check := checks.Next(); check != nil; check = checks.Next() {
cids = append(cids, check.(*structs.HealthCheck).CheckID) cids = append(cids, check.(*structs.HealthCheck).CheckID)
} }
@ -1119,7 +1120,7 @@ func (s *StateStore) parseChecks(idx uint64, iter memdb.ResultIterator) (uint64,
} }
// DeleteCheck is used to delete a health check registration. // DeleteCheck is used to delete a health check registration.
func (s *StateStore) DeleteCheck(idx uint64, node string, id structs.CheckID) error { func (s *StateStore) DeleteCheck(idx uint64, node string, id types.CheckID) error {
tx := s.db.Txn(true) tx := s.db.Txn(true)
defer tx.Abort() defer tx.Abort()
@ -1136,7 +1137,7 @@ func (s *StateStore) DeleteCheck(idx uint64, node string, id structs.CheckID) er
// deleteCheckTxn is the inner method used to call a health // deleteCheckTxn is the inner method used to call a health
// check deletion within an existing transaction. // check deletion within an existing transaction.
func (s *StateStore) deleteCheckTxn(tx *memdb.Txn, idx uint64, watches *DumbWatchManager, node string, id structs.CheckID) error { func (s *StateStore) deleteCheckTxn(tx *memdb.Txn, idx uint64, watches *DumbWatchManager, node string, id types.CheckID) error {
// Try to retrieve the existing health check. // Try to retrieve the existing health check.
hc, err := tx.First("checks", "id", node, id) hc, err := tx.First("checks", "id", node, id)
if err != nil { if err != nil {

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/consul/structs"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/types"
"github.com/hashicorp/serf/coordinate" "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, func testRegisterCheck(t *testing.T, s *StateStore, idx uint64,
nodeID string, serviceID string, checkID structs.CheckID, state string) { nodeID string, serviceID string, checkID types.CheckID, state string) {
chk := &structs.HealthCheck{ chk := &structs.HealthCheck{
Node: nodeID, Node: nodeID,
CheckID: checkID, CheckID: checkID,

View File

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/types"
"github.com/hashicorp/go-msgpack/codec" "github.com/hashicorp/go-msgpack/codec"
"github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/coordinate"
) )
@ -181,7 +182,7 @@ type DeregisterRequest struct {
Datacenter string Datacenter string
Node string Node string
ServiceID string ServiceID string
CheckID CheckID CheckID types.CheckID
WriteRequest WriteRequest
} }
@ -364,19 +365,16 @@ type NodeServices struct {
Services map[string]*NodeService Services map[string]*NodeService
} }
// CheckID is a strongly typed string
type CheckID string
// HealthCheck represents a single check on a given node // HealthCheck represents a single check on a given node
type HealthCheck struct { type HealthCheck struct {
Node string Node string
CheckID CheckID // Unique per-node ID CheckID types.CheckID // Unique per-node ID
Name string // Check name Name string // Check name
Status string // The current check status Status string // The current check status
Notes string // Additional notes with the status Notes string // Additional notes with the status
Output string // Holds output of script runs Output string // Holds output of script runs
ServiceID string // optional associated service ServiceID string // optional associated service
ServiceName string // optional service name ServiceName string // optional service name
RaftIndex RaftIndex
} }

39
types/README.md Normal file
View File

@ -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.

5
types/checks.go Normal file
View File

@ -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