diff --git a/k8s/core/configmap/configmap.go b/k8s/core/configmap/configmap.go index ed50972b..4747b94b 100644 --- a/k8s/core/configmap/configmap.go +++ b/k8s/core/configmap/configmap.go @@ -1,188 +1,101 @@ package configmap import ( - "fmt" - "strings" "time" - "github.com/portworx/sched-ops/k8s/core" - "github.com/sirupsen/logrus" - corev1 "k8s.io/api/core/v1" - k8s_errors "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" ) -// New returns the ConfigMap interface. It also creates a new -// configmap in k8s for the given name if not present and puts the data in it. -func New( - name string, - data map[string]string, - lockTimeout time.Duration, - lockAttempts uint, - v2LockRefreshDuration time.Duration, - v2LockK8sLockTTL time.Duration, -) (ConfigMap, error) { - if data == nil { - data = make(map[string]string) - } +func (c *configMap) Instance() *coreConfigMap { - labels := map[string]string{ - configMapUserLabelKey: TruncateLabel(name), - } - data[pxOwnerKey] = "" - - cm := &corev1.ConfigMap{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: name, - Namespace: k8sSystemNamespace, - Labels: labels, - }, - Data: data, + if c.pxNs == c.config.nameSpace { + //fresh install ot upgrade completed + return c.config } - if _, err := core.Instance().CreateConfigMap(cm); err != nil && - !k8s_errors.IsAlreadyExists(err) { - return nil, fmt.Errorf("failed to create configmap %v: %v", - name, err) - } + existingConfig := c.config + c.copylock.Lock(uuid.New().String()) + defer c.copylock.Unlock() - if v2LockK8sLockTTL == 0 { - v2LockK8sLockTTL = v2DefaultK8sLockTTL + lockMap, err := c.copylock.get() + if err != nil { + log.Errorf("Error during fetching data from copy lock %s", err) + return existingConfig } + status := lockMap[upgradeCompletedStatus] + if status == trueString { + // upgrade is completed + //create configmap in portworx namespace + newConfig := &coreConfigMap{ + name: existingConfig.name, + defaultLockHoldTimeout: existingConfig.defaultLockHoldTimeout, + kLocksV2: existingConfig.kLocksV2, + lockAttempts: existingConfig.lockAttempts, + lockRefreshDuration: existingConfig.lockRefreshDuration, + lockK8sLockTTL: existingConfig.lockK8sLockTTL, + nameSpace: pxNamespace, + } + + configData, err := existingConfig.get() + if err != nil { + log.Errorf("Error during fetching data from old config map %s", err) + return existingConfig + } + //copy data from old configmap to new configmap + if err = newConfig.update(configData); err != nil { + log.Errorf("Error during copying data from old config map %s", err) + return existingConfig + } - if v2LockRefreshDuration == 0 { - v2LockRefreshDuration = v2DefaultK8sLockRefreshDuration + //delete old configmap + err = c.config.delete() + if err != nil { + log.Errorf("Error during deleting configmap %s in namespace %s ", c.config.name, c.config.nameSpace) + } + c.config = newConfig + } else { + return existingConfig } - return &configMap{ - name: name, - defaultLockHoldTimeout: lockTimeout, - kLocksV2: map[string]*k8sLock{}, - lockAttempts: lockAttempts, - lockRefreshDuration: v2LockRefreshDuration, - lockK8sLockTTL: v2LockK8sLockTTL, - }, nil + return c.config } func (c *configMap) Get() (map[string]string, error) { - cm, err := core.Instance().GetConfigMap( - c.name, - k8sSystemNamespace, - ) - if err != nil { - return nil, err - } - - return cm.Data, nil + return c.Instance().get() } func (c *configMap) Delete() error { - return core.Instance().DeleteConfigMap( - c.name, - k8sSystemNamespace, - ) + return c.Instance().delete() } func (c *configMap) Patch(data map[string]string) error { - var ( - err error - cm *corev1.ConfigMap - ) - for retries := 0; retries < maxConflictRetries; retries++ { - cm, err = core.Instance().GetConfigMap( - c.name, - k8sSystemNamespace, - ) - if err != nil { - return err - } - - if cm.Data == nil { - cm.Data = make(map[string]string, 0) - } - - for k, v := range data { - cm.Data[k] = v - } - _, err = core.Instance().UpdateConfigMap(cm) - if k8s_errors.IsConflict(err) { - // try again - continue - } - return err - } - return err + return c.Instance().patch(data) } func (c *configMap) Update(data map[string]string) error { - var ( - err error - cm *corev1.ConfigMap - ) - for retries := 0; retries < maxConflictRetries; retries++ { - cm, err = core.Instance().GetConfigMap( - c.name, - k8sSystemNamespace, - ) - if err != nil { - return err - } - cm.Data = data - _, err = core.Instance().UpdateConfigMap(cm) - if k8s_errors.IsConflict(err) { - // try again - continue - } - return err - } - return err + return c.Instance().update(data) } -// SetFatalCb sets the fatal callback for the package which will get invoked in panic situations -func SetFatalCb(fb FatalCb) { - fatalCb = fb +func (c *configMap) Lock(id string) error { + return c.Instance().Lock(id) } -func configMapLog(fn, name, owner, key string, err error) *logrus.Entry { - if len(owner) > 0 && len(key) > 0 { - return logrus.WithFields(logrus.Fields{ - "Module": "ConfigMap", - "Name": name, - "Owner": owner, - "Key": key, - "Function": fn, - "Error": err, - }) - } - if len(owner) > 0 { - return logrus.WithFields(logrus.Fields{ - "Module": "ConfigMap", - "Name": name, - "Owner": owner, - "Function": fn, - "Error": err, - }) - } - return logrus.WithFields(logrus.Fields{ - "Module": "ConfigMap", - "Name": name, - "Function": fn, - "Error": err, - }) +func (c *configMap) LockWithHoldTimeout(id string, holdTimeout time.Duration) error { + return c.Instance().LockWithHoldTimeout(id, holdTimeout) } -// GetName is a helper function that returns a valid k8s -// configmap name given a prefix identifying the component using -// the configmap and a clusterID -func GetName(prefix, clusterID string) string { - return prefix + strings.ToLower(configMapNameRegex.ReplaceAllString(clusterID, "")) +func (c *configMap) LockWithKey(owner, key string) error { + return c.Instance().LockWithKey(owner, key) } -// TruncateLabel is a helper function that returns a valid k8s -// label stripped down to 63 characters. It removes the trailing characters -func TruncateLabel(label string) string { - if len(label) > 63 { - return label[:63] - } - return label +func (c *configMap) Unlock() error { + return c.Instance().Unlock() +} + +func (c *configMap) UnlockWithKey(key string) error { + return c.Instance().UnlockWithKey(key) +} +func (c *configMap) IsKeyLocked(key string) (bool, string, error) { + return c.Instance().IsKeyLocked(key) } diff --git a/k8s/core/configmap/configmap_lock_v1.go b/k8s/core/configmap/configmap_lock_v1.go index ea98317b..3a15037c 100644 --- a/k8s/core/configmap/configmap_lock_v1.go +++ b/k8s/core/configmap/configmap_lock_v1.go @@ -8,11 +8,11 @@ import ( k8s_errors "k8s.io/apimachinery/pkg/api/errors" ) -func (c *configMap) Lock(id string) error { +func (c *coreConfigMap) Lock(id string) error { return c.LockWithHoldTimeout(id, c.defaultLockHoldTimeout) } -func (c *configMap) LockWithHoldTimeout(id string, holdTimeout time.Duration) error { +func (c *coreConfigMap) LockWithHoldTimeout(id string, holdTimeout time.Duration) error { fn := "LockWithHoldTimeout" count := uint(0) // try acquiring a lock on the ConfigMap @@ -40,7 +40,7 @@ func (c *configMap) LockWithHoldTimeout(id string, holdTimeout time.Duration) er return nil } -func (c *configMap) Unlock() error { +func (c *coreConfigMap) Unlock() error { fn := "Unlock" // Get the existing ConfigMap c.kLockV1.Lock() @@ -60,7 +60,7 @@ func (c *configMap) Unlock() error { for retries := 0; retries < maxConflictRetries; retries++ { cm, err = core.Instance().GetConfigMap( c.name, - k8sSystemNamespace, + c.nameSpace, ) if err != nil { // A ConfigMap should always be created. @@ -91,11 +91,11 @@ func (c *configMap) Unlock() error { return err } -func (c *configMap) tryLockV1(id string, refresh bool) (string, error) { +func (c *coreConfigMap) tryLockV1(id string, refresh bool) (string, error) { // Get the existing ConfigMap cm, err := core.Instance().GetConfigMap( c.name, - k8sSystemNamespace, + c.nameSpace, ) if err != nil { // A ConfigMap should always be created. @@ -140,7 +140,7 @@ increase_expiry: return id, nil } -func (c *configMap) refreshLockV1(id string) { +func (c *coreConfigMap) refreshLockV1(id string) { fn := "refreshLock" refresh := time.NewTicker(v1DefaultK8sLockRefreshDuration) var ( diff --git a/k8s/core/configmap/configmap_lock_v1_test.go b/k8s/core/configmap/configmap_lock_v1_test.go index 03e29338..b7f2316a 100644 --- a/k8s/core/configmap/configmap_lock_v1_test.go +++ b/k8s/core/configmap/configmap_lock_v1_test.go @@ -13,7 +13,7 @@ import ( func TestLock(t *testing.T) { fakeClient := fakek8sclient.NewSimpleClientset() coreops.SetInstance(coreops.New(fakeClient)) - cm, err := New("px-configmaps-test", nil, lockTimeout, 5, 0, 0) + cm, err := New("px-configmaps-test", nil, lockTimeout, 5, 0, 0, "test-ns") require.NoError(t, err, "Unexpected error on New") fmt.Println("testLock") @@ -112,7 +112,7 @@ func TestLockWithHoldTimeout(t *testing.T) { customHoldTimeout := defaultHoldTimeout + v1DefaultK8sLockRefreshDuration + 10*time.Second fakeClient := fakek8sclient.NewSimpleClientset() coreops.SetInstance(coreops.New(fakeClient)) - cm, err := New("px-configmaps-test", nil, defaultHoldTimeout, 5, 0, 0) + cm, err := New("px-configmaps-test", nil, defaultHoldTimeout, 5, 0, 0, "test-ns") require.NoError(t, err, "Unexpected error on New") fmt.Println("TestLockWithHoldTimeout") diff --git a/k8s/core/configmap/configmap_lock_v2.go b/k8s/core/configmap/configmap_lock_v2.go index 794c7c03..12c5fa42 100644 --- a/k8s/core/configmap/configmap_lock_v2.go +++ b/k8s/core/configmap/configmap_lock_v2.go @@ -12,7 +12,7 @@ import ( k8s_errors "k8s.io/apimachinery/pkg/api/errors" ) -func (c *configMap) LockWithKey(owner, key string) error { +func (c *coreConfigMap) LockWithKey(owner, key string) error { if key == "" { return fmt.Errorf("key cannot be empty") } @@ -54,7 +54,7 @@ func (c *configMap) LockWithKey(owner, key string) error { return nil } -func (c *configMap) UnlockWithKey(key string) error { +func (c *coreConfigMap) UnlockWithKey(key string) error { if key == "" { return fmt.Errorf("key cannot be empty") } @@ -89,7 +89,7 @@ func (c *configMap) UnlockWithKey(key string) error { for retries := 0; retries < maxConflictRetries; retries++ { cm, err = core.Instance().GetConfigMap( c.name, - k8sSystemNamespace, + c.nameSpace, ) if err != nil { // A ConfigMap should always be created. @@ -136,11 +136,11 @@ func (c *configMap) UnlockWithKey(key string) error { return err } -func (c *configMap) IsKeyLocked(key string) (bool, string, error) { +func (c *coreConfigMap) IsKeyLocked(key string) (bool, string, error) { // Get the existing ConfigMap cm, err := core.Instance().GetConfigMap( c.name, - k8sSystemNamespace, + c.nameSpace, ) if err != nil { return false, "", err @@ -170,11 +170,11 @@ func (c *configMap) IsKeyLocked(key string) (bool, string, error) { return false, "", nil } -func (c *configMap) tryLock(owner string, key string) (string, error) { +func (c *coreConfigMap) tryLock(owner string, key string) (string, error) { // Get the existing ConfigMap cm, err := core.Instance().GetConfigMap( c.name, - k8sSystemNamespace, + c.nameSpace, ) if err != nil { // A ConfigMap should always be created. @@ -209,7 +209,7 @@ func (c *configMap) tryLock(owner string, key string) (string, error) { // parseLocks reads the lock data from the given ConfigMap and then converts it to: // * a map of keys to lock owners // * a map of keys to lock expiration times -func (c *configMap) parseLocks(cm *v1.ConfigMap) (map[string]string, map[string]time.Time, error) { +func (c *coreConfigMap) parseLocks(cm *v1.ConfigMap) (map[string]string, map[string]time.Time, error) { // Check all the locks: will be an empty string if key is not present indicating no lock parsedLocks := []lockData{} if lock, ok := cm.Data[pxLockKey]; ok && len(lock) > 0 { @@ -233,7 +233,7 @@ func (c *configMap) parseLocks(cm *v1.ConfigMap) (map[string]string, map[string] // checkAndTakeLock tries to take the given lock (owner, key) given the current state of the lock // (lockOwners, lockExpirations). -func (c *configMap) checkAndTakeLock( +func (c *coreConfigMap) checkAndTakeLock( owner, key string, lockOwners map[string]string, lockExpirations map[string]time.Time, @@ -279,7 +279,7 @@ func (c *configMap) checkAndTakeLock( // generateConfigMapData converts the given lock data (lockOwners, lockExpirations) to JSON and // stores it in the given ConfigMap. -func (c *configMap) generateConfigMapData(cm *v1.ConfigMap, lockOwners map[string]string, lockExpirations map[string]time.Time) error { +func (c *coreConfigMap) generateConfigMapData(cm *v1.ConfigMap, lockOwners map[string]string, lockExpirations map[string]time.Time) error { var locks []lockData for key, lockOwner := range lockOwners { locks = append(locks, lockData{ @@ -297,7 +297,7 @@ func (c *configMap) generateConfigMapData(cm *v1.ConfigMap, lockOwners map[strin return nil } -func (c *configMap) updateConfigMap(cm *v1.ConfigMap) (bool, error) { +func (c *coreConfigMap) updateConfigMap(cm *v1.ConfigMap) (bool, error) { if _, err := core.Instance().UpdateConfigMap(cm); err != nil { return k8s_errors.IsConflict(err), err } @@ -308,7 +308,7 @@ func (c *configMap) updateConfigMap(cm *v1.ConfigMap) (bool, error) { // It keeps the lock refreshed in k8s until we call Unlock. This is so that if the // node dies, the lock can have a short timeout and expire quickly but we can still // take longer-term locks. -func (c *configMap) refreshLock(id, key string) { +func (c *coreConfigMap) refreshLock(id, key string) { fn := "refreshLock" refresh := time.NewTicker(c.lockRefreshDuration) var ( @@ -356,7 +356,7 @@ func (c *configMap) refreshLock(id, key string) { } -func (c *configMap) checkLockTimeout(holdTimeout time.Duration, startTime time.Time, id string) { +func (c *coreConfigMap) checkLockTimeout(holdTimeout time.Duration, startTime time.Time, id string) { if holdTimeout > 0 && time.Since(startTime) > holdTimeout { panicMsg := fmt.Sprintf("Lock hold timeout (%v) triggered for K8s configmap lock key %s", holdTimeout, id) if fatalCb != nil { diff --git a/k8s/core/configmap/configmap_lock_v2_test.go b/k8s/core/configmap/configmap_lock_v2_test.go index 74955bc6..d317af1f 100644 --- a/k8s/core/configmap/configmap_lock_v2_test.go +++ b/k8s/core/configmap/configmap_lock_v2_test.go @@ -17,7 +17,7 @@ const ( func TestMultilock(t *testing.T) { fakeClient := fakek8sclient.NewSimpleClientset() coreops.SetInstance(coreops.New(fakeClient)) - cm, err := New("px-configmaps-test", nil, lockTimeout, 3, 0, 0) + cm, err := New("px-configmaps-test", nil, lockTimeout, 3, 0, 0, "test-ns") require.NoError(t, err, "Unexpected error on New") fmt.Println("testMultilock") diff --git a/k8s/core/configmap/configmap_test.go b/k8s/core/configmap/configmap_test.go index 44bfc4ae..dc60256a 100644 --- a/k8s/core/configmap/configmap_test.go +++ b/k8s/core/configmap/configmap_test.go @@ -17,7 +17,8 @@ func TestGetConfigMap(t *testing.T) { configData := map[string]string{ "key1": "val1", } - cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0) + cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0, "test-ns") + fmt.Println("cm : ", cm) require.NoError(t, err, "Unexpected error in creating configmap") resultMap, err := cm.Get() @@ -34,7 +35,7 @@ func TestDeleteConfigMap(t *testing.T) { "key1": "val1", } - cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0) + cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0, "test-ns") require.NoError(t, err, "Unexpected error in creating configmap") err = cm.Delete() @@ -50,7 +51,7 @@ func TestPatchConfigMap(t *testing.T) { "key1": "val1", } - cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0) + cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0, "test-ns") require.NoError(t, err, "Unexpected error in creating configmap") dummyData := map[string]string{ @@ -73,7 +74,7 @@ func TestUpdateConfigMap(t *testing.T) { "key1": "val1", } - cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0) + cm, err := New("px-configmaps-test", configData, lockTimeout, 5, 0, 0, "test-ns") require.NoError(t, err, "Unexpected error in creating configmap") dummyData := map[string]string{ diff --git a/k8s/core/configmap/coreconfigmap.go b/k8s/core/configmap/coreconfigmap.go new file mode 100644 index 00000000..a23ee563 --- /dev/null +++ b/k8s/core/configmap/coreconfigmap.go @@ -0,0 +1,223 @@ +package configmap + +import ( + "fmt" + "strings" + "time" + + "github.com/portworx/sched-ops/k8s/core" + "github.com/sirupsen/logrus" + corev1 "k8s.io/api/core/v1" + k8s_errors "k8s.io/apimachinery/pkg/api/errors" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// New returns the ConfigMap interface. It also creates a new +// configmap in k8s for the given name if not present and puts the data in it. +func New( + name string, + data map[string]string, + lockTimeout time.Duration, + lockAttempts uint, + v2LockRefreshDuration time.Duration, + v2LockK8sLockTTL time.Duration, + ns string, +) (ConfigMap, error) { + if data == nil { + data = make(map[string]string) + } + + //if copylock not created, then create + + labels := map[string]string{ + configMapUserLabelKey: TruncateLabel(name), + } + data[pxOwnerKey] = "" + + cm := &corev1.ConfigMap{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: name, + Namespace: ns, + Labels: labels, + }, + Data: data, + } + + if _, err := core.Instance().CreateConfigMap(cm); err != nil && + !k8s_errors.IsAlreadyExists(err) { + return nil, fmt.Errorf("failed to create configmap %v: %v", + name, err) + } + + if v2LockK8sLockTTL == 0 { + v2LockK8sLockTTL = v2DefaultK8sLockTTL + } + + if v2LockRefreshDuration == 0 { + v2LockRefreshDuration = v2DefaultK8sLockRefreshDuration + } + + config := &coreConfigMap{ + name: name, + defaultLockHoldTimeout: lockTimeout, + kLocksV2: map[string]*k8sLock{}, + lockAttempts: lockAttempts, + lockRefreshDuration: v2LockRefreshDuration, + lockK8sLockTTL: v2LockK8sLockTTL, + nameSpace: ns, + } + + cm1 := &corev1.ConfigMap{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: pxCopyLockConfigMap, + Namespace: pxNamespace, + }, + Data: map[string]string{ + upgradeCompletedStatus: trueString, + }, + } + + copyLock := &coreConfigMap{} + _, err := core.Instance().CreateConfigMap(cm1) + + if err != nil && !k8s_errors.IsAlreadyExists(err) { + fmt.Println("Failed to create configmap-copylock") + return nil, fmt.Errorf("failed to create configmap %v: %v", + name, err) + } + + copyLock.name = pxCopyLockConfigMap + copyLock.kLocksV2 = map[string]*k8sLock{} + copyLock.lockRefreshDuration = v2LockRefreshDuration + copyLock.lockK8sLockTTL = v2LockK8sLockTTL + copyLock.nameSpace = pxNamespace + + return &configMap{ + config: config, + pxNs: ns, + copylock: copyLock, + }, nil +} + +func (c *coreConfigMap) get() (map[string]string, error) { + cm, err := core.Instance().GetConfigMap( + c.name, + c.nameSpace, + ) + if err != nil { + return nil, err + } + + return cm.Data, nil +} + +func (c *coreConfigMap) delete() error { + return core.Instance().DeleteConfigMap( + c.name, + c.nameSpace, + ) +} + +func (c *coreConfigMap) patch(data map[string]string) error { + var ( + err error + cm *corev1.ConfigMap + ) + for retries := 0; retries < maxConflictRetries; retries++ { + cm, err = core.Instance().GetConfigMap( + c.name, + c.nameSpace, + ) + if err != nil { + return err + } + + if cm.Data == nil { + cm.Data = make(map[string]string, 0) + } + + for k, v := range data { + cm.Data[k] = v + } + _, err = core.Instance().UpdateConfigMap(cm) + if k8s_errors.IsConflict(err) { + // try again + continue + } + return err + } + return err +} + +func (c *coreConfigMap) update(data map[string]string) error { + var ( + err error + cm *corev1.ConfigMap + ) + for retries := 0; retries < maxConflictRetries; retries++ { + cm, err = core.Instance().GetConfigMap( + c.name, + c.nameSpace, + ) + if err != nil { + return err + } + cm.Data = data + _, err = core.Instance().UpdateConfigMap(cm) + if k8s_errors.IsConflict(err) { + // try again + continue + } + return err + } + return err +} + +// SetFatalCb sets the fatal callback for the package which will get invoked in panic situations +func SetFatalCb(fb FatalCb) { + fatalCb = fb +} + +func configMapLog(fn, name, owner, key string, err error) *logrus.Entry { + if len(owner) > 0 && len(key) > 0 { + return logrus.WithFields(logrus.Fields{ + "Module": "ConfigMap", + "Name": name, + "Owner": owner, + "Key": key, + "Function": fn, + "Error": err, + }) + } + if len(owner) > 0 { + return logrus.WithFields(logrus.Fields{ + "Module": "ConfigMap", + "Name": name, + "Owner": owner, + "Function": fn, + "Error": err, + }) + } + return logrus.WithFields(logrus.Fields{ + "Module": "ConfigMap", + "Name": name, + "Function": fn, + "Error": err, + }) +} + +// GetName is a helper function that returns a valid k8s +// configmap name given a prefix identifying the component using +// the configmap and a clusterID +func GetName(prefix, clusterID string) string { + return prefix + strings.ToLower(configMapNameRegex.ReplaceAllString(clusterID, "")) +} + +// TruncateLabel is a helper function that returns a valid k8s +// label stripped down to 63 characters. It removes the trailing characters +func TruncateLabel(label string) string { + if len(label) > 63 { + return label[:63] + } + return label +} diff --git a/k8s/core/configmap/types.go b/k8s/core/configmap/types.go index 97b43d1d..a74210bc 100644 --- a/k8s/core/configmap/types.go +++ b/k8s/core/configmap/types.go @@ -41,9 +41,14 @@ const ( // objects. pxLockKey = "px-lock" - lockSleepDuration = 1 * time.Second - configMapUserLabelKey = "user" - maxConflictRetries = 3 + lockSleepDuration = 1 * time.Second + configMapUserLabelKey = "user" + maxConflictRetries = 3 + upgradeCompletedStatus = "UPGRADE_DONE" + trueString = "true" + falseString = "false" + pxNamespace = "portworx" + pxCopyLockConfigMap = "configmaps-copylock" ) var ( @@ -58,7 +63,14 @@ var ( type FatalCb func(format string, args ...interface{}) type configMap struct { + config *coreConfigMap + pxNs string + copylock *coreConfigMap +} + +type coreConfigMap struct { name string + nameSpace string kLockV1 k8sLock kLocksV2Mutex sync.Mutex kLocksV2 map[string]*k8sLock