Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add basic retry for http requests #350

Merged
merged 1 commit into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions tests/e2e/docker/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ func CleanUpDocker(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
b, err := e2e.RunCommand(ctx, `docker ps -aqf name=localdev-control-plane`, 10*time.Second)
assert.Nil(t, err, fmt.Sprintf("error while listing docker containers: %s, %s", err, b))
assert.NoError(t, err, fmt.Sprintf("error while listing docker containers: %s, %s", err, b))

conts := strings.TrimSpace(string(b))
if len(conts) == 0 {
return
}
b, err = e2e.RunCommand(ctx, fmt.Sprintf("docker container rm -f %s", conts), 60*time.Second)
assert.Nil(t, err, fmt.Sprintf("error while removing docker containers: %s, %s", err, b))
assert.NoError(t, err, fmt.Sprintf("error while removing docker containers: %s, %s", err, b))

b, err = e2e.RunCommand(ctx, "docker system prune -f", 60*time.Second)
assert.Nil(t, err, fmt.Sprintf("error while pruning system: %s, %s", err, b))
assert.NoError(t, err, fmt.Sprintf("error while pruning system: %s, %s", err, b))

b, err = e2e.RunCommand(ctx, "docker volume prune -f", 60*time.Second)
assert.Nil(t, err, fmt.Sprintf("error while pruning volumes: %s, %s", err, b))
assert.NoError(t, err, fmt.Sprintf("error while pruning volumes: %s, %s", err, b))
t.Log("finished cleaning up docker env")
}

Expand All @@ -59,10 +59,10 @@ func testCreate(t *testing.T) {
t.Log("running idpbuilder create")
cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, "create")
b, err := cmd.CombinedOutput()
assert.Nil(t, err, fmt.Sprintf("error while running create: %s, %s", err, b))
assert.NoError(t, err, b)

kubeClient, err := e2e.GetKubeClient()
assert.Nil(t, err, fmt.Sprintf("error while getting client: %s", err))
assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err))

e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages)

Expand All @@ -80,10 +80,10 @@ func testCreatePath(t *testing.T) {
t.Log("running idpbuilder create --use-path-routing")
cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, "create", "--use-path-routing")
b, err := cmd.CombinedOutput()
assert.Nil(t, err, fmt.Sprintf("error while running create: %s, %s", err, b))
assert.NoError(t, err, fmt.Sprintf("error while running create: %s, %s", err, b))

kubeClient, err := e2e.GetKubeClient()
assert.Nil(t, err, fmt.Sprintf("error while getting client: %s", err))
assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err))

e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages)

Expand All @@ -101,10 +101,10 @@ func testCreatePort(t *testing.T) {
t.Logf("running idpbuilder create --port %s", port)
cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, "create", "--port", port)
b, err := cmd.CombinedOutput()
assert.Nil(t, err, fmt.Sprintf("error while running create: %s, %s", err, b))
assert.NoError(t, err, fmt.Sprintf("error while running create: %s, %s", err, b))

kubeClient, err := e2e.GetKubeClient()
assert.Nil(t, err, fmt.Sprintf("error while getting client: %s", err))
assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err))

e2e.TestArgoCDApps(ctx, t, kubeClient, e2e.CorePackages)

