Compare commits
22 Commits
Author | SHA1 | Date |
---|---|---|
|
a22d67edbb | |
|
955d24142c | |
|
e8a909fac7 | |
|
febff88be7 | |
|
5bea87e16b | |
|
a8c2fc0759 | |
|
6e18c487d7 | |
|
d1c85df902 | |
|
9e150256c7 | |
|
e4160c509c | |
|
fc4adfd030 | |
|
3f4e962c83 | |
|
98ecf2de79 | |
|
a3e6dd6a10 | |
|
8858332c27 | |
|
2503bda903 | |
|
fc126284ab | |
|
8f207d65db | |
|
61f24e3376 | |
|
3f4ba79594 | |
|
d65c81d035 | |
|
47b95d86a3 |
|
@ -5,7 +5,7 @@ updates:
|
|||
directory: "/"
|
||||
labels: ["dependencies"]
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
groups:
|
||||
go-deps:
|
||||
patterns:
|
||||
|
@ -27,4 +27,4 @@ updates:
|
|||
patterns:
|
||||
- "*"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
|
|
|
@ -25,3 +25,6 @@
|
|||
- name: backport:release/v1.5.x
|
||||
description: To be backported to release/v1.5.x
|
||||
color: '#ffd700'
|
||||
- name: backport:release/v1.6.x
|
||||
description: To be backported to release/v1.6.x
|
||||
color: '#ffd700'
|
||||
|
|
11
api/go.mod
11
api/go.mod
|
@ -3,8 +3,8 @@ module github.com/fluxcd/notification-controller/api
|
|||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0
|
||||
k8s.io/apimachinery v0.33.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0
|
||||
k8s.io/apimachinery v0.33.2
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
)
|
||||
|
||||
|
@ -21,8 +21,9 @@ require (
|
|||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
|
@ -30,5 +31,5 @@ require (
|
|||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
sigs.k8s.io/yaml v1.5.0 // indirect
|
||||
)
|
||||
|
|
25
api/go.sum
25
api/go.sum
|
@ -2,8 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0 h1:KVMDyJQj1NYCsppsFUkbJGMnKxsqJVpnKBFolHf/q8E=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
|
@ -54,6 +54,8 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
|||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
|
@ -63,8 +65,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -75,14 +77,14 @@ golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
|||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -96,8 +98,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
|
||||
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
|
||||
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
|
||||
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
|
@ -111,5 +113,6 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
|||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
|
||||
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=
|
||||
|
|
|
@ -97,12 +97,20 @@ type ProviderSpec struct {
|
|||
Timeout *metav1.Duration `json:"timeout,omitempty"`
|
||||
|
||||
// Proxy the HTTP/S address of the proxy server.
|
||||
// Deprecated: Use ProxySecretRef instead. Will be removed in v1.
|
||||
// +kubebuilder:validation:Pattern="^(http|https)://.*$"
|
||||
// +kubebuilder:validation:MaxLength:=2048
|
||||
// +kubebuilder:validation:Optional
|
||||
// +optional
|
||||
Proxy string `json:"proxy,omitempty"`
|
||||
|
||||
// ProxySecretRef specifies the Secret containing the proxy configuration
|
||||
// for this Provider. The Secret should contain an 'address' key with the
|
||||
// HTTP/S address of the proxy server. Optional 'username' and 'password'
|
||||
// keys can be provided for proxy authentication.
|
||||
// +optional
|
||||
ProxySecretRef *meta.LocalObjectReference `json:"proxySecretRef,omitempty"`
|
||||
|
||||
// SecretRef specifies the Secret containing the authentication
|
||||
// credentials for this Provider.
|
||||
// +optional
|
||||
|
@ -115,12 +123,17 @@ type ProviderSpec struct {
|
|||
// +optional
|
||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||
|
||||
// CertSecretRef specifies the Secret containing
|
||||
// a PEM-encoded CA certificate (in the `ca.crt` key).
|
||||
// +optional
|
||||
// CertSecretRef specifies the Secret containing TLS certificates
|
||||
// for secure communication.
|
||||
//
|
||||
// Note: Support for the `caFile` key has
|
||||
// been deprecated.
|
||||
// Supported configurations:
|
||||
// - CA-only: Server authentication (provide ca.crt only)
|
||||
// - mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
|
||||
// - Client-only: Client authentication with system CA (provide tls.crt + tls.key only)
|
||||
//
|
||||
// Legacy keys "caFile", "certFile", "keyFile" are supported but deprecated. Use "ca.crt", "tls.crt", "tls.key" instead.
|
||||
//
|
||||
// +optional
|
||||
CertSecretRef *meta.LocalObjectReference `json:"certSecretRef,omitempty"`
|
||||
|
||||
// Suspend tells the controller to suspend subsequent
|
||||
|
|
|
@ -196,6 +196,11 @@ func (in *ProviderSpec) DeepCopyInto(out *ProviderSpec) {
|
|||
*out = new(metav1.Duration)
|
||||
**out = **in
|
||||
}
|
||||
if in.ProxySecretRef != nil {
|
||||
in, out := &in.ProxySecretRef, &out.ProxySecretRef
|
||||
*out = new(meta.LocalObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
if in.SecretRef != nil {
|
||||
in, out := &in.SecretRef, &out.SecretRef
|
||||
*out = new(meta.LocalObjectReference)
|
||||
|
|
|
@ -443,11 +443,15 @@ spec:
|
|||
type: string
|
||||
certSecretRef:
|
||||
description: |-
|
||||
CertSecretRef specifies the Secret containing
|
||||
a PEM-encoded CA certificate (in the `ca.crt` key).
|
||||
CertSecretRef specifies the Secret containing TLS certificates
|
||||
for secure communication.
|
||||
|
||||
Note: Support for the `caFile` key has
|
||||
been deprecated.
|
||||
Supported configurations:
|
||||
- CA-only: Server authentication (provide ca.crt only)
|
||||
- mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
|
||||
- Client-only: Client authentication with system CA (provide tls.crt + tls.key only)
|
||||
|
||||
Legacy keys "caFile", "certFile", "keyFile" are supported but deprecated. Use "ca.crt", "tls.crt", "tls.key" instead.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
|
@ -475,10 +479,25 @@ spec:
|
|||
pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$
|
||||
type: string
|
||||
proxy:
|
||||
description: Proxy the HTTP/S address of the proxy server.
|
||||
description: |-
|
||||
Proxy the HTTP/S address of the proxy server.
|
||||
Deprecated: Use ProxySecretRef instead. Will be removed in v1.
|
||||
maxLength: 2048
|
||||
pattern: ^(http|https)://.*$
|
||||
type: string
|
||||
proxySecretRef:
|
||||
description: |-
|
||||
ProxySecretRef specifies the Secret containing the proxy configuration
|
||||
for this Provider. The Secret should contain an 'address' key with the
|
||||
HTTP/S address of the proxy server. Optional 'username' and 'password'
|
||||
keys can be provided for proxy authentication.
|
||||
properties:
|
||||
name:
|
||||
description: Name of the referent.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
secretRef:
|
||||
description: |-
|
||||
SecretRef specifies the Secret containing the authentication
|
||||
|
|
|
@ -330,7 +330,25 @@ string
|
|||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Proxy the HTTP/S address of the proxy server.</p>
|
||||
<p>Proxy the HTTP/S address of the proxy server.
|
||||
Deprecated: Use ProxySecretRef instead. Will be removed in v1.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>proxySecretRef</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
|
||||
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ProxySecretRef specifies the Secret containing the proxy configuration
|
||||
for this Provider. The Secret should contain an ‘address’ key with the
|
||||
HTTP/S address of the proxy server. Optional ‘username’ and ‘password’
|
||||
keys can be provided for proxy authentication.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -374,10 +392,13 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
|
|||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>CertSecretRef specifies the Secret containing
|
||||
a PEM-encoded CA certificate (in the <code>ca.crt</code> key).</p>
|
||||
<p>Note: Support for the <code>caFile</code> key has
|
||||
been deprecated.</p>
|
||||
<p>CertSecretRef specifies the Secret containing TLS certificates
|
||||
for secure communication.</p>
|
||||
<p>Supported configurations:
|
||||
- CA-only: Server authentication (provide ca.crt only)
|
||||
- mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
|
||||
- Client-only: Client authentication with system CA (provide tls.crt + tls.key only)</p>
|
||||
<p>Legacy keys “caFile”, “certFile”, “keyFile” are supported but deprecated. Use “ca.crt”, “tls.crt”, “tls.key” instead.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -650,7 +671,25 @@ string
|
|||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Proxy the HTTP/S address of the proxy server.</p>
|
||||
<p>Proxy the HTTP/S address of the proxy server.
|
||||
Deprecated: Use ProxySecretRef instead. Will be removed in v1.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>proxySecretRef</code><br>
|
||||
<em>
|
||||
<a href="https://pkg.go.dev/github.com/fluxcd/pkg/apis/meta#LocalObjectReference">
|
||||
github.com/fluxcd/pkg/apis/meta.LocalObjectReference
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>ProxySecretRef specifies the Secret containing the proxy configuration
|
||||
for this Provider. The Secret should contain an ‘address’ key with the
|
||||
HTTP/S address of the proxy server. Optional ‘username’ and ‘password’
|
||||
keys can be provided for proxy authentication.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -694,10 +733,13 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
|
|||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>CertSecretRef specifies the Secret containing
|
||||
a PEM-encoded CA certificate (in the <code>ca.crt</code> key).</p>
|
||||
<p>Note: Support for the <code>caFile</code> key has
|
||||
been deprecated.</p>
|
||||
<p>CertSecretRef specifies the Secret containing TLS certificates
|
||||
for secure communication.</p>
|
||||
<p>Supported configurations:
|
||||
- CA-only: Server authentication (provide ca.crt only)
|
||||
- mTLS: Mutual authentication (provide ca.crt + tls.crt + tls.key)
|
||||
- Client-only: Client authentication with system CA (provide tls.crt + tls.key only)</p>
|
||||
<p>Legacy keys “caFile”, “certFile”, “keyFile” are supported but deprecated. Use “ca.crt”, “tls.crt”, “tls.key” instead.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -284,7 +284,7 @@ field](https://api.slack.com/methods/chat.postMessage#arg_username) to the
|
|||
payload, defaulting to the name of the reporting controller.
|
||||
|
||||
This Provider type supports the configuration of a [proxy URL](#https-proxy)
|
||||
and/or [TLS certificates](#tls-certificates).
|
||||
and/or [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Slack example
|
||||
|
||||
|
@ -363,7 +363,7 @@ In both cases the Event metadata is attached as facts, and the involved object a
|
|||
The severity of the Event is used to set the color of the message.
|
||||
|
||||
This Provider type supports the configuration of a [proxy URL](#https-proxy)
|
||||
and/or [TLS certificates](#tls-certificates), but lacks support for
|
||||
and/or [certificate secret reference](#certificate-secret-reference), but lacks support for
|
||||
configuring a [Channel](#channel). This can be configured during the
|
||||
creation of the Incoming Webhook Workflow in Microsoft Teams.
|
||||
|
||||
|
@ -403,7 +403,7 @@ The Event will be formatted into a [DataDog Event](https://docs.datadoghq.com/ap
|
|||
API endpoint of the provided DataDog [Address](#address).
|
||||
|
||||
This Provider type supports the configuration of a [proxy URL](#https-proxy)
|
||||
and/or [TLS certificates](#tls-certificates).
|
||||
and/or [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
The metadata of the Event is included in the DataDog event as extra tags.
|
||||
|
||||
|
@ -459,7 +459,7 @@ The Event will be formatted into a [Slack message](#slack) and send to the
|
|||
`/slack` endpoint of the provided Discord [Address](#address).
|
||||
|
||||
This Provider type supports the configuration of a [proxy URL](#https-proxy)
|
||||
and/or [TLS certificates](#tls-certificates), but lacks support for
|
||||
and/or [certificate secret reference](#certificate-secret-reference), but lacks support for
|
||||
configuring a [Channel](#channel). This can be configured [during the creation
|
||||
of the address](https://discord.com/developers/docs/resources/webhook#create-webhook)
|
||||
|
||||
|
@ -507,7 +507,7 @@ The Provider's [Channel](#channel) is used to set the `environment` on the
|
|||
Sentry client.
|
||||
|
||||
This Provider type supports the configuration of
|
||||
[TLS certificates](#tls-certificates).
|
||||
[certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Sentry example
|
||||
|
||||
|
@ -544,7 +544,7 @@ stringData:
|
|||
##### Telegram
|
||||
|
||||
When `.spec.type` is set to `telegram`, the controller will send a payload for
|
||||
an [Event](events.md#event-structure) to the provided Telegram [Address](#address).
|
||||
an [Event](events.md#event-structure) to the Telegram Bot API.
|
||||
|
||||
The Event will be formatted into a message string, with the metadata attached
|
||||
as a list of key-value pairs.
|
||||
|
@ -554,15 +554,16 @@ This can be a unique identifier (`-1234567890`) for the target chat,
|
|||
a unique identifier with the topic identifier (`-1234567890:1`) for the forum chat,
|
||||
or the username (`@username`) of the target channel.
|
||||
|
||||
This Provider type does not support the configuration of a [proxy URL](#https-proxy)
|
||||
or [TLS certificates](#tls-certificates).
|
||||
This Provider type does not support the configuration of a [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
**Note:** The Telegram provider always ignores the `address` field and uses the default
|
||||
Telegram Bot API endpoint (`https://api.telegram.org`).
|
||||
|
||||
###### Telegram example
|
||||
|
||||
To configure a Provider for Telegram, create a Secret with [the `token`](#token-example)
|
||||
obtained from [the BotFather](https://core.telegram.org/bots#how-do-i-create-a-bot),
|
||||
and a `telegram` Provider with a [Secret reference](#secret-reference), and the
|
||||
`address` set to `https://api.telegram.org`.
|
||||
and a `telegram` Provider with a [Secret reference](#secret-reference).
|
||||
|
||||
```yaml
|
||||
---
|
||||
|
@ -573,7 +574,6 @@ metadata:
|
|||
namespace: default
|
||||
spec:
|
||||
type: telegram
|
||||
address: https://api.telegram.org
|
||||
channel: "@fluxcd" # or "-1557265138" (channel id) or "-1552289257:1" (forum chat id with topic id)
|
||||
secretRef:
|
||||
name: telegram-token
|
||||
|
@ -623,7 +623,7 @@ The Event will be formatted into a [Lark Message card](https://open.larksuite.co
|
|||
with the metadata written to the message string.
|
||||
|
||||
This Provider type does not support the configuration of a [proxy URL](#https-proxy)
|
||||
or [TLS certificates](#tls-certificates).
|
||||
or [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Lark example
|
||||
|
||||
|
@ -660,7 +660,7 @@ The Event will be formatted into a [Slack message](#slack) and send as a
|
|||
payload the provided Rocket [Address](#address).
|
||||
|
||||
This Provider type does support the configuration of a [proxy URL](#https-proxy)
|
||||
and [TLS certificates](#tls-certificates).
|
||||
and [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Rocket example
|
||||
|
||||
|
@ -742,7 +742,7 @@ You can optionally add [attributes](https://cloud.google.com/pubsub/docs/samples
|
|||
to the Pub/Sub message using a [`headers` key in the referenced Secret](#http-headers-example).
|
||||
|
||||
This Provider type does not support the configuration of a [proxy URL](#https-proxy)
|
||||
or [TLS certificates](#tls-certificates).
|
||||
or [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Google Pub/Sub with JSON Credentials and Custom Headers Example
|
||||
|
||||
|
@ -788,7 +788,7 @@ with the metadata added to the [`details` field](https://docs.opsgenie.com/docs/
|
|||
as a list of key-value pairs.
|
||||
|
||||
This Provider type does support the configuration of a [proxy URL](#https-proxy)
|
||||
and [TLS certificates](#tls-certificates).
|
||||
and [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Opsgenie example
|
||||
|
||||
|
@ -831,7 +831,7 @@ The provider will also send [Change Events](https://developer.pagerduty.com/api-
|
|||
for `info` level `Severity`, which will be displayed in the PagerDuty service's timeline to track changes.
|
||||
|
||||
This Provider type supports the configuration of a [proxy URL](#https-proxy)
|
||||
and [TLS certificates](#tls-certificates).
|
||||
and [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
The [Channel](#channel) is used to set the routing key to send the event to the appropriate integration.
|
||||
|
||||
|
@ -916,7 +916,7 @@ global:
|
|||
```
|
||||
|
||||
This Provider type does support the configuration of a [proxy URL](#https-proxy)
|
||||
and [TLS certificates](#tls-certificates).
|
||||
and [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Prometheus Alertmanager example
|
||||
|
||||
|
@ -988,7 +988,7 @@ The [Channel](#channel) is used to set the ID of the room to send the message
|
|||
to.
|
||||
|
||||
This Provider type does support the configuration of a [proxy URL](#https-proxy)
|
||||
and [TLS certificates](#tls-certificates).
|
||||
and [certificate secret reference](#certificate-secret-reference).
|
||||
|
||||
###### Webex example
|
||||
|
||||
|
@ -1097,7 +1097,7 @@ credentials for the provider API.
|
|||
The Kubernetes secret can have any of the following keys:
|
||||
|
||||
- `address` - overrides `.spec.address`
|
||||
- `proxy` - overrides `.spec.proxy`
|
||||
- `proxy` - overrides `.spec.proxy` (deprecated, use `.spec.proxySecretRef` instead. **Support for this key will be removed in v1**)
|
||||
- `token` - used for authentication
|
||||
- `username` - overrides `.spec.username`
|
||||
- `headers` - HTTP headers values included in the POST request
|
||||
|
@ -1155,7 +1155,7 @@ stringData:
|
|||
#### Proxy auth example
|
||||
|
||||
Some networks need to use an authenticated proxy to access external services.
|
||||
Therefore, the proxy address can be stored as a secret to hide parameters like the username and password:
|
||||
The recommended approach is to use `.spec.proxySecretRef` with a dedicated Secret:
|
||||
|
||||
```yaml
|
||||
---
|
||||
|
@ -1164,15 +1164,56 @@ kind: Secret
|
|||
metadata:
|
||||
name: my-provider-proxy
|
||||
namespace: default
|
||||
stringData:
|
||||
address: "http://proxy_url:proxy_port"
|
||||
username: "proxy_username"
|
||||
password: "proxy_password"
|
||||
```
|
||||
|
||||
**Legacy approach (deprecated):**
|
||||
The proxy address can also be stored in the main secret to hide parameters like the username and password:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: my-provider-proxy-legacy
|
||||
namespace: default
|
||||
stringData:
|
||||
proxy: "http://username:password@proxy_url:proxy_port"
|
||||
```
|
||||
|
||||
### TLS certificates
|
||||
### Certificate secret reference
|
||||
|
||||
`.spec.certSecretRef` is an optional field to specify a name reference to a
|
||||
Secret in the same namespace as the Provider, containing the TLS CA certificate.
|
||||
The secret must be of type `kubernetes.io/tls` or `Opaque`.
|
||||
Secret in the same namespace as the Provider, containing TLS certificates for
|
||||
secure communication. The secret must be of type `kubernetes.io/tls` or `Opaque`.
|
||||
|
||||
#### Supported configurations
|
||||
|
||||
- **CA-only**: Server authentication (provide `ca.crt` only)
|
||||
- **mTLS**: Client certificate authentication (provide `tls.crt` + `tls.key`, optionally with `ca.crt`)
|
||||
|
||||
#### Providers supporting client certificate authentication
|
||||
|
||||
The following webhook-based providers support client certificate authentication:
|
||||
|
||||
| Provider Type | Description |
|
||||
|---------------------|--------------------------------|
|
||||
| `alertmanager` | Prometheus Alertmanager |
|
||||
| `discord` | Discord webhooks |
|
||||
| `forwarder` | Generic forwarder |
|
||||
| `grafana` | Grafana annotations API |
|
||||
| `matrix` | Matrix rooms |
|
||||
| `msteams` | Microsoft Teams |
|
||||
| `opsgenie` | Opsgenie alerts |
|
||||
| `pagerduty` | PagerDuty events |
|
||||
| `rocket` | Rocket.Chat |
|
||||
| `slack` | Slack API |
|
||||
| `webex` | Webex messages |
|
||||
|
||||
Support for client certificate authentication is being expanded to additional providers over time.
|
||||
|
||||
#### Example
|
||||
|
||||
|
@ -1210,10 +1251,17 @@ the controller will log a deprecation warning.
|
|||
### HTTP/S proxy
|
||||
|
||||
`.spec.proxy` is an optional field to specify an HTTP/S proxy address.
|
||||
**Warning:** This field is deprecated, use `.spec.proxySecretRef` instead. **Support for this field will be removed in v1.**
|
||||
|
||||
`.spec.proxySecretRef` is an optional field to specify a name reference to a
|
||||
Secret in the same namespace as the Provider, containing the proxy configuration.
|
||||
The Secret should contain an `address` key with the HTTP/S address of the proxy server.
|
||||
Optional `username` and `password` keys can be provided for proxy authentication.
|
||||
|
||||
If the proxy address contains sensitive information such as basic auth credentials, it is
|
||||
recommended to store the proxy in the Kubernetes secret referenced by `.spec.secretRef.name`.
|
||||
When the referenced Secret contains a `proxy` key, the `.spec.proxy` value is ignored.
|
||||
recommended to use `.spec.proxySecretRef` instead of `.spec.proxy`.
|
||||
When `.spec.proxySecretRef` is specified, both `.spec.proxy` and the `proxy` key from
|
||||
`.spec.secretRef` are ignored.
|
||||
|
||||
### Timeout
|
||||
|
||||
|
@ -1305,10 +1353,8 @@ spec:
|
|||
|
||||
The `address` is the address of your repository where you want to send webhooks to trigger GitHub workflows.
|
||||
|
||||
GitHub uses [personal access
|
||||
tokens]((https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token))
|
||||
or [GitHub
|
||||
app]((https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation))
|
||||
GitHub uses [personal access tokens](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token)
|
||||
or [GitHub app](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation)
|
||||
for authentication with its API:
|
||||
|
||||
#### GitHub personal access token
|
||||
|
|
144
go.mod
144
go.mod
|
@ -10,64 +10,65 @@ require (
|
|||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6
|
||||
github.com/Azure/azure-amqp-common-go/v4 v4.2.0
|
||||
github.com/Azure/azure-event-hubs-go/v3 v3.6.2
|
||||
github.com/DataDog/datadog-api-client-go/v2 v2.37.1
|
||||
github.com/DataDog/datadog-api-client-go/v2 v2.42.0
|
||||
github.com/PagerDuty/go-pagerduty v1.8.0
|
||||
github.com/cdevents/sdk-go v0.4.1
|
||||
github.com/chainguard-dev/git-urls v1.0.2
|
||||
github.com/containrrr/shoutrrr v0.8.0
|
||||
github.com/elazarl/goproxy v1.7.2
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.13
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.14
|
||||
github.com/fluxcd/notification-controller/api v1.6.0
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0
|
||||
github.com/fluxcd/pkg/auth v0.16.0
|
||||
github.com/fluxcd/pkg/cache v0.9.0
|
||||
github.com/fluxcd/pkg/git v0.31.0
|
||||
github.com/fluxcd/pkg/apis/event v0.18.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0
|
||||
github.com/fluxcd/pkg/auth v0.21.0
|
||||
github.com/fluxcd/pkg/cache v0.10.0
|
||||
github.com/fluxcd/pkg/git v0.34.0
|
||||
github.com/fluxcd/pkg/masktoken v0.7.0
|
||||
github.com/fluxcd/pkg/runtime v0.60.0
|
||||
github.com/fluxcd/pkg/ssa v0.48.0
|
||||
github.com/fluxcd/pkg/ssh v0.18.0
|
||||
github.com/getsentry/sentry-go v0.32.0
|
||||
github.com/go-logr/logr v1.4.2
|
||||
github.com/google/cel-go v0.23.2
|
||||
github.com/fluxcd/pkg/runtime v0.69.0
|
||||
github.com/fluxcd/pkg/ssa v0.51.0
|
||||
github.com/fluxcd/pkg/ssh v0.20.0
|
||||
github.com/getsentry/sentry-go v0.34.1
|
||||
github.com/go-logr/logr v1.4.3
|
||||
github.com/google/cel-go v0.25.0
|
||||
github.com/google/go-github/v64 v64.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7
|
||||
github.com/ktrysmt/go-bitbucket v0.9.85
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8
|
||||
github.com/ktrysmt/go-bitbucket v0.9.86
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops/v6 v6.0.1
|
||||
github.com/nats-io/nats.go v1.41.2
|
||||
github.com/nats-io/nats.go v1.43.0
|
||||
github.com/onsi/gomega v1.37.0
|
||||
github.com/sethvargo/go-limiter v1.0.0
|
||||
github.com/slok/go-http-metrics v0.13.0
|
||||
github.com/spf13/pflag v1.0.6
|
||||
github.com/stretchr/testify v1.10.0
|
||||
gitlab.com/gitlab-org/api/client-go v0.122.0
|
||||
gitlab.com/gitlab-org/api/client-go v0.134.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/text v0.25.0
|
||||
google.golang.org/api v0.230.0
|
||||
k8s.io/api v0.33.0
|
||||
k8s.io/apimachinery v0.33.0
|
||||
k8s.io/client-go v0.33.0
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e
|
||||
golang.org/x/text v0.27.0
|
||||
google.golang.org/api v0.241.0
|
||||
k8s.io/api v0.33.2
|
||||
k8s.io/apimachinery v0.33.2
|
||||
k8s.io/client-go v0.33.2
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
sigs.k8s.io/yaml v1.5.0
|
||||
)
|
||||
|
||||
// Fix CVE-2022-28948
|
||||
replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.20.0 // indirect
|
||||
cel.dev/expr v0.23.1 // indirect
|
||||
cloud.google.com/go v0.120.0 // indirect
|
||||
cloud.google.com/go/auth v0.16.0 // indirect
|
||||
cloud.google.com/go/auth v0.16.2 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||
cloud.google.com/go/iam v1.4.2 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
||||
cloud.google.com/go/iam v1.5.2 // indirect
|
||||
github.com/42wim/httpsig v1.2.2 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v65.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.3 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 // indirect
|
||||
github.com/Azure/go-amqp v1.3.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
|
@ -81,11 +82,12 @@ require (
|
|||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
||||
github.com/DataDog/zstd v1.5.2 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.2.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.15.0 // indirect
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.16.0 // indirect
|
||||
github.com/carapace-sh/carapace-shlex v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/cloudevents/sdk-go/v2 v2.15.2 // indirect
|
||||
|
@ -94,25 +96,24 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/devigned/tab v0.1.1 // indirect
|
||||
github.com/docker/cli v27.5.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
|
||||
github.com/docker/cli v28.2.2+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.10.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-logr/zapr v1.3.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||
|
@ -122,15 +123,14 @@ require (
|
|||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-containerregistry v0.20.3 // indirect
|
||||
github.com/google/go-github/v71 v71.0.0 // indirect
|
||||
github.com/google/go-containerregistry v0.20.6 // indirect
|
||||
github.com/google/go-github/v72 v72.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
|
@ -145,8 +145,6 @@ require (
|
|||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
|
@ -167,8 +165,8 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.63.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/prometheus/common v0.65.0 // indirect
|
||||
github.com/prometheus/procfs v0.17.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
|
||||
|
@ -180,39 +178,41 @@ require (
|
|||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.39.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
|
||||
google.golang.org/grpc v1.72.0 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||
google.golang.org/grpc v1.73.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.33.0 // indirect
|
||||
k8s.io/cli-runtime v0.33.0 // indirect
|
||||
k8s.io/component-base v0.33.0 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.33.2 // indirect
|
||||
k8s.io/cli-runtime v0.33.2 // indirect
|
||||
k8s.io/component-base v0.33.2 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
|
||||
k8s.io/kubectl v0.33.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 // indirect
|
||||
k8s.io/kubectl v0.33.2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.19.0 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.20.0 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.20.0 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
|
||||
)
|
||||
|
|
311
go.sum
311
go.sum
|
@ -1,20 +1,20 @@
|
|||
cel.dev/expr v0.20.0 h1:OunBvVCfvpWlt4dN7zg3FM6TDkzOePe1+foGJ9AXeeI=
|
||||
cel.dev/expr v0.20.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
|
||||
cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg=
|
||||
cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA=
|
||||
cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q=
|
||||
cloud.google.com/go/auth v0.16.0 h1:Pd8P1s9WkcrBE2n/PhAwKsdrR35V3Sg2II9B+ndM3CU=
|
||||
cloud.google.com/go/auth v0.16.0/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI=
|
||||
cloud.google.com/go/auth v0.16.2 h1:QvBAGFPLrDeoiNjyfVunhQ10HKNYuOwZ5noee0M5df4=
|
||||
cloud.google.com/go/auth v0.16.2/go.mod h1:sRBas2Y1fB1vZTdurouM0AzuYQBMZinrUYL8EufhtEA=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
cloud.google.com/go/iam v1.4.2 h1:4AckGYAYsowXeHzsn/LCKWIwSWLkdb0eGjH8wWkd27Q=
|
||||
cloud.google.com/go/iam v1.4.2/go.mod h1:REGlrt8vSlh4dfCJfSEcNjLGq75wW75c5aU3FLOYq34=
|
||||
cloud.google.com/go/kms v1.21.1 h1:r1Auo+jlfJSf8B7mUnVw5K0fI7jWyoUy65bV53VjKyk=
|
||||
cloud.google.com/go/kms v1.21.1/go.mod h1:s0wCyByc9LjTdCjG88toVs70U9W+cc6RKFc8zAqX7nE=
|
||||
cloud.google.com/go/longrunning v0.6.5 h1:sD+t8DO8j4HKW4QfouCklg7ZC1qC4uzVZt8iz3uTW+Q=
|
||||
cloud.google.com/go/longrunning v0.6.5/go.mod h1:Et04XK+0TTLKa5IPYryKf5DkpwImy6TluQ1QTLwlKmY=
|
||||
cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
|
||||
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
|
||||
cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
|
||||
cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
|
||||
cloud.google.com/go/kms v1.21.2 h1:c/PRUSMNQ8zXrc1sdAUnsenWWaNXN+PzTXfXOcSFdoE=
|
||||
cloud.google.com/go/kms v1.21.2/go.mod h1:8wkMtHV/9Z8mLXEXr1GK7xPSBdi6knuLXIhqjuWcI6w=
|
||||
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
|
||||
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
|
||||
cloud.google.com/go/pubsub v1.49.0 h1:5054IkbslnrMCgA2MAEPcsN3Ky+AyMpEZcii/DoySPo=
|
||||
cloud.google.com/go/pubsub v1.49.0/go.mod h1:K1FswTWP+C1tI/nfi3HQecoVeFvL4HUOB1tdaNXKhUY=
|
||||
code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
|
||||
|
@ -35,8 +35,12 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3Vp
|
|||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.3 h1:ldKsKtEIblsgsr6mPwrd9yRntoX6uLz/K89wsldwx/k=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.3/go.mod h1:MAm7bk0oDLmD8yIkvfbxPW04fxzphPyL+7GzwHxOp6Y=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0 h1:figxyQZXzZQIcP3njhC68bYUiTw45J8/SsHaLW8Ax0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0/go.mod h1:TmlMW4W5OvXOmOyKNnor8nlMMiO1ctIyzmHme/VHsrA=
|
||||
github.com/Azure/go-amqp v1.3.0 h1://1rikYhoIQNXJFXyoO/Rlb4+4EkHYfJceNtLlys2/4=
|
||||
github.com/Azure/go-amqp v1.3.0/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
|
@ -70,16 +74,16 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mo
|
|||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DataDog/datadog-api-client-go/v2 v2.37.1 h1:weZhrGMO//sMEoSKWngoSQwMp4zBSlEX4p3/YWy9ltw=
|
||||
github.com/DataDog/datadog-api-client-go/v2 v2.37.1/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U=
|
||||
github.com/DataDog/datadog-api-client-go/v2 v2.42.0 h1:0L03LqChbOf7IaaiBUZpXi1Ss6PseGGhQEQrNqD9nU8=
|
||||
github.com/DataDog/datadog-api-client-go/v2 v2.42.0/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U=
|
||||
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
|
||||
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||
github.com/PagerDuty/go-pagerduty v1.8.0 h1:MTFqTffIcAervB83U7Bx6HERzLbyaSPL/+oxH3zyluI=
|
||||
github.com/PagerDuty/go-pagerduty v1.8.0/go.mod h1:nzIeAqyFSJAFkjWKvMzug0JtwDg+V+UoCWjFrfFH5mI=
|
||||
github.com/ProtonMail/go-crypto v1.2.0 h1:+PhXXn4SPGd+qk76TlEePBfOfivE0zkWFenhGhFLzWs=
|
||||
github.com/ProtonMail/go-crypto v1.2.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
|
@ -88,8 +92,10 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
|||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.15.0 h1:7r2rPUM04rgszMP0U1UZ1M5VoVVIlsaBSnpABfYxcQY=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.15.0/go.mod h1:PoH9Vhy82OeRFZfxsVrk3mfQhVkEzou9OOwPOsEhiXE=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.16.0 h1:B91r9bHtXp/+XRgS5aZm6ZzTdz3ahgJYmkt4xZkgDz8=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.16.0/go.mod h1:OeVe5ggFzoBnmgitZe/A+BqGOnv1DvU/0uiLQi1wutM=
|
||||
github.com/carapace-sh/carapace-shlex v1.0.1 h1:ww0JCgWpOVuqWG7k3724pJ18Lq8gh5pHQs9j3ojUs1c=
|
||||
github.com/carapace-sh/carapace-shlex v1.0.1/go.mod h1:lJ4ZsdxytE0wHJ8Ta9S7Qq0XpjgjU0mdfCqiI2FHx7M=
|
||||
github.com/cdevents/sdk-go v0.4.1 h1:Cr/iH/I51Z+slxKRx9AV7stn6hr2pjRHQ5wpPJhRLTU=
|
||||
github.com/cdevents/sdk-go v0.4.1/go.mod h1:3IhWLoY4vsyUEzv7XJbyr0BRQ0KPgvNx+wiD2hQGFNU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
|
@ -105,8 +111,6 @@ github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6
|
|||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/containrrr/shoutrrr v0.8.0 h1:mfG2ATzIS7NR2Ec6XL+xyoHzN97H8WPjir8aYzJUSec=
|
||||
github.com/containrrr/shoutrrr v0.8.0/go.mod h1:ioyQAyu1LJY6sILuNyKaQaw+9Ttik5QePU8atnAdO2o=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
|
@ -128,14 +132,14 @@ github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TR
|
|||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM=
|
||||
github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
||||
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||
github.com/docker/cli v28.2.2+incompatible h1:qzx5BNUDFqlvyq4AHzdNB7gSyVTmU4cgsyN9SdInc1A=
|
||||
github.com/docker/cli v28.2.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
|
@ -150,40 +154,40 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
|||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.13 h1:2X5yjz/rk9mg7+bMFBDZKGKzeZpAmY2s6iwbNZz7OzM=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.13/go.mod h1:b2iSoIeDTtjfCB0IKtGgqlhhvWa1oux3e90CjOf81oA=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.14 h1:I//AMVUXTc+M04UtIXArMXQZCazGMwfemodV1j/yG8c=
|
||||
github.com/fluxcd/cli-utils v0.36.0-flux.14/go.mod h1:uDo7BYOfbdmk/asnHuI0IQPl6u0FCgcN54AHDu3Y5As=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0 h1:foEINE++pCJlWVhWjYDXfkVmGKu8mQ4BDBlbYi5NU7M=
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0/go.mod h1:0fLhLFiHlRTDKPDXdRnv+tS7mCMIQ0fJxnEfmvGM/5A=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.10.0 h1:47EeSzkQvlQZdH92vHMe2lK2iR8aOSEJq95avw5idts=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.10.0/go.mod h1:UsqMV4sqNa1Yg0pmTsdkHRJr7bafBOENIJoAN+3ezaQ=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
|
||||
github.com/fluxcd/pkg/auth v0.16.0 h1:YEjSaNqlpYoXfoFAGhU/Z8y0322nGsT24W6zCh+sbGw=
|
||||
github.com/fluxcd/pkg/auth v0.16.0/go.mod h1:+BRnAO61Nr6fACEjJS6eNRdOk1nXhX/FCPylYn1ypNc=
|
||||
github.com/fluxcd/pkg/cache v0.9.0 h1:EGKfOLMG3fOwWnH/4Axl5xd425mxoQbZzlZoLfd8PDk=
|
||||
github.com/fluxcd/pkg/cache v0.9.0/go.mod h1:jMwabjWfsC5lW8hE7NM3wtGNwSJ38Javx6EKbEi7INU=
|
||||
github.com/fluxcd/pkg/git v0.31.0 h1:hVUJcRujNa+GA5zrjrMpuVcgHbCBjfq0CZIZJqJl22I=
|
||||
github.com/fluxcd/pkg/git v0.31.0/go.mod h1:rUgLXVQGBkBggHOLVMhHMHaweQ8Oc6HwZiN2Zm08Zxs=
|
||||
github.com/fluxcd/pkg/apis/event v0.18.0 h1:PNbWk9gvX8gMIi6VsJapnuDO+giLEeY+6olLVXvXFkk=
|
||||
github.com/fluxcd/pkg/apis/event v0.18.0/go.mod h1:7S/DGboLolfbZ6stO6dcDhG1SfkPWQ9foCULvbiYpiA=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0 h1:0IzDgxZkc4v+5SDNCvgZhfwfkdkQLPXCner7TNaJFWE=
|
||||
github.com/fluxcd/pkg/apis/kustomize v1.11.0/go.mod h1:j302mJGDww8cn9qvMsRQ0LJ1HPAPs/IlX7CSsoJV7BI=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0 h1:KVMDyJQj1NYCsppsFUkbJGMnKxsqJVpnKBFolHf/q8E=
|
||||
github.com/fluxcd/pkg/apis/meta v1.17.0/go.mod h1:97l3hTwBpJbXBY+wetNbqrUsvES8B1jGioKcBUxmqd8=
|
||||
github.com/fluxcd/pkg/auth v0.21.0 h1:ckAQqP12wuptXEkMY18SQKWEY09m9e6yI0mEMsDV15M=
|
||||
github.com/fluxcd/pkg/auth v0.21.0/go.mod h1:MXmpsXT97c874HCw5hnfqFUP7TsG8/Ss1vFrk8JccfM=
|
||||
github.com/fluxcd/pkg/cache v0.10.0 h1:M+OGDM4da1cnz7q+sZSBtkBJHpiJsLnKVmR9OdMWxEY=
|
||||
github.com/fluxcd/pkg/cache v0.10.0/go.mod h1:pPXRzQUDQagsCniuOolqVhnAkbNgYOg8d2cTliPs7ME=
|
||||
github.com/fluxcd/pkg/git v0.34.0 h1:qTViWkfpEDnjzySyKRKliqUeGj/DznqlkmPhaDNIsFY=
|
||||
github.com/fluxcd/pkg/git v0.34.0/go.mod h1:F9Asm3MlLW4uZx3FF92+bqho+oktdMdnTn/QmXe56NE=
|
||||
github.com/fluxcd/pkg/masktoken v0.7.0 h1:pitmyOg2pUVdW+nn2Lk/xqm2TaA08uxvOC0ns3sz6bM=
|
||||
github.com/fluxcd/pkg/masktoken v0.7.0/go.mod h1:Lc1uoDjO1GY6+YdkK+ZqqBIBWquyV58nlSJ5S1N1IYU=
|
||||
github.com/fluxcd/pkg/runtime v0.60.0 h1:d++EkV3FlycB+bzakB5NumwY4J8xts8i7lbvD6jBLeU=
|
||||
github.com/fluxcd/pkg/runtime v0.60.0/go.mod h1:UeU0/eZLErYC/1bTmgzBfNXhiHy9fuQzjfLK0HxRgxY=
|
||||
github.com/fluxcd/pkg/ssa v0.48.0 h1:DW+4DG8L/yZEi30UltOEXPB1d/ZFn4HfVhpJQp5oc2o=
|
||||
github.com/fluxcd/pkg/ssa v0.48.0/go.mod h1:T50TO0U2obLodZnrFgOrxollfBEy4V673OkM2aTUF1c=
|
||||
github.com/fluxcd/pkg/ssh v0.18.0 h1:SB0RrZ/YZIla3chTUulsfVmiCzJv5pEWfHM3dHMC8AU=
|
||||
github.com/fluxcd/pkg/ssh v0.18.0/go.mod h1:G5o0ZD7iR3KFoG5gPnFelX243ciI/PIiVW7J4eBrt5Y=
|
||||
github.com/fluxcd/pkg/runtime v0.69.0 h1:5gPY95NSFI34GlQTj0+NHjOFpirSwviCUb9bM09b5nA=
|
||||
github.com/fluxcd/pkg/runtime v0.69.0/go.mod h1:ug+pat+I4wfOBuCy2E/pLmBNd3kOOo4cP2jxnxefPwY=
|
||||
github.com/fluxcd/pkg/ssa v0.51.0 h1:sFarxKZcS0J8sjq9qvs/r+1XiJqNgRodEiPjV75F8R4=
|
||||
github.com/fluxcd/pkg/ssa v0.51.0/go.mod h1:v+h9RC0JxWIqMTK2Eo+8Nh700AXyZChZ2TiLVj4tf3M=
|
||||
github.com/fluxcd/pkg/ssh v0.20.0 h1:Ak0laIYIc/L8lEfqls/LDWRW8wYPESGaravQsCRGLb8=
|
||||
github.com/fluxcd/pkg/ssh v0.20.0/go.mod h1:sRfAAkxx1GwCGjYirKPnTKdNkNrJRo9kqzWLVFXKv7E=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY=
|
||||
github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY=
|
||||
github.com/getsentry/sentry-go v0.34.1 h1:HSjc1C/OsnZttohEPrrqKH42Iud0HuLCXpv8cU1pWcw=
|
||||
github.com/getsentry/sentry-go v0.34.1/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE=
|
||||
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||
|
@ -191,18 +195,18 @@ github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7
|
|||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
|
||||
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
|
@ -211,7 +215,6 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
|
@ -242,10 +245,10 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
|
|||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/cel-go v0.23.2 h1:UdEe3CvQh3Nv+E/j9r1Y//WO0K0cSyD7/y0bzyLIMI4=
|
||||
github.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo=
|
||||
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||
github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY=
|
||||
github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI=
|
||||
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
||||
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
|
@ -256,31 +259,29 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
|
||||
github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
|
||||
github.com/google/go-containerregistry v0.20.6 h1:cvWX87UxxLgaH76b4hIvya6Dzz9qHB31qAwjAohdSTU=
|
||||
github.com/google/go-containerregistry v0.20.6/go.mod h1:T0x8MuoAoKX/873bkeSfLD2FAkwCDf9/HZgsFJ02E2Y=
|
||||
github.com/google/go-github/v64 v64.0.0 h1:4G61sozmY3eiPAjjoOHponXDBONm+utovTKbyUb2Qdg=
|
||||
github.com/google/go-github/v64 v64.0.0/go.mod h1:xB3vqMQNdHzilXBiO2I+M7iEFtHf+DP/omBOv6tQzVo=
|
||||
github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30=
|
||||
github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M=
|
||||
github.com/google/go-github/v72 v72.0.0 h1:FcIO37BLoVPBO9igQQ6tStsv2asG4IPcYFi655PPvBM=
|
||||
github.com/google/go-github/v72 v72.0.0/go.mod h1:WWtw8GMRiL62mvIquf1kO3onRHeWWKmK01qdCY8c5fg=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ=
|
||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
||||
github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0=
|
||||
github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||
|
@ -289,14 +290,12 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
|
|||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
|
||||
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
|
@ -318,8 +317,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/ktrysmt/go-bitbucket v0.9.85 h1:WSKYSmpgasEmtnsr+TEhD2UtiZjCZpeTBF5T4f6/d8k=
|
||||
github.com/ktrysmt/go-bitbucket v0.9.85/go.mod h1:ZgvxUOaC6eHrNaC/DbjFvJUXaKpKeDYvfhh4U592jcs=
|
||||
github.com/ktrysmt/go-bitbucket v0.9.86 h1:co80t9wS4kKgRLsvDgi+3wQPiLY30u10ehcTxgXFvzw=
|
||||
github.com/ktrysmt/go-bitbucket v0.9.86/go.mod h1:/lsYmiQrBHNPTnPKF0Q+safIS7peInQOGbJXu0xPRho=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
|
@ -330,7 +329,6 @@ github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4
|
|||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops/v6 v6.0.1 h1:ACnM5CwgTH6OSQHErzZDrotEG0rffPdJxtF/WOWglAw=
|
||||
|
@ -356,8 +354,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
|
|||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/nats-io/nats.go v1.41.2 h1:5UkfLAtu/036s99AhFRlyNDI1Ieylb36qbGjJzHixos=
|
||||
github.com/nats-io/nats.go v1.41.2/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nats.go v1.43.0 h1:uRFZ2FEoRvP64+UUhaTokyS18XBCR/xM2vQZKO4i8ug=
|
||||
github.com/nats-io/nats.go v1.43.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
|
||||
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
|
||||
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
|
@ -386,10 +384,10 @@ github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8
|
|||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
|
@ -434,28 +432,28 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
|||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
gitlab.com/gitlab-org/api/client-go v0.122.0 h1:Nog85APtgquS+HHkMkP4DiZ6lXlUZYhQKqguS4OJYNM=
|
||||
gitlab.com/gitlab-org/api/client-go v0.122.0/go.mod h1:Jh0qjLILEdbO6z/OY94RD+3NDQRUKiuFSFYozN6cpKM=
|
||||
gitlab.com/gitlab-org/api/client-go v0.134.0 h1:J4i6qPN5hRLsqatPxVbe9w2C0A3JEItyCQrzsP52S2k=
|
||||
gitlab.com/gitlab-org/api/client-go v0.134.0/go.mod h1:crkp9sCwMQ8gDwuMLgk11sDT336t6U3kESBT0BGsOBo=
|
||||
go.einride.tech/aip v0.68.1 h1:16/AfSxcQISGN5z9C5lM+0mLYXihrHbQ1onvYTr93aQ=
|
||||
go.einride.tech/aip v0.68.1/go.mod h1:XaFtaj4HuA3Zwk9xoBtTWgNubZ0ZZXv9BZJCkuKuWbg=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
|
@ -464,14 +462,18 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
|||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
|
@ -480,8 +482,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
|
|||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -493,8 +495,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
|
@ -503,8 +505,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -514,21 +516,19 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
|
@ -537,34 +537,34 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
|||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
|
||||
google.golang.org/api v0.230.0 h1:2u1hni3E+UXAXrONrrkfWpi/V6cyKVAbfGVeGtC3OxM=
|
||||
google.golang.org/api v0.230.0/go.mod h1:aqvtoMk7YkiXx+6U12arQFExiRV9D/ekvMCwCd/TksQ=
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
|
||||
google.golang.org/api v0.241.0 h1:QKwqWQlkc6O895LchPEDUSYr22Xp3NCxpQRiWTB6avE=
|
||||
google.golang.org/api v0.241.0/go.mod h1:cOVEm2TpdAGHL2z+UwyS+kmlGr3bVWQQ6sYEqkKje50=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78=
|
||||
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -592,38 +592,39 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
|||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
|
||||
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
|
||||
k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=
|
||||
k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=
|
||||
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/cli-runtime v0.33.0 h1:Lbl/pq/1o8BaIuyn+aVLdEPHVN665tBAXUePs8wjX7c=
|
||||
k8s.io/cli-runtime v0.33.0/go.mod h1:QcA+r43HeUM9jXFJx7A+yiTPfCooau/iCcP1wQh4NFw=
|
||||
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
|
||||
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
|
||||
k8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk=
|
||||
k8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU=
|
||||
k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
|
||||
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
|
||||
k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8=
|
||||
k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8=
|
||||
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
|
||||
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/cli-runtime v0.33.2 h1:koNYQKSDdq5AExa/RDudXMhhtFasEg48KLS2KSAU74Y=
|
||||
k8s.io/cli-runtime v0.33.2/go.mod h1:gnhsAWpovqf1Zj5YRRBBU7PFsRc6NkEkwYNQE+mXL88=
|
||||
k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
|
||||
k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
|
||||
k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0=
|
||||
k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
|
||||
k8s.io/kubectl v0.33.0 h1:HiRb1yqibBSCqic4pRZP+viiOBAnIdwYDpzUFejs07g=
|
||||
k8s.io/kubectl v0.33.0/go.mod h1:gAlGBuS1Jq1fYZ9AjGWbI/5Vk3M/VW2DK4g10Fpyn/0=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911 h1:gAXU86Fmbr/ktY17lkHwSjw5aoThQvhnstGGIYKlKYc=
|
||||
k8s.io/kube-openapi v0.0.0-20250701173324-9bd5c66d9911/go.mod h1:GLOk5B+hDbRROvt0X2+hqX64v/zO3vXN7J78OUmBSKw=
|
||||
k8s.io/kubectl v0.33.2 h1:7XKZ6DYCklu5MZQzJe+CkCjoGZwD1wWl7t/FxzhMz7Y=
|
||||
k8s.io/kubectl v0.33.2/go.mod h1:8rC67FB8tVTYraovAGNi/idWIK90z2CHFNMmGJZJ3KI=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
|
||||
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ=
|
||||
sigs.k8s.io/kustomize/api v0.19.0/go.mod h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o=
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0 h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA=
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0/go.mod h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY=
|
||||
sigs.k8s.io/kustomize/api v0.20.0 h1:xPLqcobHI0bThyRUteO+nCV8G4d1Rlo5HafO57VRcas=
|
||||
sigs.k8s.io/kustomize/api v0.20.0/go.mod h1:F6CfaV27oevRCMJgehLqyX81dlUnRX/Fc13Uo7+OSo4=
|
||||
sigs.k8s.io/kustomize/kyaml v0.20.0 h1:tT8KMKi4R3hCJ1+9HDdek2VoXpkerP92ZfF6fDgGw14=
|
||||
sigs.k8s.io/kustomize/kyaml v0.20.0/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
|
||||
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
@ -32,10 +32,10 @@ import (
|
|||
)
|
||||
|
||||
type Alertmanager struct {
|
||||
URL string
|
||||
ProxyURL string
|
||||
CertPool *x509.CertPool
|
||||
Token string
|
||||
URL string
|
||||
ProxyURL string
|
||||
TLSConfig *tls.Config
|
||||
Token string
|
||||
}
|
||||
|
||||
type AlertManagerAlert struct {
|
||||
|
@ -74,17 +74,17 @@ func (a *AlertManagerTime) UnmarshalJSON(jsonRepr []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func NewAlertmanager(hookURL string, proxyURL string, certPool *x509.CertPool, token string) (*Alertmanager, error) {
|
||||
func NewAlertmanager(hookURL string, proxyURL string, tlsConfig *tls.Config, token string) (*Alertmanager, error) {
|
||||
_, err := url.ParseRequestURI(hookURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid Alertmanager URL %s: '%w'", hookURL, err)
|
||||
}
|
||||
|
||||
return &Alertmanager{
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
CertPool: certPool,
|
||||
Token: token,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Token: token,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -141,8 +141,8 @@ func (s *Alertmanager) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if s.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(s.ProxyURL))
|
||||
}
|
||||
if s.CertPool != nil {
|
||||
opts = append(opts, withCertPool(s.CertPool))
|
||||
if s.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(s.TLSConfig))
|
||||
}
|
||||
if s.Token != "" {
|
||||
opts = append(opts, withRequestModifier(func(request *retryablehttp.Request) {
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -43,10 +43,10 @@ func Fuzz_AlertManager(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
alertmanager, err := NewAlertmanager(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &cert, "")
|
||||
alertmanager, err := NewAlertmanager(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &tlsConfig, "")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -20,16 +20,15 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-amqp-common-go/v4/auth"
|
||||
azauth "github.com/Azure/azure-amqp-common-go/v4/auth"
|
||||
eventhub "github.com/Azure/azure-event-hubs-go/v3"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
pkgauth "github.com/fluxcd/pkg/auth"
|
||||
"github.com/fluxcd/pkg/auth"
|
||||
"github.com/fluxcd/pkg/auth/azure"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
pkgcache "github.com/fluxcd/pkg/cache"
|
||||
|
||||
"github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
)
|
||||
|
@ -40,7 +39,9 @@ type AzureEventHub struct {
|
|||
}
|
||||
|
||||
// NewAzureEventHub creates a eventhub client
|
||||
func NewAzureEventHub(ctx context.Context, endpointURL, token, eventHubNamespace, proxy, serviceAccountName, providerName, providerNamespace string, tokenClient client.Client, tokenCache *pkgcache.TokenCache) (*AzureEventHub, error) {
|
||||
func NewAzureEventHub(ctx context.Context, endpointURL, token, eventHubNamespace, proxy,
|
||||
serviceAccountName, providerName, providerNamespace string, tokenClient client.Client,
|
||||
tokenCache *cache.TokenCache) (*AzureEventHub, error) {
|
||||
var hub *eventhub.Hub
|
||||
var err error
|
||||
|
||||
|
@ -109,9 +110,9 @@ func NewJWTProvider(jwt string) *PureJWT {
|
|||
}
|
||||
|
||||
// GetToken uses a JWT token, we assume that we will get new tokens when needed, thus no Expiry defined
|
||||
func (j *PureJWT) GetToken(uri string) (*auth.Token, error) {
|
||||
return &auth.Token{
|
||||
TokenType: auth.CBSTokenTypeJWT,
|
||||
func (j *PureJWT) GetToken(uri string) (*azauth.Token, error) {
|
||||
return &azauth.Token{
|
||||
TokenType: azauth.CBSTokenTypeJWT,
|
||||
Token: j.jwt,
|
||||
Expiry: "",
|
||||
}, nil
|
||||
|
@ -139,14 +140,15 @@ func newSASHub(address string) (*eventhub.Hub, error) {
|
|||
}
|
||||
|
||||
// newManagedIdentityToken is used to attempt credential-free authentication.
|
||||
func newManagedIdentityToken(ctx context.Context, proxy, serviceAccountName, providerName, providerNamespace string, tokenClient client.Client, tokenCache *pkgcache.TokenCache) (string, error) {
|
||||
opts := []pkgauth.Option{pkgauth.WithScopes(azure.ScopeEventHubs)}
|
||||
func newManagedIdentityToken(ctx context.Context, proxy, serviceAccountName, providerName,
|
||||
providerNamespace string, tokenClient client.Client, tokenCache *cache.TokenCache) (string, error) {
|
||||
opts := []auth.Option{auth.WithScopes(azure.ScopeEventHubs)}
|
||||
if proxy != "" {
|
||||
proxyURL, err := url.Parse(proxy)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing proxy URL : %w", err)
|
||||
}
|
||||
opts = append(opts, pkgauth.WithProxyURL(*proxyURL))
|
||||
opts = append(opts, auth.WithProxyURL(*proxyURL))
|
||||
}
|
||||
|
||||
if serviceAccountName != "" {
|
||||
|
@ -154,7 +156,7 @@ func newManagedIdentityToken(ctx context.Context, proxy, serviceAccountName, pro
|
|||
Name: serviceAccountName,
|
||||
Namespace: providerNamespace,
|
||||
}
|
||||
opts = append(opts, pkgauth.WithServiceAccount(serviceAccount, tokenClient))
|
||||
opts = append(opts, auth.WithServiceAccount(serviceAccount, tokenClient))
|
||||
}
|
||||
|
||||
if tokenCache != nil {
|
||||
|
@ -164,10 +166,10 @@ func newManagedIdentityToken(ctx context.Context, proxy, serviceAccountName, pro
|
|||
Namespace: providerNamespace,
|
||||
Operation: OperationPost,
|
||||
}
|
||||
opts = append(opts, pkgauth.WithCache(*tokenCache, involvedObject))
|
||||
opts = append(opts, auth.WithCache(*tokenCache, involvedObject))
|
||||
}
|
||||
|
||||
token, err := pkgauth.GetToken(ctx, azure.Provider{}, opts...)
|
||||
token, err := auth.GetAccessToken(ctx, azure.Provider{}, opts...)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get token for azure event hub: %w", err)
|
||||
}
|
||||
|
@ -177,6 +179,10 @@ func newManagedIdentityToken(ctx context.Context, proxy, serviceAccountName, pro
|
|||
|
||||
// validateAuthOptions checks if the authentication options are valid
|
||||
func validateAuthOptions(endpointURL, token, serviceAccountName string) error {
|
||||
if endpointURL == "" {
|
||||
return fmt.Errorf("endpoint URL cannot be empty")
|
||||
}
|
||||
|
||||
if isSASAuth(endpointURL) {
|
||||
if err := validateSASAuth(token, serviceAccountName); err != nil {
|
||||
return err
|
||||
|
|
|
@ -47,7 +47,7 @@ func TestNewAzureEventHub(t *testing.T) {
|
|||
endpointURL: "azure-nc-eventhub",
|
||||
token: "",
|
||||
eventHubNamespace: "namespace",
|
||||
err: errors.New("failed to create a eventhub using managed identity failed to get token for azure event hub: failed to create provider access token for the controlller: ManagedIdentityCredential: failed to authenticate a system assigned identity. The endpoint responded with {\"error\":\"invalid_request\",\"error_description\":\"Identity not found\"}"),
|
||||
err: errors.New("failed to create a eventhub using managed identity failed to get token for azure event hub: failed to create provider access token for the controller: ManagedIdentityCredential: failed to authenticate a system assigned identity. The endpoint responded with {\"error\":\"invalid_request\",\"error_description\":\"Identity not found\"}"),
|
||||
},
|
||||
{
|
||||
name: "SAS auth with serviceAccountName set",
|
||||
|
@ -72,6 +72,13 @@ func TestNewAzureEventHub(t *testing.T) {
|
|||
eventHubNamespace: "namespace",
|
||||
err: errors.New("invalid authentication options: serviceAccountName and jwt token authentication cannot be set at the same time"),
|
||||
},
|
||||
{
|
||||
name: "empty endpoint URL",
|
||||
endpointURL: "",
|
||||
token: "test-token",
|
||||
eventHubNamespace: "namespace",
|
||||
err: errors.New("invalid authentication options: endpoint URL cannot be empty"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
@ -19,14 +19,11 @@ package notifier
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
|
@ -34,7 +31,7 @@ import (
|
|||
|
||||
type postOptions struct {
|
||||
proxy string
|
||||
certPool *x509.CertPool
|
||||
tlsConfig *tls.Config
|
||||
requestModifier func(*retryablehttp.Request)
|
||||
responseValidator func(statusCode int, body []byte) error
|
||||
}
|
||||
|
@ -103,9 +100,9 @@ func withProxy(proxy string) postOption {
|
|||
}
|
||||
}
|
||||
|
||||
func withCertPool(certPool *x509.CertPool) postOption {
|
||||
func withTLSConfig(tlsConfig *tls.Config) postOption {
|
||||
return func(opts *postOptions) {
|
||||
opts.certPool = certPool
|
||||
opts.tlsConfig = tlsConfig
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,12 +120,11 @@ func withResponseValidator(respValidator func(statusCode int, body []byte) error
|
|||
|
||||
func newHTTPClient(opts *postOptions) (*retryablehttp.Client, error) {
|
||||
httpClient := retryablehttp.NewClient()
|
||||
if opts.certPool != nil {
|
||||
httpClient.HTTPClient.Transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: opts.certPool,
|
||||
},
|
||||
}
|
||||
|
||||
transport := httpClient.HTTPClient.Transport.(*http.Transport)
|
||||
|
||||
if opts.tlsConfig != nil {
|
||||
transport.TLSClientConfig = opts.tlsConfig
|
||||
}
|
||||
|
||||
if opts.proxy != "" {
|
||||
|
@ -136,27 +132,7 @@ func newHTTPClient(opts *postOptions) (*retryablehttp.Client, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse proxy URL: %w", err)
|
||||
}
|
||||
|
||||
var tlsConfig *tls.Config
|
||||
if opts.certPool != nil {
|
||||
tlsConfig = &tls.Config{
|
||||
RootCAs: opts.certPool,
|
||||
}
|
||||
}
|
||||
|
||||
httpClient.HTTPClient.Transport = &http.Transport{
|
||||
Proxy: http.ProxyURL(proxyURL),
|
||||
TLSClientConfig: tlsConfig,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 15 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
|
||||
}
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
|
||||
// Disable the timeout for the HTTP client,
|
||||
|
|
|
@ -18,6 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
@ -80,7 +81,8 @@ func Test_postSelfSignedCert(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
certpool := x509.NewCertPool()
|
||||
certpool.AddCert(cert)
|
||||
err = postMessage(context.Background(), ts.URL, map[string]string{"status": "success"}, withCertPool(certpool))
|
||||
tlsConfig := &tls.Config{RootCAs: certpool}
|
||||
err = postMessage(context.Background(), ts.URL, map[string]string{"status": "success"}, withTLSConfig(tlsConfig))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,13 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
pkgcache "github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
|
||||
apiv1 "github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
)
|
||||
|
@ -69,21 +70,24 @@ type notifierMap map[string]factoryFunc
|
|||
type factoryFunc func(opts notifierOptions) (Interface, error)
|
||||
|
||||
type notifierOptions struct {
|
||||
Context context.Context
|
||||
URL string
|
||||
ProxyURL string
|
||||
Username string
|
||||
Channel string
|
||||
Token string
|
||||
Headers map[string]string
|
||||
Context context.Context
|
||||
URL string
|
||||
ProxyURL string
|
||||
Username string
|
||||
Channel string
|
||||
Token string
|
||||
Headers map[string]string
|
||||
// CertPool is kept for Git platform providers (GitHub, GitLab, etc.) that use third-party SDKs.
|
||||
// TODO: Remove this field once all notifiers support client certificate authentication via TLSConfig.
|
||||
CertPool *x509.CertPool
|
||||
TLSConfig *tls.Config
|
||||
Password string
|
||||
CommitStatus string
|
||||
ProviderName string
|
||||
ProviderNamespace string
|
||||
SecretData map[string][]byte
|
||||
ServiceAccountName string
|
||||
TokenCache *pkgcache.TokenCache
|
||||
TokenCache *cache.TokenCache
|
||||
TokenClient client.Client
|
||||
}
|
||||
|
||||
|
@ -136,6 +140,13 @@ func WithCertPool(certPool *x509.CertPool) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// WithTLSConfig sets the TLS configuration for the notifier.
|
||||
func WithTLSConfig(tlsConfig *tls.Config) Option {
|
||||
return func(o *notifierOptions) {
|
||||
o.TLSConfig = tlsConfig
|
||||
}
|
||||
}
|
||||
|
||||
// WithPassword sets the password for the notifier.
|
||||
func WithPassword(password string) Option {
|
||||
return func(o *notifierOptions) {
|
||||
|
@ -172,7 +183,7 @@ func WithSecretData(data map[string][]byte) Option {
|
|||
}
|
||||
|
||||
// WithTokenCache sets the token cache for the notifier.
|
||||
func WithTokenCache(cache *pkgcache.TokenCache) Option {
|
||||
func WithTokenCache(cache *cache.TokenCache) Option {
|
||||
return func(o *notifierOptions) {
|
||||
o.TokenCache = cache
|
||||
}
|
||||
|
@ -192,11 +203,17 @@ func WithServiceAccount(serviceAccountName string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// NewFactory creates a new notifier factory with the given URL and optional configurations.
|
||||
func NewFactory(ctx context.Context, url string, opts ...Option) *Factory {
|
||||
// WithURL sets the webhook URL for the notifier.
|
||||
func WithURL(url string) Option {
|
||||
return func(o *notifierOptions) {
|
||||
o.URL = url
|
||||
}
|
||||
}
|
||||
|
||||
// NewFactory creates a new notifier factory with optional configurations.
|
||||
func NewFactory(ctx context.Context, opts ...Option) *Factory {
|
||||
options := notifierOptions{
|
||||
Context: ctx,
|
||||
URL: url,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
|
@ -209,36 +226,24 @@ func NewFactory(ctx context.Context, url string, opts ...Option) *Factory {
|
|||
}
|
||||
|
||||
func (f Factory) Notifier(provider string) (Interface, error) {
|
||||
if f.URL == "" {
|
||||
return &NopNotifier{}, nil
|
||||
notifier, ok := notifiers[provider]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("provider %s not supported", provider)
|
||||
}
|
||||
|
||||
var (
|
||||
n Interface
|
||||
err error
|
||||
)
|
||||
if notifier, ok := notifiers[provider]; ok {
|
||||
n, err = notifier(f.notifierOptions)
|
||||
} else {
|
||||
err = fmt.Errorf("provider %s not supported", provider)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
n = &NopNotifier{}
|
||||
}
|
||||
return n, err
|
||||
return notifier(f.notifierOptions)
|
||||
}
|
||||
|
||||
func genericNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewForwarder(opts.URL, opts.ProxyURL, opts.Headers, opts.CertPool, nil)
|
||||
return NewForwarder(opts.URL, opts.ProxyURL, opts.Headers, opts.TLSConfig, nil)
|
||||
}
|
||||
|
||||
func genericHMACNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewForwarder(opts.URL, opts.ProxyURL, opts.Headers, opts.CertPool, []byte(opts.Token))
|
||||
return NewForwarder(opts.URL, opts.ProxyURL, opts.Headers, opts.TLSConfig, []byte(opts.Token))
|
||||
}
|
||||
|
||||
func slackNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewSlack(opts.URL, opts.ProxyURL, opts.Token, opts.CertPool, opts.Username, opts.Channel)
|
||||
return NewSlack(opts.URL, opts.ProxyURL, opts.Token, opts.TLSConfig, opts.Username, opts.Channel)
|
||||
}
|
||||
|
||||
func discordNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
|
@ -246,11 +251,11 @@ func discordNotifierFunc(opts notifierOptions) (Interface, error) {
|
|||
}
|
||||
|
||||
func rocketNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewRocket(opts.URL, opts.ProxyURL, opts.CertPool, opts.Username, opts.Channel)
|
||||
return NewRocket(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Username, opts.Channel)
|
||||
}
|
||||
|
||||
func msteamsNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewMSTeams(opts.URL, opts.ProxyURL, opts.CertPool)
|
||||
return NewMSTeams(opts.URL, opts.ProxyURL, opts.TLSConfig)
|
||||
}
|
||||
|
||||
func googleChatNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
|
@ -262,7 +267,7 @@ func googlePubSubNotifierFunc(opts notifierOptions) (Interface, error) {
|
|||
}
|
||||
|
||||
func webexNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewWebex(opts.URL, opts.ProxyURL, opts.CertPool, opts.Channel, opts.Token)
|
||||
return NewWebex(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Channel, opts.Token)
|
||||
}
|
||||
|
||||
func sentryNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
|
@ -274,7 +279,7 @@ func azureEventHubNotifierFunc(opts notifierOptions) (Interface, error) {
|
|||
}
|
||||
|
||||
func telegramNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewTelegram(opts.Channel, opts.Token)
|
||||
return NewTelegram(opts.ProxyURL, opts.Channel, opts.Token)
|
||||
}
|
||||
|
||||
func larkNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
|
@ -282,23 +287,23 @@ func larkNotifierFunc(opts notifierOptions) (Interface, error) {
|
|||
}
|
||||
|
||||
func matrixNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewMatrix(opts.URL, opts.Token, opts.Channel, opts.CertPool)
|
||||
return NewMatrix(opts.URL, opts.Token, opts.Channel, opts.TLSConfig)
|
||||
}
|
||||
|
||||
func opsgenieNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewOpsgenie(opts.URL, opts.ProxyURL, opts.CertPool, opts.Token)
|
||||
return NewOpsgenie(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Token)
|
||||
}
|
||||
|
||||
func alertmanagerNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewAlertmanager(opts.URL, opts.ProxyURL, opts.CertPool, opts.Token)
|
||||
return NewAlertmanager(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Token)
|
||||
}
|
||||
|
||||
func grafanaNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewGrafana(opts.URL, opts.ProxyURL, opts.Token, opts.CertPool, opts.Username, opts.Password)
|
||||
return NewGrafana(opts.URL, opts.ProxyURL, opts.Token, opts.TLSConfig, opts.Username, opts.Password)
|
||||
}
|
||||
|
||||
func pagerDutyNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
return NewPagerDuty(opts.URL, opts.ProxyURL, opts.CertPool, opts.Channel)
|
||||
return NewPagerDuty(opts.URL, opts.ProxyURL, opts.TLSConfig, opts.Channel)
|
||||
}
|
||||
|
||||
func dataDogNotifierFunc(opts notifierOptions) (Interface, error) {
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
@ -37,14 +37,14 @@ const NotificationHeader = "gotk-component"
|
|||
// Forwarder is an implementation of the notification Interface that posts the
|
||||
// body as an HTTP request using an optional proxy.
|
||||
type Forwarder struct {
|
||||
URL string
|
||||
ProxyURL string
|
||||
Headers map[string]string
|
||||
CertPool *x509.CertPool
|
||||
HMACKey []byte
|
||||
URL string
|
||||
ProxyURL string
|
||||
Headers map[string]string
|
||||
TLSConfig *tls.Config
|
||||
HMACKey []byte
|
||||
}
|
||||
|
||||
func NewForwarder(hookURL string, proxyURL string, headers map[string]string, certPool *x509.CertPool, hmacKey []byte) (*Forwarder, error) {
|
||||
func NewForwarder(hookURL string, proxyURL string, headers map[string]string, tlsConfig *tls.Config, hmacKey []byte) (*Forwarder, error) {
|
||||
if _, err := url.ParseRequestURI(hookURL); err != nil {
|
||||
return nil, fmt.Errorf("invalid hook URL %s: %w", hookURL, err)
|
||||
}
|
||||
|
@ -54,11 +54,11 @@ func NewForwarder(hookURL string, proxyURL string, headers map[string]string, ce
|
|||
}
|
||||
|
||||
return &Forwarder{
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Headers: headers,
|
||||
CertPool: certPool,
|
||||
HMACKey: hmacKey,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Headers: headers,
|
||||
HMACKey: hmacKey,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,8 @@ func (f *Forwarder) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if f.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(f.ProxyURL))
|
||||
}
|
||||
if f.CertPool != nil {
|
||||
opts = append(opts, withCertPool(f.CertPool))
|
||||
if f.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(f.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(ctx, f.URL, event, opts...); err != nil {
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -41,13 +41,13 @@ func Fuzz_Forwarder(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
header := make(map[string]string)
|
||||
_ = fuzz.NewConsumer(seed).FuzzMap(&header)
|
||||
|
||||
forwarder, err := NewForwarder(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", header, &cert, hmacKey)
|
||||
forwarder, err := NewForwarder(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", header, &tlsConfig, hmacKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
"github.com/fluxcd/pkg/apis/meta"
|
||||
pkgcache "github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
)
|
||||
|
||||
type GitHub struct {
|
||||
|
@ -36,13 +36,17 @@ type GitHub struct {
|
|||
Client *github.Client
|
||||
}
|
||||
|
||||
func NewGitHub(commitStatus string, addr string, token string, certPool *x509.CertPool, proxyURL string, providerName string, providerNamespace string, secretData map[string][]byte, tokenCache *pkgcache.TokenCache) (*GitHub, error) {
|
||||
func NewGitHub(commitStatus string, addr string, token string, certPool *x509.CertPool,
|
||||
proxyURL string, providerName string, providerNamespace string, secretData map[string][]byte,
|
||||
tokenCache *cache.TokenCache) (*GitHub, error) {
|
||||
|
||||
// this should never happen
|
||||
if commitStatus == "" {
|
||||
return nil, errors.New("commit status cannot be empty")
|
||||
}
|
||||
|
||||
repoInfo, err := getRepoInfoAndGithubClient(addr, token, certPool, proxyURL, providerName, providerNamespace, secretData, tokenCache)
|
||||
repoInfo, err := getRepoInfoAndGithubClient(addr, token, certPool,
|
||||
proxyURL, providerName, providerNamespace, secretData, tokenCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
pkgcache "github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
|
||||
"github.com/google/go-github/v64/github"
|
||||
)
|
||||
|
@ -34,8 +34,12 @@ type GitHubDispatch struct {
|
|||
Client *github.Client
|
||||
}
|
||||
|
||||
func NewGitHubDispatch(addr string, token string, certPool *x509.CertPool, proxyURL string, providerName string, providerNamespace string, secretData map[string][]byte, tokenCache *pkgcache.TokenCache) (*GitHubDispatch, error) {
|
||||
repoInfo, err := getRepoInfoAndGithubClient(addr, token, certPool, proxyURL, providerName, providerNamespace, secretData, tokenCache)
|
||||
func NewGitHubDispatch(addr string, token string, certPool *x509.CertPool, proxyURL string,
|
||||
providerName string, providerNamespace string, secretData map[string][]byte,
|
||||
tokenCache *cache.TokenCache) (*GitHubDispatch, error) {
|
||||
|
||||
repoInfo, err := getRepoInfoAndGithubClient(addr, token, certPool,
|
||||
proxyURL, providerName, providerNamespace, secretData, tokenCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ func TestNewGithubDispatchProvider(t *testing.T) {
|
|||
kp, _ := ssh.GenerateKeyPair(ssh.RSA_4096)
|
||||
expiresAt := time.Now().UTC().Add(time.Hour)
|
||||
|
||||
var tests = []struct {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
secretData map[string][]byte
|
||||
wantErr error
|
||||
|
@ -85,7 +85,7 @@ func TestNewGithubDispatchProvider(t *testing.T) {
|
|||
"githubAppInstallationID": []byte(installationID),
|
||||
"githubAppPrivateKey": kp.PrivateKey,
|
||||
},
|
||||
wantErr: errors.New("app ID must be provided to use github app authentication"),
|
||||
wantErr: errors.New("github token or github app details must be specified"),
|
||||
},
|
||||
{
|
||||
name: "provider with missing app installation ID in options ",
|
||||
|
@ -111,32 +111,32 @@ func TestNewGithubDispatchProvider(t *testing.T) {
|
|||
"githubAppPrivateKey": kp.PrivateKey,
|
||||
},
|
||||
},
|
||||
}
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
var response []byte
|
||||
var err error
|
||||
response, err = json.Marshal(&authgithub.AppToken{Token: "access-token", ExpiresAt: expiresAt})
|
||||
assert.Nil(t, err)
|
||||
w.Write(response)
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(handler))
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
})
|
||||
|
||||
for _, tt := range tests {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
var response []byte
|
||||
var err error
|
||||
response, err = json.Marshal(&authgithub.AppToken{Token: "access-token", ExpiresAt: expiresAt})
|
||||
assert.Nil(t, err)
|
||||
w.Write(response)
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(handler))
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
if len(tt.secretData) > 0 {
|
||||
tt.secretData["githubAppBaseURL"] = []byte(srv.URL)
|
||||
}
|
||||
_, err := NewGitHubDispatch("https://github.com/foo/bar", "", nil, "", "foo", "bar", tt.secretData, nil)
|
||||
if tt.wantErr != nil {
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
if tt.secretData != nil && len(tt.secretData) > 0 {
|
||||
tt.secretData["githubAppBaseURL"] = []byte(srv.URL)
|
||||
}
|
||||
_, err := NewGitHubDispatch("https://github.com/foo/bar", "", nil, "", "foo", "bar", tt.secretData, nil)
|
||||
if tt.wantErr != nil {
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,13 +26,13 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
pkgcache "github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/git/github"
|
||||
authgithub "github.com/fluxcd/pkg/git/github"
|
||||
gogithub "github.com/google/go-github/v64/github"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
gogithub "github.com/google/go-github/v64/github"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/git/github"
|
||||
|
||||
"github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
)
|
||||
|
||||
// repoInfo is an internal type encapsulating owner, repo and client
|
||||
|
@ -43,20 +43,13 @@ type repoInfo struct {
|
|||
}
|
||||
|
||||
// getGitHubAppOptions constructs the github app authentication options.
|
||||
func getGitHubAppOptions(providerName, providerNamespace, proxy string, secretData map[string][]byte, tokenCache *pkgcache.TokenCache) ([]github.OptFunc, error) {
|
||||
githubOpts := []github.OptFunc{}
|
||||
if val, ok := secretData[github.AppIDKey]; ok {
|
||||
githubOpts = append(githubOpts, github.WithAppID(string(val)))
|
||||
}
|
||||
if val, ok := secretData[github.AppInstallationIDKey]; ok {
|
||||
githubOpts = append(githubOpts, github.WithInstllationID(string(val)))
|
||||
}
|
||||
if val, ok := secretData[github.AppPrivateKey]; ok {
|
||||
githubOpts = append(githubOpts, github.WithPrivateKey(val))
|
||||
}
|
||||
if val, ok := secretData[github.AppBaseUrlKey]; ok {
|
||||
githubOpts = append(githubOpts, github.WithAppBaseURL(string(val)))
|
||||
func getGitHubAppOptions(providerName, providerNamespace, proxy string,
|
||||
secretData map[string][]byte, tokenCache *cache.TokenCache) ([]github.OptFunc, error) {
|
||||
|
||||
githubOpts := []github.OptFunc{
|
||||
github.WithAppData(secretData),
|
||||
}
|
||||
|
||||
if len(githubOpts) > 0 && proxy != "" {
|
||||
proxyURL, err := url.Parse(proxy)
|
||||
if err != nil {
|
||||
|
@ -64,26 +57,31 @@ func getGitHubAppOptions(providerName, providerNamespace, proxy string, secretDa
|
|||
}
|
||||
githubOpts = append(githubOpts, github.WithProxyURL(proxyURL))
|
||||
}
|
||||
|
||||
if len(githubOpts) > 0 && tokenCache != nil {
|
||||
githubOpts = append(githubOpts, github.WithCache(tokenCache, v1beta3.ProviderKind, providerName, providerNamespace, OperationPost))
|
||||
githubOpts = append(githubOpts, github.WithCache(tokenCache,
|
||||
v1beta3.ProviderKind, providerName, providerNamespace, OperationPost))
|
||||
}
|
||||
|
||||
return githubOpts, nil
|
||||
}
|
||||
|
||||
// getRepoInfoAndGithubClient gets the github client and repository info used by Github and GithubDispatch providers
|
||||
func getRepoInfoAndGithubClient(addr string, token string, certPool *x509.CertPool, proxyURL string, providerName string, providerNamespace string, secretData map[string][]byte, tokenCache *pkgcache.TokenCache) (*repoInfo, error) {
|
||||
func getRepoInfoAndGithubClient(addr string, token string, certPool *x509.CertPool,
|
||||
proxyURL string, providerName string, providerNamespace string,
|
||||
secretData map[string][]byte, tokenCache *cache.TokenCache) (*repoInfo, error) {
|
||||
|
||||
if len(token) == 0 {
|
||||
if _, ok := secretData[github.KeyAppID]; !ok {
|
||||
return nil, errors.New("github token or github app details must be specified")
|
||||
}
|
||||
|
||||
githubOpts, err := getGitHubAppOptions(providerName, providerNamespace, proxyURL, secretData, tokenCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(githubOpts) == 0 {
|
||||
return nil, errors.New("github token or github app details must be specified")
|
||||
}
|
||||
|
||||
client, err := authgithub.New(githubOpts...)
|
||||
client, err := github.New(githubOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ func TestNewGithubProvider(t *testing.T) {
|
|||
kp, _ := ssh.GenerateKeyPair(ssh.RSA_4096)
|
||||
expiresAt := time.Now().UTC().Add(time.Hour)
|
||||
|
||||
var tests = []struct {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
secretData map[string][]byte
|
||||
wantErr error
|
||||
|
@ -90,7 +90,7 @@ func TestNewGithubProvider(t *testing.T) {
|
|||
"githubAppInstallationID": []byte(installationID),
|
||||
"githubAppPrivateKey": kp.PrivateKey,
|
||||
},
|
||||
wantErr: errors.New("app ID must be provided to use github app authentication"),
|
||||
wantErr: errors.New("github token or github app details must be specified"),
|
||||
},
|
||||
{
|
||||
name: "provider with missing app installation ID in options ",
|
||||
|
@ -116,32 +116,32 @@ func TestNewGithubProvider(t *testing.T) {
|
|||
"githubAppPrivateKey": kp.PrivateKey,
|
||||
},
|
||||
},
|
||||
}
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
var response []byte
|
||||
var err error
|
||||
response, err = json.Marshal(&authgithub.AppToken{Token: "access-token", ExpiresAt: expiresAt})
|
||||
assert.Nil(t, err)
|
||||
w.Write(response)
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(handler))
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
})
|
||||
|
||||
for _, tt := range tests {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
var response []byte
|
||||
var err error
|
||||
response, err = json.Marshal(&authgithub.AppToken{Token: "access-token", ExpiresAt: expiresAt})
|
||||
assert.Nil(t, err)
|
||||
w.Write(response)
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(handler))
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
if len(tt.secretData) > 0 {
|
||||
tt.secretData["githubAppBaseURL"] = []byte(srv.URL)
|
||||
}
|
||||
_, err := NewGitHub("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://github.com/foo/bar", "", nil, "", "foo", "bar", tt.secretData, nil)
|
||||
if tt.wantErr != nil {
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
if tt.secretData != nil && len(tt.secretData) > 0 {
|
||||
tt.secretData["githubAppBaseURL"] = []byte(srv.URL)
|
||||
}
|
||||
_, err := NewGitHub("0c9c2e41-d2f9-4f9b-9c41-bebc1984d67a", "https://github.com/foo/bar", "", nil, "", "foo", "bar", tt.secretData, nil)
|
||||
if tt.wantErr != nil {
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
} else {
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
@ -28,12 +28,12 @@ import (
|
|||
)
|
||||
|
||||
type Grafana struct {
|
||||
URL string
|
||||
Token string
|
||||
ProxyURL string
|
||||
CertPool *x509.CertPool
|
||||
Username string
|
||||
Password string
|
||||
URL string
|
||||
Token string
|
||||
ProxyURL string
|
||||
TLSConfig *tls.Config
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
// GraphitePayload represents a Grafana API annotation in Graphite format
|
||||
|
@ -44,19 +44,19 @@ type GraphitePayload struct {
|
|||
}
|
||||
|
||||
// NewGrafana validates the Grafana URL and returns a Grafana object
|
||||
func NewGrafana(URL string, proxyURL string, token string, certPool *x509.CertPool, username string, password string) (*Grafana, error) {
|
||||
func NewGrafana(URL string, proxyURL string, token string, tlsConfig *tls.Config, username string, password string) (*Grafana, error) {
|
||||
_, err := url.ParseRequestURI(URL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid Grafana URL %s", URL)
|
||||
}
|
||||
|
||||
return &Grafana{
|
||||
URL: URL,
|
||||
ProxyURL: proxyURL,
|
||||
Token: token,
|
||||
CertPool: certPool,
|
||||
Username: username,
|
||||
Password: password,
|
||||
URL: URL,
|
||||
ProxyURL: proxyURL,
|
||||
Token: token,
|
||||
Username: username,
|
||||
Password: password,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -97,8 +97,8 @@ func (g *Grafana) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if g.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(g.ProxyURL))
|
||||
}
|
||||
if g.CertPool != nil {
|
||||
opts = append(opts, withCertPool(g.CertPool))
|
||||
if g.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(g.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(ctx, g.URL, payload, opts...); err != nil {
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -43,10 +43,10 @@ func Fuzz_Grafana(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
grafana, err := NewGrafana(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", token, &cert, username, password)
|
||||
grafana, err := NewGrafana(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", token, &tlsConfig, username, password)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package notifier
|
|||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -15,10 +15,10 @@ import (
|
|||
)
|
||||
|
||||
type Matrix struct {
|
||||
Token string
|
||||
URL string
|
||||
RoomId string
|
||||
CertPool *x509.CertPool
|
||||
Token string
|
||||
URL string
|
||||
RoomId string
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
type MatrixPayload struct {
|
||||
|
@ -26,17 +26,17 @@ type MatrixPayload struct {
|
|||
MsgType string `json:"msgtype"`
|
||||
}
|
||||
|
||||
func NewMatrix(serverURL, token, roomId string, certPool *x509.CertPool) (*Matrix, error) {
|
||||
func NewMatrix(serverURL, token, roomId string, tlsConfig *tls.Config) (*Matrix, error) {
|
||||
_, err := url.ParseRequestURI(serverURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid Matrix homeserver URL %s: '%w'", serverURL, err)
|
||||
}
|
||||
|
||||
return &Matrix{
|
||||
URL: serverURL,
|
||||
RoomId: roomId,
|
||||
Token: token,
|
||||
CertPool: certPool,
|
||||
URL: serverURL,
|
||||
RoomId: roomId,
|
||||
Token: token,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -71,8 +71,8 @@ func (m *Matrix) Post(ctx context.Context, event eventv1.Event) error {
|
|||
req.Header.Add("Authorization", "Bearer "+m.Token)
|
||||
}),
|
||||
}
|
||||
if m.CertPool != nil {
|
||||
opts = append(opts, withCertPool(m.CertPool))
|
||||
if m.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(m.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(ctx, fullURL, payload, opts...); err != nil {
|
||||
|
|
|
@ -2,7 +2,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -27,10 +27,10 @@ func Fuzz_Matrix(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
matrix, err := NewMatrix(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), token, roomId, &cert)
|
||||
matrix, err := NewMatrix(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), token, roomId, &tlsConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
Copyright 2020 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package notifier
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
)
|
||||
|
||||
type NopNotifier struct{}
|
||||
|
||||
func (n *NopNotifier) Post(ctx context.Context, event eventv1.Event) error {
|
||||
return nil
|
||||
}
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
@ -28,10 +28,10 @@ import (
|
|||
)
|
||||
|
||||
type Opsgenie struct {
|
||||
URL string
|
||||
ProxyURL string
|
||||
CertPool *x509.CertPool
|
||||
ApiKey string
|
||||
URL string
|
||||
ProxyURL string
|
||||
TLSConfig *tls.Config
|
||||
ApiKey string
|
||||
}
|
||||
|
||||
type OpsgenieAlert struct {
|
||||
|
@ -40,7 +40,7 @@ type OpsgenieAlert struct {
|
|||
Details map[string]string `json:"details"`
|
||||
}
|
||||
|
||||
func NewOpsgenie(hookURL string, proxyURL string, certPool *x509.CertPool, token string) (*Opsgenie, error) {
|
||||
func NewOpsgenie(hookURL string, proxyURL string, tlsConfig *tls.Config, token string) (*Opsgenie, error) {
|
||||
_, err := url.ParseRequestURI(hookURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid Opsgenie hook URL %s: '%w'", hookURL, err)
|
||||
|
@ -51,10 +51,10 @@ func NewOpsgenie(hookURL string, proxyURL string, certPool *x509.CertPool, token
|
|||
}
|
||||
|
||||
return &Opsgenie{
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
CertPool: certPool,
|
||||
ApiKey: token,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
ApiKey: token,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -86,8 +86,8 @@ func (s *Opsgenie) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if s.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(s.ProxyURL))
|
||||
}
|
||||
if s.CertPool != nil {
|
||||
opts = append(opts, withCertPool(s.CertPool))
|
||||
if s.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(s.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(ctx, s.URL, payload, opts...); err != nil {
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -42,10 +42,10 @@ func Fuzz_OpsGenie(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
opsgenie, err := NewOpsgenie(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &cert, token)
|
||||
opsgenie, err := NewOpsgenie(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &tlsConfig, token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
@ -33,10 +33,10 @@ type PagerDuty struct {
|
|||
Endpoint string
|
||||
RoutingKey string
|
||||
ProxyURL string
|
||||
CertPool *x509.CertPool
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
func NewPagerDuty(endpoint string, proxyURL string, certPool *x509.CertPool, routingKey string) (*PagerDuty, error) {
|
||||
func NewPagerDuty(endpoint string, proxyURL string, tlsConfig *tls.Config, routingKey string) (*PagerDuty, error) {
|
||||
URL, err := url.ParseRequestURI(endpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid PagerDuty endpoint URL %q: '%w'", endpoint, err)
|
||||
|
@ -45,7 +45,7 @@ func NewPagerDuty(endpoint string, proxyURL string, certPool *x509.CertPool, rou
|
|||
Endpoint: URL.Scheme + "://" + URL.Host,
|
||||
RoutingKey: routingKey,
|
||||
ProxyURL: proxyURL,
|
||||
CertPool: certPool,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,8 @@ func (p *PagerDuty) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if p.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(p.ProxyURL))
|
||||
}
|
||||
if p.CertPool != nil {
|
||||
opts = append(opts, withCertPool(p.CertPool))
|
||||
if p.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(p.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(
|
||||
|
|
|
@ -2,7 +2,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -32,10 +32,10 @@ func Fuzz_PagerDuty(f *testing.F) {
|
|||
ts := httptest.NewServer(mux)
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
pd, err := NewPagerDuty(ts.URL, "", &cert, routingKey)
|
||||
pd, err := NewPagerDuty(ts.URL, "", &tlsConfig, routingKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
@ -28,26 +28,26 @@ import (
|
|||
|
||||
// Rocket holds the hook URL
|
||||
type Rocket struct {
|
||||
URL string
|
||||
ProxyURL string
|
||||
Username string
|
||||
Channel string
|
||||
CertPool *x509.CertPool
|
||||
URL string
|
||||
ProxyURL string
|
||||
Username string
|
||||
Channel string
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
// NewRocket validates the Rocket URL and returns a Rocket object
|
||||
func NewRocket(hookURL string, proxyURL string, certPool *x509.CertPool, username string, channel string) (*Rocket, error) {
|
||||
func NewRocket(hookURL string, proxyURL string, tlsConfig *tls.Config, username string, channel string) (*Rocket, error) {
|
||||
_, err := url.ParseRequestURI(hookURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid Rocket hook URL %s: '%w'", hookURL, err)
|
||||
}
|
||||
|
||||
return &Rocket{
|
||||
Channel: channel,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Username: username,
|
||||
CertPool: certPool,
|
||||
Channel: channel,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Username: username,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -87,8 +87,8 @@ func (s *Rocket) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if s.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(s.ProxyURL))
|
||||
}
|
||||
if s.CertPool != nil {
|
||||
opts = append(opts, withCertPool(s.CertPool))
|
||||
if s.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(s.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(ctx, s.URL, payload, opts...); err != nil {
|
||||
|
|
|
@ -18,7 +18,6 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -42,10 +41,7 @@ func Fuzz_Rocket(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
|
||||
rocket, err := NewRocket(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &cert, username, channel)
|
||||
rocket, err := NewRocket(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", nil, username, channel)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ type Sentry struct {
|
|||
|
||||
// NewSentry creates a Sentry client from the provided Data Source Name (DSN)
|
||||
func NewSentry(certPool *x509.CertPool, dsn string, environment string) (*Sentry, error) {
|
||||
if dsn == "" {
|
||||
return nil, fmt.Errorf("DSN cannot be empty")
|
||||
}
|
||||
|
||||
tr := &http.Transport{}
|
||||
if certPool != nil {
|
||||
tr = &http.Transport{
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package notifier
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -25,15 +26,42 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewSentry(t *testing.T) {
|
||||
s, err := NewSentry(nil, "https://test@localhost/1", "foo")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, s.Client.Options().Dsn, "https://test@localhost/1")
|
||||
assert.Equal(t, s.Client.Options().Environment, "foo")
|
||||
tests := []struct {
|
||||
name string
|
||||
dsn string
|
||||
environment string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "valid DSN",
|
||||
dsn: "https://test@localhost/1",
|
||||
environment: "foo",
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "empty DSN",
|
||||
dsn: "",
|
||||
environment: "foo",
|
||||
err: errors.New("DSN cannot be empty"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, err := NewSentry(nil, tt.dsn, tt.environment)
|
||||
if tt.err != nil {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, tt.err, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, s.Client.Options().Dsn, tt.dsn)
|
||||
assert.Equal(t, s.Client.Options().Environment, tt.environment)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToSentryEvent(t *testing.T) {
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
@ -30,12 +30,12 @@ import (
|
|||
|
||||
// Slack holds the hook URL
|
||||
type Slack struct {
|
||||
URL string
|
||||
ProxyURL string
|
||||
Token string
|
||||
Username string
|
||||
Channel string
|
||||
CertPool *x509.CertPool
|
||||
URL string
|
||||
ProxyURL string
|
||||
Token string
|
||||
Username string
|
||||
Channel string
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
// SlackPayload holds the channel and attachments
|
||||
|
@ -64,19 +64,19 @@ type SlackField struct {
|
|||
}
|
||||
|
||||
// NewSlack validates the Slack URL and returns a Slack object
|
||||
func NewSlack(hookURL string, proxyURL string, token string, certPool *x509.CertPool, username string, channel string) (*Slack, error) {
|
||||
func NewSlack(hookURL string, proxyURL string, token string, tlsConfig *tls.Config, username string, channel string) (*Slack, error) {
|
||||
_, err := url.ParseRequestURI(hookURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid Slack hook URL %s: '%w'", hookURL, err)
|
||||
}
|
||||
|
||||
return &Slack{
|
||||
Channel: channel,
|
||||
Username: username,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Token: token,
|
||||
CertPool: certPool,
|
||||
Channel: channel,
|
||||
Username: username,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Token: token,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -129,8 +129,8 @@ func (s *Slack) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if s.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(s.ProxyURL))
|
||||
}
|
||||
if s.CertPool != nil {
|
||||
opts = append(opts, withCertPool(s.CertPool))
|
||||
if s.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(s.TLSConfig))
|
||||
}
|
||||
if s.URL == "https://slack.com/api/chat.postMessage" {
|
||||
opts = append(opts, withResponseValidator(validateSlackResponse))
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -43,10 +43,10 @@ func Fuzz_Slack(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
slack, err := NewSlack(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", token, &cert, username, channel)
|
||||
slack, err := NewSlack(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", token, &tlsConfig, username, channel)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
|
@ -39,10 +39,10 @@ const (
|
|||
|
||||
// MS Teams holds the incoming webhook URL
|
||||
type MSTeams struct {
|
||||
URL string
|
||||
ProxyURL string
|
||||
CertPool *x509.CertPool
|
||||
Schema int
|
||||
URL string
|
||||
ProxyURL string
|
||||
Schema int
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
// MSTeamsPayload holds the message card data
|
||||
|
@ -121,17 +121,17 @@ type msAdaptiveCardFact struct {
|
|||
}
|
||||
|
||||
// NewMSTeams validates the MS Teams URL and returns a MSTeams object
|
||||
func NewMSTeams(hookURL string, proxyURL string, certPool *x509.CertPool) (*MSTeams, error) {
|
||||
func NewMSTeams(hookURL string, proxyURL string, tlsConfig *tls.Config) (*MSTeams, error) {
|
||||
u, err := url.ParseRequestURI(hookURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid MS Teams webhook URL %s: '%w'", hookURL, err)
|
||||
}
|
||||
|
||||
provider := &MSTeams{
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
CertPool: certPool,
|
||||
Schema: msTeamsSchemaAdaptiveCard,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
Schema: msTeamsSchemaAdaptiveCard,
|
||||
TLSConfig: tlsConfig,
|
||||
}
|
||||
|
||||
// Check if the webhook URL is the deprecated connector and update the schema accordingly.
|
||||
|
@ -165,8 +165,8 @@ func (s *MSTeams) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if s.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(s.ProxyURL))
|
||||
}
|
||||
if s.CertPool != nil {
|
||||
opts = append(opts, withCertPool(s.CertPool))
|
||||
if s.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(s.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(ctx, s.URL, payload, opts...); err != nil {
|
||||
|
|
|
@ -18,7 +18,6 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -43,10 +42,7 @@ func Fuzz_MSTeams(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
|
||||
teams, err := NewMSTeams(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &cert)
|
||||
teams, err := NewMSTeams(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -4,27 +4,46 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containrrr/shoutrrr"
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
telegramBaseURL = "https://api.telegram.org/bot%s"
|
||||
sendMessageMethodName = "sendMessage"
|
||||
)
|
||||
|
||||
type Telegram struct {
|
||||
Channel string
|
||||
Token string
|
||||
send func(url string, message string) error // this allows the send function to be overridden for testing
|
||||
url string
|
||||
ProxyURL string
|
||||
Channel string
|
||||
Token string
|
||||
}
|
||||
|
||||
func NewTelegram(channel, token string) (*Telegram, error) {
|
||||
// TelegramPayload represents the payload sent to Telegram Bot API
|
||||
// Reference: https://core.telegram.org/bots/api#sendmessage
|
||||
type TelegramPayload struct {
|
||||
ChatID string `json:"chat_id"` // Unique identifier for the target chat
|
||||
Text string `json:"text"` // Text of the message to be sent
|
||||
ParseMode string `json:"parse_mode"` // Mode for parsing entities in the message text
|
||||
}
|
||||
|
||||
func NewTelegram(proxyURL, channel, token string) (*Telegram, error) {
|
||||
if channel == "" {
|
||||
return nil, errors.New("empty Telegram channel")
|
||||
}
|
||||
|
||||
if token == "" {
|
||||
return nil, errors.New("empty Telegram token")
|
||||
}
|
||||
|
||||
return &Telegram{
|
||||
Channel: channel,
|
||||
Token: token,
|
||||
send: shoutrrr.Send,
|
||||
url: fmt.Sprintf(telegramBaseURL, token),
|
||||
ProxyURL: proxyURL,
|
||||
Channel: channel,
|
||||
Token: token,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -46,9 +65,24 @@ func (t *Telegram) Post(ctx context.Context, event eventv1.Event) error {
|
|||
metadata = metadata + fmt.Sprintf("\\- *%s*: %s\n", escapeString(k), escapeString(v))
|
||||
}
|
||||
message := fmt.Sprintf("*%s*\n%s\n%s", escapeString(heading), escapeString(event.Message), metadata)
|
||||
url := fmt.Sprintf("telegram://%s@telegram?channels=%s&parseMode=markDownv2", t.Token, t.Channel)
|
||||
err := t.send(url, message)
|
||||
return err
|
||||
|
||||
payload := TelegramPayload{
|
||||
ChatID: t.Channel,
|
||||
Text: message,
|
||||
ParseMode: "MarkdownV2", // https://core.telegram.org/bots/api#markdownv2-style
|
||||
}
|
||||
|
||||
apiURL, err := url.JoinPath(t.url, sendMessageMethodName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to construct API URL: %w", err)
|
||||
}
|
||||
|
||||
var opts []postOption
|
||||
if t.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(t.ProxyURL))
|
||||
}
|
||||
|
||||
return postMessage(ctx, apiURL, payload, opts...)
|
||||
}
|
||||
|
||||
// The telegram API requires that some special characters are escaped
|
||||
|
|
|
@ -31,22 +31,21 @@ import (
|
|||
|
||||
func TestTelegram_Post(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodPost, r.Method)
|
||||
require.Equal(t, "/sendMessage", r.URL.Path)
|
||||
require.Equal(t, "application/json", r.Header.Get("Content-Type"))
|
||||
|
||||
b, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
var payload = WebexPayload{}
|
||||
var payload TelegramPayload
|
||||
err = json.Unmarshal(b, &payload)
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
telegram, err := NewTelegram("channel", "token")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "channel", payload.ChatID)
|
||||
require.Equal(t, "MarkdownV2", payload.ParseMode)
|
||||
|
||||
telegram.send = func(url, message string) error {
|
||||
require.Equal(t, "telegram://token@telegram?channels=channel&parseMode=markDownv2", url)
|
||||
|
||||
lines := strings.Split(message, "\n")
|
||||
lines := strings.Split(payload.Text, "\n")
|
||||
require.Len(t, lines, 5)
|
||||
slices.Sort(lines[2:4])
|
||||
require.Equal(t, "*💫 gitrepository/webapp/gitops\\-system*", lines[0])
|
||||
|
@ -57,8 +56,14 @@ func TestTelegram_Post(t *testing.T) {
|
|||
"",
|
||||
}, lines[2:])
|
||||
|
||||
return nil
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
telegram, err := NewTelegram("", "channel", "token")
|
||||
require.NoError(t, err)
|
||||
|
||||
telegram.url = ts.URL
|
||||
|
||||
ev := testEvent()
|
||||
ev.Metadata["kubernetes.io/somekey"] = "some.value"
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
@ -51,9 +51,8 @@ type Webex struct {
|
|||
Token string
|
||||
|
||||
// optional: use a proxy as needed
|
||||
ProxyURL string
|
||||
// optional: x509 cert is no longer needed to post to a webex space
|
||||
CertPool *x509.CertPool
|
||||
ProxyURL string
|
||||
TLSConfig *tls.Config
|
||||
}
|
||||
|
||||
// WebexPayload holds the message text
|
||||
|
@ -63,7 +62,7 @@ type WebexPayload struct {
|
|||
}
|
||||
|
||||
// NewWebex validates the Webex URL and returns a Webex object
|
||||
func NewWebex(hookURL, proxyURL string, certPool *x509.CertPool, channel string, token string) (*Webex, error) {
|
||||
func NewWebex(hookURL, proxyURL string, tlsConfig *tls.Config, channel string, token string) (*Webex, error) {
|
||||
|
||||
_, err := url.ParseRequestURI(hookURL)
|
||||
if err != nil {
|
||||
|
@ -71,11 +70,11 @@ func NewWebex(hookURL, proxyURL string, certPool *x509.CertPool, channel string,
|
|||
}
|
||||
|
||||
return &Webex{
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
CertPool: certPool,
|
||||
RoomId: channel,
|
||||
Token: token,
|
||||
URL: hookURL,
|
||||
ProxyURL: proxyURL,
|
||||
RoomId: channel,
|
||||
Token: token,
|
||||
TLSConfig: tlsConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -116,8 +115,8 @@ func (s *Webex) Post(ctx context.Context, event eventv1.Event) error {
|
|||
if s.ProxyURL != "" {
|
||||
opts = append(opts, withProxy(s.ProxyURL))
|
||||
}
|
||||
if s.CertPool != nil {
|
||||
opts = append(opts, withCertPool(s.CertPool))
|
||||
if s.TLSConfig != nil {
|
||||
opts = append(opts, withTLSConfig(s.TLSConfig))
|
||||
}
|
||||
|
||||
if err := postMessage(ctx, s.URL, payload, opts...); err != nil {
|
||||
|
|
|
@ -18,7 +18,7 @@ package notifier
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -42,10 +42,10 @@ func Fuzz_Webex(f *testing.F) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
var cert x509.CertPool
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&cert)
|
||||
var tlsConfig tls.Config
|
||||
_ = fuzz.NewConsumer(seed).GenerateStruct(&tlsConfig)
|
||||
|
||||
webex, err := NewWebex(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &cert, channel, token)
|
||||
webex, err := NewWebex(fmt.Sprintf("%s/%s", ts.URL, urlSuffix), "", &tlsConfig, channel, token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package server
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -38,8 +37,9 @@ import (
|
|||
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
"github.com/fluxcd/pkg/auth"
|
||||
pkgcache "github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/masktoken"
|
||||
"github.com/fluxcd/pkg/runtime/secrets"
|
||||
|
||||
apiv1 "github.com/fluxcd/notification-controller/api/v1"
|
||||
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
|
@ -305,154 +305,144 @@ func createCommitStatus(ctx context.Context, provider *apiv1beta3.Provider, even
|
|||
return commitStatus, nil
|
||||
}
|
||||
|
||||
// createNotifier returns a notifier.Interface for the given Provider.
|
||||
func createNotifier(ctx context.Context, kubeClient client.Client, provider *apiv1beta3.Provider, commitStatus string, tokenCache *pkgcache.TokenCache) (notifier.Interface, string, error) {
|
||||
logger := log.FromContext(ctx)
|
||||
// extractAuthFromSecret extracts notification-controller specific fields from the provider's secret
|
||||
// that are not handled by pkg/runtime/secrets (address, proxy, token, headers).
|
||||
// StandardizedSecret fields like BasicAuth, TLS, and ProxySecretRef are handled separately.
|
||||
func extractAuthFromSecret(ctx context.Context, kubeClient client.Client, provider *apiv1beta3.Provider) ([]notifier.Option, map[string][]byte, error) {
|
||||
options := []notifier.Option{}
|
||||
|
||||
webhook := provider.Spec.Address
|
||||
username := provider.Spec.Username
|
||||
proxy := provider.Spec.Proxy
|
||||
token := ""
|
||||
password := ""
|
||||
headers := make(map[string]string)
|
||||
secretName := types.NamespacedName{Namespace: provider.Namespace, Name: provider.Spec.SecretRef.Name}
|
||||
var secret corev1.Secret
|
||||
if provider.Spec.SecretRef != nil {
|
||||
secretName := types.NamespacedName{Namespace: provider.Namespace, Name: provider.Spec.SecretRef.Name}
|
||||
if err := kubeClient.Get(ctx, secretName, &secret); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to read secret: %w", err)
|
||||
}
|
||||
|
||||
err := kubeClient.Get(ctx, secretName, &secret)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to read secret: %w", err)
|
||||
}
|
||||
|
||||
if val, ok := secret.Data["address"]; ok {
|
||||
if len(val) > 2048 {
|
||||
return nil, "", fmt.Errorf("invalid address in secret: address exceeds maximum length of %d bytes", 2048)
|
||||
}
|
||||
webhook = strings.TrimSpace(string(val))
|
||||
}
|
||||
|
||||
if val, ok := secret.Data["password"]; ok {
|
||||
password = strings.TrimSpace(string(val))
|
||||
}
|
||||
|
||||
if val, ok := secret.Data["proxy"]; ok {
|
||||
proxy = strings.TrimSpace(string(val))
|
||||
_, err := url.Parse(proxy)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("invalid 'proxy' in secret '%s/%s'", secret.Namespace, secret.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := secret.Data["token"]; ok {
|
||||
token = strings.TrimSpace(string(val))
|
||||
}
|
||||
|
||||
if val, ok := secret.Data["username"]; ok {
|
||||
username = strings.TrimSpace(string(val))
|
||||
}
|
||||
|
||||
if h, ok := secret.Data["headers"]; ok {
|
||||
err := yaml.Unmarshal(h, &headers)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to read headers from secret: %w", err)
|
||||
}
|
||||
if val, ok := secret.Data["address"]; ok {
|
||||
if len(val) > 2048 {
|
||||
return nil, nil, fmt.Errorf("invalid address in secret: address exceeds maximum length of %d bytes", 2048)
|
||||
}
|
||||
}
|
||||
|
||||
var certPool *x509.CertPool
|
||||
if provider.Spec.CertSecretRef != nil {
|
||||
var secret corev1.Secret
|
||||
secretName := types.NamespacedName{Namespace: provider.Namespace, Name: provider.Spec.CertSecretRef.Name}
|
||||
|
||||
err := kubeClient.Get(ctx, secretName, &secret)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to read cert secret: %w", err)
|
||||
if val, ok := secret.Data["proxy"]; ok {
|
||||
deprecatedProxy := strings.TrimSpace(string(val))
|
||||
if _, err := url.Parse(deprecatedProxy); err != nil {
|
||||
return nil, nil, fmt.Errorf("invalid 'proxy' in secret '%s'", secretName.String())
|
||||
}
|
||||
log.FromContext(ctx).Error(nil, "warning: specifying proxy with 'proxy' key in the referenced secret is deprecated, use spec.proxySecretRef with 'address' key instead. Support for the 'proxy' key will be removed in v1.")
|
||||
options = append(options, notifier.WithProxyURL(deprecatedProxy))
|
||||
}
|
||||
|
||||
switch secret.Type {
|
||||
case corev1.SecretTypeOpaque, corev1.SecretTypeTLS, "":
|
||||
default:
|
||||
return nil, "", fmt.Errorf("cannot use Secret '%s' to get TLS certificate: invalid Secret type: '%s'", secret.Name, secret.Type)
|
||||
if val, ok := secret.Data[secrets.KeyToken]; ok {
|
||||
options = append(options, notifier.WithToken(strings.TrimSpace(string(val))))
|
||||
}
|
||||
|
||||
if h, ok := secret.Data["headers"]; ok {
|
||||
headers := make(map[string]string)
|
||||
if err := yaml.Unmarshal(h, &headers); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to read headers from secret: %w", err)
|
||||
}
|
||||
options = append(options, notifier.WithHeaders(headers))
|
||||
}
|
||||
|
||||
caFile, ok := secret.Data["ca.crt"]
|
||||
if !ok {
|
||||
// TODO: Drop support for "caFile" field in v1 Provider API.
|
||||
caFile, ok = secret.Data["caFile"]
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("no 'ca.crt' key found in Secret '%s'", secret.Name)
|
||||
}
|
||||
logger.Info("warning: specifying CA cert via 'caFile' is deprecated, please use 'ca.crt' instead")
|
||||
}
|
||||
|
||||
certPool = x509.NewCertPool()
|
||||
ok = certPool.AppendCertsFromPEM(caFile)
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("could not append to cert pool")
|
||||
if user, ok := secret.Data["username"]; ok {
|
||||
if pass, ok := secret.Data["password"]; ok {
|
||||
options = append(options, notifier.WithUsername(strings.TrimSpace(string(user))))
|
||||
options = append(options, notifier.WithPassword(strings.TrimSpace(string(pass))))
|
||||
}
|
||||
}
|
||||
|
||||
if webhook == "" {
|
||||
return nil, "", fmt.Errorf("provider has no address")
|
||||
}
|
||||
return options, secret.Data, nil
|
||||
}
|
||||
|
||||
// createNotifier constructs a notifier interface from the provider configuration,
|
||||
// handling authentication, proxy settings, and TLS configuration.
|
||||
func createNotifier(ctx context.Context, kubeClient client.Client, provider *apiv1beta3.Provider,
|
||||
commitStatus string, tokenCache *cache.TokenCache) (notifier.Interface, string, error) {
|
||||
options := []notifier.Option{
|
||||
notifier.WithTokenClient(kubeClient),
|
||||
notifier.WithProviderName(provider.Name),
|
||||
notifier.WithProviderNamespace(provider.Namespace),
|
||||
}
|
||||
|
||||
if commitStatus != "" {
|
||||
options = append(options, notifier.WithCommitStatus(commitStatus))
|
||||
}
|
||||
|
||||
if proxy != "" {
|
||||
options = append(options, notifier.WithProxyURL(proxy))
|
||||
}
|
||||
|
||||
if username != "" {
|
||||
options = append(options, notifier.WithUsername(username))
|
||||
}
|
||||
|
||||
if provider.Spec.Channel != "" {
|
||||
options = append(options, notifier.WithChannel(provider.Spec.Channel))
|
||||
}
|
||||
|
||||
if token != "" {
|
||||
options = append(options, notifier.WithToken(token))
|
||||
}
|
||||
|
||||
if len(headers) > 0 {
|
||||
options = append(options, notifier.WithHeaders(headers))
|
||||
}
|
||||
|
||||
if certPool != nil {
|
||||
options = append(options, notifier.WithCertPool(certPool))
|
||||
}
|
||||
|
||||
if password != "" {
|
||||
options = append(options, notifier.WithPassword(password))
|
||||
}
|
||||
|
||||
if provider.Name != "" {
|
||||
options = append(options, notifier.WithProviderName(provider.Name))
|
||||
}
|
||||
|
||||
if provider.Namespace != "" {
|
||||
options = append(options, notifier.WithProviderNamespace(provider.Namespace))
|
||||
}
|
||||
|
||||
if secret.Data != nil {
|
||||
options = append(options, notifier.WithSecretData(secret.Data))
|
||||
}
|
||||
|
||||
if tokenCache != nil {
|
||||
options = append(options, notifier.WithTokenCache(tokenCache))
|
||||
if provider.Spec.Username != "" {
|
||||
options = append(options, notifier.WithUsername(provider.Spec.Username))
|
||||
}
|
||||
|
||||
if provider.Spec.ServiceAccountName != "" {
|
||||
options = append(options, notifier.WithServiceAccount(provider.Spec.ServiceAccountName))
|
||||
}
|
||||
|
||||
factory := notifier.NewFactory(ctx, webhook, options...)
|
||||
if tokenCache != nil {
|
||||
options = append(options, notifier.WithTokenCache(tokenCache))
|
||||
}
|
||||
|
||||
// TODO: Remove deprecated proxy handling when Provider v1 is released.
|
||||
if provider.Spec.Proxy != "" {
|
||||
log.FromContext(ctx).Error(nil, "warning: spec.proxy is deprecated, please use spec.proxySecretRef instead. Support for this field will be removed in v1.")
|
||||
options = append(options, notifier.WithProxyURL(provider.Spec.Proxy))
|
||||
}
|
||||
|
||||
webhook := provider.Spec.Address
|
||||
var token string
|
||||
var secretData map[string][]byte
|
||||
|
||||
if provider.Spec.SecretRef != nil {
|
||||
secretOptions, sData, err := extractAuthFromSecret(ctx, kubeClient, provider)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
secretData = sData
|
||||
options = append(options, secretOptions...)
|
||||
|
||||
if secretData != nil {
|
||||
options = append(options, notifier.WithSecretData(secretData))
|
||||
}
|
||||
|
||||
if val, ok := secretData["address"]; ok {
|
||||
webhook = strings.TrimSpace(string(val))
|
||||
}
|
||||
if val, ok := secretData[secrets.KeyToken]; ok {
|
||||
token = strings.TrimSpace(string(val))
|
||||
}
|
||||
}
|
||||
|
||||
if provider.Spec.ProxySecretRef != nil {
|
||||
secretRef := types.NamespacedName{
|
||||
Name: provider.Spec.ProxySecretRef.Name,
|
||||
Namespace: provider.GetNamespace(),
|
||||
}
|
||||
proxyURL, err := secrets.ProxyURLFromSecretRef(ctx, kubeClient, secretRef)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to get proxy URL: %w", err)
|
||||
}
|
||||
options = append(options, notifier.WithProxyURL(proxyURL.String()))
|
||||
}
|
||||
|
||||
if provider.Spec.CertSecretRef != nil {
|
||||
secretRef := types.NamespacedName{
|
||||
Name: provider.Spec.CertSecretRef.Name,
|
||||
Namespace: provider.GetNamespace(),
|
||||
}
|
||||
tlsConfig, err := secrets.TLSConfigFromSecretRef(ctx, kubeClient, secretRef)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to get TLS config: %w", err)
|
||||
}
|
||||
options = append(options, notifier.WithTLSConfig(tlsConfig))
|
||||
}
|
||||
|
||||
if webhook != "" {
|
||||
options = append(options, notifier.WithURL(webhook))
|
||||
}
|
||||
|
||||
factory := notifier.NewFactory(ctx, options...)
|
||||
sender, err := factory.Notifier(provider.Spec.Type)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to initialize notifier: %w", err)
|
||||
|
|
|
@ -18,12 +18,21 @@ package server
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
@ -39,8 +48,11 @@ import (
|
|||
|
||||
apiv1 "github.com/fluxcd/notification-controller/api/v1"
|
||||
apiv1beta3 "github.com/fluxcd/notification-controller/api/v1beta3"
|
||||
"github.com/fluxcd/notification-controller/internal/notifier"
|
||||
)
|
||||
|
||||
var fixedNow = time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
func TestFilterAlertsForEvent(t *testing.T) {
|
||||
testNamespace := "foo-ns"
|
||||
|
||||
|
@ -548,21 +560,30 @@ func TestGetNotificationParams(t *testing.T) {
|
|||
func TestCreateNotifier(t *testing.T) {
|
||||
secretName := "foo-secret"
|
||||
certSecretName := "cert-secret"
|
||||
proxySecretName := "proxy-secret"
|
||||
|
||||
// Generate test certificates for mTLS testing
|
||||
caCert, clientCert, clientKey := generateTestCertificates(t)
|
||||
|
||||
// Helper to create expected TLS configs
|
||||
caPool := x509.NewCertPool()
|
||||
caPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
clientCertPair, err := tls.X509KeyPair(clientCert, clientKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client cert pair: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
providerSpec *apiv1beta3.ProviderSpec
|
||||
secretType corev1.SecretType
|
||||
secretData map[string][]byte
|
||||
certSecretData map[string][]byte
|
||||
wantErr bool
|
||||
name string
|
||||
providerSpec *apiv1beta3.ProviderSpec
|
||||
secretType corev1.SecretType
|
||||
secretData map[string][]byte
|
||||
certSecretData map[string][]byte
|
||||
proxySecretData map[string][]byte
|
||||
wantErr bool
|
||||
wantTLSConfig *tls.Config
|
||||
}{
|
||||
{
|
||||
name: "no address, no secret ref",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "slack",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid address, no secret ref",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
|
@ -578,6 +599,7 @@ func TestCreateNotifier(t *testing.T) {
|
|||
},
|
||||
wantErr: true,
|
||||
},
|
||||
// TODO: Remove deprecated secret proxy key tests when Provider v1 is released.
|
||||
{
|
||||
name: "reference to secret with valid address, proxy, headers",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
|
@ -625,6 +647,7 @@ func TestCreateNotifier(t *testing.T) {
|
|||
"address": []byte("https://example.com"),
|
||||
},
|
||||
},
|
||||
// TODO: Remove deprecated spec.proxy field tests when Provider v1 is released.
|
||||
{
|
||||
name: "invalid spec proxy overridden by valid secret ref proxy",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
|
@ -679,19 +702,9 @@ func TestCreateNotifier(t *testing.T) {
|
|||
CertSecretRef: &meta.LocalObjectReference{Name: certSecretName},
|
||||
},
|
||||
certSecretData: map[string][]byte{
|
||||
// Based on https://pkg.go.dev/crypto/tls#X509KeyPair example.
|
||||
"ca.crt": []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
|
||||
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
|
||||
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
|
||||
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
|
||||
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
|
||||
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
|
||||
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
|
||||
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
||||
6MF9+Yw1Yy0t
|
||||
-----END CERTIFICATE-----`),
|
||||
"ca.crt": caCert,
|
||||
},
|
||||
wantTLSConfig: &tls.Config{RootCAs: caPool},
|
||||
},
|
||||
{
|
||||
name: "cert secret reference in caFile with valid CA",
|
||||
|
@ -701,19 +714,9 @@ Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
|||
CertSecretRef: &meta.LocalObjectReference{Name: certSecretName},
|
||||
},
|
||||
certSecretData: map[string][]byte{
|
||||
// Based on https://pkg.go.dev/crypto/tls#X509KeyPair example.
|
||||
"caFile": []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw
|
||||
DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow
|
||||
EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d
|
||||
7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B
|
||||
5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
|
||||
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1
|
||||
NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l
|
||||
Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
||||
6MF9+Yw1Yy0t
|
||||
-----END CERTIFICATE-----`),
|
||||
"caFile": caCert,
|
||||
},
|
||||
wantTLSConfig: &tls.Config{RootCAs: caPool},
|
||||
},
|
||||
{
|
||||
name: "cert secret reference in both ca.crt and caFile",
|
||||
|
@ -750,6 +753,47 @@ Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
|||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "mTLS with standard keys",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
CertSecretRef: &meta.LocalObjectReference{Name: certSecretName},
|
||||
},
|
||||
certSecretData: map[string][]byte{
|
||||
"ca.crt": caCert,
|
||||
"tls.crt": clientCert,
|
||||
"tls.key": clientKey,
|
||||
},
|
||||
wantTLSConfig: &tls.Config{RootCAs: caPool, Certificates: []tls.Certificate{clientCertPair}},
|
||||
},
|
||||
{
|
||||
name: "mTLS with legacy keys",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
CertSecretRef: &meta.LocalObjectReference{Name: certSecretName},
|
||||
},
|
||||
certSecretData: map[string][]byte{
|
||||
"caFile": caCert,
|
||||
"certFile": clientCert,
|
||||
"keyFile": clientKey,
|
||||
},
|
||||
wantTLSConfig: &tls.Config{RootCAs: caPool, Certificates: []tls.Certificate{clientCertPair}},
|
||||
},
|
||||
{
|
||||
name: "client cert without CA",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
CertSecretRef: &meta.LocalObjectReference{Name: certSecretName},
|
||||
},
|
||||
certSecretData: map[string][]byte{
|
||||
"tls.crt": clientCert,
|
||||
"tls.key": clientKey,
|
||||
},
|
||||
wantTLSConfig: &tls.Config{Certificates: []tls.Certificate{clientCertPair}},
|
||||
},
|
||||
{
|
||||
name: "unsupported provider",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
|
@ -780,6 +824,73 @@ Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
|||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "proxy from ProxySecretRef",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
ProxySecretRef: &meta.LocalObjectReference{Name: proxySecretName},
|
||||
},
|
||||
proxySecretData: map[string][]byte{
|
||||
"address": []byte("http://proxy.example.com:8080"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "proxy from ProxySecretRef with authentication",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
ProxySecretRef: &meta.LocalObjectReference{Name: proxySecretName},
|
||||
},
|
||||
proxySecretData: map[string][]byte{
|
||||
"address": []byte("http://proxy.example.com:8080"),
|
||||
"username": []byte("proxyuser"),
|
||||
"password": []byte("proxypass"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ProxySecretRef reference to non-existing secret",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
ProxySecretRef: &meta.LocalObjectReference{Name: "non-existing"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "ProxySecretRef missing address field",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
ProxySecretRef: &meta.LocalObjectReference{Name: proxySecretName},
|
||||
},
|
||||
proxySecretData: map[string][]byte{
|
||||
"username": []byte("proxyuser"),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
// TODO: Remove deprecated spec.proxy field tests when Provider v1 is released.
|
||||
{
|
||||
name: "deprecated spec.proxy field",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
Type: "generic",
|
||||
Address: "https://example.com",
|
||||
Proxy: "http://proxy.example.com:8080",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "provider type that does not require address field",
|
||||
providerSpec: &apiv1beta3.ProviderSpec{
|
||||
// Telegram generates URLs internally, so address field is not required
|
||||
Type: "telegram",
|
||||
Channel: "test-channel",
|
||||
SecretRef: &meta.LocalObjectReference{Name: secretName},
|
||||
},
|
||||
secretData: map[string][]byte{
|
||||
"token": []byte("test-token"),
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
@ -806,10 +917,40 @@ Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc
|
|||
}
|
||||
builder.WithObjects(secret)
|
||||
}
|
||||
if tt.proxySecretData != nil {
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: proxySecretName},
|
||||
Data: tt.proxySecretData,
|
||||
}
|
||||
builder.WithObjects(secret)
|
||||
}
|
||||
provider := apiv1beta3.Provider{Spec: *tt.providerSpec}
|
||||
|
||||
_, _, err := createNotifier(context.TODO(), builder.Build(), &provider, "", nil)
|
||||
notifier, _, err := createNotifier(context.TODO(), builder.Build(), &provider, "", nil)
|
||||
g.Expect(err != nil).To(Equal(tt.wantErr))
|
||||
|
||||
if !tt.wantErr && tt.wantTLSConfig != nil {
|
||||
g.Expect(notifier).ToNot(BeNil(), "Expected notifier to be created but got nil")
|
||||
|
||||
// Get TLS configuration from notifier
|
||||
tlsConfig := getNotifierTLSConfig(notifier)
|
||||
if tlsConfig == nil {
|
||||
// Notifier doesn't support TLS via postMessage pattern, skip the check
|
||||
return
|
||||
}
|
||||
|
||||
g.Expect(tlsConfig).ToNot(BeNil(), "Expected TLS configuration but got nil")
|
||||
if tt.wantTLSConfig.RootCAs != nil {
|
||||
g.Expect(tlsConfig.RootCAs).ToNot(BeNil())
|
||||
} else {
|
||||
g.Expect(tlsConfig.RootCAs).To(BeNil())
|
||||
}
|
||||
|
||||
g.Expect(tlsConfig.Certificates).To(HaveLen(len(tt.wantTLSConfig.Certificates)))
|
||||
if len(tt.wantTLSConfig.Certificates) > 0 {
|
||||
g.Expect(tlsConfig.Certificates[0]).To(Equal(tt.wantTLSConfig.Certificates[0]))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1375,3 +1516,110 @@ func Test_excludeInternalMetadata(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// generateTestCertificates generates test certificates for mTLS testing.
|
||||
// TODO: Move to pkg/runtime/secrets test helpers after mTLS implementation is complete
|
||||
func generateTestCertificates(t *testing.T) (caCert, clientCert, clientKey []byte) {
|
||||
t.Helper()
|
||||
|
||||
caPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to generate CA private key: %v", err)
|
||||
}
|
||||
|
||||
caTemplate := x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{"Test CA"},
|
||||
Country: []string{"US"},
|
||||
Province: []string{""},
|
||||
Locality: []string{"San Francisco"},
|
||||
StreetAddress: []string{""},
|
||||
PostalCode: []string{""},
|
||||
},
|
||||
NotBefore: fixedNow,
|
||||
NotAfter: fixedNow.Add(365 * 24 * time.Hour),
|
||||
IsCA: true,
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
|
||||
caCertDER, err := x509.CreateCertificate(rand.Reader, &caTemplate, &caTemplate, &caPrivKey.PublicKey, caPrivKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create CA certificate: %v", err)
|
||||
}
|
||||
|
||||
clientPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to generate client private key: %v", err)
|
||||
}
|
||||
|
||||
clientTemplate := x509.Certificate{
|
||||
SerialNumber: big.NewInt(2),
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{"Test Client"},
|
||||
Country: []string{"US"},
|
||||
Province: []string{""},
|
||||
Locality: []string{"San Francisco"},
|
||||
StreetAddress: []string{""},
|
||||
PostalCode: []string{""},
|
||||
},
|
||||
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
|
||||
DNSNames: []string{"localhost"},
|
||||
NotBefore: fixedNow,
|
||||
NotAfter: fixedNow.Add(365 * 24 * time.Hour),
|
||||
SubjectKeyId: []byte{1, 2, 3, 4, 6},
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
}
|
||||
|
||||
clientCertDER, err := x509.CreateCertificate(rand.Reader, &clientTemplate, &caTemplate, &clientPrivKey.PublicKey, caPrivKey)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create client certificate: %v", err)
|
||||
}
|
||||
|
||||
caCertPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: caCertDER,
|
||||
})
|
||||
|
||||
clientCertPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: clientCertDER,
|
||||
})
|
||||
|
||||
clientKeyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(clientPrivKey),
|
||||
})
|
||||
|
||||
return caCertPEM, clientCertPEM, clientKeyPEM
|
||||
}
|
||||
|
||||
// getNotifierTLSConfig extracts TLSConfig from postMessage-based notifiers for testing
|
||||
func getNotifierTLSConfig(n notifier.Interface) *tls.Config {
|
||||
switch v := n.(type) {
|
||||
case *notifier.Forwarder:
|
||||
return v.TLSConfig
|
||||
case *notifier.Slack:
|
||||
return v.TLSConfig
|
||||
case *notifier.Alertmanager:
|
||||
return v.TLSConfig
|
||||
case *notifier.Grafana:
|
||||
return v.TLSConfig
|
||||
case *notifier.Matrix:
|
||||
return v.TLSConfig
|
||||
case *notifier.Opsgenie:
|
||||
return v.TLSConfig
|
||||
case *notifier.PagerDuty:
|
||||
return v.TLSConfig
|
||||
case *notifier.Rocket:
|
||||
return v.TLSConfig
|
||||
case *notifier.MSTeams:
|
||||
return v.TLSConfig
|
||||
case *notifier.Webex:
|
||||
return v.TLSConfig
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
|
||||
pkgcache "github.com/fluxcd/pkg/cache"
|
||||
"github.com/fluxcd/pkg/cache"
|
||||
)
|
||||
|
||||
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
|
||||
|
@ -54,12 +54,14 @@ type EventServer struct {
|
|||
kubeClient client.Client
|
||||
noCrossNamespaceRefs bool
|
||||
exportHTTPPathMetrics bool
|
||||
tokenCache *pkgcache.TokenCache
|
||||
tokenCache *cache.TokenCache
|
||||
kuberecorder.EventRecorder
|
||||
}
|
||||
|
||||
// NewEventServer returns an HTTP server that handles events
|
||||
func NewEventServer(port string, logger logr.Logger, kubeClient client.Client, eventRecorder kuberecorder.EventRecorder, noCrossNamespaceRefs bool, exportHTTPPathMetrics bool, tokenCache *pkgcache.TokenCache) *EventServer {
|
||||
func NewEventServer(port string, logger logr.Logger, kubeClient client.Client,
|
||||
eventRecorder kuberecorder.EventRecorder, noCrossNamespaceRefs bool,
|
||||
exportHTTPPathMetrics bool, tokenCache *cache.TokenCache) *EventServer {
|
||||
return &EventServer{
|
||||
port: port,
|
||||
logger: logger.WithName("event-server"),
|
||||
|
|
|
@ -445,7 +445,7 @@ func (s *ReceiverServer) validate(ctx context.Context, receiver apiv1.Receiver,
|
|||
case apiv1.NexusReceiver:
|
||||
signature := r.Header.Get("X-Nexus-Webhook-Signature")
|
||||
if len(signature) == 0 {
|
||||
return fmt.Errorf("Nexus signature is missing from header")
|
||||
return fmt.Errorf("the Nexus signature is missing from header")
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(r.Body)
|
||||
|
@ -583,7 +583,7 @@ func authenticateGCRRequest(c *http.Client, bearer string, tokenIndex int) (err
|
|||
}
|
||||
|
||||
if len(bearer) < tokenIndex {
|
||||
return fmt.Errorf("Authorization header is missing or malformed: %v", bearer)
|
||||
return fmt.Errorf("the Authorization header is missing or malformed: %v", bearer)
|
||||
}
|
||||
|
||||
token := bearer[tokenIndex:]
|
||||
|
|
6
main.go
6
main.go
|
@ -29,7 +29,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
"k8s.io/utils/pointer"
|
||||
"k8s.io/utils/ptr"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
ctrlcache "sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
@ -159,7 +159,7 @@ func main() {
|
|||
LeaderElectionID: fmt.Sprintf("%s-leader-election", controllerName),
|
||||
Logger: ctrl.Log,
|
||||
Controller: config.Controller{
|
||||
RecoverPanic: pointer.Bool(true),
|
||||
RecoverPanic: ptr.To(true),
|
||||
MaxConcurrentReconciles: concurrent,
|
||||
},
|
||||
Client: ctrlclient.Options{
|
||||
|
@ -176,7 +176,7 @@ func main() {
|
|||
if watchNamespace != "" {
|
||||
mgrConfig.Cache = ctrlcache.Options{
|
||||
DefaultNamespaces: map[string]ctrlcache.Config{
|
||||
watchNamespace: ctrlcache.Config{},
|
||||
watchNamespace: {},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue