mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-09 14:50:56 +00:00
Merge pull request #532 from AudriusButkevicius/config
Replace NodeConfiguration with RepositoryNodeConfiguration (Fixes #522)
This commit is contained in:
commit
52219c5f3f
@ -303,7 +303,7 @@ func main() {
|
|||||||
{
|
{
|
||||||
ID: "default",
|
ID: "default",
|
||||||
Directory: defaultRepo,
|
Directory: defaultRepo,
|
||||||
Nodes: []config.NodeConfiguration{{NodeID: myID}},
|
Nodes: []config.RepositoryNodeConfiguration{{NodeID: myID}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cfg.Nodes = []config.NodeConfiguration{
|
cfg.Nodes = []config.NodeConfiguration{
|
||||||
|
@ -31,13 +31,13 @@ type Configuration struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RepositoryConfiguration struct {
|
type RepositoryConfiguration struct {
|
||||||
ID string `xml:"id,attr"`
|
ID string `xml:"id,attr"`
|
||||||
Directory string `xml:"directory,attr"`
|
Directory string `xml:"directory,attr"`
|
||||||
Nodes []NodeConfiguration `xml:"node"`
|
Nodes []RepositoryNodeConfiguration `xml:"node"`
|
||||||
ReadOnly bool `xml:"ro,attr"`
|
ReadOnly bool `xml:"ro,attr"`
|
||||||
IgnorePerms bool `xml:"ignorePerms,attr"`
|
IgnorePerms bool `xml:"ignorePerms,attr"`
|
||||||
Invalid string `xml:"-"` // Set at runtime when there is an error, not saved
|
Invalid string `xml:"-"` // Set at runtime when there is an error, not saved
|
||||||
Versioning VersioningConfiguration `xml:"versioning"`
|
Versioning VersioningConfiguration `xml:"versioning"`
|
||||||
|
|
||||||
nodeIDs []protocol.NodeID
|
nodeIDs []protocol.NodeID
|
||||||
}
|
}
|
||||||
@ -100,6 +100,13 @@ type NodeConfiguration struct {
|
|||||||
CertName string `xml:"certName,attr,omitempty"`
|
CertName string `xml:"certName,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RepositoryNodeConfiguration struct {
|
||||||
|
NodeID protocol.NodeID `xml:"id,attr"`
|
||||||
|
|
||||||
|
Deprecated_Name string `xml:"name,attr,omitempty" json:"-"`
|
||||||
|
Deprecated_Addresses []string `xml:"address,omitempty" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
type OptionsConfiguration struct {
|
type OptionsConfiguration struct {
|
||||||
ListenAddress []string `xml:"listenAddress" default:"0.0.0.0:22000"`
|
ListenAddress []string `xml:"listenAddress" default:"0.0.0.0:22000"`
|
||||||
GlobalAnnServer string `xml:"globalAnnounceServer" default:"announce.syncthing.net:22026"`
|
GlobalAnnServer string `xml:"globalAnnounceServer" default:"announce.syncthing.net:22026"`
|
||||||
@ -311,6 +318,11 @@ func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) {
|
|||||||
convertV2V3(&cfg)
|
convertV2V3(&cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upgrade to v4 configuration if appropriate
|
||||||
|
if cfg.Version == 3 {
|
||||||
|
convertV3V4(&cfg)
|
||||||
|
}
|
||||||
|
|
||||||
// Hash old cleartext passwords
|
// Hash old cleartext passwords
|
||||||
if len(cfg.GUI.Password) > 0 && cfg.GUI.Password[0] != '$' {
|
if len(cfg.GUI.Password) > 0 && cfg.GUI.Password[0] != '$' {
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(cfg.GUI.Password), 0)
|
hash, err := bcrypt.GenerateFromPassword([]byte(cfg.GUI.Password), 0)
|
||||||
@ -329,15 +341,22 @@ func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure this node is present in all relevant places
|
// Ensure this node is present in all relevant places
|
||||||
|
me := cfg.GetNodeConfiguration(myID)
|
||||||
|
if me == nil {
|
||||||
|
myName, _ := os.Hostname()
|
||||||
|
cfg.Nodes = append(cfg.Nodes, NodeConfiguration{
|
||||||
|
NodeID: myID,
|
||||||
|
Name: myName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sort.Sort(NodeConfigurationList(cfg.Nodes))
|
||||||
// Ensure that any loose nodes are not present in the wrong places
|
// Ensure that any loose nodes are not present in the wrong places
|
||||||
// Ensure that there are no duplicate nodes
|
// Ensure that there are no duplicate nodes
|
||||||
cfg.Nodes = ensureNodePresent(cfg.Nodes, myID)
|
|
||||||
sort.Sort(NodeConfigurationList(cfg.Nodes))
|
|
||||||
for i := range cfg.Repositories {
|
for i := range cfg.Repositories {
|
||||||
cfg.Repositories[i].Nodes = ensureNodePresent(cfg.Repositories[i].Nodes, myID)
|
cfg.Repositories[i].Nodes = ensureNodePresent(cfg.Repositories[i].Nodes, myID)
|
||||||
cfg.Repositories[i].Nodes = ensureExistingNodes(cfg.Repositories[i].Nodes, existingNodes)
|
cfg.Repositories[i].Nodes = ensureExistingNodes(cfg.Repositories[i].Nodes, existingNodes)
|
||||||
cfg.Repositories[i].Nodes = ensureNoDuplicates(cfg.Repositories[i].Nodes)
|
cfg.Repositories[i].Nodes = ensureNoDuplicates(cfg.Repositories[i].Nodes)
|
||||||
sort.Sort(NodeConfigurationList(cfg.Repositories[i].Nodes))
|
sort.Sort(RepositoryNodeConfigurationList(cfg.Repositories[i].Nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// An empty address list is equivalent to a single "dynamic" entry
|
// An empty address list is equivalent to a single "dynamic" entry
|
||||||
@ -351,6 +370,21 @@ func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) {
|
|||||||
return cfg, err
|
return cfg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertV3V4(cfg *Configuration) {
|
||||||
|
// In previous versions, repositories held full node configurations.
|
||||||
|
// Since that's the only place where node configs were in V1, we still have
|
||||||
|
// to define the deprecated fields to be able to upgrade from V1 to V4.
|
||||||
|
for i, repo := range cfg.Repositories {
|
||||||
|
for j := range repo.Nodes {
|
||||||
|
rncfg := cfg.Repositories[i].Nodes[j]
|
||||||
|
rncfg.Deprecated_Name = ""
|
||||||
|
rncfg.Deprecated_Addresses = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.Version = 4
|
||||||
|
}
|
||||||
|
|
||||||
func convertV2V3(cfg *Configuration) {
|
func convertV2V3(cfg *Configuration) {
|
||||||
// In previous versions, compression was always on. When upgrading, enable
|
// In previous versions, compression was always on. When upgrading, enable
|
||||||
// compression on all existing new. New nodes will get compression on by
|
// compression on all existing new. New nodes will get compression on by
|
||||||
@ -372,7 +406,7 @@ func convertV1V2(cfg *Configuration) {
|
|||||||
// Collect the list of nodes.
|
// Collect the list of nodes.
|
||||||
// Replace node configs inside repositories with only a reference to the nide ID.
|
// Replace node configs inside repositories with only a reference to the nide ID.
|
||||||
// Set all repositories to read only if the global read only flag is set.
|
// Set all repositories to read only if the global read only flag is set.
|
||||||
var nodes = map[string]NodeConfiguration{}
|
var nodes = map[string]RepositoryNodeConfiguration{}
|
||||||
for i, repo := range cfg.Repositories {
|
for i, repo := range cfg.Repositories {
|
||||||
cfg.Repositories[i].ReadOnly = cfg.Options.Deprecated_ReadOnly
|
cfg.Repositories[i].ReadOnly = cfg.Options.Deprecated_ReadOnly
|
||||||
for j, node := range repo.Nodes {
|
for j, node := range repo.Nodes {
|
||||||
@ -380,14 +414,18 @@ func convertV1V2(cfg *Configuration) {
|
|||||||
if _, ok := nodes[id]; !ok {
|
if _, ok := nodes[id]; !ok {
|
||||||
nodes[id] = node
|
nodes[id] = node
|
||||||
}
|
}
|
||||||
cfg.Repositories[i].Nodes[j] = NodeConfiguration{NodeID: node.NodeID}
|
cfg.Repositories[i].Nodes[j] = RepositoryNodeConfiguration{NodeID: node.NodeID}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.Options.Deprecated_ReadOnly = false
|
cfg.Options.Deprecated_ReadOnly = false
|
||||||
|
|
||||||
// Set and sort the list of nodes.
|
// Set and sort the list of nodes.
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
cfg.Nodes = append(cfg.Nodes, node)
|
cfg.Nodes = append(cfg.Nodes, NodeConfiguration{
|
||||||
|
NodeID: node.NodeID,
|
||||||
|
Name: node.Deprecated_Name,
|
||||||
|
Addresses: node.Deprecated_Addresses,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
sort.Sort(NodeConfigurationList(cfg.Nodes))
|
sort.Sort(NodeConfigurationList(cfg.Nodes))
|
||||||
|
|
||||||
@ -412,23 +450,33 @@ func (l NodeConfigurationList) Len() int {
|
|||||||
return len(l)
|
return len(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureNodePresent(nodes []NodeConfiguration, myID protocol.NodeID) []NodeConfiguration {
|
type RepositoryNodeConfigurationList []RepositoryNodeConfiguration
|
||||||
|
|
||||||
|
func (l RepositoryNodeConfigurationList) Less(a, b int) bool {
|
||||||
|
return l[a].NodeID.Compare(l[b].NodeID) == -1
|
||||||
|
}
|
||||||
|
func (l RepositoryNodeConfigurationList) Swap(a, b int) {
|
||||||
|
l[a], l[b] = l[b], l[a]
|
||||||
|
}
|
||||||
|
func (l RepositoryNodeConfigurationList) Len() int {
|
||||||
|
return len(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureNodePresent(nodes []RepositoryNodeConfiguration, myID protocol.NodeID) []RepositoryNodeConfiguration {
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
if node.NodeID.Equals(myID) {
|
if node.NodeID.Equals(myID) {
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name, _ := os.Hostname()
|
nodes = append(nodes, RepositoryNodeConfiguration{
|
||||||
nodes = append(nodes, NodeConfiguration{
|
|
||||||
NodeID: myID,
|
NodeID: myID,
|
||||||
Name: name,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureExistingNodes(nodes []NodeConfiguration, existingNodes map[protocol.NodeID]bool) []NodeConfiguration {
|
func ensureExistingNodes(nodes []RepositoryNodeConfiguration, existingNodes map[protocol.NodeID]bool) []RepositoryNodeConfiguration {
|
||||||
count := len(nodes)
|
count := len(nodes)
|
||||||
i := 0
|
i := 0
|
||||||
loop:
|
loop:
|
||||||
@ -443,7 +491,7 @@ loop:
|
|||||||
return nodes[0:count]
|
return nodes[0:count]
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureNoDuplicates(nodes []NodeConfiguration) []NodeConfiguration {
|
func ensureNoDuplicates(nodes []RepositoryNodeConfiguration) []RepositoryNodeConfiguration {
|
||||||
count := len(nodes)
|
count := len(nodes)
|
||||||
i := 0
|
i := 0
|
||||||
seenNodes := make(map[protocol.NodeID]bool)
|
seenNodes := make(map[protocol.NodeID]bool)
|
||||||
|
@ -106,7 +106,21 @@ func TestNodeConfig(t *testing.T) {
|
|||||||
</node>
|
</node>
|
||||||
</configuration>`)
|
</configuration>`)
|
||||||
|
|
||||||
for i, data := range [][]byte{v1data, v2data, v3data} {
|
v4data := []byte(`
|
||||||
|
<configuration version="4">
|
||||||
|
<repository id="test" directory="~/Sync" ro="true" ignorePerms="false">
|
||||||
|
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></node>
|
||||||
|
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></node>
|
||||||
|
</repository>
|
||||||
|
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="true">
|
||||||
|
<address>a</address>
|
||||||
|
</node>
|
||||||
|
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="true">
|
||||||
|
<address>b</address>
|
||||||
|
</node>
|
||||||
|
</configuration>`)
|
||||||
|
|
||||||
|
for i, data := range [][]byte{v1data, v2data, v3data, v4data} {
|
||||||
cfg, err := Load(bytes.NewReader(data), node1)
|
cfg, err := Load(bytes.NewReader(data), node1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@ -116,7 +130,7 @@ func TestNodeConfig(t *testing.T) {
|
|||||||
{
|
{
|
||||||
ID: "test",
|
ID: "test",
|
||||||
Directory: "~/Sync",
|
Directory: "~/Sync",
|
||||||
Nodes: []NodeConfiguration{{NodeID: node1}, {NodeID: node4}},
|
Nodes: []RepositoryNodeConfiguration{{NodeID: node1}, {NodeID: node4}},
|
||||||
ReadOnly: true,
|
ReadOnly: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -136,7 +150,7 @@ func TestNodeConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
expectedNodeIDs := []protocol.NodeID{node1, node4}
|
expectedNodeIDs := []protocol.NodeID{node1, node4}
|
||||||
|
|
||||||
if cfg.Version != 3 {
|
if cfg.Version != 4 {
|
||||||
t.Errorf("%d: Incorrect version %d != 3", i, cfg.Version)
|
t.Errorf("%d: Incorrect version %d != 3", i, cfg.Version)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(cfg.Repositories, expectedRepos) {
|
if !reflect.DeepEqual(cfg.Repositories, expectedRepos) {
|
||||||
|
Loading…
Reference in New Issue
Block a user