fix: make daemon reset conflict safe

This commit is contained in:
proxyctl coordinator
2026-07-17 11:11:56 +08:00
parent 613fe56540
commit 9e2418f45e
6 changed files with 283 additions and 73 deletions
+23 -5
View File
@@ -336,12 +336,30 @@ func (a *Adapter) disable(ctx context.Context) error {
if err != nil {
return fmt.Errorf("read Docker daemon recovery metadata: %w", err)
}
// daemon.json is a shared, whole-file configuration surface. Restore it only
// while the complete current document is exactly the document proxyctl last
// applied. This protects both managed proxy keys and unrelated administrator
// edits from being overwritten by the original snapshot.
current, currentErr := a.files.ReadFile(a.configuration.DaemonConfigPath)
if currentErr != nil && !errors.Is(currentErr, fs.ErrNotExist) {
return fmt.Errorf("read Docker daemon configuration before restore: %w", currentErr)
}
alreadyOriginal := metadata.OriginalExists && currentErr == nil && fingerprint(current) == fingerprint(metadata.Original)
alreadyAbsent := !metadata.OriginalExists && errors.Is(currentErr, fs.ErrNotExist)
if alreadyOriginal || alreadyAbsent {
if err := a.files.Remove(a.configuration.RecoveryPath); err != nil && !errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("clean Docker daemon recovery metadata for already-restored configuration: %w", err)
}
return nil
}
if currentErr != nil || fingerprint(current) != metadata.ConfigFingerprint {
return errors.New("Docker daemon configuration changed after proxyctl applied it; refusing to overwrite current configuration or discard recovery metadata")
}
if metadata.OriginalExists {
current, _ := a.files.ReadFile(a.configuration.DaemonConfigPath)
if fingerprint(current) != fingerprint(metadata.Original) {
if err := a.files.AtomicWrite(a.configuration.DaemonConfigPath, metadata.Original, os.FileMode(metadata.OriginalMode)); err != nil {
return fmt.Errorf("restore Docker daemon configuration: %w", err)
}
if err := a.files.AtomicWrite(a.configuration.DaemonConfigPath, metadata.Original, os.FileMode(metadata.OriginalMode)); err != nil {
return fmt.Errorf("restore Docker daemon configuration: %w", err)
}
} else if err := a.files.Remove(a.configuration.DaemonConfigPath); err != nil && !errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("remove managed Docker daemon configuration: %w", err)