Skip to content

Commit c0804c1

Browse files
authored
Merge pull request #63 from lukaszbudnik/v3.1
migrator v3.1
2 parents 51df773 + e5b4568 commit c0804c1

30 files changed

+293
-224
lines changed

.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
language: go
22

33
addons:
4-
postgresql: "9.3"
4+
postgresql: '9.6'
55

66
env:
77
- DB=postgresql
@@ -12,10 +12,10 @@ services:
1212
- mysql
1313

1414
go:
15-
- "1.8"
16-
- "1.9"
1715
- "1.10"
1816
- "1.11"
17+
- "1.12"
18+
- "1.13"
1919

2020
before_script:
2121
- sh -c "if [ '$DB' = 'postgresql' ]; then psql -U postgres -c 'create database migrator_test'; fi"

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ RUN go get -d -v github.com/lukaszbudnik/migrator
1010
RUN cd /go/src/github.com/lukaszbudnik/migrator && git checkout $SOURCE_BRANCH && ./setup.sh
1111
RUN cd /go/src/github.com/lukaszbudnik/migrator && \
1212
GIT_BRANCH=$(git branch | awk -v FS=' ' '/\*/{print $NF}' | sed 's|[()]||g') && \
13+
GIT_COMMIT_DATE=$(git log -n1 --date=iso-strict | grep 'Date:' | sed 's|Date:\s*||g') && \
1314
GIT_COMMIT_SHA=$(git rev-list -1 HEAD) && \
14-
go build -ldflags "-X main.GitCommitSha=$GIT_COMMIT_SHA -X main.GitBranch=$GIT_BRANCH"
15+
go build -ldflags "-X main.GitCommitDate=$GIT_COMMIT_DATE -X main.GitCommitSha=$GIT_COMMIT_SHA -X main.GitBranch=$GIT_BRANCH"
1516

1617
FROM alpine:3.8
1718
COPY --from=builder /go/src/github.com/lukaszbudnik/migrator/migrator /bin

README.md

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@ Super fast and lightweight DB migration & evolution tool written in go.
44

55
migrator manages all the DB changes for you and completely eliminates manual and error-prone administrative tasks. migrator not only supports single schemas, but also comes with a multi-tenant support.
66

7-
migrator can run as a HTTP REST service. Further, there is a ready-to-go migrator docker image.
7+
migrator run as a HTTP REST service.
8+
9+
Further, there is an official docker image available on docker hub. migrator docker image is ultra lightweight and has a size of 15MB. Ideal for micro-services deployments!
10+
11+
To find out more about migrator docker container see [DOCKER.md](DOCKER.md) for more details.
812

913
# Usage
1014

1115
migrator exposes a simple REST API which you can use to invoke different actions:
1216

13-
* GET /config - returns migrator config, response is `Content-Type: application/x-yaml`
14-
* GET /diskMigrations - returns disk migrations, response is `Content-Type: application/json`
15-
* GET /tenants - returns tenants, response is `Content-Type: application/json`
16-
* POST /tenants - adds new tenant, name parameter is passed as JSON, returns applied migrations, response is `Content-Type: application/json`
17-
* GET /migrations - returns all applied migrations
18-
* POST /migrations - applies migrations, no parameters required, returns applied migrations, response is `Content-Type: application/json`
17+
* GET /config - returns migrator config (`application/x-yaml`)
18+
* GET /diskMigrations - returns disk migrations (`application/json`)
19+
* GET /tenants - returns tenants (`application/json`)
20+
* POST /tenants - adds new tenant, name parameter is passed as JSON parameter, returns applied migrations (`application/json`)
21+
* GET /migrations - returns all applied migrations (`application/json`)
22+
* POST /migrations - applies migrations, no parameters required, returns applied migrations (`application/json`)
1923

2024
Some curl examples to get you started:
2125

@@ -30,9 +34,9 @@ curl -v -X POST -H "Content-Type: application/json" -d '{"name": "new_tenant"}'
3034

3135
Port is configurable in `migrator.yaml` and defaults to 8080. Should you need HTTPS capabilities I encourage you to use nginx/apache/haproxy for TLS offloading.
3236

33-
There is an official docker image available on docker hub. migrator docker image is ultra lightweight and has a size of 15MB. Ideal for micro-services deployments!
37+
# Versions
3438

