forked from argoproj/argo-workflows
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lock_name.go
104 lines (91 loc) · 3.13 KB
/
lock_name.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
package sync
import (
"fmt"
"strings"
"github.com/argoproj/argo-workflows/v3/errors"
"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
)
type LockKind string
const (
LockKindConfigMap LockKind = "ConfigMap"
LockKindMutex LockKind = "Mutex"
)
type LockName struct {
Namespace string
ResourceName string
Key string
Kind LockKind
}
func NewLockName(namespace, resourceName, lockKey string, kind LockKind) *LockName {
return &LockName{
Namespace: namespace,
ResourceName: resourceName,
Key: lockKey,
Kind: kind,
}
}
func GetLockName(sync *v1alpha1.Synchronization, namespace string) (*LockName, error) {
switch sync.GetType() {
case v1alpha1.SynchronizationTypeSemaphore:
if sync.Semaphore.ConfigMapKeyRef != nil {
return NewLockName(namespace, sync.Semaphore.ConfigMapKeyRef.Name, sync.Semaphore.ConfigMapKeyRef.Key, LockKindConfigMap), nil
}
return nil, fmt.Errorf("cannot get LockName for a Semaphore without a ConfigMapRef")
case v1alpha1.SynchronizationTypeMutex:
return NewLockName(namespace, sync.Mutex.Name, "", LockKindMutex), nil
default:
return nil, fmt.Errorf("cannot get LockName for a Sync of Unknown type")
}
}
func DecodeLockName(lockName string) (*LockName, error) {
items := strings.Split(lockName, "/")
if len(items) < 3 {
return nil, errors.New(errors.CodeBadRequest, "Invalid lock key: unknown format")
}
var lock LockName
lockKind := LockKind(items[1])
switch lockKind {
case LockKindMutex:
lock = LockName{Namespace: items[0], Kind: LockKind(items[1]), ResourceName: items[2]}
case LockKindConfigMap:
lock = LockName{Namespace: items[0], Kind: LockKind(items[1]), ResourceName: items[2], Key: items[3]}
default:
return nil, errors.New(errors.CodeBadRequest, fmt.Sprintf("Invalid lock key, unexpected kind: %s", lockKind))
}
err := lock.Validate()
if err != nil {
return nil, err
}
return &lock, nil
}
func (ln *LockName) EncodeName() string {
if ln.Kind == LockKindMutex {
return ln.ValidateEncoding(fmt.Sprintf("%s/%s/%s", ln.Namespace, ln.Kind, ln.ResourceName))
}
return ln.ValidateEncoding(fmt.Sprintf("%s/%s/%s/%s", ln.Namespace, ln.Kind, ln.ResourceName, ln.Key))
}
func (ln *LockName) Validate() error {
if ln.Namespace == "" {
return errors.New(errors.CodeBadRequest, "Invalid lock key: Namespace is missing")
}
if ln.Kind == "" {
return errors.New(errors.CodeBadRequest, "Invalid lock key: Kind is missing")
}
if ln.ResourceName == "" {
return errors.New(errors.CodeBadRequest, "Invalid lock key: ResourceName is missing")
}
if ln.Kind == LockKindConfigMap && ln.Key == "" {
return errors.New(errors.CodeBadRequest, "Invalid lock key: Key is missing for ConfigMap lock")
}
return nil
}
func (ln *LockName) ValidateEncoding(encoding string) string {
decoded, err := DecodeLockName(encoding)
if err != nil {
panic(fmt.Sprintf("bug: unable to decode lock that was just encoded: %s", err))
}
if ln.Namespace != decoded.Namespace || ln.Kind != decoded.Kind || ln.ResourceName != decoded.ResourceName || ln.Key != decoded.Key {
panic("bug: lock that was just encoded does not match encoding")
}
return encoding
}