Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Commit

Permalink
Merge pull request #112 from duck8823/feature/health_check
Browse files Browse the repository at this point in the history
Add healthcheck
  • Loading branch information
duck8823 committed Oct 13, 2018
2 parents 4248722 + e677302 commit 92aab02
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 7 deletions.
26 changes: 26 additions & 0 deletions application/service/docker/docker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package docker

import (
"context"
"github.com/duck8823/duci/infrastructure/docker"
"github.com/pkg/errors"
)

type Service interface {
Status() error
}

type serviceImpl struct {
moby docker.Client
}

func New(moby docker.Client) Service {
return &serviceImpl{moby}
}

func (s *serviceImpl) Status() error {
if _, err := s.moby.Info(context.Background()); err != nil {
return errors.Wrap(err, "Couldn't connect to Docker daemon.")
}
return nil
}
45 changes: 45 additions & 0 deletions application/service/docker/mock_docker/docker.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions infrastructure/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type Client interface {
Rm(ctx context.Context, containerID string) error
Rmi(ctx context.Context, tag string) error
ExitCode(ctx context.Context, containerID string) (int64, error)
Info(ctx context.Context) (types.Info, error)
}

type clientImpl struct {
Expand Down Expand Up @@ -136,3 +137,12 @@ func (c *clientImpl) ExitCode(ctx context.Context, containerID string) (int64, e
return -1, errors.WithStack(e)
}
}

// Status returns error when failure get docker status.
func (c *clientImpl) Info(ctx context.Context) (types.Info, error) {
info, err := c.moby.Info(ctx)
if err != nil {
return types.Info{}, errors.WithStack(err)
}
return info, nil
}
53 changes: 53 additions & 0 deletions infrastructure/docker/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/duck8823/duci/infrastructure/docker"
"github.com/duck8823/duci/infrastructure/docker/mock_docker"
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
"github.com/google/uuid"
"github.com/labstack/gommon/random"
"github.com/pkg/errors"
Expand Down Expand Up @@ -464,6 +465,58 @@ func TestClientImpl_ExitCode(t *testing.T) {
})
}

func TestClientImpl_Info(t *testing.T) {
// setup
sut, err := docker.New()
if err != nil {
t.Fatalf("error occurred: %+v", err)
}

t.Run("without error", func(t *testing.T) {
// given
expected := types.Info{ID: uuid.New().String()}

// and
ctrl := gomock.NewController(t)
mockMoby := mock_docker.NewMockMoby(ctrl)

mockMoby.EXPECT().
Info(gomock.Any()).
Return(expected, nil)

sut.SetMoby(mockMoby)

// when
actual, err := sut.Info(context.New("test", uuid.New(), nil))

// then
if !cmp.Equal(actual, expected) {
t.Errorf("must be equal. %+v", cmp.Diff(actual, expected))
}

if err != nil {
t.Errorf("error must not occur, but got %+v", err)
}
})

t.Run("with error", func(t *testing.T) {
// given
ctrl := gomock.NewController(t)
mockMoby := mock_docker.NewMockMoby(ctrl)

mockMoby.EXPECT().
Info(gomock.Any()).
Return(types.Info{}, errors.New("test"))

sut.SetMoby(mockMoby)

// expect
if _, err := sut.Info(context.New("test", uuid.New(), nil)); err == nil {
t.Error("error must occur, but got nil")
}
})
}

