diff --git a/build/cicd/internal/config/config.go b/build/cicd/internal/config/config.go index e9c59aa..9bb9a6e 100644 --- a/build/cicd/internal/config/config.go +++ b/build/cicd/internal/config/config.go @@ -28,6 +28,10 @@ const ( // GitLabProjectBaseUrl is the base url used to create links to a specific CI/CD job or pipeline by ID. GitLabProjectBaseUrl = "https://gitlab.com/geeks-accelerator/oss/saas-starter-kit" + + // EnableRdsServerless will use the Aurora database engine that scales the capacity based on database load. This is + // a good option for intermittent or unpredictable workloads. + EnableRdsServerless = true ) // Env defines the target deployment environment. @@ -108,6 +112,15 @@ func (cfgCtx *ConfigContext) Config(log *log.Logger) (*devdeploy.Config, error) // ProjectName will be used for prefixing AWS resources. This could be changed as needed or manually defined. cfg.ProjectName = ProjectNamePrefix + modDetails.ProjectName + // In a verbatim fork of the repo, a CI/CD would fail due to a conflict creating AWS resources (such as S3) since + // their name is calculated with the go.mod path. Since the name-scope of AWS resources is region/global scope, + // it will fail to create appropriate resources for the account of the forked user. + if cfg.ProjectName == "saas-starter-kit" { + + // Replace the prefix 'saas' with the parent directory name, hopefully the gitlab group/username. + cfg.ProjectName = filepath.Base(filepath.Dir(cfg.ProjectRoot)) + "-starter-kit" + } + // Set default AWS ECR Repository Name. cfg.AwsEcrRepository = &devdeploy.AwsEcrRepository{ RepositoryName: cfg.ProjectName, @@ -337,32 +350,98 @@ func (cfgCtx *ConfigContext) Config(log *log.Logger) (*devdeploy.Config, error) }, } - // Define the RDS Database instance for transactional data. A random one will be generated for any created instance. - cfg.AwsRdsDBInstance = &devdeploy.AwsRdsDBInstance{ - DBInstanceIdentifier: cfg.ProjectName + "-" + cfg.Env, - DBName: "shared", - Engine: "postgres", - MasterUsername: "god", - Port: 5432, - DBInstanceClass: "db.t2.small", - AllocatedStorage: 20, - PubliclyAccessible: false, - BackupRetentionPeriod: aws.Int64(7), - AutoMinorVersionUpgrade: true, - CopyTagsToSnapshot: aws.Bool(true), - Tags: []devdeploy.Tag{ - {Key: devdeploy.AwsTagNameProject, Value: cfg.ProjectName}, - {Key: devdeploy.AwsTagNameEnv, Value: cfg.Env}, - }, - AfterCreate: func(res *rds.DBInstance, dbInfo *devdeploy.DBConnInfo) error { - masterDb, err := sqlx.Open(dbInfo.Driver, dbInfo.URL()) - if err != nil { - return errors.WithMessage(err, "Failed to connect to db for schema migration.") - } - defer masterDb.Close() + // If serverless RDS is enabled, defined the RDS database cluster and link it to the database instance. + if EnableRdsServerless { + cfg.AwsRdsDBCluster = &devdeploy.AwsRdsDBCluster{ + DBClusterIdentifier: cfg.ProjectName + "-" + cfg.Env, + Engine: "aurora-postgresql", + EngineMode: "serverless", + DatabaseName: "shared", + MasterUsername: "god", + Port: 5432, + BackupRetentionPeriod: aws.Int64(7), + CopyTagsToSnapshot: aws.Bool(true), + Tags: []devdeploy.Tag{ + {Key: devdeploy.AwsTagNameProject, Value: cfg.ProjectName}, + {Key: devdeploy.AwsTagNameEnv, Value: cfg.Env}, + }, + PreCreate: func(input *rds.CreateDBClusterInput) error { + input.ScalingConfiguration = &rds.ScalingConfiguration{ + // A value that indicates whether to allow or disallow automatic pause for an + // Aurora DB cluster in serverless DB engine mode. A DB cluster can be paused + // only when it's idle (it has no connections). + // + // If a DB cluster is paused for more than seven days, the DB cluster might + // be backed up with a snapshot. In this case, the DB cluster is restored when + // there is a request to connect to it. + AutoPause: aws.Bool(true), - return schema.Migrate(context.Background(), cfg.Env, masterDb, log, false) - }, + // The maximum capacity for an Aurora DB cluster in serverless DB engine mode. + // Valid capacity values are 1, 2, 4, 8, 16, 32, 64, 128, and 256. + // The maximum capacity must be greater than or equal to the minimum capacity. + MaxCapacity: aws.Int64(2), + + // The minimum capacity for an Aurora DB cluster in serverless DB engine mode. + // Valid capacity values are 1, 2, 4, 8, 16, 32, 64, 128, and 256. + // The minimum capacity must be less than or equal to the maximum capacity. + MinCapacity: aws.Int64(2), + + // The time, in seconds, before an Aurora DB cluster in serverless mode is paused. + SecondsUntilAutoPause: aws.Int64(3600), + + // The action to take when the timeout is reached, either ForceApplyCapacityChange + // or RollbackCapacityChange. + // ForceApplyCapacityChange sets the capacity to the specified value as soon + // as possible. + // RollbackCapacityChange, the default, ignores the capacity change if a scaling + // point is not found in the timeout period. + // If you specify ForceApplyCapacityChange, connections that prevent Aurora + // Serverless from finding a scaling point might be dropped. + // For more information, see Autoscaling for Aurora Serverless (https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.how-it-works.html#aurora-serverless.how-it-works.auto-scaling) + // in the Amazon Aurora User Guide. + TimeoutAction: aws.String("ForceApplyCapacityChange"), + } + + return nil + }, + AfterCreate: func(res *rds.DBCluster, dbInfo *devdeploy.DBConnInfo) error { + masterDb, err := sqlx.Open(dbInfo.Driver, dbInfo.URL()) + if err != nil { + return errors.WithMessage(err, "Failed to connect to db for schema migration.") + } + defer masterDb.Close() + + return schema.Migrate(context.Background(), cfg.Env, masterDb, log, false) + }, + } + } else { + // Define the RDS database instance for transactional data. A random password will be generated for any created instance. + cfg.AwsRdsDBInstance = &devdeploy.AwsRdsDBInstance{ + DBInstanceIdentifier: cfg.ProjectName + "-" + cfg.Env, + DBName: "shared", + Engine: "postgres", + MasterUsername: "god", + Port: 5432, + DBInstanceClass: "db.t2.small", + AllocatedStorage: 20, + PubliclyAccessible: false, + BackupRetentionPeriod: aws.Int64(7), + AutoMinorVersionUpgrade: true, + CopyTagsToSnapshot: aws.Bool(true), + Tags: []devdeploy.Tag{ + {Key: devdeploy.AwsTagNameProject, Value: cfg.ProjectName}, + {Key: devdeploy.AwsTagNameEnv, Value: cfg.Env}, + }, + AfterCreate: func(res *rds.DBInstance, dbInfo *devdeploy.DBConnInfo) error { + masterDb, err := sqlx.Open(dbInfo.Driver, dbInfo.URL()) + if err != nil { + return errors.WithMessage(err, "Failed to connect to db for schema migration.") + } + defer masterDb.Close() + + return schema.Migrate(context.Background(), cfg.Env, masterDb, log, false) + }, + } } // AwsIamPolicy defines the name and policy that will be attached to the task role. The policy document grants diff --git a/go.mod b/go.mod index a8e7871..f84ad32 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/dimfeld/httptreemux v5.0.1+incompatible github.com/dustin/go-humanize v1.0.0 github.com/geeks-accelerator/files v0.0.0-20190704085106-630677cd5c14 - github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190527223850-4a863a2d30db + github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823021348-d047c980bb66 github.com/geeks-accelerator/swag v1.6.3 github.com/go-openapi/spec v0.19.2 // indirect github.com/go-openapi/swag v0.19.4 // indirect @@ -39,7 +39,7 @@ require ( github.com/tinylib/msgp v1.1.0 // indirect github.com/urfave/cli v1.21.0 github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 - gitlab.com/geeks-accelerator/oss/devops v1.0.3 + gitlab.com/geeks-accelerator/oss/devops v1.0.7 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 // indirect diff --git a/go.sum b/go.sum index 87fb34c..744636a 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -38,6 +39,14 @@ github.com/geeks-accelerator/files v0.0.0-20190704085106-630677cd5c14 h1:Rrxsq3g github.com/geeks-accelerator/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:HMLrFyDC+sI+871eKlqqIBcaDim/NI8//Mbe+UwhY78= github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190527223850-4a863a2d30db h1:mjErP7mTFHQ3cw/ibAkW3CvQ8gM4k19EkfzRzRINDAE= github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190527223850-4a863a2d30db/go.mod h1:dzpCjo4q7chhMVuHDzs/odROkieZ5Wjp70rNDuX83jU= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823020016-2f4a58a35bb3 h1:183xSX0si++wcRtX6fbGpVXNmC15m4bn4Q9TXEuHtHI= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823020016-2f4a58a35bb3/go.mod h1:dzpCjo4q7chhMVuHDzs/odROkieZ5Wjp70rNDuX83jU= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823020330-42b8aadfc2b9 h1:4O/zyFNOCInZgxMkQTaffOJA6PJYZLY+UFVHzLsLYMc= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823020330-42b8aadfc2b9/go.mod h1:dzpCjo4q7chhMVuHDzs/odROkieZ5Wjp70rNDuX83jU= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823021239-b65769ae7cf1 h1:cH4nj3YQWCvPeRfy6KWzHPKZxn2cJnpQzjbydTdl5Cw= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823021239-b65769ae7cf1/go.mod h1:dzpCjo4q7chhMVuHDzs/odROkieZ5Wjp70rNDuX83jU= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823021348-d047c980bb66 h1:h9pb46oQroOhXmq5cCUU++Eagy240H1/aRwWNIYivrs= +github.com/geeks-accelerator/sqlxmigrate v0.0.0-20190823021348-d047c980bb66/go.mod h1:dzpCjo4q7chhMVuHDzs/odROkieZ5Wjp70rNDuX83jU= github.com/geeks-accelerator/swag v1.6.3 h1:WottuX4MHoy5ZJFXfL+p1IrChpUb/e4g5vpM6tcwOIE= github.com/geeks-accelerator/swag v1.6.3/go.mod h1:YWy7dtuct7Uk3vmKr7s+v/F0SNkGYEeV7Y1CykFhmWU= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -203,6 +212,8 @@ gitlab.com/geeks-accelerator/oss/devops v1.0.2 h1:LqME1zTc9bgB+J/tw7tv1WDjvgmrgl gitlab.com/geeks-accelerator/oss/devops v1.0.2/go.mod h1:rvI71qNJyNiO99ZgGnv/PmJCVrjJjupsXBmfYFXdjGM= gitlab.com/geeks-accelerator/oss/devops v1.0.3 h1:SE2ZD4Csvmm3t/50RoJkVLjDcwXKHayQYawSkpOSqIw= gitlab.com/geeks-accelerator/oss/devops v1.0.3/go.mod h1:rvI71qNJyNiO99ZgGnv/PmJCVrjJjupsXBmfYFXdjGM= +gitlab.com/geeks-accelerator/oss/devops v1.0.7 h1:ZlQufuVnRN3DwJ0I5c5KA5edhQs7OstXc0uUZ9V0ixI= +gitlab.com/geeks-accelerator/oss/devops v1.0.7/go.mod h1:JEl0T87/zftowrIzY1D+rhDMhG0AxnghuZB+VzEWuqM= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= diff --git a/internal/schema/migrations.go b/internal/schema/migrations.go index 0c9cd5c..e776fb6 100644 --- a/internal/schema/migrations.go +++ b/internal/schema/migrations.go @@ -43,21 +43,21 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest CONSTRAINT email UNIQUE (email) ) ;` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } return nil }, Rollback: func(tx *sql.Tx) error { q1 := `DROP TABLE IF EXISTS users` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } return nil }, }, // Create new table accounts. { - ID: "20190522-01c", + ID: "20190522-01h", Migrate: func(tx *sql.Tx) error { if err := createTypeIfNotExists(tx, "account_status_t", "enum('active','pending','disabled')"); err != nil { return err @@ -83,19 +83,19 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest CONSTRAINT name UNIQUE (name) )` if _, err := tx.Exec(q2); err != nil { - return errors.WithMessagef(err, "Query failed %s", q2) + return errors.Wrapf(err, "Query failed %s", q2) } return nil }, Rollback: func(tx *sql.Tx) error { q1 := `DROP TYPE IF EXISTS account_status_t` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } q2 := `DROP TABLE IF EXISTS accounts` if _, err := tx.Exec(q2); err != nil { - return errors.WithMessagef(err, "Query failed %s", q2) + return errors.Wrapf(err, "Query failed %s", q2) } return nil }, @@ -125,7 +125,7 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest CONSTRAINT user_account UNIQUE (user_id,account_id) )` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } return nil @@ -133,17 +133,17 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest Rollback: func(tx *sql.Tx) error { q1 := `DROP TYPE IF EXISTS user_account_role_t` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } q2 := `DROP TYPE IF EXISTS user_account_status_t` if _, err := tx.Exec(q2); err != nil { - return errors.WithMessagef(err, "Query failed %s", q2) + return errors.Wrapf(err, "Query failed %s", q2) } q3 := `DROP TABLE IF EXISTS users_accounts` if _, err := tx.Exec(q3); err != nil { - return errors.WithMessagef(err, "Query failed %s", q3) + return errors.Wrapf(err, "Query failed %s", q3) } return nil @@ -168,19 +168,19 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest PRIMARY KEY (id) )` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } return nil }, Rollback: func(tx *sql.Tx) error { q1 := `DROP TYPE IF EXISTS project_status_t` - if _, err := tx.Exec(q1); err != nil && !errorIsAlreadyExists(err) { - return errors.WithMessagef(err, "Query failed %s", q1) + if _, err := tx.Exec(q1); err != nil && !errorIsAlreadyExists(err) { + return errors.Wrapf(err, "Query failed %s", q1) } q2 := `DROP TABLE IF EXISTS projects` if _, err := tx.Exec(q2); err != nil && !errorIsAlreadyExists(err) { - return errors.WithMessagef(err, "Query failed %s", q2) + return errors.Wrapf(err, "Query failed %s", q2) } return nil }, @@ -192,13 +192,13 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest q1 := `ALTER TABLE users RENAME COLUMN name to first_name;` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } q2 := `ALTER TABLE users ADD last_name varchar(200) NOT NULL DEFAULT '';` if _, err := tx.Exec(q2); err != nil { - return errors.WithMessagef(err, "Query failed %s", q2) + return errors.Wrapf(err, "Query failed %s", q2) } return nil @@ -206,7 +206,7 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest Rollback: func(tx *sql.Tx) error { q1 := `DROP TABLE IF EXISTS users` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } return nil }, @@ -234,9 +234,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest } for _, q := range schemas { - _, err := db.Exec(q) + _, err := tx.Exec(q) if err != nil { - return errors.WithMessagef(err, "Failed to execute sql query '%s'", q) + return errors.Wrapf(err, "Failed to execute sql query '%s'", q) } } @@ -273,9 +273,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest "VALUES %s", strings.Join(valueStrings, ",")) insertStmt = db.Rebind(insertStmt) - _, err := db.Exec(insertStmt, valueArgs...) + _, err := tx.Exec(insertStmt, valueArgs...) if err != nil { - return errors.WithMessagef(err, "Failed to execute sql query '%s'", insertStmt) + return errors.Wrapf(err, "Failed to execute sql query '%s'", insertStmt) } return nil @@ -331,9 +331,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest } for _, q := range queries { - _, err := db.Exec(q) + _, err := tx.Exec(q) if err != nil { - return errors.WithMessagef(err, "Failed to execute sql query '%s'", q) + return errors.Wrapf(err, "Failed to execute sql query '%s'", q) } } @@ -364,9 +364,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest } for _, q := range schemas { - _, err := db.Exec(q) + _, err := tx.Exec(q) if err != nil { - return errors.WithMessagef(err, "Failed to execute sql query '%s'", q) + return errors.Wrapf(err, "Failed to execute sql query '%s'", q) } } @@ -399,16 +399,16 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest } for _, q := range prep { - _, err := db.Exec(q) + _, err := tx.Exec(q) if err != nil { - return errors.WithMessagef(err, "Failed to execute sql query '%s'", q) + return errors.Wrapf(err, "Failed to execute sql query '%s'", q) } } u := "http://download.geonames.org/export/dump/countryInfo.txt" resp, err := pester.Get(u) if err != nil { - return errors.WithMessagef(err, "Failed to read country info from '%s'", u) + return errors.Wrapf(err, "Failed to read country info from '%s'", u) } defer resp.Body.Close() @@ -491,9 +491,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest q := "insert into countryinfo (" + strings.Join(columns, ",") + ") values(" + strings.Join(placeholders, ",") + ")" q = db.Rebind(q) - stmt, err = db.Prepare(q) + stmt, err = tx.Prepare(q) if err != nil { - return errors.WithMessagef(err, "Failed to prepare sql query '%s'", q) + return errors.Wrapf(err, "Failed to prepare sql query '%s'", q) } } @@ -531,9 +531,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest } for _, q := range queries { - _, err := db.Exec(q) + _, err := tx.Exec(q) if err != nil { - return errors.WithMessagef(err, "Failed to execute sql query '%s'", q) + return errors.Wrapf(err, "Failed to execute sql query '%s'", q) } } } @@ -558,9 +558,9 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest } for _, q := range queries { - _, err := db.Exec(q) + _, err := tx.Exec(q) if err != nil { - return errors.WithMessagef(err, "Failed to execute sql query '%s'", q) + return errors.Wrapf(err, "Failed to execute sql query '%s'", q) } } @@ -570,15 +570,15 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest u := "http://download.geonames.org/export/dump/timeZones.txt" resp, err := pester.Get(u) if err != nil { - return errors.WithMessagef(err, "Failed to read timezones info from '%s'", u) + return errors.Wrapf(err, "Failed to read timezones info from '%s'", u) } defer resp.Body.Close() q := "insert into country_timezones (country_code,timezone_id) values(?, ?)" q = db.Rebind(q) - stmt, err := db.Prepare(q) + stmt, err := tx.Prepare(q) if err != nil { - return errors.WithMessagef(err, "Failed to prepare sql query '%s'", q) + return errors.Wrapf(err, "Failed to prepare sql query '%s'", q) } scanner := bufio.NewScanner(resp.Body) @@ -633,7 +633,7 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest CONSTRAINT account_preferences_pkey UNIQUE (account_id,name) )` if _, err := tx.Exec(q); err != nil { - return errors.WithMessagef(err, "Query failed %s", q) + return errors.Wrapf(err, "Query failed %s", q) } return nil @@ -648,12 +648,12 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest Migrate: func(tx *sql.Tx) error { q1 := `ALTER TABLE users ALTER COLUMN timezone DROP DEFAULT` if _, err := tx.Exec(q1); err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } q2 := `ALTER TABLE users ALTER COLUMN timezone DROP NOT NULL` if _, err := tx.Exec(q2); err != nil { - return errors.WithMessagef(err, "Query failed %s", q2) + return errors.Wrapf(err, "Query failed %s", q2) } return nil @@ -669,7 +669,7 @@ func migrationList(ctx context.Context, db *sqlx.DB, log *log.Logger, isUnittest func dropTypeIfExists(tx *sql.Tx, name string) error { q := "DROP TYPE IF EXISTS " + name if _, err := tx.Exec(q); err != nil && !errorIsAlreadyExists(err) { - return errors.WithMessagef(err, "Query failed %s", q) + return errors.Wrapf(err, "Query failed %s", q) } return nil } @@ -677,10 +677,10 @@ func dropTypeIfExists(tx *sql.Tx, name string) error { // createTypeIfNotExists checks to ensure a type doesn't exist before creating. func createTypeIfNotExists(tx *sql.Tx, name, val string) error { - q1 := "select exists (select 1 from pg_type where typname = '"+name+"')" + q1 := "select exists (select 1 from pg_type where typname = '" + name + "')" rows, err := tx.Query(q1) if err != nil { - return errors.WithMessagef(err, "Query failed %s", q1) + return errors.Wrapf(err, "Query failed %s", q1) } defer rows.Close() @@ -700,10 +700,9 @@ func createTypeIfNotExists(tx *sql.Tx, name, val string) error { return nil } - - q2 := `CREATE TYPE "+name+" AS `+val + q2 := "CREATE TYPE " + name + " AS " + val if _, err := tx.Exec(q2); err != nil && !errorIsAlreadyExists(err) { - return errors.WithMessagef(err, "Query failed %s", q2) + return errors.Wrapf(err, "Query failed %s", q2) } return nil