Skip to content

Add ingress status update and support for ingress class changes#67

Merged
byjg merged 57 commits intomasterfrom
ingressclassname
Feb 18, 2026
Merged

Add ingress status update and support for ingress class changes#67
byjg merged 57 commits intomasterfrom
ingressclassname

Conversation

@byjg
Copy link
Owner

@byjg byjg commented Dec 16, 2025

Summary

This release adds support for the modern Kubernetes IngressClass API and automatic ingress status updates, improving compliance with Kubernetes standards and user experience.

Features Implemented

1. IngressClass Resource Support

Added proper IngressClass resource definition and support for the modern spec.ingressClassName field.

What changed:

  • Created IngressClass resource named easyhaproxy (replaces verbose easyhaproxy-ingress)
  • Supports modern spec.ingressClassName: easyhaproxy field (Kubernetes 1.18+)
  • Maintains backward compatibility with deprecated kubernetes.io/ingress.class: easyhaproxy-ingress annotation
  • Updated RBAC permissions to include ingressclasses resource

Benefits:

  • ✅ Follows Kubernetes best practices and standards
  • ✅ Matches naming conventions of nginx, traefik, and other ingress controllers
  • ✅ Backward compatible - existing deployments continue to work
  • ✅ Future-proof as the annotation is officially deprecated

Usage:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  ingressClassName: easyhaproxy  # Modern approach (recommended)
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          service:
            name: example-service
            port:
              number: 8080
        pathType: ImplementationSpecific

2. Automatic Ingress Status Updates

EasyHAProxy now automatically updates ingress status with load balancer addresses, populating the ADDRESS column in kubectl get ingress output.

What changed:

  • Auto-detects deployment mode (DaemonSet, NodePort, or ClusterIP)
  • Reports appropriate IP addresses/hostnames based on deployment mode:
    • DaemonSet: Node IPs where pods are scheduled
    • NodePort: All node IPs (traffic can reach any node)
    • ClusterIP: LoadBalancer IP, external hostname, or ClusterIP
  • Caches deployment mode and addresses for performance
  • Added RBAC permissions for ingresses/status updates
  • Enabled by default (can be disabled via configuration)

Benefits:

  • Better UX: Users immediately see where to access their ingresses
  • Standard behavior: Matches nginx-ingress, traefik, etc.
  • Easier debugging: Quick verification that ingress is configured
  • Tool integration: Works with Kubernetes dashboards and monitoring tools

Example output:

# Before:
$ kubectl get ingress
NAME    CLASS        HOSTS         ADDRESS   PORTS
myapp   easyhaproxy  example.com             80

# After:
$ kubectl get ingress
NAME    CLASS        HOSTS         ADDRESS        PORTS
myapp   easyhaproxy  example.com   192.168.1.100  80

Configuration

Disable Status Updates

# values.yaml
ingressStatus:
  enabled: false

Override Deployment Mode Detection

# values.yaml
ingressStatus:
  deploymentMode: nodeport  # auto, daemonset, nodeport, or clusterip

Set External Hostname (ClusterIP mode)

# values.yaml
ingressStatus:
  externalHostname: "haproxy.example.com"

Adjust Cache TTL

# values.yaml
ingressStatus:
  updateInterval: 60  # seconds

Backward Compatibility

