Skip to content

Commit 4ab686a

Browse files
committed
Fix certificate reload issue when files are moved
1 parent bd3e7a4 commit 4ab686a

2 files changed

Lines changed: 33 additions & 16 deletions

File tree

‎certs/certificate2_test.go‎

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,18 @@ func TestCertificate2Close(t *testing.T) {
8585
}
8686

8787
func TestCertificate2_AutoReload(t *testing.T) {
88-
testCertificate2AutoReload(t, false)
88+
testCertificate2AutoReload(t, false, false)
89+
}
90+
91+
func TestCertificate2_AutoReloadWithRename(t *testing.T) {
92+
testCertificate2AutoReload(t, false, true)
8993
}
9094

9195
func TestCertificate2_AutoReloadSymlink(t *testing.T) {
92-
testCertificate2AutoReload(t, true)
96+
testCertificate2AutoReload(t, true, false)
9397
}
9498

95-
func testCertificate2AutoReload(t *testing.T, symlink bool) {
99+
func testCertificate2AutoReload(t *testing.T, symlink, rename bool) {
96100
tmpDir := t.TempDir()
97101
tmpCert := filepath.Join(tmpDir, "test.crt")
98102
tmpKey := filepath.Join(tmpDir, "test.key")
@@ -109,8 +113,8 @@ func testCertificate2AutoReload(t *testing.T, symlink bool) {
109113
originalCert := cert.Load()
110114

111115
updateCertWithWait(t, cert, symlink, func() {
112-
overwriteFile(t, "new-public.crt", tmpCert, symlink)
113-
overwriteFile(t, "new-private.key", tmpKey, symlink)
116+
overwriteFile(t, "new-public.crt", tmpCert, symlink, rename)
117+
overwriteFile(t, "new-private.key", tmpKey, symlink, rename)
114118
})
115119

116120
newCert := cert.Load()
@@ -151,8 +155,8 @@ func testCertificate2AutoReloadCertFileOnly(t *testing.T, symlink bool) {
151155
defer cert.Close()
152156

153157
updateCertWithWait(t, cert, symlink, func() {
154-
overwriteFile(t, "new-public.crt", tmpCert, symlink)
155-
overwriteFile(t, "new-private.key", tmpKey, symlink)
158+
overwriteFile(t, "new-public.crt", tmpCert, symlink, false)
159+
overwriteFile(t, "new-private.key", tmpKey, symlink, false)
156160
})
157161

158162
newCert := cert.Load()
@@ -225,7 +229,7 @@ func copyFile(t *testing.T, src, dst string, symlink bool) {
225229
}
226230
}
227231

228-
func overwriteFile(t *testing.T, src, dst string, symlink bool) {
232+
func overwriteFile(t *testing.T, src, dst string, symlink, rename bool) {
229233
t.Helper()
230234
data, err := os.ReadFile(src)
231235
if err != nil {
@@ -234,14 +238,27 @@ func overwriteFile(t *testing.T, src, dst string, symlink bool) {
234238
if symlink {
235239
dst = dst + ".tmp"
236240
}
237-
if err := os.WriteFile(dst, data, 0o600); err != nil {
238-
t.Fatalf("Failed to write destination file %s: %v", dst, err)
241+
if rename {
242+
tmpFile := dst + ".rename"
243+
if err := os.WriteFile(tmpFile, data, 0o600); err != nil {
244+
t.Fatalf("Failed to write destination file %s: %v", tmpFile, err)
245+
}
246+
// add a small delay to ensure the write event completes before the rename,
247+
// so the test verifies that the InMovedTo event triggers the reload
248+
time.Sleep(100 * time.Millisecond)
249+
if err := os.Rename(tmpFile, dst); err != nil {
250+
t.Fatalf("Failed to rename file %s to %s: %v", tmpFile, dst, err)
251+
}
252+
} else {
253+
if err := os.WriteFile(dst, data, 0o600); err != nil {
254+
t.Fatalf("Failed to write destination file %s: %v", dst, err)
255+
}
239256
}
240257
}
241258

242259
func updateCertWithWait(t *testing.T, cert *Certificate2, symlink bool, update func()) {
243260
done := make(chan struct{})
244-
wait := time.Second
261+
wait := 5 * time.Second
245262
if symlink {
246263
wait = wait + symlinkReloadInterval // can take up to symlinkReloadInterval to detect changes
247264
}
@@ -306,8 +323,8 @@ func TestCertificate2_ConcurrentSubscriptions(t *testing.T) {
306323

307324
// Update the certificate
308325
updateCertWithWait(t, cert, false, func() {
309-
overwriteFile(t, "new-public.crt", tmpCert, false)
310-
overwriteFile(t, "new-private.key", tmpKey, false)
326+
overwriteFile(t, "new-public.crt", tmpCert, false, false)
327+
overwriteFile(t, "new-private.key", tmpKey, false, false)
311328
})
312329

313330
// Wait for all subscribers to be notified
@@ -350,8 +367,8 @@ func TestCertificate2_UnsubscribeDuringCallback(t *testing.T) {
350367

351368
// Trigger an update
352369
updateCertWithWait(t, cert, false, func() {
353-
overwriteFile(t, "new-public.crt", tmpCert, false)
354-
overwriteFile(t, "new-private.key", tmpKey, false)
370+
overwriteFile(t, "new-public.crt", tmpCert, false, false)
371+
overwriteFile(t, "new-private.key", tmpKey, false, false)
355372
})
356373

357374
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)

‎certs/event_linux.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ package certs
2222
import "github.com/rjeczalik/notify"
2323

2424
// eventWrite contains the notify events that will cause a write
25-
var eventWrite = []notify.Event{notify.InCloseWrite}
25+
var eventWrite = []notify.Event{notify.InCloseWrite, notify.InMovedTo}

0 commit comments

Comments
 (0)