fix: complete reset recovery safety
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"proxyctl/internal/app"
|
||||
"proxyctl/internal/dockerclient"
|
||||
"proxyctl/internal/profile"
|
||||
"proxyctl/internal/target"
|
||||
@@ -202,6 +203,56 @@ func TestEnableSafelyMergesAndDisableRestoresPriorDefaults(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResetDriftedDockerClientRejectsAdministratorManagedKeyEditsWithoutWritesOrCleanup(t *testing.T) {
|
||||
files := &countingFS{FileSystem: dockerclient.OSFileSystem{}}
|
||||
a := newAdapterWithFS(t, files)
|
||||
writeConfig(t, a.ConfigPath(), `{"auths":{"keep":{}},"proxies":{"default":{"httpProxy":"http://prior.example:3128"}}}`)
|
||||
if result := a.SetDesired(context.Background(), true, activeProfile()); result.Err != nil {
|
||||
t.Fatal(result.Err)
|
||||
}
|
||||
updateDefaultKey(t, a.ConfigPath(), "httpProxy", json.RawMessage(`"http://administrator.example:3128"`))
|
||||
configBefore := readFile(t, a.ConfigPath())
|
||||
metadataBefore := readFile(t, a.RecoveryPath())
|
||||
writesBefore := files.writes
|
||||
|
||||
reset := app.NewMaintenance(profile.State{Profiles: []profile.Profile{*activeProfile()}, ActiveProfile: activeProfile().Name}, []target.Target{a}, immediateLock{}, nil).Reset(context.Background(), true)
|
||||
if reset.Err == nil || len(reset.Targets) != 1 || reset.Targets[0].Inspection.State != target.Drifted || reset.Targets[0].Err == nil {
|
||||
t.Fatalf("conflicting reset = %#v", reset)
|
||||
}
|
||||
if !strings.Contains(reset.Targets[0].Err.Error(), "changed after proxyctl applied") || files.writes != writesBefore {
|
||||
t.Fatalf("conflict outcome=%#v writes=%d->%d", reset.Targets[0], writesBefore, files.writes)
|
||||
}
|
||||
if got := readFile(t, a.ConfigPath()); got != configBefore {
|
||||
t.Fatalf("conflict rewrote config:\n%s", got)
|
||||
}
|
||||
if got := readFile(t, a.RecoveryPath()); got != metadataBefore {
|
||||
t.Fatalf("conflict changed metadata:\n%s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResetDriftedDockerClientAlreadyAtOriginalOnlyCleansMetadata(t *testing.T) {
|
||||
files := &countingFS{FileSystem: dockerclient.OSFileSystem{}}
|
||||
a := newAdapterWithFS(t, files)
|
||||
original := `{"auths":{"keep":{}},"proxies":{"default":{"httpProxy":"http://prior.example:3128","custom":{"keep":true}}}}`
|
||||
writeConfig(t, a.ConfigPath(), original)
|
||||
if result := a.SetDesired(context.Background(), true, activeProfile()); result.Err != nil {
|
||||
t.Fatal(result.Err)
|
||||
}
|
||||
writeConfig(t, a.ConfigPath(), original)
|
||||
writesBefore := files.writes
|
||||
|
||||
reset := app.NewMaintenance(profile.State{Profiles: []profile.Profile{*activeProfile()}, ActiveProfile: activeProfile().Name}, []target.Target{a}, immediateLock{}, nil).Reset(context.Background(), true)
|
||||
if reset.Err != nil || len(reset.Targets) != 1 || reset.Targets[0].Inspection.State != target.External {
|
||||
t.Fatalf("already-original reset = %#v", reset)
|
||||
}
|
||||
if files.writes != writesBefore || readFile(t, a.ConfigPath()) != original {
|
||||
t.Fatalf("already-original reset wrote config: writes=%d->%d", writesBefore, files.writes)
|
||||
}
|
||||
if _, err := os.Stat(a.RecoveryPath()); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatalf("recovery metadata remains: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInspectionDistinguishesAllStatesAndManagedValueEditsDrift(t *testing.T) {
|
||||
a := newAdapter(t, nil)
|
||||
assertState(t, a, target.Disabled)
|
||||
@@ -563,6 +614,10 @@ func assertState(t *testing.T, a *dockerclient.Adapter, want target.State) {
|
||||
}
|
||||
}
|
||||
|
||||
type immediateLock struct{}
|
||||
|
||||
func (immediateLock) Lock(context.Context) (func(), error) { return func() {}, nil }
|
||||
|
||||
type failingFS struct {
|
||||
dockerclient.FileSystem
|
||||
permission, failConfig, leak, restoreLeak, failRecoveryOnce bool
|
||||
|
||||
Reference in New Issue
Block a user