mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-12-25 16:18:16 +03:00
1511fabeec
Squashed commit of the following: commit afb5a0d8a499bccf7761baea40910f39c92b8a20 Merge: 09ac43c85abf20c6de
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Dec 25 12:55:45 2023 +0200 Merge remote-tracking branch 'origin/master' into conf-ups-mode commit 09ac43c859ef8cbd3bb0488d1a945589cd59ca19 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Dec 22 14:36:07 2023 +0200 openapi: imp docs commit d0fbd4349e4bddde73c6e92f75854acfc481ac0d Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Dec 22 11:47:10 2023 +0200 all: changelog commit 105f9c50738733b0736a768fb9ee09d2e7fbf42e Merge: 62a2cf12d4bc5c346a
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Dec 22 11:27:21 2023 +0200 Merge remote-tracking branch 'origin/master' into conf-ups-mode # Conflicts: # openapi/CHANGELOG.md commit 62a2cf12df694611888e840a5041a9c517cdfddb Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Dec 22 10:52:59 2023 +0200 openapi: imp docs commit 87956c49240da44b216489920feff69996e3502b Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Dec 21 12:08:07 2023 +0200 dnsforward: imp code commit bf74d67ad112735d557be3d8fac75964cd99e375 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Dec 20 15:46:38 2023 +0200 dnsforward: imp code commit 3a98dee88809a25118a14a1f07eeecbfccb14cd9 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Dec 20 15:41:06 2023 +0200 dnsforward: imp code commit 1499da1fa0319ac3ad914171e807446f2c4d2fdb Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Dec 20 13:36:28 2023 +0200 dnsforward: imp code commit 228c61a5a0f73cc13655cef8bdaa1995b3f7fced Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Dec 20 13:06:11 2023 +0200 dnsforward: imp code commit 069ee22c6d904db4e983135ce87a9fe8d12b7e9a Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Dec 19 12:39:25 2023 +0200 dnsforward: imp code commit 90919f99a975862dcb07ac82fb740e4404e48bae Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Dec 19 12:10:43 2023 +0200 confmigrate: fix commit a8c329950423b59098d1f2b16d1da7100dd54f8d Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Dec 19 12:08:05 2023 +0200 dnsforward: imp code commit 58b53ccd97d353fab0df29f13425b5e341c8fdeb Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Dec 18 15:10:01 2023 +0200 all: conf upstream mode
137 lines
3.7 KiB
Go
137 lines
3.7 KiB
Go
package configmigrate
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/AdguardTeam/golibs/log"
|
|
yaml "gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// Config is a the configuration for initializing a [Migrator].
|
|
type Config struct {
|
|
// WorkingDir is an absolute path to the working directory of AdGuardHome.
|
|
WorkingDir string
|
|
}
|
|
|
|
// Migrator performs the YAML configuration file migrations.
|
|
type Migrator struct {
|
|
// workingDir is an absolute path to the working directory of AdGuardHome.
|
|
workingDir string
|
|
}
|
|
|
|
// New creates a new Migrator.
|
|
func New(cfg *Config) (m *Migrator) {
|
|
return &Migrator{
|
|
workingDir: cfg.WorkingDir,
|
|
}
|
|
}
|
|
|
|
// Migrate preforms necessary upgrade operations to upgrade file to target
|
|
// schema version, if needed. It returns the body of the upgraded config file,
|
|
// whether the file was upgraded, and an error, if any. If upgraded is false,
|
|
// the body is the same as the input.
|
|
func (m *Migrator) Migrate(body []byte, target uint) (newBody []byte, upgraded bool, err error) {
|
|
diskConf := yobj{}
|
|
err = yaml.Unmarshal(body, &diskConf)
|
|
if err != nil {
|
|
return body, false, fmt.Errorf("parsing config file for upgrade: %w", err)
|
|
}
|
|
|
|
currentInt, _, err := fieldVal[int](diskConf, "schema_version")
|
|
if err != nil {
|
|
// Don't wrap the error, since it's informative enough as is.
|
|
return body, false, err
|
|
}
|
|
|
|
current := uint(currentInt)
|
|
log.Debug("got schema version %v", current)
|
|
|
|
if err = validateVersion(current, target); err != nil {
|
|
// Don't wrap the error, since it's informative enough as is.
|
|
return body, false, err
|
|
} else if current == target {
|
|
return body, false, nil
|
|
}
|
|
|
|
if err = m.upgradeConfigSchema(current, target, diskConf); err != nil {
|
|
// Don't wrap the error, since it's informative enough as is.
|
|
return body, false, err
|
|
}
|
|
|
|
buf := bytes.NewBuffer(newBody)
|
|
enc := yaml.NewEncoder(buf)
|
|
enc.SetIndent(2)
|
|
|
|
if err = enc.Encode(diskConf); err != nil {
|
|
return body, false, fmt.Errorf("generating new config: %w", err)
|
|
}
|
|
|
|
return buf.Bytes(), true, nil
|
|
}
|
|
|
|
// validateVersion validates the current and desired schema versions.
|
|
func validateVersion(current, target uint) (err error) {
|
|
switch {
|
|
case current > target:
|
|
return fmt.Errorf("unknown current schema version %d", current)
|
|
case target > LastSchemaVersion:
|
|
return fmt.Errorf("unknown target schema version %d", target)
|
|
case target < current:
|
|
return fmt.Errorf("target schema version %d lower than current %d", target, current)
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// migrateFunc is a function that upgrades a config and returns an error.
|
|
type migrateFunc = func(diskConf yobj) (err error)
|
|
|
|
// upgradeConfigSchema upgrades the configuration schema in diskConf from
|
|
// current to target version. current must be less than target, and both must
|
|
// be non-negative and less or equal to [LastSchemaVersion].
|
|
func (m *Migrator) upgradeConfigSchema(current, target uint, diskConf yobj) (err error) {
|
|
upgrades := [LastSchemaVersion]migrateFunc{
|
|
0: m.migrateTo1,
|
|
1: m.migrateTo2,
|
|
2: migrateTo3,
|
|
3: migrateTo4,
|
|
4: migrateTo5,
|
|
5: migrateTo6,
|
|
6: migrateTo7,
|
|
7: migrateTo8,
|
|
8: migrateTo9,
|
|
9: migrateTo10,
|
|
10: migrateTo11,
|
|
11: migrateTo12,
|
|
12: migrateTo13,
|
|
13: migrateTo14,
|
|
14: migrateTo15,
|
|
15: migrateTo16,
|
|
16: migrateTo17,
|
|
17: migrateTo18,
|
|
18: migrateTo19,
|
|
19: migrateTo20,
|
|
20: migrateTo21,
|
|
21: migrateTo22,
|
|
22: migrateTo23,
|
|
23: migrateTo24,
|
|
24: migrateTo25,
|
|
25: migrateTo26,
|
|
26: migrateTo27,
|
|
27: migrateTo28,
|
|
}
|
|
|
|
for i, migrate := range upgrades[current:target] {
|
|
cur := current + uint(i)
|
|
next := current + uint(i) + 1
|
|
|
|
log.Printf("Upgrade yaml: %d to %d", cur, next)
|
|
|
|
if err = migrate(diskConf); err != nil {
|
|
return fmt.Errorf("migrating schema %d to %d: %w", cur, next, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|