diff --git a/ui/Dockerfile b/ui/Dockerfile index 30c2d77fa..25a0f089d 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -1,53 +1,22 @@ -ARG BASE_IMAGE=registry.opensource.zalan.do/library/alpine-3.15:latest -ARG NODE_IMAGE=node:14.21.2-alpine - -FROM $NODE_IMAGE AS build - -COPY . /workdir -WORKDIR /workdir/app - -RUN npm install &&\ - npm run build - -FROM $BASE_IMAGE - +FROM registry.opensource.zalan.do/library/python-3.11-slim:latest LABEL maintainer="Team ACID @ Zalando " EXPOSE 8081 +WORKDIR /app -RUN \ - apk add --no-cache \ - alpine-sdk \ - autoconf \ - automake \ - ca-certificates \ - libffi-dev \ - libtool \ - python3 \ - python3-dev \ - zlib-dev \ - && \ - python3 -m ensurepip && \ - rm -r /usr/lib/python*/ensurepip && \ - pip3 install --upgrade \ - gevent \ - jq \ - pip \ - setuptools \ - && \ - rm -rf \ - /root/.cache \ - /tmp/* \ - /var/cache/apk/* +RUN apt-get -qq -y update \ + # https://www.psycopg.org/docs/install.html#psycopg-vs-psycopg-binary + && apt-get -qq -y install --no-install-recommends g++ libpq-dev python3-dev python3-distutils \ + && apt-get -qq -y clean \ + && rm -rf /var/lib/apt/lists/* -COPY requirements.txt / -COPY start_server.sh / -RUN pip3 install -r /requirements.txt +COPY requirements.txt . +COPY start_server.sh . +RUN pip install -r requirements.txt + +COPY operator_ui operator_ui/ -COPY operator_ui /operator_ui -COPY --from=build /workdir/operator_ui/static/build /operator_ui/static/build ARG VERSION=dev -RUN sed -i "s/__version__ = .*/__version__ = '${VERSION}'/" /operator_ui/__init__.py +RUN sed -i "s/__version__ = .*/__version__ = '${VERSION}'/" operator_ui/__init__.py -WORKDIR / -CMD ["/usr/bin/python3", "-m", "operator_ui"] +CMD ["python", "-m", "operator_ui"] diff --git a/ui/app/src/postgresql.tag.pug b/ui/app/src/postgresql.tag.pug index 960c3bd07..7f91ff525 100644 --- a/ui/app/src/postgresql.tag.pug +++ b/ui/app/src/postgresql.tag.pug @@ -87,9 +87,6 @@ postgresql .alert.alert-info(if='{ progress.statefulSet && !progress.containerFirst }') Waiting for 1st container to spawn .alert.alert-success(if='{ progress.containerFirst }') First PostgreSQL cluster container spawned - .alert.alert-info(if='{ !progress.postgresql }') PostgreSQL cluster manifest pending - .alert.alert-success(if='{ progress.postgresql }') PostgreSQL cluster manifest created - .alert.alert-info(if='{ progress.containerFirst && !progress.masterLabel }') Waiting for master to become available .alert.alert-success(if='{ progress.masterLabel }') PostgreSQL master available, label is attached .alert.alert-success(if='{ progress.masterLabel && progress.dnsName }') PostgreSQL ready: { progress.dnsName } diff --git a/ui/operator_ui/adapters/__init__ .py b/ui/operator_ui/adapters/__init__ .py new file mode 100644 index 000000000..e69de29bb diff --git a/ui/operator_ui/adapters/logger.py b/ui/operator_ui/adapters/logger.py new file mode 100644 index 000000000..fb1ccdf49 --- /dev/null +++ b/ui/operator_ui/adapters/logger.py @@ -0,0 +1,46 @@ +import logging +from logging.config import dictConfig + +dictConfig( + { + "version": 1, + "disable_existing_loggers": True, + "formatters": { + "json": { + "class": "pythonjsonlogger.jsonlogger.JsonFormatter", + "format": "%(asctime)s %(levelname)s: %(message)s", + } + }, + "handlers": { + "stream_handler": { + "class": "logging.StreamHandler", + "formatter": "json", + "stream": "ext://flask.logging.wsgi_errors_stream", + } + }, + "root": { + "level": "INFO", + "handlers": ["stream_handler"] + } + } +) + + +class Logger: + def __init__(self): + self.logger = logging.getLogger(__name__) + + def debug(self, msg: str, *args, **kwargs): + self.logger.debug(msg, *args, **kwargs) + + def info(self, msg: str, *args, **kwargs): + self.logger.info(msg, *args, **kwargs) + + def error(self, msg: str, *args, **kwargs): + self.logger.error(msg, *args, **kwargs) + + def exception(self, msg: str, *args, **kwargs): + self.logger.exception(msg, *args, **kwargs) + + +logger = Logger() diff --git a/ui/operator_ui/main.py b/ui/operator_ui/main.py index ec33d6776..eb77418c8 100644 --- a/ui/operator_ui/main.py +++ b/ui/operator_ui/main.py @@ -1,13 +1,8 @@ #!/usr/bin/env python3 # pylama:ignore=E402 -import gevent.monkey - -gevent.monkey.patch_all() - import requests import tokens -import sys from backoff import expo, on_exception from click import ParamType, command, echo, option @@ -25,7 +20,6 @@ from gevent import sleep, spawn from gevent.pywsgi import WSGIServer from jq import jq from json import dumps, loads -from logging import DEBUG, ERROR, INFO, basicConfig, exception, getLogger from os import getenv from re import X, compile from requests.exceptions import RequestException @@ -56,11 +50,7 @@ from .utils import ( these, ) - -# Disable access logs from Flask -getLogger('gevent').setLevel(ERROR) - -logger = getLogger(__name__) +from operator_ui.adapters.logger import logger SERVER_STATUS = {'shutdown': False} @@ -77,7 +67,7 @@ SPILO_S3_BACKUP_PREFIX = getenv('SPILO_S3_BACKUP_PREFIX', 'spilo/') SUPERUSER_TEAM = getenv('SUPERUSER_TEAM', 'acid') TARGET_NAMESPACE = getenv('TARGET_NAMESPACE') GOOGLE_ANALYTICS = getenv('GOOGLE_ANALYTICS', False) -MIN_PODS= getenv('MIN_PODS', 2) +MIN_PODS = getenv('MIN_PODS', 2) RESOURCES_VISIBLE = getenv('RESOURCES_VISIBLE', True) CUSTOM_MESSAGE_RED = getenv('CUSTOM_MESSAGE_RED', '') @@ -984,8 +974,6 @@ def init_cluster(): def main(port, debug, clusters: list): global TARGET_NAMESPACE - basicConfig(stream=sys.stdout, level=(DEBUG if debug else INFO), format='%(asctime)s %(levelname)s: %(message)s',) - init_cluster() logger.info(f'App URL: {APP_URL}') diff --git a/ui/operator_ui/spiloutils.py b/ui/operator_ui/spiloutils.py index 8126e07f3..dd2d938df 100644 --- a/ui/operator_ui/spiloutils.py +++ b/ui/operator_ui/spiloutils.py @@ -2,7 +2,6 @@ from boto3 import client from datetime import datetime, timezone from furl import furl from json import dumps, loads -from logging import getLogger from os import environ, getenv from requests import Session from urllib.parse import urljoin @@ -11,8 +10,7 @@ from wal_e.cmd import configure_backup_cxt from .utils import Attrs, defaulting, these - -logger = getLogger(__name__) +from operator_ui.adapters.logger import logger session = Session() diff --git a/ui/requirements.txt b/ui/requirements.txt index 97d1467c6..edd649d2a 100644 --- a/ui/requirements.txt +++ b/ui/requirements.txt @@ -8,6 +8,7 @@ gevent==24.2.1 jq==1.7.0 json_delta>=2.0.2 kubernetes==11.0.0 +python-json-logger==2.0.7 requests==2.32.2 stups-tokens>=1.1.19 wal_e==1.1.1