Handle context cancellation in ListAccounts and add corresponding test

Signed-off-by: Steven4Hooisma <112615049+Steven4Hooisma@users.noreply.github.com>
This commit is contained in:
Steven4Hooisma
2026-07-23 16:06:44 +02:00
committed by Aurélien Sibiril
parent 9cdc77ba8e
commit dbc49748f9
2 changed files with 49 additions and 0 deletions

View File

@@ -126,6 +126,10 @@ func (d *UpCloudDriver) ListAccounts(ctx context.Context) ([]AccountRecord, erro
details, err := d.fetchAccountDetails(ctx, username)
if err != nil {
if ctx.Err() != nil {
return nil, fmt.Errorf("cannot list upcloud accounts: %w", ctx.Err())
}
d.logger.WarnCtx(ctx, "cannot fetch upcloud account details, using list fields only", log.Error(err))
} else {
if name := strings.TrimSpace(details.FirstName + " " + details.LastName); name != "" {

View File

@@ -22,7 +22,11 @@ package drivers
import (
"context"
"errors"
"io"
"net/http"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -77,3 +81,44 @@ func TestUpCloudDriver(t *testing.T) {
assert.Equal(t, []string{"billing"}, billing.Roles)
assert.False(t, billing.IsAdmin)
}
// upcloudRoundTripFunc adapts a function to http.RoundTripper.
type upcloudRoundTripFunc func(*http.Request) (*http.Response, error)
func (f upcloudRoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return f(req)
}
// TestUpCloudDriverContextCancellation verifies that a context canceled
// mid-run aborts ListAccounts with the cancellation error instead of being
// swallowed as a best-effort per-account detail failure, which would let a
// caller mistake a truncated run for a complete, successful sync.
func TestUpCloudDriverContextCancellation(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
client := &http.Client{
Transport: upcloudRoundTripFunc(func(req *http.Request) (*http.Response, error) {
if strings.Contains(req.URL.Path, "/account/details/") {
cancel()
return nil, ctx.Err()
}
body := `{"accounts":{"account":[{"labels":[],"roles":{"role":["technical"]},"type":"mymain","username":"test"}]}}`
return &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader(body)),
Header: http.Header{"Content-Type": []string{"application/json"}},
}, nil
}),
}
driver := NewUpCloudDriver(client, log.NewLogger(log.WithName("test")))
records, err := driver.ListAccounts(ctx)
require.Error(t, err)
assert.True(t, errors.Is(err, context.Canceled))
assert.Nil(t, records)
}