func TestEnvironments_ToArray(t *testing.T) {
var empty []string
for _, testcase := range []struct {
Expand Down
14 changes: 14 additions & 0 deletions infrastructure/docker/mock_docker/docker.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions infrastructure/docker/mock_docker/third_party.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions infrastructure/docker/third_pirty.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ type Moby interface {
containerID string,
condition container.WaitCondition,
) (<-chan container.ContainerWaitOKBody, <-chan error)
Info(
ctx context.Context,
) (types.Info, error)
}
20 changes: 20 additions & 0 deletions presentation/controller/health.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package controller

import (
"github.com/duck8823/duci/application/service/docker"
"net/http"
)

// HealthController is a handler of health check.
type HealthController struct {
Docker docker.Service
}

// ServeHTTP responses a server status
func (c *HealthController) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := c.Docker.Status(); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
71 changes: 71 additions & 0 deletions presentation/controller/health_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package controller_test

import (
"github.com/duck8823/duci/application/service/docker/mock_docker"
"github.com/duck8823/duci/presentation/controller"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"net/http/httptest"
"testing"
)

func TestHealthCheckController_ServeHTTP(t *testing.T) {
t.Run("without error", func(t *testing.T) {
// given
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockService := mock_docker.NewMockService(ctrl)
mockService.EXPECT().
Status().
Return(nil)

handler := &controller.HealthController{Docker: mockService}

// and
s := httptest.NewServer(handler)
defer s.Close()

// and
req := httptest.NewRequest("GET", "/health", nil)
rec := httptest.NewRecorder()

// when
handler.ServeHTTP(rec, req)

// then
if rec.Code != 200 {
t.Errorf("status code must be 200, but got %+v", rec.Code)
}
})

t.Run("with error", func(t *testing.T) {
// given
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockService := mock_docker.NewMockService(ctrl)
mockService.EXPECT().
Status().
Return(errors.New("test"))

handler := &controller.HealthController{Docker: mockService}

// and
s := httptest.NewServer(handler)
defer s.Close()

// and
req := httptest.NewRequest("GET", "/health", nil)
rec := httptest.NewRecorder()

// when
handler.ServeHTTP(rec, req)

// then
if rec.Code != 500 {
t.Errorf("status code must be 500, but got %+v", rec.Code)
}
})

}
18 changes: 11 additions & 7 deletions presentation/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package router

import (
"github.com/duck8823/duci/application"
"github.com/duck8823/duci/application/service/docker"
"github.com/duck8823/duci/application/service/git"
"github.com/duck8823/duci/application/service/github"
"github.com/duck8823/duci/application/service/logstore"
"github.com/duck8823/duci/application/service/runner"
"github.com/duck8823/duci/infrastructure/docker"
moby "github.com/duck8823/duci/infrastructure/docker"
"github.com/duck8823/duci/presentation/controller"
"github.com/go-chi/chi"
"github.com/pkg/errors"
Expand All @@ -15,22 +16,29 @@ import (

// New returns handler of application.
func New() (http.Handler, error) {
dockerClient, err := moby.New()
if err != nil {
return nil, errors.WithStack(err)
}

logstoreService, githubService, err := createCommonServices()
if err != nil {
return nil, errors.WithStack(err)
}

dockerRunner, err := createRunner(logstoreService, githubService)
dockerRunner, err := createRunner(logstoreService, githubService, dockerClient)
if err != nil {
return nil, errors.WithStack(err)
}

webhooksCtrl := &controller.WebhooksController{Runner: dockerRunner, GitHub: githubService}
logCtrl := &controller.LogController{LogStore: logstoreService}
healthCtrl := &controller.HealthController{Docker: docker.New(dockerClient)}

rtr := chi.NewRouter()
rtr.Post("/", webhooksCtrl.ServeHTTP)
rtr.Get("/logs/{uuid}", logCtrl.ServeHTTP)
rtr.Get("/health", healthCtrl.ServeHTTP)

return rtr, nil
}
Expand All @@ -48,15 +56,11 @@ func createCommonServices() (logstore.Service, github.Service, error) {
return logstoreService, githubService, nil
}

func createRunner(logstoreService logstore.Service, githubService github.Service) (runner.Runner, error) {
func createRunner(logstoreService logstore.Service, githubService github.Service, dockerClient moby.Client) (runner.Runner, error) {
gitClient, err := git.New()
if err != nil {
return nil, errors.WithStack(err)
}
dockerClient, err := docker.New()
if err != nil {
return nil, errors.WithStack(err)
}

dockerRunner := &runner.DockerRunner{
BaseWorkDir: application.Config.Server.WorkDir,
Expand Down

0 comments on commit 92aab02

Please sign in to comment.