diff --git a/.aspell.yml b/.aspell.yml new file mode 100644 index 00000000..afcc5295 --- /dev/null +++ b/.aspell.yml @@ -0,0 +1,33 @@ +mode: commit +min_length: 3 +allowed: + - aspell + - repo + - yaml + - config + - Github + - Gitlab + - env + - failsafe + - golang + - mkdir + - WORKDIR + - apk + - ENTRYPOINT + - ubuntu + - golangci + - sudo + - releaser + - backend + - backends + - frontend + - frontends + - tcp + - crd + - linter + - linters + - govulncheck + - dataplaneapi + - quic + - userlist + - cve diff --git a/.github/workflows/.goreleaser.yml b/.github/workflows/.goreleaser.yml index 85bc5876..013845cb 100644 --- a/.github/workflows/.goreleaser.yml +++ b/.github/workflows/.goreleaser.yml @@ -18,10 +18,10 @@ jobs: go-version-file: 'go.mod' check-latest: true - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4 + uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser version: latest - args: release --clean --skip-announce + args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 2c164208..7068f888 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,4 +1,4 @@ -name: Commit subject +name: HAProxy check commit message on: pull_request: branches: @@ -7,7 +7,7 @@ jobs: check: runs-on: ubuntu-latest steps: - - name: check-commit - uses: docker://haproxytech/check-commit:v2.1.0 + - name: commit-policy + uses: docker://ghcr.io/haproxytech/commit-check:5.0.4 env: API_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 944d0d66..8f7131a1 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -8,7 +8,7 @@ jobs: name: HAProxy strategy: matrix: - haproxy_version: ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7"] + haproxy_version: ["2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "2.8", "2.9"] runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory diff --git a/.github/workflows/manual_goreleaser.yml b/.github/workflows/manual_goreleaser.yml index 47fd76af..10fd578a 100644 --- a/.github/workflows/manual_goreleaser.yml +++ b/.github/workflows/manual_goreleaser.yml @@ -19,10 +19,10 @@ jobs: run: | git checkout $(git describe --tags --abbrev=0) - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4 + uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser version: latest - args: release --clean --skip-announce + args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index ddef4a60..cf3c6795 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ cmd/dataplaneapi/* .vscode/ .test/ bin/golangci-lint +bin/check-commit # ignore Goland ide config .idea diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f99ac1f0..7400af54 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,20 +1,22 @@ stages: - lint + - checks - build - e2e variables: DOCKER_HOST: tcp://docker:2375 - DOCKER_BASE_IMAGE: $CI_REGISTRY_GO/haproxy-alpine + DOCKER_BASE_IMAGE: $CI_REGISTRY_GO/haproxy-debian BATS_VERSION: v1.4.1 - GO_VERSION: '1.21' + GO_VERSION: "1.24" + DOCKER_VERSION: "26.0" diff: stage: lint image: - name: $CI_REGISTRY_GO/docker:stable-go$GO_VERSION - entrypoint: [ "" ] + name: $CI_REGISTRY_GO/docker:$DOCKER_VERSION-go$GO_VERSION + entrypoint: [""] services: - - name: $CI_REGISTRY_GO/docker:20.10.5-dind + - name: $CI_REGISTRY_GO/docker:$DOCKER_VERSION-dind alias: docker tags: - go @@ -56,10 +58,10 @@ gofumpt: script: - make gofumpt - test -z "$(git diff 2> /dev/null)" || exit 'Go code not formatted, issue \`make gofumpt\` and commit the result' -lint-commit-msg: +commit-policy: stage: lint image: - name: $CI_REGISTRY_GO/check-commit:v2.1.0 + name: $CI_REGISTRY_GO/commit-check:5.0.4 entrypoint: [""] tags: - go @@ -75,7 +77,7 @@ build: - build image: name: $CI_REGISTRY_GO/golang:$GO_VERSION - entrypoint: [ "" ] + entrypoint: [""] tags: - go script: @@ -92,10 +94,10 @@ build: paths: - build image: - name: $CI_REGISTRY_GO/docker:stable - entrypoint: [ "" ] + name: $CI_REGISTRY_GO/docker:$DOCKER_VERSION + entrypoint: [""] services: - - name: $CI_REGISTRY_GO/docker:20.10.5-dind + - name: $CI_REGISTRY_GO/docker:$DOCKER_VERSION-dind alias: docker variables: LOCAL_IP_ADDRESS: docker @@ -104,58 +106,62 @@ build: before_script: - apk add git bash curl jq git - git clone https://github.com/bats-core/bats-core.git && cd bats-core && git checkout $BATS_VERSION && ./install.sh /usr/local && cd .. - - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY_GO + - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY_GO script: - bash -x ./e2e/run.bash rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_PIPELINE_SOURCE == 'push' -HAProxy_2_1: - extends: .e2e - parallel: - matrix: - - TESTPART: [ "1/2", "2/2" ] - HAPROXY_VERSION: "2.1" +govulncheck: + stage: checks + needs: [] + image: + name: $CI_REGISTRY_GO/docker:$DOCKER_VERSION-go$GO_VERSION + entrypoint: [ "" ] + rules: + - if: $CI_PIPELINE_SOURCE == 'schedule' && $SCHEDULE_TYPE == 'daily' + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + - go.mod + - if: "$CI_PROJECT_NAMESPACE == 'haproxy-controller' && $CI_PIPELINE_SOURCE == 'push'" + changes: + - go.mod + tags: + - go + script: + - go install golang.org/x/vuln/cmd/govulncheck@latest + - govulncheck -version + - go mod tidy + - go run cmd/govulncheck-report/main.go + HAProxy_2_2: extends: .e2e parallel: matrix: - - TESTPART: [ "1/2", "2/2" ] + - TESTPART: ["1/2", "2/2"] HAPROXY_VERSION: "2.2" -HAProxy_2_3: - extends: .e2e - parallel: - matrix: - - TESTPART: [ "1/2", "2/2" ] - HAPROXY_VERSION: "2.3" HAProxy_2_4: extends: .e2e parallel: matrix: - - TESTPART: [ "1/2", "2/2" ] + - TESTPART: ["1/2", "2/2"] HAPROXY_VERSION: "2.4" -HAProxy_2_5: - extends: .e2e - parallel: - matrix: - - TESTPART: [ "1/2", "2/2" ] - HAPROXY_VERSION: "2.5" HAProxy_2_6: extends: .e2e parallel: matrix: - - TESTPART: [ "1/2", "2/2" ] + - TESTPART: ["1/2", "2/2"] HAPROXY_VERSION: "2.6" -HAProxy_2_7: +HAProxy_2_8: extends: .e2e parallel: matrix: - - TESTPART: [ "1/2", "2/2" ] - HAPROXY_VERSION: "2.7" -HAProxy_latest_dev: + - TESTPART: ["1/2", "2/2"] + HAPROXY_VERSION: "2.8" +HAProxy_2_9: extends: .e2e parallel: matrix: - - TESTPART: [ "1/2", "2/2" ] - HAPROXY_VERSION: "2.8" + - TESTPART: ["1/2", "2/2"] + HAPROXY_VERSION: "2.9" diff --git a/.golangci.yml b/.golangci.yml index ab4a15f2..74443872 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,6 @@ linters-settings: govet: - check-shadowing: true + shadow: true golint: min-confidence: 0 gocyclo: @@ -16,15 +16,14 @@ linters-settings: min-occurrences: 2 revive: rules: - - name: var-naming - severity: warning - disabled: true + - name: var-naming + severity: warning + disabled: true linters: enable-all: true disable: - dupl - exhaustive - - exhaustivestruct - funlen - gci - gochecknoglobals @@ -32,8 +31,6 @@ linters: - goconst - gocyclo - godot - - goerr113 - - gomnd - lll - nestif - nlreturn @@ -43,18 +40,9 @@ linters: - paralleltest - testpackage - varnamelen - - nosnakecase - exhaustruct - nonamedreturns - forcetypeassert - - golint #deprecated - - varcheck #deprecated - - ifshort #deprecated - - structcheck #deprecated - - maligned #deprecated - - scopelint #deprecated - - interfacer #deprecated - - deadcode #deprecated - rowserrcheck #rowserrcheck is disabled because of generics - sqlclosecheck #rowserrcheck is disabled because of generics - wastedassign #rowserrcheck is disabled because of generics @@ -73,14 +61,17 @@ linters: - gocritic - tagalign - depguard - + - mnd + - err113 + - tenv # deprecated + - recvcheck issues: exclude: # bugs of typecheck linter - "undeclared name: `shellquote`" - - "github.com/kballard/go-shellquote\" imported but not used" - - "github.com/haproxytech/config-parser/v5/types\" imported but not used" + - 'github.com/kballard/go-shellquote" imported but not used' + - 'github.com/haproxytech/client-native/v5/config-parser/types" imported but not used' exclude-rules: - linters: - staticcheck @@ -91,7 +82,5 @@ issues: - linters: - gosec text: "G[404]" - -run: - skip-dirs: + exclude-dirs: - test diff --git a/.goreleaser.yml b/.goreleaser.yml index a925a587..1f3b1ce5 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,4 +1,5 @@ --- +version: 2 before: hooks: - go mod download @@ -62,7 +63,7 @@ release: draft: true name_template: "HAProxy Data Plane API v{{.Version}}" nfpms: - - + - id: my-package package_name: dataplaneapi builds: diff --git a/Makefile b/Makefile index a3dc4814..3af00e31 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,8 @@ GIT_MODIFIED=${GIT_MODIFIED1}${GIT_MODIFIED2} SWAGGER_VERSION=${shell curl -s https://raw.githubusercontent.com/haproxytech/client-native/master/Makefile | grep SWAGGER_VERSION -m 1 | awk -F"=" '{print $$2}'} BUILD_DATE=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ') CGO_ENABLED?=0 -GOLANGCI_LINT_VERSION=1.54.2 +GOLANGCI_LINT_VERSION=1.64.5 +CHECK_COMMIT=5.0.4 all: update clean build @@ -19,7 +20,7 @@ update: .PHONY: lint lint: cd bin;GOLANGCI_LINT_VERSION=${GOLANGCI_LINT_VERSION} sh lint-check.sh - bin/golangci-lint run --timeout 5m --color always --max-issues-per-linter 0 --max-same-issues 0 + bin/golangci-lint run --timeout 10m --color always --max-issues-per-linter 0 --max-same-issues 0 .PHONY: gofumpt gofumpt: @@ -52,3 +53,12 @@ generate: generate-native: generate/swagger/script.sh generate/post_swagger.sh + +.PHONY: test +test: + go test ./... + +.PHONY: check-commit +check-commit: + cd bin;CHECK_COMMIT=${CHECK_COMMIT} sh check-commit.sh + bin/check-commit diff --git a/bin/check-commit.sh b/bin/check-commit.sh new file mode 100644 index 00000000..b7390b51 --- /dev/null +++ b/bin/check-commit.sh @@ -0,0 +1,9 @@ +#!/bin/sh +V=$(./check-commit tag) + +if echo "$V" | grep -q "v$CHECK_COMMIT"; then + echo "$V" +else + echo "go install github.com/haproxytech/check-commit/v5@v$CHECK_COMMIT" + GOBIN=$(pwd) go install github.com/haproxytech/check-commit/v5@v$CHECK_COMMIT +fi diff --git a/client-native/cn.go b/client-native/cn.go index 2afb9251..cda4e320 100644 --- a/client-native/cn.go +++ b/client-native/cn.go @@ -10,12 +10,12 @@ import ( clientnative "github.com/haproxytech/client-native/v5" "github.com/haproxytech/client-native/v5/models" + parser "github.com/haproxytech/client-native/v5/config-parser" + "github.com/haproxytech/client-native/v5/config-parser/types" "github.com/haproxytech/client-native/v5/configuration" configuration_options "github.com/haproxytech/client-native/v5/configuration/options" runtime_api "github.com/haproxytech/client-native/v5/runtime" runtime_options "github.com/haproxytech/client-native/v5/runtime/options" - parser "github.com/haproxytech/config-parser/v5" - "github.com/haproxytech/config-parser/v5/types" dataplaneapi_config "github.com/haproxytech/dataplaneapi/configuration" "github.com/haproxytech/dataplaneapi/log" @@ -76,6 +76,7 @@ func ConfigureRuntimeClient(ctx context.Context, confClient configuration.Config var runtimeClient runtime_api.Runtime _, globalConf, err := confClient.GetGlobalConfiguration("") + waitForRuntimeOption := runtime_options.AllowDelayedStart(haproxyOptions.DelayedStartMax, haproxyOptions.DelayedStartTick) // First try to setup master runtime socket if err == nil { @@ -87,7 +88,7 @@ func ConfigureRuntimeClient(ctx context.Context, confClient configuration.Config if globalConf.Nbproc > 0 { nbproc := int(globalConf.Nbproc) ms := runtime_options.MasterSocket(masterSocket, nbproc) - runtimeClient, err = runtime_api.New(ctx, mapsDir, ms) + runtimeClient, err = runtime_api.New(ctx, mapsDir, ms, waitForRuntimeOption) if err == nil { return runtimeClient } @@ -95,7 +96,7 @@ func ConfigureRuntimeClient(ctx context.Context, confClient configuration.Config } else { // if nbproc is not set, use master socket with 1 process ms := runtime_options.MasterSocket(masterSocket, 1) - runtimeClient, err = runtime_api.New(ctx, mapsDir, ms) + runtimeClient, err = runtime_api.New(ctx, mapsDir, ms, waitForRuntimeOption) if err == nil { return runtimeClient } @@ -110,7 +111,7 @@ func ConfigureRuntimeClient(ctx context.Context, confClient configuration.Config if misc.IsUnixSocketAddr(*r.Address) { sockets[1] = *r.Address socketsL := runtime_options.Sockets(sockets) - runtimeClient, err = runtime_api.New(ctx, mapsDir, socketsL) + runtimeClient, err = runtime_api.New(ctx, mapsDir, socketsL, waitForRuntimeOption) if err == nil { muSocketsList.Lock() socketsList = sockets @@ -124,7 +125,6 @@ func ConfigureRuntimeClient(ctx context.Context, confClient configuration.Config // else try to find process specific sockets and set them up sockets := make(map[int]string) for _, r := range runtimeAPIs { - //nolint:govet if misc.IsUnixSocketAddr(*r.Address) && r.Process != "" { process, err := strconv.ParseInt(r.Process, 10, 64) if err == nil { @@ -143,7 +143,7 @@ func ConfigureRuntimeClient(ctx context.Context, confClient configuration.Config } socketLst := runtime_options.Sockets(sockets) - runtimeClient, err = runtime_api.New(ctx, mapsDir, socketLst) + runtimeClient, err = runtime_api.New(ctx, mapsDir, socketLst, waitForRuntimeOption) if err == nil { return runtimeClient } diff --git a/cmd/govulncheck-report/main.go b/cmd/govulncheck-report/main.go new file mode 100644 index 00000000..39a46b09 --- /dev/null +++ b/cmd/govulncheck-report/main.go @@ -0,0 +1,362 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log/slog" + "net/http" + "net/url" + "os" + "os/exec" + "strconv" + "strings" +) + +type Note struct { + Body string `json:"body"` + ID int `json:"id"` +} + +type Issue struct { + Title string `json:"title"` + State string `json:"state"` + ID int `json:"id"` + IID int `json:"iid"` +} + +type Thread struct { + Body string `json:"body"` + ID int `json:"id"` + IID int `json:"iid"` +} + +const baseURL = "https://gitlab.int.haproxy.com/api/v4" + +func main() { + fmt.Print(hello) + logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ + AddSource: true, + ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { + if a.Key == "source" { + x := a.Value + src := x.Any().(*slog.Source) + path := strings.Split(src.File, "/") + src.File = path[len(path)-1] + return slog.Attr{ + Key: "source", + Value: slog.AnyValue(src), + } + } + return a + }, + })) + slog.SetDefault(logger) + + slog.Info("Starting GoVulnCheck") + mergeRequestMode := false + currentBranch := os.Getenv("CI_COMMIT_BRANCH") + if currentBranch == "" { + currentBranch = os.Getenv("CI_MERGE_REQUEST_SOURCE_BRANCH_NAME") + mergeRequestMode = true + } + if currentBranch == "" { + cmd := exec.Command("git", "branch", "--show-current") + out, err := cmd.Output() + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + currentBranch = string(out) + } + slog.Info("Current branch: " + currentBranch) + + cmd := exec.Command("govulncheck", "./...") + out, _ := cmd.Output() + + vulnMessage := string(out) + fmt.Println(vulnMessage) + noVuln := false + if !strings.Contains(vulnMessage, "Vulnerability #") { + noVuln = true + } + + if currentBranch == "" { + if strings.Contains(vulnMessage, "Vulnerability #") { + slog.Error(vulnMessage) + os.Exit(1) + } + slog.Info("Current branch is empty, exiting...") + os.Exit(0) + } + + if mergeRequestMode { + if strings.Contains(vulnMessage, "Vulnerability #") { + os.Exit(1) + } + slog.Info("no vulnerabilities found") + os.Exit(0) + } + + token := os.Getenv("GITLAB_GOPHERS_TOKEN") + projectID := "534" + title := "Data Plane API: GoVulnCheck: Branch: " + strings.Trim(currentBranch, "\n") + + userID, err := fetchUserID(token) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + issues, err := fetchOpenIssues(projectID, userID, token) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + found := false + var issueFound Issue + for _, issue := range issues { + if issue.Title == title && issue.State == "opened" { + found = true + issueFound = issue + break + } + } + vulnMessage = "```\n" + vulnMessage + "\n```" + if found { + if noVuln { + closeTheIssue(baseURL, token, projectID, issueFound.IID, "No vulnerability found.") + } else { + addCommentToIssue(baseURL, token, projectID, issueFound.IID, vulnMessage) + } + } else if !noVuln { + createIssue(baseURL, token, projectID, title, vulnMessage) + } + slog.Info("GoVulnCheck done.") +} + +func createIssue(baseURL, token, projectID string, title, commentBody string) { + slog.Info("Active issue with title '" + title + "' not found in project " + projectID) + // Create the issue here + issueData := map[string]interface{}{ + "title": title, + "description": commentBody, + "labels": "bot,critical", + // Add other fields as needed + } + issueDataBytes, err := json.Marshal(issueData) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/projects/%s/issues", baseURL, url.PathEscape(projectID)), bytes.NewBuffer(issueDataBytes)) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + req.Header.Add("Private-Token", token) + req.Header.Add("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + var issue Issue + err = json.Unmarshal(body, &issue) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + slog.Info("Issue created with ID " + strconv.Itoa(issue.ID)) +} + +func closeTheIssue(baseURL, token, projectID string, issueIID int, commentBody string) { + addCommentToIssue(baseURL, token, projectID, issueIID, commentBody) + + client := &http.Client{} + issueData := map[string]interface{}{ + "state_event": "close", + } + issueDataBytes, err := json.Marshal(issueData) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%s/projects/%s/issues/%d", baseURL, url.PathEscape(projectID), issueIID), bytes.NewBuffer(issueDataBytes)) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + req.Header.Add("Private-Token", token) + req.Header.Add("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + var issue Issue + err = json.Unmarshal(body, &issue) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + slog.Info("Issue " + strconv.Itoa(issue.IID) + " closed") +} + +func addCommentToIssue(baseURL, token, projectID string, issueIID int, commentBody string) { + client := &http.Client{} + noteData := map[string]interface{}{ + "body": commentBody, + } + noteDataBytes, err := json.Marshal(noteData) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/projects/%s/issues/%d/notes", baseURL, url.PathEscape(projectID), issueIID), bytes.NewBuffer(noteDataBytes)) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + req.Header.Add("Private-Token", token) + req.Header.Add("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + var note Note + err = json.Unmarshal(body, ¬e) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + + slog.Info("Comment added with ID " + strconv.Itoa(note.ID)) +} + +func fetchOpenIssues(projectID string, userID int, accessToken string) ([]Issue, error) { + perPage := 20 // Number of issues to fetch per page + + var allIssues []Issue + page := 1 + + for { + url := fmt.Sprintf("%s/projects/%s/issues?state=opened&author_id=%s&page=%d&per_page=%d", baseURL, projectID, strconv.Itoa(userID), page, perPage) + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Authorization", "Bearer "+accessToken) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var issues []Issue + err = json.Unmarshal(body, &issues) + if err != nil { + return nil, err + } + + allIssues = append(allIssues, issues...) + + // Check if there are more pages + linkHeader := resp.Header.Get("Link") + if !strings.Contains(linkHeader, `rel="next"`) { + break + } + + page++ + } + + return allIssues, nil +} + +func fetchUserID(accessToken string) (int, error) { + url := baseURL + "/user" + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return 0, err + } + + req.Header.Set("Authorization", "Bearer "+accessToken) + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return 0, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return 0, err + } + + var user struct { + ID int `json:"id"` + } + + err = json.Unmarshal(body, &user) + if err != nil { + return 0, err + } + + return user.ID, nil +} + +const hello = ` + _ _ _ + __ _ _____ ___ _| |_ __ ___| |__ ___ ___| | __ + / _` + "`" + ` |/ _ \ \ / / | | | | '_ \ / __| '_ \ / _ \/ __| |/ / +| (_| | (_) \ V /| |_| | | | | | (__| | | | __/ (__| < + \__, |\___/ \_/ \__,_|_|_| |_|\___|_| |_|\___|\___|_|\_\ + |___/ +` diff --git a/configuration/cluster_sync.go b/configuration/cluster_sync.go index b322c9f1..05348063 100644 --- a/configuration/cluster_sync.go +++ b/configuration/cluster_sync.go @@ -25,6 +25,7 @@ import ( "crypto/x509/pkix" "encoding/asn1" "encoding/pem" + "errors" "fmt" "io" "net/http" @@ -35,7 +36,7 @@ import ( "github.com/google/renameio" client_native "github.com/haproxytech/client-native/v5" - "github.com/haproxytech/config-parser/v5/types" + "github.com/haproxytech/client-native/v5/config-parser/types" jsoniter "github.com/json-iterator/go" "github.com/haproxytech/dataplaneapi/log" @@ -149,7 +150,7 @@ func (c *ClusterSync) issueRefreshRequest(url, port, basePath string, nodesPath req, err := http.NewRequest(http.MethodPatch, url, bytes.NewBuffer(bytesRepresentation)) if err != nil { - return fmt.Errorf("error creating new POST request for cluster comunication") + return errors.New("error creating new POST request for cluster comunication") } req.Header.Add("X-Node-Key", c.cfg.Cluster.Token.Load()) req.Header.Add("Content-Type", "application/json") @@ -248,6 +249,10 @@ func (c *ClusterSync) monitorBootstrapKey() { } c.cfg.Cluster.Name.Store(data["name"]) c.cfg.Cluster.Description.Store(data["description"]) + c.cfg.Cluster.StorageDir.Store(data["storage-dir"]) + c.cfg.Cluster.ClusterID.Store(data["cluster-id"]) + c.cfg.HAProxy.ClusterTLSCertDir = path.Join(data["storage-dir"], "certs-cluster") + c.cfg.Cluster.CertificateDir.Store(path.Join(data["storage-dir"], "certs-cluster")) c.cfg.Mode.Store(ModeCluster) err = c.cfg.Save() if err != nil { diff --git a/configuration/configuration.go b/configuration/configuration.go index 5ab12156..6bb4a202 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -24,6 +24,7 @@ import ( "path/filepath" "strings" "sync" + "time" petname "github.com/dustinkirkland/golang-petname" "github.com/haproxytech/client-native/v5/models" @@ -34,40 +35,42 @@ import ( var cfg *Configuration type HAProxyConfiguration struct { - SpoeDir string `long:"spoe-dir" description:"Path to SPOE directory." default:"/etc/haproxy/spoe" group:"resources"` - ServiceName string `long:"service" description:"Name of the HAProxy service" group:"reload"` - HAProxy string `short:"b" long:"haproxy-bin" description:"Path to the haproxy binary file" default:"haproxy" group:"haproxy"` - UserListFile string `long:"userlist-file" description:"Path to the dataplaneapi userlist file. By default userlist is read from HAProxy conf. When specified userlist would be read from this file" group:"userlist"` - ReloadCmd string `short:"r" long:"reload-cmd" description:"Reload command" group:"reload"` - RestartCmd string `short:"s" long:"restart-cmd" description:"Restart command" group:"reload"` - StatusCmd string `long:"status-cmd" description:"Status command" group:"reload"` - NodeIDFile string `long:"fid" description:"Path to file that will dataplaneapi use to write its id (not a pid) that was given to him after joining a cluster" group:"haproxy"` - PIDFile string `long:"pid-file" description:"Path to file that will dataplaneapi use to write its pid" group:"dataplaneapi" example:"/tmp/dataplane.pid"` - ReloadStrategy string `long:"reload-strategy" description:"Either systemd, s6 or custom" default:"custom" group:"reload"` - TransactionDir string `short:"t" long:"transaction-dir" description:"Path to the transaction directory" default:"/tmp/haproxy" group:"transaction"` - ValidateCmd string `long:"validate-cmd" description:"Executes a custom command to perform the HAProxy configuration check" group:"reload"` - BackupsDir string `long:"backups-dir" description:"Path to directory in which to place backup files" group:"transaction"` - MapsDir string `short:"p" long:"maps-dir" description:"Path to directory of map files managed by dataplane" default:"/etc/haproxy/maps" group:"resources"` - SpoeTransactionDir string `long:"spoe-transaction-dir" description:"Path to the SPOE transaction directory" default:"/tmp/spoe-haproxy" group:"resources"` - DataplaneConfig string `short:"f" description:"Path to the dataplane configuration file" default:"/etc/haproxy/dataplaneapi.yaml" yaml:"-"` - ConfigFile string `short:"c" long:"config-file" description:"Path to the haproxy configuration file" default:"/etc/haproxy/haproxy.cfg" group:"haproxy"` - Userlist string `short:"u" long:"userlist" description:"Userlist in HAProxy configuration to use for API Basic Authentication" default:"controller" group:"userlist"` - MasterRuntime string `short:"m" long:"master-runtime" description:"Path to the master Runtime API socket" group:"haproxy"` - SSLCertsDir string `long:"ssl-certs-dir" description:"Path to SSL certificates directory" default:"/etc/haproxy/ssl" group:"resources"` - GeneralStorageDir string `long:"general-storage-dir" description:"Path to general storage directory" default:"/etc/haproxy/general" group:"resources"` - ClusterTLSCertDir string `long:"cluster-tls-dir" description:"Path where cluster tls certificates will be stored. Defaults to same directory as dataplane configuration file" group:"cluster"` - UpdateMapFilesPeriod int64 `long:"update-map-files-period" description:"Elapsed time in seconds between two maps syncing operations" default:"10" group:"resources"` - ReloadDelay int `short:"d" long:"reload-delay" description:"Minimum delay between two reloads (in s)" default:"5" group:"reload"` - MaxOpenTransactions int64 `long:"max-open-transactions" description:"Limit for active transaction in pending state" default:"20" group:"transaction"` - BackupsNumber int `short:"n" long:"backups-number" description:"Number of backup configuration files you want to keep, stored in the config dir with version number suffix" default:"0" group:"transaction"` - ReloadRetention int `long:"reload-retention" description:"Reload retention in days, every older reload id will be deleted" default:"1" group:"reload"` - UID int `long:"uid" description:"User id value to set on start" group:"dataplaneapi" example:"1000"` - GID int `long:"gid" description:"Group id value to set on start" group:"dataplaneapi" example:"1000"` - UpdateMapFiles bool `long:"update-map-files" description:"Flag used for syncing map files with runtime maps values" group:"resources"` - ShowSystemInfo bool `short:"i" long:"show-system-info" description:"Show system info on info endpoint" group:"dataplaneapi"` - MasterWorkerMode bool `long:"master-worker-mode" description:"Flag to enable helpers when running within HAProxy" group:"haproxy"` - DisableInotify bool `long:"disable-inotify" description:"Disables inotify watcher for the configuration file" group:"dataplaneapi"` - DebugSocketPath string `long:"debug-socket-path" description:"Unix socket path for the debugging command socket" group:"dataplaneapi"` + SpoeDir string `long:"spoe-dir" description:"Path to SPOE directory." default:"/etc/haproxy/spoe" group:"resources"` + ServiceName string `long:"service" description:"Name of the HAProxy service" group:"reload"` + HAProxy string `short:"b" long:"haproxy-bin" description:"Path to the haproxy binary file" default:"haproxy" group:"haproxy"` + UserListFile string `long:"userlist-file" description:"Path to the dataplaneapi userlist file. By default userlist is read from HAProxy conf. When specified userlist would be read from this file" group:"userlist"` + ReloadCmd string `short:"r" long:"reload-cmd" description:"Reload command" group:"reload"` + RestartCmd string `short:"s" long:"restart-cmd" description:"Restart command" group:"reload"` + StatusCmd string `long:"status-cmd" description:"Status command" group:"reload"` + NodeIDFile string `long:"fid" description:"Path to file that will dataplaneapi use to write its id (not a pid) that was given to him after joining a cluster" group:"haproxy"` + PIDFile string `long:"pid-file" description:"Path to file that will dataplaneapi use to write its pid" group:"dataplaneapi" example:"/tmp/dataplane.pid"` + ReloadStrategy string `long:"reload-strategy" description:"Either systemd, s6 or custom" default:"custom" group:"reload"` + TransactionDir string `short:"t" long:"transaction-dir" description:"Path to the transaction directory" default:"/tmp/haproxy" group:"transaction"` + ValidateCmd string `long:"validate-cmd" description:"Executes a custom command to perform the HAProxy configuration check" group:"reload"` + BackupsDir string `long:"backups-dir" description:"Path to directory in which to place backup files" group:"transaction"` + MapsDir string `short:"p" long:"maps-dir" description:"Path to directory of map files managed by dataplane" default:"/etc/haproxy/maps" group:"resources"` + SpoeTransactionDir string `long:"spoe-transaction-dir" description:"Path to the SPOE transaction directory" default:"/tmp/spoe-haproxy" group:"resources"` + DataplaneConfig string `short:"f" description:"Path to the dataplane configuration file" default:"/etc/haproxy/dataplaneapi.yaml" yaml:"-"` + ConfigFile string `short:"c" long:"config-file" description:"Path to the haproxy configuration file" default:"/etc/haproxy/haproxy.cfg" group:"haproxy"` + Userlist string `short:"u" long:"userlist" description:"Userlist in HAProxy configuration to use for API Basic Authentication" default:"controller" group:"userlist"` + MasterRuntime string `short:"m" long:"master-runtime" description:"Path to the master Runtime API socket" group:"haproxy"` + SSLCertsDir string `long:"ssl-certs-dir" description:"Path to SSL certificates directory" default:"/etc/haproxy/ssl" group:"resources"` + GeneralStorageDir string `long:"general-storage-dir" description:"Path to general storage directory" default:"/etc/haproxy/general" group:"resources"` + ClusterTLSCertDir string `long:"cluster-tls-dir" description:"Path where cluster tls certificates will be stored. Defaults to same directory as dataplane configuration file" group:"cluster"` + UpdateMapFilesPeriod int64 `long:"update-map-files-period" description:"Elapsed time in seconds between two maps syncing operations" default:"10" group:"resources"` + ReloadDelay int `short:"d" long:"reload-delay" description:"Minimum delay between two reloads (in s)" default:"5" group:"reload"` + MaxOpenTransactions int64 `long:"max-open-transactions" description:"Limit for active transaction in pending state" default:"20" group:"transaction"` + BackupsNumber int `short:"n" long:"backups-number" description:"Number of backup configuration files you want to keep, stored in the config dir with version number suffix" default:"0" group:"transaction"` + ReloadRetention int `long:"reload-retention" description:"Reload retention in days, every older reload id will be deleted" default:"1" group:"reload"` + UID int `long:"uid" description:"User id value to set on start" group:"dataplaneapi" example:"1000"` + GID int `long:"gid" description:"Group id value to set on start" group:"dataplaneapi" example:"1000"` + UpdateMapFiles bool `long:"update-map-files" description:"Flag used for syncing map files with runtime maps values" group:"resources"` + ShowSystemInfo bool `short:"i" long:"show-system-info" description:"Show system info on info endpoint" group:"dataplaneapi"` + MasterWorkerMode bool `long:"master-worker-mode" description:"Flag to enable helpers when running within HAProxy" group:"haproxy"` + DisableInotify bool `long:"disable-inotify" description:"Disables inotify watcher for the configuration file" group:"dataplaneapi"` + DebugSocketPath string `long:"debug-socket-path" description:"Unix socket path for the debugging command socket" group:"dataplaneapi"` + DelayedStartMax time.Duration `long:"delayed-start-max" description:"Maximum duration to wait for the haproxy runtime socket to be ready" default:"30s" group:"haproxy"` + DelayedStartTick time.Duration `long:"delayed-start-tick" description:"Duration between checks for the haproxy runtime socket to be ready" default:"500ms" group:"haproxy"` } type User struct { diff --git a/configuration/configuration_storage.go b/configuration/configuration_storage.go index 588e1a71..3b1c3761 100644 --- a/configuration/configuration_storage.go +++ b/configuration/configuration_storage.go @@ -16,6 +16,8 @@ package configuration import ( + "time" + "github.com/haproxytech/client-native/v5/models" "github.com/jessevdk/go-flags" @@ -74,6 +76,8 @@ type configTypeHaproxy struct { NodeIDFile *string `yaml:"fid,omitempty"` MasterWorkerMode *bool `yaml:"master_worker_mode,omitempty"` Reload *configTypeReload `yaml:"reload,omitempty"` + DelayedStartMax *string `yaml:"delayed_start_max,omitempty"` + DelayedStartTick *string `yaml:"delayed_start_tick,omitempty"` } type configTypeUserlist struct { @@ -391,6 +395,16 @@ func copyToConfiguration(cfg *Configuration) { //nolint:cyclop,maintidx if cfgStorage.LogTargets != nil { cfg.LogTargets = *cfgStorage.LogTargets } + if cfgStorage.Dataplaneapi != nil && cfgStorage.Haproxy.DelayedStartMax != nil && !misc.HasOSArg("", "delayed-start-max", "") { + if d, err := time.ParseDuration(*cfgStorage.Haproxy.DelayedStartMax); err == nil { + cfg.HAProxy.DelayedStartMax = d + } + } + if cfgStorage.Dataplaneapi != nil && cfgStorage.Haproxy.DelayedStartTick != nil && !misc.HasOSArg("", "delayed-start-tick", "") { + if d, err := time.ParseDuration(*cfgStorage.Haproxy.DelayedStartTick); err == nil { + cfg.HAProxy.DelayedStartTick = d + } + } } func copyConfigurationToStorage(cfg *Configuration) { diff --git a/configuration/examples/example-full.yaml b/configuration/examples/example-full.yaml index 92acf832..d5674b2d 100644 --- a/configuration/examples/example-full.yaml +++ b/configuration/examples/example-full.yaml @@ -59,6 +59,8 @@ haproxy: master_runtime: null # string fid: null # string master_worker_mode: false # bool + delayed_start_max: 30s # time.Duration + delayed_start_tick: 500ms # time.Duration reload: reload_delay: 5 # int 2 reload_cmd: "systemctl reload haproxy" diff --git a/configuration/map_sync.go b/configuration/map_sync.go index e9b3aceb..0bdfd095 100644 --- a/configuration/map_sync.go +++ b/configuration/map_sync.go @@ -96,7 +96,7 @@ func (ms *MapSync) Sync(mp *models.Map, client client_native.HAProxyClient) (boo sort.Slice(fileEntries, func(i, j int) bool { return fileEntries[i].Key < fileEntries[j].Key }) // runtime map entries - id := fmt.Sprintf("#%s", mp.ID) + id := "#" + mp.ID runtimeEntries, err := runtime.ShowMapEntries(id) if err != nil { return false, fmt.Errorf("getting runtime entries error: id: %s %s", id, err.Error()) @@ -124,7 +124,7 @@ func equalSomeEntries(fEntries, rEntries models.MapEntries, index ...int) bool { return false } - max := 0 + maxNo := 0 switch l := len(rEntries); { case l > 19: for i := l - 20; i < l; i++ { @@ -132,21 +132,21 @@ func equalSomeEntries(fEntries, rEntries models.MapEntries, index ...int) bool { return false } } - max = l - 19 + maxNo = l - 19 case l == 0: return true default: - max = l + maxNo = l } maxRandom := 10 - if max < 10 { - maxRandom = max + if maxNo < 10 { + maxRandom = maxNo } - for i := 0; i < maxRandom; i++ { + for range maxRandom { // There's no need for strong number generation, here, just need for performance - r := rand.Intn(max) + r := rand.Intn(maxNo) if len(index) > 0 { r = index[0] } diff --git a/configuration/map_sync_test.go b/configuration/map_sync_test.go index e26a55e5..5c01d85a 100644 --- a/configuration/map_sync_test.go +++ b/configuration/map_sync_test.go @@ -23,7 +23,7 @@ import ( ) func data(differentAtIndex ...int) (fileEntries models.MapEntries, runtimeEntries models.MapEntries) { - for i := 0; i < 50; i++ { + for i := range 50 { fe := &models.MapEntry{Key: "k" + strconv.Itoa(i), Value: "v" + strconv.Itoa(i)} re := &models.MapEntry{Key: "k" + strconv.Itoa(i), Value: "v" + strconv.Itoa(i)} fileEntries = append(fileEntries, fe) diff --git a/configuration/misc.go b/configuration/misc.go index e3587daf..8d23c8d7 100644 --- a/configuration/misc.go +++ b/configuration/misc.go @@ -118,9 +118,6 @@ func CheckIfStorageDirIsOK(storageDir string, config *Configuration) error { return errStorage } } - config.Cluster.StorageDir.Store(storageDir) - config.HAProxy.ClusterTLSCertDir = path.Join(storageDir, "certs-cluster") - config.Cluster.CertificateDir.Store(path.Join(storageDir, "certs-cluster")) return nil } diff --git a/configuration/pid.go b/configuration/pid.go index 2c6a3352..68764246 100644 --- a/configuration/pid.go +++ b/configuration/pid.go @@ -16,7 +16,6 @@ package configuration import ( - "fmt" "os" "strconv" @@ -47,7 +46,7 @@ func HandlePIDFile(haproxyOptions HAProxyConfiguration) { } } - err := renameio.WriteFile(haproxyOptions.PIDFile, []byte(fmt.Sprintf("%d", os.Getpid())), 0o644) + err := renameio.WriteFile(haproxyOptions.PIDFile, []byte(strconv.Itoa(os.Getpid())), 0o644) if err != nil { log.Fatalf("error while writing PID file: %s %s", haproxyOptions.PIDFile, err.Error()) } else { diff --git a/configuration/reload-strategy.go b/configuration/reload-strategy.go index 834d1f1a..aee52635 100644 --- a/configuration/reload-strategy.go +++ b/configuration/reload-strategy.go @@ -15,7 +15,10 @@ package configuration -import "fmt" +import ( + "errors" + "fmt" +) const ( ReloadStratCustom = "custom" @@ -32,7 +35,7 @@ const ( s6ReloadCmd = "s6-svc -2" s6RestartCmd = "s6-svc -r" s6StatusCmd = "s6-svstat -u" - s6DefaultService = "/etc/service.d/haproxy" + s6DefaultService = "/var/run/service/haproxy" ) // Set a default value to a string. @@ -53,7 +56,7 @@ func validateReloadConfiguration(c *HAProxyConfiguration) error { case ReloadStratCustom: // The custom commands need to be set. if c.ReloadCmd == "" || c.RestartCmd == "" { - return fmt.Errorf("the custom reload strategy requires these options to be set: " + + return errors.New("the custom reload strategy requires these options to be set: " + "ReloadCmd, RestartCmd") } case ReloadStratS6: diff --git a/configuration/user.go b/configuration/user.go index 8f8632e0..8924f382 100644 --- a/configuration/user.go +++ b/configuration/user.go @@ -25,10 +25,10 @@ import ( "github.com/GehirnInc/crypt" api_errors "github.com/go-openapi/errors" - parser "github.com/haproxytech/config-parser/v5" - "github.com/haproxytech/config-parser/v5/common" - "github.com/haproxytech/config-parser/v5/options" - "github.com/haproxytech/config-parser/v5/types" + parser "github.com/haproxytech/client-native/v5/config-parser" + "github.com/haproxytech/client-native/v5/config-parser/common" + "github.com/haproxytech/client-native/v5/config-parser/options" + "github.com/haproxytech/client-native/v5/config-parser/types" "github.com/haproxytech/dataplaneapi/misc" ) @@ -176,7 +176,7 @@ func AuthenticateUser(user string, pass string) (interface{}, error) { if strings.HasPrefix(u.Password, "\"${") && strings.HasSuffix(u.Password, "}\"") { userPass = os.Getenv(misc.ExtractEnvVar(userPass)) if userPass == "" { - return nil, api_errors.New(401, fmt.Sprintf("%s %s", "can not read password from env variable:", u.Password)) + return nil, api_errors.New(401, "%s %s", "can not read password from env variable:", u.Password) } } @@ -184,12 +184,12 @@ func AuthenticateUser(user string, pass string) (interface{}, error) { if pass == userPass { return user, nil } - return nil, api_errors.New(401, fmt.Sprintf("%s %s", "invalid password:", pass)) + return nil, api_errors.New(401, "%s %s", "invalid password:", pass) } if checkPassword(pass, userPass) { return user, nil } - return nil, api_errors.New(401, fmt.Sprintf("%s %s", "invalid password:", pass)) + return nil, api_errors.New(401, "%s %s", "invalid password:", pass) } func checkPassword(pass, storedPass string) bool { diff --git a/configuration/watcher.go b/configuration/watcher.go index 8cd8e73c..39de16a3 100644 --- a/configuration/watcher.go +++ b/configuration/watcher.go @@ -18,7 +18,7 @@ package configuration import ( "context" "crypto/md5" - "fmt" + "encoding/hex" "os" "path/filepath" "strings" @@ -108,6 +108,6 @@ func (w *ConfigWatcher) invalidHash() bool { return true } bHash := md5.Sum([]byte(strings.Join(lines[1:], "\n"))) - hash := fmt.Sprintf("%x", bHash) + hash := hex.EncodeToString(bHash[:]) return parts[1] != hash } diff --git a/configure_data_plane.go b/configure_data_plane.go index 47a9e234..a35b72af 100644 --- a/configure_data_plane.go +++ b/configure_data_plane.go @@ -20,6 +20,7 @@ package dataplaneapi import ( "context" "crypto/tls" + "encoding/json" "io" "net/http" "os" @@ -56,8 +57,9 @@ import ( "github.com/haproxytech/dataplaneapi/operations" "github.com/haproxytech/dataplaneapi/operations/discovery" "github.com/haproxytech/dataplaneapi/operations/specification" - "github.com/haproxytech/dataplaneapi/operations/specification_openapiv3" + "github.com/haproxytech/dataplaneapi/operations/version3" "github.com/haproxytech/dataplaneapi/rate" + "github.com/haproxytech/dataplaneapi/resilient" socket_runtime "github.com/haproxytech/dataplaneapi/runtime" // import various crypting algorithms @@ -290,6 +292,7 @@ func configureAPI(api *operations.DataPlaneAPI) http.Handler { //nolint:cyclop,m }) // setup transaction handlers + client = resilient.NewClient(client) api.TransactionsStartTransactionHandler = &handlers.StartTransactionHandlerImpl{Client: client} api.TransactionsDeleteTransactionHandler = &handlers.DeleteTransactionHandlerImpl{Client: client} api.TransactionsGetTransactionHandler = &handlers.GetTransactionHandlerImpl{Client: client} @@ -701,7 +704,7 @@ func configureAPI(api *operations.DataPlaneAPI) http.Handler { //nolint:cyclop,m data.ID = service_discovery.NewServiceDiscoveryUUID() } if errSD = service_discovery.ValidateConsulData(data, true); errSD != nil { - log.Fatalf("Error validating Consul instance: " + errSD.Error()) + log.Fatal("Error validating Consul instance: " + errSD.Error()) } if errSD = discovery.AddNode("consul", *data.ID, data); errSD != nil { log.Warning("Error creating consul instance: " + errSD.Error()) @@ -717,7 +720,7 @@ func configureAPI(api *operations.DataPlaneAPI) http.Handler { //nolint:cyclop,m data.ID = service_discovery.NewServiceDiscoveryUUID() } if errSD = service_discovery.ValidateAWSData(data, true); errSD != nil { - log.Fatalf("Error validating AWS instance: " + errSD.Error()) + log.Fatal("Error validating AWS instance: " + errSD.Error()) } if errSD = discovery.AddNode("aws", *data.ID, data); errSD != nil { log.Warning("Error creating AWS instance: " + errSD.Error()) @@ -750,12 +753,16 @@ func configureAPI(api *operations.DataPlaneAPI) http.Handler { //nolint:cyclop,m api.StorageReplaceStorageGeneralFileHandler = &handlers.StorageReplaceStorageGeneralFileHandlerImpl{Client: client, ReloadAgent: ra} // setup OpenAPI v3 specification handler - api.SpecificationOpenapiv3GetOpenapiv3SpecificationHandler = specification_openapiv3.GetOpenapiv3SpecificationHandlerFunc(func(params specification_openapiv3.GetOpenapiv3SpecificationParams, principal interface{}) middleware.Responder { + api.Version3GetOpenapiv3SpecificationHandler = version3.GetOpenapiv3SpecificationHandlerFunc(func(params version3.GetOpenapiv3SpecificationParams, principal interface{}) middleware.Responder { v2 := openapi2.T{} - err = v2.UnmarshalJSON(SwaggerJSON) + v2JSONString := string(SwaggerJSON) + v2JSONString = strings.ReplaceAll(v2JSONString, "#/definitions", "#/components/schemas") + curatedV2 := json.RawMessage([]byte(v2JSONString)) + + err = v2.UnmarshalJSON(curatedV2) if err != nil { e := misc.HandleError(err) - return specification_openapiv3.NewGetOpenapiv3SpecificationDefault(int(*e.Code)).WithPayload(e) + return version3.NewGetOpenapiv3SpecificationDefault(int(*e.Code)).WithPayload(e) } // if host is empty(dynamic hosts), server prop is empty, @@ -769,9 +776,9 @@ func configureAPI(api *operations.DataPlaneAPI) http.Handler { //nolint:cyclop,m v3, err = openapi2conv.ToV3(&v2) if err != nil { e := misc.HandleError(err) - return specification_openapiv3.NewGetOpenapiv3SpecificationDefault(int(*e.Code)).WithPayload(e) + return version3.NewGetOpenapiv3SpecificationDefault(int(*e.Code)).WithPayload(e) } - return specification_openapiv3.NewGetOpenapiv3SpecificationOK().WithPayload(v3) + return version3.NewGetOpenapiv3SpecificationOK().WithPayload(v3) }) // TODO: do we need a ReloadAgent for SPOE @@ -1041,6 +1048,7 @@ func handleSignals(ctx context.Context, cancel context.CancelFunc, sigs chan os. reloadConfigurationFile(client, haproxyOptions, users) } case <-ctx.Done(): + cancel() return } } @@ -1049,10 +1057,10 @@ func handleSignals(ctx context.Context, cancel context.CancelFunc, sigs chan os. func reloadConfigurationFile(client client_native.HAProxyClient, haproxyOptions dataplaneapi_config.HAProxyConfiguration, users *dataplaneapi_config.Users) { confClient, err := cn.ConfigureConfigurationClient(haproxyOptions, mWorker) if err != nil { - log.Fatalf(err.Error()) + log.Fatal(err.Error()) } if err := users.Init(); err != nil { - log.Fatalf(err.Error()) + log.Fatal(err.Error()) } log.Info("Rereading Configuration Files") clientMutex.Lock() diff --git a/configure_data_plane_test.go b/configure_data_plane_test.go index eb99d7db..862f7e6a 100644 --- a/configure_data_plane_test.go +++ b/configure_data_plane_test.go @@ -18,6 +18,8 @@ package dataplaneapi import ( + "encoding/json" + "strings" "testing" "github.com/getkin/kin-openapi/openapi2" @@ -25,12 +27,17 @@ import ( ) func TestConvOpenAPIV2ToV3(t *testing.T) { + v2JSONString := string(SwaggerJSON) + v2JSONString = strings.ReplaceAll(v2JSONString, "#/definitions", "#/components/schemas") + curatedV2 := json.RawMessage([]byte(v2JSONString)) + var v2 openapi2.T - err := v2.UnmarshalJSON(SwaggerJSON) + err := v2.UnmarshalJSON(curatedV2) if err != nil { t.Error(err) return } + _, err = openapi2conv.ToV3(&v2) if err != nil { t.Error(err) diff --git a/discovery/aws_service_discovery_instance.go b/discovery/aws_service_discovery_instance.go index 855fbf41..6514a534 100644 --- a/discovery/aws_service_discovery_instance.go +++ b/discovery/aws_service_discovery_instance.go @@ -131,10 +131,9 @@ func newAWSRegionInstance(ctx context.Context, params *models.AwsRegion, client func (a *awsInstance) filterConverter(in []*models.AwsFilters) (out []types.Filter) { out = make([]types.Filter, len(in)) for i, l := range in { - filter := l out[i] = types.Filter{ - Name: filter.Key, - Values: []string{aws.ToString(filter.Value)}, + Name: l.Key, + Values: []string{aws.ToString(l.Value)}, } } return diff --git a/discovery/consul_service_discovery_instance.go b/discovery/consul_service_discovery_instance.go index 9649f9dd..c22df7a8 100644 --- a/discovery/consul_service_discovery_instance.go +++ b/discovery/consul_service_discovery_instance.go @@ -211,7 +211,7 @@ func (c *consulInstance) validateHealthChecks(node *serviceEntry) bool { } func (c *consulInstance) validateHealthChecksAny(node *serviceEntry) bool { - if node.Checks == nil || len(node.Checks) == 0 { + if len(node.Checks) == 0 { return false } @@ -224,7 +224,7 @@ func (c *consulInstance) validateHealthChecksAny(node *serviceEntry) bool { } func (c *consulInstance) validateHealthChecksAll(node *serviceEntry) bool { - if node.Checks == nil || len(node.Checks) == 0 { + if len(node.Checks) == 0 { return false } @@ -237,7 +237,7 @@ func (c *consulInstance) validateHealthChecksAll(node *serviceEntry) bool { } func (c *consulInstance) validateHealthChecksMin(node *serviceEntry) bool { - if node.Checks == nil || len(node.Checks) == 0 { + if len(node.Checks) == 0 { return false } @@ -327,7 +327,7 @@ func (c *consulInstance) queryHealthService(se string, params *queryParams) ([]* func (c *consulInstance) doConsulQuery(method string, path string, params *queryParams, resp interface{}) (*queryMetadata, error) { mode := "http://" if c.params.Mode != nil { - mode = fmt.Sprintf("%s://", *c.params.Mode) + mode = *c.params.Mode + "://" } fullPath, err := url.JoinPath( mode, diff --git a/discovery/store.go b/discovery/store.go index 4fdb2e51..9d052b3d 100644 --- a/discovery/store.go +++ b/discovery/store.go @@ -16,6 +16,7 @@ package discovery import ( + "errors" "fmt" "sync" ) @@ -72,7 +73,7 @@ func (s *instanceStore) Create(name string, service interface{}) error { defer s.mu.Unlock() if _, err := s.get(name); err == nil { - return fmt.Errorf("instance already exists") + return errors.New("instance already exists") } s.store[name] = service @@ -102,7 +103,7 @@ func (s *instanceStore) get(name string) (sd interface{}, err error) { var ok bool sd, ok = s.store[name] if !ok { - return nil, fmt.Errorf("instance not found") + return nil, errors.New("instance not found") } return } diff --git a/doc.go b/doc.go index a30e4dc2..f2d398ab 100644 --- a/doc.go +++ b/doc.go @@ -24,7 +24,7 @@ // https // Host: localhost // BasePath: /v2 -// Version: 2.8 +// Version: 2.9 // Contact: HAProxy Support https://my.haproxy.com/portal/cust/login // // Consumes: diff --git a/e2e/fixtures/dataplaneapi-master-socket.yaml b/e2e/fixtures/dataplaneapi-master-socket.yaml index ff9d574d..6b1d0c04 100644 --- a/e2e/fixtures/dataplaneapi-master-socket.yaml +++ b/e2e/fixtures/dataplaneapi-master-socket.yaml @@ -15,8 +15,8 @@ haproxy: master_runtime: /var/lib/haproxy/master master_worker_mode: true reload: - reload_cmd: kill -SIGUSR2 1 - restart_cmd: kill -SIGUSR2 1 + reload_cmd: kill -s 12 1 + restart_cmd: kill -s 12 1 log: log_to: file log_file: /var/log/dataplaneapi.log diff --git a/e2e/fixtures/dataplaneapi.yaml b/e2e/fixtures/dataplaneapi.yaml index e8ff21c8..377f4fa2 100644 --- a/e2e/fixtures/dataplaneapi.yaml +++ b/e2e/fixtures/dataplaneapi.yaml @@ -13,8 +13,8 @@ haproxy: config_file: /etc/haproxy/haproxy.cfg haproxy_bin: /usr/local/sbin/haproxy reload: - reload_cmd: kill -SIGUSR2 1 - restart_cmd: kill -SIGUSR2 1 + reload_cmd: kill -s 12 1 + restart_cmd: kill -s 12 1 log: log_to: file log_file: /var/log/dataplaneapi.log diff --git a/e2e/libs/haproxy_config_setup.bash b/e2e/libs/haproxy_config_setup.bash index 2fb80f5d..e0419555 100644 --- a/e2e/libs/haproxy_config_setup.bash +++ b/e2e/libs/haproxy_config_setup.bash @@ -29,27 +29,35 @@ setup() { skip fi + # replace the default haproxy config file local haproxy_cfg_file="${BATS_TEST_DIRNAME}/data/haproxy_*.cfg" local haproxy_file_version="" + local copy_haproxy_file=true if ls $haproxy_cfg_file 1> /dev/null 2>&1; then - haproxy_file_version=$(echo $haproxy_cfg_file | sed 's/.*_\([0-9]\+\.[0-9]\+\)\.cfg/\1/') + haproxy_file_version=$(echo $haproxy_cfg_file | sed 's/.*_\([0-9]\+\.[0-9]\+\)\.cfg/\1/') + major_file_version=$(echo $haproxy_file_version | cut -d '.' -f 1) + minor_file_version=$(echo $haproxy_file_version | cut -d '.' -f 2) + major_cfg_version=$(echo $HAPROXY_VERSION | cut -d '.' -f 1) + minor_cfg_version=$(echo $HAPROXY_VERSION | cut -d '.' -f 2) + if [[ -f "${BATS_TEST_DIRNAME}/data/haproxy_${haproxy_file_version}.cfg" ]] ; then + if [[ $major_cfg_version -eq $major_file_version && $minor_cfg_version -ge $minor_file_version || $major_cfg_version -gt $major_file_version ]] ; then + run docker cp "${BATS_TEST_DIRNAME}/data/haproxy_${haproxy_file_version}.cfg" "${DOCKER_CONTAINER_NAME}:/etc/haproxy/haproxy.cfg" + copy_haproxy_file=false + assert_success + fi + fi fi - major_file_version=$(echo $haproxy_file_version | cut -d '.' -f 1) - minor_file_version=$(echo $haproxy_file_version | cut -d '.' -f 2) - major_cfg_version=$(echo $HAPROXY_VERSION | cut -d '.' -f 1) - minor_cfg_version=$(echo $HAPROXY_VERSION | cut -d '.' -f 2) - - # replace the default haproxy config file - if [[ $major_cfg_version -ge $major_file_version && $minor_cfg_version -ge $minor_file_version ]] && [ -f "${BATS_TEST_DIRNAME}/data/haproxy_${haproxy_file_version}.cfg" ]; then - run docker cp "${BATS_TEST_DIRNAME}/data/haproxy_${haproxy_file_version}.cfg" "${DOCKER_CONTAINER_NAME}:/etc/haproxy/haproxy.cfg" - elif [ -f "${BATS_TEST_DIRNAME}/data/haproxy.cfg" ]; then - run docker cp "${BATS_TEST_DIRNAME}/data/haproxy.cfg" "${DOCKER_CONTAINER_NAME}:/etc/haproxy/haproxy.cfg" - else - run docker cp "${E2E_DIR}/fixtures/haproxy.cfg" "${DOCKER_CONTAINER_NAME}:/etc/haproxy/haproxy.cfg" + if [[ "$copy_haproxy_file" = true ]] ; then + if [ -f "${BATS_TEST_DIRNAME}/data/haproxy.cfg" ]; then + run docker cp "${BATS_TEST_DIRNAME}/data/haproxy.cfg" "${DOCKER_CONTAINER_NAME}:/etc/haproxy/haproxy.cfg" + assert_success + else + run docker cp "${E2E_DIR}/fixtures/haproxy.cfg" "${DOCKER_CONTAINER_NAME}:/etc/haproxy/haproxy.cfg" + assert_success + fi fi - assert_success # replace the default dataplaneapi config file if [ -f "${BATS_TEST_DIRNAME}/dataplaneapi.yaml" ]; then @@ -64,7 +72,7 @@ setup() { assert_success fi - run dpa_docker_exec 'kill -SIGUSR2 1' + run dpa_docker_exec 'kill -s 12 1' assert_success run dpa_docker_exec 'pkill -9 dataplaneapi' @@ -103,7 +111,7 @@ teardown() { run docker cp "${E2E_DIR}/fixtures/dataplaneapi.yaml" "${DOCKER_CONTAINER_NAME}:/etc/haproxy/dataplaneapi.yaml" assert_success - run dpa_docker_exec 'kill -SIGUSR2 1' + run dpa_docker_exec 'kill -s 12 1' assert_success run dpa_docker_exec 'pkill -9 dataplaneapi' diff --git a/e2e/libs/haproxy_version.bash b/e2e/libs/haproxy_version.bash index 8e10a250..3f7ff8df 100644 --- a/e2e/libs/haproxy_version.bash +++ b/e2e/libs/haproxy_version.bash @@ -27,12 +27,16 @@ # >>> 1 function haproxy_version_ge() { target=$1; shift - major_minor=$HAPROXY_VERSION - numerical_v="${major_minor//.}" - numerical_target="${target//.}" - if [ "$numerical_v" -ge "$numerical_target" ] - then + IFS='.' read -ra version_parts <<< "$HAPROXY_VERSION" + haproxy_major="${version_parts[0]}" + haproxy_minor="${version_parts[1]}" + + IFS='.' read -ra version_parts_target <<< "$target" + target_major="${version_parts_target[0]}" + target_minor="${version_parts_target[1]}" + + if [[ "$haproxy_major" -eq "$target_major" && "$haproxy_minor" -ge "$target_minor" || "$haproxy_major" -gt "$target_major" ]] ; then return 0 else return 1 diff --git a/e2e/libs/resource_client.bash b/e2e/libs/resource_client.bash index 4e2f21f8..a18db2a5 100644 --- a/e2e/libs/resource_client.bash +++ b/e2e/libs/resource_client.bash @@ -36,10 +36,9 @@ function resource_put() { } function resource_delete() { - local endpoint; endpoint="$1"; shift + local endpoint; endpoint="$1"; shift local qs_params; qs_params="$1" - - run dpa_curl DELETE "$endpoint?$qs_params&version=$(version)" "$data" + run dpa_curl DELETE "$endpoint?$qs_params&version=$(version)" assert_success dpa_curl_status_body '$output' } diff --git a/e2e/run.bash b/e2e/run.bash index c57cdab8..09032377 100755 --- a/e2e/run.bash +++ b/e2e/run.bash @@ -18,8 +18,8 @@ set -eo pipefail export BASE_PATH="/v2" -HAPROXY_VERSION=${HAPROXY_VERSION:-2.8} -DOCKER_BASE_IMAGE="${DOCKER_BASE_IMAGE:-haproxytech/haproxy-alpine}:${HAPROXY_VERSION}" +HAPROXY_VERSION=${HAPROXY_VERSION:-2.9} +DOCKER_BASE_IMAGE="${DOCKER_BASE_IMAGE:-haproxytech/haproxy-debian}:${HAPROXY_VERSION}" DOCKER_CONTAINER_NAME="dataplaneapi-e2e" export DOCKER_CONTAINER_NAME @@ -44,7 +44,11 @@ if [ ! -z $PREWIPE ] && [ "$PREWIPE" == "y" ]; then fi # Custom configuration to run tests with the master socket. -if [ $HAPROXY_VERSION = 2.7 ]; then +IFS='.' read -ra version_parts <<< "$HAPROXY_VERSION" +major="${version_parts[0]}" +minor="${version_parts[1]}" + +if [[ "$major" -eq "2" && "$minor" -ge "7" || "$major" -gt "2" ]] ; then HAPROXY_FLAGS="-W -db -S /var/lib/haproxy/master -f /usr/local/etc/haproxy/haproxy.cfg" VARIANT="-master-socket" fi @@ -58,6 +62,7 @@ else --detach \ --name ${DOCKER_CONTAINER_NAME} \ --publish "${E2E_PORT}":8080 \ + --security-opt seccomp=unconfined \ "${DOCKER_BASE_IMAGE}" $HAPROXY_FLAGS > /dev/null 2>&1 docker cp "${ROOT_DIR}/build/dataplaneapi" ${DOCKER_CONTAINER_NAME}:/usr/local/bin/dataplaneapi docker cp "${E2E_DIR}/fixtures/dataplaneapi${VARIANT}.yaml" ${DOCKER_CONTAINER_NAME}:/etc/haproxy/dataplaneapi.yaml diff --git a/e2e/tests/acl_files/acl_file_entries.bats b/e2e/tests/acl_files/acl_file_entries.bats index bd1858fb..9fdf1971 100644 --- a/e2e/tests/acl_files/acl_file_entries.bats +++ b/e2e/tests/acl_files/acl_file_entries.bats @@ -19,6 +19,7 @@ load '../../libs/dataplaneapi' load "../../libs/get_json_path" load '../../libs/haproxy_config_setup' load '../../libs/resource_client' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -55,6 +56,9 @@ load 'utils/_helpers' } @test "acl_runtime: Delete an ACL file entry by its ID" { + if haproxy_version_ge "2.9"; then + skip "cause: bug in HAPRoxy 2.9" + fi # checking items and retrieving first ID resource_get "$_RUNTIME_ACL_FILE_ENTRIES_BASE_PATH" "acl_id=1" assert_equal "$SC" 200 diff --git a/e2e/tests/binds/replace_2.8.bats b/e2e/tests/binds/replace_2.8.bats index e994f370..e3e4faa8 100644 --- a/e2e/tests/binds/replace_2.8.bats +++ b/e2e/tests/binds/replace_2.8.bats @@ -21,13 +21,14 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @test "binds: Replace a bind (>=2.8)" { if haproxy_version_ge "2.8" then - PUT_FILE="/data/put_2.8.son" + PUT_FILE="data/put_2.8.json" resource_put "$_BIND_BASE_PATH/fixture" "$PUT_FILE" "frontend=test_frontend&force_reload=true" assert_equal "$SC" 200 diff --git a/e2e/tests/global/get.bats b/e2e/tests/global/get.bats index 8454cb23..dd98f8b2 100644 --- a/e2e/tests/global/get.bats +++ b/e2e/tests/global/get.bats @@ -20,6 +20,7 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' diff --git a/e2e/tests/http_after_response_rules/delete.bats b/e2e/tests/http_after_response_rules/delete.bats index ff3369e5..643d4f60 100644 --- a/e2e/tests/http_after_response_rules/delete.bats +++ b/e2e/tests/http_after_response_rules/delete.bats @@ -20,6 +20,7 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -39,7 +40,7 @@ load 'utils/_helpers' resource_delete "$_RES_RULES_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" assert_equal "$SC" 204 # - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then # Deleting the third one # resource_delete "$_RES_RULES_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" diff --git a/e2e/tests/http_after_response_rules/list.bats b/e2e/tests/http_after_response_rules/list.bats index 919ebfc1..cd1ce32a 100644 --- a/e2e/tests/http_after_response_rules/list.bats +++ b/e2e/tests/http_after_response_rules/list.bats @@ -20,6 +20,7 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -30,7 +31,7 @@ load 'utils/_helpers' resource_get "$_RES_RULES_BASE_PATH" "parent_type=frontend&parent_name=test_frontend" assert_equal "$SC" 200 - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data | length")" 11 else assert_equal "$(get_json_path "$BODY" ".data | length")" 2 @@ -43,7 +44,7 @@ load 'utils/_helpers' assert_equal "$(get_json_path "$BODY" ".data[1].hdr_name")" "X-Del-Frontend" assert_equal "$(get_json_path "$BODY" ".data[1].cond")" "if" assert_equal "$(get_json_path "$BODY" ".data[1].cond_test")" "{ src 10.1.0.0/16 }" - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data[2].type")" "set-map" assert_equal "$(get_json_path "$BODY" ".data[2].map_file")" "map.lst" assert_equal "$(get_json_path "$BODY" ".data[2].map_keyfmt")" "%[src]" diff --git a/e2e/tests/http_request_rules/delete.bats b/e2e/tests/http_request_rules/delete.bats index bd8504db..5a21d6e2 100644 --- a/e2e/tests/http_request_rules/delete.bats +++ b/e2e/tests/http_request_rules/delete.bats @@ -20,6 +20,7 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -35,7 +36,7 @@ load 'utils/_helpers' resource_delete "$_REQ_RULES_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" assert_equal "$SC" 204 # - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then # Deleting third # resource_delete "$_REQ_RULES_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" diff --git a/e2e/tests/http_request_rules/list.bats b/e2e/tests/http_request_rules/list.bats index 8bccc833..f82bc82d 100644 --- a/e2e/tests/http_request_rules/list.bats +++ b/e2e/tests/http_request_rules/list.bats @@ -20,13 +20,14 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @test "http_request_rules: Return an array of all HTTP Request Rules from frontend" { resource_get "$_REQ_RULES_BASE_PATH" "parent_type=frontend&parent_name=test_frontend" assert_equal "$SC" 200 - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data | length")" 3 else assert_equal "$(get_json_path "$BODY" ".data | length")" 2 @@ -39,7 +40,7 @@ load 'utils/_helpers' assert_equal "$(get_json_path "$BODY" ".data[1].hdr_name")" "X-Del-Frontend" assert_equal "$(get_json_path "$BODY" ".data[1].cond")" "if" assert_equal "$(get_json_path "$BODY" ".data[1].cond_test")" "{ src 10.1.0.0/16 }" - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data[2].type")" "sc-add-gpc" assert_equal "$(get_json_path "$BODY" ".data[2].index")" "2" assert_equal "$(get_json_path "$BODY" ".data[2].sc_id")" "1" diff --git a/e2e/tests/http_response_rules/delete.bats b/e2e/tests/http_response_rules/delete.bats index 510d3c1d..ae928501 100644 --- a/e2e/tests/http_response_rules/delete.bats +++ b/e2e/tests/http_response_rules/delete.bats @@ -20,6 +20,7 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -35,7 +36,7 @@ load 'utils/_helpers' resource_delete "$_RES_RULES_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" assert_equal "$SC" 204 # - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then # Deleting the third one # resource_delete "$_RES_RULES_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" diff --git a/e2e/tests/http_response_rules/list.bats b/e2e/tests/http_response_rules/list.bats index c29bbc65..ee4b6a2d 100644 --- a/e2e/tests/http_response_rules/list.bats +++ b/e2e/tests/http_response_rules/list.bats @@ -20,13 +20,14 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @test "http_response_rules: Return an array of all HTTP Response Rules from frontend" { resource_get "$_RES_RULES_BASE_PATH" "parent_type=frontend&parent_name=test_frontend" assert_equal "$SC" 200 - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data | length")" 3 else assert_equal "$(get_json_path "$BODY" ".data | length")" 2 @@ -39,7 +40,7 @@ load 'utils/_helpers' assert_equal "$(get_json_path "$BODY" ".data[1].hdr_name")" "X-Del-Frontend" assert_equal "$(get_json_path "$BODY" ".data[1].cond")" "if" assert_equal "$(get_json_path "$BODY" ".data[1].cond_test")" "{ src 10.1.0.0/16 }" - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data[2].type")" "sc-add-gpc" assert_equal "$(get_json_path "$BODY" ".data[2].index")" "2" assert_equal "$(get_json_path "$BODY" ".data[2].sc_id")" "1" diff --git a/e2e/tests/process_manager/create.bats b/e2e/tests/process_manager/create.bats index 37a113e4..d0130b4d 100644 --- a/e2e/tests/process_manager/create.bats +++ b/e2e/tests/process_manager/create.bats @@ -30,8 +30,8 @@ load 'utils/_helpers' resource_get "$_PROGRAMS_BASE_PATH/test" assert_equal "$SC" 200 assert_equal "test" "$(get_json_path "$BODY" ".data.name")" - assert_equal "nobody" "$(get_json_path "$BODY" ".data.user")" - assert_equal "nobody" "$(get_json_path "$BODY" ".data.group")" + assert_equal "haproxy" "$(get_json_path "$BODY" ".data.user")" + assert_equal "haproxy" "$(get_json_path "$BODY" ".data.group")" } @test "process-manager: Fail creating program with same name" { diff --git a/e2e/tests/process_manager/data/program.json b/e2e/tests/process_manager/data/program.json index dce2f201..c07209ac 100644 --- a/e2e/tests/process_manager/data/program.json +++ b/e2e/tests/process_manager/data/program.json @@ -2,6 +2,6 @@ "name": "test", "command": "echo true", "start-on-reload": "disabled", - "user": "nobody", - "group": "nobody" + "user": "haproxy", + "group": "haproxy" } diff --git a/e2e/tests/rings/data/post-ring2.json b/e2e/tests/rings/data/post-ring2.json new file mode 100644 index 00000000..a6f9248c --- /dev/null +++ b/e2e/tests/rings/data/post-ring2.json @@ -0,0 +1,9 @@ +{ + "description": "My Second local buffer", + "format": "rfc3164", + "maxlen": 1200, + "name": "test_ring_2", + "size": 32764, + "timeout_connect": 5, + "timeout_server": 10 +} diff --git a/e2e/tests/rings/data/put.json b/e2e/tests/rings/data/put.json index eeff9761..84318520 100644 --- a/e2e/tests/rings/data/put.json +++ b/e2e/tests/rings/data/put.json @@ -2,7 +2,7 @@ "description": "My local buffer update", "format": "iso", "maxlen": 1400, - "name": "myring2", + "name": "test_ring", "size": 32740, "timeout_connect": 15, "timeout_server": 20 diff --git a/e2e/tests/rings/test.bats b/e2e/tests/rings/test.bats index 33f0fe92..9adfbc45 100644 --- a/e2e/tests/rings/test.bats +++ b/e2e/tests/rings/test.bats @@ -19,19 +19,23 @@ load '../../libs/dataplaneapi' load '../../libs/get_json_path' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @test "rings: Add a ring" { - if haproxy_version_ge "2.1" + if haproxy_version_ge "2.2" then resource_post "$_RING_BASE_PATH" "data/post.json" "force_reload=true" assert_equal "$SC" "201" + + resource_post "$_RING_BASE_PATH" "data/post-ring2.json" "force_reload=true" + assert_equal "$SC" "201" fi } @test "rings: Return a ring" { - if haproxy_version_ge "2.1" + if haproxy_version_ge "2.2" then resource_get "$_RING_BASE_PATH/test_ring" assert_equal "$SC" 200 @@ -40,7 +44,7 @@ load 'utils/_helpers' } @test "rings: Replace a ring" { - if haproxy_version_ge "2.1" + if haproxy_version_ge "2.2" then resource_put "$_RING_BASE_PATH/test_ring" "data/put.json" "force_reload=true" assert_equal "$SC" 200 @@ -48,16 +52,17 @@ load 'utils/_helpers' } @test "rings: Return an array of rings" { - if haproxy_version_ge "2.1" + if haproxy_version_ge "2.2" then resource_get "$_RING_BASE_PATH" assert_equal "$SC" 200 - assert_equal "test_ring" "$(get_json_path "$BODY" '.data[0].name')" + assert_equal "$(get_json_path "$BODY" ".data | length")" 2 + assert_equal "$(get_json_path "$BODY" ".data[] | select(.name | contains(\"test_ring_2\") ).name")" "test_ring_2" fi } @test "rings: Delete a ring" { - if haproxy_version_ge "2.1" + if haproxy_version_ge "2.2" then resource_delete "$_RING_BASE_PATH/test_ring" "force_reload=true" assert_equal "$SC" 204 diff --git a/e2e/tests/set_uid/dataplaneapi.yaml b/e2e/tests/set_uid/dataplaneapi.yaml index 0c9ce427..d8e66b35 100644 --- a/e2e/tests/set_uid/dataplaneapi.yaml +++ b/e2e/tests/set_uid/dataplaneapi.yaml @@ -15,5 +15,5 @@ haproxy: config_file: /home/testuiduser/haproxy.cfg haproxy_bin: /usr/local/sbin/haproxy reload: - reload_cmd: kill -SIGUSR2 1 - restart_cmd: kill -SIGUSR2 1 + reload_cmd: kill -s 12 1 + restart_cmd: kill -s 12 1 diff --git a/e2e/tests/set_uid/test.bats b/e2e/tests/set_uid/test.bats index a1c6171a..51f523db 100644 --- a/e2e/tests/set_uid/test.bats +++ b/e2e/tests/set_uid/test.bats @@ -18,7 +18,7 @@ load '../../libs/dataplaneapi' setup() { - run dpa_docker_exec 'kill -SIGUSR2 1' + run dpa_docker_exec 'kill -s 12 1' assert_success run dpa_docker_exec 'pkill -9 dataplaneapi' @@ -48,7 +48,7 @@ teardown() { run docker cp "${E2E_DIR}/fixtures/dataplaneapi.yaml" "${DOCKER_CONTAINER_NAME}:/usr/local/bin/dataplaneapi.yaml" assert_success - run dpa_docker_exec 'kill -SIGUSR2 1' + run dpa_docker_exec 'kill -s 12 1' assert_success run dpa_docker_exec 'pkill -9 dataplaneapi' @@ -62,7 +62,6 @@ teardown() { } @test "set_uid: check if running user is testuiduser for dataplane" { - PS=$(dpa_docker_exec "ps -eo ruser,user,comm | grep dataplaneapi") - echo $PS - [ "${PS}" = "testuidu testuidu dataplaneapi" ] + run dpa_docker_exec "ps -eo ruser,user,comm | grep dataplaneapi" + assert_output --regexp '^testuid.* testuid.* dataplaneapi$' } diff --git a/e2e/tests/storage_maps/test.bats b/e2e/tests/storage_maps/test.bats index 69f21963..84e82899 100644 --- a/e2e/tests/storage_maps/test.bats +++ b/e2e/tests/storage_maps/test.bats @@ -41,7 +41,7 @@ load 'utils/_helpers' # sometimes we can't establish a connection to the haproxy stat socket # forcing haproxy to restart seems to fix that - assert dpa_docker_exec 'kill -SIGUSR2 1' + assert dpa_docker_exec 'kill -s 12 1' sleep 1 resource_get "$_STORAGE_MAPS_BASE_PATH/" diff --git a/e2e/tests/tcp_request_rules/delete.bats b/e2e/tests/tcp_request_rules/delete.bats index bf4f9d3d..10c43c15 100644 --- a/e2e/tests/tcp_request_rules/delete.bats +++ b/e2e/tests/tcp_request_rules/delete.bats @@ -19,6 +19,7 @@ load '../../libs/dataplaneapi' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -29,7 +30,7 @@ load 'utils/_helpers' resource_delete "$_TCP_REQ_RULES_CERTS_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" assert_equal "$SC" 204 - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then resource_delete "$_TCP_REQ_RULES_CERTS_BASE_PATH/0" "parent_type=frontend&parent_name=test_frontend&force_reload=true" assert_equal "$SC" 204 diff --git a/e2e/tests/tcp_request_rules/list.bats b/e2e/tests/tcp_request_rules/list.bats index 6f0edda7..9df94f79 100644 --- a/e2e/tests/tcp_request_rules/list.bats +++ b/e2e/tests/tcp_request_rules/list.bats @@ -28,7 +28,7 @@ load 'utils/_helpers' resource_get "$_TCP_REQ_RULES_CERTS_BASE_PATH" "parent_type=frontend&parent_name=test_frontend" assert_equal "$SC" 200 - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "${BODY}" ".data | length")" 5 else assert_equal "$(get_json_path "${BODY}" ".data | length")" 2 @@ -36,7 +36,7 @@ load 'utils/_helpers' assert_equal "$(get_json_path "$BODY" ".data[0].type")" "inspect-delay" assert_equal "$(get_json_path "$BODY" ".data[1].type")" "content" assert_equal "$(get_json_path "$BODY" ".data[1].action")" "accept" - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data[2].type")" "connection" assert_equal "$(get_json_path "$BODY" ".data[2].action")" "sc-add-gpc" assert_equal "$(get_json_path "$BODY" ".data[3].type")" "session" diff --git a/e2e/tests/tcp_response_rules/delete.bats b/e2e/tests/tcp_response_rules/delete.bats index 4c0754c8..5850ba06 100644 --- a/e2e/tests/tcp_response_rules/delete.bats +++ b/e2e/tests/tcp_response_rules/delete.bats @@ -19,6 +19,7 @@ load '../../libs/dataplaneapi' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -29,10 +30,10 @@ load 'utils/_helpers' resource_delete "$_TCP_RES_RULES_CERTS_BASE_PATH/0" "backend=test_backend&force_reload=true" assert_equal "$SC" 204 - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then - resource_delete "$_TCP_RES_RULES_CERTS_BASE_PATH/0" "backend=test_backend&force_reload=true" - assert_equal "$SC" 204 - fi + if haproxy_version_ge "2.8"; then + resource_delete "$_TCP_RES_RULES_CERTS_BASE_PATH/0" "backend=test_backend&force_reload=true" + assert_equal "$SC" 204 + fi resource_delete "$_TCP_RES_RULES_CERTS_BASE_PATH/0" "backend=test_backend&force_reload=true" assert_equal "$SC" 404 diff --git a/e2e/tests/tcp_response_rules/list.bats b/e2e/tests/tcp_response_rules/list.bats index b051b9a6..abc2f8d4 100644 --- a/e2e/tests/tcp_response_rules/list.bats +++ b/e2e/tests/tcp_response_rules/list.bats @@ -20,6 +20,7 @@ load '../../libs/get_json_path' load '../../libs/haproxy_config_setup' load '../../libs/resource_client' load '../../libs/version' +load '../../libs/haproxy_version' load 'utils/_helpers' @@ -27,14 +28,14 @@ load 'utils/_helpers' resource_get "$_TCP_RES_RULES_CERTS_BASE_PATH" "backend=test_backend" assert_equal "$SC" 200 - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "${BODY}" ".data | length")" 3 else assert_equal "$(get_json_path "${BODY}" ".data | length")" 2 fi assert_equal "$(get_json_path "$BODY" ".data[] | select(.action | contains(\"accept\") ).action")" "accept" assert_equal "$(get_json_path "$BODY" ".data[] | select(.action | contains(\"reject\") ).action")" "reject" - if [[ "$HAPROXY_VERSION" == "2.8" ]]; then + if haproxy_version_ge "2.8"; then assert_equal "$(get_json_path "$BODY" ".data[] | select(.action | contains(\"sc-add-gpc\") ).action")" "sc-add-gpc" fi } diff --git a/embedded_spec.go b/embedded_spec.go index 4f7ab9ac..1cbd30e9 100644 --- a/embedded_spec.go +++ b/embedded_spec.go @@ -52,7 +52,7 @@ func init() { "url": "https://my.haproxy.com/portal/cust/login", "email": "support@haproxy.com" }, - "version": "2.8" + "version": "2.9" }, "basePath": "/v2", "paths": { @@ -16431,14 +16431,14 @@ func init() { "adv_check": { "type": "string", "enum": [ - "ssl-hello-chk", - "smtpchk", + "httpchk", "ldap-check", "mysql-check", "pgsql-check", - "tcp-check", "redis-check", - "httpchk" + "smtpchk", + "ssl-hello-chk", + "tcp-check" ], "x-display-name": "Advanced Check" }, @@ -16552,6 +16552,7 @@ func init() { "x-display-name": "External Check Path" }, "force_persist": { + "description": "This field is deprecated in favor of force_persist_list, and will be removed in a future release", "type": "object", "required": [ "cond", @@ -16575,7 +16576,40 @@ func init() { }, "x-display-name": "Condition Test" } - } + }, + "x-deprecated": true + }, + "force_persist_list": { + "type": "array", + "items": { + "type": "object", + "required": [ + "cond", + "cond_test" + ], + "properties": { + "cond": { + "type": "string", + "enum": [ + "if", + "unless" + ], + "x-display-name": "Condition" + }, + "cond_test": { + "type": "string", + "x-dependency": { + "cond": { + "required": true + } + }, + "x-display-name": "Condition Test" + } + }, + "x-go-name": "ForcePersist" + }, + "x-go-name": "ForcePersistList", + "x-omitempty": true }, "forwardfor": { "x-dependency": { @@ -16606,6 +16640,10 @@ func init() { }, "x-display-name": "H1 Adjust Bogus Server" }, + "hash_balance_factor": { + "type": "integer", + "x-nullable": true + }, "hash_type": { "$ref": "#/definitions/hash_type" }, @@ -16793,6 +16831,7 @@ func init() { "x-nullable": true }, "ignore_persist": { + "description": "This field is deprecated in favor of ignore_persist_list, and will be removed in a future release", "type": "object", "required": [ "cond", @@ -16816,7 +16855,40 @@ func init() { }, "x-display-name": "Condition Test" } - } + }, + "x-deprecated": true + }, + "ignore_persist_list": { + "type": "array", + "items": { + "type": "object", + "required": [ + "cond", + "cond_test" + ], + "properties": { + "cond": { + "type": "string", + "enum": [ + "if", + "unless" + ], + "x-display-name": "Condition" + }, + "cond_test": { + "type": "string", + "x-dependency": { + "cond": { + "required": true + } + }, + "x-display-name": "Condition Test" + } + }, + "x-go-name": "IgnorePersist" + }, + "x-go-name": "IgnorePersistList", + "x-omitempty": true }, "independent_streams": { "type": "string", @@ -16855,7 +16927,8 @@ func init() { "type": "string", "enum": [ "http", - "tcp" + "tcp", + "log" ] }, "mysql_check_params": { @@ -17152,17 +17225,17 @@ func init() { "algorithm": { "type": "string", "enum": [ - "roundrobin", - "static-rr", - "leastconn", "first", - "source", - "uri", - "url_param", + "hash", "hdr", + "leastconn", "random", "rdp-cookie", - "hash" + "roundrobin", + "source", + "static-rr", + "uri", + "url_param" ] }, "hash_expression": { @@ -17282,35 +17355,37 @@ func init() { }, "bind": { "description": "HAProxy frontend bind configuration", - "type": "object", "title": "Bind", "allOf": [ { "$ref": "#/definitions/bind_params" - } - ], - "properties": { - "address": { - "type": "string", - "pattern": "^[^\\s]+$", - "example": "127.0.0.1" }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true, - "example": 80 - }, - "port-range-end": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true, - "example": 81 + { + "type": "object", + "properties": { + "address": { + "type": "string", + "pattern": "^[^\\s]+$", + "example": "127.0.0.1" + }, + "port": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true, + "example": 80 + }, + "port-range-end": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true, + "example": 81 + } + }, + "additionalProperties": false } - }, - "additionalProperties": false + ] }, "bind_params": { "type": "object", @@ -17501,6 +17576,10 @@ func init() { "type": "string", "example": "app" }, + "nbconn": { + "type": "integer", + "x-display-name": "Number of connection" + }, "nice": { "type": "integer", "example": 1 @@ -17593,6 +17672,13 @@ func init() { "quic-force-retry": { "type": "boolean" }, + "quic-socket": { + "type": "string", + "enum": [ + "connection", + "listener" + ] + }, "severity_output": { "type": "string", "enum": [ @@ -17884,6 +17970,16 @@ func init() { "compression": { "type": "object", "properties": { + "algo-req": { + "type": "string", + "enum": [ + "identity", + "gzip", + "deflate", + "raw-deflate" + ], + "x-omitempty": true + }, "algorithms": { "type": "array", "items": { @@ -17897,6 +17993,28 @@ func init() { }, "x-omitempty": true }, + "algos-res": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "identity", + "gzip", + "deflate", + "raw-deflate" + ] + }, + "x-omitempty": true + }, + "direction": { + "type": "string", + "enum": [ + "request", + "response", + "both" + ], + "x-omitempty": true + }, "offload": { "type": "boolean" }, @@ -17906,6 +18024,20 @@ func init() { "type": "string" }, "x-omitempty": true + }, + "types-req": { + "type": "array", + "items": { + "type": "string" + }, + "x-omitempty": true + }, + "types-res": { + "type": "array", + "items": { + "type": "string" + }, + "x-omitempty": true } } }, @@ -17933,6 +18065,14 @@ func init() { "type": "integer", "x-nullable": true }, + "srvkey": { + "type": "string", + "enum": [ + "addr", + "name" + ], + "x-nullable": true + }, "store": { "type": "string", "pattern": "^[^\\s]+$" @@ -17946,6 +18086,11 @@ func init() { "string", "binary" ] + }, + "write_to": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": true } } }, @@ -18177,7 +18322,6 @@ func init() { }, "default_bind": { "description": "HAProxy default bind configuration", - "type": "object", "title": "Default Bind", "allOf": [ { @@ -18186,7 +18330,6 @@ func init() { ] }, "default_server": { - "type": "object", "title": "Default Server", "allOf": [ { @@ -18225,14 +18368,14 @@ func init() { "adv_check": { "type": "string", "enum": [ - "ssl-hello-chk", - "smtpchk", + "httpchk", "ldap-check", "mysql-check", "pgsql-check", - "tcp-check", "redis-check", - "httpchk" + "smtpchk", + "ssl-hello-chk", + "tcp-check" ], "x-display-name": "Advanced Check" }, @@ -18438,6 +18581,10 @@ func init() { ], "x-display-name": "H1 Adjust Bogus Server" }, + "hash_balance_factor": { + "type": "integer", + "x-nullable": true + }, "hash_type": { "$ref": "#/definitions/hash_type" }, @@ -18622,7 +18769,8 @@ func init() { "type": "string", "enum": [ "tcp", - "http" + "http", + "log" ] }, "monitor_uri": { @@ -18820,11 +18968,6 @@ func init() { }, "unique_id_header": { "type": "string", - "x-dependency": { - "unique_id_format": { - "required": true - } - }, "x-display-name": "Unique ID header" } }, @@ -19476,13 +19619,13 @@ func init() { "type": { "type": "string", "enum": [ - "trace", - "compression", - "spoe", + "bwlim-in", + "bwlim-out", "cache", + "compression", "fcgi-app", - "bwlim-in", - "bwlim-out" + "spoe", + "trace" ], "x-nullable": false } @@ -19958,11 +20101,6 @@ func init() { }, "unique_id_header": { "type": "string", - "x-dependency": { - "unique_id_format": { - "required": true - } - }, "x-display-name": "Unique ID header" } }, @@ -20174,6 +20312,9 @@ func init() { "pattern": "^[^\\s]+$", "x-display-name": "Group" }, + "h1_accept_payload_with_any_method": { + "type": "boolean" + }, "h1_case_adjust": { "type": "array", "items": { @@ -20198,6 +20339,9 @@ func init() { "h1_case_adjust_file": { "type": "string" }, + "h1_do_not_close_on_insecure_transfer_encoding": { + "type": "boolean" + }, "h2_workaround_bogus_websocket_clients": { "type": "boolean" }, @@ -20258,6 +20402,9 @@ func init() { "issuers_chain_path": { "type": "string" }, + "limited_quic": { + "type": "boolean" + }, "load_server_state_from_file": { "type": "string", "enum": [ @@ -20488,21 +20635,23 @@ func init() { "runtime_apis": { "type": "array", "items": { - "type": "object", - "required": [ - "address" - ], "allOf": [ { "$ref": "#/definitions/bind_params" + }, + { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string", + "pattern": "^[^\\s]+$" + } + } } ], - "properties": { - "address": { - "type": "string", - "pattern": "^[^\\s]+$" - } - }, "x-go-name": "RuntimeAPI" }, "x-display-name": "Runtime APIs", @@ -20570,6 +20719,12 @@ func init() { "x-go-name": "SetVarFmts", "x-omitempty": true }, + "setcap": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-display-name": "OS Capabilities", + "x-omitempty": true + }, "setenv": { "type": "array", "items": { @@ -20770,6 +20925,15 @@ func init() { "type": "integer", "x-display-name": "Maximum Compression Level" }, + "disable_zero_copy_forwarding": { + "type": "boolean", + "x-display-name": "Disable zero-copy forwarding" + }, + "events_max_events_at_once": { + "type": "integer", + "maximum": 10000, + "minimum": 1 + }, "fail_alloc": { "type": "boolean", "x-display-name": "Failed Allocation Chance" @@ -20782,6 +20946,22 @@ func init() { ], "x-display-name": "Edge-triggered polling mode" }, + "h1_zero_copy_fwd_recv": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy receives of data for the HTTP/1 multiplexer" + }, + "h1_zero_copy_fwd_send": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy sends of data for the HTTP/1 multiplexer" + }, "h2_be_initial_window_size": { "type": "integer", "x-display-name": "Initial window size for outgoing connections" @@ -20816,6 +20996,14 @@ func init() { "type": "integer", "x-display-name": "HTTP/2 Maximum Frame Size" }, + "h2_zero_copy_fwd_send": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy sends of data for the HTTP/2 multiplexer" + }, "http_cookielen": { "type": "integer", "x-display-name": "Maximum Cookie Length" @@ -20870,6 +21058,23 @@ func init() { "type": "integer", "x-display-name": "Lua Forced Yield" }, + "lua_log_loggers": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "Send Lua Logs to the Loggers" + }, + "lua_log_stderr": { + "type": "string", + "enum": [ + "auto", + "enabled", + "disabled" + ], + "x-display-name": "Send Lua Logs to stderr" + }, "lua_maxmem": { "type": "boolean", "x-display-name": "Lua Maximum Memory Usage" @@ -20889,6 +21094,11 @@ func init() { "x-display-name": "Lua Task Timeout", "x-nullable": true }, + "max_checks_per_thread": { + "type": "integer", + "x-display-name": "Maximum checks per thread", + "x-nullable": true + }, "maxaccept": { "type": "integer", "x-display-name": "Maximum Accept Events" @@ -20927,6 +21137,14 @@ func init() { "type": "integer", "x-display-name": "Max Used Low FD Ratio" }, + "pt_zero_copy_forwarding": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy forwarding of data for the pass-through multiplexer" + }, "quic_frontend_conn_tx_buffers_limit": { "type": "integer", "x-display-name": "QUIC Frontend Connection TX Buffer Limit", @@ -20960,14 +21178,24 @@ func init() { ], "x-display-name": "QUIC Socket Owner" }, + "rcvbuf_backend": { + "type": "integer", + "x-display-name": "Backend Receive Buffer Size", + "x-nullable": true + }, "rcvbuf_client": { "type": "integer", - "x-display-name": "Receive Buffer Client Size", + "x-display-name": "Client Receive Buffer Size", + "x-nullable": true + }, + "rcvbuf_frontend": { + "type": "integer", + "x-display-name": "Frontend Receive Buffer Size", "x-nullable": true }, "rcvbuf_server": { "type": "integer", - "x-display-name": "Receive Buffer Server Size", + "x-display-name": "Server Receive Buffer Size", "x-nullable": true }, "recv_enough": { @@ -20986,14 +21214,24 @@ func init() { ], "x-display-name": "Low Latency Task Scheduler" }, + "sndbuf_backend": { + "type": "integer", + "x-display-name": "Backend Send Buffer Size", + "x-nullable": true + }, "sndbuf_client": { "type": "integer", - "x-display-name": "Send Buffer Client Size", + "x-display-name": "Client Send Buffer Size", + "x-nullable": true + }, + "sndbuf_frontend": { + "type": "integer", + "x-display-name": "Frontend Send Buffer Size", "x-nullable": true }, "sndbuf_server": { "type": "integer", - "x-display-name": "Send Buffer Server Size", + "x-display-name": "Server Send Buffer Size", "x-nullable": true }, "ssl_cachesize": { @@ -21178,7 +21416,8 @@ func init() { "sdbm", "djb2", "wt6", - "crc32" + "crc32", + "none" ] }, "method": { @@ -21243,6 +21482,36 @@ func init() { }, "x-display-name": "ACK Key Format" }, + "capture_id": { + "type": "integer", + "x-dependency": { + "type": { + "value": "capture" + } + }, + "x-display-name": "Capture SlotID", + "x-nullable": true + }, + "capture_len": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": "capture" + } + }, + "x-display-name": "Capture Len" + }, + "capture_sample": { + "type": "string", + "pattern": "^(?:[A-Za-z]+\\(\"([A-Za-z\\s]+)\"\\)|[A-Za-z]+)", + "x-dependency": { + "type": { + "value": "capture" + } + }, + "x-display-name": "Capture Sample" + }, "cond": { "type": "string", "enum": [ @@ -21405,6 +21674,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] } @@ -21417,7 +21687,8 @@ func init() { "required": true, "value": [ "sc-add-gpc", - "sc-inc-gpc" + "sc-inc-gpc", + "sc-set-gpt" ] } } @@ -21474,6 +21745,7 @@ func init() { "enum": [ "add-header", "allow", + "capture", "del-acl", "del-header", "del-map", @@ -21483,12 +21755,14 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "set-header", "set-log-level", "set-map", "set-status", "set-var", + "set-var-fmt", "strict-mode", "unset-var" ], @@ -21504,6 +21778,16 @@ func init() { }, "x-display-name": "Var Expression" }, + "var_format": { + "type": "string", + "x-dependency": { + "type": { + "required": true, + "value": "set-var-fmt" + } + }, + "x-display-name": "Var Format" + }, "var_name": { "type": "string", "pattern": "^[^\\s]+$", @@ -21512,6 +21796,7 @@ func init() { "required": true, "value": [ "set-var", + "set-var-fmt", "unset-var" ] } @@ -21525,6 +21810,7 @@ func init() { "required": true, "value": [ "set-var", + "set-var-fmt", "unset-var" ] } @@ -21964,7 +22250,7 @@ func init() { "return_content_format": { "type": "string", "enum": [ - "default-errorfile", + "default-errorfiles", "errorfile", "errorfiles", "file", @@ -22210,7 +22496,7 @@ func init() { }, "capture_sample": { "type": "string", - "pattern": "^[^\\s]+$", + "pattern": "^(?:[A-Za-z]+\\(\"([A-Za-z\\s]+)\"\\)|[A-Za-z]+)", "x-dependency": { "type": { "value": "capture" @@ -22472,7 +22758,7 @@ func init() { "path-strip-dot", "path-strip-dotdot", "percent-decode-unreserved", - "percent-to-upercase", + "percent-to-uppercase", "query-sort-by-name" ], "x-dependency": { @@ -22499,7 +22785,7 @@ func init() { "normalizer": { "value": [ "percent-decode-unreserved", - "percent-to-upercase" + "percent-to-uppercase" ] }, "type": { @@ -22581,7 +22867,6 @@ func init() { "type": "string", "x-dependency": { "type": { - "required": true, "value": "redirect" } }, @@ -22642,7 +22927,7 @@ func init() { "return_content_format": { "type": "string", "enum": [ - "default-errorfile", + "default-errorfiles", "errorfile", "errorfiles", "file", @@ -22704,6 +22989,18 @@ func init() { "x-display-name": "Return Error Code", "x-nullable": true }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_expr": { "type": "string", "x-dependency": { @@ -22727,6 +23024,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] } @@ -22739,7 +23037,8 @@ func init() { "required": true, "value": [ "sc-add-gpc", - "sc-inc-gpc" + "sc-inc-gpc", + "sc-set-gpt" ] } } @@ -22815,7 +23114,8 @@ func init() { "type": "string", "enum": [ "server", - "tunnel" + "tunnel", + "client" ], "x-dependency": { "type": { @@ -22965,6 +23265,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", "set-dst", @@ -22986,6 +23287,7 @@ func init() { "set-tos", "set-uri", "set-var", + "set-var-fmt", "silent-drop", "strict-mode", "tarpit", @@ -23469,7 +23771,7 @@ func init() { "return_content_format": { "type": "string", "enum": [ - "default-errorfile", + "default-errorfiles", "errorfile", "errorfiles", "file", @@ -23529,6 +23831,18 @@ func init() { "x-display-name": "Return Error Code", "x-nullable": true }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_expr": { "type": "string", "x-dependency": { @@ -23552,6 +23866,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] } @@ -23564,7 +23879,8 @@ func init() { "required": true, "value": [ "sc-add-gpc", - "sc-inc-gpc" + "sc-inc-gpc", + "sc-set-gpt" ] } } @@ -23636,6 +23952,29 @@ func init() { } } }, + "timeout": { + "type": "string", + "x-dependency": { + "type": { + "required": true, + "value": "set-timeout" + } + } + }, + "timeout_type": { + "type": "string", + "enum": [ + "server", + "tunnel", + "client" + ], + "x-dependency": { + "type": { + "required": true, + "value": "set-timeout" + } + } + }, "tos_value": { "type": "string", "pattern": "^(0x[0-9A-Fa-f]+|[0-9]+)$", @@ -23768,6 +24107,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", "set-header", @@ -23776,6 +24116,7 @@ func init() { "set-mark", "set-nice", "set-status", + "set-timeout", "set-tos", "set-var", "set-var-fmt", @@ -24822,6 +25163,20 @@ func init() { }, "x-nullable": true }, + "last_agt": { + "type": "string", + "x-dependency": { + "type": "server" + }, + "x-nullable": true + }, + "last_chk": { + "type": "string", + "x-dependency": { + "type": "server" + }, + "x-nullable": true + }, "lastchg": { "type": "integer", "x-dependency": { @@ -25074,6 +25429,7 @@ func init() { "hrsp_other": 0, "iid": 0, "intercepted": 346, + "last_chk": "L4OK in 0ms", "mode": "http", "pid": 3204, "rate": 64, @@ -26097,13 +26453,13 @@ func init() { "items": { "type": "string", "enum": [ - "ssl", + "authority", "cert-cn", - "ssl-cipher", - "cert-sig", "cert-key", - "authority", + "cert-sig", "crc32c", + "ssl", + "ssl-cipher", "unique-id" ] }, @@ -26327,39 +26683,41 @@ func init() { }, "server": { "description": "HAProxy backend server configuration", - "type": "object", "title": "Server", - "required": [ - "name", - "address" - ], "allOf": [ { "$ref": "#/definitions/server_params" - } - ], - "properties": { - "address": { - "type": "string", - "pattern": "^[^\\s]+$", - "x-nullable": false }, - "id": { - "type": "integer", - "x-nullable": true - }, - "name": { - "type": "string", - "pattern": "^[^\\s]+$", - "x-nullable": false - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true + { + "type": "object", + "required": [ + "name", + "address" + ], + "properties": { + "address": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": false + }, + "id": { + "type": "integer", + "x-nullable": true + }, + "name": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": false + }, + "port": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true + } + } } - }, + ], "additionalProperties": false, "example": { "address": "10.1.1.1", @@ -26571,6 +26929,10 @@ func init() { "type": "integer", "x-nullable": true }, + "log-bufsize": { + "type": "integer", + "x-nullable": true + }, "log_proto": { "type": "string", "enum": [ @@ -26710,13 +27072,13 @@ func init() { "items": { "type": "string", "enum": [ - "ssl", + "authority", "cert-cn", - "ssl-cipher", - "cert-sig", "cert-key", - "authority", + "cert-sig", "crc32c", + "ssl", + "ssl-cipher", "unique-id" ] }, @@ -26781,6 +27143,21 @@ func init() { "disabled" ] }, + "set-proxy-v2-tlv-fmt": { + "type": "object", + "required": [ + "id", + "value" + ], + "properties": { + "id": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "shard": { "type": "integer" }, @@ -26999,43 +27376,45 @@ func init() { }, "server_template": { "description": "Set a template to initialize servers with shared parameters.", - "type": "object", "title": "Server template", - "required": [ - "prefix", - "num_or_range", - "fqdn" - ], "allOf": [ { "$ref": "#/definitions/server_params" - } - ], - "properties": { - "fqdn": { - "type": "string", - "x-nullable": false - }, - "id": { - "type": "integer", - "x-nullable": true }, - "num_or_range": { - "type": "string", - "x-nullable": false - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true - }, - "prefix": { - "type": "string", - "pattern": "^[^\\s]+$", - "x-nullable": false + { + "type": "object", + "required": [ + "prefix", + "num_or_range", + "fqdn" + ], + "properties": { + "fqdn": { + "type": "string", + "x-nullable": false + }, + "id": { + "type": "integer", + "x-nullable": true + }, + "num_or_range": { + "type": "string", + "x-nullable": false + }, + "port": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true + }, + "prefix": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": false + } + } } - }, + ], "additionalProperties": false, "example": { "fqdn": "google.com", @@ -27477,14 +27856,14 @@ func init() { "name": { "type": "string", "enum": [ - "on-client-session", - "on-server-session", - "on-frontend-tcp-request", + "on-backend-http-request", "on-backend-tcp-request", - "on-tcp-response", + "on-client-session", "on-frontend-http-request", - "on-backend-http-request", - "on-http-response" + "on-frontend-tcp-request", + "on-http-response", + "on-server-session", + "on-tcp-response" ] } } @@ -27897,25 +28276,25 @@ func init() { "field": { "type": "string", "enum": [ - "server_id", + "bytes_in_cnt", + "bytes_in_rate", + "bytes_out_cnt", + "bytes_out_rate", + "conn_cnt", + "conn_cur", + "conn_rate", "gpc0", "gpc0_rate", "gpc1", "gpc1_rate", "gpt0", - "conn_cnt", - "conn_cur", - "conn_rate", - "sess_cnt", - "sess_rate", "http_req_cnt", "http_req_rate", "http_err_cnt", "http_err_rate", - "bytes_in_cnt", - "bytes_in_rate", - "bytes_out_cnt", - "bytes_out_rate" + "server_id", + "sess_cnt", + "sess_rate" ] }, "period": { @@ -28114,6 +28493,10 @@ func init() { "type": "integer", "x-display-name": "Type", "x-nullable": true + }, + "write_to": { + "type": "string", + "x-nullable": true } } }, @@ -28497,38 +28880,41 @@ func init() { "type": "string", "enum": [ "accept", + "attach-srv", "capture", "do-resolve", "expect-netscaler-cip", "expect-proxy", + "lua", "reject", "sc-add-gpc", "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", + "set-bandwidth-limit", "set-dst-port", "set-dst", - "set-priority", + "set-log-level", + "set-mark", + "set-nice", + "set-priority-class", + "set-priority-offset", "set-src", + "set-src-port", + "set-tos", "set-var", + "set-var-fmt", "silent-drop", + "switch-mode", "track-sc0", "track-sc1", "track-sc2", "track-sc", "unset-var", - "use-service", - "lua", - "set-bandwidth-limit", - "set-src-port", - "set-mark", - "set-tos", - "set-var-fmt", - "set-log-level", - "set-nice", - "switch-mode" + "use-service" ], "x-dependency": { "type": { @@ -28597,7 +28983,7 @@ func init() { }, "capture_sample": { "type": "string", - "pattern": "^[^\\s]+$", + "pattern": "^(?:[A-Za-z]+\\(\"([A-Za-z\\s]+)\"\\)|[A-Za-z]+)", "x-dependency": { "action": { "required": true, @@ -28659,12 +29045,13 @@ func init() { "required": true, "value": [ "do-resolve", - "set-var", - "set-src", - "set-priority", "set-dst", "set-dst-port", - "set-src-port" + "set-priority-class", + "set-priority-offset", + "set-src", + "set-src-port", + "set-var" ] }, "type": { @@ -28787,24 +29174,6 @@ func init() { "x-display-name": "Nice Value", "x-nullable": false }, - "priority_type": { - "type": "string", - "enum": [ - "class", - "offset" - ], - "x-dependency": { - "action": { - "required": true, - "value": "set-priority" - }, - "type": { - "value": [ - "content" - ] - } - } - }, "resolve_protocol": { "type": "string", "enum": [ @@ -28857,12 +29226,26 @@ func init() { }, "x-display-name": "Variable name" }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_idx": { "type": "string", "x-dependency": { "action": { "required": true, - "value": null + "value": [ + "sc-set-gpt" + ] }, "type": { "required": true, @@ -28885,6 +29268,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] }, @@ -28913,6 +29297,19 @@ func init() { "x-display-name": "ScSet Integer Value", "x-nullable": true }, + "server_name": { + "type": "string", + "x-dependency": { + "action": { + "required": true, + "value": "attach-srv" + }, + "type": { + "value": "session" + } + }, + "x-display-name": "Server name" + }, "service_name": { "type": "string", "x-dependency": { @@ -29084,6 +29481,7 @@ func init() { }, "type": { "value": [ + "session", "connection", "content" ] @@ -29165,20 +29563,23 @@ func init() { "type": "string", "enum": [ "accept", - "reject", - "lua", - "set-bandwidth-limit", "close", + "lua", + "reject", "sc-add-gpc", "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", + "set-bandwidth-limit", "set-log-level", "set-mark", "set-nice", "set-tos", + "set-var", + "set-var-fmt", "silent-drop", "unset-var" ], @@ -29355,6 +29756,18 @@ func init() { "x-display-name": "Nice Value", "x-nullable": false }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_expr": { "type": "string", "x-dependency": { @@ -29381,6 +29794,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] }, @@ -29396,6 +29810,7 @@ func init() { "required": true, "value": [ "sc-add-gpc", + "sc-set-gpt", "sc-inc-gpc" ] }, @@ -29481,6 +29896,19 @@ func init() { ], "x-nullable": false }, + "var_format": { + "type": "string", + "x-dependency": { + "action": { + "required": true, + "value": "set-var-fmt" + }, + "type": { + "value": "content" + } + }, + "x-display-name": "Var Format" + }, "var_name": { "type": "string", "pattern": "^[^\\s]+$", @@ -29917,7 +30345,7 @@ func init() { "url": "https://my.haproxy.com/portal/cust/login", "email": "support@haproxy.com" }, - "version": "2.8" + "version": "2.9" }, "basePath": "/v2", "paths": { @@ -53756,6 +54184,7 @@ func init() { }, "definitions": { "BackendForcePersist": { + "description": "This field is deprecated in favor of force_persist_list, and will be removed in a future release", "type": "object", "required": [ "cond", @@ -53779,9 +54208,38 @@ func init() { }, "x-display-name": "Condition Test" } - } + }, + "x-deprecated": true + }, + "BackendForcePersistListItems0": { + "type": "object", + "required": [ + "cond", + "cond_test" + ], + "properties": { + "cond": { + "type": "string", + "enum": [ + "if", + "unless" + ], + "x-display-name": "Condition" + }, + "cond_test": { + "type": "string", + "x-dependency": { + "cond": { + "required": true + } + }, + "x-display-name": "Condition Test" + } + }, + "x-go-name": "ForcePersist" }, "BackendIgnorePersist": { + "description": "This field is deprecated in favor of ignore_persist_list, and will be removed in a future release", "type": "object", "required": [ "cond", @@ -53805,7 +54263,35 @@ func init() { }, "x-display-name": "Condition Test" } - } + }, + "x-deprecated": true + }, + "BackendIgnorePersistListItems0": { + "type": "object", + "required": [ + "cond", + "cond_test" + ], + "properties": { + "cond": { + "type": "string", + "enum": [ + "if", + "unless" + ], + "x-display-name": "Condition" + }, + "cond_test": { + "type": "string", + "x-dependency": { + "cond": { + "required": true + } + }, + "x-display-name": "Condition Test" + } + }, + "x-go-name": "IgnorePersist" }, "ClusterSettingsCluster": { "type": "object", @@ -54090,21 +54576,23 @@ func init() { "x-go-name": "PresetEnv" }, "GlobalRuntimeApisItems0": { - "type": "object", - "required": [ - "address" - ], "allOf": [ { "$ref": "#/definitions/bind_params" + }, + { + "type": "object", + "required": [ + "address" + ], + "properties": { + "address": { + "type": "string", + "pattern": "^[^\\s]+$" + } + } } ], - "properties": { - "address": { - "type": "string", - "pattern": "^[^\\s]+$" - } - }, "x-go-name": "RuntimeAPI" }, "GlobalSetVarFmtItems0": { @@ -54218,6 +54706,15 @@ func init() { "type": "integer", "x-display-name": "Maximum Compression Level" }, + "disable_zero_copy_forwarding": { + "type": "boolean", + "x-display-name": "Disable zero-copy forwarding" + }, + "events_max_events_at_once": { + "type": "integer", + "maximum": 10000, + "minimum": 1 + }, "fail_alloc": { "type": "boolean", "x-display-name": "Failed Allocation Chance" @@ -54230,6 +54727,22 @@ func init() { ], "x-display-name": "Edge-triggered polling mode" }, + "h1_zero_copy_fwd_recv": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy receives of data for the HTTP/1 multiplexer" + }, + "h1_zero_copy_fwd_send": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy sends of data for the HTTP/1 multiplexer" + }, "h2_be_initial_window_size": { "type": "integer", "x-display-name": "Initial window size for outgoing connections" @@ -54264,6 +54777,14 @@ func init() { "type": "integer", "x-display-name": "HTTP/2 Maximum Frame Size" }, + "h2_zero_copy_fwd_send": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy sends of data for the HTTP/2 multiplexer" + }, "http_cookielen": { "type": "integer", "x-display-name": "Maximum Cookie Length" @@ -54319,6 +54840,23 @@ func init() { "type": "integer", "x-display-name": "Lua Forced Yield" }, + "lua_log_loggers": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "Send Lua Logs to the Loggers" + }, + "lua_log_stderr": { + "type": "string", + "enum": [ + "auto", + "enabled", + "disabled" + ], + "x-display-name": "Send Lua Logs to stderr" + }, "lua_maxmem": { "type": "boolean", "x-display-name": "Lua Maximum Memory Usage" @@ -54338,6 +54876,11 @@ func init() { "x-display-name": "Lua Task Timeout", "x-nullable": true }, + "max_checks_per_thread": { + "type": "integer", + "x-display-name": "Maximum checks per thread", + "x-nullable": true + }, "maxaccept": { "type": "integer", "x-display-name": "Maximum Accept Events" @@ -54376,6 +54919,14 @@ func init() { "type": "integer", "x-display-name": "Max Used Low FD Ratio" }, + "pt_zero_copy_forwarding": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy forwarding of data for the pass-through multiplexer" + }, "quic_frontend_conn_tx_buffers_limit": { "type": "integer", "x-display-name": "QUIC Frontend Connection TX Buffer Limit", @@ -54409,14 +54960,24 @@ func init() { ], "x-display-name": "QUIC Socket Owner" }, + "rcvbuf_backend": { + "type": "integer", + "x-display-name": "Backend Receive Buffer Size", + "x-nullable": true + }, "rcvbuf_client": { "type": "integer", - "x-display-name": "Receive Buffer Client Size", + "x-display-name": "Client Receive Buffer Size", + "x-nullable": true + }, + "rcvbuf_frontend": { + "type": "integer", + "x-display-name": "Frontend Receive Buffer Size", "x-nullable": true }, "rcvbuf_server": { "type": "integer", - "x-display-name": "Receive Buffer Server Size", + "x-display-name": "Server Receive Buffer Size", "x-nullable": true }, "recv_enough": { @@ -54435,14 +54996,24 @@ func init() { ], "x-display-name": "Low Latency Task Scheduler" }, + "sndbuf_backend": { + "type": "integer", + "x-display-name": "Backend Send Buffer Size", + "x-nullable": true + }, "sndbuf_client": { "type": "integer", - "x-display-name": "Send Buffer Client Size", + "x-display-name": "Client Send Buffer Size", + "x-nullable": true + }, + "sndbuf_frontend": { + "type": "integer", + "x-display-name": "Frontend Send Buffer Size", "x-nullable": true }, "sndbuf_server": { "type": "integer", - "x-display-name": "Send Buffer Server Size", + "x-display-name": "Server Send Buffer Size", "x-nullable": true }, "ssl_cachesize": { @@ -54652,6 +55223,21 @@ func init() { } } }, + "ServerParamsSetProxyV2TlvFmt": { + "type": "object", + "required": [ + "id", + "value" + ], + "properties": { + "id": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "SiteFarmsItems0": { "type": "object", "required": [ @@ -54785,14 +55371,14 @@ func init() { "name": { "type": "string", "enum": [ - "on-client-session", - "on-server-session", - "on-frontend-tcp-request", + "on-backend-http-request", "on-backend-tcp-request", - "on-tcp-response", + "on-client-session", "on-frontend-http-request", - "on-backend-http-request", - "on-http-response" + "on-frontend-tcp-request", + "on-http-response", + "on-server-session", + "on-tcp-response" ] } } @@ -54803,25 +55389,25 @@ func init() { "field": { "type": "string", "enum": [ - "server_id", + "bytes_in_cnt", + "bytes_in_rate", + "bytes_out_cnt", + "bytes_out_rate", + "conn_cnt", + "conn_cur", + "conn_rate", "gpc0", "gpc0_rate", "gpc1", "gpc1_rate", "gpt0", - "conn_cnt", - "conn_cur", - "conn_rate", - "sess_cnt", - "sess_rate", "http_req_cnt", "http_req_rate", "http_err_cnt", "http_err_rate", - "bytes_in_cnt", - "bytes_in_rate", - "bytes_out_cnt", - "bytes_out_rate" + "server_id", + "sess_cnt", + "sess_rate" ] }, "period": { @@ -55085,14 +55671,14 @@ func init() { "adv_check": { "type": "string", "enum": [ - "ssl-hello-chk", - "smtpchk", + "httpchk", "ldap-check", "mysql-check", "pgsql-check", - "tcp-check", "redis-check", - "httpchk" + "smtpchk", + "ssl-hello-chk", + "tcp-check" ], "x-display-name": "Advanced Check" }, @@ -55206,6 +55792,7 @@ func init() { "x-display-name": "External Check Path" }, "force_persist": { + "description": "This field is deprecated in favor of force_persist_list, and will be removed in a future release", "type": "object", "required": [ "cond", @@ -55229,7 +55816,16 @@ func init() { }, "x-display-name": "Condition Test" } - } + }, + "x-deprecated": true + }, + "force_persist_list": { + "type": "array", + "items": { + "$ref": "#/definitions/BackendForcePersistListItems0" + }, + "x-go-name": "ForcePersistList", + "x-omitempty": true }, "forwardfor": { "x-dependency": { @@ -55260,6 +55856,10 @@ func init() { }, "x-display-name": "H1 Adjust Bogus Server" }, + "hash_balance_factor": { + "type": "integer", + "x-nullable": true + }, "hash_type": { "$ref": "#/definitions/hash_type" }, @@ -55447,6 +56047,7 @@ func init() { "x-nullable": true }, "ignore_persist": { + "description": "This field is deprecated in favor of ignore_persist_list, and will be removed in a future release", "type": "object", "required": [ "cond", @@ -55470,7 +56071,16 @@ func init() { }, "x-display-name": "Condition Test" } - } + }, + "x-deprecated": true + }, + "ignore_persist_list": { + "type": "array", + "items": { + "$ref": "#/definitions/BackendIgnorePersistListItems0" + }, + "x-go-name": "IgnorePersistList", + "x-omitempty": true }, "independent_streams": { "type": "string", @@ -55509,7 +56119,8 @@ func init() { "type": "string", "enum": [ "http", - "tcp" + "tcp", + "log" ] }, "mysql_check_params": { @@ -55806,17 +56417,17 @@ func init() { "algorithm": { "type": "string", "enum": [ - "roundrobin", - "static-rr", - "leastconn", "first", - "source", - "uri", - "url_param", + "hash", "hdr", + "leastconn", "random", "rdp-cookie", - "hash" + "roundrobin", + "source", + "static-rr", + "uri", + "url_param" ] }, "hash_expression": { @@ -55936,35 +56547,37 @@ func init() { }, "bind": { "description": "HAProxy frontend bind configuration", - "type": "object", "title": "Bind", "allOf": [ { "$ref": "#/definitions/bind_params" - } - ], - "properties": { - "address": { - "type": "string", - "pattern": "^[^\\s]+$", - "example": "127.0.0.1" - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true, - "example": 80 }, - "port-range-end": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true, - "example": 81 + { + "type": "object", + "properties": { + "address": { + "type": "string", + "pattern": "^[^\\s]+$", + "example": "127.0.0.1" + }, + "port": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true, + "example": 80 + }, + "port-range-end": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true, + "example": 81 + } + }, + "additionalProperties": false } - }, - "additionalProperties": false + ] }, "bind_params": { "type": "object", @@ -56155,6 +56768,10 @@ func init() { "type": "string", "example": "app" }, + "nbconn": { + "type": "integer", + "x-display-name": "Number of connection" + }, "nice": { "type": "integer", "example": 1 @@ -56247,6 +56864,13 @@ func init() { "quic-force-retry": { "type": "boolean" }, + "quic-socket": { + "type": "string", + "enum": [ + "connection", + "listener" + ] + }, "severity_output": { "type": "string", "enum": [ @@ -56512,6 +57136,16 @@ func init() { "compression": { "type": "object", "properties": { + "algo-req": { + "type": "string", + "enum": [ + "identity", + "gzip", + "deflate", + "raw-deflate" + ], + "x-omitempty": true + }, "algorithms": { "type": "array", "items": { @@ -56525,6 +57159,28 @@ func init() { }, "x-omitempty": true }, + "algos-res": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "identity", + "gzip", + "deflate", + "raw-deflate" + ] + }, + "x-omitempty": true + }, + "direction": { + "type": "string", + "enum": [ + "request", + "response", + "both" + ], + "x-omitempty": true + }, "offload": { "type": "boolean" }, @@ -56534,6 +57190,20 @@ func init() { "type": "string" }, "x-omitempty": true + }, + "types-req": { + "type": "array", + "items": { + "type": "string" + }, + "x-omitempty": true + }, + "types-res": { + "type": "array", + "items": { + "type": "string" + }, + "x-omitempty": true } } }, @@ -56561,6 +57231,14 @@ func init() { "type": "integer", "x-nullable": true }, + "srvkey": { + "type": "string", + "enum": [ + "addr", + "name" + ], + "x-nullable": true + }, "store": { "type": "string", "pattern": "^[^\\s]+$" @@ -56574,6 +57252,11 @@ func init() { "string", "binary" ] + }, + "write_to": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": true } } }, @@ -56791,7 +57474,6 @@ func init() { }, "default_bind": { "description": "HAProxy default bind configuration", - "type": "object", "title": "Default Bind", "allOf": [ { @@ -56800,7 +57482,6 @@ func init() { ] }, "default_server": { - "type": "object", "title": "Default Server", "allOf": [ { @@ -56839,14 +57520,14 @@ func init() { "adv_check": { "type": "string", "enum": [ - "ssl-hello-chk", - "smtpchk", + "httpchk", "ldap-check", "mysql-check", "pgsql-check", - "tcp-check", "redis-check", - "httpchk" + "smtpchk", + "ssl-hello-chk", + "tcp-check" ], "x-display-name": "Advanced Check" }, @@ -57052,6 +57733,10 @@ func init() { ], "x-display-name": "H1 Adjust Bogus Server" }, + "hash_balance_factor": { + "type": "integer", + "x-nullable": true + }, "hash_type": { "$ref": "#/definitions/hash_type" }, @@ -57236,7 +57921,8 @@ func init() { "type": "string", "enum": [ "tcp", - "http" + "http", + "log" ] }, "monitor_uri": { @@ -57434,11 +58120,6 @@ func init() { }, "unique_id_header": { "type": "string", - "x-dependency": { - "unique_id_format": { - "required": true - } - }, "x-display-name": "Unique ID header" } }, @@ -58090,13 +58771,13 @@ func init() { "type": { "type": "string", "enum": [ - "trace", - "compression", - "spoe", + "bwlim-in", + "bwlim-out", "cache", + "compression", "fcgi-app", - "bwlim-in", - "bwlim-out" + "spoe", + "trace" ], "x-nullable": false } @@ -58572,11 +59253,6 @@ func init() { }, "unique_id_header": { "type": "string", - "x-dependency": { - "unique_id_format": { - "required": true - } - }, "x-display-name": "Unique ID header" } }, @@ -58774,6 +59450,9 @@ func init() { "pattern": "^[^\\s]+$", "x-display-name": "Group" }, + "h1_accept_payload_with_any_method": { + "type": "boolean" + }, "h1_case_adjust": { "type": "array", "items": { @@ -58785,6 +59464,9 @@ func init() { "h1_case_adjust_file": { "type": "string" }, + "h1_do_not_close_on_insecure_transfer_encoding": { + "type": "boolean" + }, "h2_workaround_bogus_websocket_clients": { "type": "boolean" }, @@ -58845,6 +59527,9 @@ func init() { "issuers_chain_path": { "type": "string" }, + "limited_quic": { + "type": "boolean" + }, "load_server_state_from_file": { "type": "string", "enum": [ @@ -59071,6 +59756,12 @@ func init() { "x-go-name": "SetVarFmts", "x-omitempty": true }, + "setcap": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-display-name": "OS Capabilities", + "x-omitempty": true + }, "setenv": { "type": "array", "items": { @@ -59226,6 +59917,15 @@ func init() { "type": "integer", "x-display-name": "Maximum Compression Level" }, + "disable_zero_copy_forwarding": { + "type": "boolean", + "x-display-name": "Disable zero-copy forwarding" + }, + "events_max_events_at_once": { + "type": "integer", + "maximum": 10000, + "minimum": 1 + }, "fail_alloc": { "type": "boolean", "x-display-name": "Failed Allocation Chance" @@ -59238,6 +59938,22 @@ func init() { ], "x-display-name": "Edge-triggered polling mode" }, + "h1_zero_copy_fwd_recv": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy receives of data for the HTTP/1 multiplexer" + }, + "h1_zero_copy_fwd_send": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy sends of data for the HTTP/1 multiplexer" + }, "h2_be_initial_window_size": { "type": "integer", "x-display-name": "Initial window size for outgoing connections" @@ -59272,6 +59988,14 @@ func init() { "type": "integer", "x-display-name": "HTTP/2 Maximum Frame Size" }, + "h2_zero_copy_fwd_send": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy sends of data for the HTTP/2 multiplexer" + }, "http_cookielen": { "type": "integer", "x-display-name": "Maximum Cookie Length" @@ -59327,6 +60051,23 @@ func init() { "type": "integer", "x-display-name": "Lua Forced Yield" }, + "lua_log_loggers": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "Send Lua Logs to the Loggers" + }, + "lua_log_stderr": { + "type": "string", + "enum": [ + "auto", + "enabled", + "disabled" + ], + "x-display-name": "Send Lua Logs to stderr" + }, "lua_maxmem": { "type": "boolean", "x-display-name": "Lua Maximum Memory Usage" @@ -59346,6 +60087,11 @@ func init() { "x-display-name": "Lua Task Timeout", "x-nullable": true }, + "max_checks_per_thread": { + "type": "integer", + "x-display-name": "Maximum checks per thread", + "x-nullable": true + }, "maxaccept": { "type": "integer", "x-display-name": "Maximum Accept Events" @@ -59384,6 +60130,14 @@ func init() { "type": "integer", "x-display-name": "Max Used Low FD Ratio" }, + "pt_zero_copy_forwarding": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "x-display-name": "enable or disable the zero-copy forwarding of data for the pass-through multiplexer" + }, "quic_frontend_conn_tx_buffers_limit": { "type": "integer", "x-display-name": "QUIC Frontend Connection TX Buffer Limit", @@ -59417,14 +60171,24 @@ func init() { ], "x-display-name": "QUIC Socket Owner" }, + "rcvbuf_backend": { + "type": "integer", + "x-display-name": "Backend Receive Buffer Size", + "x-nullable": true + }, "rcvbuf_client": { "type": "integer", - "x-display-name": "Receive Buffer Client Size", + "x-display-name": "Client Receive Buffer Size", + "x-nullable": true + }, + "rcvbuf_frontend": { + "type": "integer", + "x-display-name": "Frontend Receive Buffer Size", "x-nullable": true }, "rcvbuf_server": { "type": "integer", - "x-display-name": "Receive Buffer Server Size", + "x-display-name": "Server Receive Buffer Size", "x-nullable": true }, "recv_enough": { @@ -59443,14 +60207,24 @@ func init() { ], "x-display-name": "Low Latency Task Scheduler" }, + "sndbuf_backend": { + "type": "integer", + "x-display-name": "Backend Send Buffer Size", + "x-nullable": true + }, "sndbuf_client": { "type": "integer", - "x-display-name": "Send Buffer Client Size", + "x-display-name": "Client Send Buffer Size", + "x-nullable": true + }, + "sndbuf_frontend": { + "type": "integer", + "x-display-name": "Frontend Send Buffer Size", "x-nullable": true }, "sndbuf_server": { "type": "integer", - "x-display-name": "Send Buffer Server Size", + "x-display-name": "Server Send Buffer Size", "x-nullable": true }, "ssl_cachesize": { @@ -59635,7 +60409,8 @@ func init() { "sdbm", "djb2", "wt6", - "crc32" + "crc32", + "none" ] }, "method": { @@ -59700,6 +60475,36 @@ func init() { }, "x-display-name": "ACK Key Format" }, + "capture_id": { + "type": "integer", + "x-dependency": { + "type": { + "value": "capture" + } + }, + "x-display-name": "Capture SlotID", + "x-nullable": true + }, + "capture_len": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": "capture" + } + }, + "x-display-name": "Capture Len" + }, + "capture_sample": { + "type": "string", + "pattern": "^(?:[A-Za-z]+\\(\"([A-Za-z\\s]+)\"\\)|[A-Za-z]+)", + "x-dependency": { + "type": { + "value": "capture" + } + }, + "x-display-name": "Capture Sample" + }, "cond": { "type": "string", "enum": [ @@ -59862,6 +60667,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] } @@ -59874,7 +60680,8 @@ func init() { "required": true, "value": [ "sc-add-gpc", - "sc-inc-gpc" + "sc-inc-gpc", + "sc-set-gpt" ] } } @@ -59931,6 +60738,7 @@ func init() { "enum": [ "add-header", "allow", + "capture", "del-acl", "del-header", "del-map", @@ -59940,12 +60748,14 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "set-header", "set-log-level", "set-map", "set-status", "set-var", + "set-var-fmt", "strict-mode", "unset-var" ], @@ -59961,6 +60771,16 @@ func init() { }, "x-display-name": "Var Expression" }, + "var_format": { + "type": "string", + "x-dependency": { + "type": { + "required": true, + "value": "set-var-fmt" + } + }, + "x-display-name": "Var Format" + }, "var_name": { "type": "string", "pattern": "^[^\\s]+$", @@ -59969,6 +60789,7 @@ func init() { "required": true, "value": [ "set-var", + "set-var-fmt", "unset-var" ] } @@ -59982,6 +60803,7 @@ func init() { "required": true, "value": [ "set-var", + "set-var-fmt", "unset-var" ] } @@ -60421,7 +61243,7 @@ func init() { "return_content_format": { "type": "string", "enum": [ - "default-errorfile", + "default-errorfiles", "errorfile", "errorfiles", "file", @@ -60667,7 +61489,7 @@ func init() { }, "capture_sample": { "type": "string", - "pattern": "^[^\\s]+$", + "pattern": "^(?:[A-Za-z]+\\(\"([A-Za-z\\s]+)\"\\)|[A-Za-z]+)", "x-dependency": { "type": { "value": "capture" @@ -60929,7 +61751,7 @@ func init() { "path-strip-dot", "path-strip-dotdot", "percent-decode-unreserved", - "percent-to-upercase", + "percent-to-uppercase", "query-sort-by-name" ], "x-dependency": { @@ -60956,7 +61778,7 @@ func init() { "normalizer": { "value": [ "percent-decode-unreserved", - "percent-to-upercase" + "percent-to-uppercase" ] }, "type": { @@ -61038,7 +61860,6 @@ func init() { "type": "string", "x-dependency": { "type": { - "required": true, "value": "redirect" } }, @@ -61099,7 +61920,7 @@ func init() { "return_content_format": { "type": "string", "enum": [ - "default-errorfile", + "default-errorfiles", "errorfile", "errorfiles", "file", @@ -61161,6 +61982,18 @@ func init() { "x-display-name": "Return Error Code", "x-nullable": true }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_expr": { "type": "string", "x-dependency": { @@ -61184,6 +62017,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] } @@ -61196,7 +62030,8 @@ func init() { "required": true, "value": [ "sc-add-gpc", - "sc-inc-gpc" + "sc-inc-gpc", + "sc-set-gpt" ] } } @@ -61272,7 +62107,8 @@ func init() { "type": "string", "enum": [ "server", - "tunnel" + "tunnel", + "client" ], "x-dependency": { "type": { @@ -61422,6 +62258,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", "set-dst", @@ -61443,6 +62280,7 @@ func init() { "set-tos", "set-uri", "set-var", + "set-var-fmt", "silent-drop", "strict-mode", "tarpit", @@ -61926,7 +62764,7 @@ func init() { "return_content_format": { "type": "string", "enum": [ - "default-errorfile", + "default-errorfiles", "errorfile", "errorfiles", "file", @@ -61986,6 +62824,18 @@ func init() { "x-display-name": "Return Error Code", "x-nullable": true }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_expr": { "type": "string", "x-dependency": { @@ -62009,6 +62859,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] } @@ -62021,7 +62872,8 @@ func init() { "required": true, "value": [ "sc-add-gpc", - "sc-inc-gpc" + "sc-inc-gpc", + "sc-set-gpt" ] } } @@ -62093,6 +62945,29 @@ func init() { } } }, + "timeout": { + "type": "string", + "x-dependency": { + "type": { + "required": true, + "value": "set-timeout" + } + } + }, + "timeout_type": { + "type": "string", + "enum": [ + "server", + "tunnel", + "client" + ], + "x-dependency": { + "type": { + "required": true, + "value": "set-timeout" + } + } + }, "tos_value": { "type": "string", "pattern": "^(0x[0-9A-Fa-f]+|[0-9]+)$", @@ -62225,6 +63100,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", "set-header", @@ -62233,6 +63109,7 @@ func init() { "set-mark", "set-nice", "set-status", + "set-timeout", "set-tos", "set-var", "set-var-fmt", @@ -63280,6 +64157,20 @@ func init() { }, "x-nullable": true }, + "last_agt": { + "type": "string", + "x-dependency": { + "type": "server" + }, + "x-nullable": true + }, + "last_chk": { + "type": "string", + "x-dependency": { + "type": "server" + }, + "x-nullable": true + }, "lastchg": { "type": "integer", "x-dependency": { @@ -63532,6 +64423,7 @@ func init() { "hrsp_other": 0, "iid": 0, "intercepted": 346, + "last_chk": "L4OK in 0ms", "mode": "http", "pid": 3204, "rate": 64, @@ -64555,13 +65447,13 @@ func init() { "items": { "type": "string", "enum": [ - "ssl", + "authority", "cert-cn", - "ssl-cipher", - "cert-sig", "cert-key", - "authority", + "cert-sig", "crc32c", + "ssl", + "ssl-cipher", "unique-id" ] }, @@ -64785,39 +65677,41 @@ func init() { }, "server": { "description": "HAProxy backend server configuration", - "type": "object", "title": "Server", - "required": [ - "name", - "address" - ], "allOf": [ { "$ref": "#/definitions/server_params" - } - ], - "properties": { - "address": { - "type": "string", - "pattern": "^[^\\s]+$", - "x-nullable": false - }, - "id": { - "type": "integer", - "x-nullable": true }, - "name": { - "type": "string", - "pattern": "^[^\\s]+$", - "x-nullable": false - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true + { + "type": "object", + "required": [ + "name", + "address" + ], + "properties": { + "address": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": false + }, + "id": { + "type": "integer", + "x-nullable": true + }, + "name": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": false + }, + "port": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true + } + } } - }, + ], "additionalProperties": false, "example": { "address": "10.1.1.1", @@ -65029,6 +65923,10 @@ func init() { "type": "integer", "x-nullable": true }, + "log-bufsize": { + "type": "integer", + "x-nullable": true + }, "log_proto": { "type": "string", "enum": [ @@ -65168,13 +66066,13 @@ func init() { "items": { "type": "string", "enum": [ - "ssl", + "authority", "cert-cn", - "ssl-cipher", - "cert-sig", "cert-key", - "authority", + "cert-sig", "crc32c", + "ssl", + "ssl-cipher", "unique-id" ] }, @@ -65239,6 +66137,21 @@ func init() { "disabled" ] }, + "set-proxy-v2-tlv-fmt": { + "type": "object", + "required": [ + "id", + "value" + ], + "properties": { + "id": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "shard": { "type": "integer" }, @@ -65457,43 +66370,45 @@ func init() { }, "server_template": { "description": "Set a template to initialize servers with shared parameters.", - "type": "object", "title": "Server template", - "required": [ - "prefix", - "num_or_range", - "fqdn" - ], "allOf": [ { "$ref": "#/definitions/server_params" - } - ], - "properties": { - "fqdn": { - "type": "string", - "x-nullable": false - }, - "id": { - "type": "integer", - "x-nullable": true - }, - "num_or_range": { - "type": "string", - "x-nullable": false - }, - "port": { - "type": "integer", - "maximum": 65535, - "minimum": 1, - "x-nullable": true }, - "prefix": { - "type": "string", - "pattern": "^[^\\s]+$", - "x-nullable": false + { + "type": "object", + "required": [ + "prefix", + "num_or_range", + "fqdn" + ], + "properties": { + "fqdn": { + "type": "string", + "x-nullable": false + }, + "id": { + "type": "integer", + "x-nullable": true + }, + "num_or_range": { + "type": "string", + "x-nullable": false + }, + "port": { + "type": "integer", + "maximum": 65535, + "minimum": 1, + "x-nullable": true + }, + "prefix": { + "type": "string", + "pattern": "^[^\\s]+$", + "x-nullable": false + } + } } - }, + ], "additionalProperties": false, "example": { "fqdn": "google.com", @@ -65871,14 +66786,14 @@ func init() { "name": { "type": "string", "enum": [ - "on-client-session", - "on-server-session", - "on-frontend-tcp-request", + "on-backend-http-request", "on-backend-tcp-request", - "on-tcp-response", + "on-client-session", "on-frontend-http-request", - "on-backend-http-request", - "on-http-response" + "on-frontend-tcp-request", + "on-http-response", + "on-server-session", + "on-tcp-response" ] } } @@ -66466,6 +67381,10 @@ func init() { "type": "integer", "x-display-name": "Type", "x-nullable": true + }, + "write_to": { + "type": "string", + "x-nullable": true } } }, @@ -66849,38 +67768,41 @@ func init() { "type": "string", "enum": [ "accept", + "attach-srv", "capture", "do-resolve", "expect-netscaler-cip", "expect-proxy", + "lua", "reject", "sc-add-gpc", "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", + "set-bandwidth-limit", "set-dst-port", "set-dst", - "set-priority", + "set-log-level", + "set-mark", + "set-nice", + "set-priority-class", + "set-priority-offset", "set-src", + "set-src-port", + "set-tos", "set-var", + "set-var-fmt", "silent-drop", + "switch-mode", "track-sc0", "track-sc1", "track-sc2", "track-sc", "unset-var", - "use-service", - "lua", - "set-bandwidth-limit", - "set-src-port", - "set-mark", - "set-tos", - "set-var-fmt", - "set-log-level", - "set-nice", - "switch-mode" + "use-service" ], "x-dependency": { "type": { @@ -66949,7 +67871,7 @@ func init() { }, "capture_sample": { "type": "string", - "pattern": "^[^\\s]+$", + "pattern": "^(?:[A-Za-z]+\\(\"([A-Za-z\\s]+)\"\\)|[A-Za-z]+)", "x-dependency": { "action": { "required": true, @@ -67011,12 +67933,13 @@ func init() { "required": true, "value": [ "do-resolve", - "set-var", - "set-src", - "set-priority", "set-dst", "set-dst-port", - "set-src-port" + "set-priority-class", + "set-priority-offset", + "set-src", + "set-src-port", + "set-var" ] }, "type": { @@ -67139,24 +68062,6 @@ func init() { "x-display-name": "Nice Value", "x-nullable": false }, - "priority_type": { - "type": "string", - "enum": [ - "class", - "offset" - ], - "x-dependency": { - "action": { - "required": true, - "value": "set-priority" - }, - "type": { - "value": [ - "content" - ] - } - } - }, "resolve_protocol": { "type": "string", "enum": [ @@ -67209,12 +68114,26 @@ func init() { }, "x-display-name": "Variable name" }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_idx": { "type": "string", "x-dependency": { "action": { "required": true, - "value": [] + "value": [ + "sc-set-gpt" + ] }, "type": { "required": true, @@ -67237,6 +68156,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] }, @@ -67265,6 +68185,19 @@ func init() { "x-display-name": "ScSet Integer Value", "x-nullable": true }, + "server_name": { + "type": "string", + "x-dependency": { + "action": { + "required": true, + "value": "attach-srv" + }, + "type": { + "value": "session" + } + }, + "x-display-name": "Server name" + }, "service_name": { "type": "string", "x-dependency": { @@ -67436,6 +68369,7 @@ func init() { }, "type": { "value": [ + "session", "connection", "content" ] @@ -67517,20 +68451,23 @@ func init() { "type": "string", "enum": [ "accept", - "reject", - "lua", - "set-bandwidth-limit", "close", + "lua", + "reject", "sc-add-gpc", "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0", "send-spoe-group", + "set-bandwidth-limit", "set-log-level", "set-mark", "set-nice", "set-tos", + "set-var", + "set-var-fmt", "silent-drop", "unset-var" ], @@ -67707,6 +68644,18 @@ func init() { "x-display-name": "Nice Value", "x-nullable": false }, + "rst_ttl": { + "type": "integer", + "x-dependency": { + "type": { + "required": true, + "value": [ + "silent-drop" + ] + } + }, + "x-display-name": "RST TTL" + }, "sc_expr": { "type": "string", "x-dependency": { @@ -67733,6 +68682,7 @@ func init() { "sc-inc-gpc", "sc-inc-gpc0", "sc-inc-gpc1", + "sc-set-gpt", "sc-set-gpt0" ] }, @@ -67748,6 +68698,7 @@ func init() { "required": true, "value": [ "sc-add-gpc", + "sc-set-gpt", "sc-inc-gpc" ] }, @@ -67833,6 +68784,19 @@ func init() { ], "x-nullable": false }, + "var_format": { + "type": "string", + "x-dependency": { + "action": { + "required": true, + "value": "set-var-fmt" + }, + "type": { + "value": "content" + } + }, + "x-display-name": "Var Format" + }, "var_name": { "type": "string", "pattern": "^[^\\s]+$", diff --git a/generate/go-generate.go b/generate/go-generate.go index 359bcc05..d068f3c4 100644 --- a/generate/go-generate.go +++ b/generate/go-generate.go @@ -222,7 +222,7 @@ func getExample(att Attribute) string { if att.Example != "" { if att.Type == "int" { i, _ := strconv.ParseInt(att.Example, 10, 64) - return fmt.Sprintf("%d", i) + return strconv.FormatInt(i, 10) } return att.Example } @@ -243,7 +243,7 @@ func getExample(att Attribute) string { if v, ok := itemDefaults[att.FileName]; ok { switch t := v.(type) { case int: - return fmt.Sprintf("%d", v.(int)) + return strconv.Itoa(v.(int)) default: return t.(string) } diff --git a/go.mod b/go.mod index 333e1eb0..006eab68 100644 --- a/go.mod +++ b/go.mod @@ -1,82 +1,87 @@ module github.com/haproxytech/dataplaneapi -go 1.21 +go 1.24 require ( github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 - github.com/aws/aws-sdk-go-v2 v1.22.1 - github.com/aws/aws-sdk-go-v2/config v1.22.1 - github.com/aws/aws-sdk-go-v2/credentials v1.15.1 - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.30.7 - github.com/aws/aws-sdk-go-v2/service/ec2 v1.130.0 + github.com/aws/aws-sdk-go-v2 v1.36.3 + github.com/aws/aws-sdk-go-v2/config v1.29.14 + github.com/aws/aws-sdk-go-v2/credentials v1.17.67 + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.52.4 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.215.0 github.com/docker/go-units v0.5.0 - github.com/dustinkirkland/golang-petname v0.0.0-20231002161417-6a283f1aaaf2 - github.com/fsnotify/fsnotify v1.7.0 - github.com/getkin/kin-openapi v0.120.0 - github.com/go-openapi/errors v0.20.4 - github.com/go-openapi/loads v0.21.2 - github.com/go-openapi/runtime v0.26.0 - github.com/go-openapi/spec v0.20.9 - github.com/go-openapi/strfmt v0.21.7 - github.com/go-openapi/swag v0.22.4 - github.com/go-openapi/validate v0.22.1 + github.com/dustinkirkland/golang-petname v0.0.0-20240428194347-eebcea082ee0 + github.com/fsnotify/fsnotify v1.9.0 + github.com/getkin/kin-openapi v0.132.0 + github.com/go-openapi/errors v0.22.1 + github.com/go-openapi/loads v0.22.0 + github.com/go-openapi/runtime v0.28.0 + github.com/go-openapi/spec v0.21.0 + github.com/go-openapi/strfmt v0.23.0 + github.com/go-openapi/swag v0.23.1 + github.com/go-openapi/validate v0.24.0 github.com/google/renameio v1.0.1 - github.com/google/uuid v1.4.0 - github.com/haproxytech/client-native/v5 v5.0.1-0.20231106120845-bee8caf96cec - github.com/haproxytech/config-parser/v5 v5.0.1-0.20230913105857-585d83cb48ba - github.com/jessevdk/go-flags v1.5.0 + github.com/google/uuid v1.6.0 + github.com/haproxytech/client-native/v5 v5.1.17 + github.com/jessevdk/go-flags v1.6.1 github.com/json-iterator/go v1.1.12 github.com/kr/pretty v0.3.1 github.com/lestrrat-go/apache-logformat v0.0.0-20210106032603-24d066f940f8 - github.com/maruel/panicparse/v2 v2.3.1 + github.com/maruel/panicparse/v2 v2.5.0 github.com/nathanaelle/syslog5424/v2 v2.0.5 - github.com/rs/cors v1.10.1 + github.com/rs/cors v1.11.1 + github.com/rubyist/circuitbreaker v2.2.1+incompatible github.com/shirou/gopsutil v3.21.11+incompatible github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.8.4 - golang.org/x/net v0.17.0 - golang.org/x/sys v0.14.0 + github.com/stretchr/testify v1.10.0 + golang.org/x/net v0.40.0 + golang.org/x/sys v0.33.0 gopkg.in/yaml.v2 v2.4.0 ) require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.5.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.17.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.25.0 // indirect - github.com/aws/smithy-go v1.16.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect + github.com/aws/smithy-go v1.22.3 // indirect + github.com/cenk/backoff v2.2.1+incompatible // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-openapi/analysis v0.21.4 // indirect - github.com/go-openapi/jsonpointer v0.20.0 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/gofrs/flock v0.8.1 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/go-openapi/analysis v0.23.0 // indirect + github.com/go-openapi/jsonpointer v0.21.1 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/gofrs/flock v0.12.1 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/haproxytech/go-logger v1.1.0 // indirect - github.com/invopop/yaml v0.2.0 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/text v0.2.0 // indirect - github.com/lestrrat-go/strftime v1.0.6 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/lestrrat-go/strftime v1.1.0 // indirect + github.com/mailru/easyjson v0.9.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect + github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.mongodb.org/mongo-driver v1.12.1 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/tklauser/go-sysconf v0.3.15 // indirect + github.com/tklauser/numcpus v0.10.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.mongodb.org/mongo-driver v1.17.3 // indirect + golang.org/x/sync v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 635a9847..578a6227 100644 --- a/go.sum +++ b/go.sum @@ -1,175 +1,103 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 h1:IEjq88XO4PuBDcvmjQJcQGg+w+UaafSy8G5Kcb5tBhI= github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5/go.mod h1:exZ0C/1emQJAw5tHOaUDyY1ycttqBAPcxuzf7QbY6ec= -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/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go-v2 v1.21.1/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= -github.com/aws/aws-sdk-go-v2 v1.22.1 h1:sjnni/AuoTXxHitsIdT0FwmqUuNUuHtufcVDErVFT9U= -github.com/aws/aws-sdk-go-v2 v1.22.1/go.mod h1:Kd0OJtkW3Q0M0lUWGszapWjEvrXDzRW+D21JNsroB+c= -github.com/aws/aws-sdk-go-v2/config v1.22.1 h1:UrRYnF7mXCGuKmZWlczOXeH0WUbQpi/gseQIPtrhme8= -github.com/aws/aws-sdk-go-v2/config v1.22.1/go.mod h1:2eWgw5lps8fKI7LZVTrRTYP6HE6k/uEFUuTSHfXwqP0= -github.com/aws/aws-sdk-go-v2/credentials v1.15.1 h1:hmf6lAm9hk7uLCfapZn/jL05lm6Uwdbn1B0fgjyuf4M= -github.com/aws/aws-sdk-go-v2/credentials v1.15.1/go.mod h1:QTcHga3ZbQOneJuxmGBOCxiClxmp+TlvmjFexAnJ790= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.2 h1:gIeH4+o1MN/caGBWjoGQTUTIu94xD6fI5B2+TcwBf70= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.2/go.mod h1:wLyMIo/zPOhQhPXTddpfdkSleyigtFi8iMnC+2m/SK4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.42/go.mod h1:oDfgXoBBmj+kXnqxDDnIDnC56QBosglKp8ftRCTxR+0= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.1 h1:fi1ga6WysOyYb5PAf3Exd6B5GiSNpnZim4h1rhlBqx0= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.1/go.mod h1:V5CY8wNurvPUibTi9mwqUqpiFZ5LnioKWIFUDtIzdI8= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.36/go.mod h1:rwr4WnmFi3RJO0M4dxbJtgi9BPLMpVBMX1nUte5ha9U= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.1 h1:ZpaV/j48RlPc4AmOZuPv22pJliXjXq8/reL63YzyFnw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.1/go.mod h1:R8aXraabD2e3qv1csxM14/X9WF4wFMIY0kH4YEtYD5M= -github.com/aws/aws-sdk-go-v2/internal/ini v1.5.0 h1:DqOQvIfmGkXZUVJnl9VRk0AnxyS59tCtX9k1Pyss4Ak= -github.com/aws/aws-sdk-go-v2/internal/ini v1.5.0/go.mod h1:VV/Kbw9Mg1GWJOT9WK+oTL3cWZiXtapnNvDSRqTZLsg= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.30.7 h1:J1S+3Yx+dVYNjq5hqV/vRNeSKDKuxPD1lMke1WBJY8w= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.30.7/go.mod h1:14nJkEEU4z1s9X/AR2mMtiQgDaYSoswjXqjU2KKZ3YM= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.130.0 h1:a7CPCX/m+owAiAqcK8W9/SoB7EA4QUE4BddYdFyEGco= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.130.0/go.mod h1:EJlGVMO5zynmSDdvwJfFa2RzAZoHI4gVJER0h82/dYk= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.1 h1:2OXw3ppu1XsB6rqKEMV4tnecTjIY3PRV2U6IP6KPJQo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.1/go.mod h1:FZB4AdakIqW/yERVdGJA6Z9jraax1beXfhBBnK2wwR8= -github.com/aws/aws-sdk-go-v2/service/sso v1.17.0 h1:I/Oh3IxGPfHXiGnwM54TD6hNr/8TlUrBXAtTyGhR+zw= -github.com/aws/aws-sdk-go-v2/service/sso v1.17.0/go.mod h1:H6NCMvDBqA+CvIaXzaSqM6LWtzv9BzZrqBOqz+PzRF8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.0 h1:irbXQkfVYIRaewYSXcu4yVk0m2T+JzZd0dkop7FjmO0= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.0/go.mod h1:4wPNCkM22+oRe71oydP66K50ojDUC33XutSMi2pEF/M= -github.com/aws/aws-sdk-go-v2/service/sts v1.25.0 h1:sYIFy8tm1xQwRvVQ4CRuBGXKIg9sHNuG6+3UAQuoujk= -github.com/aws/aws-sdk-go-v2/service/sts v1.25.0/go.mod h1:S/LOQUeYDfJeJpFCIJDMjy7dwL4aA33HUdVi+i7uH8k= -github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/aws/smithy-go v1.16.0 h1:gJZEH/Fqh+RsvlJ1Zt4tVAtV6bKkp3cC+R6FCZMNzik= -github.com/aws/smithy-go v1.16.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= +github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= +github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= +github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= +github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.52.4 h1:vzLD0FyNU4uxf2QE5UDG0jSEitiJXbVEUwf2Sk3usF4= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.52.4/go.mod h1:CDqMoc3KRdZJ8qziW96J35lKH01Wq3B2aihtHj2JbRs= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.215.0 h1:6a5U/gnVIPWWtS2CCdOkrxos3Se8IL9jNMJLyD4BEU8= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.215.0/go.mod h1:ouvGEfHbLaIlWwpDpOVWPWR+YwO0HDv3vm5tYLq8ImY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= +github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k= +github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/cenk/backoff v2.2.1+incompatible h1:djdFT7f4gF2ttuzRKPbMOWgZajgesItGLwG5FTQKmmE= +github.com/cenk/backoff v2.2.1+incompatible/go.mod h1:7FtoeaSnHoZnmZzz47cM35Y9nSW7tNyaidugnHTaFDE= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/dustinkirkland/golang-petname v0.0.0-20231002161417-6a283f1aaaf2 h1:S6Dco8FtAhEI/qkg/00H6RdEGC+MCy5GPiQ+xweNRFE= -github.com/dustinkirkland/golang-petname v0.0.0-20231002161417-6a283f1aaaf2/go.mod h1:8AuBTZBRSFqEYBPYULd+NN474/zZBLP+6WeT5S9xlAc= +github.com/dustinkirkland/golang-petname v0.0.0-20240428194347-eebcea082ee0 h1:aYo8nnk3ojoQkP5iErif5Xxv0Mo0Ga/FR5+ffl/7+Nk= +github.com/dustinkirkland/golang-petname v0.0.0-20240428194347-eebcea082ee0/go.mod h1:8AuBTZBRSFqEYBPYULd+NN474/zZBLP+6WeT5S9xlAc= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= -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/getkin/kin-openapi v0.120.0 h1:MqJcNJFrMDFNc07iwE8iFC5eT2k/NPUFDIpNeiZv8Jg= -github.com/getkin/kin-openapi v0.120.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw= -github.com/go-faker/faker/v4 v4.1.1 h1:zkxj/JH/aezB4R6cTEMKU7qcVScGhlB3qRtF3D7K+rI= -github.com/go-faker/faker/v4 v4.1.1/go.mod h1:uuNc0PSRxF8nMgjGrrrU4Nw5cF30Jc6Kd0/FUTTYbhg= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk= +github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58= +github.com/go-faker/faker/v4 v4.5.0 h1:ARzAY2XoOL9tOUK+KSecUQzyXQsUaZHefjyF8x6YFHc= +github.com/go-faker/faker/v4 v4.5.0/go.mod h1:p3oq1GRjG2PZ7yqeFFfQI20Xm61DoBDlCA8RiSyZ48M= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= -github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= -github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= -github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= -github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= -github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= -github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= -github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= -github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= -github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc= -github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= -github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= -github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= -github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= -github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k= -github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= -github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= +github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= +github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= +github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= +github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= +github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= +github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= +github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= +github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= +github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= +github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= +github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= -github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= -github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= -github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= -github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= -github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= -github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= -github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= -github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= -github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= -github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= -github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= -github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= -github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= -github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= -github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= -github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= -github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= -github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.5.2/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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU= github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk= -github.com/google/uuid v1.1.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/haproxytech/client-native/v5 v5.0.1-0.20231106120845-bee8caf96cec h1:SmDJA/kvuUSO+ieGbbWBF0lAILRB9jrc0LS6k+G4DRk= -github.com/haproxytech/client-native/v5 v5.0.1-0.20231106120845-bee8caf96cec/go.mod h1:EO613ZEt1eMTaUAHRVHHJRKc9JSzVNeLMvPWxhjztz0= -github.com/haproxytech/config-parser/v5 v5.0.1-0.20230913105857-585d83cb48ba h1:l4oTCSr7nrZ9vZ7VVJ5GX64BRtZLuD9ePG8B5clbjHI= -github.com/haproxytech/config-parser/v5 v5.0.1-0.20230913105857-585d83cb48ba/go.mod h1:ASOyT1KguwXaY0NfoLNjLLs0OlnYHnFgUJsdJe6NhZg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/haproxytech/client-native/v5 v5.1.17 h1:BDuAVlHBmjPcc6s99SWqqbWiBwVSzCyALuL8srtFwMw= +github.com/haproxytech/client-native/v5 v5.1.17/go.mod h1:/ms7QkqUYwCBm31zYl/qT/0r/TBDRt60pusERVZ2j0Q= github.com/haproxytech/go-logger v1.1.0 h1:HgGtYaI1ApkvbQdsm7f9AzQQoxTB7w37criTflh7IQE= github.com/haproxytech/go-logger v1.1.0/go.mod h1:OekUd8HCb7ubxMplzHUPBTHNxZmddOWfOjWclZsqIeM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= -github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -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/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= +github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= -github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= 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/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lestrrat-go/apache-logformat v0.0.0-20210106032603-24d066f940f8 h1:YTyb23TYmO5068vabZIrocTP6Ql1bX53Qhkf7IjYU08= @@ -177,22 +105,12 @@ github.com/lestrrat-go/apache-logformat v0.0.0-20210106032603-24d066f940f8/go.mo github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/strftime v0.0.0-20180821113735-8b31f9c59b0f/go.mod h1:RMlXygAD3c48Psmr06d2G75L4E4xxzxkIe/+ppX9eAU= -github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= -github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/maruel/panicparse/v2 v2.3.1 h1:NtJavmbMn0DyzmmSStE8yUsmPZrZmudPH7kplxBinOA= -github.com/maruel/panicparse/v2 v2.3.1/go.mod h1:s3UmQB9Fm/n7n/prcD2xBGDkwXD6y2LeZnhbEXvs9Dg= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -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= +github.com/lestrrat-go/strftime v1.1.0 h1:gMESpZy44/4pXLO/m+sL0yBd1W6LjgjrrD4a68Gapyg= +github.com/lestrrat-go/strftime v1.1.0/go.mod h1:uzeIB52CeUJenCo1syghlugshMysrqUT51HlxphXVeI= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/maruel/panicparse/v2 v2.5.0 h1:yCtuS0FWjfd0RTYMXGpDvWcb0kINm8xJGu18/xMUh00= +github.com/maruel/panicparse/v2 v2.5.0/go.mod h1:DA2fDiBk63bKfBf4CVZP9gb4fuvzdPbLDsSI873hweQ= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -202,155 +120,66 @@ 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/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/nathanaelle/syslog5424/v2 v2.0.5 h1:oLVYQmKnv3nlnmvlbBWM+iWl9AONcU+tuxIL0fjko5A= github.com/nathanaelle/syslog5424/v2 v2.0.5/go.mod h1:f9MvsGkLOtYh2VzLT4Pjuwx3+Xv2EogxJNda+HLPDus= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= +github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= +github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea h1:sKwxy1H95npauwu8vtF95vG/syrL0p8fSZo/XlDg5gk= +github.com/peterbourgon/g2s v0.0.0-20170223122336-d4e7ad98afea/go.mod h1:1VcHEd3ro4QMoHfiNl/j7Jkln9+KQuorp0PItHMJYNg= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rubyist/circuitbreaker v2.2.1+incompatible h1:KUKd/pV8Geg77+8LNDwdow6rVCAYOp8+kHUyFvL6Mhk= +github.com/rubyist/circuitbreaker v2.2.1+incompatible/go.mod h1:Ycs3JgJADPuzJDwffe12k6BZT8hxVi6lFK+gWYJLN4A= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -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/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= +github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= +github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= +github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= -go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= -go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE= -go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= +go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/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-20220408201424-a24fb2fb8a0f/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= 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-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handlers/backend.go b/handlers/backend.go index c7654135..f742b7c7 100644 --- a/handlers/backend.go +++ b/handlers/backend.go @@ -16,13 +16,15 @@ package handlers import ( - "github.com/haproxytech/dataplaneapi/log" + "net/http" + "slices" "github.com/go-openapi/runtime/middleware" client_native "github.com/haproxytech/client-native/v5" "github.com/haproxytech/client-native/v5/models" "github.com/haproxytech/dataplaneapi/haproxy" + "github.com/haproxytech/dataplaneapi/log" "github.com/haproxytech/dataplaneapi/misc" "github.com/haproxytech/dataplaneapi/operations/backend" ) @@ -65,6 +67,113 @@ func logDeprecatedFieldsWarning(b *models.Backend) { if b.HTTPServerClose != "" { log.Warningf("Field HTTPServerClose is deprecated. Use HTTPConnectionMode.") } + if b.ForcePersist != nil { + log.Warningf("Field force_persist is deprecated. Use force_persist_list.") + } + if b.IgnorePersist != nil { + log.Warningf("Field ignore_persist is deprecated. Use ignore_persist_list.") + } +} + +// handleDeprecatedBackendFields adds backward compatibility support for the fields +// force_persist and ignore_persist that are deprecated in favour of force_persist_list +// and ignore_persist_list. +func handleDeprecatedBackendFields(method string, payload *models.Backend, onDisk *models.Backend) { + // A fair amount of code duplication in this function is tolerated because this code is expected to be + // short-lived - it should be removed at the end of the sunset period for the deprecated fields. + + if method == http.MethodGet { + // Populate force_persist with the first element of force_persist_list if it is present. + if len(payload.ForcePersistList) > 0 { + payload.ForcePersist = &models.BackendForcePersist{ + Cond: payload.ForcePersistList[0].Cond, + CondTest: payload.ForcePersistList[0].CondTest, + } + } + // Populate ignore_persist with the first element of ignore_persist_list if it is present. + if len(payload.IgnorePersistList) > 0 { + payload.IgnorePersist = &models.BackendIgnorePersist{ + Cond: payload.IgnorePersistList[0].Cond, + CondTest: payload.IgnorePersistList[0].CondTest, + } + } + return + } + + if payload.ForcePersist != nil && len(payload.ForcePersistList) == 0 { + if method == http.MethodPost || (method == http.MethodPut && (onDisk == nil || len(onDisk.ForcePersistList) == 0)) { + // Deprecated force_persist is present in a POST payload, or in a PUT payload when force_persist_list does not yet exist in the backend. + // Transform it into force_persist_list with the only element. + payload.ForcePersistList = []*models.ForcePersist{{ + Cond: payload.ForcePersist.Cond, + CondTest: payload.ForcePersist.CondTest, + }} + } else { + // Deprecated force_persist is present in a PUT payload, and force_persist_list already exists in the backend. + // Preserve the existing force_persist_list, and add or reposition the submitted force_persist to be its first element. + found := -1 + for i, item := range onDisk.ForcePersistList { + if *item.Cond == *payload.ForcePersist.Cond && *item.CondTest == *payload.ForcePersist.CondTest { + found = i + break + } + } + switch found { + case -1: + // force_persist value is not part of existing force_persist_list - insert it in the first position. + payload.ForcePersistList = slices.Insert(onDisk.ForcePersistList, 0, &models.ForcePersist{ + Cond: payload.ForcePersist.Cond, + CondTest: payload.ForcePersist.CondTest, + }) + case 0: + // force_persist value matches the first element of force_persist_list - preserve it without modification. + payload.ForcePersistList = onDisk.ForcePersistList + default: + // force_persist value matches another element of force_persist_list - move it to the first position. + payload.ForcePersistList = slices.Concat(onDisk.ForcePersistList[found:found+1], onDisk.ForcePersistList[:found], onDisk.ForcePersistList[found+1:]) + } + } + } + + if payload.IgnorePersist != nil && len(payload.IgnorePersistList) == 0 { + if method == http.MethodPost || (method == http.MethodPut && (onDisk == nil || len(onDisk.IgnorePersistList) == 0)) { + // Deprecated ignore_persist is present in a POST payload, or in a PUT payload when ignore_persist_list does not yet exist in the backend. + // Transform it into ignore_persist_list with the only element. + payload.IgnorePersistList = []*models.IgnorePersist{{ + Cond: payload.IgnorePersist.Cond, + CondTest: payload.IgnorePersist.CondTest, + }} + } else { + // Deprecated ignore_persist is present in a PUT payload, and ignore_persist_list already exists in the backend. + // Preserve the existing ignore_persist_list, and add or reposition the submitted ignore_persist to be its first element. + found := -1 + for i, item := range onDisk.IgnorePersistList { + if *item.Cond == *payload.IgnorePersist.Cond && *item.CondTest == *payload.IgnorePersist.CondTest { + found = i + break + } + } + switch found { + case -1: + // ignore_persist value is not part of existing ignore_persist_list - insert it in the first position. + payload.IgnorePersistList = slices.Insert(onDisk.IgnorePersistList, 0, &models.IgnorePersist{ + Cond: payload.IgnorePersist.Cond, + CondTest: payload.IgnorePersist.CondTest, + }) + case 0: + // ignore_persist value matches the first element of ignore_persist_list - preserve it without modification. + payload.IgnorePersistList = onDisk.IgnorePersistList + default: + // ignore_persist value matches another element of ignore_persist_list - move it to the first position. + payload.IgnorePersistList = slices.Concat(onDisk.IgnorePersistList[found:found+1], onDisk.IgnorePersistList[:found], onDisk.IgnorePersistList[found+1:]) + } + } + } + + // Remove force_persist and ignore_persist from the payload - at this point, they were either processed, + // or not present in the payload, or will be ignored because non-deprecated variants were submitted at the same time. + payload.ForcePersist = nil + payload.IgnorePersist = nil } // Handle executing the request and returning a response @@ -96,6 +205,10 @@ func (h *CreateBackendHandlerImpl) Handle(params backend.CreateBackendParams, pr return backend.NewCreateBackendDefault(int(*e.Code)).WithPayload(e) } + // Populate force_persist_list and ignore_persist_list if the corresponding + // deprecated fields force_persist or ignore_persist are present in the request payload. + handleDeprecatedBackendFields(http.MethodPost, params.Data, nil) + err = configuration.CreateBackend(params.Data, t, v) if err != nil { e := misc.HandleError(err) @@ -182,6 +295,10 @@ func (h *GetBackendHandlerImpl) Handle(params backend.GetBackendParams, principa e := misc.HandleError(err) return backend.NewGetBackendDefault(int(*e.Code)).WithPayload(e) } + + // Populate deprecated force_persist and ignore_persist fields in returned response. + handleDeprecatedBackendFields(http.MethodGet, bck, nil) + return backend.NewGetBackendOK().WithPayload(&backend.GetBackendOKBody{Version: v, Data: bck}) } @@ -203,6 +320,12 @@ func (h *GetBackendsHandlerImpl) Handle(params backend.GetBackendsParams, princi e := misc.HandleError(err) return backend.NewGetBackendsDefault(int(*e.Code)).WithPayload(e) } + + // Populate deprecated force_persist and ignore_persist fields in returned response. + for _, bck := range bcks { + handleDeprecatedBackendFields(http.MethodGet, bck, nil) + } + return backend.NewGetBackendsOK().WithPayload(&backend.GetBackendsOKBody{Version: v, Data: bcks}) } @@ -235,6 +358,17 @@ func (h *ReplaceBackendHandlerImpl) Handle(params backend.ReplaceBackendParams, return backend.NewReplaceBackendDefault(int(*e.Code)).WithPayload(e) } + // Populate or modify force_persist_list and ignore_persist_list if the corresponding + // deprecated fields force_persist or ignore_persist are present in the request payload. + if params.Data.ForcePersist != nil || params.Data.IgnorePersist != nil { + _, onDisk, confErr := configuration.GetBackend(params.Data.Name, t) + if confErr != nil { + e := misc.HandleError(confErr) + return backend.NewReplaceBackendDefault(int(*e.Code)).WithPayload(e) + } + handleDeprecatedBackendFields(http.MethodPut, params.Data, onDisk) + } + err = configuration.EditBackend(params.Name, params.Data, t, v) if err != nil { e := misc.HandleError(err) diff --git a/handlers/bind.go b/handlers/bind.go index 5646bbf9..ad47439e 100644 --- a/handlers/bind.go +++ b/handlers/bind.go @@ -16,7 +16,7 @@ package handlers import ( - "fmt" + "errors" "github.com/go-openapi/runtime/middleware" client_native "github.com/haproxytech/client-native/v5" @@ -60,10 +60,10 @@ func bindTypeParams(frontend *string, parentType *string, parentName *string) (p return "frontend", *frontend, nil } if parentType == nil || *parentType == "" { - return "", "", fmt.Errorf("parentType empty") + return "", "", errors.New("parentType empty") } if parentName == nil || *parentName == "" { - return "", "", fmt.Errorf("parentName empty") + return "", "", errors.New("parentName empty") } return *parentType, *parentName, nil } diff --git a/handlers/cluster.go b/handlers/cluster.go index 80b63ff1..c8dcd823 100644 --- a/handlers/cluster.go +++ b/handlers/cluster.go @@ -16,6 +16,7 @@ package handlers import ( + "errors" "fmt" "reflect" "strings" @@ -255,7 +256,7 @@ func (h *EditClusterHandlerImpl) Handle(params cluster.EditClusterParams, princi } return cluster.NewEditClusterOK().WithPayload(getClusterSettings(h.Config)) } - return h.err406(fmt.Errorf("dataplaneapi in single mode")) + return h.err406(errors.New("dataplaneapi in single mode")) } func (h *EditClusterHandlerImpl) err406(err error) middleware.Responder { diff --git a/handlers/consul.go b/handlers/consul.go index 51288c61..e369e7d3 100644 --- a/handlers/consul.go +++ b/handlers/consul.go @@ -141,7 +141,7 @@ func (c *ReplaceConsulHandlerImpl) Handle(params service_discovery.ReplaceConsul return service_discovery.NewReplaceConsulDefault(int(*e.Code)).WithPayload(e) } setFilters(params.Data) - if *params.Data.HealthCheckPolicy == models.ConsulHealthCheckPolicyMin && params.Data.HealthCheckPolicyMin <= 0 { + if params.Data.HealthCheckPolicy != nil && *params.Data.HealthCheckPolicy == models.ConsulHealthCheckPolicyMin && params.Data.HealthCheckPolicyMin <= 0 { e := &models.Error{ Message: misc.StringP("health_check_policy_min is required for 'min' health_check_policy"), Code: misc.Int64P(int(misc.ErrHTTPBadRequest)), diff --git a/handlers/frontend.go b/handlers/frontend.go index 98ce7c28..612d4960 100644 --- a/handlers/frontend.go +++ b/handlers/frontend.go @@ -228,7 +228,7 @@ func (h *ReplaceFrontendHandlerImpl) Handle(params frontend.ReplaceFrontendParam return frontend.NewReplaceFrontendDefault(int(*e.Code)).WithPayload(e) } if params.TransactionID == nil { - reload := changeThroughRuntimeAPI(*params.Data, *ondisk, "", "", h.Client) + reload := changeThroughRuntimeAPI(*params.Data, *ondisk, "", h.Client) if reload { if *params.ForceReload { err := h.ReloadAgent.ForceReload() diff --git a/handlers/information.go b/handlers/information.go index 00652d45..bbb5bb89 100644 --- a/handlers/information.go +++ b/handlers/information.go @@ -97,7 +97,6 @@ func (h *GetInfoHandlerImpl) Handle(params information.GetInfoParams, principal sys.MemInfo.TotalMemory = int64(mem.Total) sys.MemInfo.FreeMemory = int64(mem.Free) } - //nolint:govet if uptime, err := host.Uptime(); err == nil { uptimeInt64 := int64(uptime) sys.Uptime = &uptimeInt64 diff --git a/handlers/runtime.go b/handlers/runtime.go index 4f176e80..9ea5316a 100644 --- a/handlers/runtime.go +++ b/handlers/runtime.go @@ -33,7 +33,7 @@ var RuntimeSupportedFields = map[string][]string{ // ChangeThroughRuntimeAPI checks if something can be changed through the runtime API, and // returns false if reload is not needed, or true if needed. -func changeThroughRuntimeAPI(data, ondisk interface{}, parentName, parentType string, client client_native.HAProxyClient) (reload bool) { +func changeThroughRuntimeAPI(data, ondisk interface{}, parentName string, client client_native.HAProxyClient) (reload bool) { // reflect kinds and values are loosely checked as they are bound strictly in // schema, but in case of any panic, we will log and reload to ensure // changes go through @@ -183,7 +183,7 @@ func compareObjects(data, ondisk interface{}) []string { diff := make([]string, 0) dataVal := reflect.ValueOf(data) ondiskVal := reflect.ValueOf(ondisk) - for i := 0; i < dataVal.NumField(); i++ { + for i := range dataVal.NumField() { fName := dataVal.Type().Field(i).Name dataField := dataVal.FieldByName(fName) ondiskField := ondiskVal.FieldByName(fName) diff --git a/handlers/server.go b/handlers/server.go index f28f40e7..f6dea0a4 100644 --- a/handlers/server.go +++ b/handlers/server.go @@ -16,7 +16,7 @@ package handlers import ( - "fmt" + "errors" "github.com/go-openapi/runtime/middleware" client_native "github.com/haproxytech/client-native/v5" @@ -61,10 +61,10 @@ func serverTypeParams(backend *string, parentType *string, parentName *string) ( return "backend", *backend, nil } if parentType == nil || *parentType == "" { - return "", "", fmt.Errorf("parentType empty") + return "", "", errors.New("parentType empty") } if parentName == nil || *parentName == "" { - return "", "", fmt.Errorf("parentName empty") + return "", "", errors.New("parentName empty") } return *parentType, *parentName, nil } @@ -308,7 +308,7 @@ func (h *ReplaceServerHandlerImpl) Handle(params server.ReplaceServerParams, pri return server.NewReplaceServerDefault(int(*e.Code)).WithPayload(e) } if params.TransactionID == nil { - reload := changeThroughRuntimeAPI(*params.Data, *ondisk, pType, "", h.Client) + reload := changeThroughRuntimeAPI(*params.Data, *ondisk, pName, h.Client) if reload { if *params.ForceReload { err := h.ReloadAgent.ForceReload() diff --git a/handlers/server_template.go b/handlers/server_template.go index 58b334c9..3e5113e6 100644 --- a/handlers/server_template.go +++ b/handlers/server_template.go @@ -232,7 +232,7 @@ func (h *ReplaceServerTemplateHandlerImpl) Handle(params server_template.Replace return server_template.NewReplaceServerTemplateDefault(int(*e.Code)).WithPayload(e) } if params.TransactionID == nil { - reload := changeThroughRuntimeAPI(*params.Data, *ondisk, params.Backend, "", h.Client) + reload := changeThroughRuntimeAPI(*params.Data, *ondisk, params.Backend, h.Client) if reload { if *params.ForceReload { err := h.ReloadAgent.ForceReload() diff --git a/handlers/transaction.go b/handlers/transaction.go index 23320921..109151f6 100644 --- a/handlers/transaction.go +++ b/handlers/transaction.go @@ -86,7 +86,6 @@ func (h *DeleteTransactionHandlerImpl) Handle(params transactions.DeleteTransact return transactions.NewDeleteTransactionDefault(int(*e.Code)).WithPayload(e) } err = configuration.DeleteTransaction(params.ID) - if err != nil { e := misc.HandleError(err) if strings.HasSuffix(*e.Message, "does not exist") { diff --git a/haproxy/reload_agent.go b/haproxy/reload_agent.go index 3f804e4a..97ac886b 100644 --- a/haproxy/reload_agent.go +++ b/haproxy/reload_agent.go @@ -18,6 +18,7 @@ package haproxy import ( "bytes" "context" + "errors" "fmt" "io" "os" @@ -42,10 +43,10 @@ const ( type IReloadAgent interface { Reload() string - ReloadWithCallback(func()) string + ReloadWithCallback(callback func()) string Restart() error ForceReload() error - ForceReloadWithCallback(func()) error + ForceReloadWithCallback(callback func()) error Status() (bool, error) GetReloads() models.Reloads GetReload(id string) *models.Reload @@ -479,7 +480,7 @@ func (ra *ReloadAgent) Status() (bool, error) { func (ra *ReloadAgent) status() (bool, error) { if ra.statusCmd == "" { - return false, fmt.Errorf("status command not configured") + return false, errors.New("status command not configured") } resp, err := execCmd(ra.statusCmd) if err != nil { @@ -511,7 +512,7 @@ type ReloadError struct { // Error implementation for ConfError func (e *ReloadError) Error() string { - return fmt.Sprintf(e.msg) + return e.msg } // NewReloadError constructor for ReloadError diff --git a/haproxy/reload_agent_test.go b/haproxy/reload_agent_test.go index 04ca67d4..d3ac7658 100644 --- a/haproxy/reload_agent_test.go +++ b/haproxy/reload_agent_test.go @@ -22,16 +22,17 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestReloadAgentDoesntMissReloads(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - f, err := os.CreateTemp("", "config.cfg") - assert.Nil(t, err) + ctx, cancel := context.WithCancel(t.Context()) + f, err := os.CreateTemp(t.TempDir(), "config.cfg") + require.NoError(t, err) assert.NotNil(t, f) t.Cleanup(func() { cancel() - assert.Nil(t, os.Remove(f.Name())) + assert.NoError(t, os.Remove(f.Name())) }) reloadAgentParams := ReloadAgentParams{ @@ -45,7 +46,7 @@ func TestReloadAgentDoesntMissReloads(t *testing.T) { } ra, err := NewReloadAgent(reloadAgentParams) - assert.Nil(t, err) + require.NoError(t, err) assert.NotNil(t, ra) var reloadID, firstReloadID, secondReloadID string diff --git a/log/logger.go b/log/logger.go index 717d3718..ca5b8e57 100644 --- a/log/logger.go +++ b/log/logger.go @@ -18,119 +18,102 @@ type ACLLogger struct { func (l *Logger) Log(level logrus.Level, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Log(level, args...) } } func (l *Logger) Logf(level logrus.Level, format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Logf(level, format, args...) } } func (l *Logger) Print(args ...interface{}) { for _, log := range l.loggers { - log := log go log.Print(args...) } } func (l *Logger) Trace(args ...interface{}) { for _, log := range l.loggers { - log := log go log.Trace(args...) } } func (l *Logger) Debug(args ...interface{}) { for _, log := range l.loggers { - log := log go log.Debug(args...) } } func (l *Logger) Info(args ...interface{}) { for _, log := range l.loggers { - log := log go log.Info(args...) } } func (l *Logger) Warning(args ...interface{}) { for _, log := range l.loggers { - log := log go log.Warning(args...) } } func (l *Logger) Error(args ...interface{}) { for _, log := range l.loggers { - log := log go log.Error(args...) } } func (l *Logger) Panic(args ...interface{}) { for _, log := range l.loggers { - log := log go log.Panic(args...) } } func (l *Logger) Printf(format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Printf(format, args...) } } func (l *Logger) Tracef(format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Tracef(format, args...) } } func (l *Logger) Debugf(format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Debugf(format, args...) } } func (l *Logger) Infof(format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Infof(format, args...) } } func (l *Logger) Warningf(format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Warningf(format, args...) } } func (l *Logger) Errorf(format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Errorf(format, args...) } } func (l *Logger) Panicf(format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.Panicf(format, args...) } } func (l *Logger) Fatalln(args ...interface{}) { for _, log := range l.loggers { - log := log log.Logln(logrus.FatalLevel, args...) } os.Exit(1) @@ -138,7 +121,6 @@ func (l *Logger) Fatalln(args ...interface{}) { func (l *Logger) Fatal(args ...interface{}) { for _, log := range l.loggers { - log := log log.Log(logrus.FatalLevel, args...) } os.Exit(1) @@ -146,7 +128,6 @@ func (l *Logger) Fatal(args ...interface{}) { func (l *Logger) Fatalf(format string, args ...interface{}) { for _, log := range l.loggers { - log := log log.Logf(logrus.FatalLevel, format, args...) } os.Exit(1) @@ -154,14 +135,12 @@ func (l *Logger) Fatalf(format string, args ...interface{}) { func (l *Logger) WithFieldsf(fields map[string]interface{}, level logrus.Level, format string, args ...interface{}) { for _, log := range l.loggers { - log := log go log.WithFields(fields).Logf(level, format, args...) } } func (l *Logger) WithFields(fields map[string]interface{}, level logrus.Level, args ...interface{}) { for _, log := range l.loggers { - log := log go log.WithFields(fields).Log(level, args...) } } diff --git a/log/rfc5424.go b/log/rfc5424.go index 4254cbf5..906009ab 100644 --- a/log/rfc5424.go +++ b/log/rfc5424.go @@ -16,10 +16,13 @@ package log import ( + "errors" "fmt" "strings" + "time" "github.com/nathanaelle/syslog5424/v2" + circuit "github.com/rubyist/circuitbreaker" "github.com/sirupsen/logrus" ) @@ -27,6 +30,10 @@ type RFC5424Hook struct { syslog *syslog5424.Syslog sender *syslog5424.Sender msgID string + + // Use a circuit breaker to pause sending messages to the syslog target + // in the presence of connection errors. + cb *circuit.Breaker } func (r RFC5424Hook) Levels() []logrus.Level { @@ -58,14 +65,20 @@ func (r RFC5424Hook) Fire(entry *logrus.Entry) (err error) { msg := strings.Join(messages, " ") - r.syslog.Channel(sev).Msgid(r.msgID).Log(msg) + // Do not perform any action unless the circuit breaker is either closed (reset), or is ready to retry. + if r.cb.Ready() { + r.syslog.Channel(sev).Msgid(r.msgID).Log(msg) + // Register any call as successful to enable automatic resets. + // Failures are registered asynchronously by the goroutine that consumes errors from the corresponding channel. + r.cb.Success() + } return } func NewRFC5424Hook(opts Target) (logrus.Hook, error) { if len(opts.SyslogAddr) == 0 { - return nil, fmt.Errorf("no address has been declared") + return nil, errors.New("no address has been declared") } priority := strings.Join([]string{opts.SyslogFacility, opts.SyslogLevel}, ".") @@ -74,7 +87,9 @@ func NewRFC5424Hook(opts Target) (logrus.Hook, error) { return nil, err } - slConn, _, err := syslog5424.Dial(opts.SyslogProto, opts.SyslogAddr) + // syslog5424.Dial() returns an error channel, which needs to be drained + // in order to avoid blocking. + slConn, errCh, err := syslog5424.Dial(opts.SyslogProto, opts.SyslogAddr) if err != nil { return nil, err } @@ -84,10 +99,64 @@ func NewRFC5424Hook(opts Target) (logrus.Hook, error) { return nil, err } - return &RFC5424Hook{syslog: syslogServer, sender: slConn, msgID: opts.SyslogMsgID}, nil + r := &RFC5424Hook{ + syslog: syslogServer, sender: slConn, msgID: opts.SyslogMsgID, + // We can change the circuit breaker settings as desired - including making + // them configurable and/or dynamically adjustable based on runtime conditions. + // + // Please note, however, that a 3-failure threshold breaker with default settings + // was found to work well with varying load and different states of a log target. + // Specifically, the breaker will remain tripped when sending messages to the target + // that is consistently failing, and will reset quickly when delivery begins to succeed. + cb: circuit.NewThresholdBreaker(3), + } + + // A signal channel that is used to stop the goroutine reporting on circuit breaker state changes. + doneCh := make(chan struct{}) + + // Consume errors from errCh until it is closed. + go func() { + for { + err, ok := <-errCh + if err != nil { + r.cb.Fail() // Register a failure with the circuit breaker. + } + if !ok { + close(doneCh) + return + } + } + }() + + // Report on circuit breaker state changes. + cbStateCh := r.cb.Subscribe() + go func() { + for { + select { + case e, ok := <-cbStateCh: + if !ok { + return + } + var state string + switch e { + case circuit.BreakerTripped: + state = "too many connection errors, log delivery is stopped until this improves" + case circuit.BreakerReset: + state = "resuming log delivery" + default: + continue + } + fmt.Println(time.Now().Format(time.RFC3339), "syslog target", opts.SyslogAddr, "("+opts.SyslogTag+"):", state) + case <-doneCh: + return + } + } + }() + + return r, nil } func (r RFC5424Hook) Close() error { - r.sender.End() + r.sender.End() // This will also close errCh returned by syslog.Dial() in NewRFC5424Hook(), causing related goroutines to exit. return nil } diff --git a/misc/misc.go b/misc/misc.go index bd5ac27b..16afab44 100644 --- a/misc/misc.go +++ b/misc/misc.go @@ -28,10 +28,10 @@ import ( "strings" "github.com/GehirnInc/crypt" + "github.com/haproxytech/client-native/v5/config-parser/types" "github.com/haproxytech/client-native/v5/configuration" client_errors "github.com/haproxytech/client-native/v5/errors" "github.com/haproxytech/client-native/v5/models" - "github.com/haproxytech/config-parser/v5/types" jsoniter "github.com/json-iterator/go" "github.com/haproxytech/dataplaneapi/haproxy" @@ -274,12 +274,26 @@ func HasOSArg(short, long, env string) bool { } func RandomString(size int) (string, error) { - b := make([]byte, size) + str, err := randomString(size) + if err != nil { + return "", err + } + for len(str) < size { + str2, _ := randomString(size) + str += str2 + } + return str[:size], nil +} + +// randomString generates a random string of the recommended size. +// Result is not guaranteed to be correct length. +func randomString(recommendedSize int) (string, error) { + b := make([]byte, recommendedSize+8) _, err := rand.Read(b) result := strings.ReplaceAll(base64.URLEncoding.EncodeToString(b), `=`, ``) result = strings.ReplaceAll(result, `-`, ``) result = strings.ReplaceAll(result, `_`, ``) - return result[:size], err + return result, err } func IsNetworkErr(err error) bool { @@ -308,7 +322,7 @@ func CreateClusterUser() (types.User, string, error) { if err != nil { return types.User{}, "", err } - name = fmt.Sprintf("dpapi-c-%s", name) + name = "dpapi-c-" + name log.Infof("Creating user %s for cluster connection", name) user := types.User{ Name: name, diff --git a/misc/misc_test.go b/misc/misc_test.go new file mode 100644 index 00000000..297c9522 --- /dev/null +++ b/misc/misc_test.go @@ -0,0 +1,34 @@ +// Copyright 2019 HAProxy Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package misc + +import ( + "math/rand" + "testing" +) + +func TestRandomString(t *testing.T) { + for range 1024 { + size := rand.Intn(512) + str, err := RandomString(size) + if err != nil { + t.Errorf("RandomString returned an error for size %d: %v", size, err) + } + if len(str) != size { + t.Errorf("RandomString returned a string of length %d for size %d", len(str), size) + } + } +} diff --git a/operations/acl/get_acl.go b/operations/acl/get_acl.go index 0eb694ab..42205754 100644 --- a/operations/acl/get_acl.go +++ b/operations/acl/get_acl.go @@ -153,6 +153,11 @@ func (o *GetACLOKBody) ContextValidate(ctx context.Context, formats strfmt.Regis func (o *GetACLOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getAclOK" + "." + "data") diff --git a/operations/backend/get_backend.go b/operations/backend/get_backend.go index 10c81a9c..76119408 100644 --- a/operations/backend/get_backend.go +++ b/operations/backend/get_backend.go @@ -153,6 +153,11 @@ func (o *GetBackendOKBody) ContextValidate(ctx context.Context, formats strfmt.R func (o *GetBackendOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getBackendOK" + "." + "data") diff --git a/operations/backend_switching_rule/get_backend_switching_rule.go b/operations/backend_switching_rule/get_backend_switching_rule.go index a3b901a0..bf30a699 100644 --- a/operations/backend_switching_rule/get_backend_switching_rule.go +++ b/operations/backend_switching_rule/get_backend_switching_rule.go @@ -153,6 +153,11 @@ func (o *GetBackendSwitchingRuleOKBody) ContextValidate(ctx context.Context, for func (o *GetBackendSwitchingRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getBackendSwitchingRuleOK" + "." + "data") diff --git a/operations/bind/get_bind.go b/operations/bind/get_bind.go index 81f5fcac..042e5ac8 100644 --- a/operations/bind/get_bind.go +++ b/operations/bind/get_bind.go @@ -153,6 +153,11 @@ func (o *GetBindOKBody) ContextValidate(ctx context.Context, formats strfmt.Regi func (o *GetBindOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getBindOK" + "." + "data") diff --git a/operations/cache/get_cache.go b/operations/cache/get_cache.go index 063d816d..82ea88b8 100644 --- a/operations/cache/get_cache.go +++ b/operations/cache/get_cache.go @@ -153,6 +153,11 @@ func (o *GetCacheOKBody) ContextValidate(ctx context.Context, formats strfmt.Reg func (o *GetCacheOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getCacheOK" + "." + "data") diff --git a/operations/data_plane_api.go b/operations/data_plane_api.go index fe81f0de..17f47f9d 100644 --- a/operations/data_plane_api.go +++ b/operations/data_plane_api.go @@ -77,7 +77,6 @@ import ( "github.com/haproxytech/dataplaneapi/operations/service_discovery" "github.com/haproxytech/dataplaneapi/operations/sites" "github.com/haproxytech/dataplaneapi/operations/specification" - "github.com/haproxytech/dataplaneapi/operations/specification_openapiv3" "github.com/haproxytech/dataplaneapi/operations/spoe" "github.com/haproxytech/dataplaneapi/operations/spoe_transactions" "github.com/haproxytech/dataplaneapi/operations/stats" @@ -91,6 +90,7 @@ import ( "github.com/haproxytech/dataplaneapi/operations/transactions" "github.com/haproxytech/dataplaneapi/operations/user" "github.com/haproxytech/dataplaneapi/operations/userlist" + "github.com/haproxytech/dataplaneapi/operations/version3" ) // NewDataPlaneAPI creates a new DataPlane instance @@ -685,8 +685,8 @@ func NewDataPlaneAPI(spec *loads.Document) *DataPlaneAPI { StorageGetOneStorageSSLCertificateHandler: storage.GetOneStorageSSLCertificateHandlerFunc(func(params storage.GetOneStorageSSLCertificateParams, principal interface{}) middleware.Responder { return middleware.NotImplemented("operation storage.GetOneStorageSSLCertificate has not yet been implemented") }), - SpecificationOpenapiv3GetOpenapiv3SpecificationHandler: specification_openapiv3.GetOpenapiv3SpecificationHandlerFunc(func(params specification_openapiv3.GetOpenapiv3SpecificationParams, principal interface{}) middleware.Responder { - return middleware.NotImplemented("operation specification_openapiv3.GetOpenapiv3Specification has not yet been implemented") + Version3GetOpenapiv3SpecificationHandler: version3.GetOpenapiv3SpecificationHandlerFunc(func(params version3.GetOpenapiv3SpecificationParams, principal interface{}) middleware.Responder { + return middleware.NotImplemented("operation version3.GetOpenapiv3Specification has not yet been implemented") }), PeerEntryGetPeerEntriesHandler: peer_entry.GetPeerEntriesHandlerFunc(func(params peer_entry.GetPeerEntriesParams, principal interface{}) middleware.Responder { return middleware.NotImplemented("operation peer_entry.GetPeerEntries has not yet been implemented") @@ -1473,8 +1473,8 @@ type DataPlaneAPI struct { StorageGetOneStorageMapHandler storage.GetOneStorageMapHandler // StorageGetOneStorageSSLCertificateHandler sets the operation handler for the get one storage s s l certificate operation StorageGetOneStorageSSLCertificateHandler storage.GetOneStorageSSLCertificateHandler - // SpecificationOpenapiv3GetOpenapiv3SpecificationHandler sets the operation handler for the get openapiv3 specification operation - SpecificationOpenapiv3GetOpenapiv3SpecificationHandler specification_openapiv3.GetOpenapiv3SpecificationHandler + // Version3GetOpenapiv3SpecificationHandler sets the operation handler for the get openapiv3 specification operation + Version3GetOpenapiv3SpecificationHandler version3.GetOpenapiv3SpecificationHandler // PeerEntryGetPeerEntriesHandler sets the operation handler for the get peer entries operation PeerEntryGetPeerEntriesHandler peer_entry.GetPeerEntriesHandler // PeerEntryGetPeerEntryHandler sets the operation handler for the get peer entry operation @@ -2362,8 +2362,8 @@ func (o *DataPlaneAPI) Validate() error { if o.StorageGetOneStorageSSLCertificateHandler == nil { unregistered = append(unregistered, "storage.GetOneStorageSSLCertificateHandler") } - if o.SpecificationOpenapiv3GetOpenapiv3SpecificationHandler == nil { - unregistered = append(unregistered, "specification_openapiv3.GetOpenapiv3SpecificationHandler") + if o.Version3GetOpenapiv3SpecificationHandler == nil { + unregistered = append(unregistered, "version3.GetOpenapiv3SpecificationHandler") } if o.PeerEntryGetPeerEntriesHandler == nil { unregistered = append(unregistered, "peer_entry.GetPeerEntriesHandler") @@ -3571,7 +3571,7 @@ func (o *DataPlaneAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } - o.handlers["GET"]["/specification_openapiv3"] = specification_openapiv3.NewGetOpenapiv3Specification(o.context, o.SpecificationOpenapiv3GetOpenapiv3SpecificationHandler) + o.handlers["GET"]["/specification_openapiv3"] = version3.NewGetOpenapiv3Specification(o.context, o.Version3GetOpenapiv3SpecificationHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } @@ -4073,6 +4073,6 @@ func (o *DataPlaneAPI) AddMiddlewareFor(method, path string, builder middleware. } o.Init() if h, ok := o.handlers[um][path]; ok { - o.handlers[method][path] = builder(h) + o.handlers[um][path] = builder(h) } } diff --git a/operations/declare_capture/get_declare_capture.go b/operations/declare_capture/get_declare_capture.go index dd9c832f..f97adc31 100644 --- a/operations/declare_capture/get_declare_capture.go +++ b/operations/declare_capture/get_declare_capture.go @@ -153,6 +153,11 @@ func (o *GetDeclareCaptureOKBody) ContextValidate(ctx context.Context, formats s func (o *GetDeclareCaptureOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getDeclareCaptureOK" + "." + "data") diff --git a/operations/defaults/get_defaults.go b/operations/defaults/get_defaults.go index e441a2be..db0ae1e9 100644 --- a/operations/defaults/get_defaults.go +++ b/operations/defaults/get_defaults.go @@ -153,6 +153,11 @@ func (o *GetDefaultsOKBody) ContextValidate(ctx context.Context, formats strfmt. func (o *GetDefaultsOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getDefaultsOK" + "." + "data") diff --git a/operations/defaults/get_defaults_section.go b/operations/defaults/get_defaults_section.go index c147785c..2fae0d27 100644 --- a/operations/defaults/get_defaults_section.go +++ b/operations/defaults/get_defaults_section.go @@ -153,6 +153,11 @@ func (o *GetDefaultsSectionOKBody) ContextValidate(ctx context.Context, formats func (o *GetDefaultsSectionOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getDefaultsSectionOK" + "." + "data") diff --git a/operations/dgram_bind/get_dgram_bind.go b/operations/dgram_bind/get_dgram_bind.go index 395be52a..870fe416 100644 --- a/operations/dgram_bind/get_dgram_bind.go +++ b/operations/dgram_bind/get_dgram_bind.go @@ -153,6 +153,11 @@ func (o *GetDgramBindOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetDgramBindOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getDgramBindOK" + "." + "data") diff --git a/operations/fcgi_app/get_fcgi_app.go b/operations/fcgi_app/get_fcgi_app.go index 15b0baa1..f87a594e 100644 --- a/operations/fcgi_app/get_fcgi_app.go +++ b/operations/fcgi_app/get_fcgi_app.go @@ -153,6 +153,11 @@ func (o *GetFCGIAppOKBody) ContextValidate(ctx context.Context, formats strfmt.R func (o *GetFCGIAppOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getFcgiAppOK" + "." + "data") diff --git a/operations/filter/get_filter.go b/operations/filter/get_filter.go index 08879e03..2b7173f0 100644 --- a/operations/filter/get_filter.go +++ b/operations/filter/get_filter.go @@ -153,6 +153,11 @@ func (o *GetFilterOKBody) ContextValidate(ctx context.Context, formats strfmt.Re func (o *GetFilterOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getFilterOK" + "." + "data") diff --git a/operations/frontend/get_frontend.go b/operations/frontend/get_frontend.go index 8e4cbabc..1aa6c347 100644 --- a/operations/frontend/get_frontend.go +++ b/operations/frontend/get_frontend.go @@ -153,6 +153,11 @@ func (o *GetFrontendOKBody) ContextValidate(ctx context.Context, formats strfmt. func (o *GetFrontendOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getFrontendOK" + "." + "data") diff --git a/operations/global/get_global.go b/operations/global/get_global.go index 84682d10..7e7e8d69 100644 --- a/operations/global/get_global.go +++ b/operations/global/get_global.go @@ -153,6 +153,11 @@ func (o *GetGlobalOKBody) ContextValidate(ctx context.Context, formats strfmt.Re func (o *GetGlobalOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getGlobalOK" + "." + "data") diff --git a/operations/group/get_group.go b/operations/group/get_group.go index 23efc0b6..05627188 100644 --- a/operations/group/get_group.go +++ b/operations/group/get_group.go @@ -151,6 +151,11 @@ func (o *GetGroupOKBody) ContextValidate(ctx context.Context, formats strfmt.Reg func (o *GetGroupOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getGroupOK" + "." + "data") diff --git a/operations/http_after_response_rule/get_http_after_response_rule.go b/operations/http_after_response_rule/get_http_after_response_rule.go index 7f436208..57b5a011 100644 --- a/operations/http_after_response_rule/get_http_after_response_rule.go +++ b/operations/http_after_response_rule/get_http_after_response_rule.go @@ -153,6 +153,11 @@ func (o *GetHTTPAfterResponseRuleOKBody) ContextValidate(ctx context.Context, fo func (o *GetHTTPAfterResponseRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getHttpAfterResponseRuleOK" + "." + "data") diff --git a/operations/http_check/get_http_check.go b/operations/http_check/get_http_check.go index 933c872f..4ed8c629 100644 --- a/operations/http_check/get_http_check.go +++ b/operations/http_check/get_http_check.go @@ -153,6 +153,11 @@ func (o *GetHTTPCheckOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetHTTPCheckOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getHttpCheckOK" + "." + "data") diff --git a/operations/http_error_rule/get_http_error_rule.go b/operations/http_error_rule/get_http_error_rule.go index caf6e7a5..bde95702 100644 --- a/operations/http_error_rule/get_http_error_rule.go +++ b/operations/http_error_rule/get_http_error_rule.go @@ -153,6 +153,11 @@ func (o *GetHTTPErrorRuleOKBody) ContextValidate(ctx context.Context, formats st func (o *GetHTTPErrorRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getHttpErrorRuleOK" + "." + "data") diff --git a/operations/http_errors/get_http_errors_section.go b/operations/http_errors/get_http_errors_section.go index 40b9e6de..86d6f707 100644 --- a/operations/http_errors/get_http_errors_section.go +++ b/operations/http_errors/get_http_errors_section.go @@ -153,6 +153,11 @@ func (o *GetHTTPErrorsSectionOKBody) ContextValidate(ctx context.Context, format func (o *GetHTTPErrorsSectionOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getHttpErrorsSectionOK" + "." + "data") diff --git a/operations/http_request_rule/get_http_request_rule.go b/operations/http_request_rule/get_http_request_rule.go index 4ad873d3..140c1df0 100644 --- a/operations/http_request_rule/get_http_request_rule.go +++ b/operations/http_request_rule/get_http_request_rule.go @@ -153,6 +153,11 @@ func (o *GetHTTPRequestRuleOKBody) ContextValidate(ctx context.Context, formats func (o *GetHTTPRequestRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getHttpRequestRuleOK" + "." + "data") diff --git a/operations/http_response_rule/get_http_response_rule.go b/operations/http_response_rule/get_http_response_rule.go index 15ce1e89..bd5c34b9 100644 --- a/operations/http_response_rule/get_http_response_rule.go +++ b/operations/http_response_rule/get_http_response_rule.go @@ -153,6 +153,11 @@ func (o *GetHTTPResponseRuleOKBody) ContextValidate(ctx context.Context, formats func (o *GetHTTPResponseRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getHttpResponseRuleOK" + "." + "data") diff --git a/operations/log_forward/get_log_forward.go b/operations/log_forward/get_log_forward.go index a4aa9f2b..76c3351c 100644 --- a/operations/log_forward/get_log_forward.go +++ b/operations/log_forward/get_log_forward.go @@ -153,6 +153,11 @@ func (o *GetLogForwardOKBody) ContextValidate(ctx context.Context, formats strfm func (o *GetLogForwardOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getLogForwardOK" + "." + "data") diff --git a/operations/log_target/get_log_target.go b/operations/log_target/get_log_target.go index 658bd57f..806d3311 100644 --- a/operations/log_target/get_log_target.go +++ b/operations/log_target/get_log_target.go @@ -153,6 +153,11 @@ func (o *GetLogTargetOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetLogTargetOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getLogTargetOK" + "." + "data") diff --git a/operations/mailer_entry/get_mailer_entry.go b/operations/mailer_entry/get_mailer_entry.go index 1f8f5bb3..e86537e7 100644 --- a/operations/mailer_entry/get_mailer_entry.go +++ b/operations/mailer_entry/get_mailer_entry.go @@ -153,6 +153,11 @@ func (o *GetMailerEntryOKBody) ContextValidate(ctx context.Context, formats strf func (o *GetMailerEntryOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getMailerEntryOK" + "." + "data") diff --git a/operations/mailers/get_mailers_section.go b/operations/mailers/get_mailers_section.go index f09a62a1..3275ca55 100644 --- a/operations/mailers/get_mailers_section.go +++ b/operations/mailers/get_mailers_section.go @@ -153,6 +153,11 @@ func (o *GetMailersSectionOKBody) ContextValidate(ctx context.Context, formats s func (o *GetMailersSectionOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getMailersSectionOK" + "." + "data") diff --git a/operations/nameserver/get_nameserver.go b/operations/nameserver/get_nameserver.go index b9159796..6556aee8 100644 --- a/operations/nameserver/get_nameserver.go +++ b/operations/nameserver/get_nameserver.go @@ -153,6 +153,11 @@ func (o *GetNameserverOKBody) ContextValidate(ctx context.Context, formats strfm func (o *GetNameserverOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getNameserverOK" + "." + "data") diff --git a/operations/peer/get_peer_section.go b/operations/peer/get_peer_section.go index bd7f58e8..bd1b3d89 100644 --- a/operations/peer/get_peer_section.go +++ b/operations/peer/get_peer_section.go @@ -153,6 +153,11 @@ func (o *GetPeerSectionOKBody) ContextValidate(ctx context.Context, formats strf func (o *GetPeerSectionOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getPeerSectionOK" + "." + "data") diff --git a/operations/peer_entry/get_peer_entry.go b/operations/peer_entry/get_peer_entry.go index 81ee60db..34b6c34f 100644 --- a/operations/peer_entry/get_peer_entry.go +++ b/operations/peer_entry/get_peer_entry.go @@ -153,6 +153,11 @@ func (o *GetPeerEntryOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetPeerEntryOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getPeerEntryOK" + "." + "data") diff --git a/operations/process_manager/get_program.go b/operations/process_manager/get_program.go index 3e75b1fc..67b6011e 100644 --- a/operations/process_manager/get_program.go +++ b/operations/process_manager/get_program.go @@ -153,6 +153,11 @@ func (o *GetProgramOKBody) ContextValidate(ctx context.Context, formats strfmt.R func (o *GetProgramOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getProgramOK" + "." + "data") diff --git a/operations/resolver/get_resolver.go b/operations/resolver/get_resolver.go index 60e9d32b..d47d20dd 100644 --- a/operations/resolver/get_resolver.go +++ b/operations/resolver/get_resolver.go @@ -153,6 +153,11 @@ func (o *GetResolverOKBody) ContextValidate(ctx context.Context, formats strfmt. func (o *GetResolverOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getResolverOK" + "." + "data") diff --git a/operations/ring/get_ring.go b/operations/ring/get_ring.go index 442e0c36..330b31cf 100644 --- a/operations/ring/get_ring.go +++ b/operations/ring/get_ring.go @@ -153,6 +153,11 @@ func (o *GetRingOKBody) ContextValidate(ctx context.Context, formats strfmt.Regi func (o *GetRingOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getRingOK" + "." + "data") diff --git a/operations/server/get_server.go b/operations/server/get_server.go index 168097a7..9e1cd23c 100644 --- a/operations/server/get_server.go +++ b/operations/server/get_server.go @@ -153,6 +153,11 @@ func (o *GetServerOKBody) ContextValidate(ctx context.Context, formats strfmt.Re func (o *GetServerOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getServerOK" + "." + "data") diff --git a/operations/server_switching_rule/get_server_switching_rule.go b/operations/server_switching_rule/get_server_switching_rule.go index 56467435..43a1b99d 100644 --- a/operations/server_switching_rule/get_server_switching_rule.go +++ b/operations/server_switching_rule/get_server_switching_rule.go @@ -153,6 +153,11 @@ func (o *GetServerSwitchingRuleOKBody) ContextValidate(ctx context.Context, form func (o *GetServerSwitchingRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getServerSwitchingRuleOK" + "." + "data") diff --git a/operations/server_template/get_server_template.go b/operations/server_template/get_server_template.go index dbf3aae6..054ac575 100644 --- a/operations/server_template/get_server_template.go +++ b/operations/server_template/get_server_template.go @@ -153,6 +153,11 @@ func (o *GetServerTemplateOKBody) ContextValidate(ctx context.Context, formats s func (o *GetServerTemplateOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getServerTemplateOK" + "." + "data") diff --git a/operations/service_discovery/get_a_w_s_region.go b/operations/service_discovery/get_a_w_s_region.go index 11433bbd..04f46171 100644 --- a/operations/service_discovery/get_a_w_s_region.go +++ b/operations/service_discovery/get_a_w_s_region.go @@ -150,6 +150,11 @@ func (o *GetAWSRegionOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetAWSRegionOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getAWSRegionOK" + "." + "data") diff --git a/operations/service_discovery/get_consul.go b/operations/service_discovery/get_consul.go index 2962c1ba..db6824a9 100644 --- a/operations/service_discovery/get_consul.go +++ b/operations/service_discovery/get_consul.go @@ -150,6 +150,11 @@ func (o *GetConsulOKBody) ContextValidate(ctx context.Context, formats strfmt.Re func (o *GetConsulOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getConsulOK" + "." + "data") diff --git a/operations/sites/get_site.go b/operations/sites/get_site.go index e7c7c728..8a28d567 100644 --- a/operations/sites/get_site.go +++ b/operations/sites/get_site.go @@ -153,6 +153,11 @@ func (o *GetSiteOKBody) ContextValidate(ctx context.Context, formats strfmt.Regi func (o *GetSiteOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getSiteOK" + "." + "data") diff --git a/operations/spoe/get_spoe_agent.go b/operations/spoe/get_spoe_agent.go index ae069450..37914d78 100644 --- a/operations/spoe/get_spoe_agent.go +++ b/operations/spoe/get_spoe_agent.go @@ -156,6 +156,7 @@ func (o *GetSpoeAgentOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetSpoeAgentOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getSpoeAgentOK" + "." + "data") diff --git a/operations/spoe/get_spoe_group.go b/operations/spoe/get_spoe_group.go index 11adac0f..b2307055 100644 --- a/operations/spoe/get_spoe_group.go +++ b/operations/spoe/get_spoe_group.go @@ -156,6 +156,7 @@ func (o *GetSpoeGroupOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetSpoeGroupOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getSpoeGroupOK" + "." + "data") diff --git a/operations/spoe/get_spoe_message.go b/operations/spoe/get_spoe_message.go index ef18f06e..e2031402 100644 --- a/operations/spoe/get_spoe_message.go +++ b/operations/spoe/get_spoe_message.go @@ -156,6 +156,7 @@ func (o *GetSpoeMessageOKBody) ContextValidate(ctx context.Context, formats strf func (o *GetSpoeMessageOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getSpoeMessageOK" + "." + "data") diff --git a/operations/spoe/get_spoe_scope.go b/operations/spoe/get_spoe_scope.go index 7ea81d98..d8d0a680 100644 --- a/operations/spoe/get_spoe_scope.go +++ b/operations/spoe/get_spoe_scope.go @@ -160,6 +160,7 @@ func (o *GetSpoeScopeOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetSpoeScopeOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getSpoeScopeOK" + "." + "data") diff --git a/operations/stick_rule/get_stick_rule.go b/operations/stick_rule/get_stick_rule.go index 09f8bef3..38519ea2 100644 --- a/operations/stick_rule/get_stick_rule.go +++ b/operations/stick_rule/get_stick_rule.go @@ -153,6 +153,11 @@ func (o *GetStickRuleOKBody) ContextValidate(ctx context.Context, formats strfmt func (o *GetStickRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getStickRuleOK" + "." + "data") diff --git a/operations/stick_table/set_stick_table_entries.go b/operations/stick_table/set_stick_table_entries.go index 5b3aa3f1..5d485abe 100644 --- a/operations/stick_table/set_stick_table_entries.go +++ b/operations/stick_table/set_stick_table_entries.go @@ -170,6 +170,7 @@ func (o *SetStickTableEntriesBody) ContextValidate(ctx context.Context, formats func (o *SetStickTableEntriesBody) contextValidateDataType(ctx context.Context, formats strfmt.Registry) error { if o.DataType != nil { + if err := o.DataType.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("stick_table_entry" + "." + "data_type") diff --git a/operations/table/get_table.go b/operations/table/get_table.go index 1f6f99a0..64ebfe56 100644 --- a/operations/table/get_table.go +++ b/operations/table/get_table.go @@ -153,6 +153,11 @@ func (o *GetTableOKBody) ContextValidate(ctx context.Context, formats strfmt.Reg func (o *GetTableOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getTableOK" + "." + "data") diff --git a/operations/tcp_check/get_tcp_check.go b/operations/tcp_check/get_tcp_check.go index 3311b23b..3db16ec7 100644 --- a/operations/tcp_check/get_tcp_check.go +++ b/operations/tcp_check/get_tcp_check.go @@ -153,6 +153,11 @@ func (o *GetTCPCheckOKBody) ContextValidate(ctx context.Context, formats strfmt. func (o *GetTCPCheckOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getTcpCheckOK" + "." + "data") diff --git a/operations/tcp_request_rule/get_tcp_request_rule.go b/operations/tcp_request_rule/get_tcp_request_rule.go index 32268553..ab950b55 100644 --- a/operations/tcp_request_rule/get_tcp_request_rule.go +++ b/operations/tcp_request_rule/get_tcp_request_rule.go @@ -153,6 +153,11 @@ func (o *GetTCPRequestRuleOKBody) ContextValidate(ctx context.Context, formats s func (o *GetTCPRequestRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getTcpRequestRuleOK" + "." + "data") diff --git a/operations/tcp_response_rule/get_tcp_response_rule.go b/operations/tcp_response_rule/get_tcp_response_rule.go index 3f7eb8b4..b4ef153f 100644 --- a/operations/tcp_response_rule/get_tcp_response_rule.go +++ b/operations/tcp_response_rule/get_tcp_response_rule.go @@ -153,6 +153,11 @@ func (o *GetTCPResponseRuleOKBody) ContextValidate(ctx context.Context, formats func (o *GetTCPResponseRuleOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getTcpResponseRuleOK" + "." + "data") diff --git a/operations/user/get_user.go b/operations/user/get_user.go index 8f087968..f530c8ae 100644 --- a/operations/user/get_user.go +++ b/operations/user/get_user.go @@ -151,6 +151,11 @@ func (o *GetUserOKBody) ContextValidate(ctx context.Context, formats strfmt.Regi func (o *GetUserOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getUserOK" + "." + "data") diff --git a/operations/userlist/get_userlist.go b/operations/userlist/get_userlist.go index 63f34990..bc5144ad 100644 --- a/operations/userlist/get_userlist.go +++ b/operations/userlist/get_userlist.go @@ -153,6 +153,11 @@ func (o *GetUserlistOKBody) ContextValidate(ctx context.Context, formats strfmt. func (o *GetUserlistOKBody) contextValidateData(ctx context.Context, formats strfmt.Registry) error { if o.Data != nil { + + if swag.IsZero(o.Data) { // not required + return nil + } + if err := o.Data.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("getUserlistOK" + "." + "data") diff --git a/operations/specification_openapiv3/get_openapiv3_specification.go b/operations/version3/get_openapiv3_specification.go similarity index 98% rename from operations/specification_openapiv3/get_openapiv3_specification.go rename to operations/version3/get_openapiv3_specification.go index a230b44c..59793459 100644 --- a/operations/specification_openapiv3/get_openapiv3_specification.go +++ b/operations/version3/get_openapiv3_specification.go @@ -15,7 +15,7 @@ // limitations under the License. // -package specification_openapiv3 +package version3 // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the generate command diff --git a/operations/specification_openapiv3/get_openapiv3_specification_parameters.go b/operations/version3/get_openapiv3_specification_parameters.go similarity index 98% rename from operations/specification_openapiv3/get_openapiv3_specification_parameters.go rename to operations/version3/get_openapiv3_specification_parameters.go index 233ae5a3..8910da91 100644 --- a/operations/specification_openapiv3/get_openapiv3_specification_parameters.go +++ b/operations/version3/get_openapiv3_specification_parameters.go @@ -15,7 +15,7 @@ // limitations under the License. // -package specification_openapiv3 +package version3 // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command diff --git a/operations/specification_openapiv3/get_openapiv3_specification_responses.go b/operations/version3/get_openapiv3_specification_responses.go similarity index 99% rename from operations/specification_openapiv3/get_openapiv3_specification_responses.go rename to operations/version3/get_openapiv3_specification_responses.go index eb4fb89a..d26db70d 100644 --- a/operations/specification_openapiv3/get_openapiv3_specification_responses.go +++ b/operations/version3/get_openapiv3_specification_responses.go @@ -15,7 +15,7 @@ // limitations under the License. // -package specification_openapiv3 +package version3 // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command diff --git a/operations/specification_openapiv3/get_openapiv3_specification_urlbuilder.go b/operations/version3/get_openapiv3_specification_urlbuilder.go similarity index 98% rename from operations/specification_openapiv3/get_openapiv3_specification_urlbuilder.go rename to operations/version3/get_openapiv3_specification_urlbuilder.go index d9bf5d39..2c69d733 100644 --- a/operations/specification_openapiv3/get_openapiv3_specification_urlbuilder.go +++ b/operations/version3/get_openapiv3_specification_urlbuilder.go @@ -15,7 +15,7 @@ // limitations under the License. // -package specification_openapiv3 +package version3 // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the generate command diff --git a/rate/threshold_limit_test.go b/rate/threshold_limit_test.go index 508517a0..31e1dfe6 100644 --- a/rate/threshold_limit_test.go +++ b/rate/threshold_limit_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_thresholdLimit_LimitReached(t *testing.T) { @@ -37,6 +38,6 @@ func Test_thresholdLimit_LimitReached(t *testing.T) { }, limit: 10, } - assert.Nil(t, tl.LimitReached()) + require.NoError(t, tl.LimitReached()) }) } diff --git a/resilient/client.go b/resilient/client.go new file mode 100644 index 00000000..2e512944 --- /dev/null +++ b/resilient/client.go @@ -0,0 +1,69 @@ +// Copyright 2019 HAProxy Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package resilient + +import ( + "context" + "errors" + + client_native "github.com/haproxytech/client-native/v5" + "github.com/haproxytech/client-native/v5/runtime" + cn "github.com/haproxytech/dataplaneapi/client-native" + dataplaneapi_config "github.com/haproxytech/dataplaneapi/configuration" +) + +type Client struct { + client_native.HAProxyClient +} + +func NewClient(c client_native.HAProxyClient) *Client { + return &Client{ + c, + } +} + +// Runtime is a wrapper around HAProxyClient.Runtime +// that retries once to configure the runtime client if it failed +func (c *Client) Runtime() (runtime.Runtime, error) { + runtime, err := c.HAProxyClient.Runtime() + + // We already have a valid runtime + // Let's return it + if err == nil { + return runtime, nil + } + + // Now, for let's try to reconfigure once the runtime + cfg, err := c.HAProxyClient.Configuration() + if err != nil { + return nil, err + } + + dpapiCfg := dataplaneapi_config.Get() + haproxyOptions := dpapiCfg.HAProxy + + // Let's disable the delayed start by putting a max value to 0 + // This is important to not block the handlers by waiting the DelayedStartMax that we wait for when we start + haproxyOptions.DelayedStartMax = 0 + // let's retry + rnt := cn.ConfigureRuntimeClient(context.Background(), cfg, haproxyOptions) + if rnt == nil { + return nil, errors.New("retry - unable to configure runtime client") + } + c.HAProxyClient.ReplaceRuntime(rnt) + + return c.HAProxyClient.Runtime() +} diff --git a/server.go b/server.go index 21d19c3b..011b035c 100644 --- a/server.go +++ b/server.go @@ -96,7 +96,7 @@ type Server struct { ListenLimit int `long:"listen-limit" description:"limit the number of outstanding requests"` KeepAlive time.Duration `long:"keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)" default:"3m"` ReadTimeout time.Duration `long:"read-timeout" description:"maximum duration before timing out read of the request" default:"30s"` - WriteTimeout time.Duration `long:"write-timeout" description:"maximum duration before timing out write of the response" default:"60s"` + WriteTimeout time.Duration `long:"write-timeout" description:"maximum duration before timing out write of the response" default:"30s"` httpServerL net.Listener TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"`