Expand All @@ -123,11 +123,11 @@ func testCustomPkg(t *testing.T) {
t.Log(fmt.Sprintf("running %s", cmdString))
cmd := exec.CommandContext(ctx, e2e.IdpbuilderBinaryLocation, strings.Split(cmdString, " ")...)
b, err := cmd.CombinedOutput()
assert.Nil(t, err, fmt.Sprintf("error while running create: %s, %s", err, b))
assert.NoError(t, err, fmt.Sprintf("error while running create: %s, %s", err, b))

kubeClient, err := e2e.GetKubeClient()

assert.Nil(t, err, fmt.Sprintf("error while getting client: %s", err))
assert.NoError(t, err, fmt.Sprintf("error while getting client: %s", err))
if err != nil {
assert.FailNow(t, "failed creating cluster")
}
Expand All @@ -142,7 +142,7 @@ func testCustomPkg(t *testing.T) {
}
e2e.TestArgoCDApps(ctx, t, kubeClient, expectedApps)
repos, err := e2e.GetGiteaRepos(ctx, giteaBaseUrl)
assert.Nil(t, err)
assert.NoError(t, err)
expectedRepoNames := map[string]struct{}{
"idpbuilder-localdev-my-app-app1": {},
"idpbuilder-localdev-my-app2-app2": {},
Expand Down
69 changes: 50 additions & 19 deletions tests/e2e/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const (
GiteaSessionEndpoint = "/api/v1/users/%s/tokens"
GiteaUserEndpoint = "/api/v1/users/%s"
GiteaRepoEndpoint = "/api/v1/repos/search"

httpRetryDelay = 5 * time.Second
httpRetryTimeout = 300 * time.Second
)

var (
Expand Down Expand Up @@ -97,24 +100,52 @@ func RunCommand(ctx context.Context, command string, timeout time.Duration) ([]b
return b, nil
}

func SendAndParse(target any, httpClient *http.Client, req *http.Request) error {
resp, err := httpClient.Do(req)
if err != nil {
return fmt.Errorf("running http request: %w", err)
func SendAndParse(ctx context.Context, target any, httpClient *http.Client, req *http.Request) error {
sendCtx, cancel := context.WithTimeout(ctx, httpRetryTimeout)
defer cancel()
var bodyBytes []byte
if req.Body != nil {
b, bErr := io.ReadAll(req.Body)
if bErr != nil {
return fmt.Errorf("failed copying http request body: %w", bErr)
}
bodyBytes = b
}

defer resp.Body.Close()
for {
select {
case <-sendCtx.Done():
return fmt.Errorf("timedout")
default:
if req.Body != nil {
b := append(make([]byte, 0, len(bodyBytes)), bodyBytes...)
req.Body = io.NopCloser(bytes.NewBuffer(b))
}
resp, err := httpClient.Do(req)
if err != nil {
fmt.Println("failed running http request: ", err)
time.Sleep(httpRetryDelay)
continue
}

defer resp.Body.Close()

respB, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("reading http response body: %w", err)
}
respB, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("failed reading http response body: ", err)
time.Sleep(httpRetryDelay)
continue
}

err = json.Unmarshal(respB, target)
if err != nil {
return fmt.Errorf("parsing response body %s, %s", err, respB)
err = json.Unmarshal(respB, target)
if err != nil {
fmt.Println("failed parsing response body: ", err, "\n", string(respB))
time.Sleep(httpRetryDelay)
continue
}
return nil
}
}
return nil
}

func TestGiteaEndpoints(ctx context.Context, t *testing.T, baseUrl string) {
Expand Down Expand Up @@ -159,15 +190,15 @@ func GetGiteaRepos(ctx context.Context, baseUrl string) ([]gitea.Repository, err
req.Header.Set("Authorization", fmt.Sprintf("token %s", token))

user := gitea.User{}
err = SendAndParse(&user, httpClient, req)
err = SendAndParse(ctx, &user, httpClient, req)
if err != nil {
return nil, fmt.Errorf("getting user info %w", err)
}

repos := GiteaSearchRepoResponse{}
repoEp := fmt.Sprintf("%s%s", baseUrl, GiteaRepoEndpoint)
repoReq, _ := http.NewRequestWithContext(ctx, http.MethodGet, repoEp, nil)
err = SendAndParse(&repos, httpClient, repoReq)
err = SendAndParse(ctx, &repos, httpClient, repoReq)
if err != nil {
return nil, fmt.Errorf("getting gitea repositories %w", err)
}
Expand All @@ -189,7 +220,7 @@ func GetGiteaSessionToken(ctx context.Context, auth BasicAuth, baseUrl string) (
sessionReq.Header.Set("Content-Type", "application/json")

var sess gitea.AccessToken
err = SendAndParse(&sess, httpClient, sessionReq)
err = SendAndParse(ctx, &sess, httpClient, sessionReq)
if err != nil {
return "", err
}
Expand All @@ -214,7 +245,7 @@ func TestArgoCDEndpoints(ctx context.Context, t *testing.T, baseUrl string) {
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))

var appResp ArgoCDAppResp
err = SendAndParse(&appResp, httpClient, req)
err = SendAndParse(ctx, &appResp, httpClient, req)
assert.Nil(t, err, fmt.Sprintf("getting argocd applications: %s", err))

assert.Equal(t, 3, len(appResp.Items), fmt.Sprintf("number of apps do not match: %v", appResp.Items))
Expand Down Expand Up @@ -267,7 +298,7 @@ func GetArgoCDSessionToken(ctx context.Context, endpoint string) (string, error)
req.Header.Set("Content-Type", "application/json")

var tokenResp ArgoCDAuthResponse
err = SendAndParse(&tokenResp, httpClient, req)
err = SendAndParse(ctx, &tokenResp, httpClient, req)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -301,7 +332,7 @@ func TestArgoCDApps(ctx context.Context, t *testing.T, kubeClient client.Client,
}
if len(apps) != 0 {
t.Logf("waiting for apps to be ready")
time.Sleep(3 * time.Second)
time.Sleep(httpRetryDelay)
continue
}
done = true
Expand Down
Loading