mirror of
https://github.com/kemko/nomad.git
synced 2026-01-02 16:35:44 +03:00
159 lines
4.3 KiB
Go
159 lines
4.3 KiB
Go
package executor
|
|
|
|
import (
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/armon/circbuf"
|
|
docker "github.com/fsouza/go-dockerclient"
|
|
cstructs "github.com/hashicorp/nomad/client/driver/structs"
|
|
)
|
|
|
|
var (
|
|
// We store the client globally to cache the connection to the docker daemon.
|
|
createClient sync.Once
|
|
client *docker.Client
|
|
)
|
|
|
|
const (
|
|
// The default check timeout
|
|
defaultCheckTimeout = 30 * time.Second
|
|
)
|
|
|
|
// DockerScriptCheck runs nagios compatible scripts in a docker container and
|
|
// provides the check result
|
|
type DockerScriptCheck struct {
|
|
id string // id of the check
|
|
interval time.Duration // interval of the check
|
|
timeout time.Duration // timeout of the check
|
|
containerID string // container id in which the check will be invoked
|
|
logger *log.Logger
|
|
cmd string // check command
|
|
args []string // check command arguments
|
|
|
|
dockerEndpoint string // docker endpoint
|
|
tlsCert string // path to tls certificate
|
|
tlsCa string // path to tls ca
|
|
tlsKey string // path to tls key
|
|
}
|
|
|
|
// dockerClient creates the client to interact with the docker daemon
|
|
func (d *DockerScriptCheck) dockerClient() (*docker.Client, error) {
|
|
if client != nil {
|
|
return client, nil
|
|
}
|
|
|
|
var err error
|
|
createClient.Do(func() {
|
|
if d.dockerEndpoint != "" {
|
|
if d.tlsCert+d.tlsKey+d.tlsCa != "" {
|
|
d.logger.Printf("[DEBUG] executor.checks: using TLS client connection to %s", d.dockerEndpoint)
|
|
client, err = docker.NewTLSClient(d.dockerEndpoint, d.tlsCert, d.tlsKey, d.tlsCa)
|
|
} else {
|
|
d.logger.Printf("[DEBUG] executor.checks: using standard client connection to %s", d.dockerEndpoint)
|
|
client, err = docker.NewClient(d.dockerEndpoint)
|
|
}
|
|
return
|
|
}
|
|
|
|
d.logger.Println("[DEBUG] executor.checks: using client connection initialized from environment")
|
|
client, err = docker.NewClientFromEnv()
|
|
})
|
|
return client, err
|
|
}
|
|
|
|
// Run runs a script check inside a docker container
|
|
func (d *DockerScriptCheck) Run() *cstructs.CheckResult {
|
|
var (
|
|
exec *docker.Exec
|
|
err error
|
|
execRes *docker.ExecInspect
|
|
time = time.Now()
|
|
)
|
|
|
|
if client, err = d.dockerClient(); err != nil {
|
|
return &cstructs.CheckResult{Err: err}
|
|
}
|
|
client = client
|
|
execOpts := docker.CreateExecOptions{
|
|
AttachStdin: false,
|
|
AttachStdout: true,
|
|
AttachStderr: true,
|
|
Tty: false,
|
|
Cmd: append([]string{d.cmd}, d.args...),
|
|
Container: d.containerID,
|
|
}
|
|
if exec, err = client.CreateExec(execOpts); err != nil {
|
|
return &cstructs.CheckResult{Err: err}
|
|
}
|
|
|
|
output, _ := circbuf.NewBuffer(int64(cstructs.CheckBufSize))
|
|
startOpts := docker.StartExecOptions{
|
|
Detach: false,
|
|
Tty: false,
|
|
OutputStream: output,
|
|
ErrorStream: output,
|
|
}
|
|
|
|
if err = client.StartExec(exec.ID, startOpts); err != nil {
|
|
return &cstructs.CheckResult{Err: err}
|
|
}
|
|
if execRes, err = client.InspectExec(exec.ID); err != nil {
|
|
return &cstructs.CheckResult{Err: err}
|
|
}
|
|
return &cstructs.CheckResult{
|
|
ExitCode: execRes.ExitCode,
|
|
Output: string(output.Bytes()),
|
|
Timestamp: time,
|
|
}
|
|
}
|
|
|
|
// ID returns the check id
|
|
func (d *DockerScriptCheck) ID() string {
|
|
return d.id
|
|
}
|
|
|
|
// Interval returns the interval at which the check has to run
|
|
func (d *DockerScriptCheck) Interval() time.Duration {
|
|
return d.interval
|
|
}
|
|
|
|
// Timeout returns the duration after which a check is timed out.
|
|
func (d *DockerScriptCheck) Timeout() time.Duration {
|
|
if d.timeout == 0 {
|
|
return defaultCheckTimeout
|
|
}
|
|
return d.timeout
|
|
}
|
|
|
|
// ExecScriptCheck runs a nagios compatible script and returns the check result
|
|
type ExecScriptCheck struct {
|
|
id string // id of the script check
|
|
interval time.Duration // interval at which the check is invoked
|
|
timeout time.Duration // timeout duration of the check
|
|
cmd string // command of the check
|
|
args []string // args passed to the check
|
|
taskDir string // the root directory of the check
|
|
|
|
FSIsolation bool // indicates whether the check has to be run within a chroot
|
|
}
|
|
|
|
// ID returns the check id
|
|
func (e *ExecScriptCheck) ID() string {
|
|
return e.id
|
|
}
|
|
|
|
// Interval returns the interval at which the check has to run
|
|
func (e *ExecScriptCheck) Interval() time.Duration {
|
|
return e.interval
|
|
}
|
|
|
|
// Timeout returns the duration after which a check is timed out.
|
|
func (e *ExecScriptCheck) Timeout() time.Duration {
|
|
if e.timeout == 0 {
|
|
return defaultCheckTimeout
|
|
}
|
|
return e.timeout
|
|
}
|