From a072463885d6f6f5c2202b3eaf4ff2ab73d9895c Mon Sep 17 00:00:00 2001 From: henkhogan Date: Sat, 20 Jun 2026 22:23:07 +0200 Subject: [PATCH 1/6] changed repo name to lowercase --- .github/workflows/docker-build.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 8332832..b28840b 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -20,6 +20,10 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Convert repository name to lowercase + id: repo + run: echo "repo=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + - name: Login to GitHub Container Registry if: github.event_name != 'pull_request' uses: docker/login-action@v3 @@ -33,7 +37,7 @@ jobs: uses: docker/metadata-action@v5 with: images: | - ghcr.io/${{ github.repository }} + ghcr.io/${{ steps.repo.outputs.repo }} tags: | type=ref,event=branch type=semver,pattern={{version}} @@ -57,5 +61,5 @@ jobs: push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache - cache-to: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache,mode=max + cache-from: type=registry,ref=ghcr.io/${{ steps.repo.outputs.repo }}:buildcache + cache-to: type=registry,ref=ghcr.io/${{ steps.repo.outputs.repo }}:buildcache,mode=max From 2f651ddb384e1d8a84462a40dac7ed2ee94709f5 Mon Sep 17 00:00:00 2001 From: henkhogan Date: Sat, 20 Jun 2026 23:24:18 +0200 Subject: [PATCH 2/6] permissions to push image --- .github/workflows/docker-build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index b28840b..be5c75a 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -10,6 +10,10 @@ on: branches: - main +permissions: + contents: read + packages: write + jobs: build: runs-on: ubuntu-latest From 68b4b9cba90425f4f5fba499dbd92af890923b76 Mon Sep 17 00:00:00 2001 From: henkhogan Date: Thu, 25 Jun 2026 19:48:37 +0200 Subject: [PATCH 3/6] helm chart added --- .github/workflows/docker-build.yml | 62 ++- Cargo.lock | 430 +++++++++++++++++- Cargo.toml | 8 + DEPLOYMENT.md | 390 ++++++++++++++++ HELM_INTEGRATION.md | 193 ++++++++ HELM_SETUP_COMPLETE.md | 317 +++++++++++++ README.md | 63 ++- helm/playwright-proxy/.helmignore | 25 + helm/playwright-proxy/Chart.yaml | 17 + helm/playwright-proxy/README.md | 96 ++++ .../examples/development.yaml | 35 ++ .../playwright-proxy/examples/production.yaml | 93 ++++ helm/playwright-proxy/examples/staging.yaml | 68 +++ helm/playwright-proxy/templates/_helpers.tpl | 60 +++ .../templates/deployment.yaml | 73 +++ helm/playwright-proxy/templates/hpa.yaml | 32 ++ .../playwright-proxy/templates/httproute.yaml | 32 ++ helm/playwright-proxy/templates/ingress.yaml | 41 ++ helm/playwright-proxy/templates/service.yaml | 19 + .../templates/serviceaccount.yaml | 12 + helm/playwright-proxy/values.yaml | 121 +++++ scripts/package-helm.sh | 57 +++ scripts/validate-helm.sh | 78 ++++ src/main.rs | 278 ++++++----- 24 files changed, 2486 insertions(+), 114 deletions(-) create mode 100644 DEPLOYMENT.md create mode 100644 HELM_INTEGRATION.md create mode 100644 HELM_SETUP_COMPLETE.md create mode 100644 helm/playwright-proxy/.helmignore create mode 100644 helm/playwright-proxy/Chart.yaml create mode 100644 helm/playwright-proxy/README.md create mode 100644 helm/playwright-proxy/examples/development.yaml create mode 100644 helm/playwright-proxy/examples/production.yaml create mode 100644 helm/playwright-proxy/examples/staging.yaml create mode 100644 helm/playwright-proxy/templates/_helpers.tpl create mode 100644 helm/playwright-proxy/templates/deployment.yaml create mode 100644 helm/playwright-proxy/templates/hpa.yaml create mode 100644 helm/playwright-proxy/templates/httproute.yaml create mode 100644 helm/playwright-proxy/templates/ingress.yaml create mode 100644 helm/playwright-proxy/templates/service.yaml create mode 100644 helm/playwright-proxy/templates/serviceaccount.yaml create mode 100644 helm/playwright-proxy/values.yaml create mode 100644 scripts/package-helm.sh create mode 100644 scripts/validate-helm.sh diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index be5c75a..f29c951 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -1,4 +1,4 @@ -name: Docker Multi-Arch Build +name: Docker Multi-Arch Build & Helm Release on: push: @@ -15,6 +15,26 @@ permissions: packages: write jobs: + validate-helm: + name: Validate Helm Chart + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v3 + with: + version: 'latest' + + - name: Lint Helm chart + run: | + helm lint ./helm/playwright-proxy + + - name: Template Helm chart + run: | + helm template playwright-proxy ./helm/playwright-proxy + build: runs-on: ubuntu-latest steps: @@ -67,3 +87,43 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=ghcr.io/${{ steps.repo.outputs.repo }}:buildcache cache-to: type=registry,ref=ghcr.io/${{ steps.repo.outputs.repo }}:buildcache,mode=max + + package-helm: + name: Package Helm Chart + runs-on: ubuntu-latest + needs: validate-helm + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v3 + with: + version: 'latest' + + - name: Package Helm chart + run: | + mkdir -p helm-packages + helm package ./helm/playwright-proxy -d helm-packages + + - name: Generate Helm index + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + helm repo index helm-packages --url https://github.com/${{ github.repository }}/releases/download/helm-latest/ + + - name: Upload Helm chart packages + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: helm-packages + path: helm-packages/ + + - name: Create Helm Release + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + uses: softprops/action-gh-release@v1 + with: + files: | + helm-packages/playwright-proxy-*.tgz + token: ${{ secrets.GITHUB_TOKEN }} + draft: false + prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }} diff --git a/Cargo.lock b/Cargo.lock index 1d43e91..a586688 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,45 @@ dependencies = [ "libc", ] +[[package]] +name = "asn1-rs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time 0.3.49", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -29,6 +68,28 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "aws-lc-rs" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.8.9" @@ -93,6 +154,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -150,6 +217,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -173,6 +242,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -243,6 +321,32 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "der-parser" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + [[package]] name = "dirs" version = "3.0.2" @@ -274,6 +378,12 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.16.0" @@ -357,6 +467,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.32" @@ -456,6 +572,18 @@ dependencies = [ "wasi 0.11.1+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + [[package]] name = "getrandom" version = "0.4.3" @@ -464,7 +592,7 @@ checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", ] [[package]] @@ -795,6 +923,16 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.102" @@ -872,6 +1010,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -910,6 +1054,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -919,6 +1073,31 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -928,6 +1107,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "oid-registry" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1006,6 +1194,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64 0.22.1", + "serde_core", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -1053,9 +1251,17 @@ name = "playwright-proxy" version = "0.1.0" dependencies = [ "axum", + "lazy_static", + "native-tls", "playwright", + "rcgen", + "rustls 0.23.40", + "rustls-pemfile 2.2.0", "tokio", + "tokio-native-tls", + "tokio-rustls", "tracing-subscriber", + "x509-parser", ] [[package]] @@ -1067,6 +1273,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "proc-macro2" version = "1.0.106" @@ -1085,12 +1297,31 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rcgen" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time 0.3.49", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -1135,7 +1366,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", @@ -1151,6 +1382,29 @@ dependencies = [ "winreg", ] +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustix" version = "1.1.4" @@ -1164,6 +1418,35 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.103.13", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -1173,6 +1456,47 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -1395,6 +1719,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -1514,6 +1844,36 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.3" @@ -1562,6 +1922,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.18" @@ -1673,6 +2044,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.8" @@ -1724,6 +2101,15 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.125" @@ -2028,12 +2414,44 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "writeable" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "x509-parser" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time 0.3.49", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time 0.3.49", +] + [[package]] name = "yoke" version = "0.8.3" @@ -2078,6 +2496,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + [[package]] name = "zerotrie" version = "0.2.4" @@ -2122,7 +2546,7 @@ dependencies = [ "crc32fast", "flate2", "thiserror", - "time", + "time 0.1.45", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 13980ca..2622b13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,13 @@ edition = "2021" [dependencies] axum = "0.8.9" tokio = { version = "1.0", features = ["full"] } +tokio-native-tls = "0.3" +native-tls = "0.2" playwright = "0.0.20" # Community-maintained native Rust bindings tracing-subscriber = "0.3" +rcgen = "0.13" +x509-parser = "0.16" +rustls = "0.23" +rustls-pemfile = "2.1" +tokio-rustls = "0.25" +lazy_static = "1.4" diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..aee7f2e --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,390 @@ +# Kubernetes Deployment Guide + +This guide provides comprehensive instructions for deploying Playwright Proxy to Kubernetes using Helm. + +## Table of Contents + +- [Prerequisites](#prerequisites) +- [Quick Start](#quick-start) +- [Installation](#installation) +- [Configuration](#configuration) +- [Examples](#examples) +- [Monitoring](#monitoring) +- [Scaling](#scaling) +- [Troubleshooting](#troubleshooting) +- [Uninstalling](#uninstalling) + +## Prerequisites + +- Kubernetes cluster 1.19 or higher +- `kubectl` configured to access your cluster +- Helm 3.0 or higher installed +- Container registry credentials (for private registries) +- At least 2GB of free memory per Pod (for Playwright browser) + +## Quick Start + +The fastest way to deploy Playwright Proxy to Kubernetes: + +```bash +# Add Helm repository (if applicable) +helm repo add playwright-proxy https://github.com/Henkhogan/playwright-proxy/releases/download/helm-latest/ +helm repo update + +# Install with default configuration +helm install playwright-proxy playwright-proxy/playwright-proxy \ + --namespace default \ + --create-namespace + +# Verify the deployment +kubectl get pods -l app.kubernetes.io/name=playwright-proxy +kubectl get svc -l app.kubernetes.io/name=playwright-proxy +``` + +## Installation + +### From local chart + +```bash +# Clone the repository +git clone https://github.com/Henkhogan/playwright-proxy.git +cd playwright-proxy + +# Install using local chart +helm install my-release ./helm/playwright-proxy \ + --namespace default \ + --create-namespace +``` + +### With custom namespace + +```bash +helm install my-release ./helm/playwright-proxy \ + --namespace playwright-proxy \ + --create-namespace \ + --set replicaCount=3 +``` + +### With custom values file + +```bash +helm install my-release ./helm/playwright-proxy \ + --values custom-values.yaml +``` + +## Configuration + +### Basic Configuration Parameters + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `replicaCount` | `2` | Number of Pod replicas | +| `image.tag` | `latest` | Container image tag | +| `image.pullPolicy` | `IfNotPresent` | Image pull policy | +| `service.type` | `ClusterIP` | Kubernetes service type | +| `service.port` | `8000` | Service port | +| `resources.requests.cpu` | `500m` | CPU request per Pod | +| `resources.requests.memory` | `512Mi` | Memory request per Pod | +| `resources.limits.cpu` | `1000m` | CPU limit per Pod | +| `resources.limits.memory` | `1024Mi` | Memory limit per Pod | + +### Updating Configuration + +```bash +# Update via command line +helm upgrade my-release ./helm/playwright-proxy \ + --set replicaCount=5 \ + --set resources.limits.memory=2048Mi + +# Update via values file +helm upgrade my-release ./helm/playwright-proxy \ + --values production-values.yaml +``` + +## Examples + +### Example 1: Development Environment + +Minimal configuration for development: + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --values ./helm/playwright-proxy/examples/development.yaml +``` + +**Features:** +- Single Pod replica +- NodePort service +- No autoscaling +- Minimal resource requests + +### Example 2: Staging Environment + +Balanced configuration with autoscaling: + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --values ./helm/playwright-proxy/examples/staging.yaml +``` + +**Features:** +- 2 Pod replicas +- ClusterIP service +- Ingress enabled +- Horizontal Pod Autoscaler (2-10 replicas) +- Health checks enabled + +### Example 3: Production Environment + +High-availability configuration: + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --values ./helm/playwright-proxy/examples/production.yaml +``` + +**Features:** +- 3 Pod replicas +- ClusterIP service +- Ingress with TLS +- Horizontal Pod Autoscaler (3-20 replicas) +- Pod anti-affinity for distribution +- Node affinity for compute-intensive nodes +- Comprehensive monitoring annotations + +### Example 4: Custom Configuration + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --set ingress.enabled=true \ + --set ingress.className=nginx \ + --set ingress.hosts[0].host=proxy.example.com \ + --set ingress.hosts[0].paths[0].path=/ \ + --set ingress.hosts[0].paths[0].pathType=Prefix \ + --set autoscaling.enabled=true \ + --set autoscaling.minReplicas=2 \ + --set autoscaling.maxReplicas=10 \ + --set autoscaling.targetCPUUtilizationPercentage=70 +``` + +## Monitoring + +### Health Checks + +The Helm chart includes liveness and readiness probes: + +```yaml +livenessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 3 + +readinessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + failureThreshold: 3 +``` + +### Viewing Logs + +```bash +# View logs from a specific Pod +kubectl logs -l app.kubernetes.io/name=playwright-proxy -f + +# View logs from a specific deployment +kubectl logs deployment/playwright-proxy -f + +# View logs from the last 100 lines +kubectl logs -l app.kubernetes.io/name=playwright-proxy --tail=100 +``` + +### Accessing the Service + +```bash +# Port-forward for local testing +kubectl port-forward svc/playwright-proxy 8000:8000 + +# From another terminal, test the proxy +curl --proxy "http://localhost:8000" https://example.com +``` + +## Scaling + +### Manual Scaling + +```bash +# Scale to a specific number of replicas +kubectl scale deployment playwright-proxy --replicas=5 + +# Or via Helm +helm upgrade my-release ./helm/playwright-proxy --set replicaCount=5 +``` + +### Autoscaling + +Enable Horizontal Pod Autoscaler: + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --set autoscaling.enabled=true \ + --set autoscaling.minReplicas=2 \ + --set autoscaling.maxReplicas=20 \ + --set autoscaling.targetCPUUtilizationPercentage=70 +``` + +### Monitoring Autoscaling + +```bash +# View HPA status +kubectl get hpa + +# Describe HPA for detailed information +kubectl describe hpa playwright-proxy + +# Watch HPA in action +kubectl get hpa -w +``` + +## Troubleshooting + +### Pod not starting + +```bash +# Check Pod status +kubectl describe pod -l app.kubernetes.io/name=playwright-proxy + +# Check logs +kubectl logs -l app.kubernetes.io/name=playwright-proxy + +# Check events +kubectl get events --sort-by='.lastTimestamp' +``` + +### ImagePullBackOff error + +```bash +# Check if the image exists +kubectl describe pod + +# Create image pull secret if using private registry +kubectl create secret docker-registry regcred \ + --docker-server=ghcr.io \ + --docker-username= \ + --docker-password= \ + --docker-email= + +# Add to values +helm install playwright-proxy ./helm/playwright-proxy \ + --set imagePullSecrets[0].name=regcred +``` + +### Out of Memory errors + +```bash +# Increase memory limits +helm upgrade my-release ./helm/playwright-proxy \ + --set resources.limits.memory=2048Mi \ + --set resources.requests.memory=1536Mi + +# Monitor memory usage +kubectl top pods -l app.kubernetes.io/name=playwright-proxy +``` + +### Connection timeout + +```bash +# Check if service is accessible +kubectl get svc playwright-proxy + +# Test connectivity from another Pod +kubectl run -it debug --image=curlimages/curl --restart=Never -- \ + curl http://playwright-proxy:8000 +``` + +## Uninstalling + +```bash +# Uninstall the release +helm uninstall my-release + +# Uninstall from specific namespace +helm uninstall my-release --namespace playwright-proxy + +# Verify uninstallation +helm list +kubectl get pods -l app.kubernetes.io/name=playwright-proxy +``` + +## Advanced Configuration + +### Using a custom image repository + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --set image.registry=docker.io \ + --set image.repository=myorg/playwright-proxy \ + --set image.tag=v1.0.0 +``` + +### Adding environment variables + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --set env.PROXY_PORT=9000 \ + --set env.LOG_LEVEL=debug +``` + +### Node affinity and tolerations + +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --set nodeSelector.workload=compute-intensive \ + --set tolerations[0].key=compute-intensive \ + --set tolerations[0].operator=Equal \ + --set tolerations[0].value=true \ + --set tolerations[0].effect=NoSchedule +``` + +## Resources and Best Practices + +### Resource Recommendations + +**Minimum:** +- CPU: 250m per Pod +- Memory: 512Mi per Pod + +**Recommended:** +- CPU: 500m-1000m per Pod +- Memory: 512Mi-1024Mi per Pod + +**High Load:** +- CPU: 1000m-2000m per Pod +- Memory: 1024Mi-2048Mi per Pod + +### Best Practices + +1. **Set resource requests and limits** to ensure fair resource distribution +2. **Enable autoscaling** for production environments +3. **Use readiness and liveness probes** for better reliability +4. **Set pod anti-affinity** to distribute Pods across nodes +5. **Use ingress** for external access instead of NodePort +6. **Monitor metrics** using Prometheus or similar tools +7. **Use separate namespaces** for different environments +8. **Enable RBAC** for security +9. **Regularly update** the container image +10. **Test configuration changes** in staging before production + +## Support + +For issues or questions: +- Check the [main README](../README.md) +- Review the [chart README](./README.md) +- Open an issue on [GitHub](https://github.com/Henkhogan/playwright-proxy/issues) diff --git a/HELM_INTEGRATION.md b/HELM_INTEGRATION.md new file mode 100644 index 0000000..30fb6ad --- /dev/null +++ b/HELM_INTEGRATION.md @@ -0,0 +1,193 @@ +# Helm Chart & Build Pipeline Integration - Summary + +This document summarizes the Helm chart and build pipeline changes added to the playwright-proxy project. + +## What Was Added + +### 1. Helm Chart (`helm/playwright-proxy/`) + +#### Chart Files +- **`Chart.yaml`** - Helm chart metadata and version information +- **`values.yaml`** - Default configuration values for all chart parameters +- **`.helmignore`** - Patterns to ignore when building Helm packages + +#### Templates (`helm/playwright-proxy/templates/`) +- **`_helpers.tpl`** - Helm template helper functions and labels +- **`deployment.yaml`** - Kubernetes Deployment with all customizable options +- **`service.yaml`** - Kubernetes Service for exposing the application +- **`ingress.yaml`** - Optional Ingress for external HTTP/HTTPS access +- **`hpa.yaml`** - Optional Horizontal Pod Autoscaler for automatic scaling +- **`serviceaccount.yaml`** - Optional Kubernetes ServiceAccount + +#### Documentation +- **`README.md`** - Helm chart documentation with usage examples +- **`examples/production.yaml`** - Production-ready configuration +- **`examples/staging.yaml`** - Staging environment configuration +- **`examples/development.yaml`** - Development environment configuration + +### 2. Updated GitHub Actions Workflow + +The `.github/workflows/docker-build.yml` workflow now includes: + +#### New Job: `validate-helm` +- Runs Helm linting on the chart +- Validates chart templates for syntax errors +- Executes on every push and pull request + +#### New Job: `package-helm` +- Packages the Helm chart into `.tgz` files +- Generates Helm repository index +- Uploads chart packages as GitHub Actions artifacts +- Creates GitHub releases for version tags with Helm charts + +#### Improved Workflow +- Workflow renamed to: **Docker Multi-Arch Build & Helm Release** +- Better organization with dedicated jobs for Helm operations +- Automatic Helm chart release on version tags (v* format) + +### 3. Documentation + +#### Updated `README.md` +- Added Kubernetes deployment section +- Included Helm chart quick-start examples +- Updated CI/CD pipeline description +- Added link to DEPLOYMENT.md guide + +#### New `DEPLOYMENT.md` +Comprehensive deployment guide including: +- Prerequisites and quick start +- Installation instructions +- Configuration reference table +- Multiple deployment examples: + - Development environment + - Staging environment + - Production environment + - Custom configuration +- Health checks and monitoring +- Scaling and autoscaling +- Troubleshooting guide +- Advanced configuration options +- Best practices and resource recommendations + +## Key Features + +### Helm Chart Features +✅ Multi-environment support (dev, staging, prod) +✅ Configurable replicas and autoscaling +✅ Optional Ingress support with TLS +✅ Health checks (liveness and readiness probes) +✅ Resource requests and limits +✅ Pod security context +✅ Service account management +✅ Node selectors, tolerations, and affinity +✅ Environment variable configuration +✅ Horizontal Pod Autoscaler support + +### CI/CD Pipeline Features +✅ Automatic Helm chart validation +✅ Multi-architecture Docker builds (amd64, arm64) +✅ Helm chart packaging and artifact upload +✅ Automatic release creation on version tags +✅ Helm repository index generation + +## File Structure + +``` +playwright-proxy/ +├── helm/ +│ └── playwright-proxy/ +│ ├── Chart.yaml +│ ├── values.yaml +│ ├── README.md +│ ├── .helmignore +│ ├── templates/ +│ │ ├── _helpers.tpl +│ │ ├── deployment.yaml +│ │ ├── service.yaml +│ │ ├── ingress.yaml +│ │ ├── hpa.yaml +│ │ └── serviceaccount.yaml +│ └── examples/ +│ ├── production.yaml +│ ├── staging.yaml +│ └── development.yaml +├── .github/ +│ └── workflows/ +│ └── docker-build.yml (updated) +├── README.md (updated) +└── DEPLOYMENT.md (new) +``` + +## Usage Examples + +### Quick Installation +```bash +helm install playwright-proxy ./helm/playwright-proxy +``` + +### Development Environment +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --values ./helm/playwright-proxy/examples/development.yaml +``` + +### Production with Autoscaling and Ingress +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --values ./helm/playwright-proxy/examples/production.yaml +``` + +### Custom Configuration +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + --set replicaCount=5 \ + --set ingress.enabled=true \ + --set ingress.hosts[0].host=proxy.example.com +``` + +## Build Pipeline + +### Workflow Jobs + +1. **validate-helm** (runs on all events) + - Lints Helm chart syntax + - Validates template rendering + - Fails fast on any Helm issues + +2. **build** (runs on all events) + - Builds and pushes Docker images + - Supports multi-architecture builds + - Uses GitHub Container Registry (GHCR) + +3. **package-helm** (depends on validate-helm) + - Packages Helm chart into release artifacts + - Uploads to GitHub Actions artifacts + - Creates releases on version tags + +### Trigger Conditions + +- **Push to main**: Validates Helm chart, builds Docker image +- **Pull requests**: Validates Helm chart only +- **Version tags** (v*): Full pipeline + releases Helm chart + +## Next Steps + +1. **Test locally**: `helm template` and `helm lint` commands +2. **Deploy to dev**: Use development example values +3. **Scale to production**: Use production example values +4. **Monitor**: Check pod status and logs +5. **Update**: Modify values and run `helm upgrade` + +## References + +- [Helm Documentation](https://helm.sh/docs/) +- [Kubernetes Documentation](https://kubernetes.io/docs/) +- [DEPLOYMENT.md](./DEPLOYMENT.md) - Comprehensive deployment guide +- [Helm Chart README](./helm/playwright-proxy/README.md) + +## Support + +For issues or questions about the Helm chart: +1. Review the [DEPLOYMENT.md](./DEPLOYMENT.md) troubleshooting section +2. Check the [Helm Chart README](./helm/playwright-proxy/README.md) +3. Open an issue on [GitHub](https://github.com/Henkhogan/playwright-proxy/issues) diff --git a/HELM_SETUP_COMPLETE.md b/HELM_SETUP_COMPLETE.md new file mode 100644 index 0000000..87b97fc --- /dev/null +++ b/HELM_SETUP_COMPLETE.md @@ -0,0 +1,317 @@ +# Helm Chart and Build Pipeline Integration - Complete Summary + +## Overview + +This project now includes a production-ready Helm chart and an enhanced GitHub Actions build pipeline that packages and releases Helm charts automatically. This enables easy Kubernetes deployment with customizable configurations for development, staging, and production environments. + +## What's New + +### 📦 Helm Chart Structure + +The complete Helm chart is located in `helm/playwright-proxy/` with the following components: + +``` +helm/playwright-proxy/ +├── Chart.yaml # Chart metadata and version +├── values.yaml # Default configuration values +├── README.md # Helm chart documentation +├── .helmignore # Files to ignore during packaging +├── templates/ +│ ├── _helpers.tpl # Template helper functions +│ ├── deployment.yaml # Kubernetes Deployment resource +│ ├── service.yaml # Kubernetes Service resource +│ ├── ingress.yaml # Optional Ingress resource +│ ├── hpa.yaml # Optional Horizontal Pod Autoscaler +│ └── serviceaccount.yaml # Kubernetes ServiceAccount +└── examples/ + ├── production.yaml # Production environment values + ├── staging.yaml # Staging environment values + └── development.yaml # Development environment values +``` + +### 🔧 Build Pipeline Enhancements + +The GitHub Actions workflow (`.github/workflows/docker-build.yml`) now includes: + +#### New Jobs: +1. **validate-helm** - Validates Helm chart syntax on every push/PR +2. **package-helm** - Packages and releases Helm charts + +#### Features: +- ✅ Helm chart linting and validation +- ✅ Automatic Helm chart packaging +- ✅ GitHub Actions artifact uploads +- ✅ Automated GitHub releases for version tags +- ✅ Helm repository index generation +- ✅ Multi-architecture Docker builds (amd64, arm64) + +### 📚 Documentation Files + +1. **DEPLOYMENT.md** - Comprehensive Kubernetes deployment guide + - Prerequisites and quick start + - Installation methods + - Configuration reference + - Multiple deployment examples + - Monitoring and scaling + - Troubleshooting guide + +2. **HELM_INTEGRATION.md** - Helm integration overview + - Features summary + - File structure + - Usage examples + - Build pipeline details + +3. **Updated README.md** + - Added Kubernetes deployment section + - Helm chart quick-start examples + - Updated CI/CD pipeline description + +4. **helm/playwright-proxy/README.md** - Helm chart documentation + - Chart parameters table + - Installation examples + - Configuration guide + +### 🛠️ Utility Scripts + +Helper scripts in `scripts/`: + +1. **scripts/validate-helm.sh** - Local Helm chart validation + - Lints the chart + - Validates templates + - Checks for issues before committing + +2. **scripts/package-helm.sh** - Local Helm chart packaging + - Packages the chart + - Optionally generates repository index + - Useful for local testing + +## Quick Start + +### Installation + +```bash +# Basic installation with default values +helm install playwright-proxy ./helm/playwright-proxy + +# Development environment +helm install playwright-proxy ./helm/playwright-proxy \ + --values ./helm/playwright-proxy/examples/development.yaml + +# Production with autoscaling and ingress +helm install playwright-proxy ./helm/playwright-proxy \ + --values ./helm/playwright-proxy/examples/production.yaml + +# Custom configuration +helm install playwright-proxy ./helm/playwright-proxy \ + --set replicaCount=3 \ + --set autoscaling.enabled=true \ + --set ingress.enabled=true +``` + +### Validation + +```bash +# Validate Helm chart locally +./scripts/validate-helm.sh + +# Package Helm chart +./scripts/package-helm.sh + +# Lint and template +helm lint ./helm/playwright-proxy +helm template playwright-proxy ./helm/playwright-proxy +``` + +## Key Features + +### Helm Chart Features +- 🎯 Multi-environment support (dev, staging, prod) +- 📊 Configurable scaling and autoscaling +- 🌐 Optional Ingress with TLS support +- ❤️ Liveness and readiness health checks +- 🛡️ Security context and RBAC support +- 🔄 Horizontal Pod Autoscaler (HPA) with CPU/memory targets +- 📍 Node affinity and pod anti-affinity rules +- 🔧 Fully customizable via values.yaml +- 📝 Comprehensive documentation and examples + +### Build Pipeline Features +- ✅ Automatic Helm validation on every commit +- 📦 Helm chart packaging and artifact storage +- 🏷️ Version tag support for releases +- 🐳 Multi-architecture Docker builds +- 📊 Container registry caching +- 🔐 GitHub Container Registry (GHCR) integration +- 🚀 Automated GitHub release creation + +## Configuration Reference + +### Core Parameters +| Parameter | Default | Purpose | +|-----------|---------|---------| +| `replicaCount` | 2 | Number of Pod replicas | +| `image.repository` | `henkhogan/playwright-proxy` | Container image | +| `image.tag` | `latest` | Image version tag | +| `service.port` | 8000 | Service port | +| `service.type` | `ClusterIP` | Service type | + +### Autoscaling +| Parameter | Default | Purpose | +|-----------|---------|---------| +| `autoscaling.enabled` | false | Enable HPA | +| `autoscaling.minReplicas` | 2 | Minimum replicas | +| `autoscaling.maxReplicas` | 10 | Maximum replicas | +| `autoscaling.targetCPUUtilizationPercentage` | 80 | CPU threshold | +| `autoscaling.targetMemoryUtilizationPercentage` | 80 | Memory threshold | + +### Resources +| Parameter | Default | Purpose | +|-----------|---------|---------| +| `resources.requests.cpu` | 500m | CPU request | +| `resources.requests.memory` | 512Mi | Memory request | +| `resources.limits.cpu` | 1000m | CPU limit | +| `resources.limits.memory` | 1024Mi | Memory limit | + +### Ingress +| Parameter | Default | Purpose | +|-----------|---------|---------| +| `ingress.enabled` | false | Enable Ingress | +| `ingress.className` | "" | Ingress controller class | +| `ingress.hosts[0].host` | `playwright-proxy.local` | Hostname | +| `ingress.tls` | [] | TLS configuration | + +See `helm/playwright-proxy/values.yaml` for all available parameters. + +## Environment-Specific Examples + +### Development (Minimal Resources) +- Single replica +- NodePort service +- No autoscaling +- Minimal CPU/memory requests + +Usage: +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + -f ./helm/playwright-proxy/examples/development.yaml +``` + +### Staging (Balanced) +- 2 replicas +- ClusterIP service +- Ingress enabled with TLS +- HPA with 2-10 replicas +- Moderate resource limits + +Usage: +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + -f ./helm/playwright-proxy/examples/staging.yaml +``` + +### Production (High Availability) +- 3 replicas +- ClusterIP service +- Ingress with TLS +- HPA with 3-20 replicas +- Higher resource limits +- Pod anti-affinity +- Node affinity rules +- Comprehensive monitoring + +Usage: +```bash +helm install playwright-proxy ./helm/playwright-proxy \ + -f ./helm/playwright-proxy/examples/production.yaml +``` + +## CI/CD Pipeline Workflow + +### On Push to Main +1. ✅ Validates Helm chart +2. 🐳 Builds and pushes Docker image (multi-arch) +3. 📦 Packages Helm chart +4. 📤 Uploads artifacts + +### On Pull Request +1. ✅ Validates Helm chart +2. 🐳 Builds Docker image (no push) + +### On Version Tag (v*) +1. ✅ Validates Helm chart +2. 🐳 Builds and pushes Docker image +3. 📦 Packages Helm chart +4. 🏷️ Creates GitHub Release with Helm chart +5. 📤 Uploads Helm chart as release asset + +## File Changes Summary + +### New Files +- `helm/playwright-proxy/` (complete Helm chart) +- `helm/playwright-proxy/Chart.yaml` +- `helm/playwright-proxy/values.yaml` +- `helm/playwright-proxy/README.md` +- `helm/playwright-proxy/.helmignore` +- `helm/playwright-proxy/templates/` (6 template files) +- `helm/playwright-proxy/examples/` (3 example files) +- `DEPLOYMENT.md` (comprehensive deployment guide) +- `HELM_INTEGRATION.md` (integration overview) +- `scripts/validate-helm.sh` (validation script) +- `scripts/package-helm.sh` (packaging script) + +### Modified Files +- `.github/workflows/docker-build.yml` (enhanced with Helm jobs) +- `README.md` (updated with Helm/K8s information) + +## Next Steps + +1. **Test Locally** + ```bash + ./scripts/validate-helm.sh + helm template playwright-proxy ./helm/playwright-proxy + ``` + +2. **Deploy to Kubernetes** + ```bash + helm install playwright-proxy ./helm/playwright-proxy + ``` + +3. **Monitor the Deployment** + ```bash + kubectl get pods -l app.kubernetes.io/name=playwright-proxy + kubectl logs -l app.kubernetes.io/name=playwright-proxy + ``` + +4. **Access the Service** + ```bash + kubectl port-forward svc/playwright-proxy 8000:8000 + ``` + +5. **Upgrade Configuration** + ```bash + helm upgrade playwright-proxy ./helm/playwright-proxy \ + --set replicaCount=5 \ + --set autoscaling.enabled=true + ``` + +## Resources + +- [Helm Documentation](https://helm.sh/docs/) +- [Kubernetes Documentation](https://kubernetes.io/docs/) +- [Chart Development Guide](https://helm.sh/docs/chart_template_guide/) +- Full deployment guide: [DEPLOYMENT.md](./DEPLOYMENT.md) +- Helm chart docs: [helm/playwright-proxy/README.md](./helm/playwright-proxy/README.md) + +## Support + +For questions or issues: +1. Check [DEPLOYMENT.md](./DEPLOYMENT.md) troubleshooting section +2. Review [Helm Integration Guide](./HELM_INTEGRATION.md) +3. Consult [Helm Chart README](./helm/playwright-proxy/README.md) +4. Open an issue on [GitHub](https://github.com/Henkhogan/playwright-proxy/issues) + +--- + +**Last Updated:** June 22, 2026 +**Helm Chart Version:** 0.1.0 +**Application Version:** 0.1.0 diff --git a/README.md b/README.md index c0babbd..e479d81 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,13 @@ Any specific arguments are supposed to be passed as headers prefixed with "playw - **Configurable port**: Use command-line arguments or environment variables - **Extended timeouts**: Handles slow-loading sites with 60-second navigation timeout - **Realistic browser**: Uses a Chrome user-agent to avoid being blocked by anti-bot systems +- **Kubernetes-ready**: Includes Helm chart for easy Kubernetes deployment ## Prerequisites - Docker (for containerized deployment) - Rust 1.96+ (for local development) +- Kubernetes 1.19+ and Helm 3.0+ (for Kubernetes deployment) ## Building @@ -48,6 +50,50 @@ Docker execution: docker run -p 9000:9000 playwright-proxy 9000 ``` +### Kubernetes deployment with Helm + +#### Quick start + +```bash +# Install with default values +helm install playwright-proxy ./helm/playwright-proxy + +# Upgrade existing release +helm upgrade playwright-proxy ./helm/playwright-proxy + +# Uninstall +helm uninstall playwright-proxy +``` + +#### Custom configuration + +```bash +# Install with custom replica count and autoscaling +helm install playwright-proxy ./helm/playwright-proxy \ + --set replicaCount=3 \ + --set autoscaling.enabled=true \ + --set autoscaling.minReplicas=2 \ + --set autoscaling.maxReplicas=10 +``` + +```bash +# Install with Ingress enabled +helm install playwright-proxy ./helm/playwright-proxy \ + --set ingress.enabled=true \ + --set ingress.className=nginx \ + --set ingress.hosts[0].host=proxy.example.com \ + --set ingress.hosts[0].paths[0].path=/ \ + --set ingress.hosts[0].paths[0].pathType=Prefix +``` + +```bash +# Install with custom image tag +helm install playwright-proxy ./helm/playwright-proxy \ + --set image.tag=v0.2.0 +``` + +For more Helm configuration options, see [helm/playwright-proxy/README.md](helm/playwright-proxy/README.md). + ### Making requests Use as an HTTP proxy with curl: @@ -104,4 +150,19 @@ curl http://localhost:9000/https://example.com - **Performance**: Each request creates a new browser context, so the proxy is slower than traditional proxies - **Resource usage**: Requires significant memory and CPU for browser automation - **Anti-bot detection**: Some sites (like Instagram) actively block automated access despite realistic user-agents -- **JavaScript complexity**: May not handle extremely complex or obfuscated JavaScript perfectly \ No newline at end of file +- **JavaScript complexity**: May not handle extremely complex or obfuscated JavaScript perfectly + +## CI/CD Pipeline + +The project includes a GitHub Actions workflow that: + +1. **Validates** the Helm chart on every push and pull request +2. **Builds and pushes** Docker images to GitHub Container Registry (GHCR) +3. **Packages** the Helm chart and creates releases on version tags +4. **Supports** multi-architecture builds (linux/amd64, linux/arm64) + +### Workflow triggers + +- **Push to main**: Builds Docker image and validates Helm chart +- **Pull requests**: Validates Helm chart and Rust code +- **Version tags** (`v*`): Creates GitHub releases with Helm chart packages diff --git a/helm/playwright-proxy/.helmignore b/helm/playwright-proxy/.helmignore new file mode 100644 index 0000000..451d5bb --- /dev/null +++ b/helm/playwright-proxy/.helmignore @@ -0,0 +1,25 @@ +# Patterns to ignore when building packages. +# This supports shell glob patterns, relative paths, and negated patterns. + +# commonly ignored files/folders +.DS_Store +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +*.swp +*.swo +*~ +.idea/ +*.iml +.vscode/ + +# chart dependencies +**/charts/*.tgz + +# Helm-specific +*.tgz +Chart.lock diff --git a/helm/playwright-proxy/Chart.yaml b/helm/playwright-proxy/Chart.yaml new file mode 100644 index 0000000..124f358 --- /dev/null +++ b/helm/playwright-proxy/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +name: playwright-proxy +description: A web proxy that renders websites with Playwright and returns rendered HTML +type: application +version: 0.1.0 +appVersion: "0.1.0" +home: https://github.com/Henkhogan/playwright-proxy +sources: + - https://github.com/Henkhogan/playwright-proxy +maintainers: + - name: Henkhogan +keywords: + - playwright + - proxy + - web-rendering + - javascript +icon: https://playwright.dev/img/playwright-logo.svg diff --git a/helm/playwright-proxy/README.md b/helm/playwright-proxy/README.md new file mode 100644 index 0000000..90ce7b1 --- /dev/null +++ b/helm/playwright-proxy/README.md @@ -0,0 +1,96 @@ +# Playwright Proxy Helm Chart + +This Helm chart deploys the Playwright Proxy application to a Kubernetes cluster. + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ + +## Installation + +### Add the Helm repository (if applicable) + +```bash +helm repo add playwright-proxy https://example.com/charts +helm repo update +``` + +### Install the chart with default values + +```bash +helm install my-release ./helm/playwright-proxy +``` + +### Install with custom values + +```bash +helm install my-release ./helm/playwright-proxy -f values.yaml +``` + +## Configuration + +The following table lists the configurable parameters of the Playwright Proxy chart and their default values: + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `replicaCount` | Number of replicas | `2` | +| `image.registry` | Image registry | `ghcr.io` | +| `image.repository` | Image repository | `henkhogan/playwright-proxy` | +| `image.tag` | Image tag | `latest` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.port` | Kubernetes service port | `8000` | +| `ingress.enabled` | Enable ingress | `false` | +| `autoscaling.enabled` | Enable HPA | `false` | +| `autoscaling.minReplicas` | Minimum replicas for HPA | `2` | +| `autoscaling.maxReplicas` | Maximum replicas for HPA | `10` | +| `resources.limits.cpu` | CPU limit | `1000m` | +| `resources.limits.memory` | Memory limit | `1024Mi` | +| `resources.requests.cpu` | CPU request | `500m` | +| `resources.requests.memory` | Memory request | `512Mi` | + +## Examples + +### Deploy with autoscaling enabled + +```bash +helm install my-release ./helm/playwright-proxy \ + --set autoscaling.enabled=true \ + --set autoscaling.minReplicas=2 \ + --set autoscaling.maxReplicas=10 +``` + +### Deploy with ingress + +```bash +helm install my-release ./helm/playwright-proxy \ + --set ingress.enabled=true \ + --set ingress.className=nginx \ + --set ingress.hosts[0].host=playwright-proxy.example.com \ + --set ingress.hosts[0].paths[0].path=/ \ + --set ingress.hosts[0].paths[0].pathType=Prefix +``` + +### Deploy with custom image tag + +```bash +helm install my-release ./helm/playwright-proxy \ + --set image.tag=v0.2.0 +``` + +## Uninstall + +```bash +helm uninstall my-release +``` + +## Upgrade + +```bash +helm upgrade my-release ./helm/playwright-proxy +``` + +## License + +MIT diff --git a/helm/playwright-proxy/examples/development.yaml b/helm/playwright-proxy/examples/development.yaml new file mode 100644 index 0000000..c4f913b --- /dev/null +++ b/helm/playwright-proxy/examples/development.yaml @@ -0,0 +1,35 @@ +# Example: Development configuration with minimal resources +# Usage: helm install playwright-proxy ./helm/playwright-proxy -f examples/development.yaml + +replicaCount: 1 + +image: + registry: ghcr.io + repository: henkhogan/playwright-proxy + pullPolicy: Always + tag: main + +service: + type: NodePort + port: 8000 + targetPort: 8000 + +resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 250m + memory: 256Mi + +autoscaling: + enabled: false + +env: + PROXY_PORT: "8000" + +livenessProbe: + enabled: false + +readinessProbe: + enabled: false diff --git a/helm/playwright-proxy/examples/production.yaml b/helm/playwright-proxy/examples/production.yaml new file mode 100644 index 0000000..c1f3bff --- /dev/null +++ b/helm/playwright-proxy/examples/production.yaml @@ -0,0 +1,93 @@ +# Example: Production-ready configuration with autoscaling and ingress +# Usage: helm install playwright-proxy ./helm/playwright-proxy -f examples/production.yaml + +replicaCount: 3 + +image: + registry: ghcr.io + repository: henkhogan/playwright-proxy + pullPolicy: IfNotPresent + tag: latest + +service: + type: ClusterIP + port: 8000 + targetPort: 8000 + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "8000" + +ingress: + enabled: true + className: nginx + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + hosts: + - host: playwright-proxy.example.com + paths: + - path: / + pathType: Prefix + tls: + - secretName: playwright-proxy-tls + hosts: + - playwright-proxy.example.com + +resources: + limits: + cpu: 2000m + memory: 2048Mi + requests: + cpu: 1000m + memory: 1024Mi + +autoscaling: + enabled: true + minReplicas: 3 + maxReplicas: 20 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 80 + +nodeSelector: + workload: compute-intensive + +tolerations: + - key: "compute-intensive" + operator: "Equal" + value: "true" + effect: "NoSchedule" + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - playwright-proxy + topologyKey: kubernetes.io/hostname + +env: + PROXY_PORT: "8000" + +livenessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 60 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + +readinessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 diff --git a/helm/playwright-proxy/examples/staging.yaml b/helm/playwright-proxy/examples/staging.yaml new file mode 100644 index 0000000..af1bfa2 --- /dev/null +++ b/helm/playwright-proxy/examples/staging.yaml @@ -0,0 +1,68 @@ +# Example: Staging configuration with moderate resources +# Usage: helm install playwright-proxy ./helm/playwright-proxy -f examples/staging.yaml + +replicaCount: 2 + +image: + registry: ghcr.io + repository: henkhogan/playwright-proxy + pullPolicy: IfNotPresent + tag: latest + +service: + type: ClusterIP + port: 8000 + targetPort: 8000 + +ingress: + enabled: true + className: nginx + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-staging" + hosts: + - host: playwright-proxy-staging.example.com + paths: + - path: / + pathType: Prefix + tls: + - secretName: playwright-proxy-staging-tls + hosts: + - playwright-proxy-staging.example.com + +resources: + limits: + cpu: 1500m + memory: 1536Mi + requests: + cpu: 750m + memory: 768Mi + +autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 10 + targetCPUUtilizationPercentage: 75 + targetMemoryUtilizationPercentage: 80 + +env: + PROXY_PORT: "8000" + +livenessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + +readinessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 diff --git a/helm/playwright-proxy/templates/_helpers.tpl b/helm/playwright-proxy/templates/_helpers.tpl new file mode 100644 index 0000000..c1eb1e7 --- /dev/null +++ b/helm/playwright-proxy/templates/_helpers.tpl @@ -0,0 +1,60 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "playwright-proxy.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "playwright-proxy.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "playwright-proxy.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "playwright-proxy.labels" -}} +helm.sh/chart: {{ include "playwright-proxy.chart" . }} +{{ include "playwright-proxy.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "playwright-proxy.selectorLabels" -}} +app.kubernetes.io/name: {{ include "playwright-proxy.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "playwright-proxy.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "playwright-proxy.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/playwright-proxy/templates/deployment.yaml b/helm/playwright-proxy/templates/deployment.yaml new file mode 100644 index 0000000..51ec717 --- /dev/null +++ b/helm/playwright-proxy/templates/deployment.yaml @@ -0,0 +1,73 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "playwright-proxy.fullname" . }} + labels: + {{- include "playwright-proxy.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "playwright-proxy.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "playwright-proxy.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "playwright-proxy.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.targetPort }} + protocol: TCP + {{- with .Values.env }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/playwright-proxy/templates/hpa.yaml b/helm/playwright-proxy/templates/hpa.yaml new file mode 100644 index 0000000..dacfa41 --- /dev/null +++ b/helm/playwright-proxy/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "playwright-proxy.fullname" . }} + labels: + {{- include "playwright-proxy.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "playwright-proxy.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/playwright-proxy/templates/httproute.yaml b/helm/playwright-proxy/templates/httproute.yaml new file mode 100644 index 0000000..fd03e35 --- /dev/null +++ b/helm/playwright-proxy/templates/httproute.yaml @@ -0,0 +1,32 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ include "playwright-proxy.fullname" . }} + labels: + {{- include "playwright-proxy.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + - name: {{ .Values.ingress.gatewayName }} + namespace: {{ .Values.ingress.gatewayNamespace }} + {{- if .Values.ingress.sectionName }} + sectionName: {{ .Values.ingress.sectionName }} + {{- end }} + {{- with .Values.ingress.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: {{ include "playwright-proxy.fullname" . }} + port: {{ .Values.service.port }} + weight: 100 +{{- end }} diff --git a/helm/playwright-proxy/templates/ingress.yaml b/helm/playwright-proxy/templates/ingress.yaml new file mode 100644 index 0000000..5f642e1 --- /dev/null +++ b/helm/playwright-proxy/templates/ingress.yaml @@ -0,0 +1,41 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "playwright-proxy.fullname" . }} + labels: + {{- include "playwright-proxy.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "playwright-proxy.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/playwright-proxy/templates/service.yaml b/helm/playwright-proxy/templates/service.yaml new file mode 100644 index 0000000..4d7e7d2 --- /dev/null +++ b/helm/playwright-proxy/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "playwright-proxy.fullname" . }} + labels: + {{- include "playwright-proxy.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "playwright-proxy.selectorLabels" . | nindent 4 }} diff --git a/helm/playwright-proxy/templates/serviceaccount.yaml b/helm/playwright-proxy/templates/serviceaccount.yaml new file mode 100644 index 0000000..ff5465d --- /dev/null +++ b/helm/playwright-proxy/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "playwright-proxy.serviceAccountName" . }} + labels: + {{- include "playwright-proxy.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm/playwright-proxy/values.yaml b/helm/playwright-proxy/values.yaml new file mode 100644 index 0000000..7e4aa93 --- /dev/null +++ b/helm/playwright-proxy/values.yaml @@ -0,0 +1,121 @@ +# Default values for playwright-proxy +# This is a YAML-formatted file. +# Declare variables to be passed into templates. + +replicaCount: 1 + +image: + registry: ghcr.io + repository: henkhogan/playwright-proxy + pullPolicy: IfNotPresent + tag: latest + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + create: true + annotations: {} + name: "" + +podAnnotations: {} + +podSecurityContext: + runAsNonRoot: false + fsGroup: 0 + +securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: false + allowPrivilegeEscalation: true + +service: + type: ClusterIP + port: 8000 + targetPort: 8000 + annotations: {} + +# Gateway API ingress configuration +ingress: + enabled: false + # Gateway reference + gatewayName: traefik + gatewayNamespace: traefik + sectionName: "" + annotations: {} + # Hostnames for the HTTPRoute + hostnames: + - playwright-proxy.lan + # TLS configuration (if needed) + # tls: + # - secretName: playwright-proxy-tls + # hosts: + # - playwright-proxy.lan + +resources: + limits: + cpu: 1000m + memory: 1024Mi + requests: + cpu: 500m + memory: 512Mi + +autoscaling: + enabled: false + minReplicas: 2 + maxReplicas: 10 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + +nodeSelector: + topology/location: home + +tolerations: [] + +affinity: {} + +# Environment variables (list format) +env: + - name: PROXY_PORT + value: "8000" + +# Additional volumes (e.g., for custom CA bundle) +volumes: [] +# Example for custom CA: +# - name: custom-ca-bundle +# configMap: +# name: custom-ca-bundle +# items: +# - key: custom-ca-bundle.crt +# path: custom-ca-bundle.crt + +# Additional volume mounts +volumeMounts: [] +# Example for custom CA: +# - name: custom-ca-bundle +# mountPath: /etc/ssl/certs/custom-ca-bundle.crt +# subPath: custom-ca-bundle.crt + +# Liveliness and readiness probes +livenessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + +readinessProbe: + enabled: true + httpGet: + path: /health + port: 8000 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 diff --git a/scripts/package-helm.sh b/scripts/package-helm.sh new file mode 100644 index 0000000..da80a39 --- /dev/null +++ b/scripts/package-helm.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Package Helm Chart Script +# This script packages the Helm chart locally + +set -e + +echo "📦 Packaging Playwright Proxy Helm Chart..." +echo "" + +CHART_DIR="./helm/playwright-proxy" +OUTPUT_DIR="./helm-packages" + +if [ ! -d "$CHART_DIR" ]; then + echo "❌ Chart directory not found: $CHART_DIR" + exit 1 +fi + +# Check if helm is installed +if ! command -v helm &> /dev/null; then + echo "❌ Helm is not installed. Please install Helm to continue." + exit 1 +fi + +# Create output directory +mkdir -p "$OUTPUT_DIR" + +# Package the chart +echo "📦 Packaging chart..." +if helm package "$CHART_DIR" -d "$OUTPUT_DIR"; then + echo "✅ Chart packaged successfully" +else + echo "❌ Chart packaging failed" + exit 1 +fi +echo "" + +# List packaged files +echo "📁 Packaged files in $OUTPUT_DIR:" +ls -lh "$OUTPUT_DIR" +echo "" + +# Generate index (optional) +if [ "$1" = "--index" ]; then + echo "📋 Generating Helm repository index..." + if helm repo index "$OUTPUT_DIR"; then + echo "✅ Repository index generated" + else + echo "❌ Repository index generation failed" + exit 1 + fi + echo "" +fi + +echo "✨ Packaging complete!" +echo "" +echo "📝 To use the packaged chart:" +echo " helm install my-release $OUTPUT_DIR/*.tgz" diff --git a/scripts/validate-helm.sh b/scripts/validate-helm.sh new file mode 100644 index 0000000..1fa467a --- /dev/null +++ b/scripts/validate-helm.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Helm Chart Validation Script +# This script can be run locally to validate the Helm chart before committing + +set -e + +echo "🔍 Validating Playwright Proxy Helm Chart..." +echo "" + +CHART_DIR="./helm/playwright-proxy" + +if [ ! -d "$CHART_DIR" ]; then + echo "❌ Chart directory not found: $CHART_DIR" + exit 1 +fi + +# Check if helm is installed +if ! command -v helm &> /dev/null; then + echo "❌ Helm is not installed. Please install Helm to continue." + echo " See: https://helm.sh/docs/intro/install/" + exit 1 +fi + +echo "✅ Helm found: $(helm version --short)" +echo "" + +# Lint the chart +echo "🔎 Linting chart..." +if helm lint "$CHART_DIR"; then + echo "✅ Chart linting passed" +else + echo "❌ Chart linting failed" + exit 1 +fi +echo "" + +# Template the chart +echo "📋 Templating chart..." +if helm template playwright-proxy "$CHART_DIR" > /tmp/chart-template.yaml; then + echo "✅ Chart templating passed" +else + echo "❌ Chart templating failed" + exit 1 +fi +echo "" + +# Check if values.yaml is valid YAML +echo "🔎 Validating values.yaml..." +if helm show values "$CHART_DIR" > /dev/null; then + echo "✅ values.yaml is valid" +else + echo "❌ values.yaml validation failed" + exit 1 +fi +echo "" + +# Check Chart.yaml +echo "🔎 Validating Chart.yaml..." +if [ -f "$CHART_DIR/Chart.yaml" ]; then + echo "✅ Chart.yaml found" +else + echo "❌ Chart.yaml not found" + exit 1 +fi +echo "" + +# List templates +echo "📁 Chart templates:" +ls -la "$CHART_DIR/templates/" +echo "" + +# Show chart information +echo "📊 Chart information:" +helm show chart "$CHART_DIR" +echo "" + +echo "✨ All validations passed!" +exit 0 diff --git a/src/main.rs b/src/main.rs index bec2285..11b3938 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,134 +1,194 @@ -use axum::{ - Router, Extension, - http::{StatusCode, HeaderMap, Uri}, - response::IntoResponse, -}; -use playwright::Playwright; +use tokio::net::{TcpListener, TcpStream}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; use std::net::SocketAddr; +use std::io; use std::sync::Arc; -use std::collections::HashMap; -use std::env; +use rcgen::generate_simple_self_signed; +use tokio_rustls::{TlsAcceptor, rustls::ServerConfig}; +use tokio_rustls::rustls::pki_types::CertificateDer; +use playwright::Playwright; + +// Global state for Playwright +lazy_static::lazy_static! { + static ref PLAYWRIGHT: tokio::sync::Mutex> = tokio::sync::Mutex::new(None); +} -// Global shared state containing our launched browser instance -struct AppState { - browser: playwright::api::Browser, +// Generate a wildcard certificate for intercepting HTTPS - returns (cert_der, key_der) +fn generate_wildcard_cert() -> (Vec, Vec) { + let cert_key = generate_simple_self_signed(vec!["*.example.com".to_string()]) + .expect("Failed to generate certificate"); + + // Get DER format directly + let cert_der = cert_key.cert.der().to_vec(); + let key_der = cert_key.key_pair.serialize_der(); + + (cert_der, key_der) } -async fn proxy_handler( - Extension(state): Extension>, - headers: HeaderMap, - uri: Uri, -) -> Result { - // Extract the target URL from the request - // In HTTP proxy mode, the request line contains the full URL - // e.g., GET http://www.google.com/ HTTP/1.1 - let uri_str = uri.to_string(); - - // Remove any leading slash and decode the URL - let path_str = if uri_str.starts_with("/") { - &uri_str[1..] - } else { - &uri_str - }; - - let target_url = if path_str.starts_with("http://") || path_str.starts_with("https://") { - // Already a full URL - path_str.to_string() - } else if !path_str.is_empty() { - // Assume it's a domain, add https:// prefix - format!("https://{}", path_str) - } else { - return Err((StatusCode::BAD_REQUEST, "Invalid target URL".to_string())); - }; +// Parse HTTP request line +fn parse_http_request(buffer: &[u8]) -> Option<(String, String, String)> { + let request = String::from_utf8_lossy(buffer); + let lines: Vec<&str> = request.lines().collect(); + if lines.is_empty() { + return None; + } + + let parts: Vec<&str> = lines[0].split_whitespace().collect(); + if parts.len() < 3 { + return None; + } + + Some(( + parts[0].to_string(), // method + parts[1].to_string(), // path + parts[2].to_string(), // version + )) +} - // Extract playwright-prefixed headers and parse them - let mut _playwright_options = HashMap::new(); - for (key, value) in headers.iter() { - if let Some(key_str) = key.as_str().strip_prefix("playwright-") { - if let Ok(value_str) = value.to_str() { - _playwright_options.insert(key_str.to_string(), value_str.to_string()); +async fn handle_client(mut client_stream: TcpStream, cert_pem: Vec, key_pem: Vec) -> io::Result<()> { + // Read the first line to determine if it's a CONNECT request + let mut buffer = vec![0; 4096]; + let n = client_stream.read(&mut buffer).await?; + + if let Some((method, target, _)) = parse_http_request(&buffer[..n]) { + if method == "CONNECT" { + // Parse the host and port from CONNECT request + let (host, _port) = if let Some(colon_pos) = target.rfind(':') { + (target[..colon_pos].to_string(), target[colon_pos + 1..].parse::().unwrap_or(443)) + } else { + (target.clone(), 443) + }; + + // Send 200 Connection Established response + let response = "HTTP/1.1 200 Connection Established\r\n\r\n"; + client_stream.write_all(response.as_bytes()).await?; + + // Set up TLS with the generated certificate (already in DER format) + let cert_der = CertificateDer::from(cert_pem); + + // key_pem is already in DER format from generate_wildcard_cert + let key_der = rustls::pki_types::PrivateKeyDer::Pkcs8( + rustls::pki_types::PrivatePkcs8KeyDer::from(key_pem) + ); + + let config = ServerConfig::builder() + .with_no_client_auth() + .with_single_cert(vec![cert_der], key_der) + .expect("Failed to create TLS config"); + + let acceptor = TlsAcceptor::from(Arc::new(config)); + + // Upgrade connection to TLS + let tls_stream = acceptor.accept(client_stream).await?; + + // Now read the actual HTTP request over TLS + let (mut reader, mut writer) = tokio::io::split(tls_stream); + let mut tls_buffer = vec![0; 4096]; + let tls_n = reader.read(&mut tls_buffer).await?; + + if let Some((_, http_path, _)) = parse_http_request(&tls_buffer[..tls_n]) { + // Construct the full target URL + let target_url = if http_path.starts_with("http") { + http_path + } else { + format!("https://{}{}", host, http_path) + }; + + // Fetch and render the page with Playwright + match render_page(&target_url).await { + Ok(html) => { + let response = format!( + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\n\r\n{}", + html.len(), + html + ); + let _ = writer.write_all(response.as_bytes()).await; + } + Err(e) => { + let response = format!("HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n"); + let _ = writer.write_all(response.as_bytes()).await; + eprintln!("Rendering error: {}", e); + } + } } } } - // 1. Create a new browser context with proper headers - let mut context_builder = state.browser.context_builder(); + Ok(()) +} + +async fn render_page(url: &str) -> Result> { + // Initialize Playwright if needed + let mut pw_guard = PLAYWRIGHT.lock().await; + if pw_guard.is_none() { + let pw = Playwright::initialize().await?; + pw.prepare()?; + *pw_guard = Some(pw); + } - // Set a realistic user-agent to avoid being blocked by sites like Instagram - let user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"; - context_builder = context_builder.user_agent(user_agent); + let pw = pw_guard.as_ref().unwrap(); - let context = context_builder + // Launch browser + let browser = pw + .chromium() + .launcher() + .headless(true) + .launch() + .await?; + + // Create context and page + let context = browser.context_builder() + .user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") .build() - .await - .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to create context: {}", e)))?; + .await?; - // 2. Open a new page within that context - let page = context.new_page() - .await - .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to open page: {}", e)))?; - - // 3. Navigate to the target URL with extended timeout for sites like Instagram - page.goto_builder(&target_url) - .timeout(60000.0) // 60 second timeout + let page = context.new_page().await?; + + // Navigate to URL + page.goto_builder(url) + .timeout(60000.0) .goto() - .await - .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("Navigation failed: {}", e)))?; - - // 4. Wait for any dynamic content to load (Instagram might load content dynamically) - // Add a delay to ensure all JavaScript-rendered content is visible + .await?; + + // Wait for content to load tokio::time::sleep(tokio::time::Duration::from_secs(3)).await; - - // 5. Extract the fully executed and rendered DOM tree - let html_content = page.content() - .await - .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to fetch page source: {}", e)))?; - - // 6. Close the context (which also closes pages) to release resources - let _ = context.close().await; - - Ok(html_content) + + // Get rendered HTML + let html = page.content().await?; + + // Close context + context.close().await?; + + Ok(html) } #[tokio::main] -async fn main() { - tracing_subscriber::fmt::init(); - - // Parse port from command-line argument or environment variable, default to 8000 - let port = env::args() +async fn main() -> io::Result<()> { + // Generate wildcard certificate (in DER format) + let (cert_der, key_der) = generate_wildcard_cert(); + + // Parse port from command-line argument or environment variable, default to 9000 + let port = std::env::args() .nth(1) - .or_else(|| env::var("PROXY_PORT").ok()) + .or_else(|| std::env::var("PROXY_PORT").ok()) .and_then(|p| p.parse::().ok()) - .unwrap_or(8000); - - println!("Initializing Playwright engine..."); - // Initialize the core Playwright driver system - let playwright = Playwright::initialize().await.expect("Failed to initialize Playwright"); - - // Ensure the Chromium binaries are present - playwright.prepare().expect("Failed to install browser binaries"); - - // Launch a single background Chromium process - let browser = playwright - .chromium() - .launcher() - .headless(true) - .launch() - .await - .expect("Failed to launch Chromium instance"); - - let shared_state = Arc::new(AppState { browser }); - - // Build router to catch all requests and proxy them - let app = Router::new() - .fallback(proxy_handler) - .layer(Extension(shared_state)); + .unwrap_or(9000); let addr = SocketAddr::from(([0, 0, 0, 0], port)); - println!("Playwright proxy listening on {}", addr); - println!("Usage: http://localhost:{port}/"); - println!("Example: http://localhost:{port}/https://example.com"); + let listener = TcpListener::bind(addr).await?; + + println!("HTTPS Intercepting Proxy listening on {}", addr); + println!("Usage: curl --proxy http://localhost:{} https://example.com", port); - let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); - axum::serve(listener, app).await.unwrap(); + loop { + let (client_stream, _) = listener.accept().await?; + let cert = cert_der.clone(); + let key = key_der.clone(); + + tokio::spawn(async move { + if let Err(e) = handle_client(client_stream, cert, key).await { + eprintln!("Error handling client: {}", e); + } + }); + } } From 172499d99161dae7ba4105e12a58dec16b607047 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Jun 2026 18:07:18 +0000 Subject: [PATCH 4/6] fix: replace unsupported ** glob in .helmignore --- helm/playwright-proxy/.helmignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/playwright-proxy/.helmignore b/helm/playwright-proxy/.helmignore index 451d5bb..a134cbf 100644 --- a/helm/playwright-proxy/.helmignore +++ b/helm/playwright-proxy/.helmignore @@ -18,7 +18,7 @@ .vscode/ # chart dependencies -**/charts/*.tgz +charts/*.tgz # Helm-specific *.tgz From 5fb9e6714a8ea5cdba5d47777aced5e25f6c3a2b Mon Sep 17 00:00:00 2001 From: henkhogan Date: Thu, 25 Jun 2026 21:48:03 +0200 Subject: [PATCH 5/6] push helm to oci registry --- .github/workflows/docker-build.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index f29c951..e0da020 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -89,7 +89,7 @@ jobs: cache-to: type=registry,ref=ghcr.io/${{ steps.repo.outputs.repo }}:buildcache,mode=max package-helm: - name: Package Helm Chart + name: Package & Push Helm Chart runs-on: ubuntu-latest needs: validate-helm steps: @@ -101,11 +101,30 @@ jobs: with: version: 'latest' + - name: Convert repository name to lowercase + id: repo + run: echo "repo=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT + + - name: Login to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Package Helm chart run: | mkdir -p helm-packages helm package ./helm/playwright-proxy -d helm-packages + - name: Push Helm chart to OCI registry + if: github.event_name != 'pull_request' + run: | + for chart in helm-packages/*.tgz; do + helm push "$chart" oci://ghcr.io/${{ steps.repo.outputs.repo }} + done + - name: Generate Helm index if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: | From d057acb74b4279daf257dbe45f761ab5255b012f Mon Sep 17 00:00:00 2001 From: henkhogan Date: Thu, 25 Jun 2026 23:46:08 +0200 Subject: [PATCH 6/6] fix(helm): resolve probe schema and ingress validation errors - Fix livenessProbe/readinessProbe by excluding 'enabled' field from probe spec - Fix Ingress template to handle missing hosts array gracefully - Separate standard Ingress from Gateway API HTTPRoute configuration - Update HTTPRoute template to use correct values path (httproute.*) - Bump chart version to 0.1.1 --- helm/playwright-proxy/Chart.yaml | 2 +- .../templates/deployment.yaml | 4 ++-- .../playwright-proxy/templates/httproute.yaml | 14 +++++------ helm/playwright-proxy/templates/ingress.yaml | 2 ++ helm/playwright-proxy/values.yaml | 24 ++++++++++++------- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/helm/playwright-proxy/Chart.yaml b/helm/playwright-proxy/Chart.yaml index 124f358..be8e74f 100644 --- a/helm/playwright-proxy/Chart.yaml +++ b/helm/playwright-proxy/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: playwright-proxy description: A web proxy that renders websites with Playwright and returns rendered HTML type: application -version: 0.1.0 +version: 0.1.1 appVersion: "0.1.0" home: https://github.com/Henkhogan/playwright-proxy sources: diff --git a/helm/playwright-proxy/templates/deployment.yaml b/helm/playwright-proxy/templates/deployment.yaml index 51ec717..f0611bb 100644 --- a/helm/playwright-proxy/templates/deployment.yaml +++ b/helm/playwright-proxy/templates/deployment.yaml @@ -47,11 +47,11 @@ spec: {{- end }} {{- if .Values.livenessProbe.enabled }} livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} + {{- toYaml (omit .Values.livenessProbe "enabled") | nindent 12 }} {{- end }} {{- if .Values.readinessProbe.enabled }} readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} + {{- toYaml (omit .Values.readinessProbe "enabled") | nindent 12 }} {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} diff --git a/helm/playwright-proxy/templates/httproute.yaml b/helm/playwright-proxy/templates/httproute.yaml index fd03e35..02ea2dc 100644 --- a/helm/playwright-proxy/templates/httproute.yaml +++ b/helm/playwright-proxy/templates/httproute.yaml @@ -1,22 +1,22 @@ -{{- if .Values.ingress.enabled -}} +{{- if .Values.httproute.enabled -}} apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: {{ include "playwright-proxy.fullname" . }} labels: {{- include "playwright-proxy.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} + {{- with .Values.httproute.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} spec: parentRefs: - - name: {{ .Values.ingress.gatewayName }} - namespace: {{ .Values.ingress.gatewayNamespace }} - {{- if .Values.ingress.sectionName }} - sectionName: {{ .Values.ingress.sectionName }} + - name: {{ .Values.httproute.gatewayName }} + namespace: {{ .Values.httproute.gatewayNamespace }} + {{- if .Values.httproute.sectionName }} + sectionName: {{ .Values.httproute.sectionName }} {{- end }} - {{- with .Values.ingress.hostnames }} + {{- with .Values.httproute.hostnames }} hostnames: {{- toYaml . | nindent 4 }} {{- end }} diff --git a/helm/playwright-proxy/templates/ingress.yaml b/helm/playwright-proxy/templates/ingress.yaml index 5f642e1..fb03bca 100644 --- a/helm/playwright-proxy/templates/ingress.yaml +++ b/helm/playwright-proxy/templates/ingress.yaml @@ -23,6 +23,7 @@ spec: secretName: {{ .secretName }} {{- end }} {{- end }} + {{- if .Values.ingress.hosts }} rules: {{- range .Values.ingress.hosts }} - host: {{ .host | quote }} @@ -38,4 +39,5 @@ spec: number: {{ $.Values.service.port }} {{- end }} {{- end }} + {{- end }} {{- end }} diff --git a/helm/playwright-proxy/values.yaml b/helm/playwright-proxy/values.yaml index 7e4aa93..1790f15 100644 --- a/helm/playwright-proxy/values.yaml +++ b/helm/playwright-proxy/values.yaml @@ -38,22 +38,30 @@ service: targetPort: 8000 annotations: {} -# Gateway API ingress configuration +# Standard Kubernetes Ingress configuration ingress: enabled: false - # Gateway reference + className: "" + annotations: {} + hosts: + - host: playwright-proxy.lan + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: playwright-proxy-tls + # hosts: + # - playwright-proxy.lan + +# Gateway API HTTPRoute configuration (alternative to standard Ingress) +httproute: + enabled: false gatewayName: traefik gatewayNamespace: traefik sectionName: "" annotations: {} - # Hostnames for the HTTPRoute hostnames: - playwright-proxy.lan - # TLS configuration (if needed) - # tls: - # - secretName: playwright-proxy-tls - # hosts: - # - playwright-proxy.lan resources: limits: