Improve integration tests
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
This commit is contained in:
parent
cd8d5b8f10
commit
e522446909
85 changed files with 3482 additions and 4609 deletions
27
.github/workflows/build.yaml
vendored
27
.github/workflows/build.yaml
vendored
|
@ -8,7 +8,6 @@ on:
|
|||
env:
|
||||
GO_VERSION: '1.21'
|
||||
CGO_ENABLED: 0
|
||||
IN_DOCKER: ""
|
||||
|
||||
jobs:
|
||||
|
||||
|
@ -17,7 +16,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
@ -39,38 +38,22 @@ jobs:
|
|||
os: [ ubuntu-20.04, macos-latest, windows-latest ]
|
||||
needs:
|
||||
- build-webui
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
~/Library/Caches/go-build
|
||||
'%LocalAppData%\go-build'
|
||||
key: ${{ runner.os }}-build-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-build-go-
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Artifact webui
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: webui.tar.gz
|
||||
path: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
|
||||
- name: Untar webui
|
||||
run: tar xvf webui.tar.gz
|
||||
|
|
2
.github/workflows/check_doc.yml
vendored
2
.github/workflows/check_doc.yml
vendored
|
@ -13,7 +13,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
|
@ -28,7 +28,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
|
2
.github/workflows/documentation.yml
vendored
2
.github/workflows/documentation.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
2
.github/workflows/experimental.yaml
vendored
2
.github/workflows/experimental.yaml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
|||
|
||||
# https://github.com/marketplace/actions/checkout
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
74
.github/workflows/test-integration.yaml
vendored
Normal file
74
.github/workflows/test-integration.yaml
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
name: Test Integration
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
push:
|
||||
branches:
|
||||
- 'gh-actions'
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.21'
|
||||
CGO_ENABLED: 0
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Avoid generating webui
|
||||
run: touch webui/static/index.html
|
||||
|
||||
- name: Build binary
|
||||
run: make binary
|
||||
|
||||
test-integration:
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- build
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
parallel: [12]
|
||||
index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 , 11]
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Avoid generating webui
|
||||
run: touch webui/static/index.html
|
||||
|
||||
- name: Build binary
|
||||
run: make binary
|
||||
|
||||
- name: Generate go test Slice
|
||||
id: test_split
|
||||
uses: hashicorp-forge/go-test-split-action@v1
|
||||
with:
|
||||
packages: ./integration
|
||||
total: ${{ matrix.parallel }}
|
||||
index: ${{ matrix.index }}
|
||||
|
||||
- name: Run Integration tests
|
||||
run: |
|
||||
go test ./integration -test.timeout=20m -failfast -v -run "${{ steps.test_split.outputs.run}}"
|
23
.github/workflows/test-unit.yaml
vendored
23
.github/workflows/test-unit.yaml
vendored
|
@ -7,37 +7,22 @@ on:
|
|||
|
||||
env:
|
||||
GO_VERSION: '1.21'
|
||||
IN_DOCKER: ""
|
||||
|
||||
jobs:
|
||||
|
||||
test-unit:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: ${{ runner.os }}-test-unit-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-test-unit-go-
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Avoid generating webui
|
||||
run: touch webui/static/index.html
|
||||
|
|
47
.github/workflows/validate.yaml
vendored
47
.github/workflows/validate.yaml
vendored
|
@ -8,38 +8,23 @@ on:
|
|||
env:
|
||||
GO_VERSION: '1.21'
|
||||
GOLANGCI_LINT_VERSION: v1.55.2
|
||||
MISSSPELL_VERSION: v0.4.0
|
||||
IN_DOCKER: ""
|
||||
MISSSPELL_VERSION: v0.4.1
|
||||
|
||||
jobs:
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: ${{ runner.os }}-validate-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-validate-go-
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Install golangci-lint ${{ env.GOLANGCI_LINT_VERSION }}
|
||||
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION}
|
||||
|
@ -56,30 +41,16 @@ jobs:
|
|||
validate-generate:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}/go/src/github.com/traefik/traefik
|
||||
|
||||
steps:
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: go/src/github.com/traefik/traefik
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v3
|
||||
- name: Set up Go ${{ env.GO_VERSION }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
~/.cache/go-build
|
||||
key: ${{ runner.os }}-validate-generate-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-validate-generate-go-
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: go generate
|
||||
run: |
|
||||
|
|
|
@ -146,7 +146,6 @@ linters-settings:
|
|||
gomoddirectives:
|
||||
replace-allow-list:
|
||||
- github.com/abbot/go-http-auth
|
||||
- github.com/go-check/check
|
||||
- github.com/gorilla/mux
|
||||
- github.com/mailgun/minheap
|
||||
- github.com/mailgun/multibuf
|
||||
|
@ -162,7 +161,6 @@ linters-settings:
|
|||
- expected-actual
|
||||
- float-compare
|
||||
- len
|
||||
- suite-dont-use-pkg
|
||||
- suite-extra-assert-call
|
||||
- suite-thelper
|
||||
|
||||
|
|
|
@ -31,24 +31,6 @@ global_job_config:
|
|||
- cache restore traefik-$(checksum go.sum)
|
||||
|
||||
blocks:
|
||||
- name: Test Integration
|
||||
dependencies: []
|
||||
run:
|
||||
when: "branch =~ '.*' OR pull_request =~'.*'"
|
||||
task:
|
||||
jobs:
|
||||
- name: Test Integration
|
||||
commands:
|
||||
- make pull-images
|
||||
- touch webui/static/index.html # Avoid generating webui
|
||||
- IN_DOCKER="" make binary
|
||||
- make test-integration
|
||||
- df -h
|
||||
epilogue:
|
||||
always:
|
||||
commands:
|
||||
- cache store traefik-$(checksum go.sum) $HOME/go/pkg/mod
|
||||
|
||||
- name: Release
|
||||
dependencies: []
|
||||
run:
|
||||
|
@ -65,8 +47,6 @@ blocks:
|
|||
value: 2.32.1
|
||||
- name: CODENAME
|
||||
value: "mimolette"
|
||||
- name: IN_DOCKER
|
||||
value: ""
|
||||
prologue:
|
||||
commands:
|
||||
- export VERSION=${SEMAPHORE_GIT_TAG_NAME}
|
||||
|
|
103
Makefile
103
Makefile
|
@ -6,34 +6,6 @@ VERSION_GIT := $(if $(TAG_NAME),$(TAG_NAME),$(SHA))
|
|||
VERSION := $(if $(VERSION),$(VERSION),$(VERSION_GIT))
|
||||
|
||||
GIT_BRANCH := $(subst heads/,,$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null))
|
||||
TRAEFIK_DEV_IMAGE := traefik-dev$(if $(GIT_BRANCH),:$(subst /,-,$(GIT_BRANCH)))
|
||||
|
||||
REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
|
||||
TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"traefik/traefik")
|
||||
|
||||
INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)",-v "/var/run/docker.sock:/var/run/docker.sock")
|
||||
DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",)
|
||||
|
||||
# only used when running in docker
|
||||
TRAEFIK_ENVS := \
|
||||
-e OS_ARCH_ARG \
|
||||
-e OS_PLATFORM_ARG \
|
||||
-e TESTFLAGS \
|
||||
-e VERBOSE \
|
||||
-e VERSION \
|
||||
-e CODENAME \
|
||||
-e TESTDIRS \
|
||||
-e CI \
|
||||
-e IN_DOCKER=true # Indicator for integration tests that we are running inside a container.
|
||||
|
||||
TRAEFIK_MOUNT := -v "$(CURDIR)/dist:/go/src/github.com/traefik/traefik/dist"
|
||||
DOCKER_RUN_OPTS := $(TRAEFIK_ENVS) $(TRAEFIK_MOUNT) "$(TRAEFIK_DEV_IMAGE)"
|
||||
DOCKER_NON_INTERACTIVE ?= false
|
||||
DOCKER_RUN_TRAEFIK := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
|
||||
DOCKER_RUN_TRAEFIK_TEST := docker run --add-host=host.docker.internal:127.0.0.1 --rm --name=traefik --network traefik-test-network -v $(PWD):$(PWD) -w $(PWD) $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -it) $(DOCKER_RUN_OPTS)
|
||||
DOCKER_RUN_TRAEFIK_NOTTY := docker run $(INTEGRATION_OPTS) $(if $(DOCKER_NON_INTERACTIVE), , -i) $(DOCKER_RUN_OPTS)
|
||||
|
||||
IN_DOCKER ?= true
|
||||
|
||||
.PHONY: default
|
||||
default: binary
|
||||
|
@ -42,20 +14,6 @@ default: binary
|
|||
dist:
|
||||
mkdir -p dist
|
||||
|
||||
## Build Dev Docker image
|
||||
.PHONY: build-dev-image
|
||||
build-dev-image: dist
|
||||
ifneq ("$(IN_DOCKER)", "")
|
||||
docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" --build-arg HOST_PWD="$(PWD)" -f build.Dockerfile .
|
||||
endif
|
||||
|
||||
## Build Dev Docker image without cache
|
||||
.PHONY: build-dev-image-no-cache
|
||||
build-dev-image-no-cache: dist
|
||||
ifneq ("$(IN_DOCKER)", "")
|
||||
docker build $(DOCKER_BUILD_ARGS) --no-cache -t "$(TRAEFIK_DEV_IMAGE)" --build-arg HOST_PWD="$(PWD)" -f build.Dockerfile .
|
||||
endif
|
||||
|
||||
## Build WebUI Docker image
|
||||
.PHONY: build-webui-image
|
||||
build-webui-image:
|
||||
|
@ -79,8 +37,8 @@ generate-webui: webui/static/index.html
|
|||
|
||||
## Build the binary
|
||||
.PHONY: binary
|
||||
binary: generate-webui build-dev-image
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate binary
|
||||
binary: generate-webui
|
||||
./script/make.sh generate binary
|
||||
|
||||
## Build the linux binary locally
|
||||
.PHONY: binary-debug
|
||||
|
@ -89,35 +47,29 @@ binary-debug: generate-webui
|
|||
|
||||
## Build the binary for the standard platforms (linux, darwin, windows)
|
||||
.PHONY: crossbinary-default
|
||||
crossbinary-default: generate-webui build-dev-image
|
||||
$(DOCKER_RUN_TRAEFIK_NOTTY) ./script/make.sh generate crossbinary-default
|
||||
crossbinary-default: generate-webui
|
||||
./script/make.sh generate crossbinary-default
|
||||
|
||||
## Build the binary for the standard platforms (linux, darwin, windows) in parallel
|
||||
.PHONY: crossbinary-default-parallel
|
||||
crossbinary-default-parallel:
|
||||
$(MAKE) generate-webui
|
||||
$(MAKE) build-dev-image crossbinary-default
|
||||
$(MAKE) crossbinary-default
|
||||
|
||||
## Run the unit and integration tests
|
||||
.PHONY: test
|
||||
test: build-dev-image
|
||||
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
trap 'docker network rm traefik-test-network' EXIT; \
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate test-unit binary test-integration
|
||||
test:
|
||||
./script/make.sh generate test-unit binary test-integration
|
||||
|
||||
## Run the unit tests
|
||||
.PHONY: test-unit
|
||||
test-unit: build-dev-image
|
||||
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
trap 'docker network rm traefik-test-network' EXIT; \
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate test-unit
|
||||
test-unit:
|
||||
./script/make.sh generate test-unit
|
||||
|
||||
## Run the integration tests
|
||||
.PHONY: test-integration
|
||||
test-integration: build-dev-image
|
||||
-docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
trap 'docker network rm traefik-test-network' EXIT; \
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_TEST)) ./script/make.sh generate binary test-integration
|
||||
test-integration:
|
||||
./script/make.sh generate binary test-integration
|
||||
|
||||
## Pull all images for integration tests
|
||||
.PHONY: pull-images
|
||||
|
@ -128,16 +80,22 @@ pull-images:
|
|||
| uniq \
|
||||
| xargs -P 6 -n 1 docker pull
|
||||
|
||||
EXECUTABLES = misspell shellcheck
|
||||
|
||||
## Validate code and docs
|
||||
.PHONY: validate-files
|
||||
validate-files: build-dev-image
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell
|
||||
validate-files:
|
||||
$(foreach exec,$(EXECUTABLES),\
|
||||
$(if $(shell which $(exec)),,$(error "No $(exec) in PATH")))
|
||||
./script/make.sh generate validate-lint validate-misspell
|
||||
bash $(CURDIR)/script/validate-shell-script.sh
|
||||
|
||||
## Validate code, docs, and vendor
|
||||
.PHONY: validate
|
||||
validate: build-dev-image
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK)) ./script/make.sh generate validate-lint validate-misspell validate-vendor
|
||||
validate:
|
||||
$(foreach exec,$(EXECUTABLES),\
|
||||
$(if $(shell which $(exec)),,$(error "No $(exec) in PATH")))
|
||||
./script/make.sh generate validate-lint validate-misspell validate-vendor
|
||||
bash $(CURDIR)/script/validate-shell-script.sh
|
||||
|
||||
## Clean up static directory and build a Docker Traefik image
|
||||
|
@ -155,11 +113,6 @@ build-image-dirty: binary
|
|||
build-image-debug: binary-debug
|
||||
docker build -t $(TRAEFIK_IMAGE) -f debug.Dockerfile .
|
||||
|
||||
## Start a shell inside the build env
|
||||
.PHONY: shell
|
||||
shell: build-dev-image
|
||||
$(DOCKER_RUN_TRAEFIK) /bin/bash
|
||||
|
||||
## Build documentation site
|
||||
.PHONY: docs
|
||||
docs:
|
||||
|
@ -187,23 +140,23 @@ generate-genconf:
|
|||
|
||||
## Create packages for the release
|
||||
.PHONY: release-packages
|
||||
release-packages: generate-webui build-dev-image
|
||||
release-packages: generate-webui
|
||||
rm -rf dist
|
||||
@- $(foreach os, linux darwin windows freebsd openbsd, \
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) goreleaser release --skip-publish -p 2 --timeout="90m" --config $(shell go run ./internal/release $(os)); \
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) go clean -cache; \
|
||||
goreleaser release --skip-publish -p 2 --timeout="90m" --config $(shell go run ./internal/release $(os)); \
|
||||
go clean -cache; \
|
||||
)
|
||||
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) cat dist/**/*_checksums.txt >> dist/traefik_${VERSION}_checksums.txt
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) rm dist/**/*_checksums.txt
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) tar cfz dist/traefik-${VERSION}.src.tar.gz \
|
||||
cat dist/**/*_checksums.txt >> dist/traefik_${VERSION}_checksums.txt
|
||||
rm dist/**/*_checksums.txt
|
||||
tar cfz dist/traefik-${VERSION}.src.tar.gz \
|
||||
--exclude-vcs \
|
||||
--exclude .idea \
|
||||
--exclude .travis \
|
||||
--exclude .semaphoreci \
|
||||
--exclude .github \
|
||||
--exclude dist .
|
||||
$(if $(IN_DOCKER),$(DOCKER_RUN_TRAEFIK_NOTTY)) chown -R $(shell id -u):$(shell id -g) dist/
|
||||
chown -R $(shell id -u):$(shell id -g) dist/
|
||||
|
||||
## Format the Code
|
||||
.PHONY: fmt
|
||||
|
|
|
@ -13,67 +13,13 @@ Let's see how.
|
|||
|
||||
## Building
|
||||
|
||||
You need either [Docker](https://github.com/docker/docker "Link to website of Docker") and `make` (Method 1), or [Go](https://go.dev/ "Link to website of Go") (Method 2) in order to build Traefik.
|
||||
For changes to its dependencies, the `dep` dependency management tool is required.
|
||||
|
||||
### Method 1: Using `Docker` and `Makefile`
|
||||
|
||||
Run make with the `binary` target.
|
||||
|
||||
```bash
|
||||
make binary
|
||||
```
|
||||
|
||||
This will create binaries for the Linux platform in the `dist` folder.
|
||||
|
||||
In case when you run build on CI, you may probably want to run docker in non-interactive mode. To achieve that define `DOCKER_NON_INTERACTIVE=true` environment variable.
|
||||
|
||||
```bash
|
||||
$ make binary
|
||||
docker build -t traefik-webui -f webui/Dockerfile webui
|
||||
Sending build context to Docker daemon 2.686MB
|
||||
Step 1/11 : FROM node:8.15.0
|
||||
---> 1f6c34f7921c
|
||||
[...]
|
||||
Successfully built ce4ff439c06a
|
||||
Successfully tagged traefik-webui:latest
|
||||
[...]
|
||||
docker build -t "traefik-dev:4475--feature-documentation" -f build.Dockerfile .
|
||||
Sending build context to Docker daemon 279MB
|
||||
Step 1/10 : FROM golang:1.16-alpine
|
||||
---> f4bfb3d22bda
|
||||
[...]
|
||||
Successfully built 5c3c1a911277
|
||||
Successfully tagged traefik-dev:4475--feature-documentation
|
||||
docker run -e "TEST_CONTAINER=1" -v "/var/run/docker.sock:/var/run/docker.sock" -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -e VERBOSE -e VERSION -e CODENAME -e TESTDIRS -e CI -e CONTAINER=DOCKER -v "/home/ldez/sources/go/src/github.com/traefik/traefik/"dist":/go/src/github.com/traefik/traefik/"dist"" "traefik-dev:4475--feature-documentation" ./script/make.sh generate binary
|
||||
---> Making bundle: generate (in .)
|
||||
removed 'autogen/genstatic/gen.go'
|
||||
|
||||
---> Making bundle: binary (in .)
|
||||
|
||||
$ ls dist/
|
||||
traefik*
|
||||
```
|
||||
|
||||
The following targets can be executed outside Docker by setting the variable `IN_DOCKER` to an empty string (although be aware that some of the tests might fail in that context):
|
||||
|
||||
- `test-unit`
|
||||
- `test-integration`
|
||||
- `validate`
|
||||
- `binary` (the webUI is still generated by using Docker)
|
||||
|
||||
ex:
|
||||
|
||||
```bash
|
||||
IN_DOCKER= make test-unit
|
||||
```
|
||||
|
||||
### Method 2: Using `go`
|
||||
|
||||
Requirements:
|
||||
|
||||
- `go` v1.16+
|
||||
- environment variable `GO111MODULE=on`
|
||||
You need:
|
||||
- [Docker](https://github.com/docker/docker "Link to website of Docker")
|
||||
- `make`
|
||||
- [Go](https://go.dev/ "Link to website of Go")
|
||||
- [misspell](https://github.com/golangci/misspell)
|
||||
- [shellcheck](https://github.com/koalaman/shellcheck)
|
||||
- [Tailscale](https://tailscale.com/) if you are using Docker Desktop
|
||||
|
||||
!!! tip "Source Directory"
|
||||
|
||||
|
@ -106,41 +52,33 @@ Requirements:
|
|||
## ... and the list goes on
|
||||
```
|
||||
|
||||
#### Build Traefik
|
||||
### Build Traefik
|
||||
|
||||
Once you've set up your go environment and cloned the source repository, you can build Traefik.
|
||||
|
||||
```bash
|
||||
# Generate UI static files
|
||||
make clean-webui generate-webui
|
||||
$ make binary
|
||||
./script/make.sh generate binary
|
||||
---> Making bundle: generate (in .)
|
||||
|
||||
# required to merge non-code components into the final binary,
|
||||
# such as the web dashboard/UI
|
||||
go generate
|
||||
---> Making bundle: binary (in .)
|
||||
|
||||
$ ls dist/
|
||||
traefik*
|
||||
```
|
||||
|
||||
```bash
|
||||
# Standard go build
|
||||
go build ./cmd/traefik
|
||||
```
|
||||
|
||||
You will find the Traefik executable (`traefik`) in the `~/go/src/github.com/traefik/traefik` directory.
|
||||
You will find the Traefik executable (`traefik`) in the `./dist` directory.
|
||||
|
||||
## Testing
|
||||
|
||||
### Method 1: `Docker` and `make`
|
||||
|
||||
Run unit tests using the `test-unit` target.
|
||||
Run integration tests using the `test-integration` target.
|
||||
Run all tests (unit and integration) using the `test` target.
|
||||
|
||||
```bash
|
||||
$ make test-unit
|
||||
docker build -t "traefik-dev:your-feature-branch" -f build.Dockerfile .
|
||||
# […]
|
||||
docker run --rm -it -e OS_ARCH_ARG -e OS_PLATFORM_ARG -e TESTFLAGS -v "/home/user/go/src/github/traefik/traefik/dist:/go/src/github.com/traefik/traefik/dist" "traefik-dev:your-feature-branch" ./script/make.sh generate test-unit
|
||||
./script/make.sh generate test-unit
|
||||
---> Making bundle: generate (in .)
|
||||
removed 'gen.go'
|
||||
|
||||
---> Making bundle: test-unit (in .)
|
||||
+ go test -cover -coverprofile=cover.out .
|
||||
|
@ -151,28 +89,30 @@ Test success
|
|||
|
||||
For development purposes, you can specify which tests to run by using (only works the `test-integration` target):
|
||||
|
||||
??? note "Configuring Tailscale for Docker Desktop user"
|
||||
|
||||
Create `tailscale.secret` file in `integration` directory.
|
||||
|
||||
This file need to contains a [Tailscale auth key](https://tailscale.com/kb/1085/auth-keys)
|
||||
(an ephemeral, but reusable, one is recommended).
|
||||
|
||||
Add this section to your tailscale ACLs to auto-approve the routes for the
|
||||
containers in the docker subnet:
|
||||
|
||||
```json
|
||||
"autoApprovers": {
|
||||
// Allow myself to automatically
|
||||
// advertize routes for docker networks
|
||||
"routes": {
|
||||
"172.31.42.0/24": ["your_tailscale_identity"],
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
```bash
|
||||
# Run every tests in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite" make test-integration
|
||||
TESTFLAGS="-test.run TestAccessLogSuite" make test-integration
|
||||
|
||||
# Run the test "MyTest" in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite.MyTest" make test-integration
|
||||
|
||||
# Run every tests starting with "My", in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite.My" make test-integration
|
||||
|
||||
# Run every tests ending with "Test", in the MyTest suite
|
||||
TESTFLAGS="-check.f MyTestSuite.*Test" make test-integration
|
||||
TESTFLAGS="-test.run TestAccessLogSuite -testify.m ^TestAccessLog$" make test-integration
|
||||
```
|
||||
|
||||
Check [gocheck](https://labix.org/gocheck "Link to website of gocheck") for more information.
|
||||
|
||||
### Method 2: `go`
|
||||
|
||||
Unit tests can be run from the cloned directory using `$ go test ./...` which should return `ok`, similar to:
|
||||
|
||||
```test
|
||||
ok _/home/user/go/src/github/traefik/traefik 0.004s
|
||||
```
|
||||
|
||||
Integration tests must be run from the `integration/` directory and require the `-integration` switch: `$ cd integration && go test -integration ./...`.
|
||||
|
|
91
go.mod
91
go.mod
|
@ -13,14 +13,12 @@ require (
|
|||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
|
||||
github.com/docker/cli v24.0.7+incompatible
|
||||
github.com/docker/compose/v2 v2.19.0
|
||||
github.com/docker/docker v24.0.7+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2
|
||||
github.com/go-acme/lego/v4 v4.14.0
|
||||
github.com/go-check/check v0.0.0-00010101000000-000000000000
|
||||
github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/google/go-github/v28 v28.1.1
|
||||
|
@ -58,14 +56,13 @@ require (
|
|||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a
|
||||
github.com/testcontainers/testcontainers-go v0.27.0
|
||||
github.com/traefik/paerser v0.2.0
|
||||
github.com/traefik/yaegi v0.15.1
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
||||
github.com/uber/jaeger-lib v2.2.0+incompatible
|
||||
github.com/unrolled/render v1.0.2
|
||||
github.com/unrolled/secure v1.0.9
|
||||
github.com/vdemeester/shakers v0.1.0
|
||||
github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c
|
||||
github.com/vulcand/predicate v1.2.0
|
||||
go.elastic.co/apm v1.13.1
|
||||
|
@ -90,9 +87,8 @@ require (
|
|||
require (
|
||||
cloud.google.com/go/compute v1.23.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
|
||||
|
@ -121,6 +117,7 @@ require (
|
|||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.4 // indirect
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
|
||||
github.com/VividCortex/gohistogram v1.0.0 // indirect
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
|
||||
|
@ -144,29 +141,20 @@ require (
|
|||
github.com/aws/smithy-go v1.14.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/buger/goterm v1.0.4 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/civo/civogo v0.3.11 // indirect
|
||||
github.com/cloudflare/cloudflare-go v0.70.0 // indirect
|
||||
github.com/compose-spec/compose-go v1.15.0 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/containerd/containerd v1.7.2 // indirect
|
||||
github.com/containerd/continuity v0.4.1 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/containerd/containerd v1.7.11 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpu/goacmedns v0.1.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||
github.com/cpuguy83/dockercfg v0.3.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.9.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493 // indirect
|
||||
github.com/dnsimple/dnsimple-go v1.2.0 // indirect
|
||||
github.com/docker/buildx v0.11.2 // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
|
@ -178,42 +166,33 @@ require (
|
|||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/exoscale/egoscale v0.100.1 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsevents v0.1.1 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/go-resty/resty/v2 v2.7.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/go-zookeeper/zk v1.0.3 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
|
||||
github.com/google/s2a-go v0.1.5 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
|
||||
github.com/gophercloud/gophercloud v1.0.0 // indirect
|
||||
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
|
||||
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
||||
github.com/hashicorp/cronexpr v1.1.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
|
@ -225,8 +204,6 @@ require (
|
|||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/in-toto/in-toto-golang v0.9.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
|
||||
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
|
||||
github.com/jcchavezs/porto v0.1.0 // indirect
|
||||
|
@ -236,8 +213,8 @@ require (
|
|||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
||||
github.com/labbsr0x/goh v1.0.1 // indirect
|
||||
|
@ -246,28 +223,20 @@ require (
|
|||
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
||||
github.com/liquidweb/liquidweb-go v1.6.3 // indirect
|
||||
github.com/looplab/fsm v0.1.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect
|
||||
github.com/mailgun/multibuf v0.1.2 // indirect
|
||||
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.1 // indirect
|
||||
github.com/moby/buildkit v0.12.3 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.0 // indirect
|
||||
github.com/moby/sys/symlink v0.2.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
|
@ -286,23 +255,22 @@ require (
|
|||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/opencontainers/runc v1.1.7 // indirect
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect
|
||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
|
||||
github.com/outcaste-io/ristretto v0.2.3 // indirect
|
||||
github.com/ovh/go-ovh v1.4.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/philhofer/fwd v1.1.2 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/pquerna/otp v1.4.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.2.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/sacloud/api-client-go v0.2.8 // indirect
|
||||
github.com/sacloud/go-http v0.1.6 // indirect
|
||||
github.com/sacloud/iaas-api-go v1.11.1 // indirect
|
||||
|
@ -311,53 +279,36 @@ require (
|
|||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.17 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect
|
||||
github.com/segmentio/fasthash v1.0.3 // indirect
|
||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 // indirect
|
||||
github.com/shibumi/go-pathspec v1.3.0 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.23.11 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 // indirect
|
||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
||||
github.com/softlayer/softlayer-go v1.1.2 // indirect
|
||||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.5.1 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
|
||||
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 // indirect
|
||||
github.com/tinylib/msgp v1.1.8 // indirect
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb // indirect
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
|
||||
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/transip/gotransip/v6 v6.20.0 // indirect
|
||||
github.com/ultradns/ultradns-go-sdk v1.5.0-20230427130837-23c9b0c // indirect
|
||||
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||
github.com/vultr/govultr/v2 v2.17.2 // indirect
|
||||
github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
|
||||
github.com/zmap/zlint/v3 v3.1.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.elastic.co/apm/module/apmhttp v1.13.1 // indirect
|
||||
go.elastic.co/fastjson v1.1.0 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.6 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.6 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 // indirect
|
||||
go.opentelemetry.io/otel v1.20.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.20.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.20.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.20.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/goleak v1.3.0 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/ratelimit v0.2.0 // indirect
|
||||
|
@ -368,8 +319,7 @@ require (
|
|||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/oauth2 v0.11.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.128.0 // indirect
|
||||
|
@ -394,7 +344,6 @@ require (
|
|||
// Containous forks
|
||||
replace (
|
||||
github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e
|
||||
github.com/go-check/check => github.com/containous/check v0.0.0-20170915194414-ca0bf163426a
|
||||
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20220627093034-b2dd784e613f
|
||||
github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
|
||||
)
|
||||
|
|
332
go.sum
332
go.sum
|
@ -40,15 +40,13 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
|||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 h1:+vTEFqeoeur6XSq06bs+roX3YiT49gUniJK7Zky7Xjg=
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 h1:Dy3M9aegiI7d7PF1LUdjbVigJReo+QOceYsMyFh9qoE=
|
||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesnDfrtF6RFUGzQfLo=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk=
|
||||
|
@ -131,20 +129,15 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
|
|||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek=
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM=
|
||||
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
|
||||
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24=
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/sarama v1.38.1 h1:lqqPUPQZ7zPqYlWpTh+LQ9bhYNu2xJL6k1SJN4WVe2A=
|
||||
github.com/Shopify/sarama v1.38.1/go.mod h1:iwv9a67Ha8VNa+TifujYoWGxWnu2kNVAQdSdZ4X2o5g=
|
||||
|
@ -163,8 +156,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
|
|||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU=
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
|
||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
|
||||
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
|
@ -178,8 +169,6 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
|
|||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c h1:651/eoCRnQ7YtSjAnSzRucrJz+3iGEFt+ysraELS81M=
|
||||
github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
|
@ -227,27 +216,15 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
|||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=
|
||||
github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
|
||||
github.com/bugsnag/bugsnag-go v1.0.5/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/bugsnag-go v1.5.0 h1:tP8hiPv1pGGW3LA6LKy5lW6WG+y9J2xWUdPd3WC452k=
|
||||
github.com/bugsnag/bugsnag-go v1.5.0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA=
|
||||
github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
|
||||
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
|
@ -268,9 +245,6 @@ github.com/civo/civogo v0.3.11 h1:mON/fyrV946Sbk6paRtOSGsN+asCgCmHCgArf5xmGxM=
|
|||
github.com/civo/civogo v0.3.11/go.mod h1:7+GeeFwc4AYTULaEshpT2vIcl3Qq8HPoxA17viX3l6g=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||
github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8=
|
||||
github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0=
|
||||
github.com/cloudflare/cloudflare-go v0.70.0 h1:4opGbUygM8DjirUuaz23jn3akuAcnOCEx+0nQtQEcFo=
|
||||
github.com/cloudflare/cloudflare-go v0.70.0/go.mod h1:VW6GuazkaZ4xEDkFt24lkXQUsE8q7BiGqDniC2s8WEM=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
|
@ -281,38 +255,15 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH
|
|||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
|
||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
|
||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
|
||||
github.com/compose-spec/compose-go v1.15.0 h1:rv3TTgbS3U4Y8sRTngrcxDmpbz+fq26wTqHculSCi6s=
|
||||
github.com/compose-spec/compose-go v1.15.0/go.mod h1:3yngGBGfls6FHGQsg4B1z6gz8ej9SOvmAJtxCwgbcnc=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/containerd v1.7.2 h1:UF2gdONnxO8I6byZXDi5sXWiWvlW3D/sci7dTQimEJo=
|
||||
github.com/containerd/containerd v1.7.2/go.mod h1:afcz74+K10M/+cjGHIVQrCt3RAQhUSCAjJ9iMYhhkuI=
|
||||
github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU=
|
||||
github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||
github.com/containerd/nydus-snapshotter v0.8.2 h1:7SOrMU2YmLzfbsr5J7liMZJlNi5WT6vtIOxLGv+iz7E=
|
||||
github.com/containerd/nydus-snapshotter v0.8.2/go.mod h1:UJILTN5LVBRY+dt8BGJbp72Xy729hUZsOugObEI3/O8=
|
||||
github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
|
||||
github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs=
|
||||
github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak=
|
||||
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
|
||||
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
|
||||
github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw=
|
||||
github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd h1:0n+lFLh5zU0l6KSk3KpnDwfbPGAR44aRLgTbCnhRBHU=
|
||||
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd/go.mod h1:BbQgeDS5i0tNvypwEoF1oNjOJw8knRAE1DnVvjDstcQ=
|
||||
github.com/containous/check v0.0.0-20170915194414-ca0bf163426a h1:8esAQaPKjfntQR1bag/mAOvWJd5HqSX5nsa+0KT63zo=
|
||||
github.com/containous/check v0.0.0-20170915194414-ca0bf163426a/go.mod h1:eQOqZ7GoFsLxI7jFKLs7+Nv2Rm1x4FyK8d2NV+yGjwQ=
|
||||
github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e h1:D+uTEzDZc1Fhmd0Pq06c+O9+KkAyExw0eVmu/NOqaHU=
|
||||
github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e/go.mod h1:s8kLgBQolDbsJOPVIGCEEv9zGAKUUf/685Gi0Qqg8z8=
|
||||
github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595 h1:aPspFRO6b94To3gl4yTDOEtpjFwXI7V2W+z0JcNljQ4=
|
||||
|
@ -336,18 +287,16 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
|
|||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4=
|
||||
github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
|
||||
github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
|
||||
github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
|
@ -357,7 +306,6 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.
|
|||
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
|
||||
github.com/deepmap/oapi-codegen v1.9.1 h1:yHmEnA7jSTUMQgV+uN02WpZtwHnz2CBW3mZRIxr1vtI=
|
||||
github.com/deepmap/oapi-codegen v1.9.1/go.mod h1:PLqNAhdedP8ttRpBBkzLKU3bp+Fpy+tTgeAMlztR2cw=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
|
@ -366,38 +314,20 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
|
|||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
|
||||
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493 h1:fm5DpBD+A7o0+x9Nf+o9/4/qPGbfxLpr9qIPVuV8vQc=
|
||||
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493/go.mod h1:+fqBJ4vPYo4Uu1ZE4d+bUtTLRXfdSL3NvCZIZ9GHv58=
|
||||
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/dnsimple/dnsimple-go v1.2.0 h1:ddTGyLVKly5HKb5L65AkLqFqwZlWo3WnR0BlFZlIddM=
|
||||
github.com/dnsimple/dnsimple-go v1.2.0/go.mod h1:z/cs26v/eiRvUyXsHQBLd8lWF8+cD6GbmkPH84plM4U=
|
||||
github.com/docker/buildx v0.11.2 h1:R3p9F0gnI4FwvQ0p40UwdX1T4ugap4UWxY3TFHoP4Ws=
|
||||
github.com/docker/buildx v0.11.2/go.mod h1:CWAABt10iIuGpleypA3103mplDfcGu0A2AvT03xfpTc=
|
||||
github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg=
|
||||
github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/compose/v2 v2.19.0 h1:88LLRdyeVdkuIlc9wJ6SPUs2x5IoF4O9DtCgPS/d9lA=
|
||||
github.com/docker/compose/v2 v2.19.0/go.mod h1:08yDbnLQKUqBpL862sUo4RBSKXt0n0XLtIbaUSMW1O8=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
|
||||
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e h1:rMOGp6HPeMHbdLrZkX2nD+94uqDunc27tXVuS+ey4mQ=
|
||||
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw=
|
||||
|
@ -405,7 +335,6 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb
|
|||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
|
||||
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-resiliency v1.4.0 h1:3OK9bWpPk5q6pbFAaYSEwD9CLUSHG8bnZuqX2yMt3B0=
|
||||
|
@ -427,8 +356,6 @@ github.com/elastic/go-sysinfo v1.1.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6
|
|||
github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY=
|
||||
github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484 h1:pEtiCjIXx3RvGjlUJuCNxNOw0MNblyR9Wi+vJGBFh+8=
|
||||
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
|
@ -443,9 +370,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
|
|||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
|
@ -461,8 +385,6 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
|||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
|
@ -470,15 +392,11 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB
|
|||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/fsnotify/fsevents v0.1.1 h1:/125uxJvvoSDDBPen6yUZbil8J9ydKZnnl3TWWmvnkw=
|
||||
github.com/fsnotify/fsevents v0.1.1/go.mod h1:+d+hS27T6k5J8CRaPLKFgwKYcpS7GwW3Ule9+SC2ZRc=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 h1:df6OFl8WNXk82xxP3R9ZPZ5seOA8XZkwLdbEzZF1/xI=
|
||||
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2/go.mod h1:GLyXJD41gBO/NPKVPGQbhyyC06eugGy15QEZyUkE2/s=
|
||||
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||
|
@ -512,12 +430,11 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
|
|||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
|
@ -543,9 +460,6 @@ github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSG
|
|||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
|
@ -558,14 +472,9 @@ github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVr
|
|||
github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc=
|
||||
github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
|
||||
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
|
@ -578,11 +487,8 @@ github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
|
|||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
|
||||
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
@ -598,7 +504,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
|||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -627,9 +532,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
|
|||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||
github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY=
|
||||
github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ=
|
||||
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
|
||||
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
|
@ -646,6 +548,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
|
||||
|
@ -678,14 +581,12 @@ github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0Z
|
|||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.5 h1:8IYp3w9nysqv3JH+NJgXJzGbDHzLOTj43BmSkp+O7qg=
|
||||
github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
|
@ -711,18 +612,12 @@ github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf/go.mod h1:z
|
|||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/api v1.26.1 h1:5oSXOO5fboPZeW5SN+TdGFP/BILDgBm19OrPZ/pICIM=
|
||||
|
@ -778,8 +673,6 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
|
|||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
|
||||
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
||||
|
@ -791,8 +684,6 @@ github.com/hashicorp/nomad/api v0.0.0-20220506174431-b5665129cd1f/go.mod h1:b/Ao
|
|||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
|
||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
|
@ -807,11 +698,7 @@ github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
|
|||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
|
||||
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.7.0 h1:QgP5mlBE9sGnzplpnf96pr+p7uqlIlL4W2GAP3n+XZg=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.7.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
|
||||
|
@ -840,20 +727,11 @@ github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP
|
|||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
|
||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||
github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
|
@ -875,16 +753,11 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
|||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
|
@ -936,7 +809,6 @@ github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++
|
|||
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||
github.com/lestrrat-go/jwx v1.2.7/go.mod h1:bw24IXWbavc0R2RsOtpXL7RtMyP589yZ1+L7kd09ZGA=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/linode/linodego v1.17.2 h1:b32dj4662PGG5P9qVa6nBezccWdqgukndlMIuPGq1CQ=
|
||||
|
@ -951,13 +823,14 @@ github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHS
|
|||
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
||||
github.com/looplab/fsm v0.1.0 h1:Qte7Zdn/5hBNbXzP7yxVU4OIFHWXBovyTT2LaBTyC20=
|
||||
github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailgun/multibuf v0.1.2 h1:QE9kE27lK6LFZB4aYNVtUPlWVHVCT0zpgUr2uoq/+jk=
|
||||
github.com/mailgun/multibuf v0.1.2/go.mod h1:E+sUhIy69qgT6EM57kCPdUTlHnjTuxQBO/yf6af9Hes=
|
||||
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ=
|
||||
|
@ -996,11 +869,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
|
@ -1008,17 +876,12 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk
|
|||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
|
||||
github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||
github.com/miekg/dns v1.1.47/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
|
||||
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mimuret/golang-iij-dpf v0.9.1 h1:Gj6EhHJkOhr+q2RnvRPJsPMcjuVnWPSccEHyoEehU34=
|
||||
github.com/mimuret/golang-iij-dpf v0.9.1/go.mod h1:sl9KyOkESib9+KRD3HaGpgi1xk7eoN2+d96LCLsME2M=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
|
@ -1036,7 +899,6 @@ github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9
|
|||
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
|
@ -1045,22 +907,11 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
|||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
|
||||
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/buildkit v0.12.3 h1:cFaPVnyC0PwAP5xHHfzdU5v9rgQrCi6HnGSg3WuFKp4=
|
||||
github.com/moby/buildkit v0.12.3/go.mod h1:adB4y0SxxX8trnrY+oEulb48ODLqPO6pKMF0ppGcCoI=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||
github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc=
|
||||
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
|
@ -1073,7 +924,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
|||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
|
@ -1120,7 +970,6 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
|
|||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
|
@ -1134,7 +983,6 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
|
|||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
|
@ -1145,15 +993,10 @@ github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+q
|
|||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||
github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk=
|
||||
github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.2 h1:ucBtEms2tamYYW/SvGpvq9yUN0NEVL6oyLEwDcTSrk8=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
|
@ -1183,10 +1026,6 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP
|
|||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
|
||||
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
|
||||
|
@ -1213,10 +1052,11 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
|||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
|
@ -1229,7 +1069,6 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr
|
|||
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
|
||||
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
|
@ -1238,7 +1077,6 @@ github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
|
|||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
|
@ -1250,7 +1088,6 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8
|
|||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
||||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
|
@ -1279,14 +1116,12 @@ github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6Qml
|
|||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA=
|
||||
github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
|
@ -1311,22 +1146,21 @@ github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAj
|
|||
github.com/secure-systems-lab/go-securesystemslib v0.7.0/go.mod h1:/2gYnlnHVQ6xeGtfIqFy7Do03K4cdCY0A/GlJLDKLHI=
|
||||
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
|
||||
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
|
||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 h1:ka9QPuQg2u4LGipiZGsgkg3rJCo4iIUCy75FddM0GRQ=
|
||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
|
||||
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
|
||||
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
|
||||
github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ=
|
||||
github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 h1:ZTzdx88+AcnjqUfJwnz89UBrMSBQ1NEysg9u5d+dU9c=
|
||||
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04/go.mod h1:5KS21fpch8TIMyAUv/qQqTa3GZfBDYgjaZbd2KXKYfg=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
|
@ -1346,41 +1180,27 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ
|
|||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spdx/tools-golang v0.5.1 h1:fJg3SVOGG+eIva9ZUBm/hvyA7PIPVFjRxUKe6fdAgwE=
|
||||
github.com/spdx/tools-golang v0.5.1/go.mod h1:/DRDQuBfB37HctM29YtrX1v+bXiVmT2OpQDalRmX9aU=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
|
||||
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||
github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
|
@ -1408,26 +1228,20 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|||
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 h1:XGopsea1Dw7ecQ8JscCNQXDGYAKDiWjDeXnpN/+BY9g=
|
||||
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 h1:mmz27tVi2r70JYnm5y0Zk8w0Qzsx+vfUw3oqSyrEfP8=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 h1:g9SWTaTy/rEuhMErC2jWq9Qt5ci+jBYSvXnJsLq4adg=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490/go.mod h1:l9q4vc1QiawUB1m3RU+87yLvrrxe54jc0w/kEl4DbSQ=
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a h1:tlJ7tGUHvcvL1v3yR6NcCc9nOqh2L+CG6HWrYQtwzQ0=
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a/go.mod h1:Y94A6rPp2OwNfP/7vmf8O2xx2IykP8pPXQ1DLouGnEw=
|
||||
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA=
|
||||
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g=
|
||||
github.com/testcontainers/testcontainers-go v0.27.0 h1:IeIrJN4twonTDuMuBNQdKZ+K97yd7VrmNGu+lDpYcDk=
|
||||
github.com/testcontainers/testcontainers-go v0.27.0/go.mod h1:+HgYZcd17GshBUZv9b+jKFJ198heWPQq3KQIp2+N+7U=
|
||||
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
|
||||
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb h1:uUe8rNyVXM8moActoBol6Xf6xX2GMr7SosR2EywMvGg=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20230629203738-36ef4d8c0dbb/go.mod h1:SxX/oNQ/ag6Vaoli547ipFK9J7BZn5JqJG0JE8lf8bA=
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
|
||||
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 h1:Y/M5lygoNPKwVNLMPXgVfsRT40CSFKXCxuU8LoHySjs=
|
||||
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=
|
||||
github.com/traefik/paerser v0.2.0 h1:zqCLGSXoNlcBd+mzqSCLjon/I6phqIjeJL2xFB2ysgQ=
|
||||
github.com/traefik/paerser v0.2.0/go.mod h1:afzaVcgF8A+MpTnPG4wBr4whjanCSYA6vK5RwaYVtRc=
|
||||
github.com/traefik/yaegi v0.15.1 h1:YA5SbaL6HZA0Exh9T/oArRHqGN2HQ+zgmCY7dkoTXu4=
|
||||
|
@ -1456,10 +1270,6 @@ github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn
|
|||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
|
||||
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
|
||||
github.com/vdemeester/shakers v0.1.0 h1:K+n9sSyUCg2ywmZkv+3c7vsYZfivcfKhMh8kRxCrONM=
|
||||
github.com/vdemeester/shakers v0.1.0/go.mod h1:IZ1HHynUOQt32iQ3rvAeVddXLd19h/6LWiKsh9RZtAQ=
|
||||
github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4ulRMcQ=
|
||||
github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q=
|
||||
github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c h1:Qt/YKpE8uAKNF4x2mwBZxmVo2WtgUL1WFDeXr1nlfpA=
|
||||
|
@ -1468,15 +1278,8 @@ github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt
|
|||
github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA=
|
||||
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
|
||||
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
|
||||
github.com/weppos/publicsuffix-go v0.13.1-0.20210123135404-5fd73613514e/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE=
|
||||
github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b h1:FsyNrX12e5BkplJq7wKOLk0+C6LZ+KGXvuEcKUYm5ss=
|
||||
github.com/weppos/publicsuffix-go v0.15.1-0.20210511084619-b1f36a2d6c0b/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f h1:cG+ehPRJSlqljSufLf1KXeXpUd1dLNjnzA18mZcB/O0=
|
||||
|
@ -1489,13 +1292,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
|
||||
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
|
||||
github.com/zmap/zcrypto v0.0.0-20210123152837-9cf5beac6d91/go.mod h1:R/deQh6+tSWlgI9tb4jNmXxn8nSCabl5ZQsBX9//I/E=
|
||||
github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c h1:ufDm/IlBYZYLuiqvQuhpTKwrcAS2OlXEzWbDvTVGbSQ=
|
||||
github.com/zmap/zcrypto v0.0.0-20220605182715-4dfcec6e9a8c/go.mod h1:egdRkzUylATvPkWMpebZbXhv0FMEMJGX/ur0D3Csk2s=
|
||||
github.com/zmap/zlint/v3 v3.1.0 h1:WjVytZo79m/L1+/Mlphl09WBob6YTGljN5IGWZFpAv0=
|
||||
github.com/zmap/zlint/v3 v3.1.0/go.mod h1:L7t8s3sEKkb0A2BxGy1IWrxt1ZATa1R4QfJZaQOD3zU=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.elastic.co/apm v1.13.1 h1:ICIcUcQOImg/bve9mQVyLCvm1cSUZ1afdwK6ACnxczU=
|
||||
go.elastic.co/apm v1.13.1/go.mod h1:dylGv2HKR0tiCV+wliJz1KHtDyuD8SPe69oV7VyK6WY=
|
||||
go.elastic.co/apm/module/apmhttp v1.13.1 h1:g2id6+AY8NRSA6nzwPDSU1AmBiHyZeh/lJRBlXq2yfQ=
|
||||
|
@ -1529,29 +1327,7 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
|||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.0 h1:WUMhXWqLmFlznidWF4B9iML8VMdZy4TzJVYzdYTCuaM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.0/go.mod h1:H1XIOXyXFff1aZa7nQeFHGYMB+gHH1TtZSti37uHX6o=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 h1:1eHu3/pUSWaOgltNK3WJFaywKsTIr/PwvHyDmi0lQA0=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0/go.mod h1:HyABWq60Uy1kjJSa2BVOxUVao8Cdick5AWSKPutqy6U=
|
||||
go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc=
|
||||
go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0 h1:CsBiKCiQPdSjS+MlRiqeTI9JDDpSuk0Hb6QTRfwer8k=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0/go.mod h1:CMJYNAfooOwSZSAmAeMUV1M+TXld3BiK++z9fqIm2xk=
|
||||
go.opentelemetry.io/otel/metric v1.20.0 h1:ZlrO8Hu9+GAhnepmRGhSU7/VkpjrNowxRN9GyKR4wzA=
|
||||
go.opentelemetry.io/otel/metric v1.20.0/go.mod h1:90DRw3nfK4D7Sm/75yQ00gTJxtkBxX+wu6YaNymbpVM=
|
||||
go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM=
|
||||
go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0=
|
||||
go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ=
|
||||
go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
|
@ -1588,7 +1364,6 @@ go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2/go.mod h1:
|
|||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
@ -1597,14 +1372,11 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
|
@ -1776,6 +1548,7 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -1813,8 +1586,8 @@ golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -1825,7 +1598,6 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -1837,11 +1609,9 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -1853,8 +1623,10 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
@ -2029,7 +1801,6 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG
|
|||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
|
@ -2059,7 +1830,6 @@ google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:
|
|||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
|
@ -2108,10 +1878,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs
|
|||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.56.1 h1:AUe/ZF7xm6vYnigPe+TY54DmfWYJxhMRaw/TfvrbzvE=
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.56.1/go.mod h1:KDLJ3CWVOSuVVwu+0ZR5KZo2rP6c7YyBV3v387dIpUU=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII=
|
||||
gopkg.in/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -2122,7 +1889,6 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
|
|||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/h2non/gock.v1 v1.0.15 h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0=
|
||||
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
|
@ -2137,8 +1903,6 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24
|
|||
gopkg.in/ns1/ns1-go.v2 v2.7.6 h1:mCPl7q0jbIGACXvGBljAuuApmKZo3rRi4tlRIEbMvjA=
|
||||
gopkg.in/ns1/ns1-go.v2 v2.7.6/go.mod h1:GMnKY+ZuoJ+lVLL+78uSTjwTz2jMazq6AfGKQOYhsPk=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM=
|
||||
gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
|
@ -2160,8 +1924,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
|
||||
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -11,13 +11,15 @@ import (
|
|||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -28,6 +30,10 @@ const (
|
|||
// AccessLogSuite tests suite.
|
||||
type AccessLogSuite struct{ BaseSuite }
|
||||
|
||||
func TestAccessLogSuite(t *testing.T) {
|
||||
suite.Run(t, new(AccessLogSuite))
|
||||
}
|
||||
|
||||
type accessLogValue struct {
|
||||
formatOnly bool
|
||||
code string
|
||||
|
@ -36,67 +42,67 @@ type accessLogValue struct {
|
|||
serviceURL string
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "access_log")
|
||||
s.composeUp(c)
|
||||
func (s *AccessLogSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("access_log")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TearDownTest(c *check.C) {
|
||||
displayTraefikLogFile(c, traefikTestLogFile)
|
||||
func (s *AccessLogSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TearDownTest() {
|
||||
s.displayTraefikLogFile(traefikTestLogFile)
|
||||
_ = os.Remove(traefikTestAccessLogFile)
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLog(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLog() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
defer func() {
|
||||
traefikLog, err := os.ReadFile(traefikTestLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Info(string(traefikLog))
|
||||
}()
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Make some requests
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend1.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend2.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogOutput(c)
|
||||
count := s.checkAccessLogOutput()
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, 3)
|
||||
assert.Equal(s.T(), 3, count)
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontend() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -124,48 +130,43 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontend(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "authFrontend")
|
||||
s.waitForTraefik("authFrontend")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test auth entrypoint
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8006/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend.auth.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req.SetBasicAuth("test", "")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req.SetBasicAuth("test", "test")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -193,27 +194,22 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "digestAuthMiddleware")
|
||||
s.waitForTraefik("digestAuthMiddleware")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test auth entrypoint
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8008/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "entrypoint.digest.auth.docker.local"
|
||||
|
||||
resp, err := try.ResponseUntilStatusCode(req, 500*time.Millisecond, http.StatusUnauthorized)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
digest := digestParts(resp)
|
||||
digest["uri"] = "/"
|
||||
|
@ -225,22 +221,22 @@ func (s *AccessLogSuite) TestAccessLogDigestAuthMiddleware(c *check.C) {
|
|||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
digest["password"] = "test"
|
||||
|
||||
req.Header.Set("Authorization", getDigestAuthorization(digest))
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
// Thanks to mvndaai for digest authentication
|
||||
|
@ -291,7 +287,7 @@ func getDigestAuthorization(digestParts map[string]string) string {
|
|||
return authorization
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendRedirect() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -308,38 +304,33 @@ func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "frontendRedirect")
|
||||
s.waitForTraefik("frontendRedirect")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test frontend redirect
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8005/test", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = ""
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
type logLine struct {
|
||||
|
@ -365,30 +356,25 @@ func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_json_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_json_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "frontendRedirect")
|
||||
s.waitForTraefik("frontendRedirect")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test frontend redirect
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8005/test", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = ""
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
lines := extractLines(c)
|
||||
c.Assert(len(lines), checker.GreaterOrEqualThan, len(expected))
|
||||
lines := s.extractLines()
|
||||
assert.GreaterOrEqual(s.T(), len(lines), len(expected))
|
||||
|
||||
for i, line := range lines {
|
||||
if line == "" {
|
||||
|
@ -396,15 +382,15 @@ func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect(c *check.C) {
|
|||
}
|
||||
var logline logLine
|
||||
err := json.Unmarshal([]byte(line), &logline)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(logline.DownstreamStatus, checker.Equals, expected[i].DownstreamStatus)
|
||||
c.Assert(logline.OriginStatus, checker.Equals, expected[i].OriginStatus)
|
||||
c.Assert(logline.RouterName, checker.Equals, expected[i].RouterName)
|
||||
c.Assert(logline.ServiceName, checker.Equals, expected[i].ServiceName)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), expected[i].DownstreamStatus, logline.DownstreamStatus)
|
||||
assert.Equal(s.T(), expected[i].OriginStatus, logline.OriginStatus)
|
||||
assert.Equal(s.T(), expected[i].RouterName, logline.RouterName)
|
||||
assert.Equal(s.T(), expected[i].ServiceName, logline.ServiceName)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogRateLimit() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -424,42 +410,37 @@ func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "rateLimit")
|
||||
s.waitForTraefik("rateLimit")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test rate limit
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8007/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "ratelimit.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogBackendNotFound(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogBackendNotFound() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -473,38 +454,33 @@ func (s *AccessLogSuite) TestAccessLogBackendNotFound(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test rate limit
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "backendnotfound.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendWhitelist(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogFrontendWhitelist() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -518,38 +494,33 @@ func (s *AccessLogSuite) TestAccessLogFrontendWhitelist(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "frontendWhitelist")
|
||||
s.waitForTraefik("frontendWhitelist")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test rate limit
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend.whitelist.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusForbidden), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -563,39 +534,34 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "authFrontend")
|
||||
s.waitForTraefik("authFrontend")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test auth entrypoint
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8006/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend.auth.docker.local"
|
||||
req.SetBasicAuth("test", "test")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware(c *check.C) {
|
||||
func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware() {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
|
@ -609,79 +575,74 @@ func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware(c *check.C) {
|
|||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.checkStatsForLogFile()
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "preflightCORS")
|
||||
s.waitForTraefik("preflightCORS")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
s.checkTraefikStarted()
|
||||
|
||||
// Test preflight response
|
||||
req, err := http.NewRequest(http.MethodOptions, "http://127.0.0.1:8009/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "preflight.docker.local"
|
||||
req.Header.Set("Origin", "whatever")
|
||||
req.Header.Set("Access-Control-Request-Method", "GET")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
count := s.checkAccessLogExactValuesOutput(expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
assert.GreaterOrEqual(s.T(), count, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
s.checkNoOtherTraefikProblems()
|
||||
}
|
||||
|
||||
func checkNoOtherTraefikProblems(c *check.C) {
|
||||
func (s *AccessLogSuite) checkNoOtherTraefikProblems() {
|
||||
traefikLog, err := os.ReadFile(traefikTestLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
if len(traefikLog) > 0 {
|
||||
fmt.Printf("%s\n", string(traefikLog))
|
||||
}
|
||||
}
|
||||
|
||||
func checkAccessLogOutput(c *check.C) int {
|
||||
lines := extractLines(c)
|
||||
func (s *AccessLogSuite) checkAccessLogOutput() int {
|
||||
lines := s.extractLines()
|
||||
count := 0
|
||||
for i, line := range lines {
|
||||
if len(line) > 0 {
|
||||
count++
|
||||
CheckAccessLogFormat(c, line, i)
|
||||
s.CheckAccessLogFormat(line, i)
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func checkAccessLogExactValuesOutput(c *check.C, values []accessLogValue) int {
|
||||
lines := extractLines(c)
|
||||
func (s *AccessLogSuite) checkAccessLogExactValuesOutput(values []accessLogValue) int {
|
||||
lines := s.extractLines()
|
||||
count := 0
|
||||
for i, line := range lines {
|
||||
fmt.Println(line)
|
||||
if len(line) > 0 {
|
||||
count++
|
||||
if values[i].formatOnly {
|
||||
CheckAccessLogFormat(c, line, i)
|
||||
s.CheckAccessLogFormat(line, i)
|
||||
} else {
|
||||
checkAccessLogExactValues(c, line, i, values[i])
|
||||
s.checkAccessLogExactValues(line, i, values[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func extractLines(c *check.C) []string {
|
||||
func (s *AccessLogSuite) extractLines() []string {
|
||||
accessLog, err := os.ReadFile(traefikTestAccessLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
lines := strings.Split(string(accessLog), "\n")
|
||||
|
||||
|
@ -694,14 +655,14 @@ func extractLines(c *check.C) []string {
|
|||
return clean
|
||||
}
|
||||
|
||||
func checkStatsForLogFile(c *check.C) {
|
||||
func (s *AccessLogSuite) checkStatsForLogFile() {
|
||||
err := try.Do(1*time.Second, func() error {
|
||||
if _, errStat := os.Stat(traefikTestLogFile); errStat != nil {
|
||||
return fmt.Errorf("could not get stats for log file: %w", errStat)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func ensureWorkingDirectoryIsClean() {
|
||||
|
@ -709,69 +670,38 @@ func ensureWorkingDirectoryIsClean() {
|
|||
os.Remove(traefikTestLogFile)
|
||||
}
|
||||
|
||||
func checkTraefikStarted(c *check.C) []byte {
|
||||
func (s *AccessLogSuite) checkTraefikStarted() []byte {
|
||||
traefikLog, err := os.ReadFile(traefikTestLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
if len(traefikLog) > 0 {
|
||||
fmt.Printf("%s\n", string(traefikLog))
|
||||
}
|
||||
return traefikLog
|
||||
}
|
||||
|
||||
func CheckAccessLogFormat(c *check.C, line string, i int) {
|
||||
func (s *BaseSuite) CheckAccessLogFormat(line string, i int) {
|
||||
results, err := accesslog.ParseAccessLog(line)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(results, checker.HasLen, 14)
|
||||
c.Assert(results[accesslog.OriginStatus], checker.Matches, `^(-|\d{3})$`)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Len(s.T(), results, 14)
|
||||
assert.Regexp(s.T(), `^(-|\d{3})$`, results[accesslog.OriginStatus])
|
||||
count, _ := strconv.Atoi(results[accesslog.RequestCount])
|
||||
c.Assert(count, checker.GreaterOrEqualThan, i+1)
|
||||
c.Assert(results[accesslog.RouterName], checker.Matches, `"(rt-.+@docker|api@internal)"`)
|
||||
c.Assert(results[accesslog.ServiceURL], checker.HasPrefix, `"http://`)
|
||||
c.Assert(results[accesslog.Duration], checker.Matches, `^\d+ms$`)
|
||||
assert.GreaterOrEqual(s.T(), count, i+1)
|
||||
assert.Regexp(s.T(), `"(rt-.+@docker|api@internal)"`, results[accesslog.RouterName])
|
||||
assert.True(s.T(), strings.HasPrefix(results[accesslog.ServiceURL], `"http://`))
|
||||
assert.Regexp(s.T(), `^\d+ms$`, results[accesslog.Duration])
|
||||
}
|
||||
|
||||
func checkAccessLogExactValues(c *check.C, line string, i int, v accessLogValue) {
|
||||
func (s *AccessLogSuite) checkAccessLogExactValues(line string, i int, v accessLogValue) {
|
||||
results, err := accesslog.ParseAccessLog(line)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(results, checker.HasLen, 14)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Len(s.T(), results, 14)
|
||||
if len(v.user) > 0 {
|
||||
c.Assert(results[accesslog.ClientUsername], checker.Equals, v.user)
|
||||
assert.Equal(s.T(), v.user, results[accesslog.ClientUsername])
|
||||
}
|
||||
c.Assert(results[accesslog.OriginStatus], checker.Equals, v.code)
|
||||
assert.Equal(s.T(), v.code, results[accesslog.OriginStatus])
|
||||
count, _ := strconv.Atoi(results[accesslog.RequestCount])
|
||||
c.Assert(count, checker.GreaterOrEqualThan, i+1)
|
||||
c.Assert(results[accesslog.RouterName], checker.Matches, `^"?`+v.routerName+`.*(@docker)?$`)
|
||||
c.Assert(results[accesslog.ServiceURL], checker.Matches, `^"?`+v.serviceURL+`.*$`)
|
||||
c.Assert(results[accesslog.Duration], checker.Matches, `^\d+ms$`)
|
||||
}
|
||||
|
||||
func waitForTraefik(c *check.C, containerName string) {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func displayTraefikLogFile(c *check.C, path string) {
|
||||
if c.Failed() {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
content, errRead := os.ReadFile(path)
|
||||
fmt.Printf("%s: Traefik logs: \n", c.TestName())
|
||||
if errRead == nil {
|
||||
fmt.Println(content)
|
||||
} else {
|
||||
fmt.Println(errRead)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%s: No Traefik logs.\n", c.TestName())
|
||||
}
|
||||
errRemove := os.Remove(path)
|
||||
if errRemove != nil {
|
||||
fmt.Println(errRemove)
|
||||
}
|
||||
}
|
||||
assert.GreaterOrEqual(s.T(), count, i+1)
|
||||
assert.Regexp(s.T(), `^"?`+v.routerName+`.*(@docker)?$`, results[accesslog.RouterName])
|
||||
assert.Regexp(s.T(), `^"?`+v.serviceURL+`.*$`, results[accesslog.ServiceURL])
|
||||
assert.Regexp(s.T(), `^\d+ms$`, results[accesslog.Duration])
|
||||
}
|
||||
|
|
|
@ -8,16 +8,19 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/static"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/provider/acme"
|
||||
"github.com/traefik/traefik/v2/pkg/testhelpers"
|
||||
"github.com/traefik/traefik/v2/pkg/types"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// ACME test suites.
|
||||
|
@ -27,6 +30,10 @@ type AcmeSuite struct {
|
|||
fakeDNSServer *dns.Server
|
||||
}
|
||||
|
||||
func TestAcmeSuite(t *testing.T) {
|
||||
suite.Run(t, new(AcmeSuite))
|
||||
}
|
||||
|
||||
type subCases struct {
|
||||
host string
|
||||
expectedCommonName string
|
||||
|
@ -87,17 +94,18 @@ func setupPebbleRootCA() (*http.Transport, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "pebble")
|
||||
s.composeUp(c)
|
||||
func (s *AcmeSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.fakeDNSServer = startFakeDNSServer(s.getContainerIP(c, "traefik"))
|
||||
s.pebbleIP = s.getComposeServiceIP(c, "pebble")
|
||||
s.createComposeProject("pebble")
|
||||
s.composeUp()
|
||||
|
||||
// Retrieving the Docker host ip.
|
||||
s.fakeDNSServer = startFakeDNSServer(s.hostIP)
|
||||
s.pebbleIP = s.getComposeServiceIP("pebble")
|
||||
|
||||
pebbleTransport, err := setupPebbleRootCA()
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// wait for pebble
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, s.getAcmeURL(), nil)
|
||||
|
@ -113,21 +121,24 @@ func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
|||
}
|
||||
return try.StatusCodeIs(http.StatusOK)(resp)
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TearDownSuite(c *check.C) {
|
||||
func (s *AcmeSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
if s.fakeDNSServer != nil {
|
||||
err := s.fakeDNSServer.Shutdown()
|
||||
if err != nil {
|
||||
c.Log(err)
|
||||
log.WithoutContext().Info(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
s.composeDown(c)
|
||||
s.composeDown()
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01Domains(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01Domains() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -147,10 +158,10 @@ func (s *AcmeSuite) TestHTTP01Domains(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01StoreDomains(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01StoreDomains() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_store_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -170,10 +181,10 @@ func (s *AcmeSuite) TestHTTP01StoreDomains(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01DomainsInSAN(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01DomainsInSAN() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -194,10 +205,10 @@ func (s *AcmeSuite) TestHTTP01DomainsInSAN(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRule(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRule() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -214,10 +225,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRule(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestMultipleResolver(c *check.C) {
|
||||
func (s *AcmeSuite) TestMultipleResolver() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_multiple_resolvers.toml",
|
||||
subCases: []subCases{
|
||||
|
@ -245,10 +256,10 @@ func (s *AcmeSuite) TestMultipleResolver(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -266,10 +277,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleECDSA(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -287,10 +298,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleInvalidAlgo(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDefaultDynamicCertificatesWithWildcard(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDefaultDynamicCertificatesWithWildcard() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_tls.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -307,10 +318,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDefaultDynamicCertificatesWithWildcard(c
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check.C) {
|
||||
func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_tls_dynamic.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -327,10 +338,10 @@ func (s *AcmeSuite) TestHTTP01OnHostRuleDynamicCertificatesWithWildcard(c *check
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRuleTCP(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRuleTCP() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_tcp.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -347,10 +358,10 @@ func (s *AcmeSuite) TestTLSALPN01OnHostRuleTCP(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01OnHostRule() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_base.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -367,10 +378,10 @@ func (s *AcmeSuite) TestTLSALPN01OnHostRule(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01Domains(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01Domains() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -390,10 +401,10 @@ func (s *AcmeSuite) TestTLSALPN01Domains(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
func (s *AcmeSuite) TestTLSALPN01DomainsInSAN(c *check.C) {
|
||||
func (s *AcmeSuite) TestTLSALPN01DomainsInSAN() {
|
||||
testCase := acmeTestCase{
|
||||
traefikConfFilePath: "fixtures/acme/acme_domains.toml",
|
||||
subCases: []subCases{{
|
||||
|
@ -414,12 +425,12 @@ func (s *AcmeSuite) TestTLSALPN01DomainsInSAN(c *check.C) {
|
|||
},
|
||||
}
|
||||
|
||||
s.retrieveAcmeCertificate(c, testCase)
|
||||
s.retrieveAcmeCertificate(testCase)
|
||||
}
|
||||
|
||||
// Test Let's encrypt down.
|
||||
func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/acme/acme_base.toml", templateModel{
|
||||
func (s *AcmeSuite) TestNoValidLetsEncryptServer() {
|
||||
file := s.adaptFile("fixtures/acme/acme_base.toml", templateModel{
|
||||
Acme: map[string]static.CertificateResolver{
|
||||
"default": {ACME: &acme.Configuration{
|
||||
CAServer: "http://wrongurl:4001/directory",
|
||||
|
@ -427,21 +438,16 @@ func (s *AcmeSuite) TestNoValidLetsEncryptServer(c *check.C) {
|
|||
}},
|
||||
},
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected traefik works
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Doing an HTTPS request and test the response certificate.
|
||||
func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
||||
func (s *AcmeSuite) retrieveAcmeCertificate(testCase acmeTestCase) {
|
||||
if len(testCase.template.PortHTTP) == 0 {
|
||||
testCase.template.PortHTTP = ":5002"
|
||||
}
|
||||
|
@ -456,14 +462,10 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
}
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, testCase.traefikConfFilePath, testCase.template)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile(testCase.traefikConfFilePath, testCase.template)
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
// A real file is needed to have the right mode on acme.json file
|
||||
defer os.Remove("/tmp/acme.json")
|
||||
|
||||
|
@ -477,11 +479,11 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
}
|
||||
|
||||
// wait for traefik (generating acme account take some seconds)
|
||||
err = try.Do(60*time.Second, func() error {
|
||||
err := try.Do(60*time.Second, func() error {
|
||||
_, errGet := client.Get("https://127.0.0.1:5001")
|
||||
return errGet
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
for _, sub := range testCase.subCases {
|
||||
client = &http.Client{
|
||||
|
@ -503,7 +505,7 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
var resp *http.Response
|
||||
|
||||
// Retry to send a Request which uses the LE generated certificate
|
||||
err = try.Do(60*time.Second, func() error {
|
||||
err := try.Do(60*time.Second, func() error {
|
||||
resp, err = client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -517,10 +519,10 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
|
|||
return nil
|
||||
})
|
||||
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, resp.StatusCode)
|
||||
// Check Domain into response certificate
|
||||
c.Assert(resp.TLS.PeerCertificates[0].Subject.CommonName, checker.Equals, sub.expectedCommonName)
|
||||
c.Assert(resp.TLS.PeerCertificates[0].PublicKeyAlgorithm, checker.Equals, sub.expectedAlgorithm)
|
||||
assert.Equal(s.T(), sub.expectedCommonName, resp.TLS.PeerCertificates[0].Subject.CommonName)
|
||||
assert.Equal(s.T(), sub.expectedAlgorithm, resp.TLS.PeerCertificates[0].PublicKeyAlgorithm)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,36 +8,38 @@ import (
|
|||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type ThrottlingSuite struct{ BaseSuite }
|
||||
|
||||
func (s *ThrottlingSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "rest")
|
||||
s.composeUp(c)
|
||||
func TestThrottlingSuite(t *testing.T) {
|
||||
suite.Run(t, new(ThrottlingSuite))
|
||||
}
|
||||
|
||||
func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/throttling/simple.toml"))
|
||||
func (s *ThrottlingSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("rest")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *ThrottlingSuite) TestThrottleConfReload() {
|
||||
s.traefikCmd(withConfigFile("fixtures/throttling/simple.toml"))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Expected a 404 as we did not configure anything.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config := &dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
|
@ -47,7 +49,7 @@ func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
|||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://" + s.getComposeServiceIP(c, "whoami1") + ":80",
|
||||
URL: "http://" + s.getComposeServiceIP("whoami1") + ":80",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -68,28 +70,28 @@ func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
|||
for i := 0; i < confChanges; i++ {
|
||||
config.HTTP.Routers[fmt.Sprintf("routerHTTP%d", i)] = router
|
||||
data, err := json.Marshal(config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", bytes.NewReader(data))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
|
||||
reloadsRegexp := regexp.MustCompile(`traefik_config_reloads_total (\d*)\n`)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/metrics")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
fields := reloadsRegexp.FindStringSubmatch(string(body))
|
||||
c.Assert(len(fields), checker.Equals, 2)
|
||||
assert.Len(s.T(), fields, 2)
|
||||
|
||||
reloads, err := strconv.Atoi(fields[1])
|
||||
if err != nil {
|
||||
|
@ -101,5 +103,5 @@ func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
|
|||
// Therefore the throttling (set at 400ms for this test) should only let
|
||||
// (2s / 400 ms =) 5 config reloads happen in theory.
|
||||
// In addition, we have to take into account the extra config reload from the internal provider (5 + 1).
|
||||
c.Assert(reloads, checker.LessOrEqualThan, 6)
|
||||
assert.LessOrEqual(s.T(), reloads, 6)
|
||||
}
|
||||
|
|
|
@ -4,13 +4,14 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type ConsulCatalogSuite struct {
|
||||
|
@ -20,26 +21,36 @@ type ConsulCatalogSuite struct {
|
|||
consulURL string
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "consul_catalog")
|
||||
s.composeUp(c)
|
||||
func TestConsulCatalogSuite(t *testing.T) {
|
||||
suite.Run(t, new(ConsulCatalogSuite))
|
||||
}
|
||||
|
||||
s.consulURL = "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
|
||||
func (s *ConsulCatalogSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("consul_catalog")
|
||||
s.composeUp()
|
||||
|
||||
s.consulURL = "http://" + net.JoinHostPort(s.getComposeServiceIP("consul"), "8500")
|
||||
|
||||
var err error
|
||||
s.consulClient, err = api.NewClient(&api.Config{
|
||||
Address: s.consulURL,
|
||||
})
|
||||
c.Check(err, check.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Wait for consul to elect itself leader
|
||||
err = s.waitToElectConsulLeader()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.consulAgentClient, err = api.NewClient(&api.Config{
|
||||
Address: "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "consul-agent"), "8500"),
|
||||
Address: "http://" + net.JoinHostPort(s.getComposeServiceIP("consul-agent"), "8500"),
|
||||
})
|
||||
c.Check(err, check.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
|
||||
|
@ -83,36 +94,36 @@ func (s *ConsulCatalogSuite) deregisterService(id string, onAgent bool) error {
|
|||
return client.Agent().ServiceDeregister(id)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings() {
|
||||
reg1 := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
Address: s.getComposeServiceIP("whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg3 := &api.AgentServiceRegistration{
|
||||
ID: "whoami3",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami3"),
|
||||
Address: s.getComposeServiceIP("whoami3"),
|
||||
}
|
||||
err = s.registerService(reg3, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
|
@ -120,23 +131,18 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
|||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami"
|
||||
|
||||
err = try.Request(req, 2*time.Second,
|
||||
try.StatusCodeIs(200),
|
||||
try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.StatusCodeIs(200),
|
||||
|
@ -145,18 +151,18 @@ func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings(c *c
|
|||
fmt.Sprintf(`"http://%s:80":"UP"`, reg2.Address),
|
||||
fmt.Sprintf(`"http://%s:80":"UP"`, reg3.Address),
|
||||
))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami3", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
||||
containerIP := s.getComposeServiceIP(c, "whoami1")
|
||||
func (s *ConsulCatalogSuite) TestByLabels() {
|
||||
containerIP := s.getComposeServiceIP("whoami1")
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
|
@ -171,7 +177,7 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
|||
Address: containerIP,
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
|
@ -179,23 +185,18 @@ func (s *ConsulCatalogSuite) TestByLabels(c *check.C) {
|
|||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2", "Hostname: whoami3"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfiguration() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -204,37 +205,32 @@ func (s *ConsulCatalogSuite) TestSimpleConfiguration(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami.consul.localhost"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -243,39 +239,34 @@ func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple_watch.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple_watch.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Tags: []string{"traefik.enable=true"},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami.consul.localhost"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
reg.Check = &api.AgentServiceCheck{
|
||||
CheckID: "some-ok-check",
|
||||
TCP: whoamiIP + ":80",
|
||||
|
@ -285,10 +276,10 @@ func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
|||
}
|
||||
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContainsOr("Hostname: whoami1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg.Check = &api.AgentServiceCheck{
|
||||
CheckID: "some-failing-check",
|
||||
|
@ -299,16 +290,16 @@ func (s *ConsulCatalogSuite) TestSimpleConfigurationWithWatch(c *check.C) {
|
|||
}
|
||||
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 5*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -317,8 +308,7 @@ func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
|
@ -328,25 +318,21 @@ func (s *ConsulCatalogSuite) TestRegisterServiceWithoutIP(c *check.C) {
|
|||
Address: "",
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/http/services", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("whoami@consulcatalog", "\"http://127.0.0.1:80\": \"UP\""))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestDefaultConsulService() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -355,37 +341,32 @@ func (s *ConsulCatalogSuite) TestDefaultConsulService(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami.consul.localhost"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -394,8 +375,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
reg := &api.AgentServiceRegistration{
|
||||
|
@ -407,32 +387,28 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithTCPLabels(c *check.C) {
|
|||
"traefik.tcp.Services.Super.Loadbalancer.server.port=8080",
|
||||
},
|
||||
Port: 8080,
|
||||
Address: s.getComposeServiceIP(c, "whoamitcp"),
|
||||
Address: s.getComposeServiceIP("whoamitcp"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`my.super.host`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
who, err := guessWho("127.0.0.1:8000", "my.super.host", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(who, checker.Contains, "whoamitcp")
|
||||
assert.Contains(s.T(), who, "whoamitcp")
|
||||
|
||||
err = s.deregisterService("whoamitcp", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithLabels() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -441,8 +417,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
reg1 := &api.AgentServiceRegistration{
|
||||
|
@ -452,11 +427,11 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
|||
"traefik.http.Routers.Super.Rule=Host(`my.super.host`)",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start another container by replacing a '.' by a '-'
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
|
@ -466,40 +441,36 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithLabels(c *check.C) {
|
|||
"traefik.http.Routers.SuperHost.Rule=Host(`my-super.host`)",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
Address: s.getComposeServiceIP("whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my-super.host"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami2"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -508,8 +479,7 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/default_not_exposed.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
tags := []string{
|
||||
|
@ -523,50 +493,46 @@ func (s *ConsulCatalogSuite) TestSameServiceIDOnDifferentConsulAgent(c *check.C)
|
|||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami",
|
||||
Name: "whoami",
|
||||
Tags: tags,
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami2"),
|
||||
Address: s.getComposeServiceIP("whoami2"),
|
||||
}
|
||||
err = s.registerService(reg2, true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami1", "Hostname: whoami2"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(200),
|
||||
try.BodyContainsOr(s.getComposeServiceIP(c, "whoami1"), s.getComposeServiceIP(c, "whoami2")))
|
||||
c.Assert(err, checker.IsNil)
|
||||
try.BodyContainsOr(s.getComposeServiceIP("whoami1"), s.getComposeServiceIP("whoami2")))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels() {
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
DefaultRule string
|
||||
|
@ -575,8 +541,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.consul.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
// Start a container with some tags
|
||||
reg := &api.AgentServiceRegistration{
|
||||
|
@ -586,32 +551,28 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithOneMissingLabels(c *check.C) {
|
|||
"traefik.random.value=my.super.host",
|
||||
},
|
||||
Port: 80,
|
||||
Address: s.getComposeServiceIP(c, "whoami1"),
|
||||
Address: s.getComposeServiceIP("whoami1"),
|
||||
}
|
||||
|
||||
err := s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
// TODO validate : run on 80
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.Request(req, 1500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck() {
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
tags := []string{
|
||||
"traefik.enable=true",
|
||||
"traefik.http.routers.router1.rule=Path(`/whoami`)",
|
||||
|
@ -635,7 +596,7 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
|||
}
|
||||
|
||||
err := s.registerService(reg1, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
|
@ -643,22 +604,17 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
|||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/simple.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoami2IP := s.getComposeServiceIP(c, "whoami2")
|
||||
whoami2IP := s.getComposeServiceIP("whoami2")
|
||||
reg2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami",
|
||||
|
@ -675,26 +631,26 @@ func (s *ConsulCatalogSuite) TestConsulServiceWithHealthCheck(c *check.C) {
|
|||
}
|
||||
|
||||
err = s.registerService(reg2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/whoami", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "whoami"
|
||||
|
||||
// TODO Need to wait for up to 10 seconds (for consul discovery or traefik to boot up ?)
|
||||
err = try.Request(req, 10*time.Second, try.StatusCodeIs(200), try.BodyContainsOr("Hostname: whoami2"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect() {
|
||||
// Wait for consul to fully initialize connect CA
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
connectIP := s.getComposeServiceIP("connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
|
@ -712,9 +668,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
|||
Address: connectIP,
|
||||
}
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
|
@ -727,40 +683,35 @@ func (s *ConsulCatalogSuite) TestConsulConnect(c *check.C) {
|
|||
Address: whoamiIP,
|
||||
}
|
||||
err = s.registerService(regWhoami, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/connect.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("uuid-api1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault() {
|
||||
// Wait for consul to fully initialize connect CA
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
connectIP := s.getComposeServiceIP("connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
|
@ -777,9 +728,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
|||
Address: connectIP,
|
||||
}
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami1",
|
||||
|
@ -792,9 +743,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
|||
Address: whoamiIP,
|
||||
}
|
||||
err = s.registerService(regWhoami, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoami2IP := s.getComposeServiceIP(c, "whoami2")
|
||||
whoami2IP := s.getComposeServiceIP("whoami2")
|
||||
regWhoami2 := &api.AgentServiceRegistration{
|
||||
ID: "whoami2",
|
||||
Name: "whoami2",
|
||||
|
@ -808,45 +759,40 @@ func (s *ConsulCatalogSuite) TestConsulConnect_ByDefault(c *check.C) {
|
|||
Address: whoami2IP,
|
||||
}
|
||||
err = s.registerService(regWhoami2, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect_by_default.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/connect_by_default.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami2", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("uuid-api1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami2", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
||||
func (s *ConsulCatalogSuite) TestConsulConnect_NotAware() {
|
||||
// Wait for consul to fully initialize connect CA
|
||||
err := s.waitForConnectCA()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
connectIP := s.getComposeServiceIP(c, "connect")
|
||||
connectIP := s.getComposeServiceIP("connect")
|
||||
reg := &api.AgentServiceRegistration{
|
||||
ID: "uuid-api1",
|
||||
Name: "uuid-api",
|
||||
|
@ -864,9 +810,9 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
|||
Address: connectIP,
|
||||
}
|
||||
err = s.registerService(reg, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
whoamiIP := s.getComposeServiceIP(c, "whoami1")
|
||||
whoamiIP := s.getComposeServiceIP("whoami1")
|
||||
regWhoami := &api.AgentServiceRegistration{
|
||||
ID: "whoami1",
|
||||
Name: "whoami",
|
||||
|
@ -879,30 +825,25 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware(c *check.C) {
|
|||
Address: whoamiIP,
|
||||
}
|
||||
err = s.registerService(regWhoami, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tempObjects := struct {
|
||||
ConsulAddress string
|
||||
}{
|
||||
ConsulAddress: s.consulURL,
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/consul_catalog/connect_not_aware.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul_catalog/connect_not_aware.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 10*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = s.deregisterService("uuid-api1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = s.deregisterService("whoami1", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -10,16 +10,17 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/consul"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Consul test suites.
|
||||
|
@ -29,18 +30,16 @@ type ConsulSuite struct {
|
|||
consulURL string
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) resetStore(c *check.C) {
|
||||
err := s.kvClient.DeleteTree(context.Background(), "traefik")
|
||||
if err != nil && !errors.Is(err, store.ErrKeyNotFound) {
|
||||
c.Fatal(err)
|
||||
}
|
||||
func TestConsulSuite(t *testing.T) {
|
||||
suite.Run(t, new(ConsulSuite))
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "consul")
|
||||
s.composeUp(c)
|
||||
func (s *ConsulSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("consul")
|
||||
s.composeUp()
|
||||
|
||||
consulAddr := net.JoinHostPort(s.getComposeServiceIP(c, "consul"), "8500")
|
||||
consulAddr := net.JoinHostPort(s.getComposeServiceIP("consul"), "8500")
|
||||
s.consulURL = fmt.Sprintf("http://%s", consulAddr)
|
||||
|
||||
kv, err := valkeyrie.NewStore(
|
||||
|
@ -51,21 +50,27 @@ func (s *ConsulSuite) setupStore(c *check.C) {
|
|||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store consul")
|
||||
}
|
||||
require.NoError(s.T(), err, "Cannot create store consul")
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for consul
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
func (s *ConsulSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
defer os.Remove(file)
|
||||
func (s *ConsulSuite) TearDownTest() {
|
||||
err := s.kvClient.DeleteTree(context.Background(), "traefik")
|
||||
if err != nil && !errors.Is(err, store.ErrKeyNotFound) {
|
||||
require.ErrorIs(s.T(), err, store.ErrKeyNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -115,39 +120,35 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@consul":`, `"compressor@consul":`, `"srvcA@consul":`, `"srvcB@consul":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-consul.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -159,33 +160,27 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err, text)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) assertWhoami(c *check.C, host string, expectedStatusCode int) {
|
||||
func (s *ConsulSuite) assertWhoami(host string, expectedStatusCode int) {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = host
|
||||
|
||||
resp, err := try.ResponseUntilStatusCode(req, 15*time.Second, expectedStatusCode)
|
||||
require.NoError(s.T(), err)
|
||||
resp.Body.Close()
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TestDeleteRootKey(c *check.C) {
|
||||
func (s *ConsulSuite) TestDeleteRootKey() {
|
||||
// This test case reproduce the issue: https://github.com/traefik/traefik/issues/8092
|
||||
s.setupStore(c)
|
||||
s.resetStore(c)
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
|
||||
ctx := context.Background()
|
||||
svcaddr := net.JoinHostPort(s.getComposeServiceIP(c, "whoami"), "80")
|
||||
svcaddr := net.JoinHostPort(s.getComposeServiceIP("whoami"), "80")
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -202,32 +197,28 @@ func (s *ConsulSuite) TestDeleteRootKey(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(ctx, k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"Router0@consul":`, `"Router1@consul":`, `"simplesvc0@consul":`, `"simplesvc1@consul":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
s.assertWhoami("kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami("kv2.localhost", http.StatusOK)
|
||||
|
||||
// delete router1
|
||||
err = s.kvClient.DeleteTree(ctx, "traefik/http/routers/Router1")
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
s.assertWhoami("kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami("kv2.localhost", http.StatusNotFound)
|
||||
|
||||
// delete simple services and router0
|
||||
err = s.kvClient.DeleteTree(ctx, "traefik")
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusNotFound)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
s.assertWhoami("kv1.localhost", http.StatusNotFound)
|
||||
s.assertWhoami("kv2.localhost", http.StatusNotFound)
|
||||
}
|
||||
|
|
|
@ -3,15 +3,16 @@ package integration
|
|||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
"github.com/traefik/traefik/v2/pkg/testhelpers"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Docker tests suite.
|
||||
|
@ -19,12 +20,21 @@ type DockerComposeSuite struct {
|
|||
BaseSuite
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "minimal")
|
||||
s.composeUp(c)
|
||||
func TestDockerComposeSuite(t *testing.T) {
|
||||
suite.Run(t, new(DockerComposeSuite))
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
||||
func (s *DockerComposeSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("minimal")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *DockerComposeSuite) TestComposeScale() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -32,45 +42,36 @@ func (s *DockerComposeSuite) TestComposeScale(c *check.C) {
|
|||
DockerHost: s.getDockerHost(),
|
||||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
file := s.adaptFile(c, "fixtures/docker/minimal.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/minimal.toml", tempObjects)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://127.0.0.1:8000/whoami", nil)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
_, err = try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
_, err := try.ResponseUntilStatusCode(req, 5*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
var rtconf api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&rtconf)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// check that we have only three routers (the one from this test + 2 unrelated internal ones)
|
||||
c.Assert(rtconf.Routers, checker.HasLen, 3)
|
||||
assert.Len(s.T(), rtconf.Routers, 3)
|
||||
|
||||
// check that we have only one service (not counting the internal ones) with n servers
|
||||
services := rtconf.Services
|
||||
c.Assert(services, checker.HasLen, 4)
|
||||
assert.Len(s.T(), services, 4)
|
||||
for name, service := range services {
|
||||
if strings.HasSuffix(name, "@internal") {
|
||||
continue
|
||||
}
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
c.Assert(name, checker.Equals, "whoami1-"+composeProject.Name+"@docker")
|
||||
c.Assert(service.LoadBalancer.Servers, checker.HasLen, 2)
|
||||
assert.Equal(s.T(), "service-mini@docker", name)
|
||||
assert.Len(s.T(), service.LoadBalancer.Servers, 2)
|
||||
// We could break here, but we don't just to keep us honest.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,15 @@ package integration
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Docker tests suite.
|
||||
|
@ -18,15 +18,24 @@ type DockerSuite struct {
|
|||
BaseSuite
|
||||
}
|
||||
|
||||
func (s *DockerSuite) SetUpTest(c *check.C) {
|
||||
s.createComposeProject(c, "docker")
|
||||
func TestDockerSuite(t *testing.T) {
|
||||
suite.Run(t, new(DockerSuite))
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TearDownTest(c *check.C) {
|
||||
s.composeDown(c)
|
||||
func (s *DockerSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("docker")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
||||
func (s *DockerSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TearDownTest() {
|
||||
s.composeStop("simple", "withtcplabels", "withlabels1", "withlabels2", "withonelabelmissing", "powpow")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestSimpleConfiguration() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -35,24 +44,18 @@ func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c)
|
||||
s.composeUp()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
|
||||
func (s *DockerSuite) TestDefaultDockerContainers() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -61,41 +64,30 @@ func (s *DockerSuite) TestDefaultDockerContainers(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "simple")
|
||||
s.composeUp("simple")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "simple.docker.localhost"
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
req.Host = fmt.Sprintf("simple-%s.docker.localhost", composeProject.Name)
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 3*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var version map[string]interface{}
|
||||
|
||||
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
|
||||
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
|
||||
assert.NoError(s.T(), json.Unmarshal(body, &version))
|
||||
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDockerContainersWithTCPLabels(c *check.C) {
|
||||
func (s *DockerSuite) TestDockerContainersWithTCPLabels() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -104,29 +96,23 @@ func (s *DockerSuite) TestDockerContainersWithTCPLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "withtcplabels")
|
||||
s.composeUp("withtcplabels")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`my.super.host`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`my.super.host`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
who, err := guessWho("127.0.0.1:8000", "my.super.host", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(who, checker.Contains, "my.super.host")
|
||||
assert.Contains(s.T(), who, "my.super.host")
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
|
||||
func (s *DockerSuite) TestDockerContainersWithLabels() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -135,44 +121,37 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "withlabels1", "withlabels2")
|
||||
s.composeUp("withlabels1", "withlabels2")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my-super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
_, err = try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
_, err = try.ResponseUntilStatusCode(req, 3*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 3*time.Second, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var version map[string]interface{}
|
||||
|
||||
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
|
||||
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
|
||||
assert.NoError(s.T(), json.Unmarshal(body, &version))
|
||||
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) {
|
||||
func (s *DockerSuite) TestDockerContainersWithOneMissingLabels() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -181,31 +160,23 @@ func (s *DockerSuite) TestDockerContainersWithOneMissingLabels(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "withonelabelmissing")
|
||||
s.composeUp("withonelabelmissing")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
// TODO validate : run on 80
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.Request(req, 1500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 3*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
|
||||
func (s *DockerSuite) TestRestartDockerContainers() {
|
||||
tempObjects := struct {
|
||||
DockerHost string
|
||||
DefaultRule string
|
||||
|
@ -214,46 +185,40 @@ func (s *DockerSuite) TestRestartDockerContainers(c *check.C) {
|
|||
DefaultRule: "Host(`{{ normalize .Name }}.docker.localhost`)",
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/docker/simple.toml", tempObjects)
|
||||
defer os.Remove(file)
|
||||
file := s.adaptFile("fixtures/docker/simple.toml", tempObjects)
|
||||
|
||||
s.composeUp(c, "powpow")
|
||||
s.composeUp("powpow")
|
||||
|
||||
// Start traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/version", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "my.super.host"
|
||||
|
||||
// TODO Need to wait than 500 milliseconds more (for swarm or traefik to boot up ?)
|
||||
resp, err := try.ResponseUntilStatusCode(req, 1500*time.Millisecond, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var version map[string]interface{}
|
||||
|
||||
c.Assert(json.Unmarshal(body, &version), checker.IsNil)
|
||||
c.Assert(version["Version"], checker.Equals, "swarm/1.0.0")
|
||||
assert.NoError(s.T(), json.Unmarshal(body, &version))
|
||||
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.composeStop(c, "powpow")
|
||||
s.composeStop("powpow")
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
|
||||
s.composeUp(c, "powpow")
|
||||
s.composeUp("powpow")
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("powpow"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ package integration
|
|||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// ErrorPagesSuite test suites.
|
||||
|
@ -18,83 +18,78 @@ type ErrorPagesSuite struct {
|
|||
BackendIP string
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "error_pages")
|
||||
s.composeUp(c)
|
||||
|
||||
s.ErrorPageIP = s.getComposeServiceIP(c, "nginx2")
|
||||
s.BackendIP = s.getComposeServiceIP(c, "nginx1")
|
||||
func TestErrorPagesSuite(t *testing.T) {
|
||||
suite.Run(t, new(ErrorPagesSuite))
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/error_pages/simple.toml", struct {
|
||||
func (s *ErrorPagesSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("error_pages")
|
||||
s.composeUp()
|
||||
|
||||
s.ErrorPageIP = s.getComposeServiceIP("nginx2")
|
||||
s.BackendIP = s.getComposeServiceIP("nginx1")
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/error_pages/simple.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{"http://" + s.BackendIP + ":80", s.ErrorPageIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.local"
|
||||
|
||||
err = try.Request(frontendReq, 2*time.Second, try.BodyContains("nginx"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestErrorPage(c *check.C) {
|
||||
func (s *ErrorPagesSuite) TestErrorPage() {
|
||||
// error.toml contains a mis-configuration of the backend host
|
||||
file := s.adaptFile(c, "fixtures/error_pages/error.toml", struct {
|
||||
file := s.adaptFile("fixtures/error_pages/error.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.BackendIP, s.ErrorPageIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.local"
|
||||
|
||||
err = try.Request(frontendReq, 2*time.Second, try.BodyContains("An error occurred."))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ErrorPagesSuite) TestErrorPageFlush(c *check.C) {
|
||||
func (s *ErrorPagesSuite) TestErrorPageFlush() {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Header().Add("Transfer-Encoding", "chunked")
|
||||
rw.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = rw.Write([]byte("KO"))
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/error_pages/simple.toml", struct {
|
||||
file := s.adaptFile("fixtures/error_pages/simple.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{srv.URL, s.ErrorPageIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.local"
|
||||
|
||||
err = try.Request(frontendReq, 2*time.Second,
|
||||
try.BodyContains("An error occurred."),
|
||||
try.HasHeaderValue("Content-Type", "text/html", true),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -8,16 +8,17 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/etcdv3"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// etcd test suites.
|
||||
|
@ -27,12 +28,18 @@ type EtcdSuite struct {
|
|||
etcdAddr string
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "etcd")
|
||||
s.composeUp(c)
|
||||
func TestEtcdSuite(t *testing.T) {
|
||||
suite.Run(t, new(EtcdSuite))
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("etcd")
|
||||
s.composeUp()
|
||||
|
||||
var err error
|
||||
s.etcdAddr = net.JoinHostPort(s.getComposeServiceIP(c, "etcd"), "2379")
|
||||
s.etcdAddr = net.JoinHostPort(s.getComposeServiceIP("etcd"), "2379")
|
||||
s.kvClient, err = valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
etcdv3.StoreName,
|
||||
|
@ -41,18 +48,19 @@ func (s *EtcdSuite) SetUpSuite(c *check.C) {
|
|||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store etcd")
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// wait for etcd
|
||||
err = try.Do(60*time.Second, try.KVExists(s.kvClient, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/etcd/simple.toml", struct{ EtcdAddress string }{s.etcdAddr})
|
||||
defer os.Remove(file)
|
||||
func (s *EtcdSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *EtcdSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/etcd/simple.toml", struct{ EtcdAddress string }{s.etcdAddr})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -102,39 +110,35 @@ func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@etcd":`, `"compressor@etcd":`, `"srvcA@etcd":`, `"srvcB@etcd":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-etcd.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -146,7 +150,6 @@ func (s *EtcdSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err, text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,61 +2,58 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// File tests suite.
|
||||
type FileSuite struct{ BaseSuite }
|
||||
|
||||
func (s *FileSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "file")
|
||||
s.composeUp(c)
|
||||
func TestFileSuite(t *testing.T) {
|
||||
suite.Run(t, new(FileSuite))
|
||||
}
|
||||
|
||||
func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/file/simple.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *FileSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("file")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *FileSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *FileSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/file/simple.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// #56 regression test, make sure it does not fail?
|
||||
func (s *FileSuite) TestSimpleConfigurationNoPanic(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/file/56-simple-panic.toml"))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *FileSuite) TestSimpleConfigurationNoPanic() {
|
||||
s.traefikCmd(withConfigFile("fixtures/file/56-simple-panic.toml"))
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *FileSuite) TestDirectoryConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/file/directory.toml"))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *FileSuite) TestDirectoryConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/file/directory.toml"))
|
||||
|
||||
// Expected a 404 as we did not configure anything at /test
|
||||
err = try.GetRequest("http://127.0.0.1:8000/test", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/test", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Expected a 502 as there is no backend server
|
||||
err = try.GetRequest("http://127.0.0.1:8000/test2", 1000*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
[entryPoints.trust]
|
||||
address = ":8000"
|
||||
[entryPoints.web.proxyProtocol]
|
||||
trustedIPs = ["{{.HaproxyIP}}"]
|
||||
[entryPoints.trust.proxyProtocol]
|
||||
trustedIPs = ["127.0.0.1"]
|
||||
[entryPoints.nottrust]
|
||||
address = ":9000"
|
||||
[entryPoints.nottrust.proxyProtocol]
|
||||
trustedIPs = ["1.2.3.4"]
|
||||
|
||||
[api]
|
||||
insecure = true
|
|
@ -1,32 +0,0 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
[entryPoints.web.proxyProtocol]
|
||||
trustedIPs = ["1.2.3.4"]
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
||||
## dynamic configuration ##
|
||||
|
||||
[http.routers]
|
||||
[http.routers.router1]
|
||||
service = "service1"
|
||||
rule = "Path(`/whoami`)"
|
||||
|
||||
[http.services]
|
||||
[http.services.service1]
|
||||
[http.services.service1.loadBalancer]
|
||||
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://{{.WhoamiIP}}"
|
|
@ -8,9 +8,11 @@ import (
|
|||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/helloworld"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
|
@ -29,16 +31,20 @@ const randCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567
|
|||
// GRPCSuite tests suite.
|
||||
type GRPCSuite struct{ BaseSuite }
|
||||
|
||||
func TestGRPCSuite(t *testing.T) {
|
||||
suite.Run(t, new(GRPCSuite))
|
||||
}
|
||||
|
||||
type myserver struct {
|
||||
stopStreamExample chan bool
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) SetUpSuite(c *check.C) {
|
||||
func (s *GRPCSuite) SetupSuite() {
|
||||
var err error
|
||||
LocalhostCert, err = os.ReadFile("./resources/tls/local.cert")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
LocalhostKey, err = os.ReadFile("./resources/tls/local.key")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *myserver) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
|
||||
|
@ -137,19 +143,18 @@ func callStreamExampleClientGRPC() (helloworld.Greeter_StreamExampleClient, func
|
|||
return t, closer, nil
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPC(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPC() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -159,79 +164,65 @@ func (s *GRPCSuite) TestGRPC(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCh2c(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCh2c() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := starth2cGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_h2c.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_h2c.toml", struct {
|
||||
GRPCServerPort string
|
||||
}{
|
||||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", false)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCh2cTermination(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCh2cTermination() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := starth2cGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_h2c_termination.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_h2c_termination.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -241,40 +232,33 @@ func (s *GRPCSuite) TestGRPCh2cTermination(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCInsecure(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCInsecure() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_insecure.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_insecure.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -284,44 +268,37 @@ func (s *GRPCSuite) TestGRPCInsecure(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCBuffer(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCBuffer() {
|
||||
stopStreamExample := make(chan bool)
|
||||
defer func() { stopStreamExample <- true }()
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{
|
||||
stopStreamExample: stopStreamExample,
|
||||
})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -331,27 +308,21 @@ func (s *GRPCSuite) TestGRPCBuffer(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
var client helloworld.Greeter_StreamExampleClient
|
||||
client, closer, err := callStreamExampleClientGRPC()
|
||||
defer func() { _ = closer() }()
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
received := make(chan bool)
|
||||
go func() {
|
||||
tr, err := client.Recv()
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(len(tr.GetData()), check.Equals, 512)
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Len(s.T(), tr.GetData(), 512)
|
||||
received <- true
|
||||
}()
|
||||
|
||||
|
@ -363,25 +334,24 @@ func (s *GRPCSuite) TestGRPCBuffer(c *check.C) {
|
|||
return errors.New("failed to receive stream data")
|
||||
}
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCBufferWithFlushInterval() {
|
||||
stopStreamExample := make(chan bool)
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{
|
||||
stopStreamExample: stopStreamExample,
|
||||
})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -390,17 +360,11 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
|||
KeyContent: string(LocalhostKey),
|
||||
GRPCServerPort: port,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var client helloworld.Greeter_StreamExampleClient
|
||||
client, closer, err := callStreamExampleClientGRPC()
|
||||
|
@ -408,13 +372,13 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
|||
_ = closer()
|
||||
stopStreamExample <- true
|
||||
}()
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
received := make(chan bool)
|
||||
go func() {
|
||||
tr, err := client.Recv()
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(len(tr.GetData()), check.Equals, 512)
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Len(s.T(), tr.GetData(), 512)
|
||||
received <- true
|
||||
}()
|
||||
|
||||
|
@ -426,22 +390,21 @@ func (s *GRPCSuite) TestGRPCBufferWithFlushInterval(c *check.C) {
|
|||
return errors.New("failed to receive stream data")
|
||||
}
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *GRPCSuite) TestGRPCWithRetry(c *check.C) {
|
||||
func (s *GRPCSuite) TestGRPCWithRetry() {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
_, port, err := net.SplitHostPort(lis.Addr().String())
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
go func() {
|
||||
err := startGRPCServer(lis, &myserver{})
|
||||
c.Log(err)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
}()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/grpc/config_retry.toml", struct {
|
||||
file := s.adaptFile("fixtures/grpc/config_retry.toml", struct {
|
||||
CertContent string
|
||||
KeyContent string
|
||||
GRPCServerPort string
|
||||
|
@ -451,23 +414,17 @@ func (s *GRPCSuite) TestGRPCWithRetry(c *check.C) {
|
|||
GRPCServerPort: port,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err = cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`127.0.0.1`)"))
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
var response string
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
response, err = callHelloClientGRPC("World", true)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(response, check.Equals, "Hello World")
|
||||
assert.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "Hello World", response)
|
||||
}
|
||||
|
|
|
@ -4,50 +4,45 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Headers tests suite.
|
||||
type HeadersSuite struct{ BaseSuite }
|
||||
|
||||
func (s *HeadersSuite) TestSimpleConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/headers/basic.toml"))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
func TestHeadersSuite(t *testing.T) {
|
||||
suite.Run(t, new(HeadersSuite))
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestReverseProxyHeaderRemoved(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/remove_reverseproxy_headers.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
func (s *HeadersSuite) TestSimpleConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/headers/basic.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
// Expected a 404 as we did not configure anything
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestReverseProxyHeaderRemoved() {
|
||||
file := s.adaptFile("fixtures/headers/remove_reverseproxy_headers.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, found := r.Header["X-Forwarded-Host"]
|
||||
c.Assert(found, checker.True)
|
||||
assert.True(s.T(), found)
|
||||
_, found = r.Header["Foo"]
|
||||
c.Assert(found, checker.False)
|
||||
assert.False(s.T(), found)
|
||||
_, found = r.Header["X-Forwarded-For"]
|
||||
c.Assert(found, checker.False)
|
||||
assert.False(s.T(), found)
|
||||
})
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:9000")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
ts := &httptest.Server{
|
||||
Listener: listener,
|
||||
|
@ -57,31 +52,25 @@ func (s *HeadersSuite) TestReverseProxyHeaderRemoved(c *check.C) {
|
|||
defer ts.Close()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "test.localhost"
|
||||
req.Header = http.Header{
|
||||
"Foo": {"bar"},
|
||||
}
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestCorsResponses(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/cors.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HeadersSuite) TestCorsResponses() {
|
||||
file := s.adaptFile("fixtures/headers/cors.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
backend := startTestServer("9000", http.StatusOK, "")
|
||||
defer backend.Close()
|
||||
|
||||
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -147,30 +136,24 @@ func (s *HeadersSuite) TestCorsResponses(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(test.method, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.reqHost
|
||||
req.Header = test.requestHeaders
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestSecureHeadersResponses(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/secure.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HeadersSuite) TestSecureHeadersResponses() {
|
||||
file := s.adaptFile("fixtures/headers/secure.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
backend := startTestServer("9000", http.StatusOK, "")
|
||||
defer backend.Close()
|
||||
|
||||
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -190,36 +173,30 @@ func (s *HeadersSuite) TestSecureHeadersResponses(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.reqHost
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/api/rawdata", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.internalReqHost
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestMultipleSecureHeadersResponses(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/secure_multiple.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HeadersSuite) TestMultipleSecureHeadersResponses() {
|
||||
file := s.adaptFile("fixtures/headers/secure_multiple.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
backend := startTestServer("9000", http.StatusOK, "")
|
||||
defer backend.Close()
|
||||
|
||||
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -238,10 +215,10 @@ func (s *HeadersSuite) TestMultipleSecureHeadersResponses(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.reqHost
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.HasHeaderStruct(test.expected))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// HealthCheck test suites.
|
||||
|
@ -23,287 +25,272 @@ type HealthCheckSuite struct {
|
|||
whoami4IP string
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "healthcheck")
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoami1IP = s.getComposeServiceIP(c, "whoami1")
|
||||
s.whoami2IP = s.getComposeServiceIP(c, "whoami2")
|
||||
s.whoami3IP = s.getComposeServiceIP(c, "whoami3")
|
||||
s.whoami4IP = s.getComposeServiceIP(c, "whoami4")
|
||||
func TestHealthCheckSuite(t *testing.T) {
|
||||
suite.Run(t, new(HealthCheckSuite))
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/simple.toml", struct {
|
||||
func (s *HealthCheckSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("healthcheck")
|
||||
s.composeUp()
|
||||
|
||||
s.whoami1IP = s.getComposeServiceIP("whoami1")
|
||||
s.whoami2IP = s.getComposeServiceIP("whoami2")
|
||||
s.whoami3IP = s.getComposeServiceIP("whoami3")
|
||||
s.whoami4IP = s.getComposeServiceIP("whoami4")
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/healthcheck/simple.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontendHealthReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Fix all whoami health to 500
|
||||
client := &http.Client{}
|
||||
whoamiHosts := []string{s.whoami1IP, s.whoami2IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Change one whoami health to 200
|
||||
statusOKReq1, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify frontend health : after
|
||||
err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontendReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendReq.Host = "test.localhost"
|
||||
|
||||
// Check if whoami1 responds
|
||||
err = try.Request(frontendReq, 500*time.Millisecond, try.BodyContains(s.whoami1IP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check if the service with bad health check (whoami2) never respond.
|
||||
err = try.Request(frontendReq, 2*time.Second, try.BodyContains(s.whoami2IP))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1:8000/")
|
||||
|
||||
// Expected a 404 as we did not configure anything
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusNotFound, resp.StatusCode)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestMultipleEntrypoints(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/multiple-entrypoints.toml", struct {
|
||||
func (s *HealthCheckSuite) TestMultipleEntrypoints() {
|
||||
file := s.adaptFile("fixtures/healthcheck/multiple-entrypoints.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for traefik
|
||||
err = try.GetRequest("http://localhost:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check entrypoint http1
|
||||
frontendHealthReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(frontendHealthReq, 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check entrypoint http2
|
||||
frontendHealthReq, err = http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(frontendHealthReq, 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set the both whoami health to 500
|
||||
client := &http.Client{}
|
||||
whoamiHosts := []string{s.whoami1IP, s.whoami2IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(frontendHealthReq, 5*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// reactivate the whoami2
|
||||
statusInternalServerOkReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami2IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerOkReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontend1Req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontend1Req.Host = "test.localhost"
|
||||
|
||||
frontend2Req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontend2Req.Host = "test.localhost"
|
||||
|
||||
// Check if whoami1 never responds
|
||||
err = try.Request(frontend2Req, 2*time.Second, try.BodyContains(s.whoami1IP))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
|
||||
// Check if whoami1 never responds
|
||||
err = try.Request(frontend1Req, 2*time.Second, try.BodyContains(s.whoami1IP))
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Error(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPortOverload(c *check.C) {
|
||||
func (s *HealthCheckSuite) TestPortOverload() {
|
||||
// Set one whoami health to 200
|
||||
client := &http.Client{}
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/port_overload.toml", struct {
|
||||
file := s.adaptFile("fixtures/healthcheck/port_overload.toml", struct {
|
||||
Server1 string
|
||||
}{s.whoami1IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
frontendHealthReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
frontendHealthReq.Host = "test.localhost"
|
||||
|
||||
// We test bad gateway because we use an invalid port for the backend
|
||||
err = try.Request(frontendHealthReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set one whoami health to 500
|
||||
statusInternalServerErrorReq, err = http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(frontendHealthReq, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// Checks if all the loadbalancers created will correctly update the server status.
|
||||
func (s *HealthCheckSuite) TestMultipleRoutersOnSameService(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/multiple-routers-one-same-service.toml", struct {
|
||||
func (s *HealthCheckSuite) TestMultipleRoutersOnSameService() {
|
||||
file := s.adaptFile("fixtures/healthcheck/multiple-routers-one-same-service.toml", struct {
|
||||
Server1 string
|
||||
}{s.whoami1IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`test.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set whoami health to 200 to be sure to start with the wanted status
|
||||
client := &http.Client{}
|
||||
statusOkReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOkReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// check healthcheck on web1 entrypoint
|
||||
healthReqWeb1, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
healthReqWeb1.Host = "test.localhost"
|
||||
err = try.Request(healthReqWeb1, 1*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// check healthcheck on web2 entrypoint
|
||||
healthReqWeb2, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:9000/health", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
healthReqWeb2.Host = "test.localhost"
|
||||
|
||||
err = try.Request(healthReqWeb2, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Set whoami health to 500
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify no backend service is available due to failing health checks
|
||||
err = try.Request(healthReqWeb1, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(healthReqWeb2, 3*time.Second, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Change one whoami health to 200
|
||||
statusOKReq1, err := http.NewRequest(http.MethodPost, "http://"+s.whoami1IP+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify health check
|
||||
err = try.Request(healthReqWeb1, 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(healthReqWeb2, 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/propagate.toml", struct {
|
||||
func (s *HealthCheckSuite) TestPropagate() {
|
||||
file := s.adaptFile("fixtures/healthcheck/propagate.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
Server3 string
|
||||
Server4 string
|
||||
}{s.whoami1IP, s.whoami2IP, s.whoami3IP, s.whoami4IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
rootReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rootReq.Host = "root.localhost"
|
||||
|
||||
err = try.Request(rootReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Bring whoami1 and whoami3 down
|
||||
client := http.Client{
|
||||
|
@ -313,9 +300,9 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
whoamiHosts := []string{s.whoami1IP, s.whoami3IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
try.Sleep(time.Second)
|
||||
|
@ -327,19 +314,19 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
reachedServers := make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if reachedServers[s.whoami4IP] > reachedServers[s.whoami2IP] {
|
||||
c.Assert(string(body), checker.Contains, want2)
|
||||
assert.Contains(s.T(), string(body), want2)
|
||||
reachedServers[s.whoami2IP]++
|
||||
continue
|
||||
}
|
||||
|
||||
if reachedServers[s.whoami2IP] > reachedServers[s.whoami4IP] {
|
||||
c.Assert(string(body), checker.Contains, want4)
|
||||
assert.Contains(s.T(), string(body), want4)
|
||||
reachedServers[s.whoami4IP]++
|
||||
continue
|
||||
}
|
||||
|
@ -356,48 +343,48 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 2)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 2)
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami4IP])
|
||||
|
||||
fooReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
fooReq.Host = "foo.localhost"
|
||||
|
||||
// Verify load-balancing on foo still works, and that we're getting wsp2, wsp2, wsp2, wsp2, etc.
|
||||
want := `IP: ` + s.whoami2IP
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(fooReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(string(body), checker.Contains, want)
|
||||
assert.Contains(s.T(), string(body), want)
|
||||
}
|
||||
|
||||
barReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
barReq.Host = "bar.localhost"
|
||||
|
||||
// Verify load-balancing on bar still works, and that we're getting wsp2, wsp2, wsp2, wsp2, etc.
|
||||
want = `IP: ` + s.whoami2IP
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(barReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(string(body), checker.Contains, want)
|
||||
assert.Contains(s.T(), string(body), want)
|
||||
}
|
||||
|
||||
// Bring whoami2 and whoami4 down
|
||||
whoamiHosts = []string{s.whoami2IP, s.whoami4IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusInternalServerErrorReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusInternalServerErrorReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
try.Sleep(time.Second)
|
||||
|
@ -405,25 +392,25 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
// Verify that everything is down, and that we get 503s everywhere.
|
||||
for i := 0; i < 2; i++ {
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusServiceUnavailable)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusServiceUnavailable, resp.StatusCode)
|
||||
|
||||
resp, err = client.Do(fooReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusServiceUnavailable)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusServiceUnavailable, resp.StatusCode)
|
||||
|
||||
resp, err = client.Do(barReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusServiceUnavailable)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusServiceUnavailable, resp.StatusCode)
|
||||
}
|
||||
|
||||
// Bring everything back up.
|
||||
whoamiHosts = []string{s.whoami1IP, s.whoami2IP, s.whoami3IP, s.whoami4IP}
|
||||
for _, whoami := range whoamiHosts {
|
||||
statusOKReq, err := http.NewRequest(http.MethodPost, "http://"+whoami+"/health", bytes.NewBufferString("200"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
try.Sleep(time.Second)
|
||||
|
@ -432,10 +419,10 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
reachedServers = make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if strings.Contains(string(body), `IP: `+s.whoami1IP) {
|
||||
reachedServers[s.whoami1IP]++
|
||||
|
@ -458,19 +445,19 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami1IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami3IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 1)
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami1IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami3IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami4IP])
|
||||
|
||||
// Verify everything is up on foo router.
|
||||
reachedServers = make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(fooReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if strings.Contains(string(body), `IP: `+s.whoami1IP) {
|
||||
reachedServers[s.whoami1IP]++
|
||||
|
@ -493,19 +480,19 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami1IP], checker.Equals, 2)
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami3IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 0)
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami1IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami3IP])
|
||||
assert.Equal(s.T(), 0, reachedServers[s.whoami4IP])
|
||||
|
||||
// Verify everything is up on bar router.
|
||||
reachedServers = make(map[string]int)
|
||||
for i := 0; i < 4; i++ {
|
||||
resp, err := client.Do(barReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if strings.Contains(string(body), `IP: `+s.whoami1IP) {
|
||||
reachedServers[s.whoami1IP]++
|
||||
|
@ -528,102 +515,87 @@ func (s *HealthCheckSuite) TestPropagate(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
c.Assert(reachedServers[s.whoami1IP], checker.Equals, 2)
|
||||
c.Assert(reachedServers[s.whoami2IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami3IP], checker.Equals, 1)
|
||||
c.Assert(reachedServers[s.whoami4IP], checker.Equals, 0)
|
||||
assert.Equal(s.T(), 2, reachedServers[s.whoami1IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami2IP])
|
||||
assert.Equal(s.T(), 1, reachedServers[s.whoami3IP])
|
||||
assert.Equal(s.T(), 0, reachedServers[s.whoami4IP])
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPropagateNoHealthCheck(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/healthcheck/propagate_no_healthcheck.toml", struct {
|
||||
func (s *HealthCheckSuite) TestPropagateNoHealthCheck() {
|
||||
file := s.adaptFile("fixtures/healthcheck/propagate_no_healthcheck.toml", struct {
|
||||
Server1 string
|
||||
}{s.whoami1IP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`noop.localhost`)"), try.BodyNotContains("Host(`root.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`noop.localhost`)"), try.BodyNotContains("Host(`root.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
rootReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rootReq.Host = "root.localhost"
|
||||
|
||||
err = try.Request(rootReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *HealthCheckSuite) TestPropagateReload(c *check.C) {
|
||||
func (s *HealthCheckSuite) TestPropagateReload() {
|
||||
// Setup a WSP service without the healthcheck enabled (wsp-service1)
|
||||
withoutHealthCheck := s.adaptFile(c, "fixtures/healthcheck/reload_without_healthcheck.toml", struct {
|
||||
withoutHealthCheck := s.adaptFile("fixtures/healthcheck/reload_without_healthcheck.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(withoutHealthCheck)
|
||||
withHealthCheck := s.adaptFile(c, "fixtures/healthcheck/reload_with_healthcheck.toml", struct {
|
||||
withHealthCheck := s.adaptFile("fixtures/healthcheck/reload_with_healthcheck.toml", struct {
|
||||
Server1 string
|
||||
Server2 string
|
||||
}{s.whoami1IP, s.whoami2IP})
|
||||
defer os.Remove(withHealthCheck)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(withoutHealthCheck))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(withoutHealthCheck))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Host(`root.localhost`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Allow one of the underlying services on it to fail all servers HC (whoami2)
|
||||
client := http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
statusOKReq, err := http.NewRequest(http.MethodPost, "http://"+s.whoami2IP+"/health", bytes.NewBufferString("500"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = client.Do(statusOKReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
rootReq, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rootReq.Host = "root.localhost"
|
||||
|
||||
// Check the failed service (whoami2) is getting requests, but answer 500
|
||||
err = try.Request(rootReq, 500*time.Millisecond, try.StatusCodeIs(http.StatusServiceUnavailable))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Enable the healthcheck on the root WSP (wsp-service1) and let Traefik reload the config
|
||||
fr1, err := os.OpenFile(withoutHealthCheck, os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
c.Assert(fr1, checker.NotNil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
assert.NotNil(s.T(), fr1)
|
||||
require.NoError(s.T(), err)
|
||||
err = fr1.Truncate(0)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
fr2, err := os.ReadFile(withHealthCheck)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = fmt.Fprint(fr1, string(fr2))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = fr1.Close()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
try.Sleep(1 * time.Second)
|
||||
// Waiting for the reflected change.
|
||||
err = try.Request(rootReq, 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check the failed service (whoami2) is not getting requests
|
||||
wantIPs := []string{s.whoami1IP, s.whoami1IP, s.whoami1IP, s.whoami1IP}
|
||||
for _, ip := range wantIPs {
|
||||
want := "IP: " + ip
|
||||
resp, err := client.Do(rootReq)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
c.Assert(string(body), checker.Contains, want)
|
||||
err = try.Request(rootReq, 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("IP: "+ip))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,33 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type HostResolverSuite struct{ BaseSuite }
|
||||
|
||||
func (s *HostResolverSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "hostresolver")
|
||||
s.composeUp(c)
|
||||
func TestHostResolverSuite(t *testing.T) {
|
||||
suite.Run(t, new(HostResolverSuite))
|
||||
}
|
||||
|
||||
func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/simple_hostresolver.toml"))
|
||||
defer display(c)
|
||||
func (s *HostResolverSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("hostresolver")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *HostResolverSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *HostResolverSuite) TestSimpleConfig() {
|
||||
s.traefikCmd(withConfigFile("fixtures/simple_hostresolver.toml"))
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -43,10 +49,10 @@ func (s *HostResolverSuite) TestSimpleConfig(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.host
|
||||
|
||||
err = try.Request(req, 1*time.Second, try.StatusCodeIs(test.status), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.Request(req, 5*time.Second, try.StatusCodeIs(test.status), try.HasBody())
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,28 +5,27 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type HTTPSuite struct{ BaseSuite }
|
||||
|
||||
func (s *HTTPSuite) TestSimpleConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/http/simple.toml"))
|
||||
defer display(c)
|
||||
func TestHTTPSuite(t *testing.T) {
|
||||
suite.Run(t, new(HTTPSuite))
|
||||
}
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
defer s.killCmd(cmd)
|
||||
func (s *HTTPSuite) TestSimpleConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/http/simple.toml"))
|
||||
|
||||
// Expect a 404 as we configured nothing.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Provide a configuration, fetched by Traefik provider.
|
||||
configuration := &dynamic.Configuration{
|
||||
|
@ -55,14 +54,14 @@ func (s *HTTPSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
configData, err := json.Marshal(configuration)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
server := startTestServerWithResponse(configData)
|
||||
defer server.Close()
|
||||
|
||||
// Expect configuration to be applied.
|
||||
err = try.GetRequest("http://127.0.0.1:9090/api/rawdata", 3*time.Second, try.BodyContains("routerHTTP@http", "serviceHTTP@http", "http://bacon:80"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func startTestServerWithResponse(response []byte) (ts *httptest.Server) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,210 +9,325 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
stdlog "log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/context/docker"
|
||||
"github.com/docker/cli/cli/context/store"
|
||||
manifeststore "github.com/docker/cli/cli/manifest/store"
|
||||
registryclient "github.com/docker/cli/cli/registry/client"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
cmdcompose "github.com/docker/compose/v2/cmd/compose"
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
composeapi "github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
dockertypes "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
dockernetwork "github.com/docker/docker/api/types/network"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/go-check/check"
|
||||
notaryclient "github.com/theupdateframework/notary/client"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/network"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var (
|
||||
integration = flag.Bool("integration", false, "run integration tests")
|
||||
showLog = flag.Bool("tlog", false, "always show Traefik logs")
|
||||
)
|
||||
var showLog = flag.Bool("tlog", false, "always show Traefik logs")
|
||||
|
||||
func Test(t *testing.T) {
|
||||
if !*integration {
|
||||
log.WithoutContext().Info("Integration tests disabled.")
|
||||
return
|
||||
}
|
||||
type composeConfig struct {
|
||||
Services map[string]composeService `yaml:"services"`
|
||||
}
|
||||
|
||||
// TODO(mpl): very niche optimization: do not start tailscale if none of the
|
||||
// wanted tests actually need it (e.g. KeepAliveSuite does not).
|
||||
var (
|
||||
vpn *tailscaleNotSuite
|
||||
useVPN bool
|
||||
)
|
||||
if os.Getenv("IN_DOCKER") != "true" {
|
||||
if vpn = setupVPN(nil, "tailscale.secret"); vpn != nil {
|
||||
defer vpn.TearDownSuite(nil)
|
||||
useVPN = true
|
||||
}
|
||||
}
|
||||
type composeService struct {
|
||||
Image string `yaml:"image"`
|
||||
Labels map[string]string `yaml:"labels"`
|
||||
Hostname string `yaml:"hostname"`
|
||||
Volumes []string `yaml:"volumes"`
|
||||
CapAdd []string `yaml:"cap_add"`
|
||||
Command []string `yaml:"command"`
|
||||
Environment map[string]string `yaml:"environment"`
|
||||
Privileged bool `yaml:"privileged"`
|
||||
Deploy composeDeploy `yaml:"deploy"`
|
||||
}
|
||||
|
||||
check.Suite(&AccessLogSuite{})
|
||||
if !useVPN {
|
||||
check.Suite(&AcmeSuite{})
|
||||
}
|
||||
check.Suite(&ConsulCatalogSuite{})
|
||||
check.Suite(&ConsulSuite{})
|
||||
check.Suite(&DockerComposeSuite{})
|
||||
check.Suite(&DockerSuite{})
|
||||
check.Suite(&ErrorPagesSuite{})
|
||||
check.Suite(&EtcdSuite{})
|
||||
check.Suite(&FileSuite{})
|
||||
check.Suite(&GRPCSuite{})
|
||||
check.Suite(&HeadersSuite{})
|
||||
check.Suite(&HealthCheckSuite{})
|
||||
check.Suite(&HostResolverSuite{})
|
||||
check.Suite(&HTTPSSuite{})
|
||||
check.Suite(&HTTPSuite{})
|
||||
if !useVPN {
|
||||
check.Suite(&K8sSuite{})
|
||||
}
|
||||
check.Suite(&KeepAliveSuite{})
|
||||
check.Suite(&LogRotationSuite{})
|
||||
check.Suite(&MarathonSuite{})
|
||||
check.Suite(&MarathonSuite15{})
|
||||
if !useVPN {
|
||||
check.Suite(&ProxyProtocolSuite{})
|
||||
}
|
||||
check.Suite(&RateLimitSuite{})
|
||||
check.Suite(&RedisSuite{})
|
||||
check.Suite(&RestSuite{})
|
||||
check.Suite(&RetrySuite{})
|
||||
check.Suite(&SimpleSuite{})
|
||||
check.Suite(&TCPSuite{})
|
||||
check.Suite(&TimeoutSuite{})
|
||||
check.Suite(&ThrottlingSuite{})
|
||||
check.Suite(&TLSClientHeadersSuite{})
|
||||
check.Suite(&TracingSuite{})
|
||||
check.Suite(&UDPSuite{})
|
||||
check.Suite(&WebsocketSuite{})
|
||||
check.Suite(&ZookeeperSuite{})
|
||||
|
||||
check.TestingT(t)
|
||||
type composeDeploy struct {
|
||||
Replicas int `yaml:"replicas"`
|
||||
}
|
||||
|
||||
var traefikBinary = "../dist/traefik"
|
||||
|
||||
type BaseSuite struct {
|
||||
composeProjectOptions *cmdcompose.ProjectOptions
|
||||
dockerComposeService composeapi.Service
|
||||
dockerClient *client.Client
|
||||
suite.Suite
|
||||
containers map[string]testcontainers.Container
|
||||
network *testcontainers.DockerNetwork
|
||||
hostIP string
|
||||
}
|
||||
|
||||
func (s *BaseSuite) TearDownSuite(c *check.C) {
|
||||
if s.composeProjectOptions != nil && s.dockerComposeService != nil {
|
||||
s.composeDown(c)
|
||||
func (s *BaseSuite) waitForTraefik(containerName string) {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayTraefikLogFile(path string) {
|
||||
if s.T().Failed() {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
content, errRead := os.ReadFile(path)
|
||||
// TODO TestName
|
||||
// fmt.Printf("%s: Traefik logs: \n", c.TestName())
|
||||
fmt.Print("Traefik logs: \n")
|
||||
if errRead == nil {
|
||||
fmt.Println(content)
|
||||
} else {
|
||||
fmt.Println(errRead)
|
||||
}
|
||||
} else {
|
||||
// fmt.Printf("%s: No Traefik logs.\n", c.TestName())
|
||||
fmt.Print("No Traefik logs.\n")
|
||||
}
|
||||
errRemove := os.Remove(path)
|
||||
if errRemove != nil {
|
||||
fmt.Println(errRemove)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BaseSuite) SetupSuite() {
|
||||
// configure default standard log.
|
||||
stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags)
|
||||
// TODO
|
||||
// stdlog.SetOutput(log.Logger)
|
||||
|
||||
ctx := context.Background()
|
||||
// Create docker network
|
||||
// docker network create traefik-test-network --driver bridge --subnet 172.31.42.0/24
|
||||
var opts []network.NetworkCustomizer
|
||||
opts = append(opts, network.WithDriver("bridge"))
|
||||
opts = append(opts, network.WithIPAM(&dockernetwork.IPAM{
|
||||
Driver: "default",
|
||||
Config: []dockernetwork.IPAMConfig{
|
||||
{
|
||||
Subnet: "172.31.42.0/24",
|
||||
},
|
||||
},
|
||||
}))
|
||||
dockerNetwork, err := network.New(ctx, opts...)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.network = dockerNetwork
|
||||
s.hostIP = "172.31.42.1"
|
||||
if isDockerDesktop(ctx, s.T()) {
|
||||
s.hostIP = getDockerDesktopHostIP(ctx, s.T())
|
||||
s.setupVPN("tailscale.secret")
|
||||
}
|
||||
}
|
||||
|
||||
func getDockerDesktopHostIP(ctx context.Context, t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: "alpine",
|
||||
HostConfigModifier: func(config *container.HostConfig) {
|
||||
config.AutoRemove = true
|
||||
},
|
||||
Cmd: []string{"getent", "hosts", "host.docker.internal"},
|
||||
}
|
||||
|
||||
con, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: req,
|
||||
Started: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
closer, err := con.Logs(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
all, err := io.ReadAll(closer)
|
||||
require.NoError(t, err)
|
||||
|
||||
ipRegex := regexp.MustCompile(`\b(?:\d{1,3}\.){3}\d{1,3}\b`)
|
||||
matches := ipRegex.FindAllString(string(all), -1)
|
||||
require.Len(t, matches, 1)
|
||||
|
||||
return matches[0]
|
||||
}
|
||||
|
||||
func isDockerDesktop(ctx context.Context, t *testing.T) bool {
|
||||
t.Helper()
|
||||
|
||||
cli, err := testcontainers.NewDockerClientWithOpts(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create docker client: %s", err)
|
||||
}
|
||||
|
||||
info, err := cli.Info(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get docker info: %s", err)
|
||||
}
|
||||
|
||||
return info.OperatingSystem == "Docker Desktop"
|
||||
}
|
||||
|
||||
func (s *BaseSuite) TearDownSuite() {
|
||||
s.composeDown()
|
||||
|
||||
err := try.Do(5*time.Second, func() error {
|
||||
if s.network != nil {
|
||||
err := s.network.Remove(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// createComposeProject creates the docker compose project stored as a field in the BaseSuite.
|
||||
// This method should be called before starting and/or stopping compose services.
|
||||
func (s *BaseSuite) createComposeProject(c *check.C, name string) {
|
||||
projectName := fmt.Sprintf("traefik-integration-test-%s", name)
|
||||
func (s *BaseSuite) createComposeProject(name string) {
|
||||
composeFile := fmt.Sprintf("resources/compose/%s.yml", name)
|
||||
|
||||
var err error
|
||||
s.dockerClient, err = client.NewClientWithOpts()
|
||||
c.Assert(err, checker.IsNil)
|
||||
file, err := os.ReadFile(composeFile)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
fakeCLI := &FakeDockerCLI{client: s.dockerClient}
|
||||
s.dockerComposeService = compose.NewComposeService(fakeCLI)
|
||||
var composeConfigData composeConfig
|
||||
err = yaml.Unmarshal(file, &composeConfigData)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.composeProjectOptions = &cmdcompose.ProjectOptions{
|
||||
ProjectDir: ".",
|
||||
ProjectName: projectName,
|
||||
ConfigPaths: []string{composeFile},
|
||||
if s.containers == nil {
|
||||
s.containers = map[string]testcontainers.Container{}
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
for id, containerConfig := range composeConfigData.Services {
|
||||
var mounts []mount.Mount
|
||||
for _, volume := range containerConfig.Volumes {
|
||||
split := strings.Split(volume, ":")
|
||||
if len(split) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(split[0], "./") {
|
||||
path, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.WithoutContext().Errorf("can't determine current directory: %v", err)
|
||||
continue
|
||||
}
|
||||
split[0] = strings.Replace(split[0], "./", path+"/", 1)
|
||||
}
|
||||
|
||||
abs, err := filepath.Abs(split[0])
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
mounts = append(mounts, mount.Mount{Source: abs, Target: split[1], Type: mount.TypeBind})
|
||||
}
|
||||
|
||||
if containerConfig.Deploy.Replicas > 0 {
|
||||
for i := 0; i < containerConfig.Deploy.Replicas; i++ {
|
||||
id = fmt.Sprintf("%s-%d", id, i+1)
|
||||
con, err := s.createContainer(ctx, containerConfig, id, mounts)
|
||||
require.NoError(s.T(), err)
|
||||
s.containers[id] = con
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
con, err := s.createContainer(ctx, containerConfig, id, mounts)
|
||||
require.NoError(s.T(), err)
|
||||
s.containers[id] = con
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BaseSuite) createContainer(ctx context.Context, containerConfig composeService, id string, mounts []mount.Mount) (testcontainers.Container, error) {
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: containerConfig.Image,
|
||||
Env: containerConfig.Environment,
|
||||
Cmd: containerConfig.Command,
|
||||
Labels: containerConfig.Labels,
|
||||
Name: id,
|
||||
Hostname: containerConfig.Hostname,
|
||||
Privileged: containerConfig.Privileged,
|
||||
Networks: []string{s.network.Name},
|
||||
HostConfigModifier: func(config *container.HostConfig) {
|
||||
if containerConfig.CapAdd != nil {
|
||||
config.CapAdd = containerConfig.CapAdd
|
||||
}
|
||||
if !isDockerDesktop(ctx, s.T()) {
|
||||
config.ExtraHosts = append(config.ExtraHosts, "host.docker.internal:"+s.hostIP)
|
||||
}
|
||||
config.Mounts = mounts
|
||||
},
|
||||
}
|
||||
con, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: req,
|
||||
Started: false,
|
||||
})
|
||||
|
||||
return con, err
|
||||
}
|
||||
|
||||
// composeUp starts the given services of the current docker compose project, if they are not already started.
|
||||
// Already running services are not affected (i.e. not stopped).
|
||||
func (s *BaseSuite) composeUp(c *check.C, services ...string) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// We use Create and Restart instead of Up, because the only option that actually works to control which containers
|
||||
// are started is within the RestartOptions.
|
||||
err = s.dockerComposeService.Create(context.Background(), composeProject, composeapi.CreateOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Restart(context.Background(), composeProject.Name, composeapi.RestartOptions{Services: services})
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
// composeExec runs the command in the given args in the given compose service container.
|
||||
// Already running services are not affected (i.e. not stopped).
|
||||
func (s *BaseSuite) composeExec(c *check.C, service string, args ...string) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
_, err = s.dockerComposeService.Exec(context.Background(), composeProject.Name, composeapi.RunOptions{
|
||||
Service: service,
|
||||
Command: args,
|
||||
Tty: false,
|
||||
Index: 1,
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *BaseSuite) composeUp(services ...string) {
|
||||
for name, con := range s.containers {
|
||||
if len(services) == 0 || slices.Contains(services, name) {
|
||||
err := con.Start(context.Background())
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// composeStop stops the given services of the current docker compose project and removes the corresponding containers.
|
||||
func (s *BaseSuite) composeStop(c *check.C, services ...string) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Stop(context.Background(), composeProject.Name, composeapi.StopOptions{Services: services})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Remove(context.Background(), composeProject.Name, composeapi.RemoveOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *BaseSuite) composeStop(services ...string) {
|
||||
for name, con := range s.containers {
|
||||
if len(services) == 0 || slices.Contains(services, name) {
|
||||
timeout := 10 * time.Second
|
||||
err := con.Stop(context.Background(), &timeout)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// composeDown stops all compose project services and removes the corresponding containers.
|
||||
func (s *BaseSuite) composeDown(c *check.C) {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Down(context.Background(), composeProject.Name, composeapi.DownOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *BaseSuite) composeDown() {
|
||||
for _, c := range s.containers {
|
||||
err := c.Terminate(context.Background())
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
s.containers = map[string]testcontainers.Container{}
|
||||
}
|
||||
|
||||
func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) {
|
||||
cmd := exec.Command(traefikBinary, args...)
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
s.killCmd(cmd)
|
||||
})
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &out
|
||||
|
||||
err := cmd.Start()
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
return cmd, &out
|
||||
}
|
||||
|
||||
func (s *BaseSuite) killCmd(cmd *exec.Cmd) {
|
||||
if cmd.Process == nil {
|
||||
log.WithoutContext().Error("No process to kill")
|
||||
return
|
||||
}
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
log.WithoutContext().Errorf("Kill: %v", err)
|
||||
|
@ -221,15 +336,18 @@ func (s *BaseSuite) killCmd(cmd *exec.Cmd) {
|
|||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
func (s *BaseSuite) traefikCmd(args ...string) (*exec.Cmd, func(*check.C)) {
|
||||
func (s *BaseSuite) traefikCmd(args ...string) *exec.Cmd {
|
||||
cmd, out := s.cmdTraefik(args...)
|
||||
return cmd, func(c *check.C) {
|
||||
if c.Failed() || *showLog {
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
if s.T().Failed() || *showLog {
|
||||
s.displayLogK3S()
|
||||
s.displayLogCompose(c)
|
||||
s.displayTraefikLog(c, out)
|
||||
s.displayLogCompose()
|
||||
s.displayTraefikLog(out)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayLogK3S() {
|
||||
|
@ -246,34 +364,33 @@ func (s *BaseSuite) displayLogK3S() {
|
|||
log.WithoutContext().Println()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayLogCompose(c *check.C) {
|
||||
if s.dockerComposeService == nil || s.composeProjectOptions == nil {
|
||||
log.WithoutContext().Infof("%s: No docker compose logs.", c.TestName())
|
||||
return
|
||||
func (s *BaseSuite) displayLogCompose() {
|
||||
for name, ctn := range s.containers {
|
||||
readCloser, err := ctn.Logs(context.Background())
|
||||
require.NoError(s.T(), err)
|
||||
for {
|
||||
b := make([]byte, 1024)
|
||||
_, err := readCloser.Read(b)
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
trimLogs := bytes.Trim(bytes.TrimSpace(b), string([]byte{0}))
|
||||
if len(trimLogs) > 0 {
|
||||
log.WithoutContext().WithField("container", name).Info(string(trimLogs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.WithoutContext().Infof("%s: docker compose logs: ", c.TestName())
|
||||
|
||||
logWriter := log.WithoutContext().WriterLevel(log.GetLevel())
|
||||
logConsumer := formatter.NewLogConsumer(context.Background(), logWriter, logWriter, false, true, true)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = s.dockerComposeService.Logs(context.Background(), composeProject.Name, logConsumer, composeapi.LogOptions{})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
log.WithoutContext().Println()
|
||||
log.WithoutContext().Println("################################")
|
||||
log.WithoutContext().Println()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) displayTraefikLog(c *check.C, output *bytes.Buffer) {
|
||||
func (s *BaseSuite) displayTraefikLog(output *bytes.Buffer) {
|
||||
if output == nil || output.Len() == 0 {
|
||||
log.WithoutContext().Infof("%s: No Traefik logs.", c.TestName())
|
||||
log.WithoutContext().Info("No Traefik logs.")
|
||||
} else {
|
||||
log.WithoutContext().Infof("%s: Traefik logs: ", c.TestName())
|
||||
log.WithoutContext().Infof(output.String())
|
||||
for _, line := range strings.Split(output.String(), "\n") {
|
||||
log.WithoutContext().Info(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,73 +404,47 @@ func (s *BaseSuite) getDockerHost() string {
|
|||
return dockerHost
|
||||
}
|
||||
|
||||
func (s *BaseSuite) adaptFile(c *check.C, path string, tempObjects interface{}) string {
|
||||
func (s *BaseSuite) adaptFile(path string, tempObjects interface{}) string {
|
||||
// Load file
|
||||
tmpl, err := template.ParseFiles(path)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
folder, prefix := filepath.Split(path)
|
||||
tmpFile, err := os.CreateTemp(folder, strings.TrimSuffix(prefix, filepath.Ext(prefix))+"_*"+filepath.Ext(prefix))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
defer tmpFile.Close()
|
||||
|
||||
model := structs.Map(tempObjects)
|
||||
model["SelfFilename"] = tmpFile.Name()
|
||||
|
||||
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = tmpFile.Sync()
|
||||
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
os.Remove(tmpFile.Name())
|
||||
})
|
||||
return tmpFile.Name()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) getComposeServiceIP(c *check.C, name string) string {
|
||||
c.Assert(s.composeProjectOptions, check.NotNil)
|
||||
c.Assert(s.dockerComposeService, check.NotNil)
|
||||
|
||||
composeProject, err := s.composeProjectOptions.ToProject(nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
filter := filters.NewArgs(
|
||||
filters.Arg("label", fmt.Sprintf("%s=%s", composeapi.ProjectLabel, composeProject.Name)),
|
||||
filters.Arg("label", fmt.Sprintf("%s=%s", composeapi.ServiceLabel, name)),
|
||||
)
|
||||
|
||||
containers, err := s.dockerClient.ContainerList(context.Background(), dockertypes.ContainerListOptions{Filters: filter})
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(containers, checker.HasLen, 1)
|
||||
|
||||
networkNames := composeProject.NetworkNames()
|
||||
c.Assert(networkNames, checker.HasLen, 1)
|
||||
|
||||
network := composeProject.Networks[networkNames[0]]
|
||||
return containers[0].NetworkSettings.Networks[network.Name].IPAddress
|
||||
}
|
||||
|
||||
func (s *BaseSuite) getContainerIP(c *check.C, name string) string {
|
||||
container, err := s.dockerClient.ContainerInspect(context.Background(), name)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(container.NetworkSettings.Networks, check.NotNil)
|
||||
|
||||
for _, network := range container.NetworkSettings.Networks {
|
||||
return network.IPAddress
|
||||
func (s *BaseSuite) getComposeServiceIP(name string) string {
|
||||
container, ok := s.containers[name]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Should never happen.
|
||||
c.Error("No network found")
|
||||
return ""
|
||||
ip, err := container.ContainerIP(context.Background())
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
func withConfigFile(file string) string {
|
||||
return "--configFile=" + file
|
||||
}
|
||||
|
||||
// tailscaleNotSuite includes a BaseSuite out of convenience, so we can benefit
|
||||
// from composeUp et co., but it is not meant to function as a TestSuite per se.
|
||||
type tailscaleNotSuite struct{ BaseSuite }
|
||||
|
||||
// setupVPN starts Tailscale on the corresponding container, and makes it a subnet
|
||||
// router, for all the other containers (whoamis, etc) subsequently started for the
|
||||
// integration tests.
|
||||
|
@ -369,101 +460,35 @@ type tailscaleNotSuite struct{ BaseSuite }
|
|||
// "172.0.0.0/8": ["your_tailscale_identity"],
|
||||
// },
|
||||
// },
|
||||
//
|
||||
// TODO(mpl): we could maybe even move this setup to the Makefile, to start it
|
||||
// and let it run (forever, or until voluntarily stopped).
|
||||
func setupVPN(c *check.C, keyFile string) *tailscaleNotSuite {
|
||||
func (s *BaseSuite) setupVPN(keyFile string) {
|
||||
data, err := os.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
log.Fatal(err)
|
||||
log.WithoutContext().Error(err)
|
||||
}
|
||||
return nil
|
||||
|
||||
return
|
||||
}
|
||||
authKey := strings.TrimSpace(string(data))
|
||||
// TODO: copy and create versions that don't need a check.C?
|
||||
vpn := &tailscaleNotSuite{}
|
||||
vpn.createComposeProject(c, "tailscale")
|
||||
vpn.composeUp(c)
|
||||
// // TODO: copy and create versions that don't need a check.C?
|
||||
s.createComposeProject("tailscale")
|
||||
s.composeUp()
|
||||
time.Sleep(5 * time.Second)
|
||||
// If we ever change the docker subnet in the Makefile,
|
||||
// we need to change this one below correspondingly.
|
||||
vpn.composeExec(c, "tailscaled", "tailscale", "up", "--authkey="+authKey, "--advertise-routes=172.31.42.0/24")
|
||||
return vpn
|
||||
s.composeExec("tailscaled", "tailscale", "up", "--authkey="+authKey, "--advertise-routes=172.31.42.0/24")
|
||||
}
|
||||
|
||||
type FakeDockerCLI struct {
|
||||
client client.APIClient
|
||||
}
|
||||
// composeExec runs the command in the given args in the given compose service container.
|
||||
// Already running services are not affected (i.e. not stopped).
|
||||
func (s *BaseSuite) composeExec(service string, args ...string) string {
|
||||
require.Contains(s.T(), s.containers, service)
|
||||
|
||||
func (f FakeDockerCLI) Client() client.APIClient {
|
||||
return f.client
|
||||
}
|
||||
_, reader, err := s.containers[service].Exec(context.Background(), args)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
func (f FakeDockerCLI) In() *streams.In {
|
||||
return streams.NewIn(os.Stdin)
|
||||
}
|
||||
content, err := io.ReadAll(reader)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
func (f FakeDockerCLI) Out() *streams.Out {
|
||||
return streams.NewOut(os.Stdout)
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) Err() io.Writer {
|
||||
return streams.NewOut(os.Stderr)
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) SetIn(in *streams.In) {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) Apply(ops ...command.DockerCliOption) error {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ConfigFile() *configfile.ConfigFile {
|
||||
return &configfile.ConfigFile{}
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ServerInfo() command.ServerInfo {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) DefaultVersion() string {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) CurrentVersion() string {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ManifestStore() manifeststore.Store {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) RegistryClient(b bool) registryclient.RegistryClient {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ContentTrustEnabled() bool {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) BuildKitEnabled() (bool, error) {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) ContextStore() store.Store {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) CurrentContext() string {
|
||||
panic("implement me if you need me")
|
||||
}
|
||||
|
||||
func (f FakeDockerCLI) DockerEndpoint() docker.Endpoint {
|
||||
panic("implement me if you need me")
|
||||
return string(content)
|
||||
}
|
||||
|
|
|
@ -7,18 +7,21 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
var updateExpected = flag.Bool("update_expected", false, "Update expected files in testdata")
|
||||
|
@ -26,25 +29,39 @@ var updateExpected = flag.Bool("update_expected", false, "Update expected files
|
|||
// K8sSuite tests suite.
|
||||
type K8sSuite struct{ BaseSuite }
|
||||
|
||||
func (s *K8sSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "k8s")
|
||||
s.composeUp(c)
|
||||
func TestK8sSuite(t *testing.T) {
|
||||
suite.Run(t, new(K8sSuite))
|
||||
}
|
||||
|
||||
func (s *K8sSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("k8s")
|
||||
s.composeUp()
|
||||
|
||||
abs, err := filepath.Abs("./fixtures/k8s/config.skip/kubeconfig.yaml")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.Do(60*time.Second, func() error {
|
||||
_, err := os.Stat(abs)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
data, err := os.ReadFile(abs)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
content := strings.ReplaceAll(string(data), "https://server:6443", fmt.Sprintf("https://%s", net.JoinHostPort(s.getComposeServiceIP("server"), "6443")))
|
||||
|
||||
err = os.WriteFile(abs, []byte(content), 0o644)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = os.Setenv("KUBECONFIG", abs)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TearDownSuite(c *check.C) {
|
||||
s.composeDown(c)
|
||||
func (s *K8sSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
generatedFiles := []string{
|
||||
"./fixtures/k8s/config.skip/kubeconfig.yaml",
|
||||
|
@ -62,109 +79,78 @@ func (s *K8sSuite) TearDownSuite(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestIngressConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_default.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestIngressConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_default.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-ingress.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-ingress.json", "8080")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestIngressLabelSelector(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_ingress_label_selector.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestIngressLabelSelector() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_ingress_label_selector.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-ingress-label-selector.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-ingress-label-selector.json", "8080")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestCRDConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_crd.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestCRDConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_crd.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-crd.json", "8000")
|
||||
s.testConfiguration("testdata/rawdata-crd.json", "8000")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestCRDLabelSelector(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_crd_label_selector.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestCRDLabelSelector() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_crd_label_selector.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-crd-label-selector.json", "8000")
|
||||
s.testConfiguration("testdata/rawdata-crd-label-selector.json", "8000")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestGatewayConfiguration(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_gateway.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestGatewayConfiguration() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_gateway.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-gateway.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-gateway.json", "8080")
|
||||
}
|
||||
|
||||
func (s *K8sSuite) TestIngressclass(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_ingressclass.toml"))
|
||||
defer display(c)
|
||||
func (s *K8sSuite) TestIngressclass() {
|
||||
s.traefikCmd(withConfigFile("fixtures/k8s_ingressclass.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
testConfiguration(c, "testdata/rawdata-ingressclass.json", "8080")
|
||||
s.testConfiguration("testdata/rawdata-ingressclass.json", "8080")
|
||||
}
|
||||
|
||||
func testConfiguration(c *check.C, path, apiPort string) {
|
||||
func (s *K8sSuite) testConfiguration(path, apiPort string) {
|
||||
err := try.GetRequest("http://127.0.0.1:"+apiPort+"/api/entrypoints", 20*time.Second, try.BodyContains(`"name":"web"`))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash(path)
|
||||
|
||||
if *updateExpected {
|
||||
fi, err := os.Create(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = fi.Close()
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = try.GetRequest("http://127.0.0.1:"+apiPort+"/api/rawdata", 1*time.Minute, try.StatusCodeIs(http.StatusOK), matchesConfig(expectedJSON, &buf))
|
||||
|
||||
if !*updateExpected {
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
}
|
||||
require.NoError(s.T(), err)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Logf("In file update mode, got expected error: %v", err)
|
||||
log.WithoutContext().Infof("In file update mode, got expected error: %v", err)
|
||||
}
|
||||
|
||||
var rtRepr api.RunTimeRepresentation
|
||||
err = json.Unmarshal(buf.Bytes(), &rtRepr)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
newJSON, err := json.MarshalIndent(rtRepr, "", "\t")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = os.WriteFile(expectedJSON, newJSON, 0o644)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Errorf("We do not want a passing test in file update mode")
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
s.T().Fatal("We do not want a passing test in file update mode")
|
||||
}
|
||||
|
||||
func matchesConfig(wantConfig string, buf *bytes.Buffer) try.ResponseCondition {
|
||||
|
|
|
@ -5,18 +5,23 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
type KeepAliveSuite struct {
|
||||
BaseSuite
|
||||
}
|
||||
|
||||
func TestKeepAliveSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeepAliveSuite))
|
||||
}
|
||||
|
||||
type KeepAliveConfig struct {
|
||||
KeepAliveServer string
|
||||
IdleConnTimeout string
|
||||
|
@ -27,7 +32,7 @@ type connStateChangeEvent struct {
|
|||
state http.ConnState
|
||||
}
|
||||
|
||||
func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime(c *check.C) {
|
||||
func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime() {
|
||||
idleTimeout := time.Duration(75) * time.Millisecond
|
||||
|
||||
connStateChanges := make(chan connStateChangeEvent)
|
||||
|
@ -59,18 +64,18 @@ func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime(c *
|
|||
case <-noMoreRequests:
|
||||
moreRequestsExpected = false
|
||||
case <-maxWaitTimeExceeded:
|
||||
c.Logf("timeout waiting for all connections to close, waited for %v, configured idle timeout was %v", maxWaitDuration, idleTimeout)
|
||||
c.Fail()
|
||||
log.WithoutContext().Infof("timeout waiting for all connections to close, waited for %v, configured idle timeout was %v", maxWaitDuration, idleTimeout)
|
||||
s.T().Fail()
|
||||
close(completed)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Check(connCount, checker.Equals, 1)
|
||||
require.Equal(s.T(), 1, connCount)
|
||||
|
||||
for _, idlePeriod := range idlePeriodLengthMap {
|
||||
// Our method of measuring the actual idle period is not precise, so allow some sub-ms deviation
|
||||
c.Check(math.Round(idlePeriod.Seconds()), checker.LessOrEqualThan, idleTimeout.Seconds())
|
||||
require.LessOrEqual(s.T(), math.Round(idlePeriod.Seconds()), idleTimeout.Seconds())
|
||||
}
|
||||
|
||||
close(completed)
|
||||
|
@ -87,22 +92,16 @@ func (s *KeepAliveSuite) TestShouldRespectConfiguredBackendHttpKeepAliveTime(c *
|
|||
defer server.Close()
|
||||
|
||||
config := KeepAliveConfig{KeepAliveServer: server.URL, IdleConnTimeout: idleTimeout.String()}
|
||||
file := s.adaptFile(c, "fixtures/timeout/keepalive.toml", config)
|
||||
file := s.adaptFile("fixtures/timeout/keepalive.toml", config)
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Check(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Duration(1)*time.Second, try.StatusCodeIs(200), try.BodyContains("PathPrefix(`/keepalive`)"))
|
||||
c.Check(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Duration(1)*time.Second, try.StatusCodeIs(200), try.BodyContains("PathPrefix(`/keepalive`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/keepalive", time.Duration(1)*time.Second, try.StatusCodeIs(200))
|
||||
c.Check(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
close(noMoreRequests)
|
||||
<-completed
|
||||
|
|
|
@ -9,12 +9,14 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -25,13 +27,23 @@ const (
|
|||
// Log rotation integration test suite.
|
||||
type LogRotationSuite struct{ BaseSuite }
|
||||
|
||||
func (s *LogRotationSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "access_log")
|
||||
s.composeUp(c)
|
||||
func TestLogRorationSuite(t *testing.T) {
|
||||
suite.Run(t, new(LogRotationSuite))
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TearDownSuite(c *check.C) {
|
||||
s.composeDown(c)
|
||||
func (s *LogRotationSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
os.Remove(traefikTestAccessLogFile)
|
||||
os.Remove(traefikTestLogFile)
|
||||
os.Remove(traefikTestAccessLogFileRotated)
|
||||
|
||||
s.createComposeProject("access_log")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
generatedFiles := []string{
|
||||
traefikTestLogFile,
|
||||
|
@ -47,126 +59,116 @@ func (s *LogRotationSuite) TearDownSuite(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
|
||||
func (s *LogRotationSuite) TestAccessLogRotation() {
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
defer displayTraefikLogFile(c, traefikTestLogFile)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
cmd, _ := s.cmdTraefik(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer s.displayTraefikLogFile(traefikTestLogFile)
|
||||
|
||||
// Verify Traefik started ok
|
||||
verifyEmptyErrorLog(c, "traefik.log")
|
||||
s.verifyEmptyErrorLog("traefik.log")
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
// Make some requests
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "frontend1.docker.local"
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Rename access log
|
||||
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFileRotated)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// in the midst of the requests, issue SIGUSR1 signal to server process
|
||||
err = cmd.Process.Signal(syscall.SIGUSR1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// continue issuing requests
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Verify access.log.rotated output as expected
|
||||
logAccessLogFile(c, traefikTestAccessLogFileRotated)
|
||||
lineCount := verifyLogLines(c, traefikTestAccessLogFileRotated, 0, true)
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 1)
|
||||
s.logAccessLogFile(traefikTestAccessLogFileRotated)
|
||||
lineCount := s.verifyLogLines(traefikTestAccessLogFileRotated, 0, true)
|
||||
assert.GreaterOrEqual(s.T(), lineCount, 1)
|
||||
|
||||
// make sure that the access log file is at least created before we do assertions on it
|
||||
err = try.Do(1*time.Second, func() error {
|
||||
_, err := os.Stat(traefikTestAccessLogFile)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, checker.IsNil, check.Commentf("access log file was not created in time"))
|
||||
assert.NoError(s.T(), err, "access log file was not created in time")
|
||||
|
||||
// Verify access.log output as expected
|
||||
logAccessLogFile(c, traefikTestAccessLogFile)
|
||||
lineCount = verifyLogLines(c, traefikTestAccessLogFile, lineCount, true)
|
||||
c.Assert(lineCount, checker.Equals, 3)
|
||||
s.logAccessLogFile(traefikTestAccessLogFile)
|
||||
lineCount = s.verifyLogLines(traefikTestAccessLogFile, lineCount, true)
|
||||
assert.Equal(s.T(), 3, lineCount)
|
||||
|
||||
verifyEmptyErrorLog(c, traefikTestLogFile)
|
||||
s.verifyEmptyErrorLog(traefikTestLogFile)
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
|
||||
func (s *LogRotationSuite) TestTraefikLogRotation() {
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/traefik_log_config.toml"))
|
||||
defer display(c)
|
||||
defer displayTraefikLogFile(c, traefikTestLogFile)
|
||||
cmd := s.traefikCmd(withConfigFile("fixtures/traefik_log_config.toml"))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
waitForTraefik(c, "server1")
|
||||
s.waitForTraefik("server1")
|
||||
|
||||
// Rename traefik log
|
||||
err = os.Rename(traefikTestLogFile, traefikTestLogFileRotated)
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := os.Rename(traefikTestLogFile, traefikTestLogFileRotated)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// issue SIGUSR1 signal to server process
|
||||
err = cmd.Process.Signal(syscall.SIGUSR1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = cmd.Process.Signal(syscall.SIGTERM)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Allow time for switch to be processed
|
||||
err = try.Do(3*time.Second, func() error {
|
||||
_, err = os.Stat(traefikTestLogFile)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// we have at least 6 lines in traefik.log.rotated
|
||||
lineCount := verifyLogLines(c, traefikTestLogFileRotated, 0, false)
|
||||
lineCount := s.verifyLogLines(traefikTestLogFileRotated, 0, false)
|
||||
|
||||
// GreaterOrEqualThan used to ensure test doesn't break
|
||||
// If more log entries are output on startup
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 5)
|
||||
assert.GreaterOrEqual(s.T(), lineCount, 5)
|
||||
|
||||
// Verify traefik.log output as expected
|
||||
lineCount = verifyLogLines(c, traefikTestLogFile, lineCount, false)
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 7)
|
||||
lineCount = s.verifyLogLines(traefikTestLogFile, lineCount, false)
|
||||
assert.GreaterOrEqual(s.T(), lineCount, 7)
|
||||
}
|
||||
|
||||
func logAccessLogFile(c *check.C, fileName string) {
|
||||
func (s *LogRotationSuite) logAccessLogFile(fileName string) {
|
||||
output, err := os.ReadFile(fileName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Logf("Contents of file %s\n%s", fileName, string(output))
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Infof("Contents of file %s\n%s", fileName, string(output))
|
||||
}
|
||||
|
||||
func verifyEmptyErrorLog(c *check.C, name string) {
|
||||
func (s *LogRotationSuite) verifyEmptyErrorLog(name string) {
|
||||
err := try.Do(5*time.Second, func() error {
|
||||
traefikLog, e2 := os.ReadFile(name)
|
||||
if e2 != nil {
|
||||
return e2
|
||||
}
|
||||
c.Assert(string(traefikLog), checker.HasLen, 0)
|
||||
assert.Empty(s.T(), string(traefikLog))
|
||||
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func verifyLogLines(c *check.C, fileName string, countInit int, accessLog bool) int {
|
||||
func (s *LogRotationSuite) verifyLogLines(fileName string, countInit int, accessLog bool) int {
|
||||
rotated, err := os.Open(fileName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
rotatedLog := bufio.NewScanner(rotated)
|
||||
count := countInit
|
||||
for rotatedLog.Scan() {
|
||||
|
@ -174,7 +176,7 @@ func verifyLogLines(c *check.C, fileName string, countInit int, accessLog bool)
|
|||
if accessLog {
|
||||
if len(line) > 0 {
|
||||
if !strings.Contains(line, "/api/rawdata") {
|
||||
CheckAccessLogFormat(c, line, count)
|
||||
s.CheckAccessLogFormat(line, count)
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gambol99/go-marathon"
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Marathon test suites.
|
||||
|
@ -17,42 +17,46 @@ type MarathonSuite15 struct {
|
|||
marathonURL string
|
||||
}
|
||||
|
||||
func (s *MarathonSuite15) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "marathon15")
|
||||
s.composeUp(c)
|
||||
func TestMarathonSuite15(t *testing.T) {
|
||||
suite.Run(t, new(MarathonSuite))
|
||||
}
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080"
|
||||
func (s *MarathonSuite15) SetUpSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("marathon15")
|
||||
s.composeUp()
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(containerNameMarathon) + ":8080"
|
||||
|
||||
// Wait for Marathon readiness prior to creating the client so that we
|
||||
// don't run into the "all cluster members down" state right from the
|
||||
// start.
|
||||
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
||||
c.Skip("doesn't work")
|
||||
func (s *MarathonSuite15) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *MarathonSuite15) TestConfigurationUpdate() {
|
||||
s.T().Skip("doesn't work")
|
||||
|
||||
// Start Traefik.
|
||||
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
|
||||
file := s.adaptFile("fixtures/marathon/simple.toml", struct {
|
||||
MarathonURL string
|
||||
}{s.marathonURL})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Prepare Marathon client.
|
||||
config := marathon.NewDefaultConfig()
|
||||
config.URL = s.marathonURL
|
||||
client, err := marathon.NewClient(config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application to be deployed.
|
||||
app := marathon.NewDockerApplication().
|
||||
|
@ -68,11 +72,11 @@ func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
|||
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application with services to be deployed.
|
||||
app = marathon.NewDockerApplication().
|
||||
|
@ -88,9 +92,9 @@ func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
|||
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gambol99/go-marathon"
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const containerNameMarathon = "marathon"
|
||||
|
@ -19,50 +19,55 @@ type MarathonSuite struct {
|
|||
marathonURL string
|
||||
}
|
||||
|
||||
func (s *MarathonSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "marathon")
|
||||
s.composeUp(c)
|
||||
func TestMarathonSuite(t *testing.T) {
|
||||
suite.Run(t, new(MarathonSuite))
|
||||
}
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080"
|
||||
func (s *MarathonSuite) SetUpSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
s.createComposeProject("marathon")
|
||||
s.composeUp()
|
||||
|
||||
s.marathonURL = "http://" + s.getComposeServiceIP(containerNameMarathon) + ":8080"
|
||||
|
||||
// Wait for Marathon readiness prior to creating the client so that we
|
||||
// don't run into the "all cluster members down" state right from the
|
||||
// start.
|
||||
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) {
|
||||
func (s *MarathonSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *BaseSuite) deployApplication(client marathon.Marathon, application *marathon.Application) {
|
||||
deploy, err := client.UpdateApplication(application, false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
// Wait for deployment to complete.
|
||||
c.Assert(client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute), checker.IsNil)
|
||||
err = client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
|
||||
c.Skip("doesn't work")
|
||||
func (s *MarathonSuite) TestConfigurationUpdate() {
|
||||
s.T().Skip("doesn't work")
|
||||
|
||||
// Start Traefik.
|
||||
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
|
||||
file := s.adaptFile("fixtures/marathon/simple.toml", struct {
|
||||
MarathonURL string
|
||||
}{s.marathonURL})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for Traefik to turn ready.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Prepare Marathon client.
|
||||
config := marathon.NewDefaultConfig()
|
||||
config.URL = s.marathonURL
|
||||
client, err := marathon.NewClient(config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application to be deployed.
|
||||
app := marathon.NewDockerApplication().
|
||||
|
@ -75,11 +80,11 @@ func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
|
|||
Container("traefik/whoami")
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Create test application with services to be deployed.
|
||||
app = marathon.NewDockerApplication().
|
||||
|
@ -92,9 +97,9 @@ func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
|
|||
Container("traefik/whoami")
|
||||
|
||||
// Deploy the test application.
|
||||
deployApplication(c, client, app)
|
||||
s.deployApplication(client, app)
|
||||
|
||||
// Query application via Traefik.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -1,103 +1,138 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"bufio"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/pires/go-proxyproto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type ProxyProtocolSuite struct {
|
||||
BaseSuite
|
||||
gatewayIP string
|
||||
haproxyIP string
|
||||
whoamiIP string
|
||||
whoamiIP string
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "proxy-protocol")
|
||||
s.composeUp(c)
|
||||
|
||||
s.gatewayIP = s.getContainerIP(c, "traefik")
|
||||
s.haproxyIP = s.getComposeServiceIP(c, "haproxy")
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
func TestProxyProtocolSuite(t *testing.T) {
|
||||
suite.Run(t, new(ProxyProtocolSuite))
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
|
||||
func (s *ProxyProtocolSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("proxy-protocol")
|
||||
s.composeUp()
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP("whoami")
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolTrusted() {
|
||||
file := s.adaptFile("fixtures/proxy-protocol/proxy-protocol.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
}{WhoamiIP: s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/whoami", 10*time.Second)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
content, err := proxyProtoRequest("127.0.0.1:8000", 1)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 1.2.3.4")
|
||||
|
||||
content, err = proxyProtoRequest("127.0.0.1:8000", 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 1.2.3.4")
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolV2Trusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct {
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted() {
|
||||
file := s.adaptFile("fixtures/proxy-protocol/proxy-protocol.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
}{WhoamiIP: s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.gatewayIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:9000/whoami", 10*time.Second)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
content, err := proxyProtoRequest("127.0.0.1:9000", 1)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 127.0.0.1")
|
||||
|
||||
content, err = proxyProtoRequest("127.0.0.1:9000", 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), content, "X-Forwarded-For: 127.0.0.1")
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func proxyProtoRequest(address string, version byte) (string, error) {
|
||||
// Open a TCP connection to the server
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
// Create a Proxy Protocol header with v1
|
||||
proxyHeader := &proxyproto.Header{
|
||||
Version: version,
|
||||
Command: proxyproto.PROXY,
|
||||
TransportProtocol: proxyproto.TCPv4,
|
||||
DestinationAddr: &net.TCPAddr{
|
||||
IP: net.ParseIP("127.0.0.1"),
|
||||
Port: 8000,
|
||||
},
|
||||
SourceAddr: &net.TCPAddr{
|
||||
IP: net.ParseIP("1.2.3.4"),
|
||||
Port: 62541,
|
||||
},
|
||||
}
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+"/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ProxyProtocolSuite) TestProxyProtocolV2NotTrusted(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct {
|
||||
HaproxyIP string
|
||||
WhoamiIP string
|
||||
}{HaproxyIP: s.haproxyIP, WhoamiIP: s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://"+s.haproxyIP+":81/whoami", 1*time.Second,
|
||||
try.StatusCodeIs(http.StatusOK),
|
||||
try.BodyContains("X-Forwarded-For: "+s.haproxyIP))
|
||||
c.Assert(err, checker.IsNil)
|
||||
// After the connection was created write the proxy headers first
|
||||
_, err = proxyHeader.WriteTo(conn)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Create an HTTP request
|
||||
request := "GET /whoami HTTP/1.1\r\n" +
|
||||
"Host: 127.0.0.1\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n"
|
||||
|
||||
// Write the HTTP request to the TCP connection
|
||||
writer := bufio.NewWriter(conn)
|
||||
_, err = writer.WriteString(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Flush the buffer to ensure the request is sent
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Read the response from the server
|
||||
var content string
|
||||
scanner := bufio.NewScanner(conn)
|
||||
for scanner.Scan() {
|
||||
content += scanner.Text() + "\n"
|
||||
}
|
||||
|
||||
if scanner.Err() != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RateLimitSuite struct {
|
||||
|
@ -15,33 +15,38 @@ type RateLimitSuite struct {
|
|||
ServerIP string
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "ratelimit")
|
||||
s.composeUp(c)
|
||||
|
||||
s.ServerIP = s.getComposeServiceIP(c, "whoami1")
|
||||
func TestRateLimitSuite(t *testing.T) {
|
||||
suite.Run(t, new(RateLimitSuite))
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/ratelimit/simple.toml", struct {
|
||||
func (s *RateLimitSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("ratelimit")
|
||||
s.composeUp()
|
||||
|
||||
s.ServerIP = s.getComposeServiceIP("whoami1")
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *RateLimitSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/ratelimit/simple.toml", struct {
|
||||
Server1 string
|
||||
}{s.ServerIP})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("ratelimit"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("ratelimit"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
start := time.Now()
|
||||
count := 0
|
||||
for {
|
||||
err = try.GetRequest("http://127.0.0.1:8081/", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
count++
|
||||
if count > 100 {
|
||||
break
|
||||
|
@ -50,6 +55,6 @@ func (s *RateLimitSuite) TestSimpleConfiguration(c *check.C) {
|
|||
stop := time.Now()
|
||||
elapsed := stop.Sub(start)
|
||||
if elapsed < time.Second*99/100 {
|
||||
c.Fatalf("requests throughput was too fast wrt to rate limiting: 100 requests in %v", elapsed)
|
||||
s.T().Fatalf("requests throughput was too fast wrt to rate limiting: 100 requests in %v", elapsed)
|
||||
}
|
||||
}
|
||||
|
|
201
integration/redis_sentinel_test.go
Normal file
201
integration/redis_sentinel_test.go
Normal file
|
@ -0,0 +1,201 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/kvtools/redis"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
// Redis test suites.
|
||||
type RedisSentinelSuite struct {
|
||||
BaseSuite
|
||||
kvClient store.Store
|
||||
redisEndpoints []string
|
||||
}
|
||||
|
||||
func TestRedisSentinelSuite(t *testing.T) {
|
||||
suite.Run(t, new(RedisSentinelSuite))
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.setupSentinelConfiguration([]string{"26379", "26379", "26379"})
|
||||
|
||||
s.createComposeProject("redis_sentinel")
|
||||
s.composeUp()
|
||||
|
||||
s.redisEndpoints = []string{
|
||||
net.JoinHostPort(s.getComposeServiceIP("sentinel1"), "26379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP("sentinel2"), "26379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP("sentinel3"), "26379"),
|
||||
}
|
||||
kv, err := valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
redis.StoreName,
|
||||
s.redisEndpoints,
|
||||
&redis.Config{
|
||||
Sentinel: &redis.Sentinel{
|
||||
MasterName: "mymaster",
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(s.T(), err, "Cannot create store redis")
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for redis
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
|
||||
for _, filename := range []string{"sentinel1.conf", "sentinel2.conf", "sentinel3.conf"} {
|
||||
_ = os.Remove(filepath.Join(".", "resources", "compose", "config", filename))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) setupSentinelConfiguration(ports []string) {
|
||||
for i, port := range ports {
|
||||
templateValue := struct{ SentinelPort string }{SentinelPort: port}
|
||||
|
||||
// Load file
|
||||
templateFile := "resources/compose/config/sentinel_template.conf"
|
||||
tmpl, err := template.ParseFiles(templateFile)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
folder, prefix := filepath.Split(templateFile)
|
||||
|
||||
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
|
||||
tmpFile, err := os.Create(fileName)
|
||||
require.NoError(s.T(), err)
|
||||
defer tmpFile.Close()
|
||||
|
||||
model := structs.Map(templateValue)
|
||||
model["SelfFilename"] = tmpFile.Name()
|
||||
|
||||
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = tmpFile.Sync()
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSentinelSuite) TestSentinelConfiguration() {
|
||||
file := s.adaptFile("fixtures/redis/sentinel.toml", struct{ RedisAddress string }{
|
||||
RedisAddress: strings.Join(s.redisEndpoints, `","`),
|
||||
})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "true",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "true",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@redis":`, `"compressor@redis":`, `"srvcA@redis":`, `"srvcB@redis":`),
|
||||
)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Info(text)
|
||||
}
|
||||
}
|
|
@ -4,26 +4,22 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/redis"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Redis test suites.
|
||||
|
@ -33,23 +29,18 @@ type RedisSuite struct {
|
|||
redisEndpoints []string
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TearDownSuite(c *check.C) {
|
||||
s.composeDown(c)
|
||||
|
||||
for _, filename := range []string{"sentinel1.conf", "sentinel2.conf", "sentinel3.conf"} {
|
||||
err := os.Remove(filepath.Join(".", "resources", "compose", "config", filename))
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
c.Fatal("unable to clean configuration file for sentinel: ", err)
|
||||
}
|
||||
}
|
||||
func TestRedisSuite(t *testing.T) {
|
||||
suite.Run(t, new(RedisSuite))
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "redis")
|
||||
s.composeUp(c)
|
||||
func (s *RedisSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("redis")
|
||||
s.composeUp()
|
||||
|
||||
s.redisEndpoints = []string{}
|
||||
s.redisEndpoints = append(s.redisEndpoints, net.JoinHostPort(s.getComposeServiceIP(c, "redis"), "6379"))
|
||||
s.redisEndpoints = append(s.redisEndpoints, net.JoinHostPort(s.getComposeServiceIP("redis"), "6379"))
|
||||
|
||||
kv, err := valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
|
@ -57,23 +48,23 @@ func (s *RedisSuite) setupStore(c *check.C) {
|
|||
s.redisEndpoints,
|
||||
&redis.Config{},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store redis: ", err)
|
||||
}
|
||||
require.NoError(s.T(), err, "Cannot create store redis")
|
||||
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for redis
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
func (s *RedisSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{
|
||||
func (s *RedisSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/redis/simple.toml", struct{ RedisAddress string }{
|
||||
RedisAddress: strings.Join(s.redisEndpoints, ","),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -123,39 +114,35 @@ func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@redis":`, `"compressor@redis":`, `"srvcA@redis":`, `"srvcB@redis":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -167,171 +154,6 @@ func (s *RedisSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupSentinelStore(c *check.C) {
|
||||
s.setupSentinelConfiguration(c, []string{"26379", "36379", "46379"})
|
||||
|
||||
s.createComposeProject(c, "redis_sentinel")
|
||||
s.composeUp(c)
|
||||
|
||||
s.redisEndpoints = []string{
|
||||
net.JoinHostPort(s.getComposeServiceIP(c, "sentinel1"), "26379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP(c, "sentinel2"), "36379"),
|
||||
net.JoinHostPort(s.getComposeServiceIP(c, "sentinel3"), "46379"),
|
||||
}
|
||||
|
||||
kv, err := valkeyrie.NewStore(
|
||||
context.Background(),
|
||||
redis.StoreName,
|
||||
s.redisEndpoints,
|
||||
&redis.Config{
|
||||
Sentinel: &redis.Sentinel{
|
||||
MasterName: "mymaster",
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store redis sentinel")
|
||||
}
|
||||
s.kvClient = kv
|
||||
|
||||
// wait for redis
|
||||
err = try.Do(60*time.Second, try.KVExists(kv, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *RedisSuite) setupSentinelConfiguration(c *check.C, ports []string) {
|
||||
for i, port := range ports {
|
||||
templateValue := struct{ SentinelPort string }{SentinelPort: port}
|
||||
|
||||
// Load file
|
||||
templateFile := "resources/compose/config/sentinel_template.conf"
|
||||
tmpl, err := template.ParseFiles(templateFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
folder, prefix := filepath.Split(templateFile)
|
||||
|
||||
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
|
||||
tmpFile, err := os.Create(fileName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer tmpFile.Close()
|
||||
|
||||
model := structs.Map(templateValue)
|
||||
model["SelfFilename"] = tmpFile.Name()
|
||||
|
||||
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = tmpFile.Sync()
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RedisSuite) TestSentinelConfiguration(c *check.C) {
|
||||
s.setupSentinelStore(c)
|
||||
|
||||
file := s.adaptFile(c, "fixtures/redis/sentinel.toml", struct{ RedisAddress string }{
|
||||
RedisAddress: strings.Join(s.redisEndpoints, `","`),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/middlewares/0": "compressor",
|
||||
"traefik/http/routers/Router0/middlewares/1": "striper",
|
||||
"traefik/http/routers/Router0/service": "simplesvc",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/priority": "42",
|
||||
"traefik/http/routers/Router0/tls": "true",
|
||||
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/priority": "42",
|
||||
"traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost",
|
||||
"traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost",
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/service": "simplesvc",
|
||||
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888",
|
||||
"traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889",
|
||||
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888",
|
||||
"traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889",
|
||||
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888",
|
||||
"traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889",
|
||||
|
||||
"traefik/http/services/mirror/mirroring/service": "simplesvc",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/0/percent": "42",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB",
|
||||
"traefik/http/services/mirror/mirroring/mirrors/1/percent": "42",
|
||||
|
||||
"traefik/http/services/Service03/weighted/services/0/name": "srvcA",
|
||||
"traefik/http/services/Service03/weighted/services/0/weight": "42",
|
||||
"traefik/http/services/Service03/weighted/services/1/name": "srvcB",
|
||||
"traefik/http/services/Service03/weighted/services/1/weight": "42",
|
||||
|
||||
"traefik/http/middlewares/compressor/compress": "true",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo",
|
||||
"traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar",
|
||||
"traefik/http/middlewares/striper/stripPrefix/forceSlash": "true",
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"striper@redis":`, `"compressor@redis":`, `"srvcA@redis":`, `"srvcB@redis":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
FromFile: "Expected",
|
||||
A: difflib.SplitLines(string(expected)),
|
||||
ToFile: "Got",
|
||||
B: difflib.SplitLines(string(got)),
|
||||
Context: 3,
|
||||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err, text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ services:
|
|||
traefik.http.routers.rt-authFrontend.entryPoints: httpFrontendAuth
|
||||
traefik.http.routers.rt-authFrontend.rule: Host(`frontend.auth.docker.local`)
|
||||
traefik.http.routers.rt-authFrontend.middlewares: basicauth
|
||||
traefik.http.middlewares.basicauth.basicauth.users: test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/
|
||||
traefik.http.middlewares.basicauth.basicauth.users: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
digestAuthMiddleware:
|
||||
|
@ -94,8 +94,3 @@ services:
|
|||
traefik.http.routers.rt-preflightCORS.middlewares: preflightCORS
|
||||
traefik.http.middlewares.preflightCORS.headers.accessControlAllowMethods: OPTIONS, GET
|
||||
traefik.http.services.preflightCORS.loadbalancer.server.port: 80
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -34,8 +34,3 @@ services:
|
|||
traefik.http.routers.rt4.middlewares: wl4
|
||||
traefik.http.middlewares.wl4.ipallowlist.sourceRange: 8.8.8.8
|
||||
traefik.http.middlewares.wl4.ipallowlist.ipStrategy.excludedIPs: 10.0.0.1,10.0.0.2
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -11,8 +11,3 @@ services:
|
|||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: false
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -4,8 +4,3 @@ services:
|
|||
image: consul:1.6
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,11 +2,24 @@ version: "3.8"
|
|||
services:
|
||||
consul:
|
||||
image: consul:1.6.2
|
||||
command: agent -server -bootstrap -ui -client 0.0.0.0 -hcl 'connect { enabled = true }'
|
||||
command:
|
||||
- agent
|
||||
- -server
|
||||
- -bootstrap
|
||||
- -ui
|
||||
- -client
|
||||
- 0.0.0.0
|
||||
- -hcl
|
||||
- 'connect { enabled = true }'
|
||||
|
||||
consul-agent:
|
||||
image: consul:1.6.2
|
||||
command: agent -retry-join consul -client 0.0.0.0
|
||||
command:
|
||||
- agent
|
||||
- -retry-join
|
||||
- consul
|
||||
- -client
|
||||
- 0.0.0.0
|
||||
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
@ -30,8 +43,3 @@ services:
|
|||
PORT: 443
|
||||
BIND: 0.0.0.0
|
||||
CONSUL_HTTP_ADDR: http://consul:8500
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -36,8 +36,3 @@ services:
|
|||
labels:
|
||||
traefik.http.Routers.Super.Rule: Host(`my.super.host`)
|
||||
traefik.http.Services.powpow.LoadBalancer.server.Port: 2375
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
nginx1:
|
||||
image: nginx:1.13.8-alpine
|
||||
image: nginx:1.25.3-alpine3.18
|
||||
|
||||
nginx2:
|
||||
image: nginx:1.13.8-alpine
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
image: nginx:1.25.3-alpine3.18
|
||||
|
|
|
@ -2,9 +2,9 @@ version: "3.8"
|
|||
services:
|
||||
etcd:
|
||||
image: quay.io/coreos/etcd:v3.3.18
|
||||
command: etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://0.0.0.0:2380
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
command:
|
||||
- etcd
|
||||
- --listen-client-urls
|
||||
- http://0.0.0.0:2379
|
||||
- --advertise-client-urls
|
||||
- http://0.0.0.0:2380
|
||||
|
|
|
@ -14,8 +14,3 @@ services:
|
|||
|
||||
whoami5:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -11,8 +11,3 @@ services:
|
|||
|
||||
whoami4:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -6,8 +6,3 @@ services:
|
|||
traefik.enable: true
|
||||
traefik.http.services.service1.loadbalancer.server.port: 80
|
||||
traefik.http.routers.router1.rule: Host(`github.com`)
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,9 +2,23 @@ version: "3.8"
|
|||
services:
|
||||
server:
|
||||
image: rancher/k3s:v1.20.15-k3s1
|
||||
command: server --disable-agent --no-deploy coredns --no-deploy servicelb --no-deploy traefik --no-deploy local-storage --no-deploy metrics-server --log /output/k3s.log --bind-address=server --tls-san=server
|
||||
privileged: true
|
||||
command:
|
||||
- server
|
||||
- --disable-agent
|
||||
- --disable=coredns
|
||||
- --disable=servicelb
|
||||
- --disable=traefik
|
||||
- --disable=local-storage
|
||||
- --disable=metrics-server
|
||||
- --log=/output/k3s.log
|
||||
- --bind-address=server
|
||||
- --tls-san=server
|
||||
- --tls-san=172.31.42.3
|
||||
- --tls-san=172.31.42.4
|
||||
environment:
|
||||
K3S_CLUSTER_SECRET: somethingtotallyrandom
|
||||
K3S_TOKEN: somethingtotallyrandom
|
||||
K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml
|
||||
K3S_KUBECONFIG_MODE: 666
|
||||
volumes:
|
||||
|
@ -15,10 +29,6 @@ services:
|
|||
image: rancher/k3s:v1.20.15-k3s1
|
||||
privileged: true
|
||||
environment:
|
||||
K3S_TOKEN: somethingtotallyrandom
|
||||
K3S_URL: https://server:6443
|
||||
K3S_CLUSTER_SECRET: somethingtotallyrandom
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -3,12 +3,9 @@ services:
|
|||
whoami1:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.http.Routers.RouterMini.Rule: PathPrefix(`/whoami`)
|
||||
traefik.http.routers.router-mini.Rule: PathPrefix(`/whoami`)
|
||||
traefik.http.routers.router-mini.service: service-mini
|
||||
traefik.http.services.service-mini.loadbalancer.server.port: 80
|
||||
traefik.enable: true
|
||||
deploy:
|
||||
replicas: 2
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,14 +2,12 @@ version: "3.8"
|
|||
services:
|
||||
pebble:
|
||||
image: letsencrypt/pebble:v2.3.1
|
||||
command: pebble --dnsserver traefik:5053
|
||||
command:
|
||||
- pebble
|
||||
- --dnsserver
|
||||
- host.docker.internal:5053
|
||||
environment:
|
||||
# https://github.com/letsencrypt/pebble#testing-at-full-speed
|
||||
PEBBLE_VA_NOSLEEP: 1
|
||||
# https://github.com/letsencrypt/pebble#invalid-anti-replay-nonce-errors
|
||||
PEBBLE_WFE_NONCEREJECT: 0
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
haproxy:
|
||||
image: haproxy:2.2
|
||||
volumes:
|
||||
- ./resources/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
redis:
|
||||
image: redis:5.0
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -3,59 +3,51 @@ services:
|
|||
master:
|
||||
image: redis
|
||||
container_name: redis-master
|
||||
command: redis-server --port 6380
|
||||
ports:
|
||||
- 6380:6380
|
||||
healthcheck:
|
||||
test: redis-cli -p 6380 ping
|
||||
command:
|
||||
- redis-server
|
||||
- --port
|
||||
- 6380
|
||||
node1:
|
||||
image: redis
|
||||
container_name: redis-node-1
|
||||
ports:
|
||||
- 6381:6381
|
||||
command: redis-server --port 6381 --slaveof redis-master 6380
|
||||
healthcheck:
|
||||
test: redis-cli -p 6381 ping
|
||||
command:
|
||||
- redis-server
|
||||
- --port
|
||||
- 6381
|
||||
- --slaveof
|
||||
- redis-master
|
||||
- 6380
|
||||
node2:
|
||||
image: redis
|
||||
container_name: redis-node-2
|
||||
ports:
|
||||
- 6382:6382
|
||||
command: redis-server --port 6382 --slaveof redis-master 6380
|
||||
healthcheck:
|
||||
test: redis-cli -p 6382 ping
|
||||
command:
|
||||
- redis-server
|
||||
- --port
|
||||
- 6382
|
||||
- --slaveof
|
||||
- redis-master
|
||||
- 6380
|
||||
sentinel1:
|
||||
image: redis
|
||||
container_name: redis-sentinel-1
|
||||
ports:
|
||||
- 26379:26379
|
||||
command: redis-sentinel /usr/local/etc/redis/conf/sentinel1.conf
|
||||
healthcheck:
|
||||
test: redis-cli -p 26379 ping
|
||||
command:
|
||||
- redis-sentinel
|
||||
- /usr/local/etc/redis/conf/sentinel1.conf
|
||||
volumes:
|
||||
- ./resources/compose/config:/usr/local/etc/redis/conf
|
||||
sentinel2:
|
||||
image: redis
|
||||
container_name: redis-sentinel-2
|
||||
ports:
|
||||
- 36379:26379
|
||||
command: redis-sentinel /usr/local/etc/redis/conf/sentinel2.conf
|
||||
healthcheck:
|
||||
test: redis-cli -p 36379 ping
|
||||
command:
|
||||
- redis-sentinel
|
||||
- /usr/local/etc/redis/conf/sentinel2.conf
|
||||
volumes:
|
||||
- ./resources/compose/config:/usr/local/etc/redis/conf
|
||||
sentinel3:
|
||||
image: redis
|
||||
container_name: redis-sentinel-3
|
||||
ports:
|
||||
- 46379:26379
|
||||
command: redis-sentinel /usr/local/etc/redis/conf/sentinel3.conf
|
||||
healthcheck:
|
||||
test: redis-cli -p 46379 ping
|
||||
command:
|
||||
- redis-sentinel
|
||||
- /usr/local/etc/redis/conf/sentinel3.conf
|
||||
volumes:
|
||||
- ./resources/compose/config:/usr/local/etc/redis/conf
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami1:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -5,8 +5,3 @@ services:
|
|||
|
||||
whoami2:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -9,9 +9,5 @@ services:
|
|||
cap_add: # Required for tailscale to work
|
||||
- net_admin
|
||||
- sys_module
|
||||
command: tailscaled
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
command:
|
||||
- tailscaled
|
||||
|
|
|
@ -2,38 +2,58 @@ version: "3.8"
|
|||
services:
|
||||
whoami-a:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-a -certFile /certs/whoami-a.crt -keyFile /certs/whoami-a.key
|
||||
command:
|
||||
- -name
|
||||
- whoami-a
|
||||
- -certFile
|
||||
- /certs/whoami-a.crt
|
||||
- -keyFile
|
||||
- /certs/whoami-a.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-b:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-b -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
|
||||
command:
|
||||
- -name
|
||||
- whoami-b
|
||||
- -certFile
|
||||
- /certs/whoami-b.crt
|
||||
- -keyFile
|
||||
- /certs/whoami-b.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-ab:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-ab -certFile /certs/whoami-b.crt -keyFile /certs/whoami-b.key
|
||||
command:
|
||||
- -name
|
||||
- whoami-ab
|
||||
- -certFile
|
||||
- /certs/whoami-b.crt
|
||||
- -keyFile
|
||||
- /certs/whoami-b.key
|
||||
volumes:
|
||||
- ./fixtures/tcp:/certs
|
||||
|
||||
whoami-no-cert:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-cert
|
||||
command:
|
||||
- -name
|
||||
- whoami-no-cert
|
||||
|
||||
whoami-no-tls:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-no-tls
|
||||
command:
|
||||
- -name
|
||||
- whoami-no-tls
|
||||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
whoami-banner:
|
||||
image: traefik/whoamitcp
|
||||
command: -name whoami-banner --banner
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
command:
|
||||
- -name
|
||||
- whoami-banner
|
||||
- --banner
|
||||
|
|
|
@ -5,8 +5,3 @@ services:
|
|||
environment:
|
||||
PROTO: http
|
||||
PORT: 9000
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -7,8 +7,3 @@ services:
|
|||
traefik.http.routers.route1.middlewares: passtls
|
||||
traefik.http.routers.route1.tls: true
|
||||
traefik.http.middlewares.passtls.passtlsclientcert.pem: true
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -13,8 +13,3 @@ services:
|
|||
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,20 +2,21 @@ version: "3.8"
|
|||
services:
|
||||
whoami-a:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-a
|
||||
command:
|
||||
- -name
|
||||
- whoami-a
|
||||
|
||||
whoami-b:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-b
|
||||
command:
|
||||
- -name
|
||||
- whoami-b
|
||||
|
||||
whoami-c:
|
||||
image: traefik/whoamiudp:latest
|
||||
command: -name whoami-c
|
||||
command:
|
||||
- -name
|
||||
- whoami-c
|
||||
|
||||
whoami-d:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -2,8 +2,3 @@ version: "3.8"
|
|||
services:
|
||||
zookeeper:
|
||||
image: zookeeper:3.5
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
external: true
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
global
|
||||
maxconn 4096
|
||||
|
||||
defaults
|
||||
log global
|
||||
mode http
|
||||
retries 3
|
||||
option redispatch
|
||||
maxconn 2000
|
||||
timeout connect 5000
|
||||
timeout client 50000
|
||||
timeout server 50000
|
||||
|
||||
frontend TestServerTest
|
||||
bind 0.0.0.0:80
|
||||
mode tcp
|
||||
default_backend TestServerNodes
|
||||
|
||||
frontend TestServerTestV2
|
||||
bind 0.0.0.0:81
|
||||
mode tcp
|
||||
default_backend TestServerNodesV2
|
||||
|
||||
backend TestServerNodes
|
||||
mode tcp
|
||||
server TestServer01 traefik:8000 send-proxy
|
||||
|
||||
backend TestServerNodesV2
|
||||
mode tcp
|
||||
server TestServer01 traefik:8000 send-proxy-v2
|
|
@ -5,14 +5,15 @@ import (
|
|||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RestSuite struct {
|
||||
|
@ -20,28 +21,33 @@ type RestSuite struct {
|
|||
whoamiAddr string
|
||||
}
|
||||
|
||||
func (s *RestSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "rest")
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoamiAddr = net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
|
||||
func TestRestSuite(t *testing.T) {
|
||||
suite.Run(t, new(RestSuite))
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/rest/simple.toml"))
|
||||
func (s *RestSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("rest")
|
||||
s.composeUp()
|
||||
|
||||
s.whoamiAddr = net.JoinHostPort(s.getComposeServiceIP("whoami1"), "80")
|
||||
}
|
||||
|
||||
func (s *RestSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfigurationInsecure() {
|
||||
s.traefikCmd(withConfigFile("fixtures/rest/simple.toml"))
|
||||
|
||||
// wait for Traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Expected a 404 as we did not configure anything.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -105,47 +111,41 @@ func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
data, err := json.Marshal(test.config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", bytes.NewReader(data))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 3*time.Second, try.BodyContains(test.ruleMatch))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/rest/simple_secure.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
func (s *RestSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/rest/simple_secure.toml", struct{}{})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Expected a 404 as we did not configure anything.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2000*time.Millisecond, try.BodyContains("PathPrefix(`/secure`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", strings.NewReader("{}"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusNotFound, response.StatusCode)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
|
@ -209,19 +209,19 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for _, test := range testCase {
|
||||
data, err := json.Marshal(test.config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8000/secure/api/providers/rest", bytes.NewReader(data))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains(test.ruleMatch))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@ package integration
|
|||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type RetrySuite struct {
|
||||
|
@ -17,96 +18,86 @@ type RetrySuite struct {
|
|||
whoamiIP string
|
||||
}
|
||||
|
||||
func (s *RetrySuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "retry")
|
||||
s.composeUp(c)
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
func TestRetrySuite(t *testing.T) {
|
||||
suite.Run(t, new(RetrySuite))
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetry(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("retry")
|
||||
s.composeUp()
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.whoamiIP = s.getComposeServiceIP("whoami")
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetry() {
|
||||
file := s.adaptFile("fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.Get("http://127.0.0.1:8000/")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// The test only verifies that the retry middleware makes sure that the working service is eventually reached.
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryBackoff(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/backoff.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) TestRetryBackoff() {
|
||||
file := s.adaptFile("fixtures/retry/backoff.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.Get("http://127.0.0.1:8000/")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// The test only verifies that the retry middleware allows finally to reach the working service.
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
assert.Equal(s.T(), http.StatusOK, response.StatusCode)
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryWebsocket(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) TestRetryWebsocket() {
|
||||
file := s.adaptFile("fixtures/retry/simple.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// The test only verifies that the retry middleware makes sure that the working service is eventually reached.
|
||||
_, response, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8000/echo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusSwitchingProtocols)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusSwitchingProtocols, response.StatusCode)
|
||||
|
||||
// The test verifies a second time that the working service is eventually reached.
|
||||
_, response, err = websocket.DefaultDialer.Dial("ws://127.0.0.1:8000/echo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusSwitchingProtocols)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusSwitchingProtocols, response.StatusCode)
|
||||
}
|
||||
|
||||
func (s *RetrySuite) TestRetryWithStripPrefix(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/retry/strip_prefix.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
defer os.Remove(file)
|
||||
func (s *RetrySuite) TestRetryWithStripPrefix() {
|
||||
file := s.adaptFile("fixtures/retry/strip_prefix.toml", struct{ WhoamiIP string }{s.whoamiIP})
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("PathPrefix(`/`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
response, err := http.Get("http://127.0.0.1:8000/test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
body, err := io.ReadAll(response.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
c.Assert(string(body), checker.Contains, "GET / HTTP/1.1")
|
||||
c.Assert(string(body), checker.Contains, "X-Forwarded-Prefix: /test")
|
||||
assert.Contains(s.T(), string(body), "GET / HTTP/1.1")
|
||||
assert.Contains(s.T(), string(body), "X-Forwarded-Prefix: /test")
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,63 +5,69 @@ import (
|
|||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type TCPSuite struct{ BaseSuite }
|
||||
|
||||
func (s *TCPSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "tcp")
|
||||
s.composeUp(c)
|
||||
func TestTCPSuite(t *testing.T) {
|
||||
suite.Run(t, new(TCPSuite))
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestMixed(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/mixed.toml", struct {
|
||||
func (s *TCPSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("tcp")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestMixed() {
|
||||
file := s.adaptFile("fixtures/tcp/mixed.toml", struct {
|
||||
Whoami string
|
||||
WhoamiA string
|
||||
WhoamiB string
|
||||
WhoamiNoCert string
|
||||
}{
|
||||
Whoami: "http://" + s.getComposeServiceIP(c, "whoami") + ":80",
|
||||
WhoamiA: s.getComposeServiceIP(c, "whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP(c, "whoami-no-cert") + ":8080",
|
||||
Whoami: "http://" + s.getComposeServiceIP("whoami") + ":80",
|
||||
WhoamiA: s.getComposeServiceIP("whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP("whoami-no-cert") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("Path(`/test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("Path(`/test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik passes through, termination handled by whoami-a
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-a")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-a")
|
||||
|
||||
// Traefik passes through, termination handled by whoami-b
|
||||
out, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-b")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-b")
|
||||
|
||||
// Termination handled by traefik
|
||||
out, err = guessWho("127.0.0.1:8093", "whoami-c.test", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
tr1 := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
|
@ -69,174 +75,143 @@ func (s *TCPSuite) TestMixed(c *check.C) {
|
|||
},
|
||||
}
|
||||
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8093/whoami/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.RequestWithTransport(req, 10*time.Second, tr1, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "https://127.0.0.1:8093/not-found/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.RequestWithTransport(req, 10*time.Second, tr1, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8093/test", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8093/not-found", 500*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestTLSOptions(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/multi-tls-options.toml", struct {
|
||||
func (s *TCPSuite) TestTLSOptions() {
|
||||
file := s.adaptFile("fixtures/tcp/multi-tls-options.toml", struct {
|
||||
WhoamiNoCert string
|
||||
}{
|
||||
WhoamiNoCert: s.getComposeServiceIP(c, "whoami-no-cert") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP("whoami-no-cert") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-c.test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-c.test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Check that we can use a client tls version <= 1.2 with hostSNI 'whoami-c.test'
|
||||
out, err := guessWhoTLSMaxVersion("127.0.0.1:8093", "whoami-c.test", true, tls.VersionTLS12)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
// Check that we can use a client tls version <= 1.3 with hostSNI 'whoami-d.test'
|
||||
out, err = guessWhoTLSMaxVersion("127.0.0.1:8093", "whoami-d.test", true, tls.VersionTLS13)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
// Check that we cannot use a client tls version <= 1.2 with hostSNI 'whoami-d.test'
|
||||
_, err = guessWhoTLSMaxVersion("127.0.0.1:8093", "whoami-d.test", true, tls.VersionTLS12)
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(err.Error(), checker.Contains, "protocol version not supported")
|
||||
assert.ErrorContains(s.T(), err, "protocol version not supported")
|
||||
|
||||
// Check that we can't reach a route with an invalid mTLS configuration.
|
||||
conn, err := tls.Dial("tcp", "127.0.0.1:8093", &tls.Config{
|
||||
ServerName: "whoami-i.test",
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
c.Assert(conn, checker.IsNil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
assert.Nil(s.T(), conn)
|
||||
assert.Error(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestNonTLSFallback(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/non-tls-fallback.toml", struct {
|
||||
func (s *TCPSuite) TestNonTLSFallback() {
|
||||
file := s.adaptFile("fixtures/tcp/non-tls-fallback.toml", struct {
|
||||
WhoamiA string
|
||||
WhoamiB string
|
||||
WhoamiNoCert string
|
||||
WhoamiNoTLS string
|
||||
}{
|
||||
WhoamiA: s.getComposeServiceIP(c, "whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP(c, "whoami-no-cert") + ":8080",
|
||||
WhoamiNoTLS: s.getComposeServiceIP(c, "whoami-no-tls") + ":8080",
|
||||
WhoamiA: s.getComposeServiceIP("whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
WhoamiNoCert: s.getComposeServiceIP("whoami-no-cert") + ":8080",
|
||||
WhoamiNoTLS: s.getComposeServiceIP("whoami-no-tls") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik passes through, termination handled by whoami-a
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-a")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-a")
|
||||
|
||||
// Traefik passes through, termination handled by whoami-b
|
||||
out, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-b")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-b")
|
||||
|
||||
// Termination handled by traefik
|
||||
out, err = guessWho("127.0.0.1:8093", "whoami-c.test", true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-cert")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-cert")
|
||||
|
||||
out, err = guessWho("127.0.0.1:8093", "", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-tls")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-tls")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestNonTlsTcp(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/non-tls.toml", struct {
|
||||
func (s *TCPSuite) TestNonTlsTcp() {
|
||||
file := s.adaptFile("fixtures/tcp/non-tls.toml", struct {
|
||||
WhoamiNoTLS string
|
||||
}{
|
||||
WhoamiNoTLS: s.getComposeServiceIP(c, "whoami-no-tls") + ":8080",
|
||||
WhoamiNoTLS: s.getComposeServiceIP("whoami-no-tls") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik will forward every requests on the given port to whoami-no-tls
|
||||
out, err := guessWho("127.0.0.1:8093", "", false)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-no-tls")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-no-tls")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestCatchAllNoTLS(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/catch-all-no-tls.toml", struct {
|
||||
func (s *TCPSuite) TestCatchAllNoTLS() {
|
||||
file := s.adaptFile("fixtures/tcp/catch-all-no-tls.toml", struct {
|
||||
WhoamiBannerAddress string
|
||||
}{
|
||||
WhoamiBannerAddress: s.getComposeServiceIP(c, "whoami-banner") + ":8080",
|
||||
WhoamiBannerAddress: s.getComposeServiceIP("whoami-banner") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik will forward every requests on the given port to whoami-no-tls
|
||||
out, err := welcome("127.0.0.1:8093")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "Welcome")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "Welcome")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestCatchAllNoTLSWithHTTPS(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/catch-all-no-tls-with-https.toml", struct {
|
||||
func (s *TCPSuite) TestCatchAllNoTLSWithHTTPS() {
|
||||
file := s.adaptFile("fixtures/tcp/catch-all-no-tls-with-https.toml", struct {
|
||||
WhoamiNoTLSAddress string
|
||||
WhoamiURL string
|
||||
}{
|
||||
WhoamiNoTLSAddress: s.getComposeServiceIP(c, "whoami-no-tls") + ":8080",
|
||||
WhoamiURL: "http://" + s.getComposeServiceIP(c, "whoami") + ":80",
|
||||
WhoamiNoTLSAddress: s.getComposeServiceIP("whoami-no-tls") + ":8080",
|
||||
WhoamiURL: "http://" + s.getComposeServiceIP("whoami") + ":80",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`*`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "https://127.0.0.1:8093/test", nil)
|
||||
req.RequestURI = ""
|
||||
|
@ -246,64 +221,52 @@ func (s *TCPSuite) TestCatchAllNoTLSWithHTTPS(c *check.C) {
|
|||
InsecureSkipVerify: true,
|
||||
},
|
||||
}, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestMiddlewareAllowList(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/ip-allowlist.toml", struct {
|
||||
func (s *TCPSuite) TestMiddlewareAllowList() {
|
||||
file := s.adaptFile("fixtures/tcp/ip-allowlist.toml", struct {
|
||||
WhoamiA string
|
||||
WhoamiB string
|
||||
}{
|
||||
WhoamiA: s.getComposeServiceIP(c, "whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiA: s.getComposeServiceIP("whoami-a") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-a.test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-a.test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Traefik not passes through, ipWhitelist closes connection
|
||||
_, err = guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-a.test")
|
||||
c.Assert(err, checker.ErrorMatches, "EOF")
|
||||
assert.ErrorIs(s.T(), err, io.EOF)
|
||||
|
||||
// Traefik passes through, termination handled by whoami-b
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, "whoami-b")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Contains(s.T(), out, "whoami-b")
|
||||
}
|
||||
|
||||
func (s *TCPSuite) TestWRR(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/tcp/wrr.toml", struct {
|
||||
func (s *TCPSuite) TestWRR() {
|
||||
file := s.adaptFile("fixtures/tcp/wrr.toml", struct {
|
||||
WhoamiB string
|
||||
WhoamiAB string
|
||||
}{
|
||||
WhoamiB: s.getComposeServiceIP(c, "whoami-b") + ":8080",
|
||||
WhoamiAB: s.getComposeServiceIP(c, "whoami-ab") + ":8080",
|
||||
WhoamiB: s.getComposeServiceIP("whoami-b") + ":8080",
|
||||
WhoamiAB: s.getComposeServiceIP("whoami-ab") + ":8080",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-b.test`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-b.test`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
call := map[string]int{}
|
||||
for i := 0; i < 4; i++ {
|
||||
// Traefik passes through, termination handled by whoami-b or whoami-bb
|
||||
out, err := guessWhoTLSPassthrough("127.0.0.1:8093", "whoami-b.test")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
switch {
|
||||
case strings.Contains(out, "whoami-b"):
|
||||
call["whoami-b"]++
|
||||
|
@ -315,7 +278,7 @@ func (s *TCPSuite) TestWRR(c *check.C) {
|
|||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
c.Assert(call, checker.DeepEquals, map[string]int{"whoami-b": 3, "whoami-ab": 1})
|
||||
assert.EqualValues(s.T(), call, map[string]int{"whoami-b": 3, "whoami-ab": 1})
|
||||
}
|
||||
|
||||
func welcome(addr string) (string, error) {
|
||||
|
|
|
@ -4,47 +4,53 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type TimeoutSuite struct{ BaseSuite }
|
||||
|
||||
func (s *TimeoutSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "timeout")
|
||||
s.composeUp(c)
|
||||
func TestTimeoutSuite(t *testing.T) {
|
||||
suite.Run(t, new(TimeoutSuite))
|
||||
}
|
||||
|
||||
func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) {
|
||||
timeoutEndpointIP := s.getComposeServiceIP(c, "timeoutEndpoint")
|
||||
file := s.adaptFile(c, "fixtures/timeout/forwarding_timeouts.toml", struct{ TimeoutEndpoint string }{timeoutEndpointIP})
|
||||
defer os.Remove(file)
|
||||
func (s *TimeoutSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.createComposeProject("timeout")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Path(`/dialTimeout`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
func (s *TimeoutSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TimeoutSuite) TestForwardingTimeouts() {
|
||||
timeoutEndpointIP := s.getComposeServiceIP("timeoutEndpoint")
|
||||
file := s.adaptFile("fixtures/timeout/forwarding_timeouts.toml", struct{ TimeoutEndpoint string }{timeoutEndpointIP})
|
||||
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 60*time.Second, try.BodyContains("Path(`/dialTimeout`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// This simulates a DialTimeout when connecting to the backend server.
|
||||
response, err := http.Get("http://127.0.0.1:8000/dialTimeout")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusGatewayTimeout, response.StatusCode)
|
||||
|
||||
// Check that timeout service is available
|
||||
statusURL := fmt.Sprintf("http://%s/statusTest?status=200",
|
||||
net.JoinHostPort(timeoutEndpointIP, "9000"))
|
||||
c.Assert(try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)), checker.IsNil)
|
||||
assert.NoError(s.T(), try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)))
|
||||
|
||||
// This simulates a ResponseHeaderTimeout.
|
||||
response, err = http.Get("http://127.0.0.1:8000/responseHeaderTimeout?sleep=1000")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusGatewayTimeout, response.StatusCode)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ import (
|
|||
"crypto/tls"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -19,20 +21,30 @@ const (
|
|||
|
||||
type TLSClientHeadersSuite struct{ BaseSuite }
|
||||
|
||||
func (s *TLSClientHeadersSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "tlsclientheaders")
|
||||
s.composeUp(c)
|
||||
func TestTLSClientHeadersSuite(t *testing.T) {
|
||||
suite.Run(t, new(TLSClientHeadersSuite))
|
||||
}
|
||||
|
||||
func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
||||
rootCertContent, err := os.ReadFile(rootCertPath)
|
||||
c.Assert(err, check.IsNil)
|
||||
serverCertContent, err := os.ReadFile(certPemPath)
|
||||
c.Assert(err, check.IsNil)
|
||||
ServerKeyContent, err := os.ReadFile(certKeyPath)
|
||||
c.Assert(err, check.IsNil)
|
||||
func (s *TLSClientHeadersSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tlsclientheaders/simple.toml", struct {
|
||||
s.createComposeProject("tlsclientheaders")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *TLSClientHeadersSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TLSClientHeadersSuite) TestTLSClientHeaders() {
|
||||
rootCertContent, err := os.ReadFile(rootCertPath)
|
||||
assert.NoError(s.T(), err)
|
||||
serverCertContent, err := os.ReadFile(certPemPath)
|
||||
assert.NoError(s.T(), err)
|
||||
ServerKeyContent, err := os.ReadFile(certKeyPath)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
file := s.adaptFile("fixtures/tlsclientheaders/simple.toml", struct {
|
||||
RootCertContent string
|
||||
ServerCertContent string
|
||||
ServerKeyContent string
|
||||
|
@ -41,22 +53,17 @@ func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
|||
ServerCertContent: string(serverCertContent),
|
||||
ServerKeyContent: string(ServerKeyContent),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err = cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("PathPrefix(`/foo`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
request, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:8443/foo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
certificate, err := tls.LoadX509KeyPair(certPemPath, certKeyPath)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
|
@ -66,5 +73,5 @@ func (s *TLSClientHeadersSuite) TestTLSClientHeaders(c *check.C) {
|
|||
}
|
||||
|
||||
err = try.RequestWithTransport(request, 2*time.Second, tr, try.BodyContains("Forwarded-Tls-Client-Cert: MIIDNTCCAh0CFD0QQcHXUJuKwMBYDA+bBExVSP26MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazENMAsGA1UEAwwEcm9vdDAeFw0yMTAxMDgxNzQ0MjRaFw0zMTAxMDYxNzQ0MjRaMFgxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxFTATBgNVBAoMDFRyYWVmaWsgTGFiczEQMA4GA1UECwwHdHJhZWZpazEPMA0GA1UEAwwGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYK2z8gLPOfFLgXNWP2460aeJ9vrH47x/lhKLlv4amSDHDx8Cmz/6blOUM8XOfMRW1xx++AgChWN9dx/kf7G2xlA5grZxRvUQ6xj7AvFG9TQUA3muNh2hvm9c3IjaZBNKH27bRKuDIBvZBvXdX4NL/aaFy7w7v7IKxk8j4WkfB23sgyH43g4b7NqKHJugZiedFu5GALmtLbShVOFbjWcre7Wvatdw8dIBmiFJqZQT3UjIuGAgqczIShtLxo4V+XyVkIPmzfPrRV+4zoMFIFOIaj3syyxb4krPBtxhe7nz2cWvvq0wePB2y4YbAAoVY8NYpd5JsMFwZtG6Uk59ygv4QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDaPg69wNeFNFisfBJTrscqVCTW+B80gMhpLdxXD+KO0/Wgc5xpB/wLSirNtRQyxAa3+EEcIwJv/wdh8EyjlDLSpFm/8ghntrKhkOfIOPDFE41M5HNfx/Fuh5btKEenOL/XdapqtNUt2ZE4RrsfbL79sPYepa9kDUVi2mCbeH5ollZ0MDU68HpB2YwHbCEuQNk5W3pjYK2NaDkVnxTkfEDM1k+3QydO1lqB5JJmcrs59BEveTqaJ3eeh/0I4OOab6OkTTZ0JNjJp1573oxO+fce/bfGud8xHY5gSN9huU7U6RsgvO7Dhmal/sDNl8XC8oU90hVDVXZdA7ewh4jjaoIv"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -2,19 +2,24 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
type TracingSuite struct {
|
||||
BaseSuite
|
||||
whoamiIP string
|
||||
whoamiPort int
|
||||
tracerIP string
|
||||
whoamiIP string
|
||||
whoamiPort int
|
||||
tracerZipkinIP string
|
||||
tracerJaegerIP string
|
||||
}
|
||||
|
||||
func TestTracingSuite(t *testing.T) {
|
||||
suite.Run(t, new(TracingSuite))
|
||||
}
|
||||
|
||||
type TracingTemplate struct {
|
||||
|
@ -24,302 +29,264 @@ type TracingTemplate struct {
|
|||
TraceContextHeaderName string
|
||||
}
|
||||
|
||||
func (s *TracingSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "tracing")
|
||||
s.composeUp(c)
|
||||
func (s *TracingSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP(c, "whoami")
|
||||
s.createComposeProject("tracing")
|
||||
s.composeUp()
|
||||
|
||||
s.whoamiIP = s.getComposeServiceIP("whoami")
|
||||
s.whoamiPort = 80
|
||||
}
|
||||
|
||||
func (s *TracingSuite) startZipkin(c *check.C) {
|
||||
s.composeUp(c, "zipkin")
|
||||
s.tracerIP = s.getComposeServiceIP(c, "zipkin")
|
||||
func (s *TracingSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func (s *TracingSuite) startZipkin() {
|
||||
s.composeUp("zipkin")
|
||||
s.tracerZipkinIP = s.getComposeServiceIP("zipkin")
|
||||
|
||||
// Wait for Zipkin to turn ready.
|
||||
err := try.GetRequest("http://"+s.tracerIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestZipkinRateLimit(c *check.C) {
|
||||
s.startZipkin(c)
|
||||
// defer s.composeStop(c, "zipkin")
|
||||
func (s *TracingSuite) TestZipkinRateLimit() {
|
||||
s.startZipkin()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerZipkinIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// sleep for 4 seconds to be certain the configured time period has elapsed
|
||||
// then test another request and verify a 200 status code
|
||||
time.Sleep(4 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// continue requests at 3 second intervals to test the other rate limit time period
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestZipkinRetry(c *check.C) {
|
||||
s.startZipkin(c)
|
||||
defer s.composeStop(c, "zipkin")
|
||||
func (s *TracingSuite) TestZipkinRetry() {
|
||||
s.startZipkin()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: 81,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerZipkinIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestZipkinAuth(c *check.C) {
|
||||
s.startZipkin(c)
|
||||
defer s.composeStop(c, "zipkin")
|
||||
func (s *TracingSuite) TestZipkinAuth() {
|
||||
s.startZipkin()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-zipkin.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerZipkinIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("entrypoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("entrypoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) startJaeger(c *check.C) {
|
||||
s.composeUp(c, "jaeger", "whoami")
|
||||
s.tracerIP = s.getComposeServiceIP(c, "jaeger")
|
||||
func (s *TracingSuite) startJaeger() {
|
||||
s.composeUp("jaeger", "whoami")
|
||||
s.tracerJaegerIP = s.getComposeServiceIP("jaeger")
|
||||
|
||||
// Wait for Jaeger to turn ready.
|
||||
err := try.GetRequest("http://"+s.tracerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerRateLimit(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerRateLimit() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "uber-trace-id",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// sleep for 4 seconds to be certain the configured time period has elapsed
|
||||
// then test another request and verify a 200 status code
|
||||
time.Sleep(4 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// continue requests at 3 second intervals to test the other rate limit time period
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerRetry(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerRetry() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: 81,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "uber-trace-id",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerAuth(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerAuth() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "uber-trace-id",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerCustomHeader(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerCustomHeader() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
TraceContextHeaderName: "powpow",
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *TracingSuite) TestJaegerAuthCollector(c *check.C) {
|
||||
s.startJaeger(c)
|
||||
defer s.composeStop(c, "jaeger")
|
||||
func (s *TracingSuite) TestJaegerAuthCollector() {
|
||||
s.startJaeger()
|
||||
// defer s.composeStop(c, "jaeger")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/tracing/simple-jaeger-collector.toml", TracingTemplate{
|
||||
file := s.adaptFile("fixtures/tracing/simple-jaeger-collector.toml", TracingTemplate{
|
||||
WhoamiIP: s.whoamiIP,
|
||||
WhoamiPort: s.whoamiPort,
|
||||
IP: s.tracerIP,
|
||||
IP: s.tracerJaegerIP,
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
|
|
@ -3,20 +3,32 @@ package integration
|
|||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
type UDPSuite struct{ BaseSuite }
|
||||
|
||||
func (s *UDPSuite) SetUpSuite(c *check.C) {
|
||||
s.createComposeProject(c, "udp")
|
||||
s.composeUp(c)
|
||||
func TestUDPSuite(t *testing.T) {
|
||||
suite.Run(t, new(UDPSuite))
|
||||
}
|
||||
|
||||
func (s *UDPSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("udp")
|
||||
s.composeUp()
|
||||
}
|
||||
|
||||
func (s *UDPSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
func guessWhoUDP(addr string) (string, error) {
|
||||
|
@ -46,39 +58,33 @@ func guessWhoUDP(addr string) (string, error) {
|
|||
return string(out[:n]), nil
|
||||
}
|
||||
|
||||
func (s *UDPSuite) TestWRR(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/udp/wrr.toml", struct {
|
||||
func (s *UDPSuite) TestWRR() {
|
||||
file := s.adaptFile("fixtures/udp/wrr.toml", struct {
|
||||
WhoamiAIP string
|
||||
WhoamiBIP string
|
||||
WhoamiCIP string
|
||||
WhoamiDIP string
|
||||
}{
|
||||
WhoamiAIP: s.getComposeServiceIP(c, "whoami-a"),
|
||||
WhoamiBIP: s.getComposeServiceIP(c, "whoami-b"),
|
||||
WhoamiCIP: s.getComposeServiceIP(c, "whoami-c"),
|
||||
WhoamiDIP: s.getComposeServiceIP(c, "whoami-d"),
|
||||
WhoamiAIP: s.getComposeServiceIP("whoami-a"),
|
||||
WhoamiBIP: s.getComposeServiceIP("whoami-b"),
|
||||
WhoamiCIP: s.getComposeServiceIP("whoami-c"),
|
||||
WhoamiDIP: s.getComposeServiceIP("whoami-d"),
|
||||
})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("whoami-a"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("whoami-a"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8093/who", 5*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
stop := make(chan struct{})
|
||||
go func() {
|
||||
call := map[string]int{}
|
||||
for i := 0; i < 8; i++ {
|
||||
out, err := guessWhoUDP("127.0.0.1:8093")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
switch {
|
||||
case strings.Contains(out, "whoami-a"):
|
||||
call["whoami-a"]++
|
||||
|
@ -90,13 +96,13 @@ func (s *UDPSuite) TestWRR(c *check.C) {
|
|||
call["unknown"]++
|
||||
}
|
||||
}
|
||||
c.Assert(call, checker.DeepEquals, map[string]int{"whoami-a": 3, "whoami-b": 2, "whoami-c": 3})
|
||||
assert.EqualValues(s.T(), call, map[string]int{"whoami-a": 3, "whoami-b": 2, "whoami-c": 3})
|
||||
close(stop)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-stop:
|
||||
case <-time.Tick(5 * time.Second):
|
||||
c.Error("Timeout")
|
||||
log.WithoutContext().Info("Timeout")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,19 +8,25 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
gorillawebsocket "github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// WebsocketSuite tests suite.
|
||||
type WebsocketSuite struct{ BaseSuite }
|
||||
|
||||
func (s *WebsocketSuite) TestBase(c *check.C) {
|
||||
func TestWebsocketSuite(t *testing.T) {
|
||||
suite.Run(t, new(WebsocketSuite))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestBase() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -41,36 +47,30 @@ func (s *WebsocketSuite) TestBase(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestWrongOrigin(c *check.C) {
|
||||
func (s *WebsocketSuite) TestWrongOrigin() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -91,35 +91,28 @@ func (s *WebsocketSuite) TestWrongOrigin(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:800")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
_, err = websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(err, checker.ErrorMatches, "bad status")
|
||||
assert.ErrorContains(s.T(), err, "bad status")
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestOrigin(c *check.C) {
|
||||
func (s *WebsocketSuite) TestOrigin() {
|
||||
// use default options
|
||||
upgrader := gorillawebsocket.Upgrader{}
|
||||
|
||||
|
@ -141,44 +134,38 @@ func (s *WebsocketSuite) TestOrigin(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:8000")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
client, err := websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
n, err := client.Write([]byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
|
||||
msg := make([]byte, 2)
|
||||
n, err = client.Read(msg)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestWrongOriginIgnoredByServer(c *check.C) {
|
||||
func (s *WebsocketSuite) TestWrongOriginIgnoredByServer() {
|
||||
upgrader := gorillawebsocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
}}
|
||||
|
@ -201,44 +188,38 @@ func (s *WebsocketSuite) TestWrongOriginIgnoredByServer(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:80")
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
client, err := websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
n, err := client.Write([]byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
|
||||
msg := make([]byte, 2)
|
||||
n, err = client.Read(msg)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestSSLTermination(c *check.C) {
|
||||
func (s *WebsocketSuite) TestSSLTermination() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -258,44 +239,38 @@ func (s *WebsocketSuite) TestSSLTermination(c *check.C) {
|
|||
}
|
||||
}
|
||||
}))
|
||||
file := s.adaptFile(c, "fixtures/websocket/config_https.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config_https.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Add client self-signed cert
|
||||
roots := x509.NewCertPool()
|
||||
certContent, err := os.ReadFile("./resources/tls/local.cert")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
roots.AppendCertsFromPEM(certContent)
|
||||
gorillawebsocket.DefaultDialer.TLSClientConfig = &tls.Config{
|
||||
RootCAs: roots,
|
||||
}
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("wss://127.0.0.1:8000/ws", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestBasicAuth(c *check.C) {
|
||||
func (s *WebsocketSuite) TestBasicAuth() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -306,8 +281,8 @@ func (s *WebsocketSuite) TestBasicAuth(c *check.C) {
|
|||
defer conn.Close()
|
||||
|
||||
user, password, _ := r.BasicAuth()
|
||||
c.Assert(user, check.Equals, "traefiker")
|
||||
c.Assert(password, check.Equals, "secret")
|
||||
assert.Equal(s.T(), "traefiker", user)
|
||||
assert.Equal(s.T(), "secret", password)
|
||||
|
||||
for {
|
||||
mt, message, err := conn.ReadMessage()
|
||||
|
@ -320,78 +295,66 @@ func (s *WebsocketSuite) TestBasicAuth(c *check.C) {
|
|||
}
|
||||
}
|
||||
}))
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
config, err := websocket.NewConfig("ws://127.0.0.1:8000/ws", "ws://127.0.0.1:8000")
|
||||
auth := "traefiker:secret"
|
||||
config.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth)))
|
||||
|
||||
c.Assert(err, check.IsNil)
|
||||
assert.NoError(s.T(), err)
|
||||
|
||||
conn, err := net.DialTimeout("tcp", "127.0.0.1:8000", time.Second)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
client, err := websocket.NewClient(config, conn)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
n, err := client.Write([]byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
|
||||
msg := make([]byte, 2)
|
||||
n, err = client.Read(msg)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(n, checker.Equals, 2)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), 2, n)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestSpecificResponseFromBackend(c *check.C) {
|
||||
func (s *WebsocketSuite) TestSpecificResponseFromBackend() {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
}))
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, resp, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws", nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(resp.StatusCode, check.Equals, http.StatusUnauthorized)
|
||||
assert.Error(s.T(), err)
|
||||
assert.Equal(s.T(), http.StatusUnauthorized, resp.StatusCode)
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestURLWithURLEncodedChar(c *check.C) {
|
||||
func (s *WebsocketSuite) TestURLWithURLEncodedChar() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
c.Assert(r.URL.EscapedPath(), check.Equals, "/ws/http%3A%2F%2Ftest")
|
||||
assert.Equal(s.T(), "/ws/http%3A%2F%2Ftest", r.URL.EscapedPath())
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -409,36 +372,30 @@ func (s *WebsocketSuite) TestURLWithURLEncodedChar(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws/http%3A%2F%2Ftest", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestSSLhttp2(c *check.C) {
|
||||
func (s *WebsocketSuite) TestSSLhttp2() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -463,48 +420,42 @@ func (s *WebsocketSuite) TestSSLhttp2(c *check.C) {
|
|||
ts.TLS.NextProtos = append(ts.TLS.NextProtos, `h2`, `http/1.1`)
|
||||
ts.StartTLS()
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config_https.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config_https.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: ts.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG", "--accesslog")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG", "--accesslog")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// Add client self-signed cert
|
||||
roots := x509.NewCertPool()
|
||||
certContent, err := os.ReadFile("./resources/tls/local.cert")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
roots.AppendCertsFromPEM(certContent)
|
||||
gorillawebsocket.DefaultDialer.TLSClientConfig = &tls.Config{
|
||||
RootCAs: roots,
|
||||
}
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("wss://127.0.0.1:8000/echo", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
||||
func (s *WebsocketSuite) TestHeaderAreForwarded(c *check.C) {
|
||||
func (s *WebsocketSuite) TestHeaderAreForwarded() {
|
||||
upgrader := gorillawebsocket.Upgrader{} // use default options
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
c.Assert(r.Header.Get("X-Token"), check.Equals, "my-token")
|
||||
assert.Equal(s.T(), "my-token", r.Header.Get("X-Token"))
|
||||
c, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -522,33 +473,27 @@ func (s *WebsocketSuite) TestHeaderAreForwarded(c *check.C) {
|
|||
}
|
||||
}))
|
||||
|
||||
file := s.adaptFile(c, "fixtures/websocket/config.toml", struct {
|
||||
file := s.adaptFile("fixtures/websocket/config.toml", struct {
|
||||
WebsocketServer string
|
||||
}{
|
||||
WebsocketServer: srv.URL,
|
||||
})
|
||||
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file), "--log.level=DEBUG")
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 10*time.Second, try.BodyContains("127.0.0.1"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
headers := http.Header{}
|
||||
headers.Add("X-Token", "my-token")
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial("ws://127.0.0.1:8000/ws", headers)
|
||||
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
err = conn.WriteMessage(gorillawebsocket.TextMessage, []byte("OK"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
_, msg, err := conn.ReadMessage()
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(msg), checker.Equals, "OK")
|
||||
require.NoError(s.T(), err)
|
||||
assert.Equal(s.T(), "OK", string(msg))
|
||||
}
|
||||
|
|
|
@ -8,16 +8,18 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-check/check"
|
||||
"github.com/kvtools/valkeyrie"
|
||||
"github.com/kvtools/valkeyrie/store"
|
||||
"github.com/kvtools/zookeeper"
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/traefik/traefik/v2/integration/try"
|
||||
"github.com/traefik/traefik/v2/pkg/api"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
)
|
||||
|
||||
// Zk test suites.
|
||||
|
@ -27,11 +29,17 @@ type ZookeeperSuite struct {
|
|||
zookeeperAddr string
|
||||
}
|
||||
|
||||
func (s *ZookeeperSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "zookeeper")
|
||||
s.composeUp(c)
|
||||
func TestZookeeperSuite(t *testing.T) {
|
||||
suite.Run(t, new(ZookeeperSuite))
|
||||
}
|
||||
|
||||
s.zookeeperAddr = net.JoinHostPort(s.getComposeServiceIP(c, "zookeeper"), "2181")
|
||||
func (s *ZookeeperSuite) SetupSuite() {
|
||||
s.BaseSuite.SetupSuite()
|
||||
|
||||
s.createComposeProject("zookeeper")
|
||||
s.composeUp()
|
||||
|
||||
s.zookeeperAddr = net.JoinHostPort(s.getComposeServiceIP("zookeeper"), "2181")
|
||||
|
||||
var err error
|
||||
s.kvClient, err = valkeyrie.NewStore(
|
||||
|
@ -42,20 +50,19 @@ func (s *ZookeeperSuite) setupStore(c *check.C) {
|
|||
ConnectionTimeout: 10 * time.Second,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Fatal("Cannot create store zookeeper")
|
||||
}
|
||||
require.NoError(s.T(), err, "Cannot create store zookeeper")
|
||||
|
||||
// wait for zk
|
||||
err = try.Do(60*time.Second, try.KVExists(s.kvClient, "test"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
|
||||
s.setupStore(c)
|
||||
func (s *ZookeeperSuite) TearDownSuite() {
|
||||
s.BaseSuite.TearDownSuite()
|
||||
}
|
||||
|
||||
file := s.adaptFile(c, "fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{s.zookeeperAddr})
|
||||
defer os.Remove(file)
|
||||
func (s *ZookeeperSuite) TestSimpleConfiguration() {
|
||||
file := s.adaptFile("fixtures/zookeeper/simple.toml", struct{ ZkAddress string }{s.zookeeperAddr})
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
|
@ -105,39 +112,35 @@ func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
|
|||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(context.Background(), k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second,
|
||||
try.BodyContains(`"striper@zookeeper":`, `"compressor@zookeeper":`, `"srvcA@zookeeper":`, `"srvcB@zookeeper":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
resp, err := http.Get("http://127.0.0.1:8080/api/rawdata")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
var obtained api.RunTimeRepresentation
|
||||
err = json.NewDecoder(resp.Body).Decode(&obtained)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
got, err := json.MarshalIndent(obtained, "", " ")
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
expectedJSON := filepath.FromSlash("testdata/rawdata-zk.json")
|
||||
|
||||
if *updateExpected {
|
||||
err = os.WriteFile(expectedJSON, got, 0o666)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(expectedJSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
if !bytes.Equal(expected, got) {
|
||||
diff := difflib.UnifiedDiff{
|
||||
|
@ -149,7 +152,7 @@ func (s *ZookeeperSuite) TestSimpleConfiguration(c *check.C) {
|
|||
}
|
||||
|
||||
text, err := difflib.GetUnifiedDiffString(diff)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Error(text)
|
||||
require.NoError(s.T(), err)
|
||||
log.WithoutContext().Info(text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ set -e -o pipefail
|
|||
|
||||
source /go/src/k8s.io/code-generator/kube_codegen.sh
|
||||
|
||||
git config --global --add safe.directory /go/src/${PROJECT_MODULE}
|
||||
git config --global --add safe.directory "/go/src/${PROJECT_MODULE}"
|
||||
|
||||
rm -rf "/go/src/${PROJECT_MODULE}/${MODULE_VERSION}"
|
||||
mkdir -p "/go/src/${PROJECT_MODULE}/${MODULE_VERSION}/"
|
||||
|
|
|
@ -3,18 +3,9 @@ set -e
|
|||
|
||||
export DEST=.
|
||||
|
||||
TESTFLAGS+=("-test.timeout=20m" -check.v)
|
||||
|
||||
if [ -n "${VERBOSE}" ]; then
|
||||
TESTFLAGS+=(-v)
|
||||
elif [ -n "${VERBOSE_INTEGRATION}" ]; then
|
||||
TESTFLAGS+=(-v)
|
||||
fi
|
||||
|
||||
cd integration
|
||||
echo "Testing against..."
|
||||
docker version
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
# shellcheck disable=SC2048
|
||||
CGO_ENABLED=0 go test -integration ${TESTFLAGS[*]}
|
||||
go test ./integration -test.timeout=20m -failfast -v ${TESTFLAGS[*]}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
golangci-lint run
|
||||
golangci-lint run
|
||||
|
|
Loading…
Reference in a new issue