mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-11-04 10:01:05 +01:00 
			
		
		
		
	add versioned migrations (#1644)
This commit is contained in:
		
							parent
							
								
									ac910fd44c
								
							
						
					
					
						commit
						6049ec758c
					
				@ -34,6 +34,7 @@ after improving the test harness as part of adopting [#1460](https://github.com/
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Changes
 | 
					### Changes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use versioned migrations [#1644](https://github.com/juanfont/headscale/pull/1644)
 | 
				
			||||||
Make the OIDC callback page better [#1484](https://github.com/juanfont/headscale/pull/1484)
 | 
					Make the OIDC callback page better [#1484](https://github.com/juanfont/headscale/pull/1484)
 | 
				
			||||||
SSH support [#1487](https://github.com/juanfont/headscale/pull/1487)
 | 
					SSH support [#1487](https://github.com/juanfont/headscale/pull/1487)
 | 
				
			||||||
State management has been improved [#1492](https://github.com/juanfont/headscale/pull/1492)
 | 
					State management has been improved [#1492](https://github.com/juanfont/headscale/pull/1492)
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
          # When updating go.mod or go.sum, a new sha will need to be calculated,
 | 
					          # When updating go.mod or go.sum, a new sha will need to be calculated,
 | 
				
			||||||
          # update this if you have a mismatch after doing a change to thos files.
 | 
					          # update this if you have a mismatch after doing a change to thos files.
 | 
				
			||||||
          vendorHash = "sha256-7yqJbF0GkKa3wjiGWJ8BZSJyckrpwmCiX77/aoPGmRc=";
 | 
					          vendorHash = "sha256-u9AmJguQ5dnJpfhOeLN43apvMHuraOrJhvlEIp9RoIc=";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"];
 | 
					          ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"];
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@ -75,6 +75,7 @@ require (
 | 
				
			|||||||
	github.com/fsnotify/fsnotify v1.7.0 // indirect
 | 
						github.com/fsnotify/fsnotify v1.7.0 // indirect
 | 
				
			||||||
	github.com/fxamacker/cbor/v2 v2.5.0 // indirect
 | 
						github.com/fxamacker/cbor/v2 v2.5.0 // indirect
 | 
				
			||||||
	github.com/glebarez/go-sqlite v1.21.2 // indirect
 | 
						github.com/glebarez/go-sqlite v1.21.2 // indirect
 | 
				
			||||||
 | 
						github.com/go-gormigrate/gormigrate/v2 v2.1.1 // indirect
 | 
				
			||||||
	github.com/go-jose/go-jose/v3 v3.0.1 // indirect
 | 
						github.com/go-jose/go-jose/v3 v3.0.1 // indirect
 | 
				
			||||||
	github.com/gogo/protobuf v1.3.2 // indirect
 | 
						github.com/gogo/protobuf v1.3.2 // indirect
 | 
				
			||||||
	github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
 | 
						github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@ -101,6 +101,8 @@ github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9g
 | 
				
			|||||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
 | 
					github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
 | 
				
			||||||
github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc=
 | 
					github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc=
 | 
				
			||||||
github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA=
 | 
					github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA=
 | 
				
			||||||
 | 
					github.com/go-gormigrate/gormigrate/v2 v2.1.1 h1:eGS0WTFRV30r103lU8JNXY27KbviRnqqIDobW3EV3iY=
 | 
				
			||||||
 | 
					github.com/go-gormigrate/gormigrate/v2 v2.1.1/go.mod h1:L7nJ620PFDKei9QOhJzqA8kRCk+E3UbV2f5gv+1ndLc=
 | 
				
			||||||
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
 | 
					github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
 | 
				
			||||||
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
 | 
					github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
 | 
				
			||||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 | 
					github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/glebarez/sqlite"
 | 
						"github.com/glebarez/sqlite"
 | 
				
			||||||
 | 
						"github.com/go-gormigrate/gormigrate/v2"
 | 
				
			||||||
	"github.com/juanfont/headscale/hscontrol/notifier"
 | 
						"github.com/juanfont/headscale/hscontrol/notifier"
 | 
				
			||||||
	"github.com/juanfont/headscale/hscontrol/types"
 | 
						"github.com/juanfont/headscale/hscontrol/types"
 | 
				
			||||||
	"github.com/juanfont/headscale/hscontrol/util"
 | 
						"github.com/juanfont/headscale/hscontrol/util"
 | 
				
			||||||
@ -21,15 +22,11 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	dbVersion = "1"
 | 
					 | 
				
			||||||
	Postgres = "postgres"
 | 
						Postgres = "postgres"
 | 
				
			||||||
	Sqlite   = "sqlite3"
 | 
						Sqlite   = "sqlite3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var errDatabaseNotSupported = errors.New("database type not supported")
 | 
				
			||||||
	errValueNotFound        = errors.New("not found")
 | 
					 | 
				
			||||||
	errDatabaseNotSupported = errors.New("database type not supported")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// KV is a key-value store in a psql table. For future use...
 | 
					// KV is a key-value store in a psql table. For future use...
 | 
				
			||||||
// TODO(kradalby): Is this used for anything?
 | 
					// TODO(kradalby): Is this used for anything?
 | 
				
			||||||
@ -64,51 +61,50 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	db := HSDatabase{
 | 
						migrations := gormigrate.New(dbConn, gormigrate.DefaultOptions, []*gormigrate.Migration{
 | 
				
			||||||
		db:       dbConn,
 | 
							// New migrations should be added as transactions at the end of this list.
 | 
				
			||||||
		notifier: notifier,
 | 
							// The initial commit here is quite messy, completely out of order and
 | 
				
			||||||
 | 
							// has no versioning and is the tech debt of not having versioned migrations
 | 
				
			||||||
		ipPrefixes: ipPrefixes,
 | 
							// prior to this point. This first migration is all DB changes to bring a DB
 | 
				
			||||||
		baseDomain: baseDomain,
 | 
							// up to 0.23.0.
 | 
				
			||||||
	}
 | 
							{
 | 
				
			||||||
 | 
								ID: "202312101416",
 | 
				
			||||||
	log.Debug().Msgf("database %#v", dbConn)
 | 
								Migrate: func(tx *gorm.DB) error {
 | 
				
			||||||
 | 
					 | 
				
			||||||
				if dbType == Postgres {
 | 
									if dbType == Postgres {
 | 
				
			||||||
		dbConn.Exec(`create extension if not exists "uuid-ossp";`)
 | 
										tx.Exec(`create extension if not exists "uuid-ossp";`)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ = dbConn.Migrator().RenameTable("namespaces", "users")
 | 
									_ = tx.Migrator().RenameTable("namespaces", "users")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// the big rename from Machine to Node
 | 
									// the big rename from Machine to Node
 | 
				
			||||||
	_ = dbConn.Migrator().RenameTable("machines", "nodes")
 | 
									_ = tx.Migrator().RenameTable("machines", "nodes")
 | 
				
			||||||
	_ = dbConn.Migrator().RenameColumn(&types.Route{}, "machine_id", "node_id")
 | 
									_ = tx.Migrator().RenameColumn(&types.Route{}, "machine_id", "node_id")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = dbConn.AutoMigrate(types.User{})
 | 
									err = tx.AutoMigrate(types.User{})
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ = dbConn.Migrator().RenameColumn(&types.Node{}, "namespace_id", "user_id")
 | 
									_ = tx.Migrator().RenameColumn(&types.Node{}, "namespace_id", "user_id")
 | 
				
			||||||
	_ = dbConn.Migrator().RenameColumn(&types.PreAuthKey{}, "namespace_id", "user_id")
 | 
									_ = tx.Migrator().RenameColumn(&types.PreAuthKey{}, "namespace_id", "user_id")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ = dbConn.Migrator().RenameColumn(&types.Node{}, "ip_address", "ip_addresses")
 | 
									_ = tx.Migrator().RenameColumn(&types.Node{}, "ip_address", "ip_addresses")
 | 
				
			||||||
	_ = dbConn.Migrator().RenameColumn(&types.Node{}, "name", "hostname")
 | 
									_ = tx.Migrator().RenameColumn(&types.Node{}, "name", "hostname")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// GivenName is used as the primary source of DNS names, make sure
 | 
									// GivenName is used as the primary source of DNS names, make sure
 | 
				
			||||||
				// the field is populated and normalized if it was not when the
 | 
									// the field is populated and normalized if it was not when the
 | 
				
			||||||
				// node was registered.
 | 
									// node was registered.
 | 
				
			||||||
	_ = dbConn.Migrator().RenameColumn(&types.Node{}, "nickname", "given_name")
 | 
									_ = tx.Migrator().RenameColumn(&types.Node{}, "nickname", "given_name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// If the Node table has a column for registered,
 | 
									// If the Node table has a column for registered,
 | 
				
			||||||
				// find all occourences of "false" and drop them. Then
 | 
									// find all occourences of "false" and drop them. Then
 | 
				
			||||||
				// remove the column.
 | 
									// remove the column.
 | 
				
			||||||
	if dbConn.Migrator().HasColumn(&types.Node{}, "registered") {
 | 
									if tx.Migrator().HasColumn(&types.Node{}, "registered") {
 | 
				
			||||||
					log.Info().
 | 
										log.Info().
 | 
				
			||||||
						Msg(`Database has legacy "registered" column in node, removing...`)
 | 
											Msg(`Database has legacy "registered" column in node, removing...`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					nodes := types.Nodes{}
 | 
										nodes := types.Nodes{}
 | 
				
			||||||
		if err := dbConn.Not("registered").Find(&nodes).Error; err != nil {
 | 
										if err := tx.Not("registered").Find(&nodes).Error; err != nil {
 | 
				
			||||||
						log.Error().Err(err).Msg("Error accessing db")
 | 
											log.Error().Err(err).Msg("Error accessing db")
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -117,7 +113,7 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
							Str("node", node.Hostname).
 | 
												Str("node", node.Hostname).
 | 
				
			||||||
							Str("machine_key", node.MachineKey.ShortString()).
 | 
												Str("machine_key", node.MachineKey.ShortString()).
 | 
				
			||||||
							Msg("Deleting unregistered node")
 | 
												Msg("Deleting unregistered node")
 | 
				
			||||||
			if err := dbConn.Delete(&types.Node{}, node.ID).Error; err != nil {
 | 
											if err := tx.Delete(&types.Node{}, node.ID).Error; err != nil {
 | 
				
			||||||
							log.Error().
 | 
												log.Error().
 | 
				
			||||||
								Err(err).
 | 
													Err(err).
 | 
				
			||||||
								Str("node", node.Hostname).
 | 
													Str("node", node.Hostname).
 | 
				
			||||||
@ -126,20 +122,20 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err := dbConn.Migrator().DropColumn(&types.Node{}, "registered")
 | 
										err := tx.Migrator().DropColumn(&types.Node{}, "registered")
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						log.Error().Err(err).Msg("Error dropping registered column")
 | 
											log.Error().Err(err).Msg("Error dropping registered column")
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = dbConn.AutoMigrate(&types.Route{})
 | 
									err = tx.AutoMigrate(&types.Route{})
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = dbConn.AutoMigrate(&types.Node{})
 | 
									err = tx.AutoMigrate(&types.Node{})
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Ensure all keys have correct prefixes
 | 
									// Ensure all keys have correct prefixes
 | 
				
			||||||
@ -151,9 +147,9 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
					DiscoKey   string
 | 
										DiscoKey   string
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				var results []result
 | 
									var results []result
 | 
				
			||||||
	err = db.db.Raw("SELECT id, node_key, machine_key, disco_key FROM nodes").Find(&results).Error
 | 
									err = tx.Raw("SELECT id, node_key, machine_key, disco_key FROM nodes").Find(&results).Error
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for _, node := range results {
 | 
									for _, node := range results {
 | 
				
			||||||
@ -171,7 +167,7 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
						dKey = "discokey:" + node.DiscoKey
 | 
											dKey = "discokey:" + node.DiscoKey
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err := db.db.Exec(
 | 
										err := tx.Exec(
 | 
				
			||||||
						"UPDATE nodes SET machine_key = @mKey, node_key = @nKey, disco_key = @dKey WHERE ID = @id",
 | 
											"UPDATE nodes SET machine_key = @mKey, node_key = @nKey, disco_key = @dKey WHERE ID = @id",
 | 
				
			||||||
						sql.Named("mKey", mKey),
 | 
											sql.Named("mKey", mKey),
 | 
				
			||||||
						sql.Named("nKey", nKey),
 | 
											sql.Named("nKey", nKey),
 | 
				
			||||||
@ -179,11 +175,11 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
						sql.Named("id", node.ID),
 | 
											sql.Named("id", node.ID),
 | 
				
			||||||
					).Error
 | 
										).Error
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
			return nil, err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if dbConn.Migrator().HasColumn(&types.Node{}, "enabled_routes") {
 | 
									if tx.Migrator().HasColumn(&types.Node{}, "enabled_routes") {
 | 
				
			||||||
					log.Info().Msgf("Database has legacy enabled_routes column in node, migrating...")
 | 
										log.Info().Msgf("Database has legacy enabled_routes column in node, migrating...")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					type NodeAux struct {
 | 
										type NodeAux struct {
 | 
				
			||||||
@ -192,7 +188,7 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					nodesAux := []NodeAux{}
 | 
										nodesAux := []NodeAux{}
 | 
				
			||||||
		err := dbConn.Table("nodes").Select("id, enabled_routes").Scan(&nodesAux).Error
 | 
										err := tx.Table("nodes").Select("id, enabled_routes").Scan(&nodesAux).Error
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						log.Fatal().Err(err).Msg("Error accessing db")
 | 
											log.Fatal().Err(err).Msg("Error accessing db")
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@ -207,7 +203,7 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
								continue
 | 
													continue
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				err = dbConn.Preload("Node").
 | 
												err = tx.Preload("Node").
 | 
				
			||||||
								Where("node_id = ? AND prefix = ?", node.ID, types.IPPrefix(prefix)).
 | 
													Where("node_id = ? AND prefix = ?", node.ID, types.IPPrefix(prefix)).
 | 
				
			||||||
								First(&types.Route{}).
 | 
													First(&types.Route{}).
 | 
				
			||||||
								Error
 | 
													Error
 | 
				
			||||||
@ -225,7 +221,7 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
								Enabled:    true,
 | 
													Enabled:    true,
 | 
				
			||||||
								Prefix:     types.IPPrefix(prefix),
 | 
													Prefix:     types.IPPrefix(prefix),
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
				if err := dbConn.Create(&route).Error; err != nil {
 | 
												if err := tx.Create(&route).Error; err != nil {
 | 
				
			||||||
								log.Error().Err(err).Msg("Error creating route")
 | 
													log.Error().Err(err).Msg("Error creating route")
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								log.Info().
 | 
													log.Info().
 | 
				
			||||||
@ -236,15 +232,15 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = dbConn.Migrator().DropColumn(&types.Node{}, "enabled_routes")
 | 
										err = tx.Migrator().DropColumn(&types.Node{}, "enabled_routes")
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						log.Error().Err(err).Msg("Error dropping enabled_routes column")
 | 
											log.Error().Err(err).Msg("Error dropping enabled_routes column")
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if dbConn.Migrator().HasColumn(&types.Node{}, "given_name") {
 | 
									if tx.Migrator().HasColumn(&types.Node{}, "given_name") {
 | 
				
			||||||
					nodes := types.Nodes{}
 | 
										nodes := types.Nodes{}
 | 
				
			||||||
		if err := dbConn.Find(&nodes).Error; err != nil {
 | 
										if err := tx.Find(&nodes).Error; err != nil {
 | 
				
			||||||
						log.Error().Err(err).Msg("Error accessing db")
 | 
											log.Error().Err(err).Msg("Error accessing db")
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -261,7 +257,9 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
									Msg("Failed to normalize node hostname in DB migration")
 | 
														Msg("Failed to normalize node hostname in DB migration")
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				err = db.RenameNode(nodes[item], normalizedHostname)
 | 
												err = tx.Model(nodes[item]).Updates(types.Node{
 | 
				
			||||||
 | 
													GivenName: normalizedHostname,
 | 
				
			||||||
 | 
												}).Error
 | 
				
			||||||
							if err != nil {
 | 
												if err != nil {
 | 
				
			||||||
								log.Error().
 | 
													log.Error().
 | 
				
			||||||
									Caller().
 | 
														Caller().
 | 
				
			||||||
@ -273,30 +271,58 @@ func NewHeadscaleDatabase(
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = dbConn.AutoMigrate(&KV{})
 | 
									err = tx.AutoMigrate(&KV{})
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = dbConn.AutoMigrate(&types.PreAuthKey{})
 | 
									err = tx.AutoMigrate(&types.PreAuthKey{})
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = dbConn.AutoMigrate(&types.PreAuthKeyACLTag{})
 | 
									err = tx.AutoMigrate(&types.PreAuthKeyACLTag{})
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ = dbConn.Migrator().DropTable("shared_machines")
 | 
									_ = tx.Migrator().DropTable("shared_machines")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = dbConn.AutoMigrate(&types.APIKey{})
 | 
									err = tx.AutoMigrate(&types.APIKey{})
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
		return nil, err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO(kradalby): is this needed?
 | 
									return nil
 | 
				
			||||||
	err = db.setValue("db_version", dbVersion)
 | 
								},
 | 
				
			||||||
 | 
								Rollback: func(tx *gorm.DB) error {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// drop key-value table, it is not used, and has not contained
 | 
				
			||||||
 | 
								// useful data for a long time or ever.
 | 
				
			||||||
 | 
								ID: "202312101430",
 | 
				
			||||||
 | 
								Migrate: func(tx *gorm.DB) error {
 | 
				
			||||||
 | 
									return tx.Migrator().DropTable("kvs")
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Rollback: func(tx *gorm.DB) error {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = migrations.Migrate(); err != nil {
 | 
				
			||||||
 | 
							log.Fatal().Err(err).Msgf("Migration failed: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						db := HSDatabase{
 | 
				
			||||||
 | 
							db:       dbConn,
 | 
				
			||||||
 | 
							notifier: notifier,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipPrefixes: ipPrefixes,
 | 
				
			||||||
 | 
							baseDomain: baseDomain,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &db, err
 | 
						return &db, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -347,39 +373,6 @@ func openDB(dbType, connectionAddr string, debug bool) (*gorm.DB, error) {
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getValue returns the value for the given key in KV.
 | 
					 | 
				
			||||||
func (hsdb *HSDatabase) getValue(key string) (string, error) {
 | 
					 | 
				
			||||||
	var row KV
 | 
					 | 
				
			||||||
	if result := hsdb.db.First(&row, "key = ?", key); errors.Is(
 | 
					 | 
				
			||||||
		result.Error,
 | 
					 | 
				
			||||||
		gorm.ErrRecordNotFound,
 | 
					 | 
				
			||||||
	) {
 | 
					 | 
				
			||||||
		return "", errValueNotFound
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return row.Value, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// setValue sets value for the given key in KV.
 | 
					 | 
				
			||||||
func (hsdb *HSDatabase) setValue(key string, value string) error {
 | 
					 | 
				
			||||||
	keyValue := KV{
 | 
					 | 
				
			||||||
		Key:   key,
 | 
					 | 
				
			||||||
		Value: value,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, err := hsdb.getValue(key); err == nil {
 | 
					 | 
				
			||||||
		hsdb.db.Model(&keyValue).Where("key = ?", key).Update("value", value)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := hsdb.db.Create(keyValue).Error; err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("failed to create key value pair in the database: %w", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (hsdb *HSDatabase) PingDB(ctx context.Context) error {
 | 
					func (hsdb *HSDatabase) PingDB(ctx context.Context) error {
 | 
				
			||||||
	ctx, cancel := context.WithTimeout(ctx, time.Second)
 | 
						ctx, cancel := context.WithTimeout(ctx, time.Second)
 | 
				
			||||||
	defer cancel()
 | 
						defer cancel()
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user