greenlight

package module
v0.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2023 License: MIT Imports: 23 Imported by: 0

README

greenlight

greelight is a graceful health check agent.

Usage

Usage: greenlight --config="greenlight.yaml" [<child-cmds> ...]

Arguments:
  [<child-cmds> ...]

Flags:
  -h, --help                        Show context-sensitive help.
  -c, --config="greenlight.yaml"    config file path or URL(http,https,file,s3) ($GREENLIGHT_CONFIG)
  -d, --debug                       debug mode ($GREENLIGHT_DEBUG)
      --version                     show version

greenlight works as a health check agent for your application.

greenlight checks your application's health by startup and readiness checks.

Install

Homebrew
$ brew install fujiwara/tap/greenlight
Binary

Releases

Docker images

ghcr.io/fujiwara/greenlight

docker pull ghcr.io/fujiwara/greenlight:v0.0.6
FROM ghcr.io/fujiwara/greenlight:v0.0.6-distroless AS greenlight

FROM debian:bookworm-slim
COPY --from=greenlight /opt/greenlight/bin/greenlight /usr/local/bin/greenlight
COPY greenlight.yaml /etc/greenlight.yaml
ENV GREENLIGHT_CONFIG=/etc/greenlight.yaml
CMD ["/usr/local/bin/greenlight", "--", "/path/to/your/app"]

Spawn a child process

greenlight can spawn a child process (optional).

$ greenlight --config=greenlight.yaml -- /path/to/your/app

greenlight spawns a child process at first.

When greenlight catch a signal (SIGTERM and SIGINT), greenlight sends SIGTERM to the child process, and waits for the child process to exit. If the child process does not exit in 30 seconds, greenlight sends SIGKILL to the child process.

STDOUT and STDERR of the child process are redirected to greenlight's STDOUT and STDERR.

Health checks

greenlight checks your application's health by startup and readiness checks.

startup

Startup checks are executed at greenlight starts.

All the checks are passed, and greenlight starts a responder http server that responds 200 OK to GET / request.

Startup checks are executed in a defined order in the configuration file. If some check fails, greenlight retries the check until the check is passed.

readiness

Readiness checks are executed periodically while the greenlight is running.

If some checks fail, the responder returns 503 Service Unavailable to GET / request.

If all the checks are passed, the responder returns 200 OK to GET / request.

Configuration

startup:
  checks:
    - name: "memcached alive"
      tcp:
        host: "localhost"
        port: 11211
        send: "stats\n"
        expect_pattern: "STAT uptime"
        quit: "QUIT\n"
    - name: "app server is up"
      command:
        run: 'curl -s -o /dev/null -w "%{http_code}" http://localhost:3000'
    - &web
      name: "web server is ok"
      http:
        url: "http://localhost:80/health"
        expect_code: 200-399
readiness:
  checks:
    - name: "pass file exists"
      command:
        run: "test -f pass"
    - *web
responder:
  addr: ":8081"
startup section
startup:
  interval: 10s # default 5s
  grace_period: 10s # default 0
  checks:
    - name: "memcached alive"
      timeout: 30s # default 5s
      tcp:
        host: "localhost"
        port: 11211
        send: "version\n"
        expect_pattern: "VERSION 1."
startup.interval

The retry interval when all the checks are not passed.

startup.grace_period

The grace period before starting the checks.

startup.checks

See Check section.

readiness section
  interval: 10s # default 5s
  grace_period: 10s # default 0
  checks:
    - name: "app server alive"
      timeout: 10s # default 5s
      http:
        url: "http://localhost:3000/health"
        method: "GET" # default "GET"
        headers:
          Host: "example.com"
        expect_code: 200-299 # default 200-399
        expect_pattern: "OK" # matches a regexp with response body
readiness.interval

The interval to execute the checks.

readiness.grace_period

The grace period before starting the checks.

readiness.checks

See Check section.

responder section
responder:
  addr: ":8081" # default ":8080"
Check

check section defines a health check.

command check
name: "pid file exists"
command:
  run: "test -f /var/run/app.pid"

command check executes a command and checks the exit status. exit status 0 is passed, otherwise failed.

The command is not executed in a shell, so you can't use shell features like && or |. If you want to use shell features, use sh -c like this:

