Browse Source

command-line options fallback to env vars; added dockerfile; rename script

Fabian Peter Hammerle 3 years ago
parent
commit
9e1153dd69
4 changed files with 108 additions and 5 deletions
  1. 4 0
      .dockerignore
  2. 51 0
      Dockerfile
  3. 27 0
      Makefile
  4. 26 5
      location_guessing_game_telegram_bot.py

+ 4 - 0
.dockerignore

@@ -0,0 +1,4 @@
+*
+!Pipfile
+!Pipfile.lock
+!location_guessing_telegram_bot.py

+ 51 - 0
Dockerfile

@@ -0,0 +1,51 @@
+ARG BASE_IMAGE=docker.io/python:3.8.7-slim-buster
+ARG SOURCE_DIR_PATH=/location-guessing-game-telegram-bot
+
+
+# hadolint ignore=DL3006
+FROM $BASE_IMAGE as build
+
+RUN apt-get update \
+    && apt-get install --no-install-recommends --yes ca-certificates \
+    && rm -rf /var/lib/apt/lists/* \
+    && useradd --create-home build
+
+USER build
+RUN pip install --user --no-cache-dir pipenv==2020.11.15
+
+ARG SOURCE_DIR_PATH
+COPY --chown=build Pipfile Pipfile.lock $SOURCE_DIR_PATH/
+WORKDIR $SOURCE_DIR_PATH
+ENV PIPENV_CACHE_DIR=/tmp/pipenv-cache \
+    PIPENV_VENV_IN_PROJECT=yes-please \
+    PATH=/home/build/.local/bin:$PATH
+RUN pipenv install --deploy \
+    && pipenv graph \
+    && pipenv run pip freeze \
+    && rm -rf $PIPENV_CACHE_DIR
+COPY --chown=build . $SOURCE_DIR_PATH
+RUN chmod -cR a+rX .
+
+# workaround for broken multi-stage copy
+# > failed to copy files: failed to copy directory: Error processing tar file(exit status 1): Container ID ... cannot be mapped to a host ID
+USER 0
+RUN chown -R 0:0 $SOURCE_DIR_PATH
+USER build
+
+
+# hadolint ignore=DL3006
+FROM $BASE_IMAGE
+
+RUN apt-get update \
+    && apt-get install --no-install-recommends --yes ca-certificates \
+    && rm -rf /var/lib/apt/lists/* \
+    && find / -xdev -type f -perm /u+s -exec chmod -c u-s {} \; \
+    && find / -xdev -type f -perm /g+s -exec chmod -c g-s {} \;
+
+USER nobody
+
+ARG SOURCE_DIR_PATH
+COPY --from=build $SOURCE_DIR_PATH $SOURCE_DIR_PATH
+ENV PATH=$SOURCE_DIR_PATH/.venv/bin:$PATH
+WORKDIR $SOURCE_DIR_PATH
+CMD ["python", "location_guessing_game_telegram_bot.py"]

+ 27 - 0
Makefile

@@ -0,0 +1,27 @@
+# sync with https://github.com/fphammerle/switchbot-mqtt/blob/master/Makefile
+
+IMAGE_NAME = docker.io/fphammerle/location-guessing-game-telegram-bot
+PROJECT_VERSION = $(shell git describe --match=v* --always --dirty | sed -e 's/^v//')
+ARCH = $(shell arch)
+# architecture[arm_variant]
+# https://github.com/opencontainers/image-spec/blob/v1.0.1/image-index.md#image-index-property-descriptions
+IMAGE_TAG_ARCH_aarch64 = arm64
+IMAGE_TAG_ARCH_armv6l = armv6
+IMAGE_TAG_ARCH_armv7l = armv7
+IMAGE_TAG_ARCH_x86_64 = amd64
+IMAGE_TAG_ARCH = ${IMAGE_TAG_ARCH_${ARCH}}
+IMAGE_TAG = ${PROJECT_VERSION}-${IMAGE_TAG_ARCH}
+
+.PHONY: docker-build podman-build docker-push
+
+docker-build:
+	sudo docker build --tag="${IMAGE_NAME}:${IMAGE_TAG}" .
+
+podman-build:
+	# --format=oci (default) not fully supported by hub.docker.com
+	# https://github.com/docker/hub-feedback/issues/1871#issuecomment-748924149
+	podman build --format=docker --tag="${IMAGE_NAME}:${IMAGE_TAG}" .
+
+docker-push: docker-build
+	sudo docker push "${IMAGE_NAME}:${IMAGE_TAG}"
+	@echo git tag --sign --message '$(shell sudo docker image inspect --format '{{join .RepoDigests "\n"}}' "${IMAGE_NAME}:${IMAGE_TAG}")' docker/${IMAGE_TAG} $(shell git rev-parse HEAD)

+ 26 - 5
test.py → location_guessing_game_telegram_bot.py

@@ -1,9 +1,9 @@
 #!/usr/bin/env python3
 
 import argparse
-import io
 import json
 import logging
+import os
 import pathlib
 import random
 import typing
@@ -65,6 +65,7 @@ def _photo_command(
     )
     while True:
         photo = random.choice(context.bot_data["photos"])
+        _LOGGER.info("sending %s", photo)
         try:
             with urllib.request.urlopen(photo.photo_url) as photo_response:
                 photo_message = update.effective_chat.send_photo(
@@ -120,19 +121,39 @@ class _Persistence(telegram.ext.BasePersistence):
         pass
 
 
+# https://git.hammerle.me/fphammerle/pyftpd-sink/src/5daf383bc238425cd37d011959a8eeffab0112c3/pyftpd-sink#L48
+class _EnvDefaultArgparser(argparse.ArgumentParser):
+    def add_argument(self, *args, envvar=None, **kwargs):
+        # pylint: disable=arguments-differ; using *args & **kwargs to catch all
+        if envvar:
+            envvar_value = os.environ.get(envvar, None)
+            if envvar_value:
+                kwargs["required"] = False
+                kwargs["default"] = envvar_value
+        super().add_argument(*args, **kwargs)
+
+
 def _main():
     logging.basicConfig(
         level=logging.DEBUG,
         format="%(asctime)s:%(levelname)s:%(name)s:%(funcName)s:%(message)s",
         datefmt="%Y-%m-%dT%H:%M:%S%z",
     )
-    argparser = argparse.ArgumentParser()
-    argparser.add_argument("--token-path", type=pathlib.Path, required=True)
+    argparser = _EnvDefaultArgparser()
+    argparser.add_argument(
+        "--telegram-token-path",
+        type=pathlib.Path,
+        required=True,
+        envvar="TELEGRAM_TOKEN_PATH",
+        help="default: env var TELEGRAM_TOKEN_PATH",
+    )
     argparser.add_argument(
         "--wikimap-export-path",
         type=pathlib.Path,
         required=True,
-        help="https://wikimap.toolforge.org/api.php?[...] json",
+        envvar="WIKIMAP_EXPORT_PATH",
+        help="https://wikimap.toolforge.org/api.php?[...] json, "
+        "default: env var WIKIMAP_EXPORT_PATH",
     )
     args = argparser.parse_args()
     _LOGGER.debug("args=%r", args)
@@ -141,7 +162,7 @@ def _main():
         for attrs in json.loads(args.wikimap_export_path.read_text())
     ]
     updater = telegram.ext.Updater(
-        token=args.token_path.read_text().rstrip(),
+        token=args.telegram_token_path.read_text().rstrip(),
         use_context=True,
         persistence=_Persistence(photos=photos),
     )