Skip to content

Commit 17017b4

Browse files
authored
Remove dependency to external-dns (#31)
1 parent 00cb240 commit 17017b4

File tree

6 files changed

+305
-13
lines changed

6 files changed

+305
-13
lines changed

designate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
"github.com/gophercloud/gophercloud"
2424
"github.com/gophercloud/gophercloud/openstack"
2525
log "github.com/sirupsen/logrus"
26-
"sigs.k8s.io/external-dns/pkg/tlsutils"
26+
"github.com/stackitcloud/designate-certmanager-webhook/tlsutils"
2727
)
2828

2929
// copies environment variables to new names without overwriting existing values

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ require (
1212
github.com/cert-manager/cert-manager v1.17.2
1313
github.com/gophercloud/gophercloud v0.14.0
1414
github.com/sirupsen/logrus v1.9.3
15+
github.com/stretchr/testify v1.10.0
1516
k8s.io/client-go v0.33.3
16-
sigs.k8s.io/external-dns v0.17.0
1717
)
1818

1919
require (
@@ -58,6 +58,7 @@ require (
5858
github.com/modern-go/reflect2 v1.0.2 // indirect
5959
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
6060
github.com/pkg/errors v0.9.1 // indirect
61+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
6162
github.com/prometheus/client_golang v1.22.0 // indirect
6263
github.com/prometheus/client_model v0.6.2 // indirect
6364
github.com/prometheus/common v0.63.0 // indirect

go.sum

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
7979
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
8080
github.com/gophercloud/gophercloud v0.14.0 h1:c2Byo+YMxhHlTJ3TPptjQ4dOQ1YknTHDJ/9zClDH+84=
8181
github.com/gophercloud/gophercloud v0.14.0/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPUzcmMpwxvQ1WQIIWM=
82-
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
83-
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
82+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
83+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
8484
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
8585
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
8686
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
@@ -121,7 +121,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
121121
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
122122
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
123123
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
124-
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
125124
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
126125
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
127126
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
@@ -155,6 +154,8 @@ github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8w
155154
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
156155
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
157156
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
157+
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
158+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
158159
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
159160
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
160161
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -290,20 +291,14 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
290291
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
291292
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
292293
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
293-
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
294-
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
295294
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
296295
k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
297296
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
298297
k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
299-
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
300-
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
301298
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
302299
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
303300
k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8=
304301
k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc=
305-
k8s.io/client-go v0.32.6 h1:Q+O+Sd9LKKFnsGZNVX2q1RDILYRpQZX+ea2RoIgjKlM=
306-
k8s.io/client-go v0.32.6/go.mod h1:yqL9XJ2cTXy3WdJwdeyob3O6xiLwWrh9DP7SeszniW0=
307302
k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
308303
k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
309304
k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k=
@@ -320,8 +315,6 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1 h1:uOuSLOMBWkJH0
320315
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
321316
sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
322317
sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
323-
sigs.k8s.io/external-dns v0.17.0 h1:lBhJmGWvezR/HZcIAW6j8fVw2LczXFEGs5BluUMmFaM=
324-
sigs.k8s.io/external-dns v0.17.0/go.mod h1:CTN8maaP4nrMvmC9O00YBUfFIzkDp6Ka9MZvsCZbS38=
325318
sigs.k8s.io/gateway-api v1.3.0 h1:q6okN+/UKDATola4JY7zXzx40WO4VISk7i9DIfOvr9M=
326319
sigs.k8s.io/gateway-api v1.3.0/go.mod h1:d8NV8nJbaRbEKem+5IuxkL8gJGOZ+FJ+NvOIltV8gDk=
327320
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=

tlsutils/tlsconfig.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package tlsutils
18+
19+
import (
20+
"crypto/tls"
21+
"crypto/x509"
22+
"errors"
23+
"fmt"
24+
"os"
25+
"strings"
26+
)
27+
28+
const defaultMinVersion = 0
29+
30+
// CreateTLSConfig creates tls.Config instance from TLS parameters passed in environment variables with the given prefix
31+
func CreateTLSConfig(prefix string) (*tls.Config, error) {
32+
caFile := os.Getenv(fmt.Sprintf("%s_CA_FILE", prefix))
33+
certFile := os.Getenv(fmt.Sprintf("%s_CERT_FILE", prefix))
34+
keyFile := os.Getenv(fmt.Sprintf("%s_KEY_FILE", prefix))
35+
serverName := os.Getenv(fmt.Sprintf("%s_TLS_SERVER_NAME", prefix))
36+
isInsecureStr := strings.ToLower(os.Getenv(fmt.Sprintf("%s_TLS_INSECURE", prefix)))
37+
isInsecure := isInsecureStr == "true" || isInsecureStr == "yes" || isInsecureStr == "1"
38+
return NewTLSConfig(certFile, keyFile, caFile, serverName, isInsecure, defaultMinVersion)
39+
}
40+
41+
// NewTLSConfig creates a tls.Config instance from directly passed parameters, loading the ca, cert, and key from disk
42+
func NewTLSConfig(certPath, keyPath, caPath, serverName string, insecure bool, minVersion uint16) (*tls.Config, error) {
43+
if certPath != "" && keyPath == "" || certPath == "" && keyPath != "" {
44+
return nil, errors.New("either both cert and key or none must be provided")
45+
}
46+
var certificates []tls.Certificate
47+
if certPath != "" {
48+
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
49+
if err != nil {
50+
return nil, fmt.Errorf("could not load TLS cert: %w", err)
51+
}
52+
certificates = append(certificates, cert)
53+
}
54+
// If rootCAs is nil, TLS uses the host's root CA set.
55+
var rootCAs *x509.CertPool
56+
var err error
57+
58+
if caPath != "" {
59+
rootCAs, err = loadRoots(caPath)
60+
if err != nil {
61+
return nil, err
62+
}
63+
}
64+
65+
return &tls.Config{
66+
MinVersion: minVersion,
67+
Certificates: certificates,
68+
RootCAs: rootCAs,
69+
InsecureSkipVerify: insecure,
70+
ServerName: serverName,
71+
}, nil
72+
}
73+
74+
// loads CA cert
75+
func loadRoots(caPath string) (*x509.CertPool, error) {
76+
roots := x509.NewCertPool()
77+
pem, err := os.ReadFile(caPath)
78+
if err != nil {
79+
return nil, fmt.Errorf("error reading %s: %w", caPath, err)
80+
}
81+
ok := roots.AppendCertsFromPEM(pem)
82+
if !ok {
83+
return nil, fmt.Errorf("could not read root certs: %w", err)
84+
}
85+
return roots, nil
86+
}

tlsutils/tlsconfig_test.go

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package tlsutils
18+
19+
import (
20+
"crypto/tls"
21+
"fmt"
22+
"os"
23+
"strings"
24+
"testing"
25+
26+
"github.com/stretchr/testify/assert"
27+
"github.com/stretchr/testify/require"
28+
)
29+
30+
var rsaCertPEM = `-----BEGIN CERTIFICATE-----
31+
MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
32+
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
33+
aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
34+
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
35+
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
36+
hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
37+
rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
38+
zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
39+
MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
40+
r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
41+
-----END CERTIFICATE-----
42+
`
43+
44+
var rsaKeyPEM = testingKey(`-----BEGIN RSA TESTING KEY-----
45+
MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
46+
k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
47+
6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
48+
MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
49+
SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
50+
xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
51+
D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
52+
-----END RSA TESTING KEY-----
53+
`)
54+
55+
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
56+
57+
func TestCreateTLSConfig(t *testing.T) {
58+
59+
tests := []struct {
60+
title string
61+
prefix string
62+
caFile string
63+
certFile string
64+
keyFile string
65+
isInsecureStr string
66+
serverName string
67+
assertions func(actual *tls.Config, err error)
68+
}{
69+
{
70+
"Provide only CA returns error",
71+
"prefix",
72+
"",
73+
rsaCertPEM,
74+
"",
75+
"",
76+
"",
77+
func(actual *tls.Config, err error) {
78+
assert.Contains(t, err.Error(), "either both cert and key or none must be provided")
79+
},
80+
},
81+
{
82+
"Invalid cert and key returns error",
83+
"prefix",
84+
"",
85+
"invalid-cert",
86+
"invalid-key",
87+
"",
88+
"",
89+
func(actual *tls.Config, err error) {
90+
assert.Contains(t, err.Error(), "could not load TLS cert")
91+
},
92+
},
93+
{
94+
"Valid cert and key return a valid tls.Config with a certificate",
95+
"prefix",
96+
"",
97+
rsaCertPEM,
98+
rsaKeyPEM,
99+
"",
100+
"server-name",
101+
func(actual *tls.Config, err error) {
102+
require.NoError(t, err)
103+
assert.Equal(t, "server-name", actual.ServerName)
104+
assert.NotNil(t, actual.Certificates[0])
105+
assert.False(t, actual.InsecureSkipVerify)
106+
assert.Equal(t, actual.MinVersion, uint16(defaultMinVersion))
107+
},
108+
},
109+
{
110+
"Invalid CA file returns error",
111+
"prefix",
112+
"invalid-ca-content",
113+
"",
114+
"",
115+
"",
116+
"",
117+
func(actual *tls.Config, err error) {
118+
assert.Error(t, err)
119+
assert.Contains(t, err.Error(), "could not read root certs")
120+
},
121+
},
122+
{
123+
"Invalid CA file path returns error",
124+
"prefix",
125+
"ca-path-does-not-exist",
126+
"",
127+
"",
128+
"",
129+
"server-name",
130+
func(actual *tls.Config, err error) {
131+
assert.Error(t, err)
132+
assert.Contains(t, err.Error(), "error reading /path/does/not/exist")
133+
},
134+
},
135+
{
136+
"Complete config with CA, cert, and key returns valid tls.Config",
137+
"prefix",
138+
rsaCertPEM,
139+
rsaCertPEM,
140+
rsaKeyPEM,
141+
"",
142+
"server-name",
143+
func(actual *tls.Config, err error) {
144+
require.NoError(t, err)
145+
assert.Equal(t, "server-name", actual.ServerName)
146+
assert.NotNil(t, actual.Certificates[0])
147+
assert.NotNil(t, actual.RootCAs)
148+
assert.False(t, actual.InsecureSkipVerify)
149+
},
150+
},
151+
}
152+
153+
for _, tc := range tests {
154+
t.Run(tc.title, func(t *testing.T) {
155+
// setup
156+
dir := t.TempDir()
157+
158+
if tc.caFile != "" {
159+
path := fmt.Sprintf("%s/caFile", dir)
160+
writeToFile(path, tc.caFile)
161+
t.Setenv(fmt.Sprintf("%s_CA_FILE", tc.prefix), path)
162+
}
163+
164+
if tc.caFile == "ca-path-does-not-exist" {
165+
t.Setenv(fmt.Sprintf("%s_CA_FILE", tc.prefix), "/path/does/not/exist")
166+
}
167+
168+
if tc.certFile != "" {
169+
path := fmt.Sprintf("%s/certFile", dir)
170+
writeToFile(path, tc.certFile)
171+
t.Setenv(fmt.Sprintf("%s_CERT_FILE", tc.prefix), path)
172+
}
173+
174+
if tc.keyFile != "" {
175+
path := fmt.Sprintf("%s/keyFile", dir)
176+
writeToFile(path, tc.keyFile)
177+
t.Setenv(fmt.Sprintf("%s_KEY_FILE", tc.prefix), path)
178+
}
179+
180+
if tc.serverName != "" {
181+
t.Setenv(fmt.Sprintf("%s_TLS_SERVER_NAME", tc.prefix), tc.serverName)
182+
}
183+
184+
if tc.isInsecureStr != "" {
185+
t.Setenv(fmt.Sprintf("%s_INSECURE", tc.prefix), tc.isInsecureStr)
186+
}
187+
188+
// test
189+
actual, err := CreateTLSConfig(tc.prefix)
190+
tc.assertions(actual, err)
191+
})
192+
}
193+
194+
}
195+
196+
func writeToFile(filename string, content string) error {
197+
file, fileErr := os.Create(filename)
198+
if fileErr != nil {
199+
_ = fmt.Errorf("failed to create file: %w", fileErr)
200+
}
201+
defer file.Close()
202+
_, writeErr := file.WriteString(content)
203+
if writeErr != nil {
204+
_ = fmt.Errorf("failed to write to file: %s", filename)
205+
}
206+
return nil
207+
}

tlsutils/tlsutils.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// package tlsutils was copied from
2+
// https://github.com/kubernetes-sigs/external-dns/tree/0e7c3af22109aefa8664bfcd5ae6593247078ee3/pkg/tlsutils in order
3+
// to avoid a dependency on the external-dns package for this helper, which is not really tied to external-dns and
4+
// unlikely to ever change.
5+
package tlsutils

0 commit comments

Comments
 (0)