Преглед изворни кода

Add --idempotent to make --install idempotent

Kailash Nadh пре 3 година
родитељ
комит
3847c67087
3 измењених фајлова са 32 додато и 15 уклоњено
  1. 3 2
      cmd/init.go
  2. 28 12
      cmd/install.go
  3. 1 1
      cmd/main.go

+ 3 - 2
cmd/init.go

@@ -84,13 +84,14 @@ func initFlags() {
 	// Register the commandline flags.
 	// Register the commandline flags.
 	f.StringSlice("config", []string{"config.toml"},
 	f.StringSlice("config", []string{"config.toml"},
 		"path to one or more config files (will be merged in order)")
 		"path to one or more config files (will be merged in order)")
-	f.Bool("install", false, "run first time installation")
+	f.Bool("install", false, "setup database (first time)")
+	f.Bool("idempotent", false, "make --install run only if the databse isn't already setup")
 	f.Bool("upgrade", false, "upgrade database to the current version")
 	f.Bool("upgrade", false, "upgrade database to the current version")
 	f.Bool("version", false, "current version of the build")
 	f.Bool("version", false, "current version of the build")
 	f.Bool("new-config", false, "generate sample config file")
 	f.Bool("new-config", false, "generate sample config file")
 	f.String("static-dir", "", "(optional) path to directory with static files")
 	f.String("static-dir", "", "(optional) path to directory with static files")
 	f.String("i18n-dir", "", "(optional) path to directory with i18n language files")
 	f.String("i18n-dir", "", "(optional) path to directory with i18n language files")
-	f.Bool("yes", false, "assume 'yes' to prompts, eg: during --install")
+	f.Bool("yes", false, "assume 'yes' to prompts during --install/upgrade")
 	if err := f.Parse(os.Args[1:]); err != nil {
 	if err := f.Parse(os.Args[1:]); err != nil {
 		lo.Fatalf("error loading flags: %v", err)
 		lo.Fatalf("error loading flags: %v", err)
 	}
 	}

+ 28 - 12
cmd/install.go

@@ -17,13 +17,17 @@ import (
 
 
 // install runs the first time setup of creating and
 // install runs the first time setup of creating and
 // migrating the database and creating the super user.
 // migrating the database and creating the super user.
-func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt bool) {
+func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt, idempotent bool) {
 	qMap, _ := initQueries(queryFilePath, db, fs, false)
 	qMap, _ := initQueries(queryFilePath, db, fs, false)
 
 
 	fmt.Println("")
 	fmt.Println("")
-	fmt.Println("** first time installation **")
-	fmt.Printf("** IMPORTANT: This will wipe existing listmonk tables and types in the DB '%s' **",
-		ko.String("db.database"))
+	if !idempotent {
+		fmt.Println("** first time installation **")
+		fmt.Printf("** IMPORTANT: This will wipe existing listmonk tables and types in the DB '%s' **",
+			ko.String("db.database"))
+	} else {
+		fmt.Println("** first time (idempotent) installation **")
+	}
 	fmt.Println("")
 	fmt.Println("")
 
 
 	if prompt {
 	if prompt {
@@ -38,10 +42,22 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt bool) {
 		}
 		}
 	}
 	}
 
 
+	// If idempotence is on, check if the DB is already setup.
+	if idempotent {
+		if _, err := db.Exec("SELECT count(*) FROM settings"); err != nil {
+			// If "settings" doesn't exist, assume it's a fresh install.
+			if pqErr, ok := err.(*pq.Error); ok && pqErr.Code != "42P01" {
+				lo.Fatalf("error checking existing DB schema: %v", err)
+			}
+		} else {
+			lo.Println("skipping install as database appears to be already setup")
+			os.Exit(0)
+		}
+	}
+
 	// Migrate the tables.
 	// Migrate the tables.
-	err := installSchema(lastVer, db, fs)
-	if err != nil {
-		lo.Fatalf("Error migrating DB schema: %v", err)
+	if err := installSchema(lastVer, db, fs); err != nil {
+		lo.Fatalf("error migrating DB schema: %v", err)
 	}
 	}
 
 
 	// Load the queries.
 	// Load the queries.
@@ -62,7 +78,7 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt bool) {
 		models.ListOptinSingle,
 		models.ListOptinSingle,
 		pq.StringArray{"test"},
 		pq.StringArray{"test"},
 	); err != nil {
 	); err != nil {
-		lo.Fatalf("Error creating list: %v", err)
+		lo.Fatalf("error creating list: %v", err)
 	}
 	}
 
 
 	if err := q.CreateList.Get(&optinList, uuid.Must(uuid.NewV4()),
 	if err := q.CreateList.Get(&optinList, uuid.Must(uuid.NewV4()),
@@ -71,7 +87,7 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt bool) {
 		models.ListOptinDouble,
 		models.ListOptinDouble,
 		pq.StringArray{"test"},
 		pq.StringArray{"test"},
 	); err != nil {
 	); err != nil {
-		lo.Fatalf("Error creating list: %v", err)
+		lo.Fatalf("error creating list: %v", err)
 	}
 	}
 
 
 	// Sample subscriber.
 	// Sample subscriber.
@@ -93,7 +109,7 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt bool) {
 		pq.Int64Array{int64(optinList)},
 		pq.Int64Array{int64(optinList)},
 		models.SubscriptionStatusUnconfirmed,
 		models.SubscriptionStatusUnconfirmed,
 		true); err != nil {
 		true); err != nil {
-		lo.Fatalf("Error creating subscriber: %v", err)
+		lo.Fatalf("error creating subscriber: %v", err)
 	}
 	}
 
 
 	// Default template.
 	// Default template.
@@ -132,8 +148,8 @@ func install(lastVer string, db *sqlx.DB, fs stuffbin.FileSystem, prompt bool) {
 		lo.Fatalf("error creating sample campaign: %v", err)
 		lo.Fatalf("error creating sample campaign: %v", err)
 	}
 	}
 
 
-	lo.Printf("Setup complete")
-	lo.Printf(`Run the program and access the dashboard at %s`, ko.MustString("app.address"))
+	lo.Printf("setup complete")
+	lo.Printf(`run the program and access the dashboard at %s`, ko.MustString("app.address"))
 }
 }
 
 
 // installSchema executes the SQL schema and creates the necessary tables and types.
 // installSchema executes the SQL schema and creates the necessary tables and types.

+ 1 - 1
cmd/main.go

@@ -122,7 +122,7 @@ func init() {
 	// as the installer needs to work on an empty DB.
 	// as the installer needs to work on an empty DB.
 	if ko.Bool("install") {
 	if ko.Bool("install") {
 		// Save the version of the last listed migration.
 		// Save the version of the last listed migration.
-		install(migList[len(migList)-1].version, db, fs, !ko.Bool("yes"))
+		install(migList[len(migList)-1].version, db, fs, !ko.Bool("yes"), ko.Bool("idempotent"))
 		os.Exit(0)
 		os.Exit(0)
 	}
 	}