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

Update canary test to use public S3 download link. #404

Merged
merged 4 commits into from
Apr 19, 2024
Merged
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
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
}
Loading