No breaking changes. All existing deployments continue to work:

  • Old annotation kubernetes.io/ingress.class: easyhaproxy-ingress still supported
  • Ingress status updates are additive (don't affect existing functionality)
  • Status updates can be disabled if needed

Technical Details

Files Modified

Helm templates:

  • helm/easyhaproxy/templates/ingressclass.yaml (new)
  • helm/easyhaproxy/templates/clusterrole.yaml (updated RBAC)
  • helm/easyhaproxy/templates/deployment.yaml (added env vars)
  • helm/easyhaproxy/values.yaml (added configuration)

Python code:

  • src/processor/__init__.py (added detection and status update logic)
  • src/functions/__init__.py (added configuration support)

Static manifests (regenerated):

  • deploy/kubernetes/easyhaproxy-daemonset.yml
  • deploy/kubernetes/easyhaproxy-nodeport.yml
  • deploy/kubernetes/easyhaproxy-clusterip.yml

Documentation:

  • docs/kubernetes.md (updated examples and explanations)
  • deploy/kubernetes/README.md (enhanced with detailed instructions)

RBAC Permissions Added

- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses/status", "ingressclasses"]
  verbs: ["get", "list", "watch"]
  
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses/status"]
  verbs: ["patch"]
  
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list"]

Migration Guide

For New Deployments

Use the modern approach:

spec:
  ingressClassName: easyhaproxy

For Existing Deployments

Option 1: Keep current annotation (still works)

metadata:
  annotations:
    kubernetes.io/ingress.class: easyhaproxy-ingress

Option 2: Migrate to new field (recommended)

spec:
  ingressClassName: easyhaproxy

Performance Impact

  • Minimal: Deployment mode detected once and cached
  • Node IPs cached with 30s TTL (configurable)
  • Status updates: 1 API call per ingress per refresh cycle
  • Graceful degradation: Errors are logged but don't affect HAProxy config

Future Enhancements

Potential improvements for consideration:

  • Support for setting custom status messages
  • Webhook for immediate status updates on deployment changes
  • Metrics for status update success/failure rates
  • Support for multiple external IPs/hostnames

Related Documentation

byjg added 3 commits December 15, 2025 19:58
…c.ingressClassName` in Kubernetes examples and processor logic for compatibility with Kubernetes v1.22+. Updated documentation and examples to reflect the change while maintaining backward compatibility.
…Name` across templates, examples, and documentation for consistency and backward compatibility

- Introduced new IngressClass resource in Helm templates to define `easyhaproxy` as the default ingress class.
- Updated Kubernetes examples to replace `easyhaproxy-ingress` with `easyhaproxy` as the ingress class name.
- Enhanced processor logic to support both the new `spec.ingressClassName` field and the deprecated `kubernetes.io/ingress.class` annotation.
- Revised documentation to reflect the changes and ensure alignment with Kubernetes recommendations.
… modes

- Introduced `ingressStatus` configuration in Helm values to enable status updates and customize deployment modes (auto, daemonset, nodeport, clusterip).
- Implemented logic in the processor to detect deployment mode, retrieve ingress addresses, and update ingress status dynamically.
- Updated Kubernetes manifests to grant required permissions for `ingresses/status` operations and pass necessary environment variables for configuration.
- Adjusted Helm templates and associated Kubernetes examples to reflect the new ingress status update capability.
byjg added 24 commits December 15, 2025 21:18
- Added support for new configuration fields: `update_ingress_status`, `deployment_mode`, `external_hostname`, and `ingress_status_update_interval`.
- Updated assertions in test cases to validate the presence of these fields.
…fying imports, and applying type hinting refinements.
…treamline test execution

- Replaced `pip install` with `uv sync --group dev` for dependency management.
- Adjusted test step to ensure `uv` commands are properly initialized in the PATH.
- Replaced `pip install` with `uv sync --frozen` for improved dependency handling.
- Simplified Dockerfile by removing unused packages and redundant commands.
- Updated test and execution steps to utilize `uv` for consistency.
…sync`

- Deleted `.gitpod.yml` to stop using Gitpod-specific configuration.
- Added `uv.lock` for dependency versioning.
- Updated Dockerfile to include `uv sync --no-dev` in the build process.
…ions

- Introduced `--current` flag to show the current App and Chart versions.
- Improved user guidance with updated usage instructions and scripts output.
- Added post-merge steps to the version bump process.
- Replaced `secrets: inherit` with explicit `DOC_TOKEN` in workflow file.
- Adjusted Compose files to build images locally instead of pulling.
- Simplified examples by removing `/etc/hosts` entry instructions.
- Enhanced `cloudflare.py` plugin with a configurable log format.
- Improved `generate-keys.sh` for portability using `$SCRIPT_DIR`.
- Added end-to-end tests for Compose examples using pytest.
- Introduced a suite of pytest-based integration tests for Kubernetes using `kind`.
- Automated local installation of dependencies (`kind`, `kubectl`, and `helm`) when missing.
- Implemented fixtures for Kubernetes resource management and TLS secrets.
- Added end-to-end tests for HTTP and HTTPS ingress functionality.
- Enhanced the Cloudflare plugin by adding support for base64-encoded IP lists, prioritizing them over built-in lists.
- Introduced Kubernetes integration tests for the Cloudflare IP restoration feature.
- Validated plugin behavior for resource creation, pod readiness, ingress access, and HAProxy configurations.
- Improved annotations in `cloudflare.yml` for Kubernetes-native compatibility.
- Updated unit tests to cover IP list precedence, invalid base64 handling, and metadata verification.
…ting

- Deleted the `/examples/docker/python-app` directory and associated files.
- Integrated a custom `header-echo` server for Kubernetes and Docker Compose tests.
- Updated Kubernetes and Docker Compose configurations to use the new `header-echo-server:test` image.
- Enhanced Kubernetes integration tests to validate JSON responses and Cloudflare IP translation behavior.
- Relocated all files and scripts from `examples` to `tests_e2e` for better organization.
- Updated references and paths in configurations, scripts, and test files.
- Adjusted `bump-version.sh` to handle the new `tests_e2e` structure.
- Updated `.gitignore` to reflect path changes.
- Introduced `utils.py` for shared test utility functions (e.g., JWT generation, pod readiness checks, etc.).
- Added shared pytest fixtures in `conftest.py`, eliminating redundancy across Kubernetes and Docker Compose tests.
- Replaced inline test logic with reusable helper functions for Kubernetes configuration validation and resource readiness.
- Updated tests to leverage new consolidated functionality for better maintainability and clarity.
- Removed outdated, duplicate code in test files, aligning with new utilities and fixture structure.
- Added blank lines before specific print statements in E2E test scripts for better readability.
- Enabled `workflow_dispatch` in `.github/workflows/build.yml` to allow manual triggering of workflows.
- Added separate jobs for running Docker Compose and Kubernetes E2E tests in CI pipeline.
…triggers

- Removed `if` conditions for `Tests-E2E-Docker` and `Tests-E2E-Kubernetes` jobs, ensuring they always run.
- Updated `Build` job to depend on both E2E test jobs for stricter validation before building.
…triggers

- Removed `if` conditions for `Tests-E2E-Docker` and `Tests-E2E-Kubernetes` jobs, ensuring they always run.
- Updated `Build` job to depend on both E2E test jobs for stricter validation before building.
- Added detailed log messages in `conftest.py` for SSL certificate and JWT generation steps.
- Improved Docker Compose E2E test output with service-specific logs during startup and cleanup.
- Adjusted pytest run options in CI workflows to use `--tb=short` for concise error traceback.
…mize build strategy

- Added `create_cloudflare_ips_file` to centralize `cloudflare_ips.lst` creation and avoid redundant logic.
- Introduced a global flag `_docker_image_built` for smart Docker image build management.
- Improved test output readability with refined print formatting.
- Simplified `docker_compose_cloud
- Replaced `easymapping` configuration with `containers` for better maintainability and clarity.
- Introduced `DockerComposeFixture` class in `utils.py` to manage Docker Compose lifecycle and smart build strategy.
- Enhanced YAML-to-environment variable conversion in `ContainerEnv` for dynamic configuration support.
- Updated HAProxy configurations and test fixtures to reflect the new format.
- Improved test coverage for YAML parsing, environment variable handling, and HAProxy config generation.
- Added `initialize_plugins` method to `PluginManager` for requesting and processing file system resources during plugin initialization.
- Introduced `InitializationResult` and `ResourceRequest` structures for fine-grained resource management (e.g., directories, files).
- Enhanced configuration injection by separating `global_configs`, `defaults_configs`, and backend-level `haproxy_config`.
- Updated existing plugins (e.g., JWT Validator, Cloudflare) to use the initialization phase for resource setup.
- Simplified domain plugin execution by consolidating configuration logic into unified loops.
- Added integration tests to validate HAProxy configuration generation for Certbot's HTTP-01 challenges.
- Verified handling of ACLs, SSL redirects, multi-domain setups, and backend behaviors.
- Introduced unit tests for the Certbot class to ensure proper ACME server handling, certificate status checks, and configuration validation.
- Improved test coverage for edge cases, including EAB credentials, manual hooks, and custom ports.
- Enhanced certbot-related environment variable parsing and error scenarios.
byjg added 27 commits February 16, 2026 12:13
…rrect working directory

- Replaced `compose_file` references with `docker-compose-acme-e2e.yml` for improved clarity.
- Added working directory changes for Docker Compose commands to ensure relative paths work properly.
- Restored original working directory after test execution for cleanup consistency.
…startup logic, and replace Python-based health check
- Clarify that EASYHAPROXY_CERTBOT_AUTOCONFIG or CERTBOT_SERVER is required
- Add complete docker-compose.yml examples for ACME setup
- Explain SSL termination at HAProxy level vs backend containers
- Reorganize SSL docs to emphasize volume method over label method
- Add troubleshooting section for common ACME warnings
- Clarify certificate storage paths and selection priority
- Add examples showing both ACME and manual certificates together

Resolves confusion about ACME configuration requirements and makes
it clear that volume-mounted certificates are the recommended method
for manual SSL certificates.
…-Port, X-Forwarded-Proto, X-Forwarded-Host, and X-Request-ID

- Updated HAProxy configuration template to set all standard proxy headers for HTTP requests.
- Added support for a unique request ID via `unique-id-format` and `unique-id-header` directives.
- Implemented E2E tests for header validation, request correlation, and configuration correctness.
- Enhanced documentation to explain usage and examples of proxy headers.
- Updated CI workflows to include E2E tests for proxy headers.
…-Port, X-Forwarded-Proto, X-Forwarded-Host, and X-Request-ID

- Updated HAProxy configuration template to set all standard proxy headers for HTTP requests.
- Added support for a unique request ID via `unique-id-format` and `unique-id-header` directives.
- Implemented E2E tests for header validation, request correlation, and configuration correctness.
- Enhanced documentation to explain usage and examples of proxy headers.
- Updated CI workflows to include E2E tests for proxy headers.
- Introduced `HAPROXY_STATS_CORS_ORIGIN` environment variable for enabling CORS in HAProxy stats.
- Updated HAProxy configuration template to handle CORS preflight and response headers.
- Added tests for static configuration mode with CORS enabled.
- Updated documentation to include new CORS configuration details and examples.
…ON response handling

- Replaced direct `curl` calls with `wait_for_json_response` to improve retry logic and error handling.
- Simplified tests for header validation and backend readiness verification.
…lation

- Introduced `/scripts/.venv/bin/easy-haproxy` as the default entrypoint for standalone environments.
- Added `_build_parser` and `start` functions to enable CLI-driven functionality configuration.
- Updated packaging to reflect new `easyhaproxy.main` module and adapted project name from `easymapping` to `easyhaproxy`.
- Modified `Dockerfile` to align with new script paths and entrypoints for better portability.
- Enhanced documentation with dedicated sections for pip-based installation, CLI references, and systemd setup for non-Docker environments.
- Adjusted helm, plugin, and environment-related docs for accurate sidebar ordering.
- Added a new GitHub workflow to automate package publishing to PyPI.
- Implemented a two-stage Dockerfile: build environment with Python dependencies and lean runtime stage with HAProxy.
- Added custom entrypoint script for dynamic Docker group adjustment.
- Improved HAProxy command generation by introducing a static method for binary resolution.
- Updated tests and functional logic to dynamically resolve the `haproxy` binary path.
- Adjusted file permissions in E2E key generation script for better security.
- Streamlined `.gitignore` by removing unnecessary exclusions.
- Removed `install.sh` and moved Docker-related assets to `deploy/docker`.
- Updated all Dockerfile references from `build/` to `deploy/docker/`.
- Refactored paths in E2E tests, Makefile, and documentation for consistency with new directory structure.
- Added `HAPROXY_STATS_CORS_ORIGIN` environment variable in `docker-compose.yml`.
…sing, and plugin management framework

- Introduced `certbot.py` for ACME certificate management, including certificate issuance, renewal, and environment validation.
- Added `haproxy.py` for HAProxy process management, configuration validation, and dynamic command handling.
- Implemented `container_env.py` for reading and parsing environment variables with YAML overrides.
- Created `consts.py` for centralized management of static and dynamic paths.
- Added `manager.py` to enable plugin discovery, initialization, configuration, and execution.
- Refactored logging and configuration handling across modules for consistency.

Enhances modularity and scalability by introducing feature-dedicated modules and structured configuration handling.
…e Docker Swarm configurations

- Modified `pytest.fixture` scope to `class` across tests to improve fixture lifecycle and reduce setup overhead.
- Introduced a new `tests_e2e/test_swarm.py` test suite for Docker Swarm stack configurations.
- Added E2E tests for Swarm mode with scenarios such as basic services and combined plugins.
- Updated HAProxy image in Swarm stack `.yml` files to `byjg/easy-haproxy:local` for local testing consistency.
- Added `swarm` marker in `pyproject.toml` for differentiating Docker Swarm-specific tests.
- Updated GitHub workflows to include a new Swarm E2E test pipeline.
…/wait logic, consolidate replicas, and update HAProxy config refresh cycle
…/wait logic, consolidate replicas, and update HAProxy config refresh cycle
…lds in Swarm E2E tests

- Updated GitHub workflow to include Docker cache cleanup and image build steps.
- Modified Swarm E2E test logic to skip Docker image build if it already exists, optimizing CI performance.
…lds in Swarm E2E tests

- Updated GitHub workflow to include Docker cache cleanup and image build steps.
- Modified Swarm E2E test logic to skip Docker image build if it already exists, optimizing CI performance.
… HTTP 503

- Updated polling step to consider non-503 responses (e.g., 200/401/403) as backend readiness.
- Improved logging to reflect updated readiness criteria.
- Enhanced robustness by distinguishing between transient and configured backend states.
@byjg byjg merged commit deade0a into master Feb 18, 2026
10 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in EasyHAProxy features Feb 18, 2026
@byjg byjg deleted the ingressclassname branch February 18, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant

Comments