forked from AdguardTeam/AdGuardHome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
upgrade.go
146 lines (123 loc) · 3.72 KB
/
upgrade.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"gopkg.in/yaml.v2"
)
const currentSchemaVersion = 2 // used for upgrading from old configs to new config
// Performs necessary upgrade operations if needed
func upgradeConfig() error {
// read a config file into an interface map, so we can manipulate values without losing any
configFile := filepath.Join(config.ourBinaryDir, config.ourConfigFilename)
if _, err := os.Stat(configFile); os.IsNotExist(err) {
log.Printf("config file %s does not exist, nothing to upgrade", configFile)
return nil
}
diskConfig := map[string]interface{}{}
body, err := ioutil.ReadFile(configFile)
if err != nil {
log.Printf("Couldn't read config file '%s': %s", configFile, err)
return err
}
err = yaml.Unmarshal(body, &diskConfig)
if err != nil {
log.Printf("Couldn't parse config file '%s': %s", configFile, err)
return err
}
schemaVersionInterface, ok := diskConfig["schema_version"]
log.Printf("%s(): got schema version %v", _Func(), schemaVersionInterface)
if !ok {
// no schema version, set it to 0
schemaVersionInterface = 0
}
schemaVersion, ok := schemaVersionInterface.(int)
if !ok {
err = fmt.Errorf("configuration file contains non-integer schema_version, abort")
log.Println(err)
return err
}
if schemaVersion == currentSchemaVersion {
// do nothing
return nil
}
return upgradeConfigSchema(schemaVersion, &diskConfig)
}
// Upgrade from oldVersion to newVersion
func upgradeConfigSchema(oldVersion int, diskConfig *map[string]interface{}) error {
switch oldVersion {
case 0:
err := upgradeSchema0to2(diskConfig)
if err != nil {
return err
}
case 1:
err := upgradeSchema1to2(diskConfig)
if err != nil {
return err
}
default:
err := fmt.Errorf("configuration file contains unknown schema_version, abort")
log.Println(err)
return err
}
configFile := filepath.Join(config.ourBinaryDir, config.ourConfigFilename)
body, err := yaml.Marshal(diskConfig)
if err != nil {
log.Printf("Couldn't generate YAML file: %s", err)
return err
}
err = safeWriteFile(configFile, body)
if err != nil {
log.Printf("Couldn't save YAML config: %s", err)
return err
}
return nil
}
// The first schema upgrade:
// No more "dnsfilter.txt", filters are now kept in data/filters/
func upgradeSchema0to1(diskConfig *map[string]interface{}) error {
log.Printf("%s(): called", _Func())
dnsFilterPath := filepath.Join(config.ourBinaryDir, "dnsfilter.txt")
if _, err := os.Stat(dnsFilterPath); !os.IsNotExist(err) {
log.Printf("Deleting %s as we don't need it anymore", dnsFilterPath)
err = os.Remove(dnsFilterPath)
if err != nil {
log.Printf("Cannot remove %s due to %s", dnsFilterPath, err)
// not fatal, move on
}
}
(*diskConfig)["schema_version"] = 1
return nil
}
// Second schema upgrade:
// coredns is now dns in config
// delete 'Corefile', since we don't use that anymore
func upgradeSchema1to2(diskConfig *map[string]interface{}) error {
log.Printf("%s(): called", _Func())
coreFilePath := filepath.Join(config.ourBinaryDir, "Corefile")
if _, err := os.Stat(coreFilePath); !os.IsNotExist(err) {
log.Printf("Deleting %s as we don't need it anymore", coreFilePath)
err = os.Remove(coreFilePath)
if err != nil {
log.Printf("Cannot remove %s due to %s", coreFilePath, err)
// not fatal, move on
}
}
if _, ok := (*diskConfig)["dns"]; !ok {
(*diskConfig)["dns"] = (*diskConfig)["coredns"]
delete((*diskConfig), "coredns")
}
(*diskConfig)["schema_version"] = 2
return nil
}
// jump two schemas at once -- this time we just do it sequentially
func upgradeSchema0to2(diskConfig *map[string]interface{}) error {
err := upgradeSchema0to1(diskConfig)
if err != nil {
return err
}
return upgradeSchema1to2(diskConfig)
}