From d7402d351595ffd1c6a4de4840a97fb77ce4ff90 Mon Sep 17 00:00:00 2001
From: Adar Nimrod <nimrod@shore.co.il>
Date: Sun, 18 Aug 2019 20:08:15 +0300
Subject: [PATCH] Most of it, if not all of it.

---
 .dockerignore           |  5 +++++
 .gitignore              | 49 +++++++++++++++++++++++++++++++++++++++++
 .pre-commit-config.yaml | 41 ++++++++++++++++++++++++++++++++++
 Dockerfile              | 19 ++++++++++++++++
 LICENSE.txt             | 21 ++++++++++++++++++
 README.md               | 35 +++++++++++++++++++++++++++++
 awslogs.conf            |  7 ++++++
 config                  |  2 ++
 deduce-aws-region       | 10 +++++++++
 entrypoint              |  9 ++++++++
 10 files changed, 198 insertions(+)
 create mode 100644 .dockerignore
 create mode 100644 .gitignore
 create mode 100644 .pre-commit-config.yaml
 create mode 100644 Dockerfile
 create mode 100644 LICENSE.txt
 create mode 100644 README.md
 create mode 100644 awslogs.conf
 create mode 100644 config
 create mode 100755 deduce-aws-region
 create mode 100755 entrypoint

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..e407a3a
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+*
+!awslogs.conf
+!config
+!deduce-aws-region
+!entrypoint
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3e66e1d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,49 @@
+~*
+*~
+*.sw[op]
+*.py[cod]
+.DS_Store
+__pycache__/
+.vagrant/
+vendor/
+Thumbs.db
+*.retry
+.svn/
+.sass-cache/
+*.log
+*.out
+*.so
+node_modules/
+.npm/
+nbproject/
+*.ipynb
+.idea/
+*.egg-info/
+*.[ao]
+.classpath
+.cache/
+bower_components/
+*.class
+*.[ewj]ar
+secring.*
+.*.kate-swp
+.swp.*
+.directory
+.Trash-*
+build/
+_build/
+dist/
+.tox/
+*.pdf
+*.exe
+*.dll
+*.gz
+*.tgz
+*.tar
+*.rar
+*.zip
+*.pid
+*.lock
+*.env
+.bundle/
+!Pipfile.lock
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..a665d28
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,41 @@
+# vim:ff=unix ts=2 sw=2 ai expandtab
+---
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v2.3.0
+    hooks:
+      - id: check-added-large-files
+      - id: check-executables-have-shebangs
+      - id: check-merge-conflict
+      - id: detect-private-key
+      - id: trailing-whitespace
+  - repo: https://github.com/adrienverge/yamllint
+    rev: v1.17.0
+    hooks:
+      - id: yamllint
+  - repo: https://github.com/amperser/proselint
+    rev: 0.10.1
+    hooks:
+      - id: proselint
+        types: [plain-text]
+        exclude: LICENSE
+  - repo: https://www.shore.co.il/git/docker-pre-commit
+    rev: v0.3.0
+    hooks:
+      - id: hadolint
+  - repo: https://github.com/ambv/black
+    rev: 19.3b0
+    hooks:
+      - id: black
+        args:
+          - |
+              --line-length=79
+  - repo: https://gitlab.com/pycqa/flake8
+    rev: 3.7.8
+    hooks:
+      - id: flake8
+        args:
+          - |-
+            --max-line-length=79
+        additional_dependencies:
+          - flake8-bugbear
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..0ae82fa
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,19 @@
+FROM python:3.7-alpine3.10
+# hadolint ignore=DL3013
+RUN pip install --no-cache-dir --progress-bar=off \
+        awscli-cwlogs \
+        template \
+    && \
+    install -d -o nobody -g root -m 755 /var/awslogs/etc/
+COPY --chown=root:root config /etc/aws/
+COPY --chown=root:root entrypoint /usr/local/bin/
+COPY --chown=root:root awslogs.conf /var/awslogs/etc/awslogs.conf.j2
+COPY --chown=root:root deduce-aws-region /usr/local/bin/
+USER nobody
+ENV AWS_CONFIG_FILE="/etc/aws/config" \
+    LOG_GROUP_NAME="" \
+    LOG_STREAM_NAME="" \
+    LOG_FILE=""
+ENTRYPOINT ["entrypoint"]
+CMD ["aws", "logs", "push", "--config-file", "/tmp/config"]
+HEALTHCHECK CMD pgrep python || exit 1
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..17196c5
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Adar Nimrod
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3686992
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+# AWS ClougWatch Agent
+
+Send files to CloudWatch logs.
+
+## Usage
+
+Run with the directory of the log file mounted inside the container and
+specifying the `LOG_GROUP_NAME`, `LOG_STREAM_NAME` and `LOG_FILE` environment
+variables. Also, the usual [AWS CLI environment
+variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)
+can also be specified. Lastly, the AWS region is deduced on startup by accessing
+the [instance
+metadata](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-retrieval),
+unless the `AWS_DEFAULT_REGION` enviroment variable is specified. By default the
+container uses the `nobody` user, but you may need to specify a different user
+in case the log file is not readable but that user. For [file rotation
+detection](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html#agent-faq),
+don't mount just the file but the whole directory inside the container.
+
+## Example usage
+
+```
+docker run -d -v '/var/log:/var/log:ro' -e 'LOG_GROUP_NAME=/var/log/' -e 'LOG_STREAM_NAME={instance_id}' -e 'LOG_FILE=/var/log/ecs/ecs-agent.log.*' adarnimrod/cw-logs
+```
+
+## License
+
+This software is licensed under the MIT license (see `LICENSE.txt`).
+
+## Author Information
+
+Nimrod Adar, [contact me](mailto:nimrod@shore.co.il) or visit my [website](
+https://www.shore.co.il/). Patches are welcome via [`git send-email`](
+http://git-scm.com/book/en/v2/Git-Commands-Email). The repository is located
+at: <https://www.shore.co.il/git/>.
diff --git a/awslogs.conf b/awslogs.conf
new file mode 100644
index 0000000..12eedc8
--- /dev/null
+++ b/awslogs.conf
@@ -0,0 +1,7 @@
+[general]
+state_file = /tmp/push-state
+
+[LOG_FILE]
+file = {{ LOG_FILE }}
+log_group_name = {{ LOG_GROUP_NAME }}
+log_stream_name = {{ LOG_STREAM_NAME }}
diff --git a/config b/config
new file mode 100644
index 0000000..66019b4
--- /dev/null
+++ b/config
@@ -0,0 +1,2 @@
+[plugins]
+cwlogs = cwlogs
diff --git a/deduce-aws-region b/deduce-aws-region
new file mode 100755
index 0000000..75d45c3
--- /dev/null
+++ b/deduce-aws-region
@@ -0,0 +1,10 @@
+#!/usr/bin/env python3
+
+from urllib.request import urlopen
+import json
+
+if __name__ == "__main__":
+    response = urlopen(
+        "http://169.254.169.254/latest/dynamic/instance-identity/document"
+    )
+    print(json.loads(response.read().decode("utf-8"))["region"])
diff --git a/entrypoint b/entrypoint
new file mode 100755
index 0000000..86da6d3
--- /dev/null
+++ b/entrypoint
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -eux
+template /var/awslogs/etc/awslogs.conf.j2 > /tmp/config
+if [ -z "${AWS_DEFAULT_REGION:-}" ]
+then
+    AWS_DEFAULT_REGION="$(deduce-aws-region)"
+    export AWS_DEFAULT_REGION
+fi
+eval exec "$@"
-- 
GitLab