harbor/src/cmd/migrate-patch/main.go

89 lines
2.7 KiB
Go

// Copyright Project Harbor Authors
//
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"database/sql"
"flag"
"log"
"strings"
"time"
_ "github.com/jackc/pgx/v4/stdlib" // registry pgx driver
)
var dbURL string
const pgSQLAlterStmt string = `ALTER TABLE schema_migrations ADD COLUMN "dirty" boolean NOT NULL DEFAULT false`
const pgSQLCheckColStmt string = `SELECT T1.C1, T2.C2 FROM
(SELECT COUNT(*) AS C1 FROM information_schema.tables WHERE table_name='schema_migrations') T1,
(SELECT COUNT(*) AS C2 FROM information_schema.columns WHERE table_name='schema_migrations' and column_name='dirty') T2`
const pgSQLDelRows string = `DELETE FROM schema_migrations t WHERE t.version < ( SELECT MAX(version) FROM schema_migrations )`
func init() {
urlUsage := `The URL to the target database (driver://url). Currently it only supports postgres`
flag.StringVar(&dbURL, "database", "", urlUsage)
}
func main() {
flag.Parse()
log.Printf("Updating database.")
if !strings.HasPrefix(dbURL, "postgres://") {
log.Fatalf("Invalid URL: '%s'\n", dbURL)
}
db, err := sql.Open("pgx", dbURL)
if err != nil {
log.Fatalf("Failed to connect to Database, error: %v\n", err)
}
defer db.Close()
c := make(chan struct{})
go func() {
defer close(c)
err := db.Ping()
for ; err != nil; err = db.Ping() {
log.Println("Failed to Ping DB, sleep for 1 second.")
time.Sleep(1 * time.Second)
}
}()
select {
case <-c:
case <-time.After(30 * time.Second):
log.Fatal("Failed to connect DB after 30 seconds, time out. \n")
}
row := db.QueryRow(pgSQLCheckColStmt)
var tblCount, colCount int
if err := row.Scan(&tblCount, &colCount); err != nil {
log.Fatalf("Failed to check schema_migrations table, error: %v \n", err)
}
if tblCount == 0 {
log.Println("schema_migrations table does not exist, skip.")
return
}
if colCount > 0 {
log.Println("schema_migrations table does not require update, skip.")
return
}
if _, err := db.Exec(pgSQLDelRows); err != nil {
log.Fatalf("Failed to clean up table, error: %v", err)
}
if _, err := db.Exec(pgSQLAlterStmt); err != nil {
log.Fatalf("Failed to update database, error: %v \n", err)
}
log.Println("Done updating database.")
}