35-
To find out more about migrator docker container see [DOCKER.md](DOCKER.md) for more details.
39+
Please navigate to https://github.com/lukaszbudnik/migrator/releases for a complete list of versions, features, and changes.
3640

3741
# Configuration
3842

@@ -51,14 +55,20 @@ tenantSelectSQL: "select name from migrator.migrator_tenants"
5155
tenantInsertSQL: "insert into migrator.migrator_tenants (name) values ($1)"
5256
# optional, override only if you have a specific schema placeholder, default is:
5357
schemaPlaceHolder: {schema}
54-
# required, single schemas directories, these are subdirectories of baseDir
55-
singleSchemas:
58+
# required, directories of single schema SQL migrations, these are subdirectories of baseDir
59+
singleMigrations:
5660
- public
5761
- ref
5862
- config
59-
# optional, tenant schemas directories, these are subdirectories of baseDir
60-
tenantSchemas:
63+
# optional, directories of tenant schemas SQL migrations, these are subdirectories of baseDir
64+
tenantMigrations:
6165
- tenants
66+
# optional, directories of single SQL scripts which are applied always, these are subdirectories of baseDir
67+
singleScripts:
68+
- config-scripts
69+
# optional, directories of tenant SQL script which are applied always for all tenants, these are subdirectories of baseDir
70+
tenantScripts:
71+
- tenants-scripts
6272
# optional, default is:
6373
port: 8080
6474
# the webhook configuration section is optional
@@ -123,25 +133,22 @@ Currently migrator supports the following databases and their flavours:
123133

124134
You can apply your first migrations with migrator in literally a couple of minutes. There are some test migrations which are placed in `test/migrations` directory as well as some docker scripts for setting up test databases.
125135

126-
Let's start.
136+
The quick start guide shows you how to either build the migrator locally or use the official docker image.
137+
138+
Steps 1 & 2 are required either way (migrator source code contains sample configuration & setup files together with some test migrations).
139+
Step 3 is for building migrator locally, step 4 is for running the migrator container.
140+
Step 5 is running examples and enjoying migrator ;)
127141

128142
## 1. Get the migrator project
129143

130-
For building migrator from source code `go get` is required:
144+
Get the source code the usual go way:
131145

132146
```
133147
go get -d -v github.com/lukaszbudnik/migrator
134148
cd $GOPATH/src/github.com/lukaszbudnik/migrator
135149
```
136150

137-
migrator supports the following Go versions: 1.8, 1.9, 1.10, and 1.11 (all built on Travis).
138-
139-
For running migrator on docker Go is not required and `git clone` is enough:
140-
141-
```
142-
git clone [email protected]:lukaszbudnik/migrator.git
143-
cd migrator
144-
```
151+
migrator aims to support 3 latest Go versions (built automatically on Travis).
145152

146153
## 2. Setup test DB container
147154

