Skip to content

Commit e605f11

Browse files
author
Manan Maniyar
authored
Merge pull request #286 from Shopify/allow_super_user_on_read_only
add AllowSuperUserOnReadOnly flag
2 parents 40ac9a8 + 720822c commit e605f11

3 files changed

Lines changed: 34 additions & 7 deletions

File tree

config.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,17 @@ type Config struct {
753753
// in the Progress. This behaviour is perfectly okay and doesn't mean there are no rows being written
754754
// to the target DB.
755755
EnableRowBatchSize bool
756+
757+
// If the target DB is set to read_only ghostferry will throw an error during the initialization step.
758+
// AllowSuperUserOnReadOnly flag allows to run ghostferry even if the target DB is read_only. This is helpful in
759+
// scenarios where target DB needs to be restricted from writes made by any other user then the ghostferry user.
760+
//
761+
// Optional: Defaults to false.
762+
//
763+
// NOTE:
764+
// The ghostferry target user should have SUPER permissions to actually write to the target DB,
765+
// if ghostferry is ran with AllowSuperUserOnReadOnly = true and the target DB is set to read_only.
766+
AllowSuperUserOnReadOnly bool
756767
}
757768

758769
func (c *Config) ValidateConfig() error {

ferry.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -375,13 +375,15 @@ func (f *Ferry) Initialize() (err error) {
375375
return err
376376
}
377377

378-
isReplica, err := CheckDbIsAReplica(f.TargetDB)
379-
if err != nil {
380-
f.logger.WithError(err).Error("cannot check if target db is writable")
381-
return err
382-
}
383-
if isReplica {
384-
return fmt.Errorf("@@read_only must be OFF on target db")
378+
if !f.Config.AllowSuperUserOnReadOnly {
379+
isReplica, err := CheckDbIsAReplica(f.TargetDB)
380+
if err != nil {
381+
f.logger.WithError(err).Error("cannot check if target db is writable")
382+
return err
383+
}
384+
if isReplica {
385+
return fmt.Errorf("@@read_only must be OFF on target db")
386+
}
385387
}
386388

387389
// Check if we're running from a replica or not and sanity check

test/go/ferry_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,20 @@ func (t *FerryTestSuite) TestReadOnlyDatabaseFailsInitialization() {
3434
t.Require().Nil(err)
3535
}
3636

37+
func (t *FerryTestSuite) TestReadOnlyDatabaseDoesNotFailInitializationWithAllowSuperUserOnReadOnlyFlag() {
38+
_, err := t.Ferry.TargetDB.Exec("SET GLOBAL read_only = ON")
39+
t.Require().Nil(err)
40+
41+
ferry := testhelpers.NewTestFerry().Ferry
42+
ferry.Config.AllowSuperUserOnReadOnly = true
43+
44+
err = ferry.Initialize()
45+
t.Require().Nil(err)
46+
47+
_, err = t.Ferry.TargetDB.Exec("SET GLOBAL read_only = OFF")
48+
t.Require().Nil(err)
49+
}
50+
3751
func (t *FerryTestSuite) TestSourceDatabaseWithForeignKeyConstraintFailsInitialization() {
3852
createTableWithFkConstraint := `
3953
CREATE TABLE gftest.test_fk (

0 commit comments

Comments
 (0)