fix: finish progressive Target detection

This commit is contained in:
proxyctl coordinator
2026-07-17 21:25:43 +08:00
parent ad651402fd
commit 8348fa3ac8
17 changed files with 672 additions and 221 deletions
+36 -8
View File
@@ -235,29 +235,54 @@ func (a *Adapter) RecoveryPath() string { return a.configuration.RecoveryFile }
func (a *Adapter) LockPath() string { return a.configuration.RecoveryFile + ".lock" }
func (a *Adapter) Detect(ctx context.Context, active *profile.Profile) target.Detection {
return target.Detection{Availability: a.Availability(ctx), Inspection: a.Inspect(ctx, active)}
inspection, err := a.inspect(active)
return target.Detection{Availability: a.Availability(ctx), Inspection: inspection, Err: redactError(err, active)}
}
// Inspect preserves the maintenance state projection while Detect also
// reports malformed or unreadable state as a failed check.
func (a *Adapter) Inspect(_ context.Context, active *profile.Profile) target.Inspection {
inspection, _ := a.inspect(active)
return inspection
}
func (a *Adapter) inspect(active *profile.Profile) (target.Inspection, error) {
metadata, managed, metadataErr := a.readRecovery()
config, _, configErr := a.readConfig()
if managed || (metadataErr != nil && !errors.Is(metadataErr, fs.ErrNotExist)) {
if metadataErr != nil {
return target.Inspection{State: target.Drifted, Evidence: "managed Docker client recovery metadata cannot be read"}
return target.Inspection{State: target.Drifted, Evidence: "managed Docker client recovery metadata cannot be read"}, fmt.Errorf("inspect Docker client recovery metadata: %w", metadataErr)
}
if configErr != nil {
return target.Inspection{State: target.Drifted, Evidence: "managed Docker client configuration is missing, unreadable, or not safely mergeable"}
return target.Inspection{State: target.Drifted, Evidence: "managed Docker client configuration is missing, unreadable, or not safely mergeable"}, fmt.Errorf("inspect managed Docker client configuration: %w", configErr)
}
desired, desiredErr := desiredDefaults(active)
if desiredErr == nil && fingerprintCurrent(config) == metadata.Fingerprint && fingerprintDefaults(desired) == metadata.Fingerprint {
return target.Inspection{State: target.Enabled, Evidence: "managed Docker client proxy defaults match the Active Profile"}
return target.Inspection{State: target.Enabled, Evidence: "managed Docker client proxy defaults match the Active Profile"}, nil
}
return target.Inspection{State: target.Drifted, Evidence: "managed Docker client proxy defaults do not match the Active Profile"}
return target.Inspection{State: target.Drifted, Evidence: "managed Docker client proxy defaults do not match the Active Profile"}, nil
}
if configErr == nil && recognizesProxyDefaults(config) {
return target.Inspection{State: target.External, Evidence: "recognized proxy defaults exist in Docker client config.json"}
if configErr != nil {
return target.Inspection{State: target.Disabled, Evidence: "Docker client configuration could not be inspected safely"}, fmt.Errorf("inspect Docker client configuration: %w", configErr)
}
return target.Inspection{State: target.Disabled, Evidence: "no recognized Docker client proxy defaults detected"}
proxies, _, err := childObject(config, "proxies")
if err != nil {
return target.Inspection{State: target.Disabled, Evidence: "Docker client configuration could not be inspected safely"}, err
}
defaults, _, err := childObject(proxies, "default")
if err != nil {
return target.Inspection{State: target.Disabled, Evidence: "Docker client configuration could not be inspected safely"}, err
}
if err := validateManagedProxyStrings(defaults); err != nil {
return target.Inspection{State: target.Disabled, Evidence: "Docker client configuration could not be inspected safely"}, err
}
for _, key := range append(append([]string(nil), managedKeys...), "ftpProxy") {
var value string
if raw, ok := defaults[key]; ok && json.Unmarshal(raw, &value) == nil && value != "" {
return target.Inspection{State: target.External, Evidence: "recognized proxy defaults exist in Docker client config.json"}, nil
}
}
return target.Inspection{State: target.Disabled, Evidence: "no recognized Docker client proxy defaults detected"}, nil
}
func (a *Adapter) SetDesired(ctx context.Context, enabled bool, active *profile.Profile) target.OperationResult {
@@ -613,6 +638,9 @@ type redactedError struct {
func (e *redactedError) Error() string { return e.message }
func (e *redactedError) Is(other error) bool { return e.class != nil && errors.Is(e.class, other) }
func redactError(err error, active *profile.Profile) error {
if err == nil {
return nil
}
message := profile.RedactText(err.Error())
if active != nil {
for _, raw := range []string{active.SingleURL, active.HTTPURL, active.HTTPSURL, active.AllURL} {
@@ -20,6 +20,19 @@ import (
"proxyctl/internal/target/targettest"
)
func TestDetectClassifiesMalformedClientConfigurationAsFailure(t *testing.T) {
a := newAdapter(t, nil)
writeConfig(t, a.ConfigPath(), `{"proxies":[]}`)
detection := a.Detect(context.Background(), activeProfile())
if detection.Err == nil || detection.Inspection.State != target.Disabled {
t.Fatalf("detection = %#v, want failed Disabled inspection", detection)
}
if got := a.Inspect(context.Background(), activeProfile()); got.State != target.Disabled {
t.Fatalf("maintenance inspection = %#v, want established Disabled semantics", got)
}
}
func TestAvailabilityAndDescriptionDescribeOnlyDockerClientDefaults(t *testing.T) {
a := newAdapter(t, nil)
availability := a.Availability(context.Background())