Skip to content

Commit d8bec0f

Browse files
authored
Merge pull request #75 from lukaszbudnik/dev-v4.0.1
migrator will introduce itself a little bit better on GET /
2 parents 300ee8b + 265220f commit d8bec0f

File tree

6 files changed

+96
-15
lines changed

6 files changed

+96
-15
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Further, there is an official docker image available on docker hub. [lukasz/migr
1111
# Table of contents
1212

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

4142
migrator exposes a simple REST API described below.
4243

44+
# GET /
45+
46+
Migrator returns build information together with supported API versions.
47+
48+
Sample request:
49+
50+
```
51+
curl -v http://localhost:8080/
52+
```
53+
54+
Sample HTTP response:
55+
56+
```
57+
< HTTP/1.1 200 OK
58+
< Content-Type: application/json; charset=utf-8
59+
< Date: Wed, 08 Jan 2020 09:13:58 GMT
60+
< Content-Length: 142
61+
62+
{
63+
"release": "dev-v4.0.1",
64+
"commitSha": "300ee8b98f4d6a4725d38b3676accd5a361d7a04",
65+
"commitDate": "2020-01-07T14:52:00+01:00",
66+
"apiVersions": [
67+
"v1"
68+
]
69+
}
70+
```
71+
4372
## GET /v1/config
4473

4574
Returns migrator's config as `application/x-yaml`.

hooks/build

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,16 @@ echo "DOCKER_REPO: $DOCKER_REPO"
99
echo "CACHE_TAG: $CACHE_TAG"
1010
echo "IMAGE_NAME: $IMAGE_NAME"
1111

12+
# if running from master check if the source commit is not referenced in known tags
13+
# if that's the case use the last tag rather than 'master'
14+
# this is because SOURCE_BRANCH is later injected into migrator.go and used as a version identifier
15+
# a little bit more user friendly than master and commit sha/date
16+
if [ "$SOURCE_BRANCH" = "master" ]; then
17+
TAGS=$(git tag --contains $SOURCE_COMMIT 2> /dev/null)
18+
if [ $? -eq 0 ]; then
19+
SOURCE_BRANCH=$(echo "$TAGS" | tail -1)
20+
echo "Changed master to $SOURCE_BRANCH"
21+
fi
22+
fi
23+
1224
docker build --build-arg SOURCE_BRANCH=$SOURCE_BRANCH -f $DOCKERFILE_PATH -t $IMAGE_NAME .

migrator.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/lukaszbudnik/migrator/loader"
1515
"github.com/lukaszbudnik/migrator/notifications"
1616
"github.com/lukaszbudnik/migrator/server"
17+
"github.com/lukaszbudnik/migrator/types"
1718
)
1819

