Skip to content

Commit

Permalink
Merge pull request #286 from Shopify/allow_super_user_on_read_only
Browse files Browse the repository at this point in the history
add AllowSuperUserOnReadOnly flag
  • Loading branch information
Manan Maniyar committed Jun 9, 2021
2 parents 40ac9a8 + 720822c commit e605f11
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
11 changes: 11 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,17 @@ type Config struct {
// in the Progress. This behaviour is perfectly okay and doesn't mean there are no rows being written
// to the target DB.
EnableRowBatchSize bool

// If the target DB is set to read_only ghostferry will throw an error during the initialization step.
// AllowSuperUserOnReadOnly flag allows to run ghostferry even if the target DB is read_only. This is helpful in
// scenarios where target DB needs to be restricted from writes made by any other user then the ghostferry user.
//
// Optional: Defaults to false.
//
// NOTE:
// The ghostferry target user should have SUPER permissions to actually write to the target DB,
// if ghostferry is ran with AllowSuperUserOnReadOnly = true and the target DB is set to read_only.
AllowSuperUserOnReadOnly bool
}

func (c *Config) ValidateConfig() error {
Expand Down
16 changes: 9 additions & 7 deletions ferry.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,15 @@ func (f *Ferry) Initialize() (err error) {
return err
}

isReplica, err := CheckDbIsAReplica(f.TargetDB)
if err != nil {
f.logger.WithError(err).Error("cannot check if target db is writable")
return err
}
if isReplica {
return fmt.Errorf("@@read_only must be OFF on target db")
if !f.Config.AllowSuperUserOnReadOnly {
isReplica, err := CheckDbIsAReplica(f.TargetDB)
if err != nil {
f.logger.WithError(err).Error("cannot check if target db is writable")
return err
}
if isReplica {
return fmt.Errorf("@@read_only must be OFF on target db")
}
}

// Check if we're running from a replica or not and sanity check
Expand Down
14 changes: 14 additions & 0 deletions test/go/ferry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ func (t *FerryTestSuite) TestReadOnlyDatabaseFailsInitialization() {
t.Require().Nil(err)
}

func (t *FerryTestSuite) TestReadOnlyDatabaseDoesNotFailInitializationWithAllowSuperUserOnReadOnlyFlag() {
_, err := t.Ferry.TargetDB.Exec("SET GLOBAL read_only = ON")
t.Require().Nil(err)

ferry := testhelpers.NewTestFerry().Ferry
ferry.Config.AllowSuperUserOnReadOnly = true

err = ferry.Initialize()
t.Require().Nil(err)

_, err = t.Ferry.TargetDB.Exec("SET GLOBAL read_only = OFF")
t.Require().Nil(err)
}

func (t *FerryTestSuite) TestSourceDatabaseWithForeignKeyConstraintFailsInitialization() {
createTableWithFkConstraint := `
CREATE TABLE gftest.test_fk (
Expand Down

0 comments on commit e605f11

Please sign in to comment.