Skip to content

Commit

Permalink
Merge pull request #75 from lukaszbudnik/dev-v4.0.1
Browse files Browse the repository at this point in the history
migrator will introduce itself a little bit better on GET /
  • Loading branch information
lukaszbudnik authored Jan 8, 2020
2 parents 300ee8b + 265220f commit d8bec0f
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 15 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Further, there is an official docker image available on docker hub. [lukasz/migr
# Table of contents

* [Usage](#usage)
* [GET /](#get-)
* [GET /v1/config](#get-v1config)
* [GET /v1/migrations/source](#get-v1migrationssource)
* [GET /v1/migrations/applied](#get-v1migrationsapplied)
Expand Down Expand Up @@ -40,6 +41,34 @@ Further, there is an official docker image available on docker hub. [lukasz/migr

migrator exposes a simple REST API described below.

# GET /

Migrator returns build information together with supported API versions.

Sample request:

```
curl -v http://localhost:8080/
```

Sample HTTP response:

```
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Wed, 08 Jan 2020 09:13:58 GMT
< Content-Length: 142
{
"release": "dev-v4.0.1",
"commitSha": "300ee8b98f4d6a4725d38b3676accd5a361d7a04",
"commitDate": "2020-01-07T14:52:00+01:00",
"apiVersions": [
"v1"
]
}
```

## GET /v1/config

Returns migrator's config as `application/x-yaml`.
Expand Down
12 changes: 12 additions & 0 deletions hooks/build
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,16 @@ echo "DOCKER_REPO: $DOCKER_REPO"
echo "CACHE_TAG: $CACHE_TAG"
echo "IMAGE_NAME: $IMAGE_NAME"

# if running from master check if the source commit is not referenced in known tags
# if that's the case use the last tag rather than 'master'
# this is because SOURCE_BRANCH is later injected into migrator.go and used as a version identifier
# a little bit more user friendly than master and commit sha/date
if [ "$SOURCE_BRANCH" = "master" ]; then
TAGS=$(git tag --contains $SOURCE_COMMIT 2> /dev/null)
if [ $? -eq 0 ]; then
SOURCE_BRANCH=$(echo "$TAGS" | tail -1)
echo "Changed master to $SOURCE_BRANCH"
fi
fi

docker build --build-arg SOURCE_BRANCH=$SOURCE_BRANCH -f $DOCKERFILE_PATH -t $IMAGE_NAME .
4 changes: 3 additions & 1 deletion migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/lukaszbudnik/migrator/loader"
"github.com/lukaszbudnik/migrator/notifications"
"github.com/lukaszbudnik/migrator/server"
"github.com/lukaszbudnik/migrator/types"
)

const (
Expand Down Expand Up @@ -58,7 +59,8 @@ func main() {
}

gin.SetMode(gin.ReleaseMode)
g := server.SetupRouter(cfg, createCoordinator)
versionInfo := &types.VersionInfo{Release: GitBranch, CommitSha: GitCommitSha, CommitDate: GitCommitDate, APIVersions: []string{"v1"}}
g := server.SetupRouter(versionInfo, cfg, createCoordinator)
if err := g.Run(":" + server.GetPort(cfg)); err != nil {
common.Log("ERROR", "Error starting migrator: %v", err)
}
Expand Down
6 changes: 5 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func tenantsPostHandler(c *gin.Context, config *config.Config, newCoordinator fu
}

// SetupRouter setups router
func SetupRouter(config *config.Config, newCoordinator func(ctx context.Context, config *config.Config) coordinator.Coordinator) *gin.Engine {
func SetupRouter(versionInfo *types.VersionInfo, config *config.Config, newCoordinator func(ctx context.Context, config *config.Config) coordinator.Coordinator) *gin.Engine {
r := gin.New()
r.HandleMethodNotAllowed = true
r.Use(recovery(), requestIDHandler(), requestLoggerHandler())
Expand All @@ -214,6 +214,10 @@ func SetupRouter(config *config.Config, newCoordinator func(ctx context.Context,
v.RegisterValidation("mode", types.ValidateMigrationsModeType)
}

r.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, versionInfo)
})

v1 := r.Group("/v1")

v1.GET("/config", makeHandler(config, newCoordinator, configHandler))
Expand Down
52 changes: 39 additions & 13 deletions server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package server

import (
"bytes"
"context"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/gin-gonic/gin"
"github.com/lukaszbudnik/migrator/config"
"github.com/lukaszbudnik/migrator/coordinator"
"github.com/lukaszbudnik/migrator/types"
"github.com/stretchr/testify/assert"
)

Expand All @@ -22,6 +26,11 @@ func newTestRequest(method, url string, body io.Reader) (*http.Request, error) {
return http.NewRequest(method, versionURL, body)
}

func testSetupRouter(config *config.Config, newCoordinator func(ctx context.Context, config *config.Config) coordinator.Coordinator) *gin.Engine {
versionInfo := &types.VersionInfo{Release: "GitBranch", CommitSha: "GitCommitSha", CommitDate: "2020-01-08T09:56:41+01:00", APIVersions: []string{"v1"}}
return SetupRouter(versionInfo, config, newCoordinator)
}

func TestGetDefaultPort(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)
Expand All @@ -34,13 +43,30 @@ func TestGetDefaultPortOverrides(t *testing.T) {
assert.Equal(t, "8811", GetPort(config))
}

// section /

func TestRoot(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := testSetupRouter(config, nil)

w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/", nil)
router.ServeHTTP(w, req)

assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap["Content-Type"][0])
assert.Equal(t, `{"release":"GitBranch","commitSha":"GitCommitSha","commitDate":"2020-01-08T09:56:41+01:00","apiVersions":["v1"]}`, strings.TrimSpace(w.Body.String()))
}

// section /config

func TestConfigRoute(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, nil)
router := testSetupRouter(config, nil)

w := httptest.NewRecorder()
req, _ := newTestRequest("GET", "/config", nil)
Expand All @@ -57,7 +83,7 @@ func TestDiskMigrationsRoute(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

w := httptest.NewRecorder()
req, _ := newTestRequest("GET", "/migrations/source", nil)
Expand All @@ -74,7 +100,7 @@ func TestAppliedMigrationsRoute(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

req, _ := newTestRequest(http.MethodGet, "/migrations/applied", nil)

Expand All @@ -92,7 +118,7 @@ func TestMigrationsPostRoute(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

json := []byte(`{"mode": "apply", "response": "full"}`)
req, _ := newTestRequest(http.MethodPost, "/migrations", bytes.NewBuffer(json))
Expand All @@ -109,7 +135,7 @@ func TestMigrationsPostRouteSummaryResponse(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

json := []byte(`{"mode": "apply", "response": "summary"}`)
req, _ := newTestRequest(http.MethodPost, "/migrations", bytes.NewBuffer(json))
Expand All @@ -127,7 +153,7 @@ func TestMigrationsPostRouteBadRequest(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

// response is invalid
json := []byte(`{"mode": "apply", "response": "abc"}`)
Expand All @@ -145,7 +171,7 @@ func TestMigrationsPostRouteCheckSumError(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedErrorCoordinator(0))
router := testSetupRouter(config, newMockedErrorCoordinator(0))

json := []byte(`{"mode": "apply", "response": "full"}`)
req, _ := newTestRequest(http.MethodPost, "/migrations", bytes.NewBuffer(json))
Expand All @@ -164,7 +190,7 @@ func TestTenantsGetRoute(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

w := httptest.NewRecorder()
req, _ := newTestRequest("GET", "/tenants", nil)
Expand All @@ -179,7 +205,7 @@ func TestTenantsPostRoute(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

json := []byte(`{"name": "new_tenant", "response": "full", "mode":"dry-run"}`)
req, _ := newTestRequest(http.MethodPost, "/tenants", bytes.NewBuffer(json))
Expand All @@ -196,7 +222,7 @@ func TestTenantsPostRouteSummaryResponse(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

json := []byte(`{"name": "new_tenant", "response": "summary", "mode":"dry-run"}`)
req, _ := newTestRequest(http.MethodPost, "/tenants", bytes.NewBuffer(json))
Expand All @@ -214,7 +240,7 @@ func TestTenantsPostRouteBadRequestError(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedCoordinator)
router := testSetupRouter(config, newMockedCoordinator)

json := []byte(`{"a": "new_tenant"}`)
req, _ := newTestRequest(http.MethodPost, "/tenants", bytes.NewBuffer(json))
Expand All @@ -231,7 +257,7 @@ func TestTenantsPostRouteCheckSumError(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedErrorCoordinator(0))
router := testSetupRouter(config, newMockedErrorCoordinator(0))

json := []byte(`{"name": "new_tenant", "response": "full", "mode":"dry-run"}`)
req, _ := newTestRequest(http.MethodPost, "/tenants", bytes.NewBuffer(json))
Expand All @@ -248,7 +274,7 @@ func TestRouteError(t *testing.T) {
config, err := config.FromFile(configFile)
assert.Nil(t, err)

router := SetupRouter(config, newMockedErrorCoordinator(0))
router := testSetupRouter(config, newMockedErrorCoordinator(0))

w := httptest.NewRecorder()
req, _ := newTestRequest("GET", "/migrations/source", nil)
Expand Down
8 changes: 8 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,11 @@ type MigrationResults struct {
TenantScriptsTotal int `json:"tenantScriptsTotal"` // tenant scripts for all tenants
ScriptsGrandTotal int `json:"scriptsGrandTotal"` // total number of all scripts applied
}

// VersionInfo contains build information and supported API versions
type VersionInfo struct {
Release string `json:"release"`
CommitSha string `json:"commitSha"`
CommitDate string `json:"commitDate"`
APIVersions []string `json:"apiVersions"`
}

0 comments on commit d8bec0f

Please sign in to comment.