Skip to content

Commit

Permalink
add apiv2 healthcheck code
Browse files Browse the repository at this point in the history
reworking binding and endpoint to actually work.  added documentation in swagger for and various return code possibilities.  add a good start on tests though we need some other container functions not yet implemented for that.

Signed-off-by: Brent Baude <bbaude@redhat.com>
  • Loading branch information
baude committed Mar 13, 2020
1 parent c9f148f commit 2099643
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 5 deletions.
24 changes: 23 additions & 1 deletion pkg/api/handlers/libpod/healthcheck.go
Expand Up @@ -14,8 +14,30 @@ func RunHealthCheck(w http.ResponseWriter, r *http.Request) {
if err != nil {
if status == libpod.HealthCheckContainerNotFound {
utils.ContainerNotFound(w, name, err)
return
}
if status == libpod.HealthCheckNotDefined {
utils.Error(w, "no healthcheck defined", http.StatusConflict, err)
return
}
if status == libpod.HealthCheckContainerStopped {
utils.Error(w, "container not running", http.StatusConflict, err)
return
}
utils.InternalServerError(w, err)
return
}
ctr, err := runtime.LookupContainer(name)
if err != nil {
utils.InternalServerError(w, err)
return
}
utils.WriteResponse(w, http.StatusOK, status)

hcLog, err := ctr.GetHealthCheckLog()
if err != nil {
utils.InternalServerError(w, err)
return
}

utils.WriteResponse(w, http.StatusOK, hcLog)
}
25 changes: 24 additions & 1 deletion pkg/api/server/register_healthcheck.go
Expand Up @@ -8,6 +8,29 @@ import (
)

func (s *APIServer) registerHealthCheckHandlers(r *mux.Router) error {
r.Handle(VersionedPath("/libpod/containers/{name}/runhealthcheck"), s.APIHandler(libpod.RunHealthCheck)).Methods(http.MethodGet)
// swagger:operation GET /libpod/containers/{name:.*}/healthcheck libpod libpodRunHealthCheck
// ---
// tags:
// - containers
// summary: Run a container's healthcheck
// description: Execute the defined healthcheck and return information about the results
// parameters:
// - in: path
// name: name:.*
// type: string
// required: true
// description: the name or ID of the container
// produces:
// - application/json
// responses:
// 200:
// $ref: "#/responses/HealthcheckRun"
// 404:
// $ref: "#/responses/NoSuchContainer"
// 409:
// description: container has no healthcheck or is not running
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/containers/{name:.*}/healthcheck"), s.APIHandler(libpod.RunHealthCheck)).Methods(http.MethodGet)
return nil
}
9 changes: 9 additions & 0 deletions pkg/api/server/swagger.go
Expand Up @@ -156,3 +156,12 @@ type swagVolumeListResponse struct {
// in:body
Body []libpod.Volume
}

// Healthcheck
// swagger:response HealthcheckRun
type swagHealthCheckRunResponse struct {
// in:body
Body struct {
libpod.HealthCheckResults
}
}
6 changes: 3 additions & 3 deletions pkg/bindings/containers/healthcheck.go
Expand Up @@ -10,15 +10,15 @@ import (

// RunHealthCheck executes the container's healthcheck and returns the health status of the
// container.
func RunHealthCheck(ctx context.Context, nameOrID string) (*libpod.HealthCheckStatus, error) {
func RunHealthCheck(ctx context.Context, nameOrID string) (*libpod.HealthCheckResults, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
var (
status libpod.HealthCheckStatus
status libpod.HealthCheckResults
)
response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/runhealthcheck", nil, nameOrID)
response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/healthcheck", nil, nameOrID)
if err != nil {
return nil, err
}
Expand Down
45 changes: 45 additions & 0 deletions pkg/bindings/test/containers_test.go
Expand Up @@ -312,4 +312,49 @@ var _ = Describe("Podman containers ", func() {
Expect(exitCode).To(BeNumerically("==", -1))
})

It("run healthcheck", func() {
bt.runPodman([]string{"run", "-d", "--name", "hc", "--health-interval", "disable", "--health-retries", "2", "--health-cmd", "ls / || exit 1", alpine.name, "top"})

// bogus name should result in 404
_, err := containers.RunHealthCheck(bt.conn, "foobar")
Expect(err).ToNot(BeNil())
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))

// a container that has no healthcheck should be a 409
var name = "top"
bt.RunTopContainer(&name, &falseFlag, nil)
_, err = containers.RunHealthCheck(bt.conn, name)
Expect(err).ToNot(BeNil())
code, _ = bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusConflict))

// TODO for the life of me, i cannot get this to work. maybe another set
// of eyes will
// successful healthcheck
//status := "healthy"
//for i:=0; i < 10; i++ {
// result, err := containers.RunHealthCheck(connText, "hc")
// Expect(err).To(BeNil())
// if result.Status != "healthy" {
// fmt.Println("Healthcheck container still starting, retrying in 1 second")
// time.Sleep(1 * time.Second)
// continue
// }
// status = result.Status
// break
//}
//Expect(status).To(Equal("healthy"))

// TODO enable this when wait is working
// healthcheck on a stopped container should be a 409
//err = containers.Stop(connText, "hc", nil)
//Expect(err).To(BeNil())
//_, err = containers.Wait(connText, "hc")
//Expect(err).To(BeNil())
//_, err = containers.RunHealthCheck(connText, "hc")
//code, _ = bindings.CheckResponseCode(err)
//Expect(code).To(BeNumerically("==", http.StatusConflict))
})

})

0 comments on commit 2099643

Please sign in to comment.