@@ -2,6 +2,7 @@ package sync
22
33import (
44 "fmt"
5+ "regexp"
56 "strings"
67
78 "github.com/argoproj/argo-workflows/v3/errors"
@@ -20,14 +21,16 @@ type lockName struct {
2021 ResourceName string
2122 Key string
2223 Kind lockKind
24+ Selectors []v1alpha1.SyncSelector
2325}
2426
25- func newLockName (namespace , resourceName , lockKey string , kind lockKind ) * lockName {
27+ func newLockName (namespace , resourceName , lockKey string , kind lockKind , selectors []v1alpha1. SyncSelector ) * lockName {
2628 return & lockName {
2729 Namespace : namespace ,
2830 ResourceName : resourceName ,
2931 Key : lockKey ,
3032 Kind : kind ,
33+ Selectors : selectors ,
3134 }
3235}
3336
@@ -37,7 +40,7 @@ func getSemaphoreLockName(sem *v1alpha1.SemaphoreRef, wfNamespace string) (*lock
3740 if namespace == "" {
3841 namespace = wfNamespace
3942 }
40- return newLockName (namespace , sem .ConfigMapKeyRef .Name , sem .ConfigMapKeyRef .Key , lockKindConfigMap ), nil
43+ return newLockName (namespace , sem .ConfigMapKeyRef .Name , sem .ConfigMapKeyRef .Key , lockKindConfigMap , sem . Selectors ), nil
4144 }
4245 return nil , fmt .Errorf ("cannot get LockName for a Semaphore without a ConfigMapRef" )
4346}
@@ -47,7 +50,7 @@ func getMutexLockName(mtx *v1alpha1.Mutex, wfNamespace string) *lockName {
4750 if namespace == "" {
4851 namespace = wfNamespace
4952 }
50- return newLockName (namespace , mtx .Name , "" , lockKindMutex )
53+ return newLockName (namespace , mtx .Name , "" , lockKindMutex , mtx . Selectors )
5154}
5255
5356func getLockName (item * syncItem , wfNamespace string ) (* lockName , error ) {
@@ -62,7 +65,10 @@ func getLockName(item *syncItem, wfNamespace string) (*lockName, error) {
6265}
6366
6467func DecodeLockName (name string ) (* lockName , error ) {
65- items := strings .SplitN (name , "/" , 3 )
68+ splittedLockName := strings .Split (name , "?" )
69+ lockNameTrimedSelectors := splittedLockName [0 ]
70+ selectors := ParseSelectors (strings .Join (splittedLockName [1 :], "?" ))
71+ items := strings .SplitN (lockNameTrimedSelectors , "/" , 3 )
6672 if len (items ) < 3 {
6773 return nil , errors .New (errors .CodeBadRequest , "Invalid lock key: unknown format" )
6874 }
@@ -73,15 +79,15 @@ func DecodeLockName(name string) (*lockName, error) {
7379
7480 switch lockKind {
7581 case lockKindMutex :
76- lock = lockName {Namespace : namespace , Kind : lockKind , ResourceName : items [2 ]}
82+ lock = lockName {Namespace : namespace , Kind : lockKind , ResourceName : items [2 ], Selectors : selectors }
7783 case lockKindConfigMap :
7884 components := strings .Split (items [2 ], "/" )
7985
8086 if len (components ) != 2 {
8187 return nil , errors .New (errors .CodeBadRequest , "Invalid ConfigMap lock key: unknown format" )
8288 }
8389
84- lock = lockName {Namespace : namespace , Kind : lockKind , ResourceName : components [0 ], Key : components [1 ]}
90+ lock = lockName {Namespace : namespace , Kind : lockKind , ResourceName : components [0 ], Key : components [1 ], Selectors : selectors }
8591 default :
8692 return nil , errors .New (errors .CodeBadRequest , fmt .Sprintf ("Invalid lock key, unexpected kind: %s" , lockKind ))
8793 }
@@ -93,11 +99,50 @@ func DecodeLockName(name string) (*lockName, error) {
9399 return & lock , nil
94100}
95101
102+ func StringifySelectors (selectors []v1alpha1.SyncSelector ) string {
103+ joinedSelectors := ""
104+ for _ , selector := range selectors {
105+ // at this point template should be already replaced
106+ if selector .Template != "" {
107+ // escape & and = chars to decode easily later
108+ re := regexp .MustCompile ("&|=" )
109+ escapedSelectorName := re .ReplaceAllString (selector .Name , "-" )
110+ escapedSelectorValue := re .ReplaceAllString (selector .Template , "-" )
111+
112+ joinedSelectors = joinedSelectors + fmt .Sprintf ("%s=%s&" , escapedSelectorName , escapedSelectorValue )
113+ }
114+ }
115+ return strings .TrimRight (joinedSelectors , "&" )
116+ }
117+
118+ func ParseSelectors (selectors string ) []v1alpha1.SyncSelector {
119+ parsedSelectors := []v1alpha1.SyncSelector {}
120+ splittedSelectors := strings .Split (selectors , "&" )
121+
122+ for _ , selectorStr := range splittedSelectors {
123+ keyValPair := strings .Split (selectorStr , "=" )
124+ if len (keyValPair ) == 2 {
125+ parsedSelectors = append (parsedSelectors , v1alpha1.SyncSelector {
126+ Name : keyValPair [0 ],
127+ Template : keyValPair [1 ],
128+ })
129+ }
130+ // otherwise consider invalid, do nothing
131+ }
132+ return parsedSelectors
133+ }
134+
96135func (ln * lockName ) encodeName () string {
97- if ln .Kind == lockKindMutex {
98- return ln .validateEncoding (fmt .Sprintf ("%s/%s/%s" , ln .Namespace , ln .Kind , ln .ResourceName ))
136+ encodingBuilder := & strings.Builder {}
137+
138+ encodingBuilder .WriteString (fmt .Sprintf ("%s/%s/%s" , ln .Namespace , ln .Kind , ln .ResourceName ))
139+ if ln .Kind == lockKindConfigMap {
140+ encodingBuilder .WriteString (fmt .Sprintf ("/%s" , ln .Key ))
141+ }
142+ if selectors := StringifySelectors (ln .Selectors ); len (selectors ) > 0 {
143+ encodingBuilder .WriteString (fmt .Sprintf ("?%s" , selectors ))
99144 }
100- return ln .validateEncoding (fmt . Sprintf ( "%s/%s/%s/%s" , ln . Namespace , ln . Kind , ln . ResourceName , ln . Key ))
145+ return ln .validateEncoding (encodingBuilder . String ( ))
101146}
102147
103148func (ln * lockName ) validate () error {
0 commit comments