synced with upstream
This commit is contained in:
commit
c252a1e4ea
54 changed files with 1410 additions and 414 deletions
32
.github/workflows/ci.yaml
vendored
32
.github/workflows/ci.yaml
vendored
|
@ -42,7 +42,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
||||||
id: filter
|
id: filter
|
||||||
|
@ -68,7 +68,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Run Gosec Security Scanner
|
- name: Run Gosec Security Scanner
|
||||||
uses: securego/gosec@c5ea1b7bdd9efc3792e513258853552b0ae31e06 # v2.16.0
|
uses: securego/gosec@c5ea1b7bdd9efc3792e513258853552b0ae31e06 # v2.16.0
|
||||||
|
@ -85,7 +85,7 @@ jobs:
|
||||||
(needs.changes.outputs.go == 'true')
|
(needs.changes.outputs.go == 'true')
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
id: go
|
id: go
|
||||||
|
@ -104,7 +104,7 @@ jobs:
|
||||||
(needs.changes.outputs.go == 'true')
|
(needs.changes.outputs.go == 'true')
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
id: go
|
id: go
|
||||||
|
@ -123,7 +123,7 @@ jobs:
|
||||||
(needs.changes.outputs.go == 'true')
|
(needs.changes.outputs.go == 'true')
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
id: go
|
id: go
|
||||||
|
@ -144,7 +144,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
id: go
|
id: go
|
||||||
|
@ -154,11 +154,11 @@ jobs:
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0
|
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0
|
uses: docker/setup-buildx-action@6a58db7e0d21ca03e6c44877909e80e45217eed2 # v2.6.0
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1
|
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1
|
||||||
|
@ -286,7 +286,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: cache
|
- name: cache
|
||||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||||
|
@ -336,7 +336,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: cache
|
- name: cache
|
||||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||||
|
@ -380,7 +380,7 @@ jobs:
|
||||||
PLATFORMS: linux/amd64,linux/arm64
|
PLATFORMS: linux/amd64,linux/arm64
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
||||||
id: filter-images
|
id: filter-images
|
||||||
|
@ -391,6 +391,8 @@ jobs:
|
||||||
- 'images/custom-error-pages/**'
|
- 'images/custom-error-pages/**'
|
||||||
cfssl:
|
cfssl:
|
||||||
- 'images/cfssl/**'
|
- 'images/cfssl/**'
|
||||||
|
fastcgi-helloserver:
|
||||||
|
- 'images/fastcgi-helloserver/**'
|
||||||
echo:
|
echo:
|
||||||
- 'images/echo/**'
|
- 'images/echo/**'
|
||||||
go-grpc-greeter-server:
|
go-grpc-greeter-server:
|
||||||
|
@ -410,6 +412,10 @@ jobs:
|
||||||
if: ${{ steps.filter-images.outputs.cfssl == 'true' }}
|
if: ${{ steps.filter-images.outputs.cfssl == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
cd images/cfssl && make build
|
cd images/cfssl && make build
|
||||||
|
- name: fastcgi-helloserver
|
||||||
|
if: ${{ steps.filter-images.outputs.fastcgi-helloserver == 'true' }}
|
||||||
|
run: |
|
||||||
|
cd images/fastcgi-helloserver && make build
|
||||||
- name: echo image build
|
- name: echo image build
|
||||||
if: ${{ steps.filter-images.outputs.echo == 'true' }}
|
if: ${{ steps.filter-images.outputs.echo == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
|
@ -447,7 +453,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
||||||
id: filter-images
|
id: filter-images
|
||||||
|
|
2
.github/workflows/depreview.yaml
vendored
2
.github/workflows/depreview.yaml
vendored
|
@ -9,6 +9,6 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout Repository'
|
- name: 'Checkout Repository'
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- name: 'Dependency Review'
|
- name: 'Dependency Review'
|
||||||
uses: actions/dependency-review-action@1360a344ccb0ab6e9475edef90ad2f46bf8003b1 # v3.0.6
|
uses: actions/dependency-review-action@1360a344ccb0ab6e9475edef90ad2f46bf8003b1 # v3.0.6
|
||||||
|
|
4
.github/workflows/docs.yaml
vendored
4
.github/workflows/docs.yaml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1
|
||||||
id: filter
|
id: filter
|
||||||
|
@ -47,7 +47,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout master
|
- name: Checkout master
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
uses: ./.github/actions/mkdocs
|
uses: ./.github/actions/mkdocs
|
||||||
|
|
4
.github/workflows/helm.yaml
vendored
4
.github/workflows/helm.yaml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Run Artifact Hub lint
|
- name: Run Artifact Hub lint
|
||||||
run: |
|
run: |
|
||||||
|
@ -61,7 +61,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout master
|
- name: Checkout master
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
with:
|
with:
|
||||||
# Fetch entire history. Required for chart-releaser; see https://github.com/helm/chart-releaser-action/issues/13#issuecomment-602063896
|
# Fetch entire history. Required for chart-releaser; see https://github.com/helm/chart-releaser-action/issues/13#issuecomment-602063896
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
2
.github/workflows/perftest.yaml
vendored
2
.github/workflows/perftest.yaml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- name: Install K6
|
- name: Install K6
|
||||||
run: |
|
run: |
|
||||||
|
|
2
.github/workflows/plugin.yaml
vendored
2
.github/workflows/plugin.yaml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout code"
|
- name: "Checkout code"
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
|
6
.github/workflows/vulnerability-scans.yaml
vendored
6
.github/workflows/vulnerability-scans.yaml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
||||||
versions: ${{ steps.version.outputs.TAGS }}
|
versions: ${{ steps.version.outputs.TAGS }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ jobs:
|
||||||
versions: ${{ fromJSON(needs.version.outputs.versions) }}
|
versions: ${{ fromJSON(needs.version.outputs.versions) }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
|
|
||||||
- shell: bash
|
- shell: bash
|
||||||
id: test
|
id: test
|
||||||
|
@ -60,7 +60,7 @@ jobs:
|
||||||
|
|
||||||
- name: Scan image with AquaSec/Trivy
|
- name: Scan image with AquaSec/Trivy
|
||||||
id: scan
|
id: scan
|
||||||
uses: aquasecurity/trivy-action@e5f43133f6e8736992c9f3c1b3296e24b37e17f2 # v0.10.0
|
uses: aquasecurity/trivy-action@41f05d9ecffa2ed3f1580af306000f734b733e54 # v0.11.2
|
||||||
with:
|
with:
|
||||||
image-ref: registry.k8s.io/ingress-nginx/controller:${{ matrix.versions }}
|
image-ref: registry.k8s.io/ingress-nginx/controller:${{ matrix.versions }}
|
||||||
format: 'sarif'
|
format: 'sarif'
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
|
|
||||||
- [cfssl](https://github.com/kubernetes/ingress-nginx/tree/main/images/cfssl)
|
- [cfssl](https://github.com/kubernetes/ingress-nginx/tree/main/images/cfssl)
|
||||||
|
|
||||||
|
- [fastcgi-helloserver](https://github.com/kubernetes/ingress-nginx/tree/main/images/fastcgi-helloserver)
|
||||||
|
|
||||||
- [httpbin](https://github.com/kubernetes/ingress-nginx/tree/main/images/httpbin)
|
- [httpbin](https://github.com/kubernetes/ingress-nginx/tree/main/images/httpbin)
|
||||||
|
|
||||||
- [kube-webhook-certgen](https://github.com/kubernetes/ingress-nginx/tree/main/images/kube-webhook-certgen)
|
- [kube-webhook-certgen](https://github.com/kubernetes/ingress-nginx/tree/main/images/kube-webhook-certgen)
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -262,3 +262,8 @@ release: ensure-buildx clean
|
||||||
--build-arg COMMIT_SHA="$(COMMIT_SHA)" \
|
--build-arg COMMIT_SHA="$(COMMIT_SHA)" \
|
||||||
--build-arg BUILD_ID="$(BUILD_ID)" \
|
--build-arg BUILD_ID="$(BUILD_ID)" \
|
||||||
-t $(REGISTRY)/controller-chroot:$(TAG) rootfs -f rootfs/Dockerfile-chroot
|
-t $(REGISTRY)/controller-chroot:$(TAG) rootfs -f rootfs/Dockerfile-chroot
|
||||||
|
|
||||||
|
.PHONY: build-docs
|
||||||
|
build-docs:
|
||||||
|
pip install -U mkdocs-material==6.2.4 mkdocs-awesome-pages-plugin mkdocs-minify-plugin mkdocs-redirects
|
||||||
|
mkdocs build --config-file mkdocs.yml
|
||||||
|
|
|
@ -201,8 +201,12 @@ Extra modules.
|
||||||
|
|
||||||
- name: {{ .name }}
|
- name: {{ .name }}
|
||||||
image: {{ .image }}
|
image: {{ .image }}
|
||||||
|
{{- if .distroless | default false }}
|
||||||
|
command: ['/init_module']
|
||||||
|
{{- else }}
|
||||||
command: ['sh', '-c', '/usr/local/bin/init_module.sh']
|
command: ['sh', '-c', '/usr/local/bin/init_module.sh']
|
||||||
{{- if (.containerSecurityContext) }}
|
{{- end }}
|
||||||
|
{{- if .containerSecurityContext }}
|
||||||
securityContext: {{ .containerSecurityContext | toYaml | nindent 4 }}
|
securityContext: {{ .containerSecurityContext | toYaml | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|
|
@ -190,7 +190,7 @@ spec:
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.controller.opentelemetry.enabled}}
|
{{- if .Values.controller.opentelemetry.enabled}}
|
||||||
{{ $otelContainerSecurityContext := $.Values.controller.opentelemetry.containerSecurityContext | default $.Values.controller.containerSecurityContext }}
|
{{ $otelContainerSecurityContext := $.Values.controller.opentelemetry.containerSecurityContext | default $.Values.controller.containerSecurityContext }}
|
||||||
{{- include "extraModules" (dict "name" "opentelemetry" "image" .Values.controller.opentelemetry.image "containerSecurityContext" $otelContainerSecurityContext) | nindent 8}}
|
{{- include "extraModules" (dict "name" "opentelemetry" "image" .Values.controller.opentelemetry.image "containerSecurityContext" $otelContainerSecurityContext "distroless" false) | nindent 8}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.controller.hostNetwork }}
|
{{- if .Values.controller.hostNetwork }}
|
||||||
|
|
|
@ -108,6 +108,7 @@ Do not try to edit it manually.
|
||||||
- [should set backend protocol to $scheme:// and use proxy_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L49)
|
- [should set backend protocol to $scheme:// and use proxy_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L49)
|
||||||
- [should set backend protocol to grpc:// and use grpc_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L64)
|
- [should set backend protocol to grpc:// and use grpc_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L64)
|
||||||
- [should set backend protocol to grpcs:// and use grpc_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L79)
|
- [should set backend protocol to grpcs:// and use grpc_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L79)
|
||||||
|
- [should set backend protocol to '' and use fastcgi_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L94)
|
||||||
- [should set backend protocol to '' and use ajp_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L109)
|
- [should set backend protocol to '' and use ajp_pass](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/backendprotocol.go#L109)
|
||||||
|
|
||||||
### [canary-*](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L36)
|
### [canary-*](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L36)
|
||||||
|
@ -191,6 +192,13 @@ Do not try to edit it manually.
|
||||||
- [disable-http-access-log set access_log off](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/disableaccesslog.go#L53)
|
- [disable-http-access-log set access_log off](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/disableaccesslog.go#L53)
|
||||||
- [disable-stream-access-log set access_log off](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/disableaccesslog.go#L71)
|
- [disable-stream-access-log set access_log off](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/disableaccesslog.go#L71)
|
||||||
|
|
||||||
|
### [backend-protocol - FastCGI](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/fastcgi.go#L30)
|
||||||
|
|
||||||
|
- [should use fastcgi_pass in the configuration file](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/fastcgi.go#L37)
|
||||||
|
- [should add fastcgi_index in the configuration file](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/fastcgi.go#L54)
|
||||||
|
- [should add fastcgi_param in the configuration file](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/fastcgi.go#L71)
|
||||||
|
- [should return OK for service with backend protocol FastCGI](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/fastcgi.go#L102)
|
||||||
|
|
||||||
### [force-ssl-redirect](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/forcesslredirect.go#L27)
|
### [force-ssl-redirect](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/forcesslredirect.go#L27)
|
||||||
|
|
||||||
- [should redirect to https](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/forcesslredirect.go#L34)
|
- [should redirect to https](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/forcesslredirect.go#L34)
|
||||||
|
@ -342,101 +350,6 @@ Do not try to edit it manually.
|
||||||
- [should set the X-Forwarded-Prefix to the annotation value](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/xforwardedprefix.go#L35)
|
- [should set the X-Forwarded-Prefix to the annotation value](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/xforwardedprefix.go#L35)
|
||||||
- [should not add X-Forwarded-Prefix if the annotation value is empty](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/xforwardedprefix.go#L57)
|
- [should not add X-Forwarded-Prefix if the annotation value is empty](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/xforwardedprefix.go#L57)
|
||||||
|
|
||||||
### [denylist-source-range](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L28)
|
|
||||||
|
|
||||||
- [only deny explicitly denied IPs, allow all others](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L35)
|
|
||||||
- [only allow explicitly allowed IPs, deny all others](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L86)
|
|
||||||
|
|
||||||
### [affinity session-cookie-name](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L35)
|
|
||||||
|
|
||||||
- [should set sticky cookie SERVERID](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L42)
|
|
||||||
- [should change cookie name on ingress definition change](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L64)
|
|
||||||
- [should set the path to /something on the generated cookie](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L99)
|
|
||||||
- [does not set the path to / on the generated cookie if there's more than one rule referring to the same backend](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L121)
|
|
||||||
- [should set cookie with expires](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L194)
|
|
||||||
- [should set cookie with domain](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L225)
|
|
||||||
- [should not set cookie without domain annotation](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L248)
|
|
||||||
- [should work with use-regex annotation and session-cookie-path](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L270)
|
|
||||||
- [should warn user when use-regex is true and session-cookie-path is not set](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L294)
|
|
||||||
- [should not set affinity across all server locations when using separate ingresses](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L320)
|
|
||||||
- [should set sticky cookie without host](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L352)
|
|
||||||
- [should work with server-alias annotation](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L372)
|
|
||||||
- [should set secure in cookie with provided true annotation on http](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L412)
|
|
||||||
- [should not set secure in cookie with provided false annotation on http](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L435)
|
|
||||||
- [should set secure in cookie with provided false annotation on https](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L458)
|
|
||||||
|
|
||||||
### [rewrite-target use-regex enable-rewrite-log](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L30)
|
|
||||||
|
|
||||||
- [should write rewrite logs](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L37)
|
|
||||||
- [should use correct longest path match](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L66)
|
|
||||||
- [should use ~* location modifier if regex annotation is present](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L111)
|
|
||||||
- [should fail to use longest match for documented warning](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L158)
|
|
||||||
- [should allow for custom rewrite parameters](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L190)
|
|
||||||
|
|
||||||
### [auth-*](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L39)
|
|
||||||
|
|
||||||
- [should return status code 200 when no authentication is configured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L46)
|
|
||||||
- [should return status code 503 when authentication is configured with an invalid secret](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L65)
|
|
||||||
- [should return status code 401 when authentication is configured but Authorization header is not configured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L89)
|
|
||||||
- [should return status code 401 when authentication is configured and Authorization header is sent with invalid credentials](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L116)
|
|
||||||
- [should return status code 401 and cors headers when authentication and cors is configured but Authorization header is not configured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L144)
|
|
||||||
- [should return status code 200 when authentication is configured and Authorization header is sent](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L172)
|
|
||||||
- [should return status code 200 when authentication is configured with a map and Authorization header is sent](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L199)
|
|
||||||
- [should return status code 401 when authentication is configured with invalid content and Authorization header is sent](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L227)
|
|
||||||
- [ when external auth is configured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L266)
|
|
||||||
- [ when external auth is not configured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L284)
|
|
||||||
- [ when auth-headers are set](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L301)
|
|
||||||
- [should set cache_key when external auth cache is configured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L322)
|
|
||||||
- [user retains cookie by default](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L411)
|
|
||||||
- [user does not retain cookie if upstream returns error status code](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L422)
|
|
||||||
- [user with annotated ingress retains cookie if upstream returns error status code](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L433)
|
|
||||||
- [should return status code 200 when signed in](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L485)
|
|
||||||
- [should redirect to signin url when not signed in](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L494)
|
|
||||||
- [keeps processing new ingresses even if one of the existing ingresses is misconfigured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L505)
|
|
||||||
- [should overwrite Foo header with auth response](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L529)
|
|
||||||
- [should not create additional upstream block when auth-keepalive is not set](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L552)
|
|
||||||
- [should not create additional upstream block when host part of auth-url contains a variable](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L570)
|
|
||||||
- [should not create additional upstream block when auth-keepalive is negative](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L590)
|
|
||||||
- [should not create additional upstream block when auth-keepalive is set with HTTP/2](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L609)
|
|
||||||
- [should create additional upstream block when auth-keepalive is set with HTTP/1.x](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L623)
|
|
||||||
- [should return status code 200 when signed in](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L678)
|
|
||||||
- [should redirect to signin url when not signed in](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L687)
|
|
||||||
- [keeps processing new ingresses even if one of the existing ingresses is misconfigured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L698)
|
|
||||||
- [should return status code 200 when signed in after auth backend is deleted ](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L772)
|
|
||||||
- [should deny login for different location on same server](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L792)
|
|
||||||
- [should deny login for different servers](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L820)
|
|
||||||
- [should redirect to signin url when not signed in](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L849)
|
|
||||||
- [should return 503 (location was denied)](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L879)
|
|
||||||
- [should add error to the config](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L887)
|
|
||||||
|
|
||||||
### [canary-*](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L36)
|
|
||||||
|
|
||||||
- [should response with a 200 status from the mainline upstream when requests are made to the mainline ingress](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L48)
|
|
||||||
- [should return 404 status for requests to the canary if no matching ingress is found](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L80)
|
|
||||||
- [should return the correct status codes when endpoints are unavailable](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L107)
|
|
||||||
- [should route requests to the correct upstream if mainline ingress is created before the canary ingress](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L161)
|
|
||||||
- [should route requests to the correct upstream if mainline ingress is created after the canary ingress](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L206)
|
|
||||||
- [should route requests to the correct upstream if the mainline ingress is modified](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L250)
|
|
||||||
- [should route requests to the correct upstream if the canary ingress is modified](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L307)
|
|
||||||
- [should route requests to the correct upstream](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L372)
|
|
||||||
- [should route requests to the correct upstream](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L426)
|
|
||||||
- [should route requests to the correct upstream](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L490)
|
|
||||||
- [should route requests to the correct upstream](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L532)
|
|
||||||
- [should routes to mainline upstream when the given Regex causes error](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L566)
|
|
||||||
- [should route requests to the correct upstream](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L604)
|
|
||||||
- [respects always and never values](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L643)
|
|
||||||
- [should route requests only to mainline if canary weight is 0](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L705)
|
|
||||||
- [should route requests only to canary if canary weight is 100](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L743)
|
|
||||||
- [should route requests only to canary if canary weight is equal to canary weight total](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L775)
|
|
||||||
- [should route requests split between mainline and canary if canary weight is 50](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L808)
|
|
||||||
- [should route requests split between mainline and canary if canary weight is 100 and weight total is 200](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L834)
|
|
||||||
- [should not use canary as a catch-all server](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L863)
|
|
||||||
- [should not use canary with domain as a server](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L891)
|
|
||||||
- [does not crash when canary ingress has multiple paths to the same non-matching backend](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L915)
|
|
||||||
- [always routes traffic to canary if first request was affinitized to canary (default behavior)](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L943)
|
|
||||||
- [always routes traffic to canary if first request was affinitized to canary (explicit sticky behavior)](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L1000)
|
|
||||||
- [routes traffic to either mainline or canary backend (legacy behavior)](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/canary.go#L1058)
|
|
||||||
|
|
||||||
### [Debug CLI](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/dbg/main.go#L29)
|
### [Debug CLI](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/dbg/main.go#L29)
|
||||||
|
|
||||||
- [should list the backend servers](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/dbg/main.go#L37)
|
- [should list the backend servers](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/dbg/main.go#L37)
|
||||||
|
@ -485,6 +398,10 @@ Do not try to edit it manually.
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/exec.go#L)
|
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/exec.go#L)
|
||||||
|
|
||||||
|
### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/fastcgi_helloserver.go#L)
|
||||||
|
|
||||||
|
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/fastcgi_helloserver.go#L)
|
||||||
|
|
||||||
### [[Setting] ](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/framework.go#L194)
|
### [[Setting] ](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/framework.go#L194)
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/framework.go#L)
|
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/framework.go#L)
|
||||||
|
@ -561,30 +478,6 @@ Do not try to edit it manually.
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/util.go#L)
|
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/util.go#L)
|
||||||
|
|
||||||
### [[Setting] ](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/framework.go#L194)
|
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/framework.go#L)
|
|
||||||
|
|
||||||
### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/healthz.go#L)
|
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/healthz.go#L)
|
|
||||||
|
|
||||||
### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/k8s.go#L)
|
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/k8s.go#L)
|
|
||||||
|
|
||||||
### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/metrics.go#L)
|
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/metrics.go#L)
|
|
||||||
|
|
||||||
### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/deployment.go#L)
|
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/deployment.go#L)
|
|
||||||
|
|
||||||
### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/exec.go#L)
|
|
||||||
|
|
||||||
- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/exec.go#L)
|
|
||||||
|
|
||||||
### [[Shutdown] Grace period shutdown](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/gracefulshutdown/grace_period.go#L32)
|
### [[Shutdown] Grace period shutdown](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/gracefulshutdown/grace_period.go#L32)
|
||||||
|
|
||||||
- [/healthz should return status code 500 during shutdown grace period](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/gracefulshutdown/grace_period.go#L35)
|
- [/healthz should return status code 500 during shutdown grace period](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/gracefulshutdown/grace_period.go#L35)
|
||||||
|
|
|
@ -200,6 +200,7 @@ kubectl ingress-nginx conf -n ingress-nginx --host testaddr.local
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ kubectl ingress-nginx exec -i -n ingress-nginx -- ls /etc/nginx
|
$ kubectl ingress-nginx exec -i -n ingress-nginx -- ls /etc/nginx
|
||||||
|
fastcgi_params
|
||||||
geoip
|
geoip
|
||||||
lua
|
lua
|
||||||
mime.types
|
mime.types
|
||||||
|
|
|
@ -2,10 +2,118 @@
|
||||||
|
|
||||||
# Exposing FastCGI Servers
|
# Exposing FastCGI Servers
|
||||||
|
|
||||||
**This feature has been removed from Ingress NGINX**
|
> **FastCGI** is a [binary protocol](https://en.wikipedia.org/wiki/Binary_protocol "Binary protocol") for interfacing interactive programs with a [web server](https://en.wikipedia.org/wiki/Web_server "Web server"). [...] (It's) aim is to reduce the overhead related to interfacing between web server and CGI programs, allowing a server to handle more web page requests per unit of time.
|
||||||
|
>
|
||||||
|
> — Wikipedia
|
||||||
|
|
||||||
People willing to use fastcgi servers, should create an NGINX + FastCGI service and expose
|
The _ingress-nginx_ ingress controller can be used to directly expose [FastCGI](https://en.wikipedia.org/wiki/FastCGI) servers. Enabling FastCGI in your Ingress only requires setting the _backend-protocol_ annotation to `FCGI`, and with a couple more annotations you can customize the way _ingress-nginx_ handles the communication with your FastCGI _server_.
|
||||||
this service via Ingress NGINX.
|
|
||||||
|
|
||||||
We recommend using images like `cgr.dev/chainguard/nginx:latest` and expose your fast_cgi application
|
|
||||||
as another container on this Pod.
|
## Example Objects to Expose a FastCGI Pod
|
||||||
|
|
||||||
|
The _Pod_ example object below exposes port `9000`, which is the conventional FastCGI port.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: example-app
|
||||||
|
labels:
|
||||||
|
app: example-app
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: example-app
|
||||||
|
image: example-app:1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 9000
|
||||||
|
name: fastcgi
|
||||||
|
```
|
||||||
|
|
||||||
|
The _Service_ object example below matches port `9000` from the _Pod_ object above.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: example-service
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: example-app
|
||||||
|
ports:
|
||||||
|
- port: 9000
|
||||||
|
targetPort: 9000
|
||||||
|
name: fastcgi
|
||||||
|
```
|
||||||
|
|
||||||
|
And the _Ingress_ and _ConfigMap_ objects below demonstrates the supported _FastCGI_ specific annotations (NGINX actually has 50 FastCGI directives, all of which have not been exposed in the ingress yet), and matches the service `example-service`, and the port named `fastcgi` from above. The _ConfigMap_ **must** be created first for the _Ingress Controller_ to be able to find it when the _Ingress_ object is created, otherwise you will need to restart the _Ingress Controller_ pods.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# The ConfigMap MUST be created first for the ingress controller to be able to
|
||||||
|
# find it when the Ingress object is created.
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: example-cm
|
||||||
|
data:
|
||||||
|
SCRIPT_FILENAME: "/example/index.php"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/backend-protocol: "FCGI"
|
||||||
|
nginx.ingress.kubernetes.io/fastcgi-index: "index.php"
|
||||||
|
nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-cm"
|
||||||
|
name: example-app
|
||||||
|
spec:
|
||||||
|
ingressClassName: nginx
|
||||||
|
rules:
|
||||||
|
- host: app.example.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: example-service
|
||||||
|
port:
|
||||||
|
name: fastcgi
|
||||||
|
```
|
||||||
|
|
||||||
|
## FastCGI Ingress Annotations
|
||||||
|
|
||||||
|
To enable FastCGI, the `nginx.ingress.kubernetes.io/backend-protocol` annotation needs to be set to `FCGI`, which overrides the default `HTTP` value.
|
||||||
|
|
||||||
|
> `nginx.ingress.kubernetes.io/backend-protocol: "FCGI"`
|
||||||
|
|
||||||
|
**This enables the _FastCGI_ mode for all paths defined in the _Ingress_ object**
|
||||||
|
|
||||||
|
### The `nginx.ingress.kubernetes.io/fastcgi-index` Annotation
|
||||||
|
|
||||||
|
To specify an index file, the `fastcgi-index` annotation value can optionally be set. In the example below, the value is set to `index.php`. This annotation corresponds to [the _NGINX_ `fastcgi_index` directive](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_index).
|
||||||
|
|
||||||
|
> `nginx.ingress.kubernetes.io/fastcgi-index: "index.php"`
|
||||||
|
|
||||||
|
### The `nginx.ingress.kubernetes.io/fastcgi-params-configmap` Annotation
|
||||||
|
|
||||||
|
To specify [_NGINX_ `fastcgi_param` directives](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_param), the `fastcgi-params-configmap` annotation is used, which in turn must lead to a _ConfigMap_ object containing the _NGINX_ `fastcgi_param` directives as key/values.
|
||||||
|
|
||||||
|
> `nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-configmap"`
|
||||||
|
|
||||||
|
And the _ConfigMap_ object to specify the `SCRIPT_FILENAME` and `HTTP_PROXY` _NGINX's_ `fastcgi_param` directives will look like the following:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: example-configmap
|
||||||
|
data:
|
||||||
|
SCRIPT_FILENAME: "/example/index.php"
|
||||||
|
HTTP_PROXY: ""
|
||||||
|
```
|
||||||
|
Using the _namespace/_ prefix is also supported, for example:
|
||||||
|
|
||||||
|
> `nginx.ingress.kubernetes.io/fastcgi-params-configmap: "example-namespace/example-configmap"`
|
||||||
|
|
|
@ -906,7 +906,7 @@ Include /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf
|
||||||
### Backend Protocol
|
### Backend Protocol
|
||||||
|
|
||||||
Using `backend-protocol` annotations is possible to indicate how NGINX should communicate with the backend service. (Replaces `secure-backends` in older versions)
|
Using `backend-protocol` annotations is possible to indicate how NGINX should communicate with the backend service. (Replaces `secure-backends` in older versions)
|
||||||
Valid Values: HTTP, HTTPS, GRPC, GRPCS, AJP
|
Valid Values: HTTP, HTTPS, GRPC, GRPCS, AJP and FCGI
|
||||||
|
|
||||||
By default NGINX uses `HTTP`.
|
By default NGINX uses `HTTP`.
|
||||||
|
|
||||||
|
|
59
images/fastcgi-helloserver/Makefile
Normal file
59
images/fastcgi-helloserver/Makefile
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
# Copyright 2020 The Kubernetes Authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Docker image for e2e testing.
|
||||||
|
|
||||||
|
# set default shell
|
||||||
|
SHELL=/bin/bash -o pipefail -o errexit
|
||||||
|
|
||||||
|
DIR:=$(strip $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))
|
||||||
|
INIT_BUILDX=$(DIR)/../../hack/init-buildx.sh
|
||||||
|
|
||||||
|
SHORT_SHA ?=$(shell git rev-parse --short HEAD)
|
||||||
|
TAG ?=v$(shell date +%Y%m%d)-$(SHORT_SHA)
|
||||||
|
|
||||||
|
REGISTRY ?= local
|
||||||
|
|
||||||
|
IMAGE = $(REGISTRY)/e2e-test-fastcgi-helloserver
|
||||||
|
|
||||||
|
# required to enable buildx
|
||||||
|
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
|
|
||||||
|
# build with buildx
|
||||||
|
PLATFORMS?=linux/amd64,linux/arm,linux/arm64
|
||||||
|
OUTPUT=
|
||||||
|
PROGRESS=plain
|
||||||
|
|
||||||
|
build: ensure-buildx
|
||||||
|
docker buildx build \
|
||||||
|
--platform=${PLATFORMS} $(OUTPUT) \
|
||||||
|
--progress=$(PROGRESS) \
|
||||||
|
--pull \
|
||||||
|
-t $(IMAGE):$(TAG) rootfs
|
||||||
|
|
||||||
|
# push the cross built image
|
||||||
|
push: OUTPUT=--push
|
||||||
|
push: build
|
||||||
|
|
||||||
|
# enable buildx
|
||||||
|
ensure-buildx:
|
||||||
|
# this is required for cloudbuild
|
||||||
|
ifeq ("$(wildcard $(INIT_BUILDX))","")
|
||||||
|
@curl -sSL https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/hack/init-buildx.sh | bash
|
||||||
|
else
|
||||||
|
@exec $(INIT_BUILDX)
|
||||||
|
endif
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
.PHONY: build push ensure-buildx
|
22
images/fastcgi-helloserver/cloudbuild.yaml
Normal file
22
images/fastcgi-helloserver/cloudbuild.yaml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
timeout: 1800s
|
||||||
|
options:
|
||||||
|
substitution_option: ALLOW_LOOSE
|
||||||
|
steps:
|
||||||
|
- name: gcr.io/k8s-staging-test-infra/gcb-docker-gcloud:v20211118-2f2d816b90
|
||||||
|
entrypoint: bash
|
||||||
|
env:
|
||||||
|
- DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
|
- SHORT_SHA=$SHORT_SHA
|
||||||
|
- BASE_REF=$_PULL_BASE_REF
|
||||||
|
- REGISTRY=gcr.io/k8s-staging-ingress-nginx
|
||||||
|
# default cloudbuild has HOME=/builder/home and docker buildx is in /root/.docker/cli-plugins/docker-buildx
|
||||||
|
# set the home to /root explicitly to if using docker buildx
|
||||||
|
- HOME=/root
|
||||||
|
args:
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
gcloud auth configure-docker \
|
||||||
|
&& cd images/fastcgi-helloserver && make push
|
||||||
|
substitutions:
|
||||||
|
_GIT_TAG: "12345"
|
||||||
|
_PULL_BASE_REF: "master"
|
32
images/fastcgi-helloserver/rootfs/Dockerfile
Executable file
32
images/fastcgi-helloserver/rootfs/Dockerfile
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
# Copyright 2017 The Kubernetes Authors. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
FROM golang:1.20.4-alpine3.18 as builder
|
||||||
|
|
||||||
|
WORKDIR /go/src/k8s.io/ingress-nginx/images/fastcgi
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN CGO_ENABLED=0 go build -a -installsuffix cgo \
|
||||||
|
-ldflags "-s -w" \
|
||||||
|
-o fastcgi-helloserver main.go
|
||||||
|
|
||||||
|
# Use distroless as minimal base image to package the binary
|
||||||
|
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||||
|
FROM gcr.io/distroless/static:nonroot
|
||||||
|
|
||||||
|
COPY --from=builder /go/src/k8s.io/ingress-nginx/images/fastcgi/fastcgi-helloserver /
|
||||||
|
USER nonroot:nonroot
|
||||||
|
|
||||||
|
CMD ["/fastcgi-helloserver"]
|
30
images/fastcgi-helloserver/rootfs/main.go
Normal file
30
images/fastcgi-helloserver/rootfs/main.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/fcgi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func hello(w http.ResponseWriter, r *http.Request) {
|
||||||
|
keys, ok := r.URL.Query()["name"]
|
||||||
|
|
||||||
|
if !ok || len(keys[0]) < 1 {
|
||||||
|
fmt.Fprintf(w, "Hello world!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
key := keys[0]
|
||||||
|
fmt.Fprintf(w, "Hello "+string(key)+"!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.HandleFunc("/hello", hello)
|
||||||
|
|
||||||
|
l, err := net.Listen("tcp", "0.0.0.0:9000")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fcgi.Serve(l, nil)
|
||||||
|
}
|
|
@ -21,9 +21,11 @@ COPY . /opt/third_party/
|
||||||
# install build tools
|
# install build tools
|
||||||
RUN apk update \
|
RUN apk update \
|
||||||
&& apk upgrade \
|
&& apk upgrade \
|
||||||
&& apk add -U bash cmake \
|
&& apk add -U bash cmake ninja \
|
||||||
&& bash /opt/third_party/build.sh -p
|
&& bash /opt/third_party/build.sh -p
|
||||||
|
|
||||||
|
ENV NINJA_STATUS "[%p/%f/%t]"
|
||||||
|
|
||||||
# install gRPC
|
# install gRPC
|
||||||
FROM base as grpc
|
FROM base as grpc
|
||||||
RUN bash /opt/third_party/build.sh -g v1.49.2
|
RUN bash /opt/third_party/build.sh -g v1.49.2
|
||||||
|
@ -39,7 +41,17 @@ COPY --from=grpc /opt/third_party/install/ /usr
|
||||||
COPY --from=otel-cpp /opt/third_party/install/ /usr
|
COPY --from=otel-cpp /opt/third_party/install/ /usr
|
||||||
RUN bash /opt/third_party/build.sh -n
|
RUN bash /opt/third_party/build.sh -n
|
||||||
|
|
||||||
FROM alpine:3.18.0 as final
|
FROM cgr.dev/chainguard/go:latest as build-init
|
||||||
COPY --from=base /opt/third_party/init_module.sh /usr/local/bin/init_module.sh
|
|
||||||
|
WORKDIR /go/src/app
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go mod download
|
||||||
|
RUN CGO_ENABLED=0 go build -o /go/bin/init_module
|
||||||
|
|
||||||
|
FROM cgr.dev/chainguard/static as final
|
||||||
|
COPY --from=build-init /go/bin/init_module /
|
||||||
COPY --from=nginx /etc/nginx/modules /etc/nginx/modules
|
COPY --from=nginx /etc/nginx/modules /etc/nginx/modules
|
||||||
COPY --from=nginx /opt/third_party/install/lib /etc/nginx/modules
|
COPY --from=nginx /opt/third_party/install/lib /etc/nginx/modules
|
||||||
|
|
||||||
|
CMD ["/init_module"]
|
||||||
|
|
|
@ -70,6 +70,7 @@ install_grpc()
|
||||||
mkdir -p $BUILD_PATH/grpc
|
mkdir -p $BUILD_PATH/grpc
|
||||||
cd ${BUILD_PATH}/grpc
|
cd ${BUILD_PATH}/grpc
|
||||||
cmake -DCMAKE_INSTALL_PREFIX=${INSTAL_DIR} \
|
cmake -DCMAKE_INSTALL_PREFIX=${INSTAL_DIR} \
|
||||||
|
-G Ninja \
|
||||||
-DGRPC_GIT_TAG=${GRPC_GIT_TAG} /opt/third_party \
|
-DGRPC_GIT_TAG=${GRPC_GIT_TAG} /opt/third_party \
|
||||||
-DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF \
|
-DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF \
|
||||||
-DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF \
|
-DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF \
|
||||||
|
@ -92,6 +93,7 @@ install_otel()
|
||||||
cd .build
|
cd .build
|
||||||
|
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release \
|
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-G Ninja \
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \
|
-DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \
|
||||||
-DWITH_ZIPKIN=OFF \
|
-DWITH_ZIPKIN=OFF \
|
||||||
-DWITH_JAEGER=OFF \
|
-DWITH_JAEGER=OFF \
|
||||||
|
@ -143,6 +145,7 @@ install_nginx()
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release \
|
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-G Ninja \
|
||||||
-DCMAKE_INSTALL_PREFIX=${INSTAL_DIR} \
|
-DCMAKE_INSTALL_PREFIX=${INSTAL_DIR} \
|
||||||
-DBUILD_SHARED_LIBS=ON \
|
-DBUILD_SHARED_LIBS=ON \
|
||||||
-DNGINX_VERSION=${NGINX_VERSION} \
|
-DNGINX_VERSION=${NGINX_VERSION} \
|
||||||
|
|
3
images/opentelemetry/rootfs/go.mod
Normal file
3
images/opentelemetry/rootfs/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module init-otel
|
||||||
|
|
||||||
|
go 1.20
|
104
images/opentelemetry/rootfs/init_module.go
Normal file
104
images/opentelemetry/rootfs/init_module.go
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Enable error handling for all operations
|
||||||
|
err := run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() error {
|
||||||
|
// Create the target directory if it doesn't exist
|
||||||
|
targetDir := "/modules_mount/etc/nginx/modules/otel"
|
||||||
|
err := os.MkdirAll(targetDir, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create target directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy files from source directory to target directory
|
||||||
|
sourceDir := "/etc/nginx/modules/"
|
||||||
|
err = filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip directories
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the destination path
|
||||||
|
relPath, err := filepath.Rel(sourceDir, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
destPath := filepath.Join(targetDir, relPath)
|
||||||
|
|
||||||
|
// Create the destination directory if it doesn't exist
|
||||||
|
destDir := filepath.Dir(destPath)
|
||||||
|
err = os.MkdirAll(destDir, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the file
|
||||||
|
err = copyFile(path, destPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to copy files: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFile(sourcePath, destPath string) error {
|
||||||
|
sourceFile, err := os.Open(sourcePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sourceFile.Close()
|
||||||
|
|
||||||
|
destFile, err := os.Create(destPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer destFile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(destFile, sourceFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Copyright 2021 The Kubernetes Authors.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
set -o nounset
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
mkdir -p /modules_mount/etc/nginx/modules/otel
|
|
||||||
cp -R /etc/nginx/modules/* /modules_mount/etc/nginx/modules/otel
|
|
|
@ -42,6 +42,7 @@ import (
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/customhttperrors"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/customhttperrors"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/defaultbackend"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/defaultbackend"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/annotations/fastcgi"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/globalratelimit"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/globalratelimit"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/http2pushpreload"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/http2pushpreload"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ipdenylist"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/ipdenylist"
|
||||||
|
@ -87,6 +88,8 @@ type Ingress struct {
|
||||||
CustomHTTPErrors []int
|
CustomHTTPErrors []int
|
||||||
DisableProxyInterceptErrors bool
|
DisableProxyInterceptErrors bool
|
||||||
DefaultBackend *apiv1.Service
|
DefaultBackend *apiv1.Service
|
||||||
|
//TODO: Change this back into an error when https://github.com/imdario/mergo/issues/100 is resolved
|
||||||
|
FastCGI fastcgi.Config
|
||||||
Denied *string
|
Denied *string
|
||||||
ExternalAuth authreq.Config
|
ExternalAuth authreq.Config
|
||||||
EnableGlobalAuth bool
|
EnableGlobalAuth bool
|
||||||
|
@ -138,6 +141,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
|
||||||
"CustomHTTPErrors": customhttperrors.NewParser(cfg),
|
"CustomHTTPErrors": customhttperrors.NewParser(cfg),
|
||||||
"DisableProxyInterceptErrors": disableproxyintercepterrors.NewParser(cfg),
|
"DisableProxyInterceptErrors": disableproxyintercepterrors.NewParser(cfg),
|
||||||
"DefaultBackend": defaultbackend.NewParser(cfg),
|
"DefaultBackend": defaultbackend.NewParser(cfg),
|
||||||
|
"FastCGI": fastcgi.NewParser(cfg),
|
||||||
"ExternalAuth": authreq.NewParser(cfg),
|
"ExternalAuth": authreq.NewParser(cfg),
|
||||||
"EnableGlobalAuth": authreqglobal.NewParser(cfg),
|
"EnableGlobalAuth": authreqglobal.NewParser(cfg),
|
||||||
"HTTP2PushPreload": http2pushpreload.NewParser(cfg),
|
"HTTP2PushPreload": http2pushpreload.NewParser(cfg),
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
const HTTP = "HTTP"
|
const HTTP = "HTTP"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
validProtocols = regexp.MustCompile(`^(AUTO_HTTP|HTTP|HTTPS|AJP|GRPC|GRPCS)$`)
|
validProtocols = regexp.MustCompile(`^(AUTO_HTTP|HTTP|HTTPS|AJP|GRPC|GRPCS|FCGI)$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type backendProtocol struct {
|
type backendProtocol struct {
|
||||||
|
|
106
internal/ingress/annotations/fastcgi/main.go
Normal file
106
internal/ingress/annotations/fastcgi/main.go
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fastcgi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
networking "k8s.io/api/networking/v1"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||||
|
ing_errors "k8s.io/ingress-nginx/internal/ingress/errors"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fastcgi struct {
|
||||||
|
r resolver.Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config describes the per location fastcgi config
|
||||||
|
type Config struct {
|
||||||
|
Index string `json:"index"`
|
||||||
|
Params map[string]string `json:"params"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal tests for equality between two Configuration types
|
||||||
|
func (l1 *Config) Equal(l2 *Config) bool {
|
||||||
|
if l1 == l2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if l1 == nil || l2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if l1.Index != l2.Index {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.DeepEqual(l1.Params, l2.Params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewParser creates a new fastcgiConfig protocol annotation parser
|
||||||
|
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||||
|
return fastcgi{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseAnnotations parses the annotations contained in the ingress
|
||||||
|
// rule used to indicate the fastcgiConfig.
|
||||||
|
func (a fastcgi) Parse(ing *networking.Ingress) (interface{}, error) {
|
||||||
|
|
||||||
|
fcgiConfig := Config{}
|
||||||
|
|
||||||
|
if ing.GetAnnotations() == nil {
|
||||||
|
return fcgiConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
index, err := parser.GetStringAnnotation("fastcgi-index", ing)
|
||||||
|
if err != nil {
|
||||||
|
index = ""
|
||||||
|
}
|
||||||
|
fcgiConfig.Index = index
|
||||||
|
|
||||||
|
cm, err := parser.GetStringAnnotation("fastcgi-params-configmap", ing)
|
||||||
|
if err != nil {
|
||||||
|
return fcgiConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cmns, cmn, err := cache.SplitMetaNamespaceKey(cm)
|
||||||
|
if err != nil {
|
||||||
|
return fcgiConfig, ing_errors.LocationDenied{
|
||||||
|
Reason: fmt.Errorf("error reading configmap name from annotation: %w", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmns != "" && cmns != ing.Namespace {
|
||||||
|
return fcgiConfig, fmt.Errorf("different namespace is not supported on fast_cgi param configmap")
|
||||||
|
}
|
||||||
|
|
||||||
|
cm = fmt.Sprintf("%v/%v", ing.Namespace, cmn)
|
||||||
|
cmap, err := a.r.GetConfigMap(cm)
|
||||||
|
if err != nil {
|
||||||
|
return fcgiConfig, ing_errors.LocationDenied{
|
||||||
|
Reason: fmt.Errorf("unexpected error reading configmap %s: %w", cm, err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fcgiConfig.Params = cmap.Data
|
||||||
|
|
||||||
|
return fcgiConfig, nil
|
||||||
|
}
|
285
internal/ingress/annotations/fastcgi/main_test.go
Normal file
285
internal/ingress/annotations/fastcgi/main_test.go
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fastcgi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
api "k8s.io/api/core/v1"
|
||||||
|
networking "k8s.io/api/networking/v1"
|
||||||
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildIngress() *networking.Ingress {
|
||||||
|
return &networking.Ingress{
|
||||||
|
ObjectMeta: meta_v1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
},
|
||||||
|
Spec: networking.IngressSpec{
|
||||||
|
DefaultBackend: &networking.IngressBackend{
|
||||||
|
Service: &networking.IngressServiceBackend{
|
||||||
|
Name: "default-backend",
|
||||||
|
Port: networking.ServiceBackendPort{
|
||||||
|
Number: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockConfigMap struct {
|
||||||
|
resolver.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mockConfigMap) GetConfigMap(name string) (*api.ConfigMap, error) {
|
||||||
|
if name != "default/demo-configmap" && name != "otherns/demo-configmap" {
|
||||||
|
return nil, fmt.Errorf("there is no configmap with name %v", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmns, cmn, err := cache.SplitMetaNamespaceKey(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid configmap name")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.ConfigMap{
|
||||||
|
ObjectMeta: meta_v1.ObjectMeta{
|
||||||
|
Namespace: cmns,
|
||||||
|
Name: cmn,
|
||||||
|
},
|
||||||
|
Data: map[string]string{"REDIRECT_STATUS": "200", "SERVER_NAME": "$server_name"},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseEmptyFastCGIAnnotations(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||||
|
}
|
||||||
|
|
||||||
|
config, ok := i.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Parse do not return a Config object")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Index != "" {
|
||||||
|
t.Errorf("Index should be an empty string")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.Params) != 0 {
|
||||||
|
t.Errorf("Params should be an empty slice")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseFastCGIIndexAnnotation(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
const expectedAnnotation = "index.php"
|
||||||
|
|
||||||
|
data := map[string]string{}
|
||||||
|
data[parser.GetAnnotationWithPrefix("fastcgi-index")] = expectedAnnotation
|
||||||
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
|
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||||
|
}
|
||||||
|
|
||||||
|
config, ok := i.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Parse do not return a Config object")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Index != "index.php" {
|
||||||
|
t.Errorf("expected %s but %v returned", expectedAnnotation, config.Index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseEmptyFastCGIParamsConfigMapAnnotation(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
data := map[string]string{}
|
||||||
|
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = ""
|
||||||
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
|
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||||
|
}
|
||||||
|
|
||||||
|
config, ok := i.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Parse do not return a Config object")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.Params) != 0 {
|
||||||
|
t.Errorf("Params should be an empty slice")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseFastCGIInvalidParamsConfigMapAnnotation(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
invalidConfigMapList := []string{"unknown/configMap", "unknown/config/map"}
|
||||||
|
for _, configmap := range invalidConfigMapList {
|
||||||
|
|
||||||
|
data := map[string]string{}
|
||||||
|
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = configmap
|
||||||
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
|
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Reading an unexisting configmap should return an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
config, ok := i.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Parse do not return a Config object")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.Params) != 0 {
|
||||||
|
t.Errorf("Params should be an empty slice")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseFastCGIParamsConfigMapAnnotationWithoutNS(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
data := map[string]string{}
|
||||||
|
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = "demo-configmap"
|
||||||
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
|
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||||
|
}
|
||||||
|
|
||||||
|
config, ok := i.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Parse do not return a Config object")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.Params) != 2 {
|
||||||
|
t.Errorf("Params should have a length of 2")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Params["REDIRECT_STATUS"] != "200" || config.Params["SERVER_NAME"] != "$server_name" {
|
||||||
|
t.Errorf("Params value is not the one expected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseFastCGIParamsConfigMapAnnotationWithNS(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
data := map[string]string{}
|
||||||
|
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = "default/demo-configmap"
|
||||||
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
|
i, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error parsing ingress without fastcgi")
|
||||||
|
}
|
||||||
|
|
||||||
|
config, ok := i.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Parse do not return a Config object")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.Params) != 2 {
|
||||||
|
t.Errorf("Params should have a length of 2")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Params["REDIRECT_STATUS"] != "200" || config.Params["SERVER_NAME"] != "$server_name" {
|
||||||
|
t.Errorf("Params value is not the one expected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseFastCGIParamsConfigMapAnnotationWithDifferentNS(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
data := map[string]string{}
|
||||||
|
data[parser.GetAnnotationWithPrefix("fastcgi-params-configmap")] = "otherns/demo-configmap"
|
||||||
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
|
_, err := NewParser(&mockConfigMap{}).Parse(ing)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Different namespace configmap should return an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigEquality(t *testing.T) {
|
||||||
|
|
||||||
|
var nilConfig *Config
|
||||||
|
|
||||||
|
config := Config{
|
||||||
|
Index: "index.php",
|
||||||
|
Params: map[string]string{"REDIRECT_STATUS": "200", "SERVER_NAME": "$server_name"},
|
||||||
|
}
|
||||||
|
|
||||||
|
configCopy := Config{
|
||||||
|
Index: "index.php",
|
||||||
|
Params: map[string]string{"REDIRECT_STATUS": "200", "SERVER_NAME": "$server_name"},
|
||||||
|
}
|
||||||
|
|
||||||
|
config2 := Config{
|
||||||
|
Index: "index.php",
|
||||||
|
Params: map[string]string{"REDIRECT_STATUS": "200"},
|
||||||
|
}
|
||||||
|
|
||||||
|
config3 := Config{
|
||||||
|
Index: "index.py",
|
||||||
|
Params: map[string]string{"SERVER_NAME": "$server_name", "REDIRECT_STATUS": "200"},
|
||||||
|
}
|
||||||
|
|
||||||
|
config4 := Config{
|
||||||
|
Index: "index.php",
|
||||||
|
Params: map[string]string{"SERVER_NAME": "$server_name", "REDIRECT_STATUS": "200"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.Equal(&config) {
|
||||||
|
t.Errorf("config should be equal to itself")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nilConfig.Equal(&config) {
|
||||||
|
t.Errorf("Foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.Equal(&configCopy) {
|
||||||
|
t.Errorf("config should be equal to configCopy")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Equal(&config2) {
|
||||||
|
t.Errorf("config2 should not be equal to config")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Equal(&config3) {
|
||||||
|
t.Errorf("config3 should not be equal to config")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.Equal(&config4) {
|
||||||
|
t.Errorf("config4 should be equal to config")
|
||||||
|
}
|
||||||
|
}
|
|
@ -160,6 +160,7 @@ func normalizeString(input string) string {
|
||||||
|
|
||||||
var configmapAnnotations = sets.NewString(
|
var configmapAnnotations = sets.NewString(
|
||||||
"auth-proxy-set-header",
|
"auth-proxy-set-header",
|
||||||
|
"fastcgi-params-configmap",
|
||||||
)
|
)
|
||||||
|
|
||||||
// AnnotationsReferencesConfigmap checks if at least one annotation in the Ingress rule
|
// AnnotationsReferencesConfigmap checks if at least one annotation in the Ingress rule
|
||||||
|
|
|
@ -271,8 +271,6 @@ func (n *NGINXController) CheckWarning(ing *networking.Ingress) ([]string, error
|
||||||
"influxdb-host",
|
"influxdb-host",
|
||||||
"influxdb-server-name",
|
"influxdb-server-name",
|
||||||
"secure-verify-ca-secret",
|
"secure-verify-ca-secret",
|
||||||
"fastcgi-params-configmap",
|
|
||||||
"fastcgi-index",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Skip checks if the ingress is marked as deleted
|
// Skip checks if the ingress is marked as deleted
|
||||||
|
@ -608,7 +606,7 @@ func (n *NGINXController) getConfiguration(ingresses []*ingress.Ingress) (sets.S
|
||||||
|
|
||||||
for _, server := range servers {
|
for _, server := range servers {
|
||||||
// If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of
|
// If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of
|
||||||
// proxy_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass, then the special processing is performed.
|
// proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass, then the special processing is performed.
|
||||||
// In response to a request with URI equal to // this string, but without the trailing slash, a permanent redirect with the
|
// In response to a request with URI equal to // this string, but without the trailing slash, a permanent redirect with the
|
||||||
// code 301 will be returned to the requested URI with the slash appended. If this is not desired, an exact match of the
|
// code 301 will be returned to the requested URI with the slash appended. If this is not desired, an exact match of the
|
||||||
// URIand location could be defined like this:
|
// URIand location could be defined like this:
|
||||||
|
@ -1519,6 +1517,7 @@ func locationApplyAnnotations(loc *ingress.Location, anns *annotations.Ingress)
|
||||||
loc.Logs = anns.Logs
|
loc.Logs = anns.Logs
|
||||||
loc.DefaultBackend = anns.DefaultBackend
|
loc.DefaultBackend = anns.DefaultBackend
|
||||||
loc.BackendProtocol = anns.BackendProtocol
|
loc.BackendProtocol = anns.BackendProtocol
|
||||||
|
loc.FastCGI = anns.FastCGI
|
||||||
loc.CustomHTTPErrors = anns.CustomHTTPErrors
|
loc.CustomHTTPErrors = anns.CustomHTTPErrors
|
||||||
loc.DisableProxyInterceptErrors = anns.DisableProxyInterceptErrors
|
loc.DisableProxyInterceptErrors = anns.DisableProxyInterceptErrors
|
||||||
loc.ModSecurity = anns.ModSecurity
|
loc.ModSecurity = anns.ModSecurity
|
||||||
|
|
|
@ -431,7 +431,7 @@ func TestCheckWarning(t *testing.T) {
|
||||||
t.Run("adding invalid annotations increases the warning count", func(t *testing.T) {
|
t.Run("adding invalid annotations increases the warning count", func(t *testing.T) {
|
||||||
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("enable-influxdb")] = "true"
|
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("enable-influxdb")] = "true"
|
||||||
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("secure-verify-ca-secret")] = "true"
|
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("secure-verify-ca-secret")] = "true"
|
||||||
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("fastcgi-index")] = "blabla"
|
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("influxdb-host")] = "blabla"
|
||||||
defer func() {
|
defer func() {
|
||||||
ing.ObjectMeta.Annotations = map[string]string{}
|
ing.ObjectMeta.Annotations = map[string]string{}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -739,6 +739,9 @@ func buildProxyPass(host string, b interface{}, loc interface{}) string {
|
||||||
case "AJP":
|
case "AJP":
|
||||||
proto = ""
|
proto = ""
|
||||||
proxyPass = "ajp_pass"
|
proxyPass = "ajp_pass"
|
||||||
|
case "FCGI":
|
||||||
|
proto = ""
|
||||||
|
proxyPass = "fastcgi_pass"
|
||||||
}
|
}
|
||||||
|
|
||||||
upstreamName := "upstream_balancer"
|
upstreamName := "upstream_balancer"
|
||||||
|
|
|
@ -1138,6 +1138,7 @@ func TestOpentracingPropagateContext(t *testing.T) {
|
||||||
{BackendProtocol: "GRPC"}: "opentracing_grpc_propagate_context;",
|
{BackendProtocol: "GRPC"}: "opentracing_grpc_propagate_context;",
|
||||||
{BackendProtocol: "GRPCS"}: "opentracing_grpc_propagate_context;",
|
{BackendProtocol: "GRPCS"}: "opentracing_grpc_propagate_context;",
|
||||||
{BackendProtocol: "AJP"}: "opentracing_propagate_context;",
|
{BackendProtocol: "AJP"}: "opentracing_propagate_context;",
|
||||||
|
{BackendProtocol: "FCGI"}: "opentracing_propagate_context;",
|
||||||
nil: "",
|
nil: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1157,6 +1158,7 @@ func TestOpentelemetryPropagateContext(t *testing.T) {
|
||||||
{BackendProtocol: "GRPC"}: "opentelemetry_propagate;",
|
{BackendProtocol: "GRPC"}: "opentelemetry_propagate;",
|
||||||
{BackendProtocol: "GRPCS"}: "opentelemetry_propagate;",
|
{BackendProtocol: "GRPCS"}: "opentelemetry_propagate;",
|
||||||
{BackendProtocol: "AJP"}: "opentelemetry_propagate;",
|
{BackendProtocol: "AJP"}: "opentelemetry_propagate;",
|
||||||
|
{BackendProtocol: "FCGI"}: "opentelemetry_propagate;",
|
||||||
nil: "",
|
nil: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
netlify.toml
Normal file
10
netlify.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# netlify configuration
|
||||||
|
[build]
|
||||||
|
publish = "site"
|
||||||
|
command = "make build-docs"
|
||||||
|
# available here https://github.com/netlify/build-image/blob/focal/included_software.md#languages
|
||||||
|
environment = { PYTHON_VERSION = "3.8" }
|
||||||
|
|
||||||
|
[context.deploy-preview]
|
||||||
|
publish = "site/"
|
||||||
|
command = "make build-docs"
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/authtls"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/authtls"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/connection"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/connection"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/annotations/fastcgi"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/globalratelimit"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/globalratelimit"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ipdenylist"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/ipdenylist"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist"
|
||||||
|
@ -339,6 +340,9 @@ type Location struct {
|
||||||
// BackendProtocol indicates which protocol should be used to communicate with the service
|
// BackendProtocol indicates which protocol should be used to communicate with the service
|
||||||
// By default this is HTTP
|
// By default this is HTTP
|
||||||
BackendProtocol string `json:"backend-protocol"`
|
BackendProtocol string `json:"backend-protocol"`
|
||||||
|
// FastCGI allows the ingress to act as a FastCGI client for a given location.
|
||||||
|
// +optional
|
||||||
|
FastCGI fastcgi.Config `json:"fastcgi,omitempty"`
|
||||||
// CustomHTTPErrors specifies the error codes that should be intercepted.
|
// CustomHTTPErrors specifies the error codes that should be intercepted.
|
||||||
// +optional
|
// +optional
|
||||||
CustomHTTPErrors []int `json:"custom-http-errors"`
|
CustomHTTPErrors []int `json:"custom-http-errors"`
|
||||||
|
|
|
@ -435,6 +435,10 @@ func (l1 *Location) Equal(l2 *Location) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !(&l1.FastCGI).Equal(&l2.FastCGI) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
match := compareInts(l1.CustomHTTPErrors, l2.CustomHTTPErrors)
|
match := compareInts(l1.CustomHTTPErrors, l2.CustomHTTPErrors)
|
||||||
if !match {
|
if !match {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -305,6 +305,7 @@ http {
|
||||||
keepalive_requests {{ $cfg.KeepAliveRequests }};
|
keepalive_requests {{ $cfg.KeepAliveRequests }};
|
||||||
|
|
||||||
client_body_temp_path /tmp/nginx/client-body;
|
client_body_temp_path /tmp/nginx/client-body;
|
||||||
|
fastcgi_temp_path /tmp/nginx/fastcgi-temp;
|
||||||
proxy_temp_path /tmp/nginx/proxy-temp;
|
proxy_temp_path /tmp/nginx/proxy-temp;
|
||||||
ajp_temp_path /tmp/nginx/ajp-temp;
|
ajp_temp_path /tmp/nginx/ajp-temp;
|
||||||
|
|
||||||
|
@ -1488,6 +1489,16 @@ stream {
|
||||||
{{ range $errCode := $location.CustomHTTPErrors }}
|
{{ range $errCode := $location.CustomHTTPErrors }}
|
||||||
error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }}
|
error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }}
|
||||||
|
|
||||||
|
{{ if (eq $location.BackendProtocol "FCGI") }}
|
||||||
|
include /etc/nginx/fastcgi_params;
|
||||||
|
{{ end }}
|
||||||
|
{{- if $location.FastCGI.Index -}}
|
||||||
|
fastcgi_index {{ $location.FastCGI.Index | quote }};
|
||||||
|
{{- end -}}
|
||||||
|
{{ range $k, $v := $location.FastCGI.Params }}
|
||||||
|
fastcgi_param {{ $k }} {{ $v | quote }};
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
{{ if not (empty $location.Redirect.URL) }}
|
{{ if not (empty $location.Redirect.URL) }}
|
||||||
return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }};
|
return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
1
test/e2e/HTTPBUN_IMAGE
Normal file
1
test/e2e/HTTPBUN_IMAGE
Normal file
|
@ -0,0 +1 @@
|
||||||
|
registry.k8s.io/ingress-nginx/e2e-test-httpbun:v20230505-v0.0.1
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.DescribeAnnotation("auth-*", func() {
|
var _ = framework.DescribeAnnotation("auth-*", func() {
|
||||||
f := framework.NewDefaultFramework("auth")
|
f := framework.NewDefaultFramework("auth", framework.WithHTTPBunEnabled())
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewEchoDeployment()
|
f.NewEchoDeployment()
|
||||||
|
@ -390,10 +389,10 @@ http {
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
||||||
|
|
||||||
httpbunIP := e.Subsets[0].Addresses[0].IP
|
nginxIP := e.Subsets[0].Addresses[0].IP
|
||||||
|
|
||||||
annotations = map[string]string{
|
annotations = map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/cookies/set/alma/armud", httpbunIP),
|
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/cookies/set/alma/armud", nginxIP),
|
||||||
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,21 +456,8 @@ http {
|
||||||
var ing *networking.Ingress
|
var ing *networking.Ingress
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
err := framework.WaitForEndpoints(f.KubeClientSet, framework.DefaultTimeout, framework.HTTPBunService, f.Namespace, 1)
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
e, err := f.KubeClientSet.CoreV1().Endpoints(f.Namespace).Get(context.TODO(), framework.HTTPBunService, metav1.GetOptions{})
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
|
||||||
|
|
||||||
httpbunIP := e.Subsets[0].Addresses[0].IP
|
|
||||||
|
|
||||||
annotations = map[string]string{
|
annotations = map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", httpbunIP),
|
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", f.HTTPBunIP),
|
||||||
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,20 +636,8 @@ http {
|
||||||
var ing *networking.Ingress
|
var ing *networking.Ingress
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
var httpbunIP string
|
|
||||||
|
|
||||||
err := framework.WaitForEndpoints(f.KubeClientSet, framework.DefaultTimeout, framework.HTTPBunService, f.Namespace, 1)
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
e, err := f.KubeClientSet.CoreV1().Endpoints(f.Namespace).Get(context.TODO(), framework.HTTPBunService, metav1.GetOptions{})
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
httpbunIP = e.Subsets[0].Addresses[0].IP
|
|
||||||
|
|
||||||
annotations = map[string]string{
|
annotations = map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", httpbunIP),
|
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", f.HTTPBunIP),
|
||||||
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
||||||
"nginx.ingress.kubernetes.io/auth-signin-redirect-param": "orig",
|
"nginx.ingress.kubernetes.io/auth-signin-redirect-param": "orig",
|
||||||
}
|
}
|
||||||
|
@ -729,23 +703,8 @@ http {
|
||||||
barPath := "/bar"
|
barPath := "/bar"
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
err := framework.WaitForEndpoints(f.KubeClientSet, framework.DefaultTimeout, framework.HTTPBunService, f.Namespace, 1)
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
framework.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
e, err := f.KubeClientSet.CoreV1().Endpoints(f.Namespace).Get(context.TODO(), framework.HTTPBunService, metav1.GetOptions{})
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
|
||||||
|
|
||||||
httpbunIP := e.Subsets[0].Addresses[0].IP
|
|
||||||
|
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", httpbunIP),
|
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", f.HTTPBunIP),
|
||||||
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
||||||
"nginx.ingress.kubernetes.io/auth-cache-key": "fixed",
|
"nginx.ingress.kubernetes.io/auth-cache-key": "fixed",
|
||||||
"nginx.ingress.kubernetes.io/auth-cache-duration": "200 201 401 30m",
|
"nginx.ingress.kubernetes.io/auth-cache-duration": "200 201 401 30m",
|
||||||
|
|
|
@ -91,6 +91,21 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should set backend protocol to '' and use fastcgi_pass", func() {
|
||||||
|
host := "backendprotocol.foo.com"
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
|
||||||
|
}
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "fastcgi_pass upstream_balancer;")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
ginkgo.It("should set backend protocol to '' and use ajp_pass", func() {
|
ginkgo.It("should set backend protocol to '' and use ajp_pass", func() {
|
||||||
host := "backendprotocol.foo.com"
|
host := "backendprotocol.foo.com"
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
|
|
125
test/e2e/annotations/fastcgi.go
Normal file
125
test/e2e/annotations/fastcgi.go
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package annotations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo/v2"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = framework.DescribeAnnotation("backend-protocol - FastCGI", func() {
|
||||||
|
f := framework.NewDefaultFramework("fastcgi")
|
||||||
|
|
||||||
|
ginkgo.BeforeEach(func() {
|
||||||
|
f.NewFastCGIHelloServerDeployment()
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should use fastcgi_pass in the configuration file", func() {
|
||||||
|
host := "fastcgi"
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
|
||||||
|
}
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, "/hello", host, f.Namespace, "fastcgi-helloserver", 9000, annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "include /etc/nginx/fastcgi_params;") &&
|
||||||
|
strings.Contains(server, "fastcgi_pass")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should add fastcgi_index in the configuration file", func() {
|
||||||
|
host := "fastcgi-index"
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
|
||||||
|
"nginx.ingress.kubernetes.io/fastcgi-index": "index.php",
|
||||||
|
}
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, "/hello", host, f.Namespace, "fastcgi-helloserver", 9000, annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "fastcgi_index \"index.php\";")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should add fastcgi_param in the configuration file", func() {
|
||||||
|
configuration := &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fastcgi-configmap",
|
||||||
|
Namespace: f.Namespace,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"SCRIPT_FILENAME": "/home/www/scripts/php$fastcgi_script_name",
|
||||||
|
"REDIRECT_STATUS": "200",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
f.EnsureConfigMap(configuration)
|
||||||
|
|
||||||
|
host := "fastcgi-params-configmap"
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
|
||||||
|
"nginx.ingress.kubernetes.io/fastcgi-params-configmap": "fastcgi-configmap",
|
||||||
|
}
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, "/hello", host, f.Namespace, "fastcgi-helloserver", 9000, annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "fastcgi_param SCRIPT_FILENAME \"/home/www/scripts/php$fastcgi_script_name\";") &&
|
||||||
|
strings.Contains(server, "fastcgi_param REDIRECT_STATUS \"200\";")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should return OK for service with backend protocol FastCGI", func() {
|
||||||
|
host := "fastcgi-helloserver"
|
||||||
|
path := "/hello"
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
|
||||||
|
}
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, path, host, f.Namespace, "fastcgi-helloserver", 9000, annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "fastcgi_pass")
|
||||||
|
})
|
||||||
|
|
||||||
|
f.HTTPTestClient().
|
||||||
|
GET(path).
|
||||||
|
WithHeader("Host", host).
|
||||||
|
Expect().
|
||||||
|
Status(http.StatusOK).
|
||||||
|
Body().Contains("Hello world!")
|
||||||
|
})
|
||||||
|
})
|
|
@ -37,7 +37,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
|
var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
|
||||||
f := framework.NewDefaultFramework("grpc")
|
f := framework.NewDefaultFramework("grpc", framework.WithHTTPBunEnabled())
|
||||||
|
|
||||||
ginkgo.It("should use grpc_pass in the configuration file", func() {
|
ginkgo.It("should use grpc_pass in the configuration file", func() {
|
||||||
f.NewGRPCFortuneTellerDeployment()
|
f.NewGRPCFortuneTellerDeployment()
|
||||||
|
@ -124,8 +124,6 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
|
||||||
|
|
||||||
ginkgo.It("authorization metadata should be overwritten by external auth response headers", func() {
|
ginkgo.It("authorization metadata should be overwritten by external auth response headers", func() {
|
||||||
f.NewGRPCBinDeployment()
|
f.NewGRPCBinDeployment()
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
host := "echo"
|
host := "echo"
|
||||||
|
|
||||||
svc := &corev1.Service{
|
svc := &corev1.Service{
|
||||||
|
@ -148,19 +146,8 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
|
||||||
}
|
}
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
err := framework.WaitForEndpoints(f.KubeClientSet, framework.DefaultTimeout, framework.HTTPBunService, f.Namespace, 1)
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
e, err := f.KubeClientSet.CoreV1().Endpoints(f.Namespace).Get(context.TODO(), framework.HTTPBunService, metav1.GetOptions{})
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
|
||||||
|
|
||||||
httpbunIP := e.Subsets[0].Addresses[0].IP
|
|
||||||
|
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/response-headers?authorization=foo", httpbunIP),
|
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/response-headers?authorization=foo", f.HTTPBunIP),
|
||||||
"nginx.ingress.kubernetes.io/auth-response-headers": "Authorization",
|
"nginx.ingress.kubernetes.io/auth-response-headers": "Authorization",
|
||||||
"nginx.ingress.kubernetes.io/backend-protocol": "GRPC",
|
"nginx.ingress.kubernetes.io/backend-protocol": "GRPC",
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package annotations
|
package annotations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -27,13 +26,12 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
networking "k8s.io/api/networking/v1"
|
networking "k8s.io/api/networking/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/test/e2e/framework"
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.DescribeAnnotation("satisfy", func() {
|
var _ = framework.DescribeAnnotation("satisfy", func() {
|
||||||
f := framework.NewDefaultFramework("satisfy")
|
f := framework.NewDefaultFramework("satisfy", framework.WithHTTPBunEnabled())
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewEchoDeployment()
|
f.NewEchoDeployment()
|
||||||
|
@ -84,17 +82,6 @@ var _ = framework.DescribeAnnotation("satisfy", func() {
|
||||||
ginkgo.It("should allow multiple auth with satisfy any", func() {
|
ginkgo.It("should allow multiple auth with satisfy any", func() {
|
||||||
host := "auth"
|
host := "auth"
|
||||||
|
|
||||||
// setup external auth
|
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
err := framework.WaitForEndpoints(f.KubeClientSet, framework.DefaultTimeout, framework.HTTPBunService, f.Namespace, 1)
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
e, err := f.KubeClientSet.CoreV1().Endpoints(f.Namespace).Get(context.TODO(), framework.HTTPBunService, metav1.GetOptions{})
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
httpbunIP := e.Subsets[0].Addresses[0].IP
|
|
||||||
|
|
||||||
// create basic auth secret at ingress
|
// create basic auth secret at ingress
|
||||||
s := f.EnsureSecret(buildSecret("uname", "pwd", "basic-secret", f.Namespace))
|
s := f.EnsureSecret(buildSecret("uname", "pwd", "basic-secret", f.Namespace))
|
||||||
|
|
||||||
|
@ -105,7 +92,7 @@ var _ = framework.DescribeAnnotation("satisfy", func() {
|
||||||
"nginx.ingress.kubernetes.io/auth-realm": "test basic auth",
|
"nginx.ingress.kubernetes.io/auth-realm": "test basic auth",
|
||||||
|
|
||||||
// annotations for external auth
|
// annotations for external auth
|
||||||
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", httpbunIP),
|
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", f.HTTPBunIP),
|
||||||
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
||||||
|
|
||||||
// set satisfy any
|
// set satisfy any
|
||||||
|
|
|
@ -43,12 +43,28 @@ const HTTPBunService = "httpbun"
|
||||||
// NipService name of external service using nip.io
|
// NipService name of external service using nip.io
|
||||||
const NIPService = "external-nip"
|
const NIPService = "external-nip"
|
||||||
|
|
||||||
|
// HTTPBunImage is the default image that is used to deploy HTTPBun with the framwork
|
||||||
|
var HTTPBunImage = os.Getenv("HTTPBUN_IMAGE")
|
||||||
|
|
||||||
|
// EchoImage is the default image to be used by the echo service
|
||||||
|
const EchoImage = "registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:4938d1d91a2b7d19454460a8c1b010b89f6ff92d2987fd889ac3e8fc3b70d91a"
|
||||||
|
|
||||||
|
// TODO: change all Deployment functions to use these options
|
||||||
|
// in order to reduce complexity and have a unified API accross the
|
||||||
|
// framework
|
||||||
type deploymentOptions struct {
|
type deploymentOptions struct {
|
||||||
namespace string
|
|
||||||
name string
|
name string
|
||||||
replicas int
|
namespace string
|
||||||
svcAnnotations map[string]string
|
|
||||||
image string
|
image string
|
||||||
|
port int32
|
||||||
|
replicas int
|
||||||
|
command []string
|
||||||
|
args []string
|
||||||
|
env []corev1.EnvVar
|
||||||
|
volumeMounts []corev1.VolumeMount
|
||||||
|
volumes []corev1.Volume
|
||||||
|
svcAnnotations map[string]string
|
||||||
|
setProbe bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithDeploymentNamespace allows configuring the deployment's namespace
|
// WithDeploymentNamespace allows configuring the deployment's namespace
|
||||||
|
@ -100,22 +116,25 @@ func (f *Framework) NewEchoDeployment(opts ...func(*deploymentOptions)) {
|
||||||
namespace: f.Namespace,
|
namespace: f.Namespace,
|
||||||
name: EchoService,
|
name: EchoService,
|
||||||
replicas: 1,
|
replicas: 1,
|
||||||
image: "registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:6fc5aa2994c86575975bb20a5203651207029a0d28e3f491d8a127d08baadab4",
|
image: EchoImage,
|
||||||
}
|
}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(options)
|
o(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
deployment := newDeployment(options.name, options.namespace, options.image, 80, int32(options.replicas),
|
f.EnsureDeployment(newDeployment(
|
||||||
|
options.name,
|
||||||
|
options.namespace,
|
||||||
|
options.image,
|
||||||
|
80,
|
||||||
|
int32(options.replicas),
|
||||||
nil, nil, nil,
|
nil, nil, nil,
|
||||||
[]corev1.VolumeMount{},
|
[]corev1.VolumeMount{},
|
||||||
[]corev1.Volume{},
|
[]corev1.Volume{},
|
||||||
true,
|
true,
|
||||||
)
|
))
|
||||||
|
|
||||||
f.EnsureDeployment(deployment)
|
f.EnsureService(&corev1.Service{
|
||||||
|
|
||||||
service := &corev1.Service{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: options.name,
|
Name: options.name,
|
||||||
Namespace: options.namespace,
|
Namespace: options.namespace,
|
||||||
|
@ -134,11 +153,15 @@ func (f *Framework) NewEchoDeployment(opts ...func(*deploymentOptions)) {
|
||||||
"app": options.name,
|
"app": options.name,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
|
|
||||||
f.EnsureService(service)
|
err := WaitForEndpoints(
|
||||||
|
f.KubeClientSet,
|
||||||
err := WaitForEndpoints(f.KubeClientSet, DefaultTimeout, options.name, options.namespace, options.replicas)
|
DefaultTimeout,
|
||||||
|
options.name,
|
||||||
|
options.namespace,
|
||||||
|
options.replicas,
|
||||||
|
)
|
||||||
assert.Nil(ginkgo.GinkgoT(), err, "waiting for endpoints to become ready")
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for endpoints to become ready")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +170,12 @@ func BuildNIPHost(ip string) string {
|
||||||
return fmt.Sprintf("%s.nip.io", ip)
|
return fmt.Sprintf("%s.nip.io", ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNipHost used to generate a nip host for external DNS resolving
|
||||||
|
// for the instance deployed by the framework
|
||||||
|
func (f *Framework) GetNIPHost() string {
|
||||||
|
return BuildNIPHost(f.HTTPBunIP)
|
||||||
|
}
|
||||||
|
|
||||||
// BuildNIPExternalNameService used to generate a service pointing to nip.io to
|
// BuildNIPExternalNameService used to generate a service pointing to nip.io to
|
||||||
// help resolve to an IP address
|
// help resolve to an IP address
|
||||||
func BuildNIPExternalNameService(f *Framework, ip, portName string) *corev1.Service {
|
func BuildNIPExternalNameService(f *Framework, ip, portName string) *corev1.Service {
|
||||||
|
@ -177,22 +206,27 @@ func (f *Framework) NewHttpbunDeployment(opts ...func(*deploymentOptions)) strin
|
||||||
namespace: f.Namespace,
|
namespace: f.Namespace,
|
||||||
name: HTTPBunService,
|
name: HTTPBunService,
|
||||||
replicas: 1,
|
replicas: 1,
|
||||||
image: "registry.k8s.io/ingress-nginx/e2e-test-httpbun:v20230505-v0.0.1",
|
image: HTTPBunImage,
|
||||||
}
|
}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(options)
|
o(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
deployment := newDeployment(options.name, options.namespace, options.image, 80, int32(options.replicas),
|
// Create the HTTPBun Deployment
|
||||||
|
f.EnsureDeployment(newDeployment(
|
||||||
|
options.name,
|
||||||
|
options.namespace,
|
||||||
|
options.image,
|
||||||
|
80,
|
||||||
|
int32(options.replicas),
|
||||||
nil, nil, nil,
|
nil, nil, nil,
|
||||||
[]corev1.VolumeMount{},
|
[]corev1.VolumeMount{},
|
||||||
[]corev1.Volume{},
|
[]corev1.Volume{},
|
||||||
true,
|
true,
|
||||||
)
|
))
|
||||||
|
|
||||||
f.EnsureDeployment(deployment)
|
// Create a service pointing to deployment
|
||||||
|
f.EnsureService(&corev1.Service{
|
||||||
service := &corev1.Service{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: options.name,
|
Name: options.name,
|
||||||
Namespace: options.namespace,
|
Namespace: options.namespace,
|
||||||
|
@ -211,14 +245,26 @@ func (f *Framework) NewHttpbunDeployment(opts ...func(*deploymentOptions)) strin
|
||||||
"app": options.name,
|
"app": options.name,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
|
|
||||||
s := f.EnsureService(service)
|
// Wait for deployment to become available
|
||||||
|
err := WaitForEndpoints(
|
||||||
err := WaitForEndpoints(f.KubeClientSet, DefaultTimeout, options.name, options.namespace, options.replicas)
|
f.KubeClientSet,
|
||||||
|
DefaultTimeout,
|
||||||
|
options.name,
|
||||||
|
options.namespace,
|
||||||
|
options.replicas,
|
||||||
|
)
|
||||||
assert.Nil(ginkgo.GinkgoT(), err, "waiting for endpoints to become ready")
|
assert.Nil(ginkgo.GinkgoT(), err, "waiting for endpoints to become ready")
|
||||||
|
|
||||||
return s.Spec.ClusterIPs[0]
|
// Get cluster ip for HTTPBun to be used in tests
|
||||||
|
e, err := f.KubeClientSet.
|
||||||
|
CoreV1().
|
||||||
|
Endpoints(f.Namespace).
|
||||||
|
Get(context.TODO(), HTTPBunService, metav1.GetOptions{})
|
||||||
|
assert.Nil(ginkgo.GinkgoT(), err, "failed to get httpbun endpoint")
|
||||||
|
|
||||||
|
return e.Subsets[0].Addresses[0].IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSlowEchoDeployment creates a new deployment of the slow echo server image in a particular namespace.
|
// NewSlowEchoDeployment creates a new deployment of the slow echo server image in a particular namespace.
|
||||||
|
@ -276,7 +322,10 @@ func (f *Framework) NGINXDeployment(name string, cfg string, waitendpoint bool)
|
||||||
"nginx.conf": cfg,
|
"nginx.conf": cfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := f.KubeClientSet.CoreV1().ConfigMaps(f.Namespace).Create(context.TODO(), &corev1.ConfigMap{
|
_, err := f.KubeClientSet.
|
||||||
|
CoreV1().
|
||||||
|
ConfigMaps(f.Namespace).
|
||||||
|
Create(context.TODO(), &corev1.ConfigMap{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: f.Namespace,
|
Namespace: f.Namespace,
|
||||||
|
|
104
test/e2e/framework/fastcgi_helloserver.go
Normal file
104
test/e2e/framework/fastcgi_helloserver.go
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package framework
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/onsi/ginkgo/v2"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewFastCGIHelloServerDeployment creates a new single replica
|
||||||
|
// deployment of the fortune teller image in a particular namespace
|
||||||
|
func (f *Framework) NewFastCGIHelloServerDeployment() {
|
||||||
|
f.NewNewFastCGIHelloServerDeploymentWithReplicas(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNewFastCGIHelloServerDeploymentWithReplicas creates a new deployment of the
|
||||||
|
// fortune teller image in a particular namespace. Number of replicas is configurable
|
||||||
|
func (f *Framework) NewNewFastCGIHelloServerDeploymentWithReplicas(replicas int32) {
|
||||||
|
deployment := &appsv1.Deployment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fastcgi-helloserver",
|
||||||
|
Namespace: f.Namespace,
|
||||||
|
},
|
||||||
|
Spec: appsv1.DeploymentSpec{
|
||||||
|
Replicas: NewInt32(replicas),
|
||||||
|
Selector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"app": "fastcgi-helloserver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "fastcgi-helloserver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
TerminationGracePeriodSeconds: NewInt64(0),
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "fastcgi-helloserver",
|
||||||
|
Image: "registry.k8s.io/ingress-nginx/e2e-test-fastcgi-helloserver@sha256:0e08c836cc58f1ea862578de99b13bc4264fe071e816f96dc1d79857bfba7473",
|
||||||
|
Env: []corev1.EnvVar{},
|
||||||
|
Ports: []corev1.ContainerPort{
|
||||||
|
{
|
||||||
|
Name: "fastcgi",
|
||||||
|
ContainerPort: 9000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
d := f.EnsureDeployment(deployment)
|
||||||
|
|
||||||
|
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, metav1.ListOptions{
|
||||||
|
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
|
||||||
|
})
|
||||||
|
assert.Nil(ginkgo.GinkgoT(), err, "failed to wait for to become ready")
|
||||||
|
|
||||||
|
service := &corev1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fastcgi-helloserver",
|
||||||
|
Namespace: f.Namespace,
|
||||||
|
},
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Ports: []corev1.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "fastcgi",
|
||||||
|
Port: 9000,
|
||||||
|
TargetPort: intstr.FromInt(9000),
|
||||||
|
Protocol: "TCP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Selector: map[string]string{
|
||||||
|
"app": "fastcgi-helloserver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
f.EnsureService(service)
|
||||||
|
}
|
|
@ -67,16 +67,32 @@ type Framework struct {
|
||||||
IngressClass string
|
IngressClass string
|
||||||
|
|
||||||
pod *v1.Pod
|
pod *v1.Pod
|
||||||
|
// We use httpbun as a service that we route to in our tests through
|
||||||
|
// the ingress controller. We add it as part of the framework as it
|
||||||
|
// is used extensively
|
||||||
|
HTTPBunIP string
|
||||||
|
HTTPBunEnabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHTTPBunEnabled deploys an instance of HTTPBun for the specific test
|
||||||
|
func WithHTTPBunEnabled() func(*Framework) {
|
||||||
|
return func(f *Framework) {
|
||||||
|
f.HTTPBunEnabled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDefaultFramework makes a new framework and sets up a BeforeEach/AfterEach for
|
// NewDefaultFramework makes a new framework and sets up a BeforeEach/AfterEach for
|
||||||
// you (you can write additional before/after each functions).
|
// you (you can write additional before/after each functions).
|
||||||
func NewDefaultFramework(baseName string) *Framework {
|
func NewDefaultFramework(baseName string, opts ...func(*Framework)) *Framework {
|
||||||
defer ginkgo.GinkgoRecover()
|
defer ginkgo.GinkgoRecover()
|
||||||
|
|
||||||
f := &Framework{
|
f := &Framework{
|
||||||
BaseName: baseName,
|
BaseName: baseName,
|
||||||
}
|
}
|
||||||
|
// set framework options
|
||||||
|
for _, o := range opts {
|
||||||
|
o(f)
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.BeforeEach(f.BeforeEach)
|
ginkgo.BeforeEach(f.BeforeEach)
|
||||||
ginkgo.AfterEach(f.AfterEach)
|
ginkgo.AfterEach(f.AfterEach)
|
||||||
|
@ -86,12 +102,16 @@ func NewDefaultFramework(baseName string) *Framework {
|
||||||
|
|
||||||
// NewSimpleFramework makes a new framework that allows the usage of a namespace
|
// NewSimpleFramework makes a new framework that allows the usage of a namespace
|
||||||
// for arbitraty tests.
|
// for arbitraty tests.
|
||||||
func NewSimpleFramework(baseName string) *Framework {
|
func NewSimpleFramework(baseName string, opts ...func(*Framework)) *Framework {
|
||||||
defer ginkgo.GinkgoRecover()
|
defer ginkgo.GinkgoRecover()
|
||||||
|
|
||||||
f := &Framework{
|
f := &Framework{
|
||||||
BaseName: baseName,
|
BaseName: baseName,
|
||||||
}
|
}
|
||||||
|
// set framework options
|
||||||
|
for _, o := range opts {
|
||||||
|
o(f)
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.BeforeEach(f.CreateEnvironment)
|
ginkgo.BeforeEach(f.CreateEnvironment)
|
||||||
ginkgo.AfterEach(f.DestroyEnvironment)
|
ginkgo.AfterEach(f.DestroyEnvironment)
|
||||||
|
@ -140,6 +160,11 @@ func (f *Framework) BeforeEach() {
|
||||||
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress controller pod information")
|
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress controller pod information")
|
||||||
|
|
||||||
f.WaitForNginxListening(80)
|
f.WaitForNginxListening(80)
|
||||||
|
|
||||||
|
// If HTTPBun is enabled deploy an instance to the namespace
|
||||||
|
if f.HTTPBunEnabled {
|
||||||
|
f.HTTPBunIP = f.NewHttpbunDeployment()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AfterEach deletes the namespace, after reading its events.
|
// AfterEach deletes the namespace, after reading its events.
|
||||||
|
|
|
@ -51,6 +51,7 @@ fi
|
||||||
|
|
||||||
BASEDIR=$(dirname "$0")
|
BASEDIR=$(dirname "$0")
|
||||||
NGINX_BASE_IMAGE=$(cat $BASEDIR/../../NGINX_BASE)
|
NGINX_BASE_IMAGE=$(cat $BASEDIR/../../NGINX_BASE)
|
||||||
|
HTTPBUN_IMAGE=$(cat $BASEDIR/HTTPBUN_IMAGE)
|
||||||
|
|
||||||
echo -e "${BGREEN}Granting permissions to ingress-nginx e2e service account...${NC}"
|
echo -e "${BGREEN}Granting permissions to ingress-nginx e2e service account...${NC}"
|
||||||
kubectl create serviceaccount ingress-nginx-e2e || true
|
kubectl create serviceaccount ingress-nginx-e2e || true
|
||||||
|
@ -79,6 +80,7 @@ kubectl run --rm \
|
||||||
--env="IS_CHROOT=${IS_CHROOT:-false}"\
|
--env="IS_CHROOT=${IS_CHROOT:-false}"\
|
||||||
--env="E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS}" \
|
--env="E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS}" \
|
||||||
--env="NGINX_BASE_IMAGE=${NGINX_BASE_IMAGE}" \
|
--env="NGINX_BASE_IMAGE=${NGINX_BASE_IMAGE}" \
|
||||||
|
--env="HTTPBUN_IMAGE=${HTTPBUN_IMAGE}" \
|
||||||
--overrides='{ "apiVersion": "v1", "spec":{"serviceAccountName": "ingress-nginx-e2e"}}' \
|
--overrides='{ "apiVersion": "v1", "spec":{"serviceAccountName": "ingress-nginx-e2e"}}' \
|
||||||
e2e --image=nginx-ingress-controller:e2e
|
e2e --image=nginx-ingress-controller:e2e
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
f := framework.NewDefaultFramework("type-externalname")
|
f := framework.NewDefaultFramework("type-externalname", framework.WithHTTPBunEnabled())
|
||||||
|
|
||||||
ginkgo.It("works with external name set to incomplete fqdn", func() {
|
ginkgo.It("works with external name set to incomplete fqdn", func() {
|
||||||
f.NewEchoDeployment()
|
f.NewEchoDeployment()
|
||||||
|
@ -43,7 +43,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
|
|
||||||
svc := &corev1.Service{
|
svc := &corev1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: framework.HTTPBunService,
|
Name: framework.NIPService,
|
||||||
Namespace: f.Namespace,
|
Namespace: f.Namespace,
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
|
@ -51,10 +51,15 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
Type: corev1.ServiceTypeExternalName,
|
Type: corev1.ServiceTypeExternalName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, nil)
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.NIPService,
|
||||||
|
80,
|
||||||
|
nil)
|
||||||
f.EnsureIngress(ing)
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
f.WaitForNginxServer(host,
|
f.WaitForNginxServer(host,
|
||||||
|
@ -70,10 +75,6 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should return 200 for service type=ExternalName without a port defined", func() {
|
ginkgo.It("should return 200 for service type=ExternalName without a port defined", func() {
|
||||||
// This is a workaround so we only depend on a self hosted instance of
|
|
||||||
// httpbun
|
|
||||||
ip := f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
host := "echo"
|
host := "echo"
|
||||||
|
|
||||||
svc := &corev1.Service{
|
svc := &corev1.Service{
|
||||||
|
@ -82,17 +83,23 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
Namespace: f.Namespace,
|
Namespace: f.Namespace,
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
ExternalName: framework.BuildNIPHost(ip),
|
ExternalName: f.GetNIPHost(),
|
||||||
Type: corev1.ServiceTypeExternalName,
|
Type: corev1.ServiceTypeExternalName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/upstream-vhost": framework.BuildNIPHost(ip),
|
"nginx.ingress.kubernetes.io/upstream-vhost": f.GetNIPHost(),
|
||||||
}
|
}
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, annotations)
|
|
||||||
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.HTTPBunService,
|
||||||
|
80,
|
||||||
|
annotations)
|
||||||
f.EnsureIngress(ing)
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
f.WaitForNginxServer(host,
|
f.WaitForNginxServer(host,
|
||||||
|
@ -108,19 +115,21 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should return 200 for service type=ExternalName with a port defined", func() {
|
ginkgo.It("should return 200 for service type=ExternalName with a port defined", func() {
|
||||||
// This is a workaround so we only depend on a self hosted instance of
|
|
||||||
// httpbun
|
|
||||||
ip := f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
host := "echo"
|
host := "echo"
|
||||||
|
|
||||||
svc := framework.BuildNIPExternalNameService(f, ip, host)
|
svc := framework.BuildNIPExternalNameService(f, f.HTTPBunIP, host)
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/upstream-vhost": framework.BuildNIPHost(ip),
|
"nginx.ingress.kubernetes.io/upstream-vhost": f.GetNIPHost(),
|
||||||
}
|
}
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, annotations)
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.HTTPBunService,
|
||||||
|
80,
|
||||||
|
annotations)
|
||||||
f.EnsureIngress(ing)
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
f.WaitForNginxServer(host,
|
f.WaitForNginxServer(host,
|
||||||
|
@ -140,7 +149,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
|
|
||||||
svc := &corev1.Service{
|
svc := &corev1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: framework.HTTPBunService,
|
Name: framework.NIPService,
|
||||||
Namespace: f.Namespace,
|
Namespace: f.Namespace,
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
|
@ -148,10 +157,15 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
Type: corev1.ServiceTypeExternalName,
|
Type: corev1.ServiceTypeExternalName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, nil)
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.NIPService,
|
||||||
|
80,
|
||||||
|
nil)
|
||||||
f.EnsureIngress(ing)
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
f.WaitForNginxServer(host,
|
f.WaitForNginxServer(host,
|
||||||
|
@ -167,19 +181,22 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should return 200 for service type=ExternalName using a port name", func() {
|
ginkgo.It("should return 200 for service type=ExternalName using a port name", func() {
|
||||||
// This is a workaround so we only depend on a self hosted instance of
|
|
||||||
// httpbun
|
|
||||||
ip := f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
host := "echo"
|
host := "echo"
|
||||||
|
|
||||||
svc := framework.BuildNIPExternalNameService(f, ip, host)
|
svc := framework.BuildNIPExternalNameService(f, f.HTTPBunIP, host)
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/upstream-vhost": framework.BuildNIPHost(ip),
|
"nginx.ingress.kubernetes.io/upstream-vhost": f.GetNIPHost(),
|
||||||
}
|
}
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, annotations)
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.HTTPBunService,
|
||||||
|
80,
|
||||||
|
annotations)
|
||||||
|
|
||||||
namedBackend := networking.IngressBackend{
|
namedBackend := networking.IngressBackend{
|
||||||
Service: &networking.IngressServiceBackend{
|
Service: &networking.IngressServiceBackend{
|
||||||
Name: framework.NIPService,
|
Name: framework.NIPService,
|
||||||
|
@ -188,6 +205,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ing.Spec.Rules[0].HTTP.Paths[0].Backend = namedBackend
|
ing.Spec.Rules[0].HTTP.Paths[0].Backend = namedBackend
|
||||||
f.EnsureIngress(ing)
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
@ -204,10 +222,6 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should return 200 for service type=ExternalName using FQDN with trailing dot", func() {
|
ginkgo.It("should return 200 for service type=ExternalName using FQDN with trailing dot", func() {
|
||||||
// This is a workaround so we only depend on a self hosted instance of
|
|
||||||
// httpbun
|
|
||||||
ip := f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
host := "echo"
|
host := "echo"
|
||||||
|
|
||||||
svc := &corev1.Service{
|
svc := &corev1.Service{
|
||||||
|
@ -216,14 +230,19 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
Namespace: f.Namespace,
|
Namespace: f.Namespace,
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
ExternalName: framework.BuildNIPHost(ip),
|
ExternalName: f.GetNIPHost(),
|
||||||
Type: corev1.ServiceTypeExternalName,
|
Type: corev1.ServiceTypeExternalName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, nil)
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.HTTPBunService,
|
||||||
|
80,
|
||||||
|
nil)
|
||||||
f.EnsureIngress(ing)
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
f.WaitForNginxServer(host,
|
f.WaitForNginxServer(host,
|
||||||
|
@ -239,20 +258,23 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should update the external name after a service update", func() {
|
ginkgo.It("should update the external name after a service update", func() {
|
||||||
// This is a workaround so we only depend on a self hosted instance of
|
|
||||||
// httpbun
|
|
||||||
ip := f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
host := "echo"
|
host := "echo"
|
||||||
|
|
||||||
svc := framework.BuildNIPExternalNameService(f, ip, host)
|
svc := framework.BuildNIPExternalNameService(f, f.HTTPBunIP, host)
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/upstream-vhost": framework.BuildNIPHost(ip),
|
"nginx.ingress.kubernetes.io/upstream-vhost": f.GetNIPHost(),
|
||||||
}
|
}
|
||||||
|
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, annotations)
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.HTTPBunService,
|
||||||
|
80,
|
||||||
|
annotations)
|
||||||
|
|
||||||
namedBackend := networking.IngressBackend{
|
namedBackend := networking.IngressBackend{
|
||||||
Service: &networking.IngressServiceBackend{
|
Service: &networking.IngressServiceBackend{
|
||||||
Name: framework.NIPService,
|
Name: framework.NIPService,
|
||||||
|
@ -279,14 +301,20 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
|
|
||||||
assert.Contains(ginkgo.GinkgoT(), body, `"X-Forwarded-Host": "echo"`)
|
assert.Contains(ginkgo.GinkgoT(), body, `"X-Forwarded-Host": "echo"`)
|
||||||
|
|
||||||
svc, err := f.KubeClientSet.CoreV1().Services(f.Namespace).Get(context.TODO(), framework.NIPService, metav1.GetOptions{})
|
svc, err := f.KubeClientSet.
|
||||||
|
CoreV1().
|
||||||
|
Services(f.Namespace).
|
||||||
|
Get(context.TODO(), framework.NIPService, metav1.GetOptions{})
|
||||||
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error obtaining external service")
|
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error obtaining external service")
|
||||||
|
|
||||||
ip = f.NewHttpbunDeployment(framework.WithDeploymentName("eu-server"))
|
//Deploy a new instance to switch routing to
|
||||||
|
ip := f.NewHttpbunDeployment(framework.WithDeploymentName("eu-server"))
|
||||||
svc.Spec.ExternalName = framework.BuildNIPHost(ip)
|
svc.Spec.ExternalName = framework.BuildNIPHost(ip)
|
||||||
|
|
||||||
_, err = f.KubeClientSet.CoreV1().Services(f.Namespace).Update(context.Background(), svc, metav1.UpdateOptions{})
|
_, err = f.KubeClientSet.
|
||||||
|
CoreV1().
|
||||||
|
Services(f.Namespace).
|
||||||
|
Update(context.Background(), svc, metav1.UpdateOptions{})
|
||||||
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error updating external service")
|
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error updating external service")
|
||||||
|
|
||||||
framework.Sleep()
|
framework.Sleep()
|
||||||
|
@ -302,21 +330,31 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
assert.Contains(ginkgo.GinkgoT(), body, `"X-Forwarded-Host": "echo"`)
|
assert.Contains(ginkgo.GinkgoT(), body, `"X-Forwarded-Host": "echo"`)
|
||||||
|
|
||||||
ginkgo.By("checking the service is updated to use new host")
|
ginkgo.By("checking the service is updated to use new host")
|
||||||
curlCmd := fmt.Sprintf("curl --fail --silent http://localhost:%v/configuration/backends", nginx.StatusPort)
|
curlCmd := fmt.Sprintf(
|
||||||
|
"curl --fail --silent http://localhost:%v/configuration/backends",
|
||||||
|
nginx.StatusPort,
|
||||||
|
)
|
||||||
|
|
||||||
output, err := f.ExecIngressPod(curlCmd)
|
output, err := f.ExecIngressPod(curlCmd)
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
assert.Nil(ginkgo.GinkgoT(), err)
|
||||||
assert.Contains(ginkgo.GinkgoT(), output, fmt.Sprintf("{\"address\":\"%s\"", framework.BuildNIPHost(ip)))
|
assert.Contains(
|
||||||
|
ginkgo.GinkgoT(),
|
||||||
|
output,
|
||||||
|
fmt.Sprintf("{\"address\":\"%s\"", framework.BuildNIPHost(ip)),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("should sync ingress on external name service addition/deletion", func() {
|
ginkgo.It("should sync ingress on external name service addition/deletion", func() {
|
||||||
// This is a workaround so we only depend on a self hosted instance of
|
|
||||||
// httpbun
|
|
||||||
ip := f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
host := "echo"
|
host := "echo"
|
||||||
|
|
||||||
// Create the Ingress first
|
// Create the Ingress first
|
||||||
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.NIPService, 80, nil)
|
ing := framework.NewSingleIngress(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
f.Namespace,
|
||||||
|
framework.NIPService,
|
||||||
|
80,
|
||||||
|
nil)
|
||||||
f.EnsureIngress(ing)
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
f.WaitForNginxServer(host,
|
f.WaitForNginxServer(host,
|
||||||
|
@ -332,7 +370,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
Status(http.StatusServiceUnavailable)
|
Status(http.StatusServiceUnavailable)
|
||||||
|
|
||||||
// Now create the service
|
// Now create the service
|
||||||
svc := framework.BuildNIPExternalNameService(f, ip, host)
|
svc := framework.BuildNIPExternalNameService(f, f.HTTPBunIP, host)
|
||||||
f.EnsureService(svc)
|
f.EnsureService(svc)
|
||||||
|
|
||||||
framework.Sleep()
|
framework.Sleep()
|
||||||
|
@ -345,7 +383,10 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
|
||||||
Status(http.StatusOK)
|
Status(http.StatusOK)
|
||||||
|
|
||||||
// And back to 503 after deleting the service
|
// And back to 503 after deleting the service
|
||||||
err := f.KubeClientSet.CoreV1().Services(f.Namespace).Delete(context.TODO(), framework.NIPService, metav1.DeleteOptions{})
|
err := f.KubeClientSet.
|
||||||
|
CoreV1().
|
||||||
|
Services(f.Namespace).
|
||||||
|
Delete(context.TODO(), framework.NIPService, metav1.DeleteOptions{})
|
||||||
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error deleting external service")
|
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error deleting external service")
|
||||||
|
|
||||||
framework.Sleep()
|
framework.Sleep()
|
||||||
|
|
|
@ -28,14 +28,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.IngressNginxDescribe("brotli", func() {
|
var _ = framework.IngressNginxDescribe("brotli", func() {
|
||||||
f := framework.NewDefaultFramework("brotli")
|
f := framework.NewDefaultFramework(
|
||||||
|
"brotli",
|
||||||
|
framework.WithHTTPBunEnabled(),
|
||||||
|
)
|
||||||
|
|
||||||
host := "brotli"
|
host := "brotli"
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("should only compress responses that meet the `brotli-min-length` condition", func() {
|
ginkgo.It("should only compress responses that meet the `brotli-min-length` condition", func() {
|
||||||
brotliMinLength := 24
|
brotliMinLength := 24
|
||||||
contentEncoding := "application/octet-stream"
|
contentEncoding := "application/octet-stream"
|
||||||
|
|
|
@ -33,7 +33,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.IngressNginxDescribe("[Flag] disable-service-external-name", func() {
|
var _ = framework.IngressNginxDescribe("[Flag] disable-service-external-name", func() {
|
||||||
f := framework.NewDefaultFramework("disabled-service-external-name")
|
f := framework.NewDefaultFramework(
|
||||||
|
"disabled-service-external-name",
|
||||||
|
framework.WithHTTPBunEnabled(),
|
||||||
|
)
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewEchoDeployment(framework.WithDeploymentReplicas(2))
|
f.NewEchoDeployment(framework.WithDeploymentReplicas(2))
|
||||||
|
@ -54,21 +57,18 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-service-external-name", f
|
||||||
|
|
||||||
externalhost := "echo-external-svc.com"
|
externalhost := "echo-external-svc.com"
|
||||||
|
|
||||||
ip := f.NewHttpbunDeployment()
|
f.EnsureService(framework.BuildNIPExternalNameService(f, f.HTTPBunIP, "echo"))
|
||||||
svc := framework.BuildNIPExternalNameService(f, ip, "echo")
|
|
||||||
f.EnsureService(svc)
|
|
||||||
|
|
||||||
svcexternal := &corev1.Service{
|
f.EnsureService(&corev1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "external",
|
Name: "external",
|
||||||
Namespace: f.Namespace,
|
Namespace: f.Namespace,
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
ExternalName: framework.BuildNIPHost(ip),
|
ExternalName: f.GetNIPHost(),
|
||||||
Type: corev1.ServiceTypeExternalName,
|
Type: corev1.ServiceTypeExternalName,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
f.EnsureService(svcexternal)
|
|
||||||
|
|
||||||
ingexternal := framework.NewSingleIngress(externalhost, "/", externalhost, f.Namespace, "external", 80, nil)
|
ingexternal := framework.NewSingleIngress(externalhost, "/", externalhost, f.Namespace, "external", 80, nil)
|
||||||
f.EnsureIngress(ingexternal)
|
f.EnsureIngress(ingexternal)
|
||||||
|
|
|
@ -32,7 +32,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
|
var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
|
||||||
f := framework.NewDefaultFramework("global-external-auth")
|
f := framework.NewDefaultFramework(
|
||||||
|
"global-external-auth",
|
||||||
|
framework.WithHTTPBunEnabled(),
|
||||||
|
)
|
||||||
|
|
||||||
host := "global-external-auth"
|
host := "global-external-auth"
|
||||||
|
|
||||||
|
@ -50,7 +53,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewEchoDeployment()
|
f.NewEchoDeployment()
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.Context("when global external authentication is configured", func() {
|
ginkgo.Context("when global external authentication is configured", func() {
|
||||||
|
@ -307,9 +309,9 @@ http {
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
||||||
|
|
||||||
httpbunIP := e.Subsets[0].Addresses[0].IP
|
nginxIP := e.Subsets[0].Addresses[0].IP
|
||||||
|
|
||||||
f.UpdateNginxConfigMapData(globalExternalAuthURLSetting, fmt.Sprintf("http://%s/cookies/set/alma/armud", httpbunIP))
|
f.UpdateNginxConfigMapData(globalExternalAuthURLSetting, fmt.Sprintf("http://%s/cookies/set/alma/armud", nginxIP))
|
||||||
|
|
||||||
ing1 = framework.NewSingleIngress(host, "/", host, f.Namespace, "http-cookie-with-error", 80, nil)
|
ing1 = framework.NewSingleIngress(host, "/", host, f.Namespace, "http-cookie-with-error", 80, nil)
|
||||||
f.EnsureIngress(ing1)
|
f.EnsureIngress(ing1)
|
||||||
|
|
|
@ -17,14 +17,12 @@ limitations under the License.
|
||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/onsi/ginkgo/v2"
|
"github.com/onsi/ginkgo/v2"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/test/e2e/framework"
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
)
|
)
|
||||||
|
@ -33,7 +31,7 @@ var _ = framework.IngressNginxDescribe("[Flag] custom HTTP and HTTPS ports", fun
|
||||||
|
|
||||||
host := "forwarded-headers"
|
host := "forwarded-headers"
|
||||||
|
|
||||||
f := framework.NewDefaultFramework("forwarded-port-headers")
|
f := framework.NewDefaultFramework("forwarded-port-headers", framework.WithHTTPBunEnabled())
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
f.NewEchoDeployment()
|
f.NewEchoDeployment()
|
||||||
|
@ -98,21 +96,8 @@ var _ = framework.IngressNginxDescribe("[Flag] custom HTTP and HTTPS ports", fun
|
||||||
ginkgo.Context("when external authentication is configured", func() {
|
ginkgo.Context("when external authentication is configured", func() {
|
||||||
|
|
||||||
ginkgo.It("should set the X-Forwarded-Port header to 443", func() {
|
ginkgo.It("should set the X-Forwarded-Port header to 443", func() {
|
||||||
f.NewHttpbunDeployment()
|
|
||||||
|
|
||||||
err := framework.WaitForEndpoints(f.KubeClientSet, framework.DefaultTimeout, framework.HTTPBunService, f.Namespace, 1)
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
e, err := f.KubeClientSet.CoreV1().Endpoints(f.Namespace).Get(context.TODO(), framework.HTTPBunService, metav1.GetOptions{})
|
|
||||||
assert.Nil(ginkgo.GinkgoT(), err)
|
|
||||||
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets), 1, "expected at least one endpoint")
|
|
||||||
assert.GreaterOrEqual(ginkgo.GinkgoT(), len(e.Subsets[0].Addresses), 1, "expected at least one address ready in the endpoint")
|
|
||||||
|
|
||||||
httpbunIP := e.Subsets[0].Addresses[0].IP
|
|
||||||
|
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", httpbunIP),
|
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", f.HTTPBunIP),
|
||||||
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = framework.IngressNginxDescribe("[Flag] enable-ssl-passthrough", func() {
|
var _ = framework.IngressNginxDescribe("[Flag] enable-ssl-passthrough", func() {
|
||||||
f := framework.NewDefaultFramework("ssl-passthrough")
|
f := framework.NewDefaultFramework("ssl-passthrough", framework.WithHTTPBunEnabled())
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
err := f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error {
|
err := f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error {
|
||||||
|
@ -86,7 +86,14 @@ var _ = framework.IngressNginxDescribe("[Flag] enable-ssl-passthrough", func() {
|
||||||
"nginx.ingress.kubernetes.io/ssl-passthrough": "true",
|
"nginx.ingress.kubernetes.io/ssl-passthrough": "true",
|
||||||
}
|
}
|
||||||
|
|
||||||
ingressDef := framework.NewSingleIngressWithTLS(host, "/", host, []string{host}, f.Namespace, echoName, 80, annotations)
|
ingressDef := framework.NewSingleIngressWithTLS(host,
|
||||||
|
"/",
|
||||||
|
host,
|
||||||
|
[]string{host},
|
||||||
|
f.Namespace,
|
||||||
|
echoName,
|
||||||
|
80,
|
||||||
|
annotations)
|
||||||
tlsConfig, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
|
tlsConfig, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
|
||||||
ingressDef.Spec.TLS[0].Hosts,
|
ingressDef.Spec.TLS[0].Hosts,
|
||||||
ingressDef.Spec.TLS[0].SecretName,
|
ingressDef.Spec.TLS[0].SecretName,
|
||||||
|
@ -119,7 +126,17 @@ var _ = framework.IngressNginxDescribe("[Flag] enable-ssl-passthrough", func() {
|
||||||
Value: "/certs/tls.key",
|
Value: "/certs/tls.key",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.NewDeploymentWithOpts("echopass", "ghcr.io/sharat87/httpbun:latest", 80, 1, nil, nil, envs, volumeMount, volume, false)
|
|
||||||
|
f.NewDeploymentWithOpts("echopass",
|
||||||
|
framework.HTTPBunImage,
|
||||||
|
80,
|
||||||
|
1,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
envs,
|
||||||
|
volumeMount,
|
||||||
|
volume,
|
||||||
|
false)
|
||||||
|
|
||||||
f.EnsureIngress(ingressDef)
|
f.EnsureIngress(ingressDef)
|
||||||
|
|
||||||
|
@ -133,7 +150,14 @@ var _ = framework.IngressNginxDescribe("[Flag] enable-ssl-passthrough", func() {
|
||||||
|
|
||||||
/* This one should not receive traffic as it does not contain passthrough annotation */
|
/* This one should not receive traffic as it does not contain passthrough annotation */
|
||||||
hostBad := "noannotationnopassthrough.com"
|
hostBad := "noannotationnopassthrough.com"
|
||||||
ingBad := f.EnsureIngress(framework.NewSingleIngressWithTLS(hostBad, "/", hostBad, []string{hostBad}, f.Namespace, echoName, 80, nil))
|
ingBad := f.EnsureIngress(framework.NewSingleIngressWithTLS(hostBad,
|
||||||
|
"/",
|
||||||
|
hostBad,
|
||||||
|
[]string{hostBad},
|
||||||
|
f.Namespace,
|
||||||
|
echoName,
|
||||||
|
80,
|
||||||
|
nil))
|
||||||
tlsConfigBad, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
|
tlsConfigBad, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
|
||||||
ingBad.Spec.TLS[0].Hosts,
|
ingBad.Spec.TLS[0].Hosts,
|
||||||
ingBad.Spec.TLS[0].SecretName,
|
ingBad.Spec.TLS[0].SecretName,
|
||||||
|
|
Loading…
Reference in a new issue