Compare commits
1 Commits
ptabor-pat
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
123fe53561 |
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@ -19,8 +19,3 @@ updates:
|
||||
interval: weekly
|
||||
allow:
|
||||
- dependency-type: all
|
||||
|
||||
- package-ecosystem: docker
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
2
.github/workflows/build.yaml
vendored
2
.github/workflows/build.yaml
vendored
@ -23,7 +23,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- env:
|
||||
|
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
|
||||
uses: github/codeql-action/init@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
with:
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
@ -50,6 +50,6 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
|
||||
uses: github/codeql-action/autobuild@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
|
||||
uses: github/codeql-action/analyze@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
|
2
.github/workflows/contrib.yaml
vendored
2
.github/workflows/contrib.yaml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- run: |
|
||||
|
2
.github/workflows/coverage.yaml
vendored
2
.github/workflows/coverage.yaml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- env:
|
||||
|
6
.github/workflows/e2e-arm64.yaml
vendored
6
.github/workflows/e2e-arm64.yaml
vendored
@ -6,17 +6,19 @@ jobs:
|
||||
test:
|
||||
# this is to prevent the job to run at forked projects
|
||||
if: github.repository == 'etcd-io/etcd'
|
||||
runs-on: actuated-arm64-8cpu-8gb
|
||||
runs-on: actuated-arm64-8cpu-32gb
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- linux-arm64-e2e
|
||||
steps:
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v1
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- env:
|
||||
|
2
.github/workflows/e2e.yaml
vendored
2
.github/workflows/e2e.yaml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- env:
|
||||
|
2
.github/workflows/fuzzing.yaml
vendored
2
.github/workflows/fuzzing.yaml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- run: |
|
||||
|
2
.github/workflows/govuln.yaml
vendored
2
.github/workflows/govuln.yaml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- run: date
|
||||
|
2
.github/workflows/grpcproxy.yaml
vendored
2
.github/workflows/grpcproxy.yaml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- env:
|
||||
|
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- name: release
|
||||
|
4
.github/workflows/robustness-nightly.yaml
vendored
4
.github/workflows/robustness-nightly.yaml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
count: 80
|
||||
testTimeout: 200m
|
||||
artifactName: main-arm64
|
||||
runs-on: "['actuated-arm64-8cpu-8gb']"
|
||||
runs-on: "['actuated-arm64-8cpu-32gb']"
|
||||
release-35:
|
||||
uses: ./.github/workflows/robustness-template.yaml
|
||||
with:
|
||||
@ -43,7 +43,7 @@ jobs:
|
||||
count: 100
|
||||
testTimeout: 200m
|
||||
artifactName: release-35-arm64
|
||||
runs-on: "['actuated-arm64-8cpu-8gb']"
|
||||
runs-on: "['actuated-arm64-8cpu-32gb']"
|
||||
release-34:
|
||||
uses: ./.github/workflows/robustness-template.yaml
|
||||
with:
|
||||
|
4
.github/workflows/robustness-template.yaml
vendored
4
.github/workflows/robustness-template.yaml
vendored
@ -27,10 +27,12 @@ jobs:
|
||||
timeout-minutes: 210
|
||||
runs-on: ${{ fromJson(inputs.runs-on) }}
|
||||
steps:
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v1
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- name: test-robustness
|
||||
|
2
.github/workflows/robustness.yaml
vendored
2
.github/workflows/robustness.yaml
vendored
@ -18,4 +18,4 @@ jobs:
|
||||
count: 12
|
||||
testTimeout: 30m
|
||||
artifactName: main-arm64
|
||||
runs-on: "['actuated-arm64-8cpu-8gb']"
|
||||
runs-on: "['actuated-arm64-8cpu-32gb']"
|
||||
|
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@ -50,6 +50,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@b374143c1149a9115d881581d29b8390bbcbb59c # v3.22.11
|
||||
uses: github/codeql-action/upload-sarif@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
2
.github/workflows/static-analysis.yaml
vendored
2
.github/workflows/static-analysis.yaml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- id: golangci_lint_version
|
||||
|
4
.github/workflows/tests-template.yaml
vendored
4
.github/workflows/tests-template.yaml
vendored
@ -26,10 +26,12 @@ jobs:
|
||||
- linux-${{ inputs.arch }}-unit-4-cpu
|
||||
- linux-386-unit-1-cpu
|
||||
steps:
|
||||
- name: Collect Workflow Telemetry
|
||||
uses: catchpoint/workflow-telemetry-action@v1
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: goversion
|
||||
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: ${{ steps.goversion.outputs.goversion }}
|
||||
- env:
|
||||
|
2
.github/workflows/tests.yaml
vendored
2
.github/workflows/tests.yaml
vendored
@ -12,4 +12,4 @@ jobs:
|
||||
uses: ./.github/workflows/tests-template.yaml
|
||||
with:
|
||||
arch: arm64
|
||||
runs-on: actuated-arm64-8cpu-8gb
|
||||
runs-on: actuated-arm64-8cpu-32gb
|
||||
|
@ -1 +1 @@
|
||||
1.21.5
|
||||
1.21.4
|
||||
|
@ -2,15 +2,6 @@
|
||||
|
||||
Previous change logs can be found at [CHANGELOG-3.3](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.3.md).
|
||||
|
||||
## v3.4.29 (tbd)
|
||||
|
||||
### etcd server
|
||||
- [Disable following HTTP redirects in peer communication](https://github.com/etcd-io/etcd/pull/17112)
|
||||
- [Add livez/readyz HTTP endpoints](https://github.com/etcd-io/etcd/pull/17128)
|
||||
|
||||
### Dependencies
|
||||
- Compile binaries using go [1.20.12](https://github.com/etcd-io/etcd/pull/17076).
|
||||
|
||||
<hr>
|
||||
|
||||
## v3.4.28 (2023-11-23)
|
||||
|
@ -4,19 +4,14 @@ Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/
|
||||
|
||||
<hr>
|
||||
|
||||
## v3.5.12 (tbd)
|
||||
|
||||
### etcd server
|
||||
- [Add livez/readyz HTTP endpoints](https://github.com/etcd-io/etcd/pull/17039)
|
||||
|
||||
## v3.5.11 (2023-12-07)
|
||||
## v3.5.11 (tbd)
|
||||
|
||||
### etcd server
|
||||
- Fix distributed tracing by ensuring `--experimental-distributed-tracing-sampling-rate` configuration option is available to [set tracing sample rate](https://github.com/etcd-io/etcd/pull/16951).
|
||||
- Fix [url redirects while checking peer urls during new member addition](https://github.com/etcd-io/etcd/pull/16986)
|
||||
|
||||
### Dependencies
|
||||
- Compile binaries using [go 1.20.12](https://github.com/etcd-io/etcd/pull/17077)
|
||||
- Compile binaries using [go 1.20.11](https://github.com/etcd-io/etcd/pull/16915)
|
||||
- Fix [CVE-2023-47108](https://github.com/advisories/GHSA-8pgv-569h-w5rw) by [bumping go.opentelemetry.io/otel to 1.20.0 and go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc to 0.46.0](https://github.com/etcd-io/etcd/pull/16946).
|
||||
|
||||
<hr>
|
||||
|
@ -1,5 +1,5 @@
|
||||
ARG ARCH=amd64
|
||||
FROM --platform=linux/${ARCH} gcr.io/distroless/static-debian12@sha256:4a2c1a51ae5e10ec4758a0f981be3ce5d6ac55445828463fce8dff3a355e0b75
|
||||
FROM --platform=linux/${ARCH} gcr.io/distroless/static-debian12
|
||||
|
||||
ADD etcd /usr/local/bin/
|
||||
ADD etcdctl /usr/local/bin/
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Roadmap
|
||||
# roadmap
|
||||
|
||||
etcd uses GitHub milestones to track all tasks in each major or minor release. The `roadmap.md` file only records the
|
||||
etcd uses GitHub milestones to track all tasks in each major or minor release. The roadmap.md file only records the
|
||||
most important tasks for each release. The list is based on current maintainers capacity that may shift over time.
|
||||
Proposed milestones is what we think we can deliver with people we have. If we have more support on the important
|
||||
stuff, we could pick up more items from backlog. Note that etcd will continue to mainly focus on technical debt over
|
||||
@ -13,24 +13,24 @@ Each item has an assigned priority:
|
||||
|
||||
## v3.6.0
|
||||
|
||||
For a full list of tasks in `v3.6.0`, please see [milestone etcd-v3.6](https://github.com/etcd-io/etcd/milestone/38).
|
||||
For a full list of tasks in v3.6.0, please see [milestone etcd-v3.6](https://github.com/etcd-io/etcd/milestone/38).
|
||||
|
||||
| Title | Priority | Status | Note |
|
||||
|--------------------------------------------------------------------------------------------------------------------|----------|-------------|--------------------------------------------------------------------------------------------------------------|
|
||||
| [Support downgrade](https://github.com/etcd-io/etcd/issues/11716) | P0 | In progress | etcd will support downgrade starting from 3.6.0. But it will also support offline downgrade from 3.5 to 3.4. |
|
||||
| [StoreV2 deprecation](https://github.com/etcd-io/etcd/issues/12913) | P0 | In progress | This task will be covered in both 3.6 and 3.7. |
|
||||
| [Release raft 3.6.0](https://github.com/etcd-io/raft/issues/89) | P0 | Not started | etcd 3.6.0 will depends on raft 3.6.0 |
|
||||
| [Release bbolt 1.4.0](https://github.com/etcd-io/bbolt/issues/553) | P0 | Not started | etcd 3.6.0 will depends on bbolt 1.4.0 |
|
||||
| [Support /livez and /readyz endpoints](https://github.com/etcd-io/etcd/issues/16007) | P1 | In progress | It provides clearer APIs, and can also workaround the stalled writes issue |
|
||||
| [Bump gRPC](https://github.com/etcd-io/etcd/issues/16290) | P1 | Completed | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. |
|
||||
| [Deprecate grpc-gateway or bump it](https://github.com/etcd-io/etcd/issues/14499) | P1 | Completed | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. |
|
||||
| [bbolt: Add logger into bbolt](https://github.com/etcd-io/bbolt/issues/509) | P1 | In progress | It's important to diagnose bbolt issues |
|
||||
| [bbolt: Add surgery commands](https://github.com/etcd-io/bbolt/issues/370) | P1 | Completed | Surgery commands are important for fixing corrupted db files |
|
||||
| [Evaluate and (Gradulate or deprecate/remove) experimental features](https://github.com/etcd-io/etcd/issues/16292) | P2 | Not started | This task will be covered in both 3.6 and 3.7. |
|
||||
| Title | Priority | Note |
|
||||
|--------------------------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------------|
|
||||
| [Support downgrade](https://github.com/etcd-io/etcd/issues/11716) | P0 | etcd will support downgrade starting from 3.6.0. But it will also support offline downgrade from 3.5 to 3.4. |
|
||||
| [StoreV2 deprecation](https://github.com/etcd-io/etcd/issues/12913) | P0 | This task will be covered in both 3.6 and 3.7. |
|
||||
| [Release raft 3.6.0](https://github.com/etcd-io/raft/issues/89) | P0 | etcd 3.6.0 will depends on raft 3.6.0 |
|
||||
| [Release bbolt 1.4.0](https://github.com/etcd-io/bbolt/issues/553) | P0 | etcd 3.6.0 will depends on bbolt 1.4.0 |
|
||||
| [Support /livez and /readyz endpoints](https://github.com/etcd-io/etcd/issues/16007) | P1 | It provides clearer APIs, and can also workaround the stalled writes issue |
|
||||
| [Bump gRPC](https://github.com/etcd-io/etcd/issues/16290) | P1 | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. |
|
||||
| [Deprecate grpc-gateway or bump it](https://github.com/etcd-io/etcd/issues/14499) | P1 | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. |
|
||||
| [bbolt: Add logger into bbolt](https://github.com/etcd-io/bbolt/issues/509) | P1 | It's important to diagnose bbolt issues |
|
||||
| [bbolt: Add surgery commands](https://github.com/etcd-io/bbolt/issues/370) | P1 | Surgery commands are important for fixing corrupted db files |
|
||||
| [Evaluate and (Gradulate or deprecate/remove) experimental features](https://github.com/etcd-io/etcd/issues/16292) | P2 | This task will be covered in both 3.6 and 3.7. |
|
||||
|
||||
## v3.7.0
|
||||
|
||||
For a full list of tasks in `v3.7.0`, please see [milestone etcd-v3.7](https://github.com/etcd-io/etcd/milestone/39).
|
||||
For a full list of tasks in v3.7.0, please see [milestone etcd-v3.7](https://github.com/etcd-io/etcd/milestone/39).
|
||||
|
||||
| Title | Priority | Note |
|
||||
|-------------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------|
|
||||
|
1
OWNERS
1
OWNERS
@ -4,6 +4,7 @@ approvers:
|
||||
- ahrtr # Benjamin Wang <wachao@vmware.com> <benjamin.ahrtr@gmail.com>
|
||||
- mitake # Hitoshi Mitake <h.mitake@gmail.com>
|
||||
- serathius # Marek Siarkowicz <siarkowicz@google.com> <marek.siarkowicz@gmail.com>
|
||||
- ptabor # Piotr Tabor <piotr.tabor@gmail.com>
|
||||
- spzala # Sahdev Zala <spzala@us.ibm.com>
|
||||
- wenjiaswe # Wenjia Zhang <wenjiazhang@google.com> <wenjia.swe@gmail.com>
|
||||
reviewers:
|
||||
|
@ -9,7 +9,6 @@
|
||||
[](https://github.com/etcd-io/etcd/releases)
|
||||
[](https://github.com/etcd-io/etcd/blob/main/LICENSE)
|
||||
[](https://api.securityscorecards.dev/projects/github.com/etcd-io/etcd)
|
||||
<a href="https://actuated.dev/"><img alt="Arm CI sponsored by Actuated" src="https://docs.actuated.dev/images/actuated-badge.png" width="120px"></img></a>
|
||||
|
||||
**Note**: The `main` branch may be in an *unstable or even broken state* during development. For stable versions, see [releases][github-release].
|
||||
|
||||
@ -191,7 +190,6 @@ These emeritus maintainers dedicated a part of their career to etcd and reviewed
|
||||
* Xiang Li
|
||||
* Ben Darnell
|
||||
* Sam Batschelet
|
||||
* Piotr Tabor
|
||||
|
||||
### License
|
||||
|
||||
|
@ -18,7 +18,7 @@ require (
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
|
@ -36,8 +36,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -29,7 +29,7 @@ require (
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
|
@ -63,8 +63,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -549,12 +549,9 @@ func (l *lessor) recvKeepAlive(resp *pb.LeaseKeepAliveResponse) {
|
||||
// deadlineLoop reaps any keep alive channels that have not received a response
|
||||
// within the lease TTL
|
||||
func (l *lessor) deadlineLoop() {
|
||||
timer := time.NewTimer(time.Second)
|
||||
defer timer.Stop()
|
||||
for {
|
||||
timer.Reset(time.Second)
|
||||
select {
|
||||
case <-timer.C:
|
||||
case <-time.After(time.Second):
|
||||
case <-l.donec:
|
||||
return
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
Scripts and files which may be useful but aren't part of the core etcd project.
|
||||
|
||||
* [lock](lock) - example addressing the expired lease problem of distributed locking with etcd
|
||||
* [mixin](mixin) - customisable set of Grafana dashboard and Prometheus alerts for etcd
|
||||
* [raftexample](raftexample) - an example distributed key-value store using raft
|
||||
* [systemd](systemd) - an example unit file for deploying etcd on systemd-based distributions
|
||||
* [raftexample](raftexample) - an example distributed key-value store using raft
|
||||
* [systemd/etcd3-multinode](systemd/etcd3-multinode) - multi-node cluster setup with systemd
|
||||
|
@ -32,7 +32,7 @@ require (
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
|
@ -84,8 +84,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -63,7 +63,7 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.16.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
|
@ -109,8 +109,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
|
||||
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
2
go.mod
2
go.mod
@ -87,7 +87,7 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.16.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -194,8 +194,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
|
||||
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
|
||||
|
@ -20,7 +20,7 @@ require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect
|
||||
|
@ -31,8 +31,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
|
@ -25,28 +25,8 @@ fi
|
||||
source ./scripts/test_lib.sh
|
||||
|
||||
if [[ $(protoc --version | cut -f2 -d' ') != "3.20.3" ]]; then
|
||||
echo "Could not find protoc 3.20.3, installing now..."
|
||||
|
||||
arch=$(go env GOARCH)
|
||||
|
||||
case ${arch} in
|
||||
"amd64") file="x86_64" ;;
|
||||
"arm64") file="aarch_64" ;;
|
||||
*)
|
||||
echo "Unsupported architecture: ${arch}"
|
||||
exit 255
|
||||
;;
|
||||
esac
|
||||
|
||||
download_url="https://github.com/protocolbuffers/protobuf/releases/download/v3.20.3/protoc-3.20.3-linux-${file}.zip"
|
||||
echo "Running on ${arch}."
|
||||
wget ${download_url} && unzip -p protoc-3.20.3-linux-${file}.zip bin/protoc > tmpFile && mv tmpFile bin/protoc
|
||||
rm protoc-3.20.3-linux-${file}.zip
|
||||
chmod +x bin/protoc
|
||||
PATH=$PATH:$(pwd)/bin
|
||||
export PATH
|
||||
echo "Now running: $(protoc --version)"
|
||||
|
||||
echo "could not find protoc 3.20.3, is it installed + in PATH?"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
GOFAST_BIN=$(tool_get_bin github.com/gogo/protobuf/protoc-gen-gofast)
|
||||
|
@ -90,22 +90,18 @@ func bootstrap(cfg config.ServerConfig) (b *bootstrappedServer, err error) {
|
||||
bwal = bootstrapWALFromSnapshot(cfg, backend.snapshot)
|
||||
}
|
||||
|
||||
cfg.Logger.Info("bootstrapping cluster")
|
||||
cluster, err := bootstrapCluster(cfg, bwal, prt)
|
||||
if err != nil {
|
||||
backend.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.Logger.Info("bootstrapping storage")
|
||||
s := bootstrapStorage(cfg, st, backend, bwal, cluster)
|
||||
|
||||
if err = cluster.Finalize(cfg, s); err != nil {
|
||||
backend.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.Logger.Info("bootstrapping raft")
|
||||
raft := bootstrapRaft(cfg, cluster, s.wal)
|
||||
return &bootstrappedServer{
|
||||
prt: prt,
|
||||
|
@ -72,9 +72,6 @@ func getClusterFromRemotePeers(lg *zap.Logger, urls []string, timeout time.Durat
|
||||
cc := &http.Client{
|
||||
Transport: rt,
|
||||
Timeout: timeout,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
for _, u := range urls {
|
||||
addr := u + "/members"
|
||||
@ -292,12 +289,7 @@ func getVersion(lg *zap.Logger, m *membership.Member, rt http.RoundTripper, time
|
||||
}
|
||||
|
||||
func promoteMemberHTTP(ctx context.Context, url string, id uint64, peerRt http.RoundTripper) ([]*membership.Member, error) {
|
||||
cc := &http.Client{
|
||||
Transport: peerRt,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
cc := &http.Client{Transport: peerRt}
|
||||
// TODO: refactor member http handler code
|
||||
// cannot import etcdhttp, so manually construct url
|
||||
requestUrl := url + "/members/promote/" + fmt.Sprintf("%d", id)
|
||||
@ -370,9 +362,6 @@ func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTrip
|
||||
cc := &http.Client{
|
||||
Transport: rt,
|
||||
Timeout: timeout,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
var (
|
||||
err error
|
||||
|
@ -467,12 +467,7 @@ func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp {
|
||||
|
||||
lg := s.Logger()
|
||||
|
||||
cc := &http.Client{
|
||||
Transport: s.peerRt,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
cc := &http.Client{Transport: s.peerRt}
|
||||
var resps []*peerHashKVResp
|
||||
for _, p := range peers {
|
||||
if len(p.eps) == 0 {
|
||||
|
@ -298,10 +298,8 @@ type EtcdServer struct {
|
||||
func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) {
|
||||
b, err := bootstrap(cfg)
|
||||
if err != nil {
|
||||
cfg.Logger.Error("bootstrap failed", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
cfg.Logger.Info("bootstrap successfully")
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@ -394,15 +392,8 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) {
|
||||
|
||||
if srv.Cfg.EnableLeaseCheckpoint {
|
||||
// setting checkpointer enables lease checkpoint feature.
|
||||
srv.lessor.SetCheckpointer(func(ctx context.Context, cp *pb.LeaseCheckpointRequest) error {
|
||||
if !srv.ensureLeadership() {
|
||||
srv.lg.Warn("Ignore the checkpoint request because current member isn't a leader",
|
||||
zap.Uint64("local-member-id", uint64(srv.MemberId())))
|
||||
return lease.ErrNotPrimary
|
||||
}
|
||||
|
||||
srv.lessor.SetCheckpointer(func(ctx context.Context, cp *pb.LeaseCheckpointRequest) {
|
||||
srv.raftRequestOnce(ctx, pb.InternalRaftRequest{LeaseCheckpoint: cp})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -707,14 +698,6 @@ func (s *EtcdServer) Process(ctx context.Context, m raftpb.Message) error {
|
||||
)
|
||||
return httptypes.NewHTTPError(http.StatusForbidden, "cannot process message from removed member")
|
||||
}
|
||||
if s.MemberId() != types.ID(m.To) {
|
||||
lg.Warn(
|
||||
"rejected Raft message to mismatch member",
|
||||
zap.String("local-member-id", s.MemberId().String()),
|
||||
zap.String("mismatch-member-id", types.ID(m.To).String()),
|
||||
)
|
||||
return httptypes.NewHTTPError(http.StatusForbidden, "cannot process message to mismatch member")
|
||||
}
|
||||
if m.Type == raftpb.MsgApp {
|
||||
s.stats.RecvAppendReq(types.ID(m.From).String(), m.Size())
|
||||
}
|
||||
@ -851,19 +834,7 @@ func (s *EtcdServer) run() {
|
||||
|
||||
func (s *EtcdServer) revokeExpiredLeases(leases []*lease.Lease) {
|
||||
s.GoAttach(func() {
|
||||
// We shouldn't revoke any leases if current member isn't a leader,
|
||||
// because the operation should only be performed by the leader. When
|
||||
// the leader gets blocked on the raft loop, such as writing WAL entries,
|
||||
// it can't process any events or messages from raft. It may think it
|
||||
// is still the leader even the leader has already changed.
|
||||
// Refer to https://github.com/etcd-io/etcd/issues/15247
|
||||
lg := s.Logger()
|
||||
if !s.ensureLeadership() {
|
||||
lg.Warn("Ignore the lease revoking request because current member isn't a leader",
|
||||
zap.Uint64("local-member-id", uint64(s.MemberId())))
|
||||
return
|
||||
}
|
||||
|
||||
// Increases throughput of expired leases deletion process through parallelization
|
||||
c := make(chan struct{}, maxPendingRevokes)
|
||||
for _, curLease := range leases {
|
||||
@ -896,29 +867,6 @@ func (s *EtcdServer) revokeExpiredLeases(leases []*lease.Lease) {
|
||||
})
|
||||
}
|
||||
|
||||
// ensureLeadership checks whether current member is still the leader.
|
||||
func (s *EtcdServer) ensureLeadership() bool {
|
||||
lg := s.Logger()
|
||||
|
||||
ctx, cancel := context.WithTimeout(s.ctx, s.Cfg.ReqTimeout())
|
||||
defer cancel()
|
||||
if err := s.linearizableReadNotify(ctx); err != nil {
|
||||
lg.Warn("Failed to check current member's leadership",
|
||||
zap.Error(err))
|
||||
return false
|
||||
}
|
||||
|
||||
newLeaderId := s.raftStatus().Lead
|
||||
if newLeaderId != uint64(s.MemberId()) {
|
||||
lg.Warn("Current member isn't a leader",
|
||||
zap.Uint64("local-member-id", uint64(s.MemberId())),
|
||||
zap.Uint64("new-lead", newLeaderId))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Cleanup removes allocated objects by EtcdServer.NewServer in
|
||||
// situation that EtcdServer::Start was not called (that takes care of cleanup).
|
||||
func (s *EtcdServer) Cleanup() {
|
||||
@ -2019,9 +1967,7 @@ func removeNeedlessRangeReqs(txn *pb.TxnRequest) {
|
||||
// applyConfChange applies a ConfChange to the server. It is only
|
||||
// invoked with a ConfChange that has already passed through Raft
|
||||
func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.ConfState, shouldApplyV3 membership.ShouldApplyV3) (bool, error) {
|
||||
lg := s.Logger()
|
||||
if err := s.cluster.ValidateConfigurationChange(cc); err != nil {
|
||||
lg.Error("Validation on configuration change failed", zap.Bool("shouldApplyV3", bool(shouldApplyV3)), zap.Error(err))
|
||||
cc.NodeID = raft.None
|
||||
s.r.ApplyConfChange(cc)
|
||||
|
||||
@ -2034,6 +1980,7 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con
|
||||
return false, err
|
||||
}
|
||||
|
||||
lg := s.Logger()
|
||||
*confState = *s.r.ApplyConfChange(cc)
|
||||
s.beHooks.SetConfState(confState)
|
||||
switch cc.Type {
|
||||
|
@ -470,7 +470,7 @@ func TestApplyConfigChangeUpdatesConsistIndex(t *testing.T) {
|
||||
lgMu: new(sync.RWMutex),
|
||||
lg: lg,
|
||||
memberId: 1,
|
||||
r: *realisticRaftNode(lg, 1, nil),
|
||||
r: *realisticRaftNode(lg),
|
||||
cluster: cl,
|
||||
w: wait.New(),
|
||||
consistIndex: ci,
|
||||
@ -514,17 +514,11 @@ func TestApplyConfigChangeUpdatesConsistIndex(t *testing.T) {
|
||||
assert.Equal(t, consistIndex, rindex)
|
||||
}
|
||||
|
||||
func realisticRaftNode(lg *zap.Logger, id uint64, snap *raftpb.Snapshot) *raftNode {
|
||||
func realisticRaftNode(lg *zap.Logger) *raftNode {
|
||||
storage := raft.NewMemoryStorage()
|
||||
storage.SetHardState(raftpb.HardState{Commit: 0, Term: 0})
|
||||
if snap != nil {
|
||||
err := storage.ApplySnapshot(*snap)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
c := &raft.Config{
|
||||
ID: id,
|
||||
ID: 1,
|
||||
ElectionTick: 10,
|
||||
HeartbeatTick: 1,
|
||||
Storage: storage,
|
||||
@ -895,61 +889,6 @@ func TestAddMember(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestProcessIgnoreMismatchMessage tests Process must ignore messages to
|
||||
// mismatch member.
|
||||
func TestProcessIgnoreMismatchMessage(t *testing.T) {
|
||||
lg := zaptest.NewLogger(t)
|
||||
cl := newTestCluster(t)
|
||||
st := v2store.New()
|
||||
cl.SetStore(st)
|
||||
be, _ := betesting.NewDefaultTmpBackend(t)
|
||||
defer betesting.Close(t, be)
|
||||
cl.SetBackend(schema.NewMembershipBackend(lg, be))
|
||||
|
||||
// Bootstrap a 3-node cluster, member IDs: 1 2 3.
|
||||
cl.AddMember(&membership.Member{ID: types.ID(1)}, true)
|
||||
cl.AddMember(&membership.Member{ID: types.ID(2)}, true)
|
||||
cl.AddMember(&membership.Member{ID: types.ID(3)}, true)
|
||||
// r is initialized with ID 1.
|
||||
r := realisticRaftNode(lg, 1, &raftpb.Snapshot{
|
||||
Metadata: raftpb.SnapshotMetadata{
|
||||
Index: 11, // Magic number.
|
||||
Term: 11, // Magic number.
|
||||
ConfState: raftpb.ConfState{
|
||||
// Member ID list.
|
||||
Voters: []uint64{1, 2, 3},
|
||||
},
|
||||
},
|
||||
})
|
||||
s := &EtcdServer{
|
||||
lgMu: new(sync.RWMutex),
|
||||
lg: lg,
|
||||
memberId: 1,
|
||||
r: *r,
|
||||
v2store: st,
|
||||
cluster: cl,
|
||||
reqIDGen: idutil.NewGenerator(0, time.Time{}),
|
||||
SyncTicker: &time.Ticker{},
|
||||
consistIndex: cindex.NewFakeConsistentIndex(0),
|
||||
beHooks: serverstorage.NewBackendHooks(lg, nil),
|
||||
}
|
||||
// Mock a mad switch dispatching messages to wrong node.
|
||||
m := raftpb.Message{
|
||||
Type: raftpb.MsgHeartbeat,
|
||||
To: 2, // Wrong ID, s.MemberId() is 1.
|
||||
From: 3,
|
||||
Term: 11,
|
||||
Commit: 42, // Commit is larger than the last index 11.
|
||||
}
|
||||
if types.ID(m.To) == s.MemberId() {
|
||||
t.Fatalf("m.To (%d) is expected to mismatch s.MemberId (%d)", m.To, s.MemberId())
|
||||
}
|
||||
err := s.Process(context.Background(), m)
|
||||
if err == nil {
|
||||
t.Fatalf("Must ignore the message and return an error")
|
||||
}
|
||||
}
|
||||
|
||||
// TestRemoveMember tests RemoveMember can propose and perform node removal.
|
||||
func TestRemoveMember(t *testing.T) {
|
||||
lg := zaptest.NewLogger(t)
|
||||
|
@ -278,16 +278,6 @@ func (s *EtcdServer) LeaseRevoke(ctx context.Context, r *pb.LeaseRevokeRequest)
|
||||
|
||||
func (s *EtcdServer) LeaseRenew(ctx context.Context, id lease.LeaseID) (int64, error) {
|
||||
if s.isLeader() {
|
||||
// If s.isLeader() returns true, but we fail to ensure the current
|
||||
// member's leadership, there are a couple of possibilities:
|
||||
// 1. current member gets stuck on writing WAL entries;
|
||||
// 2. current member is in network isolation status;
|
||||
// 3. current member isn't a leader anymore (possibly due to #1 above).
|
||||
// In such case, we just return error to client, so that the client can
|
||||
// switch to another member to continue the lease keep-alive operation.
|
||||
if !s.ensureLeadership() {
|
||||
return -1, lease.ErrNotPrimary
|
||||
}
|
||||
if err := s.waitAppliedIndex(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ require (
|
||||
go.uber.org/multierr v1.11.0
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.16.0
|
||||
golang.org/x/net v0.19.0
|
||||
golang.org/x/net v0.18.0
|
||||
golang.org/x/time v0.5.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17
|
||||
google.golang.org/grpc v1.59.0
|
||||
|
@ -172,8 +172,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
|
||||
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
|
||||
|
@ -150,12 +150,7 @@ func RenewHTTP(ctx context.Context, id lease.LeaseID, url string, rt http.RoundT
|
||||
return -1, err
|
||||
}
|
||||
|
||||
cc := &http.Client{
|
||||
Transport: rt,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
cc := &http.Client{Transport: rt}
|
||||
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(lreq))
|
||||
if err != nil {
|
||||
return -1, err
|
||||
@ -215,12 +210,7 @@ func TimeToLiveHTTP(ctx context.Context, id lease.LeaseID, keys bool, url string
|
||||
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
cc := &http.Client{
|
||||
Transport: rt,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
cc := &http.Client{Transport: rt}
|
||||
var b []byte
|
||||
// buffer errc channel so that errc don't block inside the go routinue
|
||||
resp, err := cc.Do(req)
|
||||
|
@ -75,7 +75,7 @@ type RangeDeleter func() TxnDelete
|
||||
|
||||
// Checkpointer permits checkpointing of lease remaining TTLs to the consensus log. Defined here to
|
||||
// avoid circular dependency with mvcc.
|
||||
type Checkpointer func(ctx context.Context, lc *pb.LeaseCheckpointRequest) error
|
||||
type Checkpointer func(ctx context.Context, lc *pb.LeaseCheckpointRequest)
|
||||
|
||||
type LeaseID int64
|
||||
|
||||
@ -281,6 +281,10 @@ func (le *lessor) Grant(id LeaseID, ttl int64) (*Lease, error) {
|
||||
// with longer TTL to reduce renew load.
|
||||
l := NewLease(id, ttl)
|
||||
|
||||
if l.ttl < le.minLeaseTTL {
|
||||
l.ttl = le.minLeaseTTL
|
||||
}
|
||||
|
||||
le.mu.Lock()
|
||||
defer le.mu.Unlock()
|
||||
|
||||
@ -288,10 +292,6 @@ func (le *lessor) Grant(id LeaseID, ttl int64) (*Lease, error) {
|
||||
return nil, ErrLeaseExists
|
||||
}
|
||||
|
||||
if l.ttl < le.minLeaseTTL {
|
||||
l.ttl = le.minLeaseTTL
|
||||
}
|
||||
|
||||
if le.isPrimary() {
|
||||
l.refresh(0)
|
||||
} else {
|
||||
@ -322,6 +322,11 @@ func (le *lessor) Revoke(id LeaseID) error {
|
||||
return ErrLeaseNotFound
|
||||
}
|
||||
|
||||
// We shouldn't delete the lease inside the transaction lock, otherwise
|
||||
// it may lead to deadlock with Grant or Checkpoint operations, which
|
||||
// acquire the le.mu firstly and then the batchTx lock.
|
||||
delete(le.leaseMap, id)
|
||||
|
||||
defer close(l.revokec)
|
||||
// unlock before doing external work
|
||||
le.mu.Unlock()
|
||||
@ -340,9 +345,6 @@ func (le *lessor) Revoke(id LeaseID) error {
|
||||
txn.DeleteRange([]byte(key), nil)
|
||||
}
|
||||
|
||||
le.mu.Lock()
|
||||
defer le.mu.Unlock()
|
||||
delete(le.leaseMap, l.ID)
|
||||
// lease deletion needs to be in the same backend transaction with the
|
||||
// kv deletion. Or we might end up with not executing the revoke or not
|
||||
// deleting the keys if etcdserver fails in between.
|
||||
@ -422,9 +424,7 @@ func (le *lessor) Renew(id LeaseID) (int64, error) {
|
||||
// By applying a RAFT entry only when the remainingTTL is already set, we limit the number
|
||||
// of RAFT entries written per lease to a max of 2 per checkpoint interval.
|
||||
if clearRemainingTTL {
|
||||
if err := le.cp(context.Background(), &pb.LeaseCheckpointRequest{Checkpoints: []*pb.LeaseCheckpoint{{ID: int64(l.ID), Remaining_TTL: 0}}}); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
le.cp(context.Background(), &pb.LeaseCheckpointRequest{Checkpoints: []*pb.LeaseCheckpoint{{ID: int64(l.ID), Remaining_TTL: 0}}})
|
||||
}
|
||||
|
||||
le.mu.Lock()
|
||||
@ -658,9 +658,7 @@ func (le *lessor) checkpointScheduledLeases() {
|
||||
le.mu.Unlock()
|
||||
|
||||
if len(cps) != 0 {
|
||||
if err := le.cp(context.Background(), &pb.LeaseCheckpointRequest{Checkpoints: cps}); err != nil {
|
||||
return
|
||||
}
|
||||
le.cp(context.Background(), &pb.LeaseCheckpointRequest{Checkpoints: cps})
|
||||
}
|
||||
if len(cps) < maxLeaseCheckpointBatchSize {
|
||||
return
|
||||
|
@ -269,11 +269,10 @@ func TestLessorRenewWithCheckpointer(t *testing.T) {
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
le := newLessor(lg, be, clusterLatest(), LessorConfig{MinLeaseTTL: minLeaseTTL})
|
||||
fakerCheckerpointer := func(ctx context.Context, cp *pb.LeaseCheckpointRequest) error {
|
||||
fakerCheckerpointer := func(ctx context.Context, cp *pb.LeaseCheckpointRequest) {
|
||||
for _, cp := range cp.GetCheckpoints() {
|
||||
le.Checkpoint(LeaseID(cp.GetID()), cp.GetRemaining_TTL())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
defer le.Stop()
|
||||
// Set checkpointer
|
||||
@ -557,7 +556,7 @@ func TestLessorCheckpointScheduling(t *testing.T) {
|
||||
defer le.Stop()
|
||||
le.minLeaseTTL = 1
|
||||
checkpointedC := make(chan struct{})
|
||||
le.SetCheckpointer(func(ctx context.Context, lc *pb.LeaseCheckpointRequest) error {
|
||||
le.SetCheckpointer(func(ctx context.Context, lc *pb.LeaseCheckpointRequest) {
|
||||
close(checkpointedC)
|
||||
if len(lc.Checkpoints) != 1 {
|
||||
t.Errorf("expected 1 checkpoint but got %d", len(lc.Checkpoints))
|
||||
@ -566,7 +565,6 @@ func TestLessorCheckpointScheduling(t *testing.T) {
|
||||
if c.Remaining_TTL != 1 {
|
||||
t.Errorf("expected checkpoint to be called with Remaining_TTL=%d but got %d", 1, c.Remaining_TTL)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
_, err := le.Grant(1, 2)
|
||||
if err != nil {
|
||||
|
@ -218,10 +218,15 @@ func TestPeriodicCheckDetectsCorruption(t *testing.T) {
|
||||
assert.NoError(t, err, "error on put")
|
||||
}
|
||||
|
||||
memberID, found, err := getMemberIdByName(ctx, cc, epc.Procs[0].Config().Name)
|
||||
members, err := cc.MemberList(ctx, false)
|
||||
assert.NoError(t, err, "error on member list")
|
||||
assert.Equal(t, found, true, "member not found")
|
||||
|
||||
var memberID uint64
|
||||
for _, m := range members.Members {
|
||||
if m.Name == epc.Procs[0].Config().Name {
|
||||
memberID = m.ID
|
||||
}
|
||||
}
|
||||
assert.NotZero(t, memberID, "member not found")
|
||||
epc.Procs[0].Stop()
|
||||
err = testutil.CorruptBBolt(datadir.ToBackendFileName(epc.Procs[0].Config().DataDirPath))
|
||||
assert.NoError(t, err)
|
||||
@ -258,9 +263,14 @@ func TestCompactHashCheckDetectCorruption(t *testing.T) {
|
||||
err = cc.Put(ctx, testutil.PickKey(int64(i)), fmt.Sprint(i), config.PutOptions{})
|
||||
assert.NoError(t, err, "error on put")
|
||||
}
|
||||
memberID, found, err := getMemberIdByName(ctx, cc, epc.Procs[0].Config().Name)
|
||||
members, err := cc.MemberList(ctx, false)
|
||||
assert.NoError(t, err, "error on member list")
|
||||
assert.Equal(t, found, true, "member not found")
|
||||
var memberID uint64
|
||||
for _, m := range members.Members {
|
||||
if m.Name == epc.Procs[0].Config().Name {
|
||||
memberID = m.ID
|
||||
}
|
||||
}
|
||||
|
||||
epc.Procs[0].Stop()
|
||||
err = testutil.CorruptBBolt(datadir.ToBackendFileName(epc.Procs[0].Config().DataDirPath))
|
||||
|
@ -1,99 +0,0 @@
|
||||
// Copyright 2023 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !cluster_proxy
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.etcd.io/etcd/server/v3/etcdserver"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
"go.etcd.io/etcd/tests/v3/framework/testutils"
|
||||
)
|
||||
|
||||
func TestMemberReplace(t *testing.T) {
|
||||
e2e.BeforeTest(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer cancel()
|
||||
|
||||
epc, err := e2e.NewEtcdProcessCluster(ctx, t)
|
||||
require.NoError(t, err)
|
||||
defer epc.Close()
|
||||
|
||||
memberIdx := rand.Int() % len(epc.Procs)
|
||||
member := epc.Procs[memberIdx]
|
||||
memberName := member.Config().Name
|
||||
var endpoints []string
|
||||
for i := 1; i < len(epc.Procs); i++ {
|
||||
endpoints = append(endpoints, epc.Procs[(memberIdx+i)%len(epc.Procs)].EndpointsGRPC()...)
|
||||
}
|
||||
cc, err := e2e.NewEtcdctl(epc.Cfg.Client, endpoints)
|
||||
require.NoError(t, err)
|
||||
|
||||
memberID, found, err := getMemberIdByName(ctx, cc, memberName)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, found, true, "Member not found")
|
||||
|
||||
// Need to wait health interval for cluster to accept member changes
|
||||
time.Sleep(etcdserver.HealthInterval)
|
||||
|
||||
t.Logf("Removing member %s", memberName)
|
||||
_, err = cc.MemberRemove(ctx, memberID)
|
||||
require.NoError(t, err)
|
||||
_, found, err = getMemberIdByName(ctx, cc, memberName)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, found, false, "Expected member to be removed")
|
||||
for member.IsRunning() {
|
||||
err = member.Wait(ctx)
|
||||
if err != nil && !strings.Contains(err.Error(), "unexpected exit code") {
|
||||
t.Fatalf("member didn't exit as expected: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Removing member %s data", memberName)
|
||||
err = os.RemoveAll(member.Config().DataDirPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Logf("Adding member %s back", memberName)
|
||||
removedMemberPeerUrl := member.Config().PeerURL.String()
|
||||
_, err = cc.MemberAdd(ctx, memberName, []string{removedMemberPeerUrl})
|
||||
require.NoError(t, err)
|
||||
err = patchArgs(member.Config().Args, "initial-cluster-state", "existing")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Sleep 100ms to bypass the known issue https://github.com/etcd-io/etcd/issues/16687.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
t.Logf("Starting member %s", memberName)
|
||||
err = member.Start(ctx)
|
||||
require.NoError(t, err)
|
||||
testutils.ExecuteUntil(ctx, t, func() {
|
||||
for {
|
||||
_, found, err := getMemberIdByName(ctx, cc, memberName)
|
||||
if err != nil || !found {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
@ -122,26 +122,3 @@ func runCommandAndReadJsonOutput(args []string) (map[string]any, error) {
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func getMemberIdByName(ctx context.Context, c *e2e.EtcdctlV3, name string) (id uint64, found bool, err error) {
|
||||
resp, err := c.MemberList(ctx, false)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
for _, member := range resp.Members {
|
||||
if name == member.Name {
|
||||
return member.ID, true, nil
|
||||
}
|
||||
}
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
func patchArgs(args []string, flag, newValue string) error {
|
||||
for i, arg := range args {
|
||||
if strings.Contains(arg, flag) {
|
||||
args[i] = fmt.Sprintf("--%s=%s", flag, newValue)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("--%s flag not found", flag)
|
||||
}
|
||||
|
@ -1,157 +0,0 @@
|
||||
// Copyright 2023 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !cluster_proxy
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/tests/v3/framework/e2e"
|
||||
"go.etcd.io/etcd/tests/v3/framework/testutils"
|
||||
)
|
||||
|
||||
// TestLeaseRevoke_IgnoreOldLeader verifies that leases shouldn't be revoked
|
||||
// by old leader.
|
||||
// See the case 1 in https://github.com/etcd-io/etcd/issues/15247#issuecomment-1777862093.
|
||||
func TestLeaseRevoke_IgnoreOldLeader(t *testing.T) {
|
||||
testLeaseRevokeIssue(t, true)
|
||||
}
|
||||
|
||||
// TestLeaseRevoke_ClientSwitchToOtherMember verifies that leases shouldn't
|
||||
// be revoked by new leader.
|
||||
// See the case 2 in https://github.com/etcd-io/etcd/issues/15247#issuecomment-1777862093.
|
||||
func TestLeaseRevoke_ClientSwitchToOtherMember(t *testing.T) {
|
||||
testLeaseRevokeIssue(t, false)
|
||||
}
|
||||
|
||||
func testLeaseRevokeIssue(t *testing.T, connectToOneFollower bool) {
|
||||
e2e.BeforeTest(t)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
t.Log("Starting a new etcd cluster")
|
||||
epc, err := e2e.NewEtcdProcessCluster(ctx, t,
|
||||
e2e.WithClusterSize(3),
|
||||
e2e.WithGoFailEnabled(true),
|
||||
e2e.WithGoFailClientTimeout(40*time.Second),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
if errC := epc.Close(); errC != nil {
|
||||
t.Fatalf("error closing etcd processes (%v)", errC)
|
||||
}
|
||||
}()
|
||||
|
||||
leaderIdx := epc.WaitLeader(t)
|
||||
t.Logf("Leader index: %d", leaderIdx)
|
||||
|
||||
epsForNormalOperations := epc.Procs[(leaderIdx+2)%3].EndpointsGRPC()
|
||||
t.Logf("Creating a client for normal operations: %v", epsForNormalOperations)
|
||||
client, err := clientv3.New(clientv3.Config{Endpoints: epsForNormalOperations, DialTimeout: 3 * time.Second})
|
||||
require.NoError(t, err)
|
||||
defer client.Close()
|
||||
|
||||
var epsForLeaseKeepAlive []string
|
||||
if connectToOneFollower {
|
||||
epsForLeaseKeepAlive = epc.Procs[(leaderIdx+1)%3].EndpointsGRPC()
|
||||
} else {
|
||||
epsForLeaseKeepAlive = epc.EndpointsGRPC()
|
||||
}
|
||||
t.Logf("Creating a client for the leaseKeepAlive operation: %v", epsForLeaseKeepAlive)
|
||||
clientForKeepAlive, err := clientv3.New(clientv3.Config{Endpoints: epsForLeaseKeepAlive, DialTimeout: 3 * time.Second})
|
||||
require.NoError(t, err)
|
||||
defer clientForKeepAlive.Close()
|
||||
|
||||
resp, err := client.Status(ctx, epsForNormalOperations[0])
|
||||
require.NoError(t, err)
|
||||
oldLeaderId := resp.Leader
|
||||
|
||||
t.Log("Creating a new lease")
|
||||
leaseRsp, err := client.Grant(ctx, 20)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log("Starting a goroutine to keep alive the lease")
|
||||
doneC := make(chan struct{})
|
||||
stopC := make(chan struct{})
|
||||
startC := make(chan struct{}, 1)
|
||||
go func() {
|
||||
defer close(doneC)
|
||||
|
||||
respC, kerr := clientForKeepAlive.KeepAlive(ctx, leaseRsp.ID)
|
||||
require.NoError(t, kerr)
|
||||
// ensure we have received the first response from the server
|
||||
<-respC
|
||||
startC <- struct{}{}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-stopC:
|
||||
return
|
||||
case <-respC:
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
t.Log("Wait for the keepAlive goroutine to get started")
|
||||
<-startC
|
||||
|
||||
t.Log("Trigger the failpoint to simulate stalled writing")
|
||||
err = epc.Procs[leaderIdx].Failpoints().SetupHTTP(ctx, "raftBeforeSave", `sleep("30s")`)
|
||||
require.NoError(t, err)
|
||||
|
||||
cctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
t.Logf("Waiting for a new leader to be elected, old leader index: %d, old leader ID: %d", leaderIdx, oldLeaderId)
|
||||
testutils.ExecuteUntil(cctx, t, func() {
|
||||
for {
|
||||
resp, err = client.Status(ctx, epsForNormalOperations[0])
|
||||
if err == nil && resp.Leader != oldLeaderId {
|
||||
t.Logf("A new leader has already been elected, new leader index: %d", resp.Leader)
|
||||
return
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
})
|
||||
cancel()
|
||||
|
||||
t.Log("Writing a key/value pair")
|
||||
_, err = client.Put(ctx, "foo", "bar")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log("Sleeping 30 seconds")
|
||||
time.Sleep(30 * time.Second)
|
||||
|
||||
t.Log("Remove the failpoint 'raftBeforeSave'")
|
||||
err = epc.Procs[leaderIdx].Failpoints().DeactivateHTTP(ctx, "raftBeforeSave")
|
||||
require.NoError(t, err)
|
||||
|
||||
// By default, etcd tries to revoke leases every 7 seconds.
|
||||
t.Log("Sleeping 10 seconds")
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
t.Log("Confirming the lease isn't revoked")
|
||||
leases, err := client.Leases(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(leases.Leases))
|
||||
|
||||
t.Log("Waiting for the keepAlive goroutine to exit")
|
||||
close(stopC)
|
||||
<-doneC
|
||||
}
|
@ -79,10 +79,13 @@ func (logOb *LogObserver) ExpectFunc(ctx context.Context, filter func(string) bo
|
||||
}
|
||||
|
||||
if len(res) >= count {
|
||||
return res, nil
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(res) >= count {
|
||||
return res, nil
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
|
@ -198,8 +198,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
|
||||
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
|
||||
|
@ -350,9 +350,7 @@ func putAndWatch(t *testing.T, wctx *watchctx, key, val string) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestWatchResumeAfterDisconnect tests watch resume after member disconnects then connects.
|
||||
// It ensures that correct events are returned corresponding to the start revision.
|
||||
func TestWatchResumeAfterDisconnect(t *testing.T) {
|
||||
func TestWatchResumeInitRev(t *testing.T) {
|
||||
integration2.BeforeTest(t)
|
||||
clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, UseBridge: true})
|
||||
defer clus.Terminate(t)
|
||||
@ -369,10 +367,7 @@ func TestWatchResumeAfterDisconnect(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// watch from revision 1
|
||||
wch := clus.Client(0).Watch(context.Background(), "a", clientv3.WithRev(1), clientv3.WithCreatedNotify())
|
||||
// response for the create watch request, no events are in this response
|
||||
// the current revision of etcd should be 4
|
||||
if resp, ok := <-wch; !ok || resp.Header.Revision != 4 {
|
||||
t.Fatalf("got (%v, %v), expected create notification rev=4", resp, ok)
|
||||
}
|
||||
@ -394,16 +389,12 @@ func TestWatchResumeAfterDisconnect(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("unexpected watch close")
|
||||
}
|
||||
// Events should be put(a, 3) and put(a, 4)
|
||||
if len(resp.Events) != 2 {
|
||||
t.Fatal("expected two events on watch")
|
||||
if len(resp.Events) == 0 {
|
||||
t.Fatal("expected event on watch")
|
||||
}
|
||||
if string(resp.Events[0].Kv.Value) != "3" {
|
||||
t.Fatalf("expected value=3, got event %+v", resp.Events[0])
|
||||
}
|
||||
if string(resp.Events[1].Kv.Value) != "4" {
|
||||
t.Fatalf("expected value=4, got event %+v", resp.Events[1])
|
||||
}
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("watch timed out")
|
||||
}
|
||||
|
@ -747,7 +747,7 @@ func TestV3LeaseFailover(t *testing.T) {
|
||||
|
||||
// send keep alive to old leader until the old leader starts
|
||||
// to drop lease request.
|
||||
expectedExp := time.Now().Add(5 * time.Second)
|
||||
var expectedExp time.Time
|
||||
for {
|
||||
if err = lac.Send(lreq); err != nil {
|
||||
break
|
||||
|
@ -52,7 +52,7 @@ gofail-disable: install-gofail
|
||||
|
||||
.PHONY: install-gofail
|
||||
install-gofail:
|
||||
go install go.etcd.io/gofail@${GOFAIL_VERSION}
|
||||
cd tools/mod; go install go.etcd.io/gofail@${GOFAIL_VERSION}
|
||||
|
||||
# Build previous releases for robustness tests
|
||||
|
||||
|
@ -155,7 +155,7 @@ func (t kubernetesTraffic) Write(ctx context.Context, kc *kubernetesClient, ids
|
||||
} else {
|
||||
choices := t.writeChoices
|
||||
if !nonUniqueWriteLimiter.Take() {
|
||||
choices = filterOutNonUniqueKubernetesWrites(t.writeChoices)
|
||||
choices = filterOutNonUniqueKuberntesWrites(t.writeChoices)
|
||||
}
|
||||
op := pickRandom(choices)
|
||||
switch op {
|
||||
@ -178,7 +178,7 @@ func (t kubernetesTraffic) Write(ctx context.Context, kc *kubernetesClient, ids
|
||||
return nil
|
||||
}
|
||||
|
||||
func filterOutNonUniqueKubernetesWrites(choices []choiceWeight[KubernetesRequestType]) (resp []choiceWeight[KubernetesRequestType]) {
|
||||
func filterOutNonUniqueKuberntesWrites(choices []choiceWeight[KubernetesRequestType]) (resp []choiceWeight[KubernetesRequestType]) {
|
||||
for _, choice := range choices {
|
||||
if choice.choice != KubernetesDelete {
|
||||
resp = append(resp, choice)
|
||||
|
@ -12,7 +12,7 @@ require (
|
||||
github.com/google/addlicense v1.1.1
|
||||
github.com/google/yamlfmt v0.10.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1
|
||||
github.com/mikefarah/yq/v4 v4.40.4
|
||||
github.com/mikefarah/yq/v4 v4.35.2
|
||||
go.etcd.io/gofail v0.1.0
|
||||
go.etcd.io/protodoc v0.0.0-20180829002748-484ab544e116
|
||||
go.etcd.io/raft/v3 v3.0.0-20231012085229-7c3ed830bbb0
|
||||
@ -158,7 +158,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/polyfloyd/go-errorlint v1.4.5 // indirect
|
||||
github.com/prometheus/client_golang v1.17.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
github.com/quasilyte/go-ruleguard v0.4.0 // indirect
|
||||
@ -206,7 +206,6 @@ require (
|
||||
github.com/yagipy/maintidx v1.0.0 // indirect
|
||||
github.com/yeya24/promlinter v0.2.0 // indirect
|
||||
github.com/ykadowak/zerologlint v0.1.3 // indirect
|
||||
github.com/yuin/gopher-lua v1.1.0 // indirect
|
||||
github.com/zmap/zcrypto v0.0.0-20220402174210-599ec18ecbac // indirect
|
||||
github.com/zmap/zlint/v3 v3.4.1 // indirect
|
||||
gitlab.com/bosi/decorder v0.4.1 // indirect
|
||||
@ -219,13 +218,13 @@ require (
|
||||
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.15.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
|
@ -74,8 +74,8 @@ github.com/alecthomas/go-check-sumtype v0.1.3 h1:M+tqMxB68hcgccRXBMVCPI4UJ+QUfdS
|
||||
github.com/alecthomas/go-check-sumtype v0.1.3/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ=
|
||||
github.com/alecthomas/participle/v2 v2.1.0 h1:z7dElHRrOEEq45F2TG5cbQihMtNTv8vwldytDj7Wrz4=
|
||||
github.com/alecthomas/participle/v2 v2.1.0/go.mod h1:Y1+hAs8DHPmc3YUFzqllV+eSQ9ljPTk0ZkPMtEdAx2c=
|
||||
github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8=
|
||||
github.com/alecthomas/repr v0.3.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@ -203,12 +203,6 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
@ -427,8 +421,6 @@ github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUc
|
||||
github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0=
|
||||
github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo=
|
||||
github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU=
|
||||
github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
@ -468,8 +460,8 @@ github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwg
|
||||
github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc=
|
||||
github.com/mgechev/revive v1.3.4 h1:k/tO3XTaWY4DEHal9tWBkkUMJYO/dLDVyMmAQxmIMDc=
|
||||
github.com/mgechev/revive v1.3.4/go.mod h1:W+pZCMu9qj8Uhfs1iJMQsEFLRozUfvwFwqVvRbSNLVw=
|
||||
github.com/mikefarah/yq/v4 v4.40.4 h1:xLoMgs3ORN9Qqiq63q86lPZf6VXyPXTuXFhyWaKImFM=
|
||||
github.com/mikefarah/yq/v4 v4.40.4/go.mod h1:yCG9Y1pdzkpPqWWooozMTcbVb67rslEVaDnigLPhuqg=
|
||||
github.com/mikefarah/yq/v4 v4.35.2 h1:WAvRpJNytw13x1arsRprZcdOb3WxDIJ539NG4oshzFc=
|
||||
github.com/mikefarah/yq/v4 v4.35.2/go.mod h1:7nyFSLbxP+nXJNoPXUbYTlJDDn/d9K/SMtKbOqQLbwM=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
@ -532,8 +524,8 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
@ -669,8 +661,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
|
||||
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
|
||||
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
|
||||
github.com/zmap/zcrypto v0.0.0-20220402174210-599ec18ecbac h1:+nr36qrZEH0RIYNjcUEnOrCUdcSG3om2ANaFA6iSVWA=
|
||||
@ -814,8 +804,8 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -1012,8 +1002,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
|
||||
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
|
Reference in New Issue
Block a user