Skip to content

Commit

Permalink
introspection: enable readiness endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Hank Donnay <hdonnay@redhat.com>
  • Loading branch information
hdonnay committed May 12, 2021
1 parent 6638793 commit ec59a43
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 22 deletions.
2 changes: 2 additions & 0 deletions cmd/clair/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
yaml "gopkg.in/yaml.v3"

"github.com/quay/clair/v4/config"
"github.com/quay/clair/v4/health"
"github.com/quay/clair/v4/httptransport"
"github.com/quay/clair/v4/initialize"
"github.com/quay/clair/v4/introspection"
Expand Down Expand Up @@ -108,6 +109,7 @@ func main() {
return fmt.Errorf("http transport configuration failed: %w", err)
}
down.Add(h.Server)
health.Ready()
if err := h.ListenAndServe(); err != http.ErrServerClosed {
return fmt.Errorf("http transport failed to launch: %w", err)
}
Expand Down
38 changes: 17 additions & 21 deletions health/readinesshandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,39 @@ package health
import (
"net/http"
"sync/atomic"

je "github.com/quay/claircore/pkg/jsonerr"
)

var ready *uint32 = new(uint32)

// Ready instructs the ReadinessHandler to begin serving 200OK status
// Ready instructs the ReadinessHandler to begin serving 200 OK status.
func Ready() {
atomic.StoreUint32(ready, uint32(1))
}

// NotReady instructs the ReadinessHandler to begin serving 503ServiceUnavailable status
func UnReady() {
// Unready instructs the ReadinessHandler to begin serving 503
// Service Unavailable.
func Unready() {
atomic.StoreUint32(ready, uint32(0))
}

// ReadinessHandler will return a 200OK or 503ServiceUnavailable status dependent
// on whether the exported Ready or NotReady methods have been called.
// ReadinessHandler will return a 200 OK or 503 "Service Unavailable" status
// depending on whether the Ready or Unready functions have been called.
//
// The Ready() method must be called to begin returning 200OK
func ReadinessHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// The Ready() method must be called to begin returning 200 OK.
func ReadinessHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h := w.Header()
h.Set("X-Content-Type-Options", "nosniff")
h.Set("Content-Type", "text/plain; charset=utf-8")
h.Set("Content-Length", "0")
h.Set("Cache-Control", "no-store")
if r.Method != http.MethodGet {
resp := &je.Response{
Code: "method-not-allowed",
Message: "endpoint only allows GET",
}
je.Error(w, resp, http.StatusMethodNotAllowed)
w.WriteHeader(http.StatusMethodNotAllowed)
return
}

ready := atomic.LoadUint32(ready)
if ready == 1 {
w.WriteHeader(http.StatusOK)
} else {
if atomic.LoadUint32(ready) != 1 {
w.WriteHeader(http.StatusServiceUnavailable)
}
return
}
})
}
2 changes: 1 addition & 1 deletion health/readinesshandler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestReadinessHandler(t *testing.T) {
}

// signal to handler that process is unready. should return StatusServiceUnavailable
health.UnReady()
health.Unready()
resp, err = client.Do(req)
if err != nil {
t.Fatalf("failed to do request: %v", err)
Expand Down
10 changes: 10 additions & 0 deletions introspection/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
sdktrace "go.opentelemetry.io/otel/sdk/trace"

"github.com/quay/clair/v4/config"
"github.com/quay/clair/v4/health"
)

const (
Expand All @@ -27,6 +28,7 @@ const (
Jaeger = "jaeger"
DefaultJaegerEndpoint = "localhost:6831"
HealthEndpoint = "/healthz"
ReadyEndpoint = "/readyz"
DefaultIntrospectionAddr = ":8089"
)

Expand Down Expand Up @@ -122,6 +124,9 @@ func New(ctx context.Context, conf config.Config, health func() bool) (*Server,
if err != nil {
return nil, fmt.Errorf("error configuring diagnostics: %v", err)
}
if err := i.withReady(ctx); err != nil {
return nil, fmt.Errorf("error configuring ready: %v", err)
}

// attach Introspection to server, this works because we embed http.ServeMux
i.Server.Handler = i
Expand Down Expand Up @@ -149,6 +154,11 @@ func (i *Server) withDiagnostics(_ context.Context) error {
return nil
}

func (i *Server) withReady(_ context.Context) error {
i.ServeMux.Handle(ReadyEndpoint, health.ReadinessHandler())
return nil
}

// withStdOut configures the stdout exporter for distributed tracing
func (i *Server) withStdOut(_ context.Context, traceOpts []sdktrace.TracerProviderOption) error {
exporter, err := stdout.NewExporter()
Expand Down

0 comments on commit ec59a43

Please sign in to comment.