-
Notifications
You must be signed in to change notification settings - Fork 137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Apply migrations when tink-server boots #296
Conversation
Codecov Report
@@ Coverage Diff @@
## master #296 +/- ##
==========================================
+ Coverage 22.90% 22.91% +0.01%
==========================================
Files 15 15
Lines 1275 1274 -1
==========================================
Hits 292 292
+ Misses 964 963 -1
Partials 19 19
Continue to review full report at Codecov.
|
This is just a PoC to see what other people think about it.
(original status command)
|
, metadata JSONB | ||
, data JSONB | ||
);`}, | ||
Down: []string{"DROP DATABASE tinkerbell"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I um worry about this. I think every thing I've ever read about Down migrations is always "no, don't". Of course I can't find anything on this atm, but I'll keep looking :D.
In general I think its just always easier to think about failing-forward instead of reverting. iirc its less foot-gunny.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now there is no logic that applies rollback :) :) That's one of the topic I would like to discuss. We can say: "you rollback is one migration forward"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So lets drop this Down
;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved
func Get202009171251() *migrate.Migration { | ||
return &migrate.Migration{ | ||
Id: "123", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for minimizing context it would be best to have the Id match the name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great to have a sed or similar check that Id matches Get.*
.
cmd/tink-server/main.go
Outdated
tinkDB := db.Connect(logger) | ||
numAppliedMigrations, err := tinkDB.Migrate() | ||
if err != nil { | ||
panic(err) | ||
} | ||
log.With("num_applied_migrations", numAppliedMigrations).Info("Running migrations if necessary") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've found out the hard way that its best to allow for migrations to run separately from normal service startup. This way once we have multiple tinks running an upgrade won't have +1 tinks trying to migrate the db.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a good point that I didn't think about. Ideally, good migrations should be applicable more than once without side effect I presume but still... I see your point.
This PR has a very specific title :P so if we don't want to do that, I will close this in favor of something else. I think there are a good amount of people that will stay benefit from having a managed migration process and this will avoid for them the extra work to apply migrations by themself when they update.
I presume for the other people we can have a flag=--disable-migration
? Or do you think an external workflow will make everyone happy enough?
I am just doing an exercise here. But, we can embed the same migration function we do here:
numAppliedMigrations, err := tinkDB.Migrate()
if err != nil {
panic(err)
}
As part of the tink-cli itself, so who wants to manage migration externally can disable migration in tink-server and they can apply it when they like via tink-cli. Not sure if it has sense or if it is just useless complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well if you start up 2 tink-servers at the same time they may both try to do some costly migration and take up db time and only one will succeed, the other will fail and restart and then continue. It would stay correct, but waste time/db resources.
Having --migrate-only
would be better imo, as it can be a separate step in the deployment pipeline and would exit when done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think that flag should stay in tink-server? I like that! I will check if the library supports something like a dry run that checks for migrations but does not apply them. In this way I can run it at start and notify the user that there are migration not applied yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done @mmlb and I have updated the PR description with the new workflow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah the dry run would be pretty nice imo.
db/db.go
Outdated
return migrate.Exec(t.instance, "postgres", migration.GetMigrations(), migrate.Up) | ||
} | ||
|
||
func (t *TinkDB) CheckAvailableMigrations() (int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Available seems like the wrong word to me... Necessary? Required?
db/db.go
Outdated
fmt.Println("migrations ", len(migrations)) | ||
fmt.Println("records ", len(records)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debugging?
Up: []string{` | ||
SELECT 'CREATE DATABASE tinkerbell' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'tinkerbell'); | ||
|
||
SET ROLE tinkerbell; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should probably happen before the SELECT 'CREATE...'
if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
It will be nice to have the tink-server capable of applying migrations if necessary. The idea to self-apply migrations will may look unusual but it is an easy way to distribute software capable of migrating database schema without having to run any external procedures. ```console $ docker run -d -it -e POSTGRES_PASSWORD=tinkerbell -e POSTGRES_USER=tinkerbell -p 5432:5432 postgres $ PGPASSWORD=tinkerbell PGUSER=tinkerbell PGSSLMODE=disable PACKET_VERSION=v1 PACKET_ENV=ga ROLLBAR_TOKEN=ignored go run cmd/tink-server/main.go {"level":"info","ts":1600349232.375571,"caller":"tink-server/main.go:31","msg":"starting version devel","service":"github.com/tinkerbell/tink"} {"level":"info","ts":1600349232.419096,"caller":"tink-server/main.go:42","msg":"Running migrations if necessary","service":"github.com/tinkerbell/tink","num_applied_migrations":1} ``` Second time you run it: ``` $ PGPASSWORD=tinkerbell PGUSER=tinkerbell PGSSLMODE=disable PACKET_VERSION=v1 PACKET_ENV=ga ROLLBAR_TOKEN=ignored go run cmd/tink-server/main.go [12/78]{"level":"info","ts":1600349264.877263,"caller":"tink-server/main.go:31","msg":"starting version devel","service":"github.com/tinkerbell/tink"} {"level":"info","ts":1600349264.8883042,"caller":"tink-server/main.go:42","msg":"Running migrations if necessary","service":"github.com/tinkerbell/tink","num_applied_migrations":0} ``` Signed-off-by: Gianluca Arbezzano <[email protected]>
Reverts #296 I have to rever this PR because we merged it too early. I don't have a good story yet for what concerns "how to apply migration" in sandbox or with docker compose.
Description
It will be nice to have the tink-server capable of applying migrations
if necessary. The idea to self-apply migrations will may look unusual
but it is an easy way to distribute software capable of migrating
database schema without having to run any external procedures.
Why is this needed
Fixes: #295
How Has This Been Tested?
As suggested you should run tink-server with ONLY_MIGRATION=true
How are existing users impacted? What migration steps/scripts do we need?
They are not impacted by this change.
Checklist:
I have: