diff --git a/test/canary/canary_test.go b/test/canary/canary_test.go index d0d92ab04..6d4116ecd 100644 --- a/test/canary/canary_test.go +++ b/test/canary/canary_test.go @@ -7,7 +7,9 @@ package canary import ( "errors" "fmt" + "io" "log" + "net/http" "os" "strings" "testing" @@ -22,6 +24,10 @@ import ( const ( configInputPath = "resources/canary_config.json" + // todo: expand testing to include regional S3 links. + // todo: test ARM64, DEB, MSI based on OS type. + downloadLink = "https://amazoncloudwatch-agent.s3.amazonaws.com/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm" + versionLink = "https://amazoncloudwatch-agent.s3.amazonaws.com/info/latest/CWAGENT_VERSION" ) func init() { @@ -31,22 +37,24 @@ func init() { // TestCanary verifies downloading, installing, and starting the agent. // Reports metrics for each failure type. func TestCanary(t *testing.T) { - e := environment.GetEnvironmentMetaData() - defer setupCron(e.Bucket, e.S3Key) + defer setupCron() // Don't care if uninstall fails. Agent might not be installed anyways. _ = common.UninstallAgent(common.RPM) // S3 keys always use backslash, so split on that to get filename. - installerFilePath := "./" + e.S3Key[strings.LastIndex(e.S3Key, "/")+1:] - err := awsservice.DownloadFile(e.Bucket, e.S3Key, installerFilePath) + installerFilePath := "./" + downloadLink[strings.LastIndex(downloadLink, "/")+1:] + err := downloadFile(installerFilePath, downloadLink) reportMetric(t, "DownloadFail", err) err = common.InstallAgent(installerFilePath) reportMetric(t, "InstallFail", err) common.CopyFile(configInputPath, common.ConfigOutputPath) err = common.StartAgent(common.ConfigOutputPath, false, false) reportMetric(t, "StartFail", err) - actualVersion, _ := os.ReadFile(common.InstallAgentVersionPath) - expectedVersion, _ := getVersionFromS3(e.Bucket) - if expectedVersion != string(actualVersion) { + data, _ := os.ReadFile(common.InstallAgentVersionPath) + actualVersion := strings.TrimSpace(string(data)) + expectedVersion, _ := getVersionFromS3() + expectedVersion = strings.TrimSpace(expectedVersion) + log.Printf("expected version: %s, actual version: %s", expectedVersion, actualVersion) + if expectedVersion != actualVersion { err = errors.New("agent version mismatch") } reportMetric(t, "VersionFail", err) @@ -65,11 +73,9 @@ func reportMetric(t *testing.T, name string, err error) { require.NoError(t, err) } -func getVersionFromS3(bucket string) (string, error) { +func getVersionFromS3() (string, error) { filename := "./CWAGENT_VERSION" - // Assuming the release process will create this s3 key. - key := "release/CWAGENT_VERSION" - err := awsservice.DownloadFile(bucket, key, filename) + err := downloadFile(filename, versionLink) if err != nil { return "", err } @@ -77,33 +83,53 @@ func getVersionFromS3(bucket string) (string, error) { return string(v), err } -func setupCron(bucket, key string) { +func setupCron() { // default to us-west-2 region := os.Getenv("AWS_REGION") if region == "" { region = "us-west-2" } - // Need to create a temporary file at low privilege. // Then use sudo to copy it to the CRON directory. src := "resources/canary_test_cron" - updateCron(src, region, bucket, key) + updateCron(src, region) dst := "/etc/cron.d/canary_test_cron" common.CopyFile(src, dst) } -func updateCron(filepath, region, bucket, s3Key string) { +func updateCron(filepath, region string) { // cwd will be something like .../amazon-cloudwatch-agent-test/test/canary/ cwd, err := os.Getwd() log.Printf("cwd %s", cwd) if err != nil { log.Fatalf("error: Getwd(), %s", err) } - s := fmt.Sprintf("MAILTO=\"\"\n*/5 * * * * ec2-user cd %s && AWS_REGION=%s go test ./ -count=1 -computeType=EC2 -bucket=%s -s3key=%s > ./cron_run.log\n", - cwd, region, bucket, s3Key) + s := fmt.Sprintf("MAILTO=\"\"\n*/5 * * * * ec2-user cd %s && AWS_REGION=%s go test ./ -count=1 -computeType=EC2 > ./cron_run.log\n", + cwd, region) b := []byte(s) err = os.WriteFile(filepath, b, 0644) if err != nil { log.Println("error: creating temp cron file") } } + +// downloadFile will download from a given url to a file. It will +// write as it downloads (useful for large files). +func downloadFile(filepath string, url string) error { + log.Printf("downloading from %s to %s", url, filepath) + // Get the data + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + // Create the file + out, err := os.Create(filepath) + if err != nil { + return err + } + defer out.Close() + // Write the body to file + _, err = io.Copy(out, resp.Body) + return err +}