Skip to content

Commit

Permalink
Adds Docker checks support to client API.
Browse files Browse the repository at this point in the history
Also changed `DockerContainerId` to `DockerContainerID`, and updated the agent
API docs to reflect their support for Docker checks.
  • Loading branch information
James Phillips committed Nov 18, 2015
1 parent 402a366 commit 95c708f
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 20 deletions.
16 changes: 9 additions & 7 deletions api/agent.go
Expand Up @@ -63,13 +63,15 @@ type AgentCheckRegistration struct {
// AgentServiceCheck is used to create an associated
// check for a service
type AgentServiceCheck struct {
Script string `json:",omitempty"`
Interval string `json:",omitempty"`
Timeout string `json:",omitempty"`
TTL string `json:",omitempty"`
HTTP string `json:",omitempty"`
TCP string `json:",omitempty"`
Status string `json:",omitempty"`
Script string `json:",omitempty"`
DockerContainerID string `json:",omitempty"`
Shell string `json:",omitempty"` // Only supported for Docker.
Interval string `json:",omitempty"`
Timeout string `json:",omitempty"`
TTL string `json:",omitempty"`
HTTP string `json:",omitempty"`
TCP string `json:",omitempty"`
Status string `json:",omitempty"`
}
type AgentServiceChecks []*AgentServiceCheck

Expand Down
44 changes: 44 additions & 0 deletions api/agent_test.go
Expand Up @@ -387,6 +387,50 @@ func TestAgent_Checks_serviceBound(t *testing.T) {
}
}

func TestAgent_Checks_Docker(t *testing.T) {
t.Parallel()
c, s := makeClient(t)
defer s.Stop()

agent := c.Agent()

// First register a service
serviceReg := &AgentServiceRegistration{
Name: "redis",
}
if err := agent.ServiceRegister(serviceReg); err != nil {
t.Fatalf("err: %v", err)
}

// Register a check bound to the service
reg := &AgentCheckRegistration{
Name: "redischeck",
ServiceID: "redis",
AgentServiceCheck: AgentServiceCheck{
DockerContainerID: "f972c95ebf0e",
Script: "/bin/true",
Shell: "/bin/bash",
Interval: "10s",
},
}
if err := agent.CheckRegister(reg); err != nil {
t.Fatalf("err: %v", err)
}

checks, err := agent.Checks()
if err != nil {
t.Fatalf("err: %v", err)
}

check, ok := checks["redischeck"]
if !ok {
t.Fatalf("missing check: %v", checks)
}
if check.ServiceID != "redis" {
t.Fatalf("missing service association for check: %v", check)
}
}

