Skip to content

Commit a90bc32

Browse files
committed
feat: add nats service
Signed-off-by: Tom Bojer <[email protected]>
1 parent e3fe626 commit a90bc32

File tree

6 files changed

+350
-19
lines changed

6 files changed

+350
-19
lines changed

docs/services/nats.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Nats
2+
3+
## Parameters
4+
5+
This notification service is capable of sending simple messages via Nats.
6+
7+
* Url - Nats server URL, e.g. `nats://nats:4222`
8+
* Headers - optional, additional headers to be sent with the message
9+
* User - optional, Nats user for authentication used in combination with password
10+
* Password - optional, Nats password for authentication used in combination with user
11+
* Nkey - optional, Nats key for authentication
12+
13+
## Example
14+
15+
Resource Annotation:
16+
```yaml
17+
apiVersion: apps/v1
18+
kind: Deployment
19+
metadata:
20+
name: nginx-deployment
21+
annotations:
22+
notifications.argoproj.io/subscribe.on-deployment-ready.nats: "mytopic"
23+
```
24+
25+
* ConfigMap
26+
```yaml
27+
apiVersion: v1
28+
kind: ConfigMap
29+
metadata:
30+
name: argocd-notifications-cm
31+
data:
32+
service.nats: |
33+
url: "nats://nats:4222"
34+
headers:
35+
my-header: "my-value"
36+
37+
template.deployment-ready: |
38+
message: |
39+
Deployment {{.obj.metadata.name}} is ready!
40+
41+
trigger.on-deployment-ready: |
42+
- when: any(obj.status.conditions, {.type == 'Available' && .status == 'True'})
43+
send: [deployment-ready]
44+
- oncePer: obj.metadata.annotations["generation"]
45+
46+
```
47+
48+
49+

