From 1f5963919f0140fbc25913b58b02f04a0828666e Mon Sep 17 00:00:00 2001 From: Humble Chirammal Date: Thu, 16 Sep 2021 11:04:06 +0530 Subject: [PATCH] util: get clusterID for the passed in mon string as part of migration support, the clusterID has to be fetched from passed in mon. Because the intree RBD storage class only got monitor and not `clusterID` parameter support. However, in CSI, SC has the `clusterID` parameter support but not mon. Due to that we have to fetch the clusterID from config file for the passed in mon and use it in our operations. This adds a helper function to retrieve clusterID from passed in mon string. Updates https://github.com/ceph/ceph-csi/issues/2509 Signed-off-by: Humble Chirammal --- internal/util/csiconfig.go | 41 +++++++++++++++++++++++++++++++++ internal/util/csiconfig_test.go | 40 +++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/internal/util/csiconfig.go b/internal/util/csiconfig.go index c19525e3c..238aeead4 100644 --- a/internal/util/csiconfig.go +++ b/internal/util/csiconfig.go @@ -161,3 +161,44 @@ func GetClusterID(options map[string]string) (string, error) { return clusterID, nil } + +// GetClusterIDFromMon will be called with a mon string to fetch +// clusterID based on the passed in mon string. If passed in 'mon' +// string has been found in the config the clusterID is returned, +// else error. +func GetClusterIDFromMon(mon string) (string, error) { + clusterID, err := readClusterInfoWithMon(CsiConfigFile, mon) + if err != nil { + return "", err + } + + return clusterID, nil +} + +func readClusterInfoWithMon(pathToConfig, mon string) (string, error) { + var config []ClusterInfo + + // #nosec + content, err := ioutil.ReadFile(pathToConfig) + if err != nil { + err = fmt.Errorf("error fetching configuration file %q: %w", pathToConfig, err) + + return "", err + } + + err = json.Unmarshal(content, &config) + if err != nil { + return "", fmt.Errorf("unmarshal failed (%w), raw buffer response: %s", + err, string(content)) + } + + for _, cluster := range config { + for _, m := range cluster.Monitors { + if m == mon { + return cluster.ClusterID, nil + } + } + } + + return "", fmt.Errorf("missing configuration of cluster ID for mon %q", mon) +} diff --git a/internal/util/csiconfig_test.go b/internal/util/csiconfig_test.go index 81dabfcd8..b0cd98a5e 100644 --- a/internal/util/csiconfig_test.go +++ b/internal/util/csiconfig_test.go @@ -34,7 +34,7 @@ func cleanupTestData() { os.RemoveAll(basePath) } -// TODO: make this function less complex. +// nolint:gocyclo,cyclop // TODO: make this function less complex. func TestCSIConfig(t *testing.T) { t.Parallel() var err error @@ -132,4 +132,42 @@ func TestCSIConfig(t *testing.T) { if err != nil || content != "mon4,mon5,mon6" { t.Errorf("Failed: want (%s), got (%s) (%v)", "mon4,mon5,mon6", content, err) } + + data = "[{\"clusterID\":\"" + clusterID2 + "\",\"monitors\":[\"mon1\",\"mon2\",\"mon3\"]}," + + "{\"clusterID\":\"" + clusterID1 + "\",\"monitors\":[\"mon4\",\"mon5\",\"mon6\"]}]" + err = ioutil.WriteFile(basePath+"/"+csiClusters, []byte(data), 0o600) + if err != nil { + t.Errorf("Test setup error %s", err) + } + + // TEST: Should pass as clusterID is present in config + content, err = readClusterInfoWithMon(pathToConfig, "mon1") + if err != nil || content != "test2" { + t.Errorf("Failed: want (%s), got (%s) (%v)", "test2", content, err) + } + + // TEST: Should pass as clusterID is present in config + content, err = readClusterInfoWithMon(pathToConfig, "mon5") + if err != nil || content != "test1" { + t.Errorf("Failed: want (%s), got (%s) (%v)", "test1", content, err) + } + + // TEST: Should fail as clusterID is not present in config + content, err = readClusterInfoWithMon(pathToConfig, "mon8") + if err == nil { + t.Errorf("Failed: got (%s)", content) + } + + data = "[{\"clusterID\":\"" + clusterID2 + "\", \"radosNamespace\": \"ns1\", \"monitors\":[\"mon1\"]}," + + "{\"clusterID\":\"" + clusterID1 + "\",\"monitors\":[\"mon1\"]}]" + err = ioutil.WriteFile(basePath+"/"+csiClusters, []byte(data), 0o600) + if err != nil { + t.Errorf("Test setup error %s", err) + } + + // TEST: Should pass as clusterID is present in config + content, err = readClusterInfoWithMon(pathToConfig, "mon1") + if err != nil || content != clusterID1 { + t.Errorf("Failed: want (%s), got (%s) (%v)", "test2", content, err) + } }