From e4fe057d9ffed210ae0c6f4f605e5ae7ae4a676a Mon Sep 17 00:00:00 2001 From: Nithish Date: Tue, 25 Jun 2019 11:17:50 -0500 Subject: [PATCH] Moving log collector script to Amazon eks ami repo (#243) * Moving log collector script to this repo * Added changes according to 1.4.1 --- log-collector-script/README.md | 110 +++++ log-collector-script/eks-log-collector.sh | 570 ++++++++++++++++++++++ log-collector-script/eks-ssm-content.json | 44 ++ 3 files changed, 724 insertions(+) create mode 100644 log-collector-script/README.md create mode 100644 log-collector-script/eks-log-collector.sh create mode 100644 log-collector-script/eks-ssm-content.json diff --git a/log-collector-script/README.md b/log-collector-script/README.md new file mode 100644 index 000000000..d63bc271b --- /dev/null +++ b/log-collector-script/README.md @@ -0,0 +1,110 @@ +### EKS Logs Collector + +This project was created to collect Amazon EKS log files and OS logs for troubleshooting Amazon EKS customer support cases. + +#### Usage +* Collect EKS logs using SSM agent, jump to below [section](#collect-eks-logs-using-ssm-agent) _(or)_ + +* Run this project as the root user: +``` +curl -O https://raw.githubusercontent.com/nithu0115/eks-logs-collector/master/eks-log-collector.sh +sudo bash eks-log-collector.sh +``` + +Confirm if the tarball file was successfully created (it can be .tgz or .tar.gz) + +#### Retrieving the logs +Download the tarball using your favourite Secure Copy tool. + +#### Example output +The project can be used in normal or enable_debug(**Caution: enable_debug will prompt to confirm if we can restart Docker daemon which would kill running containers**). + +``` +# sudo bash eks-log-collector.sh --help +USAGE: eks-log-collector --help [ --mode=collect|enable_debug --ignore_introspection=true|false --ignore_metrics=true|false ] + +OPTIONS: + --mode Has two parameters 1) collect or 2) enable_debug,: + collect Gathers basic operating system, Docker daemon, and + Amazon EKS related config files and logs. This is the default mode. + enable_debug Enables debug mode for the Docker daemon(Not for production use) + + --ignore_introspection To ignore introspection of IPAMD; Pass this flag if DISABLE_INTROSPECTION is enabled on CNI + + --ignore_metrics To ignore prometheus metrics collection; Pass this flag if DISABLE_METRICS enabled on CNI + + --help Show this help message. + +Example to Ignore IPAMD introspection: +sudo bash eks-log-collector.sh --ignore_introspection=true + +Example to Ignore IPAMD Prometheus metrics collection: +sudo bash eks-log-collector.sh --ignore_metrics=true + +Example to Ignore IPAMD introspection and Prometheus metrics collection: +sudo bash eks-log-collector.sh --ignore_introspection=true --ignore_metrics=true +``` +#### Example output in normal mode +The following output shows this project running in normal mode. + +``` +sudo bash eks-log-collector.sh + + This is version 0.5.0. New versions can be found at https://github.com/awslabs/amazon-eks-ami + +Trying to collect common operating system logs... +Trying to collect kernel logs... +Trying to collect mount points and volume information... +Trying to collect SELinux status... +Trying to collect iptables information... +Trying to collect installed packages... +Trying to collect active system services... +Trying to collect Docker daemon information... +Trying to collect kubelet information... +Trying to collect L-IPAMD information... +Trying to collect sysctls information... +Trying to collect networking infomation... +Trying to collect CNI configuration information... +Trying to collect running Docker containers and gather container data... +Trying to collect Docker daemon logs... +Trying to archive gathered information... + + Done... your bundled logs are located in /opt/log-collector/eks_i-0717c9d54b6cfaa19_2019-02-02_0103-UTC_0.0.4.tar.gz +``` + + +### Collect EKS logs using SSM agent +#### To run EKS log collector script on Worker Node(s) and upload the bundle(tar) to a S3 Bucket using SSM agent, please follow below steps + +##### *Prerequisites*: + +* Configure AWS CLI on the system where you will run the below commands. The IAM entity (User/Role) should have permissions to run/invoke `aws ssm send-command` and `get-command-invocation` commands. + +* SSM agent should be installed and running on Worker Node(s). [How to Install SSM Agent link](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-manual-agent-install.html) + +* Worker Node(s) should have required permissions to communicate with SSM service. IAM managed role `AmazonEC2RoleforSSM` will have all the required permission for SSM agent to run on EC2 instances. The IAM managed role `AmazonEC2RoleforSSM` has `S3:PutObject` permission to all S3 resources. + +        *Note:* For more granular control of the IAM permission check [AWS Systems Manager Permissions link ](https://docs.aws.amazon.com/systems-manager/latest/userguide/auth-and-access-control-permissions-reference.html) + +* A S3 bucket location is required which is taken as an input parameter to `aws ssm send-command` command, to which the logs should be pushed. + + +#### *To invoke SSM agent to run EKS log collector script and push bundle to S3 from Worker Node(s):* + +1. Create the SSM document named "EKSLogCollector" using the following command:
+``` +aws ssm create-document --name "EKSLogCollector" --document-type "Command" --content https://raw.githubusercontent.com/nithu0115/eks-logs-collector/master/eks-ssm-content.json +``` +2. To execute the bash script in the SSM document and to collect the logs from worker, run the following command:
+``` +aws ssm send-command --instance-ids --document-name "EKSLogCollector" --parameters "bucketName=" --output json +``` +3. To check the status of SSM command submitted in previous step use the command
+``` +aws ssm get-command-invocation --command-id "" --instance-id "" --output text +``` +    `SSM command ID`One of the response parameters after running `aws ssm send-command` in step2
+    `EC2 Instance ID`The EC2 Instance ID provided in the `aws ssm send-command` in step2 + +4. Once the above command is executed successfully, the logs should be present in the S3 bucket specified in the previous step. + diff --git a/log-collector-script/eks-log-collector.sh b/log-collector-script/eks-log-collector.sh new file mode 100644 index 000000000..44ae0d7d5 --- /dev/null +++ b/log-collector-script/eks-log-collector.sh @@ -0,0 +1,570 @@ +#!/usr/bin/env bash + +# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You may +# not use this file except in compliance with the License. A copy of the +# License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# This script generates a file in go with the license contents as a constant + +# Set language to C to make sorting consistent among different environments. + +export LANG="C" +export LC_ALL="C" + +# Global options +readonly PROGRAM_VERSION="0.5.1" +readonly PROGRAM_SOURCE="https://github.com/awslabs/amazon-eks-ami/blob/master/log-collector-script/" +readonly PROGRAM_NAME="$(basename "$0" .sh)" +readonly PROGRAM_DIR="/opt/log-collector" +readonly COLLECT_DIR="/tmp/${PROGRAM_NAME}" +readonly DAYS_10=$(date -d "-10 days" '+%Y-%m-%d %H:%M') +INSTANCE_ID="" +INIT_TYPE="" +PACKAGE_TYPE="" + +# Script run defaults +mode='collect' +ignore_introspection='false' +ignore_metrics='false' + +REQUIRED_UTILS=( + timeout + curl + tar + date + mkdir + iptables + iptables-save + grep + awk + df + sysctl +) + +COMMON_DIRECTORIES=( + kernel + system + docker + storage + var_log + networking + ipamd # eks + sysctls # eks + kubelet # eks + cni # eks +) + +COMMON_LOGS=( + syslog + messages + aws-routed-eni # eks + containers # eks + pods # eks + cloud-init.log + cloud-init-output.log + kube-proxy.log +) + +# L-IPAMD introspection data points +IPAMD_DATA=( + enis + pods + networkutils-env-settings + ipamd-env-settings + eni-configs +) + +help() { + echo "" + echo "USAGE: ${PROGRAM_NAME} --help [ --mode=collect|enable_debug --ignore_introspection=true|false --ignore_metrics=true|false ]" + echo "" + echo "OPTIONS:" + echo " --mode Has two parameters 1) collect or 2) enable_debug,:" + echo " collect Gathers basic operating system, Docker daemon, and" + echo " Amazon EKS related config files and logs. This is the default mode." + echo " enable_debug Enables debug mode for the Docker daemon(Not for production use)" + echo "" + echo " --ignore_introspection To ignore introspection of IPAMD; Pass this flag if DISABLE_INTROSPECTION is enabled on CNI" + echo "" + echo " --ignore_metrics Variable To ignore prometheus metrics collection; Pass this flag if DISABLE_METRICS enabled on CNI" + echo "" + echo " --help Show this help message." + echo "" +} + +parse_options() { + local count="$#" + + for i in $(seq "${count}"); do + eval arg="\$$i" + param="$(echo "${arg}" | awk -F '=' '{print $1}' | sed -e 's|--||')" + val="$(echo "${arg}" | awk -F '=' '{print $2}')" + + case "${param}" in + mode) + eval "${param}"="${val}" + ;; + ignore_introspection) + eval "${param}"="${val}" + ;; + ignore_metrics) + eval "${param}"="${val}" + ;; + help) + help && exit 0 + ;; + *) + echo "Parameter not found: '$param'" + help && exit 1 + ;; + esac + done +} + +ok() { + echo +} + +try() { + local action=$* + echo -n "Trying to $action... " +} + +warning() { + local reason=$* + echo -e "\n\n\tWarning: $reason " +} + +die() { + echo -e "\n\tFatal Error! $* Exiting!\n" + exit 1 +} + +is_root() { + if [[ "$(id -u)" -ne 0 ]]; then + die "This script must be run as root!" + fi +} + +check_required_utils() { + for utils in ${REQUIRED_UTILS[*]}; do + # if exit code of "command -v" not equal to 0, fail + if ! command -v "${utils}" >/dev/null 2>&1; then + die "Application \"${utils}\" is missing, please install \"${utils}\" as this script requires it, and will not function without it." + fi + done +} + +version_output() { + echo -e "\n\tThis is version ${PROGRAM_VERSION}. New versions can be found at ${PROGRAM_SOURCE}\n" +} + +log_parameters() { + echo mode: "${mode}" >> "${COLLECT_DIR}"/system/script-params.txt + echo ignore_introspection: "${ignore_introspection}" >> "${COLLECT_DIR}"/system/script-params.txt + echo ignore_metrics: "${ignore_metrics}" >> "${COLLECT_DIR}"/system/script-params.txt +} + +systemd_check() { + if command -v systemctl >/dev/null 2>&1; then + INIT_TYPE="systemd" + else + INIT_TYPE="other" + fi +} + +create_directories() { + # Make sure the directory the script lives in is there. Not an issue if + # the EKS AMI is used, as it will have it. + mkdir --parents "${PROGRAM_DIR}" + + # Common directors creation + for directory in ${COMMON_DIRECTORIES[*]}; do + mkdir --parents "${COLLECT_DIR}"/"${directory}" + done +} + +get_instance_metadata() { + readonly INSTANCE_ID=$(curl --max-time 3 --silent http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null) + echo "${INSTANCE_ID}" > "${COLLECT_DIR}"/system/instance-id.txt +} + +is_diskfull() { + local threshold + local result + + # 1.5GB in KB + threshold=1500000 + result=$(df / | grep --invert-match "Filesystem" | awk '{ print $4 }') + + # If "result" is less than or equal to "threshold", fail. + if [[ "${result}" -le "${threshold}" ]]; then + die "Free space on root volume is less than or equal to $((threshold>>10))MB, please ensure adequate disk space to collect and store the log files." + fi +} + +cleanup() { + rm --recursive --force "${COLLECT_DIR}" >/dev/null 2>&1 +} + +init() { + check_required_utils + version_output + create_directories + # Log parameters passed when this script is invoked + log_parameters + is_root + systemd_check + get_pkgtype +} + +collect() { + init + is_diskfull + get_instance_metadata + get_common_logs + get_kernel_info + get_mounts_info + get_selinux_info + get_iptables_info + get_pkglist + get_system_services + get_docker_info + get_k8s_info + get_ipamd_info + get_sysctls_info + get_networking_info + get_cni_config + get_docker_logs +} + +enable_debug() { + init + enable_docker_debug +} + +pack() { + try "archive gathered information" + + tar --create --verbose --gzip --file "${PROGRAM_DIR}"/eks_"${INSTANCE_ID}"_"$(date --utc +%Y-%m-%d_%H%M-%Z)"_"${PROGRAM_VERSION}".tar.gz --directory="${COLLECT_DIR}" . > /dev/null 2>&1 + + ok +} + +finished() { + if [[ "${mode}" == "collect" ]]; then + cleanup + echo -e "\n\tDone... your bundled logs are located in ${PROGRAM_DIR}/eks_${INSTANCE_ID}_$(date --utc +%Y-%m-%d_%H%M-%Z)_${PROGRAM_VERSION}.tar.gz\n" + fi +} + +get_mounts_info() { + try "collect mount points and volume information" + mount > "${COLLECT_DIR}"/storage/mounts.txt + echo >> "${COLLECT_DIR}"/storage/mounts.txt + df --human-readable >> "${COLLECT_DIR}"/storage/mounts.txt + lsblk > "${COLLECT_DIR}"/storage/lsblk.txt + lvs > "${COLLECT_DIR}"/storage/lvs.txt + pvs > "${COLLECT_DIR}"/storage/pvs.txt + vgs > "${COLLECT_DIR}"/storage/vgs.txt + + ok +} + +get_selinux_info() { + try "collect SELinux status" + + if ! command -v getenforce >/dev/null 2>&1; then + echo -e "SELinux mode:\n\t Not installed" > "${COLLECT_DIR}"/system/selinux.txt + else + echo -e "SELinux mode:\n\t $(getenforce)" > "${COLLECT_DIR}"/system/selinux.txt + fi + + ok +} + +get_iptables_info() { + try "collect iptables information" + + iptables --wait 1 --numeric --verbose --list --table mangle > "${COLLECT_DIR}"/networking/iptables-mangle.txt + iptables --wait 1 --numeric --verbose --list --table filter > "${COLLECT_DIR}"/networking/iptables-filter.txt + iptables --wait 1 --numeric --verbose --list --table nat > "${COLLECT_DIR}"/networking/iptables-nat.txt + iptables --wait 1 --numeric --verbose --list > "${COLLECT_DIR}"/networking/iptables.txt + iptables-save > "${COLLECT_DIR}"/networking/iptables-save.txt + + ok +} + +get_common_logs() { + try "collect common operating system logs" + + for entry in ${COMMON_LOGS[*]}; do + if [[ -e "/var/log/${entry}" ]]; then + if [[ "${entry}" == "messages" ]]; then + tail -c 10M /var/log/messages > "${COLLECT_DIR}"/var_log/messages + continue + fi + cp --force --recursive --dereference /var/log/"${entry}" "${COLLECT_DIR}"/var_log/ + fi + done + + ok +} + +get_kernel_info() { + try "collect kernel logs" + + if [[ -e "/var/log/dmesg" ]]; then + cp --force /var/log/dmesg "${COLLECT_DIR}/kernel/dmesg.boot" + fi + dmesg > "${COLLECT_DIR}/kernel/dmesg.current" + dmesg --ctime > "${COLLECT_DIR}/kernel/dmesg.human.current" + uname -a > "${COLLECT_DIR}/kernel/uname.txt" + + ok +} + +get_docker_logs() { + try "collect Docker daemon logs" + + case "${INIT_TYPE}" in + systemd) + journalctl --unit=docker --since "${DAYS_10}" > "${COLLECT_DIR}"/docker/docker.log + ;; + other) + for entry in docker upstart/docker; do + if [[ -e "/var/log/${entry}" ]]; then + cp --force --recursive --dereference /var/log/"${entry}" "${COLLECT_DIR}"/docker/ + fi + done + ;; + *) + warning "The current operating system is not supported." + ;; + esac + + ok +} + +get_k8s_info() { + try "collect kubelet information" + + if [[ -n "${KUBECONFIG:-}" ]]; then + command -v kubectl > /dev/null && kubectl get --kubeconfig=${KUBECONFIG} svc > "${COLLECT_DIR}"/kubelet/svc.log + kubectl --kubeconfig=${KUBECONFIG} config view --output yaml > "${COLLECT_DIR}"/kubelet/kubeconfig.yaml + + elif [[ -f /etc/eksctl/kubeconfig.yaml ]]; then + KUBECONFIG="/etc/eksctl/kubeconfig.yaml" + command -v kubectl > /dev/null && kubectl get --kubeconfig=${KUBECONFIG} svc > "${COLLECT_DIR}"/kubelet/svc.log + kubectl --kubeconfig=${KUBECONFIG} config view --output yaml > "${COLLECT_DIR}"/kubelet/kubeconfig.yaml + + elif [[ -f /etc/systemd/system/kubelet.service ]]; then + KUBECONFIG=`grep kubeconfig /etc/systemd/system/kubelet.service | awk '{print $2}'` + command -v kubectl > /dev/null && kubectl get --kubeconfig=${KUBECONFIG} svc > "${COLLECT_DIR}"/kubelet/svc.log + kubectl --kubeconfig=${KUBECONFIG} config view --output yaml > "${COLLECT_DIR}"/kubelet/kubeconfig.yaml + + else + echo "======== Unable to find KUBECONFIG, IGNORING POD DATA =========" >> "${COLLECT_DIR}"/kubelet/svc.log + fi + + case "${INIT_TYPE}" in + systemd) + timeout 75 journalctl --unit=kubelet --since "${DAYS_10}" > "${COLLECT_DIR}"/kubelet/kubelet.log + timeout 75 journalctl --unit=kubeproxy --since "${DAYS_10}" > "${COLLECT_DIR}"/kubelet/kubeproxy.log + + for entry in kubelet kube-proxy; do + systemctl cat "${entry}" > "${COLLECT_DIR}"/kubelet/"${entry}"_service.txt 2>&1 + done + ;; + *) + warning "The current operating system is not supported." + ;; + esac + + ok +} + +get_ipamd_info() { + if [[ "${ignore_introspection}" == "false" ]]; then + try "collect L-IPAMD introspectioon information" + for entry in ${IPAMD_DATA[*]}; do + curl --max-time 3 --silent http://localhost:61679/v1/"${entry}" >> "${COLLECT_DIR}"/ipamd/"${entry}".txt + done + else + echo "Ignoring IPAM introspection stats as mentioned"| tee -a "${COLLECT_DIR}"/ipamd/ipam_introspection_ignore.txt + + fi + + if [[ "${ignore_metrics}" == "false" ]]; then + try "collect L-IPAMD prometheus metrics" + curl --max-time 3 --silent http://localhost:61678/metrics > "${COLLECT_DIR}"/ipamd/metrics.txt 2>&1 + else + echo "Ignoring Prometheus Metrics collection as mentioned"| tee -a "${COLLECT_DIR}"/ipamd/ipam_metrics_ignore.txt + fi + + ok +} + +get_sysctls_info() { + try "collect sysctls information" + # dump all sysctls + sysctl --all >> "${COLLECT_DIR}"/sysctls/sysctl_all.txt 2>/dev/null + + ok +} + +get_networking_info() { + try "collect networking infomation" + + # ifconfig + timeout 75 ifconfig > "${COLLECT_DIR}"/networking/ifconfig.txt + + # ip rule show + timeout 75 ip rule show > "${COLLECT_DIR}"/networking/iprule.txt + timeout 75 ip route show table all >> "${COLLECT_DIR}"/networking/iproute.txt + + ok +} + +get_cni_config() { + try "collect CNI configuration information" + + if [[ -e "/etc/cni/net.d/" ]]; then + cp --force --recursive --dereference /etc/cni/net.d/* "${COLLECT_DIR}"/cni/ + fi + + ok +} + +get_pkgtype() { + if [[ "$(command -v rpm )" ]]; then + PACKAGE_TYPE=rpm + elif [[ "$(command -v deb )" ]]; then + PACKAGE_TYPE=deb + else + PACKAGE_TYPE='unknown' + fi +} + +get_pkglist() { + try "collect installed packages" + + case "${PACKAGE_TYPE}" in + rpm) + rpm -qa > "${COLLECT_DIR}"/system/pkglist.txt 2>&1 + ;; + deb) + dpkg --list > "${COLLECT_DIR}"/system/pkglist.txt 2>&1 + ;; + *) + warning "Unknown package type." + ;; + esac + + ok +} + +get_system_services() { + try "collect active system services" + + case "${INIT_TYPE}" in + systemd) + systemctl list-units > "${COLLECT_DIR}"/system/services.txt 2>&1 + ;; + other) + initctl list | awk '{ print $1 }' | xargs -n1 initctl show-config > "${COLLECT_DIR}"/system/services.txt 2>&1 + printf "\n\n\n\n" >> "${COLLECT_DIR}"/system/services.txt 2>&1 + service --status-all >> "${COLLECT_DIR}"/system/services.txt 2>&1 + ;; + *) + warning "Unable to determine active services." + ;; + esac + + timeout 75 top -b -n 1 > "${COLLECT_DIR}"/system/top.txt 2>&1 + timeout 75 ps fauxwww > "${COLLECT_DIR}"/system/ps.txt 2>&1 + timeout 75 netstat -plant > "${COLLECT_DIR}"/system/netstat.txt 2>&1 + + ok +} + +get_docker_info() { + try "collect Docker daemon information" + + if [[ "$(pgrep dockerd)" -ne 0 ]]; then + timeout 75 docker info > "${COLLECT_DIR}"/docker/docker-info.txt 2>&1 || echo -e "\tTimed out, ignoring \"docker info output \" " + timeout 75 docker ps --all --no-trunc > "${COLLECT_DIR}"/docker/docker-ps.txt 2>&1 || echo -e "\tTimed out, ignoring \"docker ps --all --no-truc output \" " + timeout 75 docker images > "${COLLECT_DIR}"/docker/docker-images.txt 2>&1 || echo -e "\tTimed out, ignoring \"docker images output \" " + timeout 75 docker version > "${COLLECT_DIR}"/docker/docker-version.txt 2>&1 || echo -e "\tTimed out, ignoring \"docker version output \" " + else + warning "The Docker daemon is not running." + fi + + ok +} + +enable_docker_debug() { + try "enable debug mode for the Docker daemon" + + case "${PACKAGE_TYPE}" in + rpm) + + if [[ -e /etc/sysconfig/docker ]] && grep -q "^\s*OPTIONS=\"-D" /etc/sysconfig/docker + then + echo "Debug mode is already enabled." + ok + else + if [[ -e /etc/sysconfig/docker ]]; then + echo "OPTIONS=\"-D \$OPTIONS\"" >> /etc/sysconfig/docker + + try "restart Docker daemon to enable debug mode" + service docker restart + ok + fi + fi + ;; + *) + warning "The current operating system is not supported." + + ok + ;; + esac +} + +confirm_enable_docker_debug() { + read -r -p "${1:-Enabled Docker Debug will restart the Docker Daemon and restart all running container. Are you sure? [y/N]} " USER_INPUT + case "$USER_INPUT" in + [yY][eE][sS]|[yY]) + enable_docker_debug + ;; + *) + die "\"No\" was selected." + ;; + esac +} + +parse_options "$@" + +case "${mode}" in + collect) + collect + pack + finished + ;; + enable_debug) + confirm_enable_docker_debug + finished + ;; + *) + help && exit 1 + ;; +esac diff --git a/log-collector-script/eks-ssm-content.json b/log-collector-script/eks-ssm-content.json new file mode 100644 index 000000000..8c237a30f --- /dev/null +++ b/log-collector-script/eks-ssm-content.json @@ -0,0 +1,44 @@ +{ + "schemaVersion":"2.2", + "description":"EKS Log Collector", + "parameters":{ + "bucketName":{ + "type": "String", + "default": "Enabled" + } + }, + "mainSteps":[ + { + "action":"aws:runShellScript", + "name":"PatchLinux", + "precondition":{ + "StringEquals":[ + "platformType", + "Linux" + ] + }, + "inputs":{ + "runCommand":[ + "curl -O https://raw.githubusercontent.com/awslabs/amazon-eks-ami/master/log-collector-script/eks-log-collector.sh", + "bash ./eks-log-collector.sh >/dev/null 2>&1", + "echo \"EKS logs collected\"", + "if [ -f /usr/local/bin/aws ]; then", + "echo \"AWS_already_installed\"", + "else", + "echo \"Installing AWSCLI\"", + "curl \"https://s3.amazonaws.com/aws-cli/awscli-bundle.zip\" -o \"awscli-bundle.zip\" >/dev/null 2>&1", + "yum install unzip -y >/dev/null 2>&1", + "unzip awscli-bundle.zip >/dev/null 2>&1", + "./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws", + "echo \"AWSCLI version is\"", + "/usr/local/bin/aws --version", + "fi", + "echo \"Pushing to S3\"", + "/usr/local/bin/aws s3 cp --recursive /opt/log-collector/ s3://{{bucketName}}", + "echo \"Logs uploaded to S3\"" + ] + } + } + ] +} +