Skip to content

Commit 9006795

Browse files
authored
Fix AWS CLI install/download flakiness in Windows E2E host_cache (#54725)
### What does this PR do? - Check msiexec's real exit code instead of just whether `Start-Process` launched it. - Retry the AWS CLI install and `aws s3 cp` to handle flaky network. - Collect the msiexec install log into the test artifacts folder on failure. ### Motivation Try to avoid flakes like https://gitlab.ddbuild.io/DataDog/datadog-agent/-/jobs/1914723351. See https://datadoghq.atlassian.net/browse/WINA-3000 Co-authored-by: branden.clark <branden.clark@datadoghq.com>
1 parent eb013eb commit 9006795

1 file changed

Lines changed: 48 additions & 2 deletions

File tree

test/e2e-framework/testing/utils/e2e/client/host_cache.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,33 @@
66
package client
77

88
import (
9+
"context"
910
"errors"
1011
"fmt"
12+
"path/filepath"
13+
"strings"
14+
"time"
15+
16+
"github.com/cenkalti/backoff/v7"
17+
"github.com/pkg/sftp"
1118

1219
"github.com/DataDog/datadog-agent/test/e2e-framework/components"
1320
oscomp "github.com/DataDog/datadog-agent/test/e2e-framework/components/os"
1421
)
1522

1623
const (
1724
cacheBucketURL = "s3://agent-e2e-s3-bucket"
25+
26+
// awsCliInstallRetries/awsS3CopyRetries account for a flaky AWS network on the test host.
27+
awsCliInstallRetries = 3
28+
awsS3CopyRetries = 3
29+
awsRetryInterval = 5 * time.Second
30+
31+
awsCliRemoteInstallLogPath = `C:\Windows\Temp\awscli-install.log`
32+
33+
// msiExitSuccessRebootRequired is the successful msiexec exit code returned when /norestart
34+
// defers a pending reboot. See https://learn.microsoft.com/en-us/windows/win32/msi/error-codes
35+
msiExitSuccessRebootRequired = 3010
1836
)
1937

2038
type unimplementedHostCache struct{}
@@ -65,15 +83,43 @@ func (c *windowsAWSCLI) ensureInstalled() error {
6583
if _, err := c.sshExecutor.Execute("& \"c:\\Program Files\\Amazon\\AWSCLIV2\\aws.exe\" --version"); err == nil {
6684
return nil
6785
}
68-
_, err := c.sshExecutor.Execute("Start-Process msiexec.exe -Wait -ArgumentList \"/i https://awscli.amazonaws.com/AWSCLIV2.msi /qn /norestart /L*V ./awscli-install.log\" ")
86+
_, err := backoff.Retry(context.Background(), func() (any, error) {
87+
// Start-Process's own exit code only reflects whether it launched msiexec, not whether the
88+
// install succeeded, so capture the process with -PassThru and check its ExitCode explicitly.
89+
_, err := c.sshExecutor.Execute(fmt.Sprintf(
90+
`$p = Start-Process msiexec.exe -Wait -PassThru -ArgumentList "/i https://awscli.amazonaws.com/AWSCLIV2.msi /qn /norestart /L*V %s"; if ($p.ExitCode -ne 0 -and $p.ExitCode -ne %d) { throw "msiexec exited with code $($p.ExitCode)" }`,
91+
awsCliRemoteInstallLogPath, msiExitSuccessRebootRequired))
92+
return nil, err
93+
}, backoff.WithBackOff(backoff.NewConstantBackOff(awsRetryInterval)), backoff.WithMaxTries(awsCliInstallRetries))
94+
c.collectInstallLog()
6995
return err
7096
}
7197

98+
// collectInstallLog best-effort copies the AWS CLI msiexec log to the test's artifacts folder,
99+
// mirroring the log collection test/new-e2e/tests/windows/common/msi.go does for Agent MSI installs.
100+
func (c *windowsAWSCLI) collectInstallLog() {
101+
sftpClient, err := sftp.NewClient(c.sshExecutor.client, sftp.UseConcurrentWrites(true))
102+
if err != nil {
103+
c.sshExecutor.context.Logf("failed to collect AWS CLI install log: %v", err)
104+
return
105+
}
106+
defer sftpClient.Close()
107+
108+
remotePath := strings.ReplaceAll(awsCliRemoteInstallLogPath, "\\", "/")
109+
localPath := filepath.Join(c.sshExecutor.context.SessionOutputDir(), "awscli-install.log")
110+
if err := downloadFile(sftpClient, remotePath, localPath); err != nil {
111+
c.sshExecutor.context.Logf("failed to collect AWS CLI install log: %v", err)
112+
}
113+
}
114+
72115
func (c *windowsAWSCLI) download(path string, destPath string) error {
73116
if err := c.ensureInstalled(); err != nil {
74117
return err
75118
}
76-
_, err := c.sshExecutor.Execute(fmt.Sprintf("& \"c:\\Program Files\\Amazon\\AWSCLIV2\\aws.exe\" s3 cp \"%s\" \"%s\"", path, destPath))
119+
_, err := backoff.Retry(context.Background(), func() (any, error) {
120+
_, err := c.sshExecutor.Execute(fmt.Sprintf("& \"c:\\Program Files\\Amazon\\AWSCLIV2\\aws.exe\" s3 cp \"%s\" \"%s\"", path, destPath))
121+
return nil, err
122+
}, backoff.WithBackOff(backoff.NewConstantBackOff(awsRetryInterval)), backoff.WithMaxTries(awsS3CopyRetries))
77123
return err
78124
}
79125

0 commit comments

Comments
 (0)