From 55d0d1a105f4bc290396c26f394cadade1c59a4f Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Thu, 22 Jan 2026 20:14:22 -0500 Subject: [PATCH] Modernizing PyThon Projec --- .github/workflows/build.yml | 13 ++-- .gitignore | 10 +++ .python-version | 1 + Makefile | 14 +++- README.md | 41 ++++++++++ build/Dockerfile | 12 ++- pyproject.toml | 77 +++++++++++++++++++ setup.py | 20 ----- src/pytest.ini | 2 - src/requirements.txt | 9 --- src/tests/context.py | 5 -- {src/tests => tests}/__init__.py | 0 {src/tests => tests}/expected/docker.txt | 0 {src/tests => tests}/expected/no-services.txt | 0 .../expected/services-fcgi.txt | 0 .../expected/services-letsencrypt.txt | 0 .../expected/services-multi-containers.txt | 0 .../expected/services-multiple-hosts.txt | 0 .../expected/services-redirect-ssl.txt | 0 .../tests => tests}/expected/services-tcp.txt | 0 {src/tests => tests}/expected/services.txt | 0 {src/tests => tests}/expected/ssl-loose.txt | 0 {src/tests => tests}/expected/ssl-strict.txt | 0 {src/tests => tests}/expected/static.txt | 0 {src/tests => tests}/fixtures/00_haproxy.cfg | 0 {src/tests => tests}/fixtures/10_haproxy.cfg | 0 {src/tests => tests}/fixtures/no-services | 0 {src/tests => tests}/fixtures/run_bash.sh | 0 {src/tests => tests}/fixtures/services | 0 .../fixtures/services-changed-label | 0 .../fixtures/services-clone-to-ssl | 0 {src/tests => tests}/fixtures/services-fcgi | 0 .../fixtures/services-letsencrypt | 0 .../fixtures/services-multi-containers | 0 .../fixtures/services-multiple-hosts | 0 .../fixtures/services-redirect-ssl | 0 {src/tests => tests}/fixtures/services-tcp | 0 .../fixtures/services-with-cloudflare | 0 .../fixtures/services-with-deny-pages | 0 .../fixtures/services-with-ip-whitelist | 0 .../fixtures/services-with-jwt-validator | 0 .../fixtures/services-with-multiple-plugins | 0 {src/tests => tests}/fixtures/static.yml | 0 {src/tests => tests}/test_containerenv.py | 0 {src/tests => tests}/test_daemonize.py | 0 {src/tests => tests}/test_docker.py | 0 {src/tests => tests}/test_functions.py | 0 {src/tests => tests}/test_labels.py | 0 {src/tests => tests}/test_parser.py | 0 {src/tests => tests}/test_plugins.py | 0 {src/tests => tests}/test_static.py | 0 51 files changed, 157 insertions(+), 47 deletions(-) create mode 100644 .python-version create mode 100644 pyproject.toml delete mode 100644 setup.py delete mode 100644 src/pytest.ini delete mode 100644 src/requirements.txt delete mode 100644 src/tests/context.py rename {src/tests => tests}/__init__.py (100%) rename {src/tests => tests}/expected/docker.txt (100%) rename {src/tests => tests}/expected/no-services.txt (100%) rename {src/tests => tests}/expected/services-fcgi.txt (100%) rename {src/tests => tests}/expected/services-letsencrypt.txt (100%) rename {src/tests => tests}/expected/services-multi-containers.txt (100%) rename {src/tests => tests}/expected/services-multiple-hosts.txt (100%) rename {src/tests => tests}/expected/services-redirect-ssl.txt (100%) rename {src/tests => tests}/expected/services-tcp.txt (100%) rename {src/tests => tests}/expected/services.txt (100%) rename {src/tests => tests}/expected/ssl-loose.txt (100%) rename {src/tests => tests}/expected/ssl-strict.txt (100%) rename {src/tests => tests}/expected/static.txt (100%) rename {src/tests => tests}/fixtures/00_haproxy.cfg (100%) rename {src/tests => tests}/fixtures/10_haproxy.cfg (100%) rename {src/tests => tests}/fixtures/no-services (100%) rename {src/tests => tests}/fixtures/run_bash.sh (100%) rename {src/tests => tests}/fixtures/services (100%) rename {src/tests => tests}/fixtures/services-changed-label (100%) rename {src/tests => tests}/fixtures/services-clone-to-ssl (100%) rename {src/tests => tests}/fixtures/services-fcgi (100%) rename {src/tests => tests}/fixtures/services-letsencrypt (100%) rename {src/tests => tests}/fixtures/services-multi-containers (100%) rename {src/tests => tests}/fixtures/services-multiple-hosts (100%) rename {src/tests => tests}/fixtures/services-redirect-ssl (100%) rename {src/tests => tests}/fixtures/services-tcp (100%) rename {src/tests => tests}/fixtures/services-with-cloudflare (100%) rename {src/tests => tests}/fixtures/services-with-deny-pages (100%) rename {src/tests => tests}/fixtures/services-with-ip-whitelist (100%) rename {src/tests => tests}/fixtures/services-with-jwt-validator (100%) rename {src/tests => tests}/fixtures/services-with-multiple-plugins (100%) rename {src/tests => tests}/fixtures/static.yml (100%) rename {src/tests => tests}/test_containerenv.py (100%) rename {src/tests => tests}/test_daemonize.py (100%) rename {src/tests => tests}/test_docker.py (100%) rename {src/tests => tests}/test_functions.py (100%) rename {src/tests => tests}/test_labels.py (100%) rename {src/tests => tests}/test_parser.py (100%) rename {src/tests => tests}/test_plugins.py (100%) rename {src/tests => tests}/test_static.py (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index efd19ea..51ee99d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,15 +26,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Install requirements + - name: Install uv + run: curl -LsSf https://astral.sh/uv/install.sh | sh + + - name: Install dependencies run: | - cd src/ - pip install -r requirements.txt + export PATH="$HOME/.local/bin:$PATH" + uv pip install --system -e ".[dev]" - name: Run tests - run: | - cd src/ - pytest -s tests/ -vv + run: pytest -s tests/ -vv Build: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index a32f7e6..1f28c18 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,16 @@ __pycache__ .pytest_cache *.pyc .env + +# uv +uv.lock +.venv/ + +# Build artifacts +dist/ +build/ +*.egg-info/ + /examples/static/conf/config.yml /examples/docker/certs/haproxy/.place_holder_cert.pem /examples/static/host1.local.pem diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/Makefile b/Makefile index 4c9c278..f8ee00a 100644 --- a/Makefile +++ b/Makefile @@ -6,4 +6,16 @@ build: .PHONY: test test: - cd src/ && pytest tests/ -vv + uv run pytest tests/ -vv + +.PHONY: sync +sync: + uv sync --dev + +.PHONY: lint +lint: + uv run ruff check src/ tests/ + +.PHONY: format +format: + uv run ruff format src/ tests/ diff --git a/README.md b/README.md index a9c3e34..cb8d033 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,47 @@ Detailed configuration guides for advanced setups: - [Other Configurations](docs/other.md) - Additional configurations (ports, custom errors, etc.) - [Limitations](docs/limitations.md) - Important limitations and considerations +## Development + +### Requirements + +- Python 3.11 or higher +- [uv](https://github.com/astral-sh/uv) package manager + +### Installation for Development + +```bash +# Install uv (if not already installed) +curl -LsSf https://astral.sh/uv/install.sh | sh + +# Clone the repository +git clone https://github.com/byjg/docker-easy-haproxy.git +cd docker-easy-haproxy + +# Install dependencies (creates virtual environment automatically) +uv sync --dev + +# Run tests +make test +# or directly: uv run pytest tests/ -vv + +# Run linting +make lint + +# Format code +make format +``` + +### Installing the Package + +```bash +# Install with uv +uv pip install easymapping + +# Or install from source +uv pip install -e ".[dev]" +``` + ## See EasyHAProxy in action Click on the image to see the videos (use HD for better visualization) diff --git a/build/Dockerfile b/build/Dockerfile index 51772bf..dcf0588 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -5,9 +5,11 @@ ARG RELEASE_VERSION_ARG ENV RELEASE_VERSION=$RELEASE_VERSION_ARG ENV TZ="Etc/UTC" -RUN apk add --no-cache haproxy bash python3 py3-pip py-yaml certbot openssl \ +RUN apk add --no-cache haproxy bash python3 py3-pip py-yaml certbot openssl curl \ && apk add --no-cache --virtual .build-deps build-base python3-dev musl-dev linux-headers \ - && pip3 install --upgrade pip --break-system-packages + && pip3 install --upgrade pip --break-system-packages \ + && curl -LsSf https://astral.sh/uv/install.sh | sh \ + && ln -s /root/.local/bin/uv /usr/local/bin/uv RUN openssl dhparam -out /etc/haproxy/dhparam 2048 \ && openssl dhparam -out /etc/haproxy/dhparam-1024 1024 @@ -16,12 +18,14 @@ WORKDIR /scripts COPY build/assets / +COPY pyproject.toml LICENSE README.md /scripts/ COPY src/ /scripts/ +COPY tests/ /scripts/tests/ -RUN pip install -r requirements.txt --break-system-packages +RUN cd /scripts && uv pip install --python /usr/bin/python3 --break-system-packages ".[dev]" RUN apk del .build-deps -RUN pytest -s -vv tests/ +RUN cd /scripts && pytest -s -vv tests/ CMD ["/usr/bin/python", "-u", "/scripts/main.py" ] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8fd0c20 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,77 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "easymapping" +version = "5.0.0" +description = "HAProxy label based routing with service discovery for Docker, Swarm, and Kubernetes" +readme = "README.md" +license = {file = "LICENSE"} +requires-python = ">=3.11" +authors = [] +keywords = ["haproxy", "docker", "kubernetes", "service-discovery", "load-balancer"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "Topic :: System :: Systems Administration", + "Topic :: Internet :: Proxy Servers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] + +dependencies = [ + "pyyaml>=6.0", + "docker>=7.0.0", + "jinja2>=3.1.0", + "kubernetes>=28.0.0", + "deepdiff>=6.0.0", + "pyopenssl>=24.0.0", + "psutil>=5.9.0", + "requests>=2.31.0", +] + +[dependency-groups] +dev = [ + "pytest>=8.0.0", + "pytest-cov>=4.1.0", + "ruff>=0.1.0", +] + +[project.scripts] +easy-haproxy = "main:main" + +[tool.hatch.build.targets.wheel] +packages = ["src/easymapping", "src/functions", "src/processor", "src/plugins", "src/templates"] + +[tool.hatch.build.targets.wheel.sources] +"src" = "" + +[tool.pytest.ini_options] +addopts = "-v -p no:warnings" +testpaths = ["tests"] +pythonpath = ["src"] + +[tool.ruff] +line-length = 120 +target-version = "py311" + +[tool.ruff.lint] +select = ["E", "F", "W", "I", "N", "UP"] +ignore = ["E501"] + +[tool.coverage.run] +source = ["src"] +omit = ["*/tests/*", "*/test_*.py"] + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "raise AssertionError", + "raise NotImplementedError", + "if __name__ == .__main__.:", +] diff --git a/setup.py b/setup.py deleted file mode 100644 index f19e91e..0000000 --- a/setup.py +++ /dev/null @@ -1,20 +0,0 @@ -from setuptools import setup, find_packages - - -with open('README.md') as f: - readme = f.read() - -with open('LICENSE') as f: - license = f.read() - -setup( - name='easymapping', - version='0.1.0', - description='HAProxy label based routing', - long_description=readme, - author='', - author_email='', - url='', - license=license, - packages=find_packages(exclude=('tests', 'docs')) -) diff --git a/src/pytest.ini b/src/pytest.ini deleted file mode 100644 index 3acaa4f..0000000 --- a/src/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -addopts = -v -p no:warnings diff --git a/src/requirements.txt b/src/requirements.txt deleted file mode 100644 index d7cd171..0000000 --- a/src/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -pyyaml -docker -jinja2 -pytest -docker -kubernetes -deepdiff -pyopenssl -psutil \ No newline at end of file diff --git a/src/tests/context.py b/src/tests/context.py deleted file mode 100644 index 66ad651..0000000 --- a/src/tests/context.py +++ /dev/null @@ -1,5 +0,0 @@ -import os -import sys - - -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) diff --git a/src/tests/__init__.py b/tests/__init__.py similarity index 100% rename from src/tests/__init__.py rename to tests/__init__.py diff --git a/src/tests/expected/docker.txt b/tests/expected/docker.txt similarity index 100% rename from src/tests/expected/docker.txt rename to tests/expected/docker.txt diff --git a/src/tests/expected/no-services.txt b/tests/expected/no-services.txt similarity index 100% rename from src/tests/expected/no-services.txt rename to tests/expected/no-services.txt diff --git a/src/tests/expected/services-fcgi.txt b/tests/expected/services-fcgi.txt similarity index 100% rename from src/tests/expected/services-fcgi.txt rename to tests/expected/services-fcgi.txt diff --git a/src/tests/expected/services-letsencrypt.txt b/tests/expected/services-letsencrypt.txt similarity index 100% rename from src/tests/expected/services-letsencrypt.txt rename to tests/expected/services-letsencrypt.txt diff --git a/src/tests/expected/services-multi-containers.txt b/tests/expected/services-multi-containers.txt similarity index 100% rename from src/tests/expected/services-multi-containers.txt rename to tests/expected/services-multi-containers.txt diff --git a/src/tests/expected/services-multiple-hosts.txt b/tests/expected/services-multiple-hosts.txt similarity index 100% rename from src/tests/expected/services-multiple-hosts.txt rename to tests/expected/services-multiple-hosts.txt diff --git a/src/tests/expected/services-redirect-ssl.txt b/tests/expected/services-redirect-ssl.txt similarity index 100% rename from src/tests/expected/services-redirect-ssl.txt rename to tests/expected/services-redirect-ssl.txt diff --git a/src/tests/expected/services-tcp.txt b/tests/expected/services-tcp.txt similarity index 100% rename from src/tests/expected/services-tcp.txt rename to tests/expected/services-tcp.txt diff --git a/src/tests/expected/services.txt b/tests/expected/services.txt similarity index 100% rename from src/tests/expected/services.txt rename to tests/expected/services.txt diff --git a/src/tests/expected/ssl-loose.txt b/tests/expected/ssl-loose.txt similarity index 100% rename from src/tests/expected/ssl-loose.txt rename to tests/expected/ssl-loose.txt diff --git a/src/tests/expected/ssl-strict.txt b/tests/expected/ssl-strict.txt similarity index 100% rename from src/tests/expected/ssl-strict.txt rename to tests/expected/ssl-strict.txt diff --git a/src/tests/expected/static.txt b/tests/expected/static.txt similarity index 100% rename from src/tests/expected/static.txt rename to tests/expected/static.txt diff --git a/src/tests/fixtures/00_haproxy.cfg b/tests/fixtures/00_haproxy.cfg similarity index 100% rename from src/tests/fixtures/00_haproxy.cfg rename to tests/fixtures/00_haproxy.cfg diff --git a/src/tests/fixtures/10_haproxy.cfg b/tests/fixtures/10_haproxy.cfg similarity index 100% rename from src/tests/fixtures/10_haproxy.cfg rename to tests/fixtures/10_haproxy.cfg diff --git a/src/tests/fixtures/no-services b/tests/fixtures/no-services similarity index 100% rename from src/tests/fixtures/no-services rename to tests/fixtures/no-services diff --git a/src/tests/fixtures/run_bash.sh b/tests/fixtures/run_bash.sh similarity index 100% rename from src/tests/fixtures/run_bash.sh rename to tests/fixtures/run_bash.sh diff --git a/src/tests/fixtures/services b/tests/fixtures/services similarity index 100% rename from src/tests/fixtures/services rename to tests/fixtures/services diff --git a/src/tests/fixtures/services-changed-label b/tests/fixtures/services-changed-label similarity index 100% rename from src/tests/fixtures/services-changed-label rename to tests/fixtures/services-changed-label diff --git a/src/tests/fixtures/services-clone-to-ssl b/tests/fixtures/services-clone-to-ssl similarity index 100% rename from src/tests/fixtures/services-clone-to-ssl rename to tests/fixtures/services-clone-to-ssl diff --git a/src/tests/fixtures/services-fcgi b/tests/fixtures/services-fcgi similarity index 100% rename from src/tests/fixtures/services-fcgi rename to tests/fixtures/services-fcgi diff --git a/src/tests/fixtures/services-letsencrypt b/tests/fixtures/services-letsencrypt similarity index 100% rename from src/tests/fixtures/services-letsencrypt rename to tests/fixtures/services-letsencrypt diff --git a/src/tests/fixtures/services-multi-containers b/tests/fixtures/services-multi-containers similarity index 100% rename from src/tests/fixtures/services-multi-containers rename to tests/fixtures/services-multi-containers diff --git a/src/tests/fixtures/services-multiple-hosts b/tests/fixtures/services-multiple-hosts similarity index 100% rename from src/tests/fixtures/services-multiple-hosts rename to tests/fixtures/services-multiple-hosts diff --git a/src/tests/fixtures/services-redirect-ssl b/tests/fixtures/services-redirect-ssl similarity index 100% rename from src/tests/fixtures/services-redirect-ssl rename to tests/fixtures/services-redirect-ssl diff --git a/src/tests/fixtures/services-tcp b/tests/fixtures/services-tcp similarity index 100% rename from src/tests/fixtures/services-tcp rename to tests/fixtures/services-tcp diff --git a/src/tests/fixtures/services-with-cloudflare b/tests/fixtures/services-with-cloudflare similarity index 100% rename from src/tests/fixtures/services-with-cloudflare rename to tests/fixtures/services-with-cloudflare diff --git a/src/tests/fixtures/services-with-deny-pages b/tests/fixtures/services-with-deny-pages similarity index 100% rename from src/tests/fixtures/services-with-deny-pages rename to tests/fixtures/services-with-deny-pages diff --git a/src/tests/fixtures/services-with-ip-whitelist b/tests/fixtures/services-with-ip-whitelist similarity index 100% rename from src/tests/fixtures/services-with-ip-whitelist rename to tests/fixtures/services-with-ip-whitelist diff --git a/src/tests/fixtures/services-with-jwt-validator b/tests/fixtures/services-with-jwt-validator similarity index 100% rename from src/tests/fixtures/services-with-jwt-validator rename to tests/fixtures/services-with-jwt-validator diff --git a/src/tests/fixtures/services-with-multiple-plugins b/tests/fixtures/services-with-multiple-plugins similarity index 100% rename from src/tests/fixtures/services-with-multiple-plugins rename to tests/fixtures/services-with-multiple-plugins diff --git a/src/tests/fixtures/static.yml b/tests/fixtures/static.yml similarity index 100% rename from src/tests/fixtures/static.yml rename to tests/fixtures/static.yml diff --git a/src/tests/test_containerenv.py b/tests/test_containerenv.py similarity index 100% rename from src/tests/test_containerenv.py rename to tests/test_containerenv.py diff --git a/src/tests/test_daemonize.py b/tests/test_daemonize.py similarity index 100% rename from src/tests/test_daemonize.py rename to tests/test_daemonize.py diff --git a/src/tests/test_docker.py b/tests/test_docker.py similarity index 100% rename from src/tests/test_docker.py rename to tests/test_docker.py diff --git a/src/tests/test_functions.py b/tests/test_functions.py similarity index 100% rename from src/tests/test_functions.py rename to tests/test_functions.py diff --git a/src/tests/test_labels.py b/tests/test_labels.py similarity index 100% rename from src/tests/test_labels.py rename to tests/test_labels.py diff --git a/src/tests/test_parser.py b/tests/test_parser.py similarity index 100% rename from src/tests/test_parser.py rename to tests/test_parser.py diff --git a/src/tests/test_plugins.py b/tests/test_plugins.py similarity index 100% rename from src/tests/test_plugins.py rename to tests/test_plugins.py diff --git a/src/tests/test_static.py b/tests/test_static.py similarity index 100% rename from src/tests/test_static.py rename to tests/test_static.py