1920
const (
@@ -58,7 +59,8 @@ func main() {
5859
}
5960

6061
gin.SetMode(gin.ReleaseMode)
61-
g := server.SetupRouter(cfg, createCoordinator)
62+
versionInfo := &types.VersionInfo{Release: GitBranch, CommitSha: GitCommitSha, CommitDate: GitCommitDate, APIVersions: []string{"v1"}}
63+
g := server.SetupRouter(versionInfo, cfg, createCoordinator)
6264
if err := g.Run(":" + server.GetPort(cfg)); err != nil {
6365
common.Log("ERROR", "Error starting migrator: %v", err)
6466
}

server/server.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func tenantsPostHandler(c *gin.Context, config *config.Config, newCoordinator fu
204204
}
205205

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

217+
r.GET("/", func(c *gin.Context) {
218+
c.JSON(http.StatusOK, versionInfo)
219+
})
220+
217221
v1 := r.Group("/v1")
218222

219223
v1.GET("/config", makeHandler(config, newCoordinator, configHandler))

server/server_test.go

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ package server
22

33
import (
44
"bytes"
5+
"context"
56
"io"
67
"net/http"
78
"net/http/httptest"
89
"strings"
910
"testing"
1011

12+
"github.com/gin-gonic/gin"
1113
"github.com/lukaszbudnik/migrator/config"
14+
"github.com/lukaszbudnik/migrator/coordinator"
15+
"github.com/lukaszbudnik/migrator/types"
1216
"github.com/stretchr/testify/assert"
1317
)
1418

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

29+
func testSetupRouter(config *config.Config, newCoordinator func(ctx context.Context, config *config.Config) coordinator.Coordinator) *gin.Engine {
30+
versionInfo := &types.VersionInfo{Release: "GitBranch", CommitSha: "GitCommitSha", CommitDate: "2020-01-08T09:56:41+01:00", APIVersions: []string{"v1"}}
31+
return SetupRouter(versionInfo, config, newCoordinator)
32+
}
33+
2534
func TestGetDefaultPort(t *testing.T) {
2635
config, err := config.FromFile(configFile)
2736
assert.Nil(t, err)
@@ -34,13 +43,30 @@ func TestGetDefaultPortOverrides(t *testing.T) {
3443
assert.Equal(t, "8811", GetPort(config))
3544
}
3645

46+
// section /
47+
48+
func TestRoot(t *testing.T) {
49+
config, err := config.FromFile(configFile)
50+
assert.Nil(t, err)
51+
52+
router := testSetupRouter(config, nil)
53+
54+
w := httptest.NewRecorder()
55+
req, _ := http.NewRequest("GET", "/", nil)
56+
router.ServeHTTP(w, req)
57+
58+
assert.Equal(t, http.StatusOK, w.Code)
59+
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap["Content-Type"][0])
60+
assert.Equal(t, `{"release":"GitBranch","commitSha":"GitCommitSha","commitDate":"2020-01-08T09:56:41+01:00","apiVersions":["v1"]}`, strings.TrimSpace(w.Body.String()))
61+
}
62+
3763
// section /config
3864

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

43-
router := SetupRouter(config, nil)
69+
router := testSetupRouter(config, nil)
4470

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

60-
router := SetupRouter(config, newMockedCoordinator)
86+
router := testSetupRouter(config, newMockedCoordinator)
6187

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

77-
router := SetupRouter(config, newMockedCoordinator)
103+
router := testSetupRouter(config, newMockedCoordinator)
78104

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

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

95-
router := SetupRouter(config, newMockedCoordinator)
121+
router := testSetupRouter(config, newMockedCoordinator)
96122

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

112-
router := SetupRouter(config, newMockedCoordinator)
138+
router := testSetupRouter(config, newMockedCoordinator)
113139

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

130-
router := SetupRouter(config, newMockedCoordinator)
156+
router := testSetupRouter(config, newMockedCoordinator)
131157

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

148-
router := SetupRouter(config, newMockedErrorCoordinator(0))
174+
router := testSetupRouter(config, newMockedErrorCoordinator(0))
149175

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

167-
router := SetupRouter(config, newMockedCoordinator)
193+
router := testSetupRouter(config, newMockedCoordinator)
168194

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

182-
router := SetupRouter(config, newMockedCoordinator)
208+
router := testSetupRouter(config, newMockedCoordinator)
183209

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

199-
router := SetupRouter(config, newMockedCoordinator)
225+
router := testSetupRouter(config, newMockedCoordinator)
200226

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

217-
router := SetupRouter(config, newMockedCoordinator)
243+
router := testSetupRouter(config, newMockedCoordinator)
218244

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

234-
router := SetupRouter(config, newMockedErrorCoordinator(0))
260+
router := testSetupRouter(config, newMockedErrorCoordinator(0))
235261

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

251-
router := SetupRouter(config, newMockedErrorCoordinator(0))
277+
router := testSetupRouter(config, newMockedErrorCoordinator(0))
252278

253279
w := httptest.NewRecorder()
254280
req, _ := newTestRequest("GET", "/migrations/source", nil)

types/types.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,11 @@ type MigrationResults struct {
9191
TenantScriptsTotal int `json:"tenantScriptsTotal"` // tenant scripts for all tenants
9292
ScriptsGrandTotal int `json:"scriptsGrandTotal"` // total number of all scripts applied
9393
}
94+
95+
// VersionInfo contains build information and supported API versions
96+
type VersionInfo struct {
97+
Release string `json:"release"`
98+
CommitSha string `json:"commitSha"`
99+
CommitDate string `json:"commitDate"`
100+
APIVersions []string `json:"apiVersions"`
101+
}

0 commit comments

Comments
 (0)