diff --git a/fs-repo-9-to-10/migration/config_conv.go b/fs-repo-9-to-10/migration/config_conv.go index b1811749..92d976bb 100644 --- a/fs-repo-9-to-10/migration/config_conv.go +++ b/fs-repo-9-to-10/migration/config_conv.go @@ -83,6 +83,170 @@ func convert(in io.Reader, out io.Writer, convBootstrap convArray, convAddresses return err } +// Convert Routing.Type to implicit default +// https://github.com/ipfs/kubo/pull/9475 +func convertRouting(confMap map[string]interface{}) { + routing, _ := confMap["Routing"].(map[string]interface{}) + if routing == nil { + log.Log("No Routing field in config, skipping") + return + } + + rType, ok := routing["Type"].(string) + if !ok { + log.Log("No Routing.Type field in config, skipping") + return + } + if rType == "dht" || rType == "" { + delete(routing, "Type") + } else { + log.Log("Routing.Type settings is different than the old default, skipping") + } +} +func undoRouting(confMap map[string]interface{}) { + routing, ok := confMap["Routing"].(map[string]interface{}) + if routing == nil { + log.Log("No Routing field in config, skipping") + return + } + + t, ok := routing["Type"].(string) + if !ok || t == "" { + routing["Type"] = "dht" + } else { + log.Log("Custom Routing.Type settings, skipping") + } +} + +// Convert Reprovider to implicit defaults +// https://github.com/ipfs/kubo/pull/9326 +func convertReprovider(confMap map[string]interface{}) { + reprovider, _ := confMap["Reprovider"].(map[string]interface{}) + if reprovider == nil { + log.Log("No Reprovider field in config, skipping") + return + } + + interval, ok := reprovider["Interval"].(string) + if !ok { + log.Log("No Reprovider.Interval field in config, skipping") + return + } + if interval == "12h" { + delete(reprovider, "Interval") + } else { + log.Log("Reprovider.Interval settings is different than the old default, skipping") + } + + strategy, ok := reprovider["Strategy"].(string) + if !ok { + log.Log("No Reprovider.Strategy field in config, skipping") + return + } + if strategy == "all" { + delete(reprovider, "Strategy") + } else { + log.Log("Reprovider.Strategy settings is different than the old default, skipping") + } +} +func undoReprovider(confMap map[string]interface{}) { + reprovider, _ := confMap["Reprovider"].(map[string]interface{}) + if reprovider == nil { + log.Log("No Reprovider field in config, skipping") + return + } + + _, ok := reprovider["Interval"].(string) + if !ok { + reprovider["Interval"] = "12h" + } else { + log.Log("Custom Reprovider.Interval settings present, skipping") + } + + _, ok = reprovider["Strategy"].(string) + if !ok { + reprovider["Strategy"] = "all" + } else { + log.Log("Custom Reprovider.Strategy settings present, skipping") + } +} + +// Convert Swarm.ConnMgr to implicit defaults +// https://github.com/ipfs/kubo/pull/9467 +func convertConnMgr(confMap map[string]interface{}) { + swarm, _ := confMap["Swarm"].(map[string]interface{}) + if swarm == nil { + log.Log("No Swarm field in config, skipping") + return + } + connmgr, _ := swarm["ConnMgr"].(map[string]interface{}) + if connmgr == nil { + log.Log("No Swarm.ConnMgr field in config, skipping") + return + } + cmType, ok := connmgr["Type"].(string) + if !ok { + log.Log("No Swarm.ConnMgr.Type field in config, skipping") + return + } + cmLowWater, ok := connmgr["LowWater"].(float64) + if !ok { + log.Log("No Swarm.ConnMgr.LowWater field in config, skipping") + return + } + cmHighWater, ok := connmgr["HighWater"].(float64) + if !ok { + log.Log("No Swarm.ConnMgr.HighWater field in config, skipping") + return + } + cmGrace, ok := connmgr["GracePeriod"].(string) + if !ok { + log.Log("No Swarm.ConnMgr.GracePeriod field in config, skipping") + return + } + + if cmType == "basic" && + int(cmLowWater) == 600 && + int(cmHighWater) == 900 && + cmGrace == "20s" { + // remove defaults from config, switch user to implicit ones + delete(connmgr, "Type") + delete(connmgr, "LowWater") + delete(connmgr, "HighWater") + delete(connmgr, "GracePeriod") + } else { + log.Log("Swarm.ConnMgr settings are different than the old defaults, skipping") + } +} +func undoConnMgr(confMap map[string]interface{}) { + swarm, _ := confMap["Swarm"].(map[string]interface{}) + if swarm == nil { + log.Log("No Swarm field in config, skipping") + return + } + connmgr, _ := swarm["ConnMgr"].(map[string]interface{}) + if connmgr == nil { + log.Log("No Swarm.ConnMgr field in config, skipping") + return + } + _, ok := connmgr["Type"].(string) + if !ok { + connmgr["Type"] = "basic" + } + _, ok = connmgr["LowWater"].(float64) + if !ok { + connmgr["LowWater"] = 600 + } + _, ok = connmgr["HighWater"].(float64) + if !ok { + connmgr["HighWater"] = 900 + } + _, ok = connmgr["GracePeriod"].(string) + if !ok { + connmgr["GracePeriod"] = "20s" + } +} + // Convert Bootstrap addresses to/from QUIC func convertBootstrap(confMap map[string]interface{}, conv convArray) { bootstrapi, _ := confMap["Bootstrap"].([]interface{}) diff --git a/fs-repo-9-to-10/migration/kubo18_test.go b/fs-repo-9-to-10/migration/kubo18_test.go new file mode 100644 index 00000000..fd0b94e6 --- /dev/null +++ b/fs-repo-9-to-10/migration/kubo18_test.go @@ -0,0 +1,114 @@ +package mg9 + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "strings" + "testing" +) + +var beforeConfig = `{ + "Reprovider": { + "Interval": "12h", + "Strategy": "all" + }, + "Routing": { + "Methods": {}, + "Routers": {}, + "Type": "dht" + }, + "Swarm": { + "ConnMgr": { + "GracePeriod": "20s", + "HighWater": 900, + "LowWater": 600, + "Type": "basic" + } + } +}` + +var afterConfig = `{ + "Reprovider": {}, + "Routing": { + "Methods": {}, + "Routers": {} + }, + "Swarm": { + "ConnMgr": {} + } +}` + +func TestKubo18Migration(t *testing.T) { + out := new(bytes.Buffer) + + data, err := ioutil.ReadAll(strings.NewReader(beforeConfig)) + if err != nil { + t.Fatal(err) + } + + confMap := make(map[string]interface{}) + if err = json.Unmarshal(data, &confMap); err != nil { + t.Fatal(err) + } + + // Kubo 0.18 + convertRouting(confMap) + convertReprovider(confMap) + convertConnMgr(confMap) + + fixed, err := json.MarshalIndent(confMap, "", " ") + if err != nil { + t.Fatal(err) + } + + if _, err := out.Write(fixed); err != nil { + t.Fatal(err) + } + _, err = out.Write([]byte("\n")) + if err != nil { + t.Fatal(err) + } + + forward := out.String() + if noSpace(forward) != noSpace(afterConfig) { + t.Fatalf("Mismatch\nConversion produced:\n%s\nExpected:\n%s\n", forward, afterConfig) + } +} + +func TestKubo18MigrationReversal(t *testing.T) { + out := new(bytes.Buffer) + + data, err := ioutil.ReadAll(strings.NewReader(afterConfig)) + if err != nil { + t.Fatal(err) + } + + confMap := make(map[string]interface{}) + if err = json.Unmarshal(data, &confMap); err != nil { + t.Fatal(err) + } + + // Kubo 0.18 + undoRouting(confMap) + undoReprovider(confMap) + undoConnMgr(confMap) + + fixed, err := json.MarshalIndent(confMap, "", " ") + if err != nil { + t.Fatal(err) + } + + if _, err := out.Write(fixed); err != nil { + t.Fatal(err) + } + _, err = out.Write([]byte("\n")) + if err != nil { + t.Fatal(err) + } + + undone := out.String() + if noSpace(undone) != noSpace(beforeConfig) { + t.Fatalf("Mismatch\nConversion produced:\n%s\nExpected:\n%s\n", undone, beforeConfig) + } +}