Skip to content
This repository was archived by the owner on Oct 19, 2024. It is now read-only.

Commit a2ec42c

Browse files
feat: support defaultTriggers.<service> (#258)
* refactor: fix TestGetAll Signed-off-by: Ryota Sakamoto <[email protected]> * feat: support defaultTriggers.<service> Signed-off-by: Ryota Sakamoto <[email protected]>
1 parent a53d095 commit a2ec42c

File tree

8 files changed

+170
-24
lines changed

8 files changed

+170
-24
lines changed

controller/controller.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,12 @@ func (c *notificationController) getAppProj(app *unstructured.Unstructured) *uns
219219
func (c *notificationController) getSubscriptions(app *unstructured.Unstructured) pkg.Subscriptions {
220220
res := c.cfg.GetGlobalSubscriptions(app.GetLabels())
221221

222-
res.Merge(controller.Subscriptions(app.GetAnnotations()).GetAll(c.cfg.DefaultTriggers...))
223-
res.Merge(legacy.GetSubscriptions(app.GetAnnotations(), c.cfg.DefaultTriggers...))
222+
res.Merge(controller.Subscriptions(app.GetAnnotations()).GetAll(c.cfg.DefaultTriggers, c.cfg.ServiceDefaultTriggers))
223+
res.Merge(legacy.GetSubscriptions(app.GetAnnotations(), c.cfg.DefaultTriggers, c.cfg.ServiceDefaultTriggers))
224224

225225
if proj := c.getAppProj(app); proj != nil {
226-
res.Merge(controller.Subscriptions(proj.GetAnnotations()).GetAll(c.cfg.DefaultTriggers...))
227-
res.Merge(legacy.GetSubscriptions(proj.GetAnnotations(), c.cfg.DefaultTriggers...))
226+
res.Merge(controller.Subscriptions(proj.GetAnnotations()).GetAll(c.cfg.DefaultTriggers, c.cfg.ServiceDefaultTriggers))
227+
res.Merge(legacy.GetSubscriptions(proj.GetAnnotations(), c.cfg.DefaultTriggers, c.cfg.ServiceDefaultTriggers))
228228
}
229229

230230
return res.Dedup()

docs/triggers.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,21 @@ data:
9393
# Holds list of triggers that are used by default if trigger is not specified explicitly in the subscription
9494
defaultTriggers: |
9595
- on-sync-status-unknown
96+
97+
defaultTriggers.mattermost: |
98+
- on-sync-running
99+
- on-sync-succeeded
96100
```
97101

98-
Specify the annotations as follows to use `defaultTriggers`.
102+
Specify the annotations as follows to use `defaultTriggers`. In this example, `slack` sends when `on-sync-status-unknown`, and `mattermost` sends when `on-sync-running` and `on-sync-succeeded`.
99103

100104
```yaml
101105
apiVersion: argoproj.io/v1alpha1
102106
kind: Application
103107
metadata:
104108
annotations:
105109
notifications.argoproj.io/subscribe.slack: my-channel
110+
notifications.argoproj.io/subscribe.mattermost: my-mattermost-channel
106111
```
107112

108113
## Functions

pkg/config.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ type ServiceFactory func() (services.NotificationService, error)
4242

4343
// Config holds settings required to create new api
4444
type Config struct {
45-
Services map[string]ServiceFactory
46-
Triggers map[string][]triggers.Condition
47-
Templates map[string]services.Notification
45+
Services map[string]ServiceFactory
46+
Triggers map[string][]triggers.Condition
47+
ServiceDefaultTriggers map[string][]string
48+
Templates map[string]services.Notification
4849
}
4950

5051
var keyPattern = regexp.MustCompile(`[$][\w-_]+`)
@@ -63,7 +64,12 @@ func replaceStringSecret(val string, secretValues map[string][]byte) string {
6364

6465
// ParseConfig retrieves Config from given ConfigMap and Secret
6566
func ParseConfig(configMap *v1.ConfigMap, secret *v1.Secret) (*Config, error) {
66-
cfg := Config{map[string]ServiceFactory{}, map[string][]triggers.Condition{}, map[string]services.Notification{}}
67+
cfg := Config{
68+
Services: map[string]ServiceFactory{},
69+
Triggers: map[string][]triggers.Condition{},
70+
ServiceDefaultTriggers: map[string][]string{},
71+
Templates: map[string]services.Notification{},
72+
}
6773
for k, v := range configMap.Data {
6874
parts := strings.Split(k, ".")
6975
switch {
@@ -101,6 +107,13 @@ func ParseConfig(configMap *v1.ConfigMap, secret *v1.Secret) (*Config, error) {
101107
return nil, fmt.Errorf("failed to unmarshal trigger %s: %v", name, err)
102108
}
103109
cfg.Triggers[name] = trigger
110+
case strings.HasPrefix(k, "defaultTriggers."):
111+
name := strings.Join(parts[1:], ".")
112+
var defaultTriggers []string
113+
if err := yaml.Unmarshal([]byte(v), &defaultTriggers); err != nil {
114+
return nil, fmt.Errorf("failed to unmarshal default trigger %s: %v", name, err)
115+
}
116+
cfg.ServiceDefaultTriggers[name] = defaultTriggers
104117
}
105118
}
106119
return &cfg, nil

pkg/config_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,25 @@ message: hello world
4141
}, cfg.Templates)
4242
}
4343

44+
func TestParseConfig_DefaultTriggers(t *testing.T) {
45+
cfg, err := ParseConfig(&v1.ConfigMap{Data: map[string]string{
46+
"defaultTriggers.slack": `
47+
- trigger-a
48+
- trigger-b
49+
`}}, emptySecret)
50+
51+
if !assert.NoError(t, err) {
52+
return
53+
}
54+
55+
assert.Equal(t, map[string][]string{
56+
"slack": {
57+
"trigger-a",
58+
"trigger-b",
59+
},
60+
}, cfg.ServiceDefaultTriggers)
61+
}
62+
4463
func TestReplaceStringSecret_KeyPresent(t *testing.T) {
4564
val := replaceStringSecret("hello $secret-value", map[string][]byte{
4665
"secret-value": []byte("world"),

pkg/controller/subscriptions.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,17 @@ func (a Subscriptions) Has(service string, recipient string) bool {
105105
return has
106106
}
107107

108-
func (a Subscriptions) GetAll(defaultTriggers ...string) pkg.Subscriptions {
108+
func (a Subscriptions) GetAll(defaultTriggers []string, serviceDefaultTriggers map[string][]string) pkg.Subscriptions {
109109
subscriptions := pkg.Subscriptions{}
110110
a.iterate(func(trigger string, service string, recipients []string, v string) {
111111
for _, recipient := range recipients {
112112
triggers := defaultTriggers
113113
if trigger != "" {
114114
triggers = []string{trigger}
115+
} else if t, ok := serviceDefaultTriggers[service]; ok {
116+
triggers = t
115117
}
118+
116119
for i := range triggers {
117120
subscriptions[triggers[i]] = append(subscriptions[triggers[i]], services.Destination{
118121
Service: service,

pkg/controller/subscriptions_test.go

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,96 @@ func TestIterate(t *testing.T) {
5959
}
6060

6161
func TestGetAll(t *testing.T) {
62-
a := Subscriptions(map[string]string{
63-
"notifications.argoproj.io/subscribe.my-trigger.slack": "my-channel",
64-
})
65-
subscriptions := a.GetAll()
66-
assert.Equal(t, pkg.Subscriptions{
67-
"my-trigger": []services.Destination{{
68-
Service: "slack",
69-
Recipient: "my-channel",
70-
}},
71-
}, subscriptions)
62+
tests := []struct {
63+
subscriptions Subscriptions
64+
defaultTrigger []string
65+
serviceDefaultTrigger map[string][]string
66+
result pkg.Subscriptions
67+
}{
68+
{
69+
subscriptions: Subscriptions(map[string]string{
70+
"notifications.argoproj.io/subscribe.my-trigger.slack": "my-channel",
71+
}),
72+
defaultTrigger: []string{},
73+
result: pkg.Subscriptions{
74+
"my-trigger": []services.Destination{{
75+
Service: "slack",
76+
Recipient: "my-channel",
77+
}},
78+
},
79+
},
80+
{
81+
subscriptions: Subscriptions(map[string]string{
82+
"notifications.argoproj.io/subscribe.my-trigger.slack": "my-channel",
83+
}),
84+
defaultTrigger: []string{
85+
"trigger-a",
86+
"trigger-b",
87+
"trigger-c",
88+
},
89+
result: pkg.Subscriptions{
90+
"my-trigger": []services.Destination{{
91+
Service: "slack",
92+
Recipient: "my-channel",
93+
}},
94+
},
95+
},
96+
{
97+
subscriptions: Subscriptions(map[string]string{
98+
"notifications.argoproj.io/subscribe.slack": "my-channel",
99+
}),
100+
defaultTrigger: []string{
101+
"trigger-a",
102+
"trigger-b",
103+
"trigger-c",
104+
},
105+
result: pkg.Subscriptions{
106+
"trigger-a": []services.Destination{{
107+
Service: "slack",
108+
Recipient: "my-channel",
109+
}},
110+
"trigger-b": []services.Destination{{
111+
Service: "slack",
112+
Recipient: "my-channel",
113+
}},
114+
"trigger-c": []services.Destination{{
115+
Service: "slack",
116+
Recipient: "my-channel",
117+
}},
118+
},
119+
},
120+
{
121+
subscriptions: Subscriptions(map[string]string{
122+
"notifications.argoproj.io/subscribe.slack": "my-channel",
123+
}),
124+
defaultTrigger: []string{
125+
"trigger-a",
126+
"trigger-b",
127+
"trigger-c",
128+
},
129+
serviceDefaultTrigger: map[string][]string{
130+
"slack": {
131+
"trigger-d",
132+
"trigger-e",
133+
},
134+
},
135+
result: pkg.Subscriptions{
136+
"trigger-d": []services.Destination{{
137+
Service: "slack",
138+
Recipient: "my-channel",
139+
}},
140+
"trigger-e": []services.Destination{{
141+
Service: "slack",
142+
Recipient: "my-channel",
143+
}},
144+
},
145+
},
146+
}
147+
148+
for _, tt := range tests {
149+
subscriptions := tt.subscriptions.GetAll(tt.defaultTrigger, tt.serviceDefaultTrigger)
150+
assert.Equal(t, tt.result, subscriptions)
151+
}
72152
}
73153

74154
func TestSubscribe(t *testing.T) {

shared/legacy/subscriptions.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const (
1313
annotationKey = "recipients.argocd-notifications.argoproj.io"
1414
)
1515

16-
func GetSubscriptions(annotations map[string]string, defaultTriggers ...string) pkg.Subscriptions {
16+
func GetSubscriptions(annotations map[string]string, defaultTriggers []string, serviceDefaultTriggers map[string][]string) pkg.Subscriptions {
1717
subscriptions := pkg.Subscriptions{}
1818
for k, v := range annotations {
1919
if !strings.HasSuffix(k, annotationKey) {
@@ -35,7 +35,12 @@ func GetSubscriptions(annotations map[string]string, defaultTriggers ...string)
3535
if len(parts) > 1 {
3636
dest.Recipient = parts[1]
3737
}
38-
for _, name := range triggerNames {
38+
39+
t := triggerNames
40+
if v, ok := serviceDefaultTriggers[dest.Service]; ok {
41+
t = v
42+
}
43+
for _, name := range t {
3944
subscriptions[name] = append(subscriptions[name], dest)
4045
}
4146
}

shared/legacy/subscriptions_test.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
func TestGetSubscriptions(t *testing.T) {
1313
res := GetSubscriptions(map[string]string{
1414
"my-trigger.recipients.argocd-notifications.argoproj.io": "slack:my-channel",
15-
})
15+
}, []string{}, nil)
1616
assert.Equal(t, pkg.Subscriptions{
1717
"my-trigger": []services.Destination{{
1818
Recipient: "my-channel",
@@ -24,11 +24,32 @@ func TestGetSubscriptions(t *testing.T) {
2424
func TestGetSubscriptions_DefaultTrigger(t *testing.T) {
2525
res := GetSubscriptions(map[string]string{
2626
"recipients.argocd-notifications.argoproj.io": "slack:my-channel",
27-
}, "my-trigger")
27+
}, []string{"my-trigger"}, nil)
2828
assert.Equal(t, pkg.Subscriptions{
2929
"my-trigger": []services.Destination{{
3030
Recipient: "my-channel",
3131
Service: "slack",
3232
}},
3333
}, res)
3434
}
35+
36+
func TestGetSubscriptions_ServiceDefaultTriggers(t *testing.T) {
37+
res := GetSubscriptions(map[string]string{
38+
"recipients.argocd-notifications.argoproj.io": "slack:my-channel",
39+
}, []string{}, map[string][]string{
40+
"slack": {
41+
"trigger-a",
42+
"trigger-b",
43+
},
44+
})
45+
assert.Equal(t, pkg.Subscriptions{
46+
"trigger-a": []services.Destination{{
47+
Recipient: "my-channel",
48+
Service: "slack",
49+
}},
50+
"trigger-b": []services.Destination{{
51+
Recipient: "my-channel",
52+
Service: "slack",
53+
}},
54+
}, res)
55+
}

0 commit comments

Comments
 (0)