@@ -153,7 +160,7 @@ migrator comes with helper scripts to setup test DB containers. Let's use postgr
153160
154161
Script will start container called `migrator-postgres`.
155162
156-
Further, apart of starting test DB container, the script also generates a ready-to-use test config file. We will use it too.
163+
Further, apart of starting test DB container, the script also generates a ready-to-use test config file. We will use it later.
157164
158165
## 3. Build and run migrator
159166
@@ -167,6 +174,8 @@ go build
167174
168175
> Note: There are 2 git variables injected into the production build (branch/tag and commit sha). When migrator is built like above it prints empty branch/tag and commit sha. This is OK for local development. If you want to inject proper values take a look at `Dockerfile` for details.
169176
177+
## 4. Run migrator from official docker image
178+
170179
When running migrator from docker we need to update `migrator.yaml` (generated in step 2) as well as provide a link to `migrator-postgres` container:
171180
172181
```
@@ -196,7 +205,7 @@ curl -v -X POST -H "X-Request-Id: xyzpoi098654" http://localhost:8080/migrations
196205
curl -v -X POST -H "Content-Type: application/json" -H "X-Request-Id: abcdef123456" -d '{"name": "new_tenant2"}' http://localhost:8080/tenants
197206
```
198207
199-
In above error requests we used `X-Request-Id` header. This header can be used with all requests for request tracing and/or auditing purposes.
208+
In above error requests I used optional `X-Request-Id` header. This header can be used with all requests for tracing and/or auditing purposes.
200209
201210
# Customisation
202211
@@ -254,7 +263,7 @@ The `ultimate-coverage.sh` script loops through 5 different containers (3 MySQL
254263

255264
# License
256265

257-
Copyright 2016-2018 Łukasz Budnik
266+
Copyright 2016-2019 Łukasz Budnik
258267

259268
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
260269

TestDockerfile

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@ ARG SOURCE_BRANCH=master
1010
RUN apk add git
1111

1212
# A - install migrator from local source code
13-
#RUN mkdir -p /go/src/github.com/lukaszbudnik/migrator
14-
#COPY . /go/src/github.com/lukaszbudnik/migrator
13+
RUN mkdir -p /go/src/github.com/lukaszbudnik/migrator
14+
COPY . /go/src/github.com/lukaszbudnik/migrator
1515

1616
# B - install migrator from $SOURCE_BRANCH branch
17-
RUN go get -d -v github.com/lukaszbudnik/migrator
18-
RUN cd /go/src/github.com/lukaszbudnik/migrator && git checkout $SOURCE_BRANCH && ./setup.sh
17+
#RUN go get -d -v github.com/lukaszbudnik/migrator
18+
#RUN cd /go/src/github.com/lukaszbudnik/migrator && git checkout $SOURCE_BRANCH
19+
20+
RUN cd /go/src/github.com/lukaszbudnik/migrator && ./setup.sh
1921

2022
RUN cd /go/src/github.com/lukaszbudnik/migrator && \
2123
GIT_BRANCH=$(git branch | awk -v FS=' ' '/\*/{print $NF}' | sed 's|[()]||g') && \
24+
GIT_COMMIT_DATE=$(git log -n1 --date=iso-strict | grep 'Date:' | sed 's|Date:\s*||g') && \
2225
GIT_COMMIT_SHA=$(git rev-list -1 HEAD) && \
23-
go build -ldflags "-X main.GitCommitSha=$GIT_COMMIT_SHA -X main.GitBranch=$GIT_BRANCH"
26+
go build -ldflags "-X main.GitCommitDate=$GIT_COMMIT_DATE -X main.GitCommitSha=$GIT_COMMIT_SHA -X main.GitBranch=$GIT_BRANCH"
2427

2528
FROM alpine:3.8
2629
COPY --from=builder /go/src/github.com/lukaszbudnik/migrator/migrator /bin

common/common.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,6 @@ type RequestIDKey struct{}
1212
// ActionKey is used together with context for setting/getting current action
1313
type ActionKey struct{}
1414

15-
func logLevel(ctx context.Context, level string, format string, a ...interface{}) string {
16-
requestID := ctx.Value(RequestIDKey{})
17-
action := ctx.Value(ActionKey{})
18-
message := fmt.Sprintf(format, a...)
19-
log.Printf("%v %v [%v] - %v", level, action, requestID, message)
20-
return message
21-
}
22-
2315
// LogError logs error message
2416
func LogError(ctx context.Context, format string, a ...interface{}) string {
2517
return logLevel(ctx, "ERROR", format, a...)
@@ -35,3 +27,11 @@ func LogPanic(ctx context.Context, format string, a ...interface{}) string {
3527
message := logLevel(ctx, "PANIC", format, a...)
3628
panic(message)
3729
}
30+
31+
func logLevel(ctx context.Context, level string, format string, a ...interface{}) string {
32+
requestID := ctx.Value(RequestIDKey{})
33+
action := ctx.Value(ActionKey{})
34+
message := fmt.Sprintf(format, a...)
35+
log.Printf("%v %v [%v] - %v", level, action, requestID, message)
36+
return message
37+
}

config/config.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ type Config struct {
1818
TenantSelectSQL string `yaml:"tenantSelectSQL,omitempty"`
1919
TenantInsertSQL string `yaml:"tenantInsertSQL,omitempty"`
2020
SchemaPlaceHolder string `yaml:"schemaPlaceHolder,omitempty"`
21-
SingleSchemas []string `yaml:"singleSchemas" validate:"min=1"`
22-
TenantSchemas []string `yaml:"tenantSchemas,omitempty"`
21+
SingleMigrations []string `yaml:"singleMigrations" validate:"min=1"`
22+
TenantMigrations []string `yaml:"tenantMigrations,omitempty"`
23+
SingleScripts []string `yaml:"singleScripts,omitempty"`
24+
TenantScripts []string `yaml:"tenantScripts,omitempty"`
2325
Port string `yaml:"port,omitempty"`
2426
WebHookURL string `yaml:"webHookURL,omitempty"`
2527
WebHookTemplate string `yaml:"webHookTemplate,omitempty"`

config/config_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ func TestFromFile(t *testing.T) {
2424
assert.Equal(t, "select name from migrator.migrator_tenants", config.TenantSelectSQL)
2525
assert.Equal(t, "postgres", config.Driver)
2626
assert.Equal(t, "user=postgres dbname=migrator_test host=192.168.99.100 port=55432 sslmode=disable", config.DataSource)
27-
assert.Equal(t, []string{"tenants"}, config.TenantSchemas)
28-
assert.Equal(t, []string{"public", "ref", "config"}, config.SingleSchemas)
27+
assert.Equal(t, []string{"tenants"}, config.TenantMigrations)
28+
assert.Equal(t, []string{"public", "ref", "config"}, config.SingleMigrations)
2929
assert.Equal(t, "8811", config.Port)
3030
assert.Equal(t, "{schema}", config.SchemaPlaceHolder)
3131
assert.Equal(t, "https://slack.com/api/api.test", config.WebHookURL)
@@ -43,26 +43,28 @@ func TestWithEnvFromFile(t *testing.T) {
4343
assert.Equal(t, fmt.Sprintf("lets_assume_password=%v&and_something_else=%v&param=value", os.Getenv("HOME"), os.Getenv("USER")), config.DataSource)
4444
assert.Equal(t, os.Getenv("_"), config.Port)
4545
assert.Equal(t, os.Getenv("USER"), config.SchemaPlaceHolder)
46-
assert.Equal(t, []string{"tenants"}, config.TenantSchemas)
47-
assert.Equal(t, []string{"public", "ref", "config"}, config.SingleSchemas)
46+
assert.Equal(t, []string{"tenants"}, config.TenantMigrations)
47+
assert.Equal(t, []string{"public", "ref", "config"}, config.SingleMigrations)
4848
assert.Equal(t, os.Getenv("SHLVL"), config.WebHookURL)
4949
assert.Equal(t, os.Getenv("TERM"), config.WebHookTemplate)
5050
assert.Equal(t, fmt.Sprintf("X-Security-Token: %v", os.Getenv("USER")), config.WebHookHeaders[0])
5151
}
5252

5353
func TestConfigString(t *testing.T) {
54-
config := &Config{"/opt/app/migrations", "postgres", "user=p dbname=db host=localhost", "select abc", "insert into table", ":tenant", []string{"ref"}, []string{"tenants"}, "8181", "https://hooks.slack.com/services/TTT/BBB/XXX", "{json: text}", []string{}}
54+
config := &Config{"/opt/app/migrations", "postgres", "user=p dbname=db host=localhost", "select abc", "insert into table", ":tenant", []string{"ref"}, []string{"tenants"}, []string{"procedures"}, []string{}, "8181", "https://hooks.slack.com/services/TTT/BBB/XXX", "{json: text}", []string{}}
5555
// check if go naming convention applies
5656
expected := `baseDir: /opt/app/migrations
5757
driver: postgres
5858
dataSource: user=p dbname=db host=localhost
5959
tenantSelectSQL: select abc
6060
tenantInsertSQL: insert into table
6161
schemaPlaceHolder: :tenant
62-
singleSchemas:
62+
singleMigrations:
6363
- ref
64-
tenantSchemas:
64+
tenantMigrations:
6565
- tenants
66+
singleScripts:
67+
- procedures
6668
port: "8181"
6769
webHookURL: https://hooks.slack.com/services/TTT/BBB/XXX
6870
webHookTemplate: '{json: text}'`

db/db.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ func (bc *baseConnector) applyMigrationsInTx(ctx context.Context, tx *sql.Tx, te
281281

282282
for _, m := range migrations {
283283
var schemas []string
284-
if m.MigrationType == types.MigrationTypeTenantSchema {
284+
// TODO check if golang supports "in"
285+
if m.MigrationType == types.MigrationTypeTenantMigration || m.MigrationType == types.MigrationTypeTenantScript {
285286
schemas = tenants
286287
} else {
287288
schemas = []string{m.SourceDir}

0 commit comments

Comments
 (0)