func TestAgent_Join(t *testing.T) {
t.Parallel()
c, s := makeClient(t)
Expand Down
2 changes: 1 addition & 1 deletion command/agent/agent.go
Expand Up @@ -919,7 +919,7 @@ func (a *Agent) AddCheck(check *structs.HealthCheck, chkType *CheckType, persist
dockerCheck := &CheckDocker{
Notify: &a.state,
CheckID: check.CheckID,
DockerContainerId: chkType.DockerContainerId,
DockerContainerID: chkType.DockerContainerID,
Shell: chkType.Shell,
Script: chkType.Script,
Interval: chkType.Interval,
Expand Down
12 changes: 6 additions & 6 deletions command/agent/check.go
Expand Up @@ -44,7 +44,7 @@ type CheckType struct {
HTTP string
TCP string
Interval time.Duration
DockerContainerId string
DockerContainerID string
Shell string

Timeout time.Duration
Expand All @@ -68,7 +68,7 @@ func (c *CheckType) IsTTL() bool {

// IsMonitor checks if this is a Monitor type
func (c *CheckType) IsMonitor() bool {
return c.Script != "" && c.DockerContainerId == "" && c.Interval != 0
return c.Script != "" && c.DockerContainerID == "" && c.Interval != 0
}

// IsHTTP checks if this is a HTTP type
Expand All @@ -82,7 +82,7 @@ func (c *CheckType) IsTCP() bool {
}

func (c *CheckType) IsDocker() bool {
return c.DockerContainerId != "" && c.Script != "" && c.Interval != 0
return c.DockerContainerID != "" && c.Script != "" && c.Interval != 0
}

// CheckNotifier interface is used by the CheckMonitor
Expand Down Expand Up @@ -518,7 +518,7 @@ type CheckDocker struct {
Notify CheckNotifier
CheckID string
Script string
DockerContainerId string
DockerContainerID string
Shell string
Interval time.Duration
Logger *log.Logger
Expand Down Expand Up @@ -574,7 +574,7 @@ func (c *CheckDocker) Stop() {
func (c *CheckDocker) run() {
// Get the randomized initial pause time
initialPauseTime := randomStagger(c.Interval)
c.Logger.Printf("[DEBUG] agent: pausing %v before first invocation of %s -c %s in container %s", initialPauseTime, c.Shell, c.Script, c.DockerContainerId)
c.Logger.Printf("[DEBUG] agent: pausing %v before first invocation of %s -c %s in container %s", initialPauseTime, c.Shell, c.Script, c.DockerContainerID)
next := time.After(initialPauseTime)
for {
select {
Expand All @@ -595,7 +595,7 @@ func (c *CheckDocker) check() {
AttachStderr: true,
Tty: false,
Cmd: c.cmd,
Container: c.DockerContainerId,
Container: c.DockerContainerID,
}
var (
exec *docker.Exec
Expand Down
8 changes: 4 additions & 4 deletions command/agent/check_test.go
Expand Up @@ -535,7 +535,7 @@ func expectDockerCheckStatus(t *testing.T, dockerClient DockerClient, status str
Notify: mock,
CheckID: "foo",
Script: "/health.sh",
DockerContainerId: "54432bad1fc7",
DockerContainerID: "54432bad1fc7",
Shell: "/bin/sh",
Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags),
Expand Down Expand Up @@ -595,7 +595,7 @@ func TestDockerCheckDefaultToSh(t *testing.T) {
Notify: mock,
CheckID: "foo",
Script: "/health.sh",
DockerContainerId: "54432bad1fc7",
DockerContainerID: "54432bad1fc7",
Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags),
dockerClient: &fakeDockerClientWithNoErrors{},
Expand All @@ -620,7 +620,7 @@ func TestDockerCheckUseShellFromEnv(t *testing.T) {
Notify: mock,
CheckID: "foo",
Script: "/health.sh",
DockerContainerId: "54432bad1fc7",
DockerContainerID: "54432bad1fc7",
Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags),
dockerClient: &fakeDockerClientWithNoErrors{},
Expand All @@ -645,7 +645,7 @@ func TestDockerCheckTruncateOutput(t *testing.T) {
Notify: mock,
CheckID: "foo",
Script: "/health.sh",
DockerContainerId: "54432bad1fc7",
DockerContainerID: "54432bad1fc7",
Shell: "/bin/sh",
Interval: 10 * time.Millisecond,
Logger: log.New(os.Stderr, "", log.LstdFlags),
Expand Down
2 changes: 1 addition & 1 deletion command/agent/config.go
Expand Up @@ -782,7 +782,7 @@ func FixupCheckType(raw interface{}) error {
rawMap["serviceid"] = v
delete(rawMap, "service_id")
case "docker_container_id":
rawMap["DockerContainerId"] = v
rawMap["DockerContainerID"] = v
delete(rawMap, "docker_container_id")
}
}
Expand Down
2 changes: 1 addition & 1 deletion command/agent/config_test.go
Expand Up @@ -1133,7 +1133,7 @@ func TestDecodeConfig_Check(t *testing.T) {
t.Fatalf("bad: %v", chk)
}

if chk.DockerContainerId != "redis" {
if chk.DockerContainerID != "redis" {
t.Fatalf("bad: %v", chk)
}
}
Expand Down
6 changes: 6 additions & 0 deletions website/source/docs/agent/http/agent.html.markdown
Expand Up @@ -241,6 +241,8 @@ body must look like:
"Name": "Memory utilization",
"Notes": "Ensure we don't oversubscribe memory",
"Script": "/usr/local/bin/check_mem.py",
"DockerContainerID": "f972c95ebf0e",
"Shell": "/bin/bash",
"HTTP": "http://example.com",
"TCP": "example.com:22",
"Interval": "10s",
Expand All @@ -259,6 +261,10 @@ The `Notes` field is not used internally by Consul and is meant to be human-read
If a `Script` is provided, the check type is a script, and Consul will
evaluate the script every `Interval` to update the status.

If a `DockerContainerID` is provided, the check is a Docker check, and Consul will
evaluate the script every `Interval` in the given container using the specified
`Shell`. Note that `Shell` is currently only supported for Docker checks.

An `HTTP` check will perform an HTTP GET request against the value of `HTTP` (expected to
be a URL) every `Interval`. If the response is any `2xx` code, the check is `passing`.
If the response is `429 Too Many Requests`, the check is `warning`. Otherwise, the check
Expand Down

0 comments on commit 95c708f

Please sign in to comment.