name: "pid file exists"
command:
  run: "sh -c 'test -f /var/run/app.pid && test -f /var/run/app.pid'"
tcp check
name: "memcached alive"
tcp:
  host: "localhost"
  port: 11211
  send: "version\n"
  expect_pattern: "VERSION 1."
  quit: "quit\n"

tcp check connects to the host and port.

Optionally, sends the send string, and checks the response matches the expect_pattern regexp.

If quit is defined, sends the quit string and closes the connection.

You can use TLS by tls section.

name: "LDAPS server alive"
tcp:
  host: "localhost"
  port: 636
  tls: true
  no_check_certificate: true

If no_check_certificate is true, the certificate is not checked.

http check
name: "app server alive"
http:
  url: "http://localhost:3000/health"
  method: "GET" # default "GET"
  headers:
    Host: "example.com"
  expect_code: 200-299 # default 200-399
  expect_pattern: "OK" # matches a regexp with response body
name: "app server alive"
http:
  url: "https://localhost:3000/post"
  method: "POST"
  headers:
    Host: "example.com"
    Content-Type: "application/json"
  body: '{"foo":"bar"}'
  expect_code: 200-299 # default 200-399
  expect_pattern: "OK"
  no_check_certificate: true

http check sends a http request to the url, and checks the response code.

Optionally, checks the response body matches the expect_pattern regexp.

expect_code can be a range like 200-299, or a list like 200,201,202 or complex of them. For example, 200-299,301,302 is valid.

If body is defined, sends the body (for POST, PUT, etc).

If no_check_certificate is true, the certificate is not checked.

responder.addr

The address to listen by responder.

LICENSE

MIT

Author

fujiwara

Documentation

Index

Constants

View Source
const (
	DefaultCheckInterval = 6 * time.Second
	DefaultCheckTimeout  = 5 * time.Second
	DefaultListenAddr    = ":8080"
)

Variables

View Source
var (
	DefaultHTTPTimeout = 15 * time.Second
)
View Source
var (
	DefaultTCPMaxBytes = 32 * 1024
)
View Source
var Version = ""

Functions

func Run

func Run(ctx context.Context, cli *CLI) error

Types

type CLI added in v0.0.1

type CLI struct {
	Config    string   `` /* 126-byte string literal not displayed */
	Debug     bool     `help:"debug mode" short:"d" default:"false" env:"GREENLIGHT_DEBUG"`
	Version   bool     `help:"show version"`
	ChildCmds []string `arg:"" optional:"true"`
}

type CheckConfig

type CheckConfig struct {
	Name    string        `yaml:"name"`
	Timeout time.Duration `yaml:"timeout"`

	Command *CommandCheckConfig `yaml:"command"`
	TCP     *TCPCheckConfig     `yaml:"tcp"`
	HTTP    *HTTPCheckConfig    `yaml:"http"`
}

type Checker

type Checker interface {
	Name() string
	Run(ctx context.Context) error
}

func NewChecker added in v0.0.1

func NewChecker(cfg *CheckConfig) (Checker, error)

type CommandCheckConfig added in v0.0.1

type CommandCheckConfig struct {
	Run string `yaml:"run"`
}

type CommandChecker

type CommandChecker struct {
	// contains filtered or unexported fields
}

func NewCommandChecker

func NewCommandChecker(cfg *CheckConfig) (*CommandChecker, error)

func (*CommandChecker) Name added in v0.0.1

func (c *CommandChecker) Name() string

func (*CommandChecker) Run

func (c *CommandChecker) Run(ctx context.Context) error

type Config

type Config struct {
	Responder *ResponderConfig `yaml:"responder"`
	StartUp   *PhaseConfig     `yaml:"startup"`
	Readiness *PhaseConfig     `yaml:"readiness"`
}

func LoadConfig

func LoadConfig(ctx context.Context, src string) (*Config, error)

type Greenlight

type Greenlight struct {
	Config *Config
	// contains filtered or unexported fields
}

func NewGreenlight

func NewGreenlight(cfg *Config) (*Greenlight, error)

func (*Greenlight) CheckRediness added in v0.0.1

func (g *Greenlight) CheckRediness(ctx context.Context) error

func (*Greenlight) CheckStartUp

func (g *Greenlight) CheckStartUp(ctx context.Context) error

