mirror of https://github.com/status-im/consul.git
Merge pull request #1424 from hashicorp/b-docker-client-api
Adds Docker checks support to client API.
This commit is contained in:
commit
1b31d543bc
16
api/agent.go
16
api/agent.go
|
@ -63,13 +63,15 @@ type AgentCheckRegistration struct {
|
||||||
// AgentServiceCheck is used to create an associated
|
// AgentServiceCheck is used to create an associated
|
||||||
// check for a service
|
// check for a service
|
||||||
type AgentServiceCheck struct {
|
type AgentServiceCheck struct {
|
||||||
Script string `json:",omitempty"`
|
Script string `json:",omitempty"`
|
||||||
Interval string `json:",omitempty"`
|
DockerContainerID string `json:",omitempty"`
|
||||||
Timeout string `json:",omitempty"`
|
Shell string `json:",omitempty"` // Only supported for Docker.
|
||||||
TTL string `json:",omitempty"`
|
Interval string `json:",omitempty"`
|
||||||
HTTP string `json:",omitempty"`
|
Timeout string `json:",omitempty"`
|
||||||
TCP string `json:",omitempty"`
|
TTL string `json:",omitempty"`
|
||||||
Status string `json:",omitempty"`
|
HTTP string `json:",omitempty"`
|
||||||
|
TCP string `json:",omitempty"`
|
||||||
|
Status string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
type AgentServiceChecks []*AgentServiceCheck
|
type AgentServiceChecks []*AgentServiceCheck
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
func TestAgent_Join(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
c, s := makeClient(t)
|
c, s := makeClient(t)
|
||||||
|
|
|
@ -919,7 +919,7 @@ func (a *Agent) AddCheck(check *structs.HealthCheck, chkType *CheckType, persist
|
||||||
dockerCheck := &CheckDocker{
|
dockerCheck := &CheckDocker{
|
||||||
Notify: &a.state,
|
Notify: &a.state,
|
||||||
CheckID: check.CheckID,
|
CheckID: check.CheckID,
|
||||||
DockerContainerId: chkType.DockerContainerId,
|
DockerContainerID: chkType.DockerContainerID,
|
||||||
Shell: chkType.Shell,
|
Shell: chkType.Shell,
|
||||||
Script: chkType.Script,
|
Script: chkType.Script,
|
||||||
Interval: chkType.Interval,
|
Interval: chkType.Interval,
|
||||||
|
|
|
@ -44,7 +44,7 @@ type CheckType struct {
|
||||||
HTTP string
|
HTTP string
|
||||||
TCP string
|
TCP string
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
DockerContainerId string
|
DockerContainerID string
|
||||||
Shell string
|
Shell string
|
||||||
|
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
|
@ -68,7 +68,7 @@ func (c *CheckType) IsTTL() bool {
|
||||||
|
|
||||||
// IsMonitor checks if this is a Monitor type
|
// IsMonitor checks if this is a Monitor type
|
||||||
func (c *CheckType) IsMonitor() bool {
|
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
|
// IsHTTP checks if this is a HTTP type
|
||||||
|
@ -82,7 +82,7 @@ func (c *CheckType) IsTCP() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CheckType) IsDocker() 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
|
// CheckNotifier interface is used by the CheckMonitor
|
||||||
|
@ -518,7 +518,7 @@ type CheckDocker struct {
|
||||||
Notify CheckNotifier
|
Notify CheckNotifier
|
||||||
CheckID string
|
CheckID string
|
||||||
Script string
|
Script string
|
||||||
DockerContainerId string
|
DockerContainerID string
|
||||||
Shell string
|
Shell string
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
Logger *log.Logger
|
Logger *log.Logger
|
||||||
|
@ -574,7 +574,7 @@ func (c *CheckDocker) Stop() {
|
||||||
func (c *CheckDocker) run() {
|
func (c *CheckDocker) run() {
|
||||||
// Get the randomized initial pause time
|
// Get the randomized initial pause time
|
||||||
initialPauseTime := randomStagger(c.Interval)
|
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)
|
next := time.After(initialPauseTime)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -595,7 +595,7 @@ func (c *CheckDocker) check() {
|
||||||
AttachStderr: true,
|
AttachStderr: true,
|
||||||
Tty: false,
|
Tty: false,
|
||||||
Cmd: c.cmd,
|
Cmd: c.cmd,
|
||||||
Container: c.DockerContainerId,
|
Container: c.DockerContainerID,
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
exec *docker.Exec
|
exec *docker.Exec
|
||||||
|
|
|
@ -535,7 +535,7 @@ func expectDockerCheckStatus(t *testing.T, dockerClient DockerClient, status str
|
||||||
Notify: mock,
|
Notify: mock,
|
||||||
CheckID: "foo",
|
CheckID: "foo",
|
||||||
Script: "/health.sh",
|
Script: "/health.sh",
|
||||||
DockerContainerId: "54432bad1fc7",
|
DockerContainerID: "54432bad1fc7",
|
||||||
Shell: "/bin/sh",
|
Shell: "/bin/sh",
|
||||||
Interval: 10 * time.Millisecond,
|
Interval: 10 * time.Millisecond,
|
||||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||||
|
@ -595,7 +595,7 @@ func TestDockerCheckDefaultToSh(t *testing.T) {
|
||||||
Notify: mock,
|
Notify: mock,
|
||||||
CheckID: "foo",
|
CheckID: "foo",
|
||||||
Script: "/health.sh",
|
Script: "/health.sh",
|
||||||
DockerContainerId: "54432bad1fc7",
|
DockerContainerID: "54432bad1fc7",
|
||||||
Interval: 10 * time.Millisecond,
|
Interval: 10 * time.Millisecond,
|
||||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||||
dockerClient: &fakeDockerClientWithNoErrors{},
|
dockerClient: &fakeDockerClientWithNoErrors{},
|
||||||
|
@ -620,7 +620,7 @@ func TestDockerCheckUseShellFromEnv(t *testing.T) {
|
||||||
Notify: mock,
|
Notify: mock,
|
||||||
CheckID: "foo",
|
CheckID: "foo",
|
||||||
Script: "/health.sh",
|
Script: "/health.sh",
|
||||||
DockerContainerId: "54432bad1fc7",
|
DockerContainerID: "54432bad1fc7",
|
||||||
Interval: 10 * time.Millisecond,
|
Interval: 10 * time.Millisecond,
|
||||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||||
dockerClient: &fakeDockerClientWithNoErrors{},
|
dockerClient: &fakeDockerClientWithNoErrors{},
|
||||||
|
@ -645,7 +645,7 @@ func TestDockerCheckTruncateOutput(t *testing.T) {
|
||||||
Notify: mock,
|
Notify: mock,
|
||||||
CheckID: "foo",
|
CheckID: "foo",
|
||||||
Script: "/health.sh",
|
Script: "/health.sh",
|
||||||
DockerContainerId: "54432bad1fc7",
|
DockerContainerID: "54432bad1fc7",
|
||||||
Shell: "/bin/sh",
|
Shell: "/bin/sh",
|
||||||
Interval: 10 * time.Millisecond,
|
Interval: 10 * time.Millisecond,
|
||||||
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
Logger: log.New(os.Stderr, "", log.LstdFlags),
|
||||||
|
|
|
@ -782,7 +782,7 @@ func FixupCheckType(raw interface{}) error {
|
||||||
rawMap["serviceid"] = v
|
rawMap["serviceid"] = v
|
||||||
delete(rawMap, "service_id")
|
delete(rawMap, "service_id")
|
||||||
case "docker_container_id":
|
case "docker_container_id":
|
||||||
rawMap["DockerContainerId"] = v
|
rawMap["DockerContainerID"] = v
|
||||||
delete(rawMap, "docker_container_id")
|
delete(rawMap, "docker_container_id")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1133,7 +1133,7 @@ func TestDecodeConfig_Check(t *testing.T) {
|
||||||
t.Fatalf("bad: %v", chk)
|
t.Fatalf("bad: %v", chk)
|
||||||
}
|
}
|
||||||
|
|
||||||
if chk.DockerContainerId != "redis" {
|
if chk.DockerContainerID != "redis" {
|
||||||
t.Fatalf("bad: %v", chk)
|
t.Fatalf("bad: %v", chk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,8 @@ body must look like:
|
||||||
"Name": "Memory utilization",
|
"Name": "Memory utilization",
|
||||||
"Notes": "Ensure we don't oversubscribe memory",
|
"Notes": "Ensure we don't oversubscribe memory",
|
||||||
"Script": "/usr/local/bin/check_mem.py",
|
"Script": "/usr/local/bin/check_mem.py",
|
||||||
|
"DockerContainerID": "f972c95ebf0e",
|
||||||
|
"Shell": "/bin/bash",
|
||||||
"HTTP": "http://example.com",
|
"HTTP": "http://example.com",
|
||||||
"TCP": "example.com:22",
|
"TCP": "example.com:22",
|
||||||
"Interval": "10s",
|
"Interval": "10s",
|
||||||
|
@ -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
|
If a `Script` is provided, the check type is a script, and Consul will
|
||||||
evaluate the script every `Interval` to update the status.
|
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
|
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`.
|
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
|
If the response is `429 Too Many Requests`, the check is `warning`. Otherwise, the check
|
||||||
|
|
Loading…
Reference in New Issue