commit
2794f514a2
19 changed files with 149 additions and 143 deletions
2
.actrc
2
.actrc
|
@ -9,3 +9,5 @@
|
||||||
--platform ubuntu-22.04=ghcr.io/catthehacker/ubuntu:act-22.04
|
--platform ubuntu-22.04=ghcr.io/catthehacker/ubuntu:act-22.04
|
||||||
--platform ubuntu-20.04=ghcr.io/catthehacker/ubuntu:act-20.04
|
--platform ubuntu-20.04=ghcr.io/catthehacker/ubuntu:act-20.04
|
||||||
--platform ubuntu-18.04=ghcr.io/catthehacker/ubuntu:act-18.04
|
--platform ubuntu-18.04=ghcr.io/catthehacker/ubuntu:act-18.04
|
||||||
|
--secret-file=.act.secrets
|
||||||
|
--var-file=.act.vars
|
||||||
|
|
22
.github/workflows/docker.build.yml
vendored
22
.github/workflows/docker.build.yml
vendored
|
@ -9,35 +9,37 @@ on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PLATFORMS: linux/amd64,linux/arm64
|
PLATFORMS: ${{ vars.PLATFORMS }}
|
||||||
CANDIDATE_IMAGE: ghcr.io/benzine-framework/bouncer:build-${{ github.sha }}
|
DOCKER_IMAGE: ghcr.io/${{ github.repository }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker-build:
|
docker-build:
|
||||||
name: Build Swarm Load Balancer
|
name: Build Swarm Load Balancer
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- uses: benzine-framework/action-setup-php@main
|
- uses: benzine-framework/action-setup-php@main
|
||||||
- uses: benzine-framework/action-get-datetime@main
|
- uses: benzine-framework/action-get-datetime@main
|
||||||
- uses: benzine-framework/action-setup-docker@main
|
- uses: benzine-framework/action-setup-docker@main
|
||||||
with:
|
with:
|
||||||
ghcr_user: matthewbaggett
|
ghcr_user: ${{ vars.SERVICE_ACCOUNT_USERNAME }}
|
||||||
ghcr_token: ${{ secrets.GITHUB_TOKEN }}
|
ghcr_token: ${{ secrets.SERVICE_ACCOUNT_TOKEN }}
|
||||||
docker_hub_user: matthewbaggett
|
|
||||||
docker_hub_token: ${{ secrets.DOCKER_HUB_TOKEN }}
|
|
||||||
- name: "Build & Push Candidate Image as ${{ env.CANDIDATE_IMAGE }}"
|
- name: "Build & Push Candidate Image as ${{ env.CANDIDATE_IMAGE }}"
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
target: bouncer
|
target: loadbalancer
|
||||||
build-args: |
|
build-args: |
|
||||||
|
MAINTAINER=${{ vars.PUBLIC_MAINTAINER || 'Matthew Baggett <matthew@baggett.me>' }}
|
||||||
|
SOURCE_URL="https://github.com/${{ github.repository }}"
|
||||||
GIT_SHA=${{ github.sha }}
|
GIT_SHA=${{ github.sha }}
|
||||||
GIT_BUILD_ID=${{ github.ref_name }}
|
GIT_BUILD_ID=${{ github.ref_name }}
|
||||||
GIT_COMMIT_MESSAGE=${{ github.event.head_commit.message }}
|
GIT_COMMIT_MESSAGE=${{ github.event.head_commit.message }}
|
||||||
BUILD_DATE=${{ env.ATOM }}
|
BUILD_DATE=${{ env.ATOM }}
|
||||||
platforms: ${{ github.actor != 'nektos/act' && env.PLATFORMS || 'linux/amd64' }}
|
platforms: ${{ github.actor != 'nektos/act' && vars.PLATFORMS || 'linux/amd64' }}
|
||||||
pull: true
|
pull: true
|
||||||
push: ${{ github.ref == 'refs/heads/main' }}
|
push: ${{ github.ref == 'refs/heads/main' }}
|
||||||
tags: ${{ env.CANDIDATE_IMAGE }}
|
tags: |
|
||||||
|
${{ env.DOCKER_IMAGE }}:date-${{ env.DATE }}
|
||||||
|
${{ env.DOCKER_IMAGE }}:sha-${{ github.sha }}
|
||||||
cache-from: ${{ env.DOCKER_CACHE_FROM }}
|
cache-from: ${{ env.DOCKER_CACHE_FROM }}
|
||||||
cache-to: ${{ env.DOCKER_CACHE_TO }}
|
cache-to: ${{ env.DOCKER_CACHE_TO }}
|
||||||
|
|
12
.github/workflows/docker.clean.yml
vendored
12
.github/workflows/docker.clean.yml
vendored
|
@ -15,30 +15,32 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
cleanup-delete-candidate-image:
|
cleanup-delete-candidate-image:
|
||||||
name: Delete candidate image
|
name: Delete candidate image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
||||||
- uses: vlaurin/action-ghcr-prune@v0.6.0
|
- uses: vlaurin/action-ghcr-prune@v0.6.0
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
organization: ${{ github.repository_owner }}
|
organization: ${{ github.repository_owner }}
|
||||||
container: bouncer
|
container: docker-swarm-loadbalancer
|
||||||
dry-run: true
|
dry-run: true
|
||||||
prune-tags-regexes: |
|
prune-tags-regexes: |
|
||||||
^build-${{ github.sha }}$
|
^build-${{ github.sha }}$
|
||||||
|
|
||||||
cleanup-untagged-images:
|
cleanup-untagged-images:
|
||||||
name: Delete untagged images
|
name: Delete untagged images
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
||||||
- uses: vlaurin/action-ghcr-prune@v0.6.0
|
- uses: vlaurin/action-ghcr-prune@v0.6.0
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
organization: ${{ github.repository_owner }}
|
organization: ${{ github.repository_owner }}
|
||||||
container: bouncer
|
container: docker-swarm-loadbalancer
|
||||||
dry-run: true
|
dry-run: true
|
||||||
keep-younger-than: 30 # days
|
keep-younger-than: 90 # days
|
||||||
keep-last: 2
|
keep-last: 2
|
||||||
prune-untagged: true
|
prune-untagged: true
|
||||||
keep-tags-regexes: |
|
keep-tags-regexes: |
|
||||||
|
|
25
.github/workflows/docker.release.yml
vendored
25
.github/workflows/docker.release.yml
vendored
|
@ -9,26 +9,15 @@ on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CANDIDATE_IMAGE: ghcr.io/benzine-framework/bouncer:build-${{ github.sha }}
|
CANDIDATE_IMAGE: ghcr.io/${{ github.repository }}:sha-${{ github.sha }}
|
||||||
RELEASE_IMAGE_GHCR: ghcr.io/benzine-framework/bouncer:latest
|
RELEASE_IMAGE: ghcr.io/${{ github.repository }}:latest
|
||||||
RELEASE_IMAGE_DOCKER: benzine/bouncer:latest
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-ghcr:
|
release-ghcr:
|
||||||
name: GHCR
|
name: GitHub Container Registry
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
- run: docker login ghcr.io -u ${{ vars.SERVICE_ACCOUNT_USERNAME }} -p ${{ secrets.SERVICE_ACCOUNT_TOKEN }}
|
||||||
- run: docker pull ${{ env.CANDIDATE_IMAGE }}
|
- run: docker pull ${{ env.CANDIDATE_IMAGE }}
|
||||||
- run: docker tag ${{ env.CANDIDATE_IMAGE }} ${{ env.RELEASE_IMAGE_GHCR }}
|
- run: docker tag ${{ env.CANDIDATE_IMAGE }} ${{ env.RELEASE_IMAGE }}
|
||||||
- run: docker push ${{ env.RELEASE_IMAGE_GHCR }}
|
- run: docker push ${{ env.RELEASE_IMAGE }}
|
||||||
|
|
||||||
release-docker-hub:
|
|
||||||
name: Docker Hub
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- run: docker login docker.io -u matthewbaggett -p ${{ secrets.DOCKER_HUB_TOKEN }}
|
|
||||||
- run: docker pull ${{ env.CANDIDATE_IMAGE }}
|
|
||||||
- run: docker tag ${{ env.CANDIDATE_IMAGE }} ${{ env.RELEASE_IMAGE_DOCKER }}
|
|
||||||
- run: docker push ${{ env.RELEASE_IMAGE_DOCKER }}
|
|
||||||
|
|
8
.github/workflows/docker.validate.yml
vendored
8
.github/workflows/docker.validate.yml
vendored
|
@ -13,12 +13,12 @@ on:
|
||||||
- completed
|
- completed
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CANDIDATE_IMAGE: ghcr.io/benzine-framework/bouncer:build-${{ github.sha }}
|
CANDIDATE_IMAGE: ghcr.io/${{ github.repository }}:sha-${{ github.sha }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
validate-install-report:
|
validate-install-report:
|
||||||
name: Run Install Report
|
name: Run Install Report
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: "Pull Candidate Image"
|
- name: "Pull Candidate Image"
|
||||||
|
@ -27,7 +27,7 @@ jobs:
|
||||||
run: docker run --rm ${{ env.CANDIDATE_IMAGE }} /usr/bin/install-report
|
run: docker run --rm ${{ env.CANDIDATE_IMAGE }} /usr/bin/install-report
|
||||||
validate-dive-report:
|
validate-dive-report:
|
||||||
name: Run Dive
|
name: Run Dive
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: "Pull Candidate Image"
|
- name: "Pull Candidate Image"
|
||||||
|
@ -48,7 +48,7 @@ jobs:
|
||||||
config-file: ${{ github.workspace }}/.dive-ci.yml
|
config-file: ${{ github.workspace }}/.dive-ci.yml
|
||||||
validate-vulnerability-report:
|
validate-vulnerability-report:
|
||||||
name: Run Trivy
|
name: Run Trivy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
- run: docker login ghcr.io -u ${{ github.repository_owner }} -p ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: "Pull Candidate Image"
|
- name: "Pull Candidate Image"
|
||||||
|
|
4
.github/workflows/php.check.yml
vendored
4
.github/workflows/php.check.yml
vendored
|
@ -10,7 +10,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
php-stan:
|
php-stan:
|
||||||
name: PHPStan
|
name: PHPStan
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
permissions:
|
permissions:
|
||||||
checks: write # To post annotations
|
checks: write # To post annotations
|
||||||
contents: read # For repo checkout
|
contents: read # For repo checkout
|
||||||
|
@ -20,7 +20,7 @@ jobs:
|
||||||
|
|
||||||
php-cs-fixer:
|
php-cs-fixer:
|
||||||
name: PHP-CS-Fixer
|
name: PHP-CS-Fixer
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
permissions:
|
permissions:
|
||||||
checks: write # For trunk to post annotations
|
checks: write # For trunk to post annotations
|
||||||
contents: read # For repo checkout
|
contents: read # For repo checkout
|
||||||
|
|
2
.github/workflows/tag.release.yml
vendored
2
.github/workflows/tag.release.yml
vendored
|
@ -17,7 +17,7 @@ env:
|
||||||
jobs:
|
jobs:
|
||||||
build-tagged-release:
|
build-tagged-release:
|
||||||
name: Build Swarm Load Balancer
|
name: Build Swarm Load Balancer
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
steps:
|
steps:
|
||||||
- run: echo "Building Tagged Release ${{ env.TAG_IMAGE_GHCR }} & ${{ env.TAG_IMAGE_DOCKER }}"
|
- run: echo "Building Tagged Release ${{ env.TAG_IMAGE_GHCR }} & ${{ env.TAG_IMAGE_DOCKER }}"
|
||||||
|
|
20
.github/workflows/tests.yml
vendored
20
.github/workflows/tests.yml
vendored
|
@ -10,49 +10,63 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
test-integration:
|
test-integration:
|
||||||
name: Integration Tests
|
name: Integration Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Start Bouncer
|
- name: Start Loadbalancer
|
||||||
run: |
|
run: |
|
||||||
rm -f docker-compose.override.yml
|
rm -f docker-compose.override.yml
|
||||||
docker compose up --build -d bouncer test-box
|
docker compose up --build -d loadbalancer test-box
|
||||||
- name: Give it a moment...
|
- name: Give it a moment...
|
||||||
run: sleep 5
|
run: sleep 5
|
||||||
- name: No-SSL Connect to Web A
|
- name: No-SSL Connect to Web A
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -xeu
|
||||||
docker compose exec test-box curl -s -D - http://a.example.org > a.nossl.http
|
docker compose exec test-box curl -s -D - http://a.example.org > a.nossl.http
|
||||||
grep "HTTP/1.1 200 OK" a.nossl.http;
|
grep "HTTP/1.1 200 OK" a.nossl.http;
|
||||||
grep "<h1>Website A</h1>" a.nossl.http;
|
grep "<h1>Website A</h1>" a.nossl.http;
|
||||||
- name: SSL Connect to Web A
|
- name: SSL Connect to Web A
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -xeu
|
||||||
docker compose exec test-box curl -s -k -D - https://a.example.org 2>&1 > a.ssl.http;
|
docker compose exec test-box curl -s -k -D - https://a.example.org 2>&1 > a.ssl.http;
|
||||||
grep "HTTP/1.1 200 OK" a.ssl.http;
|
grep "HTTP/1.1 200 OK" a.ssl.http;
|
||||||
grep "<h1>Website A</h1>" a.ssl.http;
|
grep "<h1>Website A</h1>" a.ssl.http;
|
||||||
- name: No-SSL Connect to Web B
|
- name: No-SSL Connect to Web B
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -xeu
|
||||||
docker compose exec test-box curl -s -D - http://b.example.org 2>&1 > b.nossl.http
|
docker compose exec test-box curl -s -D - http://b.example.org 2>&1 > b.nossl.http
|
||||||
grep "HTTP/1.1 200 OK" b.nossl.http
|
grep "HTTP/1.1 200 OK" b.nossl.http
|
||||||
grep "<h1>Website B</h1>" b.nossl.http
|
grep "<h1>Website B</h1>" b.nossl.http
|
||||||
- name: SSL Connect to Web B
|
- name: SSL Connect to Web B
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -xeu
|
||||||
docker compose exec test-box curl -s -k -D - https://b.example.org 2>&1 > b.ssl.http
|
docker compose exec test-box curl -s -k -D - https://b.example.org 2>&1 > b.ssl.http
|
||||||
grep "HTTP/1.1 200 OK" b.ssl.http
|
grep "HTTP/1.1 200 OK" b.ssl.http
|
||||||
grep "<h1>Website B</h1>" b.ssl.http
|
grep "<h1>Website B</h1>" b.ssl.http
|
||||||
- name: No-SSL Connect to SSL-redirect
|
- name: No-SSL Connect to SSL-redirect
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -xeu
|
||||||
docker compose exec test-box curl -s -D - http://redirect-to-ssl.example.org 2>&1 > redirect.nossl.http
|
docker compose exec test-box curl -s -D - http://redirect-to-ssl.example.org 2>&1 > redirect.nossl.http
|
||||||
# Validate its redirected
|
# Validate its redirected
|
||||||
grep "HTTP/1.1 301 Moved Permanently" redirect.nossl.http
|
grep "HTTP/1.1 301 Moved Permanently" redirect.nossl.http
|
||||||
# And going to the right place
|
# And going to the right place
|
||||||
grep "Location: https://redirect-to-ssl.example.org" redirect.nossl.http
|
grep "Location: https://redirect-to-ssl.example.org" redirect.nossl.http
|
||||||
- name: SSL Connect to SSL-redirect
|
- name: SSL Connect to SSL-redirect
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -xeu
|
||||||
docker compose exec test-box curl -s -k -D - https://redirect-to-ssl.example.org 2>&1 > redirect.ssl.http
|
docker compose exec test-box curl -s -k -D - https://redirect-to-ssl.example.org 2>&1 > redirect.ssl.http
|
||||||
grep "HTTP/1.1 200 OK" redirect.ssl.http
|
grep "HTTP/1.1 200 OK" redirect.ssl.http
|
||||||
grep "<h1>Website redirect-to-ssl</h1>" redirect.ssl.http
|
grep "<h1>Website redirect-to-ssl</h1>" redirect.ssl.http
|
||||||
- name: Connect to Plural multiple times and verify it loadbalances
|
- name: Connect to Plural multiple times and verify it loadbalances
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
set -xeu
|
||||||
rm -f plural_requests
|
rm -f plural_requests
|
||||||
for i in {1..20}; do
|
for i in {1..20}; do
|
||||||
docker compose exec test-box curl -s -k https://plural.example.org 2>&1 >> plural_requests
|
docker compose exec test-box curl -s -k https://plural.example.org 2>&1 >> plural_requests
|
||||||
|
|
2
.github/workflows/trunk.cache.yml
vendored
2
.github/workflows/trunk.cache.yml
vendored
|
@ -22,7 +22,7 @@ concurrency:
|
||||||
jobs:
|
jobs:
|
||||||
trunk-cache:
|
trunk-cache:
|
||||||
name: Trunk Cache
|
name: Trunk Cache
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
permissions:
|
permissions:
|
||||||
actions: write
|
actions: write
|
||||||
steps:
|
steps:
|
||||||
|
|
2
.github/workflows/trunk.check.yml
vendored
2
.github/workflows/trunk.check.yml
vendored
|
@ -10,7 +10,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
trunk-check:
|
trunk-check:
|
||||||
name: Trunk Check Runner
|
name: Trunk Check Runner
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
permissions:
|
permissions:
|
||||||
checks: write # For trunk to post annotations
|
checks: write # For trunk to post annotations
|
||||||
contents: read # For repo checkout
|
contents: read # For repo checkout
|
||||||
|
|
2
.github/workflows/trunk.upgrade.yml
vendored
2
.github/workflows/trunk.upgrade.yml
vendored
|
@ -20,7 +20,7 @@ concurrency:
|
||||||
jobs:
|
jobs:
|
||||||
trunk-upgrade:
|
trunk-upgrade:
|
||||||
name: Upgrade Trunk
|
name: Upgrade Trunk
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.RUNS_ON }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: write # For trunk to create PRs
|
contents: write # For trunk to create PRs
|
||||||
pull-requests: write # For trunk to create PRs
|
pull-requests: write # For trunk to create PRs
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,3 +2,5 @@
|
||||||
/.php-cs-fixer.cache
|
/.php-cs-fixer.cache
|
||||||
/.github/cache
|
/.github/cache
|
||||||
/.secrets
|
/.secrets
|
||||||
|
/.act.secrets
|
||||||
|
/.act.vars
|
||||||
|
|
|
@ -47,16 +47,16 @@ tools:
|
||||||
enabled:
|
enabled:
|
||||||
- tfupdate@0.8.2
|
- tfupdate@0.8.2
|
||||||
- phpstan@1.10.58
|
- phpstan@1.10.58
|
||||||
- gh@2.49.2
|
- gh@2.51.0
|
||||||
- jq@jq-1.7.1
|
- jq@jq-1.7.1
|
||||||
- yq@4.44.1
|
- yq@4.44.2
|
||||||
- awscli@1.33.9
|
- awscli@1.33.13
|
||||||
- action-validator@0.6.0
|
- action-validator@0.6.0
|
||||||
- act@0.2.63
|
- act@0.2.63
|
||||||
- shellcheck@0.10.0
|
- shellcheck@0.10.0
|
||||||
- hadolint@2.12.0
|
- hadolint@2.12.0
|
||||||
- svgo@3.3.2
|
- svgo@3.3.2
|
||||||
- tofu@1.7.1
|
- tofu@1.7.2
|
||||||
- trunk-toolbox@0.3.1
|
- trunk-toolbox@0.3.1
|
||||||
- tflint@0.51.1
|
- tflint@0.51.1
|
||||||
- terraform@1.1.4
|
- terraform@1.1.4
|
||||||
|
|
48
Dockerfile
48
Dockerfile
|
@ -1,9 +1,22 @@
|
||||||
# checkov:skip=CKV_DOCKER_3 I don't have time for rootless
|
# checkov:skip=CKV_DOCKER_3 I don't have time for rootless
|
||||||
FROM ghcr.io/benzine-framework/php:cli-8.2 AS bouncer
|
FROM ghcr.io/benzine-framework/php:cli-8.2 AS loadbalancer
|
||||||
|
|
||||||
LABEL maintainer="Matthew Baggett <matthew@baggett.me>" \
|
# Allow overriding the default SSL cert subject
|
||||||
org.label-schema.vcs-url="https://github.com/benzine-framework/docker-swarm-loadbalancer" \
|
ARG DEFAULT_SSL_CERT_SUBJECT="/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname"
|
||||||
org.opencontainers.image.source="https://github.com/benzine-framework/docker-swarm-loadbalancer"
|
ARG PUBLIC_MAINTAINER="Matthew Baggett <matthew@baggett.me>"
|
||||||
|
ARG SOURCE_URL="https://github.com/benzine-framework/docker-swarm-loadbalancer"
|
||||||
|
ARG BUILD_DATE
|
||||||
|
ARG GIT_SHA
|
||||||
|
ARG GIT_BUILD_ID
|
||||||
|
ARG GIT_COMMIT_MESSAGE
|
||||||
|
ENV BUILD_DATE=${BUILD_DATE} \
|
||||||
|
GIT_SHA=${GIT_SHA} \
|
||||||
|
GIT_BUILD_ID=${GIT_BUILD_ID} \
|
||||||
|
GIT_COMMIT_MESSAGE=${GIT_COMMIT_MESSAGE}
|
||||||
|
|
||||||
|
LABEL maintainer="${PUBLIC_MAINTAINER}" \
|
||||||
|
org.label-schema.vcs-url="${SOURCE_URL}" \
|
||||||
|
org.opencontainers.image.source="${SOURCE_URL}"
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
|
||||||
|
@ -37,8 +50,17 @@ RUN apt-get -qq update && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /var/lib/dpkg/status.old /var/cache/debconf/templates.dat /var/log/dpkg.log /var/log/lastlog /var/log/apt/*.log
|
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /var/lib/dpkg/status.old /var/cache/debconf/templates.dat /var/log/dpkg.log /var/log/lastlog /var/log/apt/*.log
|
||||||
|
|
||||||
# copy some default self-signed certs
|
# Generate some default self-signed certs
|
||||||
COPY self-signed-certificates /certs
|
RUN mkdir /certs && \
|
||||||
|
openssl req \
|
||||||
|
-x509 \
|
||||||
|
-newkey rsa:4096 \
|
||||||
|
-keyout /certs/example.key \
|
||||||
|
-out /certs/example.crt \
|
||||||
|
-sha256 \
|
||||||
|
-days 3650 \
|
||||||
|
-nodes \
|
||||||
|
-subj "${DEFAULT_SSL_CERT_SUBJECT}"
|
||||||
|
|
||||||
# Install runits for services
|
# Install runits for services
|
||||||
COPY nginx.runit /etc/service/nginx/run
|
COPY nginx.runit /etc/service/nginx/run
|
||||||
|
@ -72,16 +94,6 @@ COPY src /app/src
|
||||||
COPY templates /app/templates
|
COPY templates /app/templates
|
||||||
RUN chmod +x /app/bin/bouncer
|
RUN chmod +x /app/bin/bouncer
|
||||||
|
|
||||||
# stuff some envs from build
|
|
||||||
ARG BUILD_DATE
|
|
||||||
ARG GIT_SHA
|
|
||||||
ARG GIT_BUILD_ID
|
|
||||||
ARG GIT_COMMIT_MESSAGE
|
|
||||||
ENV BUILD_DATE=${BUILD_DATE} \
|
|
||||||
GIT_SHA=${GIT_SHA} \
|
|
||||||
GIT_BUILD_ID=${GIT_BUILD_ID} \
|
|
||||||
GIT_COMMIT_MESSAGE=${GIT_COMMIT_MESSAGE}
|
|
||||||
|
|
||||||
# Create some volumes for logs and certs
|
# Create some volumes for logs and certs
|
||||||
VOLUME /etc/letsencrypt
|
VOLUME /etc/letsencrypt
|
||||||
VOLUME /var/log/bouncer
|
VOLUME /var/log/bouncer
|
||||||
|
@ -104,5 +116,5 @@ HEALTHCHECK --start-period=3s --interval=3s \
|
||||||
|
|
||||||
# checkov:skip=CKV_DOCKER_7 This is a test container.
|
# checkov:skip=CKV_DOCKER_7 This is a test container.
|
||||||
# checkov:skip=CKV_DOCKER_3 This is a test container.
|
# checkov:skip=CKV_DOCKER_3 This is a test container.
|
||||||
FROM alpine as test-box
|
FROM alpine AS test-box
|
||||||
RUN apk add --no-cache curl bash
|
RUN apk add --no-cache curl bash
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
services:
|
services:
|
||||||
bouncer:
|
loadbalancer:
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- ./src:/app/src
|
- ./src:/app/src
|
||||||
|
|
|
@ -2,14 +2,22 @@ networks:
|
||||||
default:
|
default:
|
||||||
|
|
||||||
services:
|
services:
|
||||||
bouncer:
|
loadbalancer:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
target: bouncer
|
target: loadbalancer
|
||||||
|
args:
|
||||||
|
MAINTAINER: "Test <test@oneupsales.co.uk>"
|
||||||
|
SOURCE_URL: "https://github.com/doesntmatter"
|
||||||
|
GIT_SHA: "1234"
|
||||||
|
GIT_BUILD_ID: "test"
|
||||||
|
GIT_COMMIT_MESSAGE: "testy mctestface"
|
||||||
|
BUILD_DATE: "1970-01-01"
|
||||||
additional_contexts:
|
additional_contexts:
|
||||||
- php:cli=docker-image://ghcr.io/benzine-framework/php:cli-8.2
|
- php:cli=docker-image://ghcr.io/benzine-framework/php:cli-8.2
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
image: loadbalancer-test
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
aliases:
|
aliases:
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDnTCCAoWgAwIBAgIUJYUUmBQ2/ERZ7xinAJzVhiFWViYwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwXTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB0Zsb3JpZGExDjAMBgNVBAcMBU1p
|
|
||||||
YW1pMRYwFAYDVQQKDA1FeGFtcGxlIEdyb3VwMRQwEgYDVQQDDAtleGFtcGxlLm9y
|
|
||||||
ZzAgFw0yMTA1MzAxNzU4MzlaGA8yMTIxMDUwNjE3NTgzOVowXTELMAkGA1UEBhMC
|
|
||||||
VVMxEDAOBgNVBAgMB0Zsb3JpZGExDjAMBgNVBAcMBU1pYW1pMRYwFAYDVQQKDA1F
|
|
||||||
eGFtcGxlIEdyb3VwMRQwEgYDVQQDDAtleGFtcGxlLm9yZzCCASIwDQYJKoZIhvcN
|
|
||||||
AQEBBQADggEPADCCAQoCggEBANJa9OcoCW+mej8qDMCCTGnqMAuUqBIj1wZLgOdT
|
|
||||||
4DHriq1vKi1JLsDZkYekrCq/sfWo97kDXsdK6YN4+mua5EN4cTG3mSpal+RgLTc2
|
|
||||||
HMKHFfgzPzIN/n5AEqzdVZb5j0P3LoUNH687AlplW0BB+K64Gw//2KPx0Q8Fkhq2
|
|
||||||
I97V8SRpqds78PJHzhfuZNs/AUFpFXnYHJyO2Q63Btq2aoTMQyoLDRBBxin70II2
|
|
||||||
6Cjh3k6EhMY+HuYS1AjfI8cDQw289asJBLa6zPoD0VGaGNfCSrOzxrUqfhIoOkuY
|
|
||||||
W7rOIsK6rSSu1neSKQIiOLVjQxifxrQIIKTQhRiSplgD9LUCAwEAAaNTMFEwHQYD
|
|
||||||
VR0OBBYEFADK74w4AGeETK72k/htsnol9ye0MB8GA1UdIwQYMBaAFADK74w4AGeE
|
|
||||||
TK72k/htsnol9ye0MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
|
|
||||||
AKElv0xx95lD2leXEOfD6DKakrzuE8lONmcrkfjehTOd7jbqblnj8u1DCWytwB8P
|
|
||||||
gEr5FXve0iy7avGoNkU33MufbbQokAMoTs/IA+rwMfv0unupT1aYN8TTEXJJ100j
|
|
||||||
MXBsq/PvNkBNwkBcXjYHHsVjdM3bptbaw9A4V9opfMjQXAY5wuk3rBBm8On2rJKy
|
|
||||||
Qksh/uLoe8wbZ5dvLv9oc9sRpIilaSy8TcbrHkDIaWA5WCdVFfcayDGYdjhCYLGW
|
|
||||||
tj/48g0THvJv6JvVYwFJqTM690YUSlxaOHQE2ZneLytocVyAdEL2MMldRezvtI1z
|
|
||||||
1OXOia2G7koNYtS7cD8G1IM=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,28 +0,0 @@
|
||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDSWvTnKAlvpno/
|
|
||||||
KgzAgkxp6jALlKgSI9cGS4DnU+Ax64qtbyotSS7A2ZGHpKwqv7H1qPe5A17HSumD
|
|
||||||
ePprmuRDeHExt5kqWpfkYC03NhzChxX4Mz8yDf5+QBKs3VWW+Y9D9y6FDR+vOwJa
|
|
||||||
ZVtAQfiuuBsP/9ij8dEPBZIatiPe1fEkaanbO/DyR84X7mTbPwFBaRV52BycjtkO
|
|
||||||
twbatmqEzEMqCw0QQcYp+9CCNugo4d5OhITGPh7mEtQI3yPHA0MNvPWrCQS2usz6
|
|
||||||
A9FRmhjXwkqzs8a1Kn4SKDpLmFu6ziLCuq0krtZ3kikCIji1Y0MYn8a0CCCk0IUY
|
|
||||||
kqZYA/S1AgMBAAECggEARqfQjPgwuzTi6OZ55AugGQ9VVf53uagaKH4h7RGKQ5pH
|
|
||||||
OVwWgaGMN7CcpkAUqEM9RjOcCaPtKOmrp8Jx8sTTGSqScs2lf8lwLYB0j4/4dwqi
|
|
||||||
wXyNJIX4znU9EJ1Di3OFwKF9Gam/077xWmWjEeFW43DpfiVEokSuIOqRGbHGOKlt
|
|
||||||
2ygHJu+rmPapEPyYqSWQnAkYX0DW/KCAGiyIAqph/SgrCDTdsxbNOa2OwDygPC54
|
|
||||||
7xW0yCduvgFLh9bxedF8iifzRkPw710cxyqVsYwHiwugDgxL4NiK1DlWbpBimab5
|
|
||||||
ocye9+ElymMZ8DTjpA85cXny/TtoqJfqTs1YGYgrvQKBgQDwHnAcY0BjQ4o+ZneG
|
|
||||||
oqBJeQ8KCMRU4pEIa5QOOeUr46gtiPIfcFh/BJUHQ61qk7gcJj5BV2GXNS7+m+sU
|
|
||||||
RC3Usblm9twwxZn7mfoOk4z9NEfBI2MXmbB8ARjAQBCost+3KQAoSIL1AyDKiAlY
|
|
||||||
2JfMt+73+kwUsg7b9g0pYIfn/wKBgQDgRJPlSIxJs2mbjzUwVBAeslct2W0dehrh
|
|
||||||
V0sXPxEhJHWX6P343vLqRHRsKgqhbU/vy+3JrIS9ftwGKcmb+Y9EJgYrR+D3ZYzs
|
|
||||||
idSOsunSspJgbCG5mHE1VQhr8IpHeCkuSt22aFErLfsjzXWZIewK2tqZN1QUjdc5
|
|
||||||
EJHOD4UDSwKBgFYRYvgZ72NlOzFAw0kkE7YiSWy8Vbtjdr8A6JHs2KNRt9+Sfc8d
|
|
||||||
Eut8dfqjnI5eIpkccCY1rwpnCtBCjRG3moHprl4k0Co/OgGAYKxG4TuFOM8W4xb7
|
|
||||||
hNH+BqQqko4Vh7D8Zk0KKL6v/1n5RvhssoSzzVlfg1PLux3G5VLWggB7AoGAAP/N
|
|
||||||
OORN27Y07kCBGCoHuFtLECU72znEDOT6rKvXQ7KJ45diKk2z/182tZSqX3XBOWxL
|
|
||||||
Lu7Z2I5MJKri/xLplIAm3uJ/GhsVuagTjl81s36gMFXLAKyxNG+gjfqQYykh5dbn
|
|
||||||
jfyBABRAXjR4JaqFBrda6fvZIA5RuytbuvNOwGkCgYAUs82tDGLiqyMPd2jgYS3k
|
|
||||||
aL62f0TLKHjmTCmRca7IqXbqcMbAj+LgAHI2HfCfjc4KWd68ZGRLcpDlehMcis1f
|
|
||||||
PQi3HW+2b9dAZX6+HAIGiVem//ckYXgUza4MMosh0hXquGs1yJ/VNWC+HPIHrj6X
|
|
||||||
9tvvvHnGKav329q/Z/8K/A==
|
|
||||||
-----END PRIVATE KEY-----
|
|
|
@ -8,16 +8,19 @@ use AdamBrett\ShellWrapper\Command\Builder as CommandBuilder;
|
||||||
use AdamBrett\ShellWrapper\Runners\Exec;
|
use AdamBrett\ShellWrapper\Runners\Exec;
|
||||||
use Aws\S3\S3Client;
|
use Aws\S3\S3Client;
|
||||||
use Bouncer\Logger\AbstractLogger;
|
use Bouncer\Logger\AbstractLogger;
|
||||||
|
use Bouncer\Logger\Formatter;
|
||||||
|
use Bouncer\Logger\Logger;
|
||||||
|
use Bouncer\Settings\Settings;
|
||||||
use GuzzleHttp\Client as Guzzle;
|
use GuzzleHttp\Client as Guzzle;
|
||||||
use GuzzleHttp\Exception\ConnectException;
|
use GuzzleHttp\Exception\ConnectException;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
use GuzzleHttp\Exception\ServerException;
|
use GuzzleHttp\Exception\ServerException;
|
||||||
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
|
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
|
||||||
use League\Flysystem\FileAttributes;
|
use League\Flysystem\FileAttributes;
|
||||||
use League\Flysystem\Filesystem;
|
use League\Flysystem\Filesystem;
|
||||||
use League\Flysystem\FilesystemException;
|
use League\Flysystem\FilesystemException;
|
||||||
use League\Flysystem\Local\LocalFilesystemAdapter;
|
use League\Flysystem\Local\LocalFilesystemAdapter;
|
||||||
use Bouncer\Logger\Logger;
|
use Monolog\Processor;
|
||||||
use Bouncer\Logger\Formatter;
|
|
||||||
use Spatie\Emoji\Emoji;
|
use Spatie\Emoji\Emoji;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
use Twig\Environment as Twig;
|
use Twig\Environment as Twig;
|
||||||
|
@ -25,9 +28,6 @@ use Twig\Error\LoaderError;
|
||||||
use Twig\Error\RuntimeError;
|
use Twig\Error\RuntimeError;
|
||||||
use Twig\Error\SyntaxError;
|
use Twig\Error\SyntaxError;
|
||||||
use Twig\Loader\FilesystemLoader as TwigLoader;
|
use Twig\Loader\FilesystemLoader as TwigLoader;
|
||||||
use GuzzleHttp\Exception\GuzzleException;
|
|
||||||
use Monolog\Processor;
|
|
||||||
use Bouncer\Settings\Settings;
|
|
||||||
|
|
||||||
class Bouncer
|
class Bouncer
|
||||||
{
|
{
|
||||||
|
@ -186,6 +186,7 @@ class Bouncer
|
||||||
public function findContainersContainerMode(): array
|
public function findContainersContainerMode(): array
|
||||||
{
|
{
|
||||||
$bouncerTargets = [];
|
$bouncerTargets = [];
|
||||||
|
$this->logger->warning('Interrogating CONTAINERS for BOUNCER_* environment variables.', ['emoji' => Emoji::magnifyingGlassTiltedLeft()]);
|
||||||
|
|
||||||
$containers = json_decode($this->docker->request('GET', 'containers/json')->getBody()->getContents(), true);
|
$containers = json_decode($this->docker->request('GET', 'containers/json')->getBody()->getContents(), true);
|
||||||
foreach ($containers as $container) {
|
foreach ($containers as $container) {
|
||||||
|
@ -210,6 +211,8 @@ class Bouncer
|
||||||
}
|
}
|
||||||
// If BOUNCER_IGNORE is set, skip this service.
|
// If BOUNCER_IGNORE is set, skip this service.
|
||||||
if (isset($envs['BOUNCER_IGNORE'])) {
|
if (isset($envs['BOUNCER_IGNORE'])) {
|
||||||
|
$this->logger->warning('Container {container_name} has BOUNCER_IGNORE set, skipping.', ['emoji' => Emoji::warning() . ' ', 'container_name' => $container['Name']]);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,16 +265,19 @@ class Bouncer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->logger->warning('Interrogating CONTAINERS for BOUNCER_* environment variables found {count} containers.', ['emoji' => Emoji::magnifyingGlassTiltedLeft(), 'count' => count($validBouncerTargets)]);
|
||||||
|
|
||||||
return $validBouncerTargets;
|
return $validBouncerTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findContainersSwarmMode(): array
|
public function findContainersSwarmMode(): array
|
||||||
{
|
{
|
||||||
|
$this->logger->warning('Interrogating SERVICES for BOUNCER_* environment variables.', ['emoji' => Emoji::magnifyingGlassTiltedLeft()]);
|
||||||
$bouncerTargets = [];
|
$bouncerTargets = [];
|
||||||
$services = json_decode($this->docker->request('GET', 'services')->getBody()->getContents(), true);
|
$services = json_decode($this->docker->request('GET', 'services')->getBody()->getContents(), true);
|
||||||
|
|
||||||
if (isset($services['message'])) {
|
if (isset($services['message'])) {
|
||||||
$this->logger->debug('Something happened while interrogating services.. This node is not a swarm node, cannot have services: {message}', ['emoji' => Emoji::warning() . ' Bouncer.php', 'message' => $services['message']]);
|
$this->logger->debug('Something happened while interrogating services.. This node is not a swarm node, cannot have services: {message}', ['emoji' => Emoji::warning() . ' ', 'message' => $services['message']]);
|
||||||
} else {
|
} else {
|
||||||
foreach ($services as $service) {
|
foreach ($services as $service) {
|
||||||
$envs = [];
|
$envs = [];
|
||||||
|
@ -283,6 +289,7 @@ class Bouncer
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse all the environment variables and store them in an array.
|
// Parse all the environment variables and store them in an array.
|
||||||
foreach ($service['Spec']['TaskTemplate']['ContainerSpec']['Env'] as $env) {
|
foreach ($service['Spec']['TaskTemplate']['ContainerSpec']['Env'] as $env) {
|
||||||
[$envKey, $envVal] = explode('=', $env, 2);
|
[$envKey, $envVal] = explode('=', $env, 2);
|
||||||
|
@ -291,12 +298,18 @@ class Bouncer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ksort($envs);
|
ksort($envs);
|
||||||
|
|
||||||
// If there are no BOUNCER_* environment variables, skip this service.
|
// If there are no BOUNCER_* environment variables, skip this service.
|
||||||
if (count($envs) == 0) {
|
if (count($envs) == 0) {
|
||||||
|
$this->logger->debug('Service {service_name} has no BOUNCER_* envs set, skipping.', ['emoji' => Emoji::ghost() . ' ', 'service_name' => $service['Spec']['Name']]);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if BOUNCER_IGNORE is set, skip this service.
|
// if BOUNCER_IGNORE is set, skip this service.
|
||||||
if (isset($envs['BOUNCER_IGNORE'])) {
|
if (isset($envs['BOUNCER_IGNORE'])) {
|
||||||
|
$this->logger->debug('Service {service_name} has BOUNCER_IGNORE set, skipping.', ['emoji' => Emoji::warning() . ' ', 'service_name' => $service['Spec']['Name']]);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +338,7 @@ class Bouncer
|
||||||
$bouncerTarget->setEndpoints(['172.17.0.1']);
|
$bouncerTarget->setEndpoints(['172.17.0.1']);
|
||||||
$bouncerTarget->setPort(intval($service['Endpoint']['Ports'][0]['PublishedPort']));
|
$bouncerTarget->setPort(intval($service['Endpoint']['Ports'][0]['PublishedPort']));
|
||||||
} else {
|
} else {
|
||||||
$this->logger->warning('{label}: ports block missing for {target_name}. Try setting BOUNCER_TARGET_PORT.', ['emoji' => Emoji::warning() . ' Bouncer.php', 'label' => $bouncerTarget->getLabel(), 'target_name' => $bouncerTarget->getName()]);
|
$this->logger->warning('{label}: ports block missing for {target_name}. Try setting BOUNCER_TARGET_PORT.', ['emoji' => Emoji::warning() . ' ', 'label' => $bouncerTarget->getLabel(), 'target_name' => $bouncerTarget->getName()]);
|
||||||
\Kint::dump(
|
\Kint::dump(
|
||||||
$bouncerTarget->getId(),
|
$bouncerTarget->getId(),
|
||||||
$bouncerTarget->getLabel(),
|
$bouncerTarget->getLabel(),
|
||||||
|
@ -344,6 +357,10 @@ class Bouncer
|
||||||
unset($bouncerTarget);
|
unset($bouncerTarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($bouncerTarget)) {
|
||||||
|
$bouncerTargets[] = $bouncerTarget;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,13 +381,16 @@ class Bouncer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->logger->debug('There are {count} bouncer targets, of which {validCount} are valid', ['count' => count($bouncerTargets), 'validCount' => count($validBouncerTargets)]);
|
||||||
|
|
||||||
|
$this->logger->warning('Interrogating SERVICES for BOUNCER_* environment variables found {count} services.', ['emoji' => Emoji::magnifyingGlassTiltedLeft(), 'count' => count($validBouncerTargets)]);
|
||||||
|
|
||||||
return $validBouncerTargets;
|
return $validBouncerTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$this->logger->info('Starting Bouncer. Built {build_id} on {build_date}, {build_ago}', ['emoji' => Emoji::redHeart() . ' Bouncer.php', 'build_id' => $this->settings->get('build/id'), 'build_date' => $this->settings->get('build/date')->toDateTimeString(), 'build_ago' => $this->settings->get('build/date')->ago()]);
|
$this->logger->info('Starting Bouncer. Built {build_id} on {build_date}, {build_ago}', ['emoji' => Emoji::redHeart() . ' ', 'build_id' => $this->settings->get('build/id'), 'build_date' => $this->settings->get('build/date')->toDateTimeString(), 'build_ago' => $this->settings->get('build/date')->ago()]);
|
||||||
$this->logger->info('Build #{git_sha}: "{build_message}"', ['emoji' => Emoji::memo(), 'git_sha' => $this->settings->get('build/sha_short'), 'build_message' => $this->settings->get('build/message')]);
|
$this->logger->info('Build #{git_sha}: "{build_message}"', ['emoji' => Emoji::memo(), 'git_sha' => $this->settings->get('build/sha_short'), 'build_message' => $this->settings->get('build/message')]);
|
||||||
$this->logger->debug(' > HTTPS Listener is on {https_port}', ['emoji' => Emoji::ship(), 'https_port' => $this->settings->get('bouncer/https_port')]);
|
$this->logger->debug(' > HTTPS Listener is on {https_port}', ['emoji' => Emoji::ship(), 'https_port' => $this->settings->get('bouncer/https_port')]);
|
||||||
$this->logger->debug(' > HTTP Listener is on {http_port}', ['emoji' => Emoji::ship(), 'http_port' => $this->settings->get('bouncer/http_port')]);
|
$this->logger->debug(' > HTTP Listener is on {http_port}', ['emoji' => Emoji::ship(), 'http_port' => $this->settings->get('bouncer/http_port')]);
|
||||||
|
@ -586,7 +606,7 @@ class Bouncer
|
||||||
$containerStateDiff = $this->diff($this->previousContainerState, $newContainerState);
|
$containerStateDiff = $this->diff($this->previousContainerState, $newContainerState);
|
||||||
if (!$isTainted && !empty($containerStateDiff)) {
|
if (!$isTainted && !empty($containerStateDiff)) {
|
||||||
if ($this->settings->if('logger/show_state_deltas')) {
|
if ($this->settings->if('logger/show_state_deltas')) {
|
||||||
$this->logger->warning('Container state has changed', ['emoji' => Emoji::warning() . ' Bouncer.php']);
|
$this->logger->warning('Container state has changed', ['emoji' => Emoji::warning() . ' ']);
|
||||||
echo $containerStateDiff;
|
echo $containerStateDiff;
|
||||||
}
|
}
|
||||||
$isTainted = true;
|
$isTainted = true;
|
||||||
|
@ -598,7 +618,7 @@ class Bouncer
|
||||||
if ($this->isSwarmMode()) {
|
if ($this->isSwarmMode()) {
|
||||||
$services = json_decode($this->docker->request('GET', 'services')->getBody()->getContents(), true);
|
$services = json_decode($this->docker->request('GET', 'services')->getBody()->getContents(), true);
|
||||||
if (isset($services['message'])) {
|
if (isset($services['message'])) {
|
||||||
$this->logger->warning('Something happened while interrogating services.. This node is not a swarm node, cannot have services: {message}', ['emoji' => Emoji::warning() . ' Bouncer.php', 'message' => $services['message']]);
|
$this->logger->warning('Something happened while interrogating services.. This node is not a swarm node, cannot have services: {message}', ['emoji' => Emoji::warning() . ' ', 'message' => $services['message']]);
|
||||||
} else {
|
} else {
|
||||||
foreach ($services as $service) {
|
foreach ($services as $service) {
|
||||||
$name = $service['Spec']['Name'];
|
$name = $service['Spec']['Name'];
|
||||||
|
@ -626,7 +646,7 @@ class Bouncer
|
||||||
$swarmStateDiff = $this->diff($this->previousSwarmState, $newSwarmState);
|
$swarmStateDiff = $this->diff($this->previousSwarmState, $newSwarmState);
|
||||||
if ($this->isSwarmMode() && !$isTainted && !empty($swarmStateDiff)) {
|
if ($this->isSwarmMode() && !$isTainted && !empty($swarmStateDiff)) {
|
||||||
if ($this->settings->if('logger/show_state_deltas')) {
|
if ($this->settings->if('logger/show_state_deltas')) {
|
||||||
$this->logger->warning('Swarm state has changed', ['emoji' => Emoji::warning() . ' Bouncer.php']);
|
$this->logger->warning('Swarm state has changed', ['emoji' => Emoji::warning() . ' ']);
|
||||||
echo $swarmStateDiff;
|
echo $swarmStateDiff;
|
||||||
}
|
}
|
||||||
$isTainted = true;
|
$isTainted = true;
|
||||||
|
@ -662,7 +682,7 @@ class Bouncer
|
||||||
} catch (ServerException $exception) {
|
} catch (ServerException $exception) {
|
||||||
$this->setSwarmMode(false);
|
$this->setSwarmMode(false);
|
||||||
} catch (ConnectException $exception) {
|
} catch (ConnectException $exception) {
|
||||||
$this->logger->critical('Unable to connect to docker socket!', ['emoji' => Emoji::warning() . ' Bouncer.php']);
|
$this->logger->critical('Unable to connect to docker socket!', ['emoji' => Emoji::warning() . ' ']);
|
||||||
$this->logger->critical($exception->getMessage());
|
$this->logger->critical($exception->getMessage());
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -670,6 +690,7 @@ class Bouncer
|
||||||
|
|
||||||
$this->logger->debug(' > Swarm mode is {enabled}.', ['emoji' => Emoji::honeybee(), 'enabled' => $this->isSwarmMode() ? 'enabled' : 'disabled']);
|
$this->logger->debug(' > Swarm mode is {enabled}.', ['emoji' => Emoji::honeybee(), 'enabled' => $this->isSwarmMode() ? 'enabled' : 'disabled']);
|
||||||
|
|
||||||
|
/** @var Target[] $targets */
|
||||||
$targets = array_values(
|
$targets = array_values(
|
||||||
array_merge(
|
array_merge(
|
||||||
$this->findContainersContainerMode(),
|
$this->findContainersContainerMode(),
|
||||||
|
@ -677,6 +698,10 @@ class Bouncer
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
foreach ($targets as $target) {
|
||||||
|
$this->logger->info('Found target {target}', ['emoji' => Emoji::magnifyingGlassTiltedLeft(), 'target' => $target->getName()]);
|
||||||
|
}
|
||||||
|
|
||||||
// Use some bs to sort the targets by domain from right to left.
|
// Use some bs to sort the targets by domain from right to left.
|
||||||
$sortedTargets = [];
|
$sortedTargets = [];
|
||||||
foreach ($targets as $target) {
|
foreach ($targets as $target) {
|
||||||
|
@ -702,7 +727,7 @@ class Bouncer
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isTestMode()) {
|
if ($this->isTestMode()) {
|
||||||
$this->logger->info('Test mode enabled, not restarting nginx. Infact, I\'ll die now..', ['emoji' => Emoji::warning() . ' Bouncer.php']);
|
$this->logger->info('Test mode enabled, not restarting nginx. Infact, I\'ll die now..', ['emoji' => Emoji::warning() . ' ']);
|
||||||
$this->dumpConfigs();
|
$this->dumpConfigs();
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -818,15 +843,15 @@ class Bouncer
|
||||||
'file' => $target->getNginxConfigFileName(),
|
'file' => $target->getNginxConfigFileName(),
|
||||||
'config_dir' => Bouncer::FILESYSTEM_CONFIG_DIR,
|
'config_dir' => Bouncer::FILESYSTEM_CONFIG_DIR,
|
||||||
];
|
];
|
||||||
$this->logger->info('Created {label}', $context + ['emoji' => Emoji::pencil() . ' Bouncer.php']);
|
$this->logger->info('Created {label}', $context + ['emoji' => Emoji::pencil() . ' ']);
|
||||||
$this->logger->debug(' -> {config_dir}/{file}', $context + ['emoji' => Emoji::pencil() . ' Bouncer.php']);
|
$this->logger->debug(' -> {config_dir}/{file}', $context + ['emoji' => Emoji::pencil() . ' ']);
|
||||||
$this->logger->debug(' -> {domain}', $context + ['emoji' => Emoji::pencil() . ' Bouncer.php']);
|
$this->logger->debug(' -> {domain}', $context + ['emoji' => Emoji::pencil() . ' ']);
|
||||||
$this->logger->critical('{label} cert type is {cert_type}', $context + ['emoji' => Emoji::catFace(), 'cert_type' => $target->getTypeCertInUse()->name]);
|
$this->logger->critical('{label} cert type is {cert_type}', $context + ['emoji' => Emoji::catFace(), 'cert_type' => $target->getTypeCertInUse()->name]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->logger->info('More than {num_max} Nginx configs generated.. Too many to show them all!', ['emoji' => Emoji::pencil() . ' Bouncer.php', 'num_max' => $this->getMaximumNginxConfigCreationNotices()]);
|
$this->logger->info('More than {num_max} Nginx configs generated.. Too many to show them all!', ['emoji' => Emoji::pencil() . ' ', 'num_max' => $this->getMaximumNginxConfigCreationNotices()]);
|
||||||
}
|
}
|
||||||
$this->logger->info('Updated {num_created} Nginx configs, {num_changed} changed..', ['emoji' => Emoji::pencil() . ' Bouncer.php', 'num_created' => count($targets), 'num_changed' => count($changedTargets)]);
|
$this->logger->info('Updated {num_created} Nginx configs, {num_changed} changed..', ['emoji' => Emoji::pencil() . ' ', 'num_created' => count($targets), 'num_changed' => count($changedTargets)]);
|
||||||
|
|
||||||
$this->pruneNonExistentConfigs($targets);
|
$this->pruneNonExistentConfigs($targets);
|
||||||
}
|
}
|
||||||
|
@ -949,13 +974,13 @@ class Bouncer
|
||||||
$command->addFlag('n');
|
$command->addFlag('n');
|
||||||
$command->addFlag('m', $this->environment['BOUNCER_LETSENCRYPT_EMAIL']);
|
$command->addFlag('m', $this->environment['BOUNCER_LETSENCRYPT_EMAIL']);
|
||||||
$command->addArgument('agree-tos');
|
$command->addArgument('agree-tos');
|
||||||
$this->logger->info('Generating letsencrypt for {target_name} - {command}', ['emoji' => Emoji::pencil() . ' Bouncer.php', 'target_name' => $target->getName(), 'command' => $command->__toString()]);
|
$this->logger->info('Generating letsencrypt for {target_name} - {command}', ['emoji' => Emoji::pencil() . ' ', 'target_name' => $target->getName(), 'command' => $command->__toString()]);
|
||||||
$shell->run($command);
|
$shell->run($command);
|
||||||
|
|
||||||
if ($shell->getReturnValue() == 0) {
|
if ($shell->getReturnValue() == 0) {
|
||||||
$this->logger->info('Generating successful', ['emoji' => Emoji::partyPopper()]);
|
$this->logger->info('Generating successful', ['emoji' => Emoji::partyPopper()]);
|
||||||
} else {
|
} else {
|
||||||
$this->logger->critical('Generating failed!', ['emoji' => Emoji::warning() . ' Bouncer.php']);
|
$this->logger->critical('Generating failed!', ['emoji' => Emoji::warning() . ' ']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-enable nginx tweaks
|
// Re-enable nginx tweaks
|
||||||
|
@ -977,7 +1002,7 @@ class Bouncer
|
||||||
$shell = new Exec();
|
$shell = new Exec();
|
||||||
$command = new CommandBuilder('/usr/sbin/nginx');
|
$command = new CommandBuilder('/usr/sbin/nginx');
|
||||||
$command->addFlag('s', 'reload');
|
$command->addFlag('s', 'reload');
|
||||||
$this->logger->info('Restarting nginx', ['emoji' => Emoji::timerClock() . ' Bouncer.php']);
|
$this->logger->info('Restarting nginx', ['emoji' => Emoji::timerClock() . ' ']);
|
||||||
$nginxRestartOutput = $shell->run($command);
|
$nginxRestartOutput = $shell->run($command);
|
||||||
$this->logger->debug('Nginx restarted {restart_output}', ['restart_output' => $nginxRestartOutput, 'emoji' => Emoji::partyPopper()]);
|
$this->logger->debug('Nginx restarted {restart_output}', ['restart_output' => $nginxRestartOutput, 'emoji' => Emoji::partyPopper()]);
|
||||||
}
|
}
|
||||||
|
@ -990,7 +1015,7 @@ class Bouncer
|
||||||
if ($file['path'] == 'default.conf') {
|
if ($file['path'] == 'default.conf') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$this->logger->info('Dumping {file}', ['emoji' => Emoji::pencil() . ' Bouncer.php', 'file' => $file['path']]);
|
$this->logger->info('Dumping {file}', ['emoji' => Emoji::pencil() . ' ', 'file' => $file['path']]);
|
||||||
echo $this->configFilesystem->read($file['path']);
|
echo $this->configFilesystem->read($file['path']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue