Skip to content

Commit

Permalink
Update canary test to use public S3 download link. (#404)
Browse files Browse the repository at this point in the history
* Update canary test to use public S3 download link.
  • Loading branch information
adam-mateen authored Apr 19, 2024
1 parent ff4892e commit d4e556e
Showing 1 changed file with 43 additions and 17 deletions.
60 changes: 43 additions & 17 deletions test/canary/canary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ package canary
import (
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"testing"
Expand All @@ -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() {
Expand All @@ -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)
Expand All @@ -65,45 +73,63 @@ 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
}
v, err := os.ReadFile(filename)
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
}

0 comments on commit d4e556e

Please sign in to comment.