func (*Greenlight) Run

func (g *Greenlight) Run(ctx context.Context) error

func (*Greenlight) RunChildCommand added in v0.0.4

func (g *Greenlight) RunChildCommand(ctx context.Context, wg *sync.WaitGroup, ch chan error)

func (*Greenlight) RunRedinessChecks added in v0.0.1

func (g *Greenlight) RunRedinessChecks(ctx context.Context, wg *sync.WaitGroup, ch chan error)

func (*Greenlight) RunResponder added in v0.0.4

func (g *Greenlight) RunResponder(ctx context.Context, wg *sync.WaitGroup, ch chan error)

func (*Greenlight) RunStartUpChecks added in v0.0.1

func (g *Greenlight) RunStartUpChecks(ctx context.Context, wg *sync.WaitGroup, ch chan error)

func (*Greenlight) Send added in v0.0.1

func (g *Greenlight) Send(s Signal)

type HTTPCheckConfig added in v0.0.1

type HTTPCheckConfig struct {
	URL                string            `yaml:"url"`
	Method             string            `yaml:"method"`
	Headers            map[string]string `yaml:"headers"`
	Body               string            `yaml:"body"`
	ExpectCode         string            `yaml:"expect_code"`
	ExpectPattern      string            `yaml:"expect_pattern"`
	NoCheckCertificate bool              `yaml:"no_check_certificate"`
}

type HTTPChecker added in v0.0.1

type HTTPChecker struct {
	URL                string
	Method             string
	Headers            map[string]string
	Body               string
	ExpectCodeFunc     func(code int) bool
	ExpectPattern      *regexp.Regexp
	Timeout            time.Duration
	NoCheckCertificate bool
	// contains filtered or unexported fields
}

func NewHTTPChecker added in v0.0.1

func NewHTTPChecker(cfg *CheckConfig) (*HTTPChecker, error)

func (*HTTPChecker) Name added in v0.0.1

func (p *HTTPChecker) Name() string

func (*HTTPChecker) Run added in v0.0.1

func (p *HTTPChecker) Run(ctx context.Context) error

type PhaseConfig

type PhaseConfig struct {
	Checks      []*CheckConfig `yaml:"checks"`
	Interval    time.Duration  `yaml:"interval"`
	GracePeriod time.Duration  `yaml:"grace_period"`
}

type Responder added in v0.0.1

type Responder struct {
	// contains filtered or unexported fields
}

func NewResponder added in v0.0.1

func NewResponder(cfg *ResponderConfig) (*Responder, chan Signal)

func (*Responder) Run added in v0.0.1

func (r *Responder) Run(ctx context.Context) error

type ResponderConfig added in v0.0.1

type ResponderConfig struct {
	Addr string `yaml:"addr"`
}

type Signal added in v0.0.1

type Signal string
const (
	SignalNone   Signal = ""
	SignalGreen  Signal = "green"
	SignalYellow Signal = "yellow"
	SignalRed    Signal = "red"
)

type State

type State struct {
	Phase      phase
	CheckIndex numofCheckers
}

func (*State) NextPhase added in v0.0.1

func (s *State) NextPhase()

type TCPCheckConfig added in v0.0.1

type TCPCheckConfig struct {
	Host               string `yaml:"host"`
	Port               string `yaml:"port"`
	Send               string `yaml:"send"`
	Quit               string `yaml:"quiet"`
	MaxBytes           int    `yaml:"max_bytes"`
	ExpectPattern      string `yaml:"expect_pattern"`
	TLS                bool   `yaml:"tls"`
	NoCheckCertificate bool   `yaml:"no_check_certificate"`
}

type TCPChecker added in v0.0.1

type TCPChecker struct {
	Host               string
	Port               string
	Send               string
	Quit               string
	MaxBytes           int
	ExpectPattern      *regexp.Regexp
	Timeout            time.Duration
	TLS                bool
	NoCheckCertificate bool
	// contains filtered or unexported fields
}

func NewTCPChecker added in v0.0.1

func NewTCPChecker(cfg *CheckConfig) (*TCPChecker, error)

func (*TCPChecker) Name added in v0.0.1

func (p *TCPChecker) Name() string

func (*TCPChecker) Run added in v0.0.1

func (p *TCPChecker) Run(ctx context.Context) error

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL