util/common/agent_util_unix.go (224 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT
//go:build !windows
package common
import (
"bytes"
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/amazon-cloudwatch-agent-test/environment"
)
const (
CatCommand = "cat "
AppOwnerCommand = "ps -u -p "
ConfigOutputPath = "/opt/aws/amazon-cloudwatch-agent/bin/config.json"
Namespace = "CWAgent"
Host = "host"
AgentLogFile = "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log"
InstallAgentVersionPath = "/opt/aws/amazon-cloudwatch-agent/bin/CWAGENT_VERSION"
)
type PackageManager int
const (
RPM PackageManager = iota
DEB
)
func CopyFile(pathIn string, pathOut string) {
log.Printf("Copy File %s to %s", pathIn, pathOut)
pathInAbs, err := filepath.Abs(pathIn)
if err != nil {
log.Fatal(err)
}
log.Printf("File %s abs path %s", pathIn, pathInAbs)
cmd := exec.Command("bash", "-c", "sudo cp "+pathInAbs+" "+pathOut)
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err = cmd.Run()
if err != nil {
log.Fatalf("Error : %s | Error Code: %s | Out: %s", fmt.Sprint(err), stderr.String(), out.String())
}
log.Printf("File : %s copied to : %s", pathIn, pathOut)
}
func DeleteFile(filePathAbsolute string) error {
log.Printf("Delete file %s", filePathAbsolute)
out, err := exec.Command("bash", "-c", "sudo rm "+filePathAbsolute).Output()
if err != nil {
log.Printf(fmt.Sprint(err) + string(out))
return err
}
log.Printf("Removed file: %s", filePathAbsolute)
return nil
}
func TouchFile(filePathAbsolute string) error {
log.Printf("Touch file %s", filePathAbsolute)
out, err := exec.Command("bash", "-c", "sudo touch "+filePathAbsolute).Output()
if err != nil {
log.Printf(fmt.Sprint(err) + string(out))
return err
}
log.Printf("Touched file: %s", filePathAbsolute)
return nil
}
// printOutputAndError does nothing if there was no error.
// Else it prints stdout and stderr.
func printOutputAndError(stdout []byte, err error) {
if err == nil {
return
}
stderr := ""
ee, ok := err.(*exec.ExitError)
if ok {
stderr = string(ee.Stderr)
}
log.Printf("failed\n\tstdout:\n%s\n\tstderr:\n%s\n", string(stdout), stderr)
}
func UninstallAgent(pm PackageManager) error {
log.Printf("Uninstalling Agent...")
var c *exec.Cmd
switch pm {
case RPM:
c = exec.Command("bash", "-c", "sudo rpm -e amazon-cloudwatch-agent")
case DEB:
c = exec.Command("bash", "-c", "sudo dpkg -r amazon-cloudwatch-agent")
default:
log.Fatalf("unsupported package manager, %v", pm)
}
out, err := c.Output()
printOutputAndError(out, err)
return err
}
// InstallAgent can determine the package manager based on the installer suffix.
func InstallAgent(installerFilePath string) error {
log.Printf("Installing Agent...")
var c *exec.Cmd
// Assuming lower case
if strings.HasSuffix(installerFilePath, ".rpm") {
c = exec.Command("bash", "-c", "sudo rpm -Uvh "+installerFilePath)
} else {
c = exec.Command("bash", "-c", "sudo dpkg -i -E "+installerFilePath)
}
out, err := c.Output()
printOutputAndError(out, err)
return err
}
func StartAgent(configOutputPath string, fatalOnFailure bool, ssm bool) error {
agentStartCommand := environment.GetEnvironmentMetaData().AgentStartCommand
return StartAgentWithCommand(configOutputPath, fatalOnFailure, ssm, agentStartCommand)
}
func StartAgentWithCommand(configOutputPath string, fatalOnFailure bool, ssm bool, agentStartCommand string) error {
path := "file:"
if ssm {
path = "ssm:"
}
completedAgentStartCommand := agentStartCommand + path + configOutputPath
log.Printf("Starting agent with command %s", completedAgentStartCommand)
out, err := exec.
Command("bash", "-c", completedAgentStartCommand).
Output()
if err != nil && fatalOnFailure {
log.Fatal(fmt.Sprint(err) + string(out))
} else if err != nil {
log.Printf(fmt.Sprint(err) + string(out))
} else {
log.Printf("Agent has started")
}
return err
}
func StopAgent() {
out, err := exec.
Command("bash", "-c", "sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a stop").
Output()
if err != nil {
log.Fatal(fmt.Sprint(err) + string(out))
}
log.Printf("Agent is stopped")
}
func ReadAgentLogfile(logfile string) string {
out, err := os.ReadFile(logfile)
if err != nil {
log.Fatal(fmt.Sprint(err) + string(out))
}
return string(out)
}
func RecreateAgentLogfile(logfile string) {
out, err := exec.Command("bash", "-c",
fmt.Sprintf("sudo rm %s", logfile)).
Output()
if err != nil {
log.Fatal(fmt.Sprint(err) + string(out))
}
}
func RunShellScript(path string, args ...string) (string, error) {
out, err := exec.Command("bash", "-c", "sudo chmod +x "+path).Output()
if err != nil {
log.Printf("Error occurred when attempting to chmod %s: %s | %s", path, err.Error(), string(out))
return "", err
}
bashArgs := []string{"-c", "sudo ./" + path}
bashArgs = append(bashArgs, args...)
//out, err = exec.Command("bash", "-c", "sudo ./"+path, args).Output()
out, err = exec.Command("bash", bashArgs...).Output()
if err != nil {
log.Printf("Error occurred when executing %s: %s | %s", path, err.Error(), string(out))
return "", err
}
return string(out), nil
}
func RunCommand(cmd string) (string, error) {
log.Printf("running cmd, %s", cmd)
out, err := exec.Command("bash", "-c", cmd).Output()
printOutputAndError(out, err)
return string(out), err
}
func RunAsyncCommand(cmd string) error {
log.Printf("running async cmd, %s", cmd)
return exec.Command("nohup", "bash", "-c", cmd).Start()
}
func RunCommands(commands []string) error {
for _, cmd := range commands {
_, err := RunCommand(cmd)
if err != nil {
return err
}
}
return nil
}
func ReplaceLocalStackHostName(pathIn string) {
out, err := exec.Command("bash", "-c", "sed -i 's/localhost.localstack.cloud/'\"$LOCAL_STACK_HOST_NAME\"'/g' "+pathIn).Output()
if err != nil {
log.Fatal(fmt.Sprint(err) + string(out))
}
}
func DownloadFromS3(bucket string, key string, destPath string) error {
sess := session.Must(session.NewSession())
s3Client := s3.New(sess)
result, err := s3Client.GetObject(&s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
})
if err != nil {
return fmt.Errorf("failed to download from S3 bucket %s, key %s: %v", bucket, key, err)
}
defer result.Body.Close()
outFile, err := os.Create(destPath)
if err != nil {
return fmt.Errorf("failed to create file at %s: %v", destPath, err)
}
defer outFile.Close()
_, err = io.Copy(outFile, result.Body)
if err != nil {
return fmt.Errorf("failed to copy content to %s: %v", destPath, err)
}
return nil
}
func SELinuxEnforced() (bool, error) {
status, err := os.ReadFile("/sys/fs/selinux/enforce")
if err != nil {
return false, err
}
if strings.TrimSpace(string(status)) == "1" {
return true, nil
}
return false, nil
}