Name Heroku personal account without an API call
GET /teams/@personal 404s, which would loop the source-name worker the same way a stale Sentry slug did. Short-circuit the personal-account slug to a static name before any HTTP call. Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -726,6 +726,12 @@ func (r *herokuNameResolver) ResolveInstanceName(ctx context.Context) (string, e
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// A personal account has no Team to name; short-circuit before hitting
|
||||
// GET /teams/@personal, which 404s and would loop the source-name worker.
|
||||
if r.teamID == herokuPersonalAccountSlug {
|
||||
return herokuPersonalAccountDisplayName, nil
|
||||
}
|
||||
|
||||
endpoint, err := url.JoinPath("https://api.heroku.com", "teams", url.PathEscape(r.teamID))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot build heroku team URL: %w", err)
|
||||
|
||||
@@ -248,6 +248,42 @@ func TestTailscaleNameResolver(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHerokuNameResolver(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("personal-account slug returns a name without an HTTP call", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client := &http.Client{Transport: roundTripperFunc(func(*http.Request) (*http.Response, error) {
|
||||
t.Fatalf("resolver should not make an HTTP call for a personal account")
|
||||
return nil, nil
|
||||
})}
|
||||
|
||||
got, err := NewHerokuNameResolver(client, herokuPersonalAccountSlug).ResolveInstanceName(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Personal account", got)
|
||||
})
|
||||
|
||||
t.Run("team slug resolves the team name", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, http.MethodGet, r.Method)
|
||||
assert.Equal(t, "/teams/acme", r.URL.Path)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte(`{"name":"Acme Inc"}`))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
client := &http.Client{Transport: &hostRewriter{target: srv.URL}}
|
||||
|
||||
got, err := NewHerokuNameResolver(client, "acme").ResolveInstanceName(context.Background())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Acme Inc", got)
|
||||
})
|
||||
}
|
||||
|
||||
// roundTripperFunc adapts a function into an http.RoundTripper, useful for
|
||||
// asserting that a resolver short-circuits before making any HTTP call.
|
||||
type roundTripperFunc func(*http.Request) (*http.Response, error)
|
||||
|
||||
Reference in New Issue
Block a user