package hub import ( "context" "net/http" "testing" ) // FetchDesiredState GETs the SELF-SCOPED path with the bearer token and decodes the response. func TestFetchDesiredState_PathAuthAndDecode(t *testing.T) { var gotPath, gotAuth, gotMethod string c := testClient(func(r *http.Request) (*http.Response, error) { gotPath = r.URL.Path gotAuth = r.Header.Get("Authorization") gotMethod = r.Method return httpResp(200, `{"generation":4,"desired_state":{"guests":[ {"vmid":100,"run":"running"}, {"vmid":200,"decommission":true} ],"restore_directive":{"mode":"guest_loss","archive":"local:backup/x","vmid":100}}}`), nil }) resp, err := c.FetchDesiredState(context.Background()) if err != nil { t.Fatalf("FetchDesiredState: %v", err) } // Self-scoped: the client only ever fetches ITS OWN host (the configured host_id). if gotMethod != http.MethodGet || gotPath != "/api/v1/hosts/demo-host-01/desired-state" { t.Errorf("request = %s %s, want GET /api/v1/hosts/demo-host-01/desired-state", gotMethod, gotPath) } if gotAuth != "Bearer super-secret-bearer-key" { t.Errorf("auth header = %q, want the per-host bearer", gotAuth) } if resp.Generation != 4 { t.Errorf("generation = %d, want 4", resp.Generation) } if len(resp.DesiredState.Guests) != 2 { t.Fatalf("guests = %d, want 2", len(resp.DesiredState.Guests)) } if resp.DesiredState.Guests[0].Run != "running" || !resp.DesiredState.Guests[1].Decommission { t.Errorf("guests = %+v", resp.DesiredState.Guests) } // Forward-compat restore_directive is carried through (consumed in 10D). if resp.DesiredState.RestoreDirective == nil || resp.DesiredState.RestoreDirective.Mode != "guest_loss" { t.Errorf("restore_directive = %+v, want carried (mode guest_loss)", resp.DesiredState.RestoreDirective) } } // A non-2xx response is a typed HTTPError (e.g. a 403 self-scope refusal from the hub). func TestFetchDesiredState_HTTPError(t *testing.T) { c := testClient(func(r *http.Request) (*http.Response, error) { return httpResp(403, `Forbidden: host_id mismatch`), nil }) _, err := c.FetchDesiredState(context.Background()) if err == nil { t.Fatal("expected an error on 403") } var he *HTTPError if !asHTTPError(err, &he) || he.StatusCode != 403 { t.Errorf("err = %v, want HTTPError 403", err) } } func asHTTPError(err error, target **HTTPError) bool { for err != nil { if he, ok := err.(*HTTPError); ok { *target = he return true } type unwrapper interface{ Unwrap() error } if u, ok := err.(unwrapper); ok { err = u.Unwrap() } else { return false } } return false }