go.mod

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,17 @@ require (
2020
github.com/google/uuid v1.6.0
2121
github.com/gregdel/pushover v1.3.1
2222
github.com/hashicorp/go-retryablehttp v0.7.7
23+
github.com/nats-io/nats-server/v2 v2.11.4
24+
github.com/nats-io/nats.go v1.43.0
25+
github.com/nats-io/nkeys v0.4.11
2326
github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.23
2427
github.com/prometheus/client_golang v1.21.0
2528
github.com/sirupsen/logrus v1.9.3
2629
github.com/slack-go/slack v0.16.0
2730
github.com/spf13/cast v1.7.1
2831
github.com/spf13/cobra v1.9.1
2932
github.com/stretchr/testify v1.10.0
30-
golang.org/x/time v0.10.0
33+
golang.org/x/time v0.11.0
3134
gomodules.xyz/notify v0.1.1
3235
google.golang.org/api v0.223.0
3336
gopkg.in/yaml.v3 v3.0.1
@@ -71,6 +74,7 @@ require (
7174
github.com/golang/protobuf v1.5.4 // indirect
7275
github.com/google/gnostic-models v0.6.8 // indirect
7376
github.com/google/go-querystring v1.1.0 // indirect
77+
github.com/google/go-tpm v0.9.5 // indirect
7478
github.com/google/gofuzz v1.2.0 // indirect
7579
github.com/google/s2a-go v0.1.9 // indirect
7680
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
@@ -81,12 +85,16 @@ require (
8185
github.com/inconshreveable/mousetrap v1.1.0 // indirect
8286
github.com/josharian/intern v1.0.0 // indirect
8387
github.com/json-iterator/go v1.1.12 // indirect
88+
github.com/klauspost/compress v1.18.0 // indirect
8489
github.com/mailru/easyjson v0.7.7 // indirect
90+
github.com/minio/highwayhash v1.0.3 // indirect
8591
github.com/mitchellh/copystructure v1.2.0 // indirect
8692
github.com/mitchellh/reflectwalk v1.0.2 // indirect
8793
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
8894
github.com/modern-go/reflect2 v1.0.2 // indirect
8995
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
96+
github.com/nats-io/jwt/v2 v2.7.4 // indirect
97+
github.com/nats-io/nuid v1.0.1 // indirect
9098
github.com/pkg/errors v0.9.1 // indirect
9199
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
92100
github.com/prometheus/client_model v0.6.1 // indirect
@@ -101,12 +109,12 @@ require (
101109
go.opentelemetry.io/otel v1.34.0 // indirect
102110
go.opentelemetry.io/otel/metric v1.34.0 // indirect
103111
go.opentelemetry.io/otel/trace v1.34.0 // indirect
104-
golang.org/x/crypto v0.33.0 // indirect
112+
golang.org/x/crypto v0.38.0 // indirect
105113
golang.org/x/net v0.35.0 // indirect
106114
golang.org/x/oauth2 v0.26.0 // indirect
107-
golang.org/x/sys v0.30.0 // indirect
108-
golang.org/x/term v0.29.0 // indirect
109-
golang.org/x/text v0.22.0 // indirect
115+
golang.org/x/sys v0.33.0 // indirect
116+
golang.org/x/term v0.32.0 // indirect
117+
golang.org/x/text v0.25.0 // indirect
110118
gomodules.xyz/envconfig v1.3.1-0.20190308184047-426f31af0d45 // indirect
111119
google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 // indirect
112120
google.golang.org/grpc v1.70.0 // indirect

go.sum

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ github.com/PagerDuty/go-pagerduty v1.8.0 h1:MTFqTffIcAervB83U7Bx6HERzLbyaSPL/+ox
2020
github.com/PagerDuty/go-pagerduty v1.8.0/go.mod h1:nzIeAqyFSJAFkjWKvMzug0JtwDg+V+UoCWjFrfFH5mI=
2121
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20240116134246-a8cbe886bab0 h1:ztLQGVQsey3BjCoh0TvHc/iKTQmkio2OmsIxhuu+EeY=
2222
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20240116134246-a8cbe886bab0/go.mod h1:rjP7sIipbZcagro/6TCk6X0ZeFT2eyudH5+fve/cbBA=
23+
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op h1:+OSa/t11TFhqfrX0EOSqQBDJ0YlpmK0rDSiB19dg9M0=
24+
github.com/antithesishq/antithesis-sdk-go v0.4.3-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E=
2325
github.com/appscode/go v0.0.0-20191119085241-0887d8ec2ecc/go.mod h1:OawnOmAL4ZX3YaPdN+8HTNwBveT1jMsqP74moa9XUbE=
2426
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
2527
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
@@ -136,6 +138,8 @@ github.com/google/go-github/v69 v69.2.0/go.mod h1:xne4jymxLR6Uj9b7J7PyTpkMYstEMM
136138
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
137139
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
138140
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
141+
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
142+
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
139143
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
140144
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
141145
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -184,8 +188,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
184188
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
185189
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
186190
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
187-
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
188-
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
191+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
192+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
189193
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
190194
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
191195
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -207,6 +211,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
207211
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
208212
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
209213
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
214+
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
215+
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
210216
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
211217
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
212218
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
@@ -220,6 +226,16 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
220226
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
221227
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
222228
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
229+
github.com/nats-io/jwt/v2 v2.7.4 h1:jXFuDDxs/GQjGDZGhNgH4tXzSUK6WQi2rsj4xmsNOtI=
230+
github.com/nats-io/jwt/v2 v2.7.4/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
231+
github.com/nats-io/nats-server/v2 v2.11.4 h1:oQhvy6He6ER926sGqIKBKuYHH4BGnUQCNb0Y5Qa+M54=
232+
github.com/nats-io/nats-server/v2 v2.11.4/go.mod h1:jFnKKwbNeq6IfLHq+OMnl7vrFRihQ/MkhRbiWfjLdjU=
233+
github.com/nats-io/nats.go v1.43.0 h1:uRFZ2FEoRvP64+UUhaTokyS18XBCR/xM2vQZKO4i8ug=
234+
github.com/nats-io/nats.go v1.43.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
235+
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
236+
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
237+
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
238+
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
223239
github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
224240
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
225241
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
@@ -315,8 +331,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
315331
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
316332
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
317333
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
318-
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
319-
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
334+
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
335+
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
320336
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
321337
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
322338
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -339,8 +355,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
339355
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
340356
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
341357
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
342-
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
343-
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
358+
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
359+
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
344360
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
345361
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
346362
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -356,18 +372,19 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
356372
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
357373
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
358374
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
359-
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
360-
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
375+
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
376+
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
377+
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
361378
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
362-
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
363-
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
379+
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
380+
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
364381
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
365382
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
366383
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
367-
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
368-
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
369-
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
370-
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
384+
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
385+
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
386+
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
387+
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
371388
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
372389
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
373390
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=

pkg/services/nats.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package services
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/nats-io/nats.go"
7+
"github.com/nats-io/nkeys"
8+
)
9+
10+
type NatsNotification struct{}
11+
12+
type NatsOptions struct {
13+
// Url is the NATS server URL to connect to
14+
// e.g. nats://nats.nats.svc.cluster.local:4222
15+
Url string `json:"url"`
16+
// Headers is an optional map of headers to include in the NATS message
17+
Headers map[string]string `json:"headers,omitempty"`
18+
// NKey is optional for nkey authentication
19+
NKey string `json:"nkey,omitempty"`
20+
// Username and Password are optional for basic auth
21+
Username string `json:"username,omitempty"`
22+
Password string `json:"password,omitempty"`
23+
}
24+
25+
func NewNatsService(opts NatsOptions, defaultConnectionOpts ...nats.Option) NotificationService {
26+
return natsService{opts: opts, defaultConnectionOpts: defaultConnectionOpts}
27+
}
28+
29+
type natsService struct {
30+
opts NatsOptions
31+
// defaultConnectionOpts are additional options to pass to nats.Connect
32+
defaultConnectionOpts []nats.Option
33+
}
34+
35+
// Send implements NotificationService.
36+
func (n natsService) Send(notification Notification, dest Destination) error {
37+
var options []nats.Option
38+
options = append(options, n.defaultConnectionOpts...)
39+
40+
if n.opts.NKey != "" {
41+
// create nkey key pair from seed
42+
keyPair, err := nkeys.FromSeed([]byte(n.opts.NKey))
43+
if err != nil {
44+
return fmt.Errorf("failed to create NKey from seed: %w", err)
45+
}
46+
47+
// get the public nkey
48+
publicKey, err := keyPair.PublicKey()
49+
if err != nil {
50+
return fmt.Errorf("failed to get public NKey: %w", err)
51+
}
52+
53+
// add nkey authentication option
54+
options = append(options, nats.Nkey(publicKey, func(nonce []byte) ([]byte, error) {
55+
return keyPair.Sign(nonce)
56+
}))
57+
}
58+
59+
if n.opts.Username != "" && n.opts.Password != "" {
60+
options = append(options, nats.UserInfo(n.opts.Username, n.opts.Password))
61+
}
62+
63+
conn, err := nats.Connect(n.opts.Url, options...)
64+
if err != nil {
65+
return fmt.Errorf("failed to connect to NATS server: %w", err)
66+
}
67+
defer conn.Close()
68+
69+
msg := nats.NewMsg(dest.Recipient)
70+
msg.Data = []byte(notification.Message)
71+
72+
if len(n.opts.Headers) > 0 {
73+
msg.Header = make(nats.Header)
74+
for key, value := range n.opts.Headers {
75+
msg.Header.Set(key, value)
76+
}
77+
}
78+
79+
err = conn.PublishMsg(msg)
80+
if err != nil {
81+
return fmt.Errorf("failed to publish message to NATS: %w", err)
82+
}
83+
return nil
84+
}

0 commit comments

Comments
 (0)