mirror of
https://github.com/slackhq/nebula.git
synced 2026-09-30 10:26:39 +02:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6259aef68 | ||
|
|
7fc40557a8 | ||
|
|
bdaf1eb92f | ||
|
|
e7b4e094b9 | ||
|
|
6740518403 | ||
|
|
5cbf029d06 | ||
|
|
368855c2e8 | ||
|
|
6d124d0441 |
Executable
+142
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Backport a merged PR to a release branch.
|
||||
#
|
||||
# Cherry-picks the merge commit of a merged PR onto release-1.11 and opens a
|
||||
# backport PR, mirroring the shape of #1842.
|
||||
#
|
||||
# Usage: ./backport.sh <pr-number> [target-version] [--continue]
|
||||
# pr-number The merged PR to backport
|
||||
# target-version Release version to target (default: 1.11)
|
||||
# --continue Resume after resolving cherry-pick conflicts: assumes the
|
||||
# fixes are staged, runs `git cherry-pick --continue`, and
|
||||
# proceeds to push and open the backport PR.
|
||||
#
|
||||
# Requires: gh (authenticated), git, jq.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PR_NUMBER=${1:?usage: backport.sh <pr-number> [target-version] [--continue]}
|
||||
shift
|
||||
CONTINUE=0
|
||||
TARGET_VERSION=""
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--continue) CONTINUE=1 ;;
|
||||
*) TARGET_VERSION=$arg ;;
|
||||
esac
|
||||
done
|
||||
|
||||
for cmd in gh git jq; do
|
||||
command -v "$cmd" >/dev/null || { echo "error: $cmd is required" >&2; exit 1; }
|
||||
done
|
||||
|
||||
# Pull the source PR's metadata. Refuse to backport a PR that never merged.
|
||||
pr_json=$(gh pr view "$PR_NUMBER" --json title,body,mergedAt,mergeCommit,milestone)
|
||||
PR_TITLE=$(jq -r '.title' <<<"$pr_json")
|
||||
PR_BODY=$(jq -r '.body' <<<"$pr_json")
|
||||
MERGE_SHA=$(jq -r '.mergeCommit.oid // empty' <<<"$pr_json")
|
||||
PR_MILESTONE=$(jq -r '.milestone.title // empty' <<<"$pr_json")
|
||||
|
||||
if [ "$(jq -r '.mergedAt // empty' <<<"$pr_json")" = "" ] || [ -z "$MERGE_SHA" ]; then
|
||||
echo "error: PR #${PR_NUMBER} is not merged (no merge commit to cherry-pick)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Default the target to one minor below the PR's milestone: a PR landing in
|
||||
# v1.12.0 backports to release-1.11. An explicit target-version arg overrides.
|
||||
if [ -z "$TARGET_VERSION" ]; then
|
||||
if [[ $PR_MILESTONE =~ ^v?([0-9]+)\.([0-9]+) ]]; then
|
||||
TARGET_VERSION="${BASH_REMATCH[1]}.$(( BASH_REMATCH[2] - 1 ))"
|
||||
else
|
||||
echo "error: PR #${PR_NUMBER} has no v<major>.<minor>.* milestone to infer the target from." >&2
|
||||
echo "Pass the target version explicitly, e.g. $0 ${PR_NUMBER} 1.11" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
TARGET_BRANCH="release-${TARGET_VERSION}"
|
||||
|
||||
# Slug from the PR title: lower-case, non-alphanumerics to dashes, trimmed.
|
||||
slug=$(printf '%s' "$PR_TITLE" \
|
||||
| tr '[:upper:]' '[:lower:]' \
|
||||
| sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//' \
|
||||
| cut -c1-50 \
|
||||
| sed -E 's/-+$//')
|
||||
BRANCH="backport-${TARGET_VERSION//./-}-${slug}"
|
||||
|
||||
if [ "$CONTINUE" -eq 1 ]; then
|
||||
# Resuming: the branch already exists and a cherry-pick is mid-conflict.
|
||||
current=$(git rev-parse --abbrev-ref HEAD)
|
||||
if [ "$current" != "$BRANCH" ]; then
|
||||
echo "error: --continue expects to be on ${BRANCH}, but HEAD is ${current}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Resuming backport of #${PR_NUMBER} on ${BRANCH}"
|
||||
# Conflicts assumed resolved and staged; core.editor=true keeps the commit message.
|
||||
git -c core.editor=true cherry-pick --continue
|
||||
else
|
||||
# A fresh run switches branches and cherry-picks, so tracked changes must be
|
||||
# clean. Untracked files are fine, and --continue is exempt (its resolved
|
||||
# conflicts are meant to be staged).
|
||||
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
|
||||
echo "error: working tree has uncommitted changes to tracked files; commit or stash them first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Backporting #${PR_NUMBER} (${MERGE_SHA}) onto ${TARGET_BRANCH} as ${BRANCH}"
|
||||
|
||||
git fetch origin
|
||||
git checkout -b "$BRANCH" "origin/${TARGET_BRANCH}"
|
||||
|
||||
# -m 1 handles a real merge commit; plain cherry-pick handles a squash merge.
|
||||
if ! { git cherry-pick -x -m 1 "$MERGE_SHA" 2>/dev/null || git cherry-pick -x "$MERGE_SHA"; }; then
|
||||
echo "error: ${MERGE_SHA} did not cherry-pick cleanly onto ${TARGET_BRANCH}." >&2
|
||||
echo "Resolve the conflicts, 'git add' them, then re-run:" >&2
|
||||
echo " $0 ${PR_NUMBER} ${TARGET_VERSION} --continue" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
title="backport v${TARGET_VERSION}: ${PR_TITLE}"
|
||||
body=$(printf 'Backport from #%s to release v%s\n\n---\n\n%s' \
|
||||
"$PR_NUMBER" "$TARGET_VERSION" "$PR_BODY")
|
||||
|
||||
# Highest open milestone matching v<version>.* (e.g. v1.11.1), if any.
|
||||
MILESTONE=$(gh api "repos/{owner}/{repo}/milestones?state=open" \
|
||||
--jq ".[].title | select(startswith(\"v${TARGET_VERSION}.\"))" \
|
||||
| sort -V | tail -n1)
|
||||
milestone_args=()
|
||||
if [ -n "$MILESTONE" ]; then
|
||||
milestone_args=(--milestone "$MILESTONE")
|
||||
else
|
||||
echo "warning: no open milestone matching v${TARGET_VERSION}.* found; PR will have no milestone" >&2
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "About to run:"
|
||||
printf ' git push -u --force-with-lease origin %q\n' "$BRANCH"
|
||||
printf ' gh pr create --base %q --head %q --title %q --body %q' \
|
||||
"$TARGET_BRANCH" "$BRANCH" "$title" "$body"
|
||||
[ -n "$MILESTONE" ] && printf ' --milestone %q' "$MILESTONE"
|
||||
printf '\n'
|
||||
echo
|
||||
read -r -p "Open this pull request? [y/N] " reply
|
||||
case "$reply" in
|
||||
[yY] | [yY][eE][sS]) ;;
|
||||
*) echo "Aborted. The cherry-pick is on local branch ${BRANCH}; push it manually if desired."; exit 0 ;;
|
||||
esac
|
||||
|
||||
git push -u --force-with-lease origin "$BRANCH"
|
||||
|
||||
gh pr create \
|
||||
--base "$TARGET_BRANCH" \
|
||||
--head "$BRANCH" \
|
||||
--title "$title" \
|
||||
--body "$body" \
|
||||
${milestone_args[@]+"${milestone_args[@]}"}
|
||||
|
||||
# The backport now exists, so drop the label that flagged this PR for one.
|
||||
gh pr edit "$PR_NUMBER" --remove-label needs-backport
|
||||
|
||||
# Switch back to the original branch we were on before doing the backport
|
||||
git checkout -
|
||||
@@ -73,8 +73,11 @@ jobs:
|
||||
build-darwin:
|
||||
name: Build Universal Darwin
|
||||
env:
|
||||
HAS_SIGNING_CREDS: ${{ secrets.AC_USERNAME != '' }}
|
||||
HAS_SIGNING_CREDS: ${{ secrets.APPLE_SIGNING_ROLE_ARN != '' }}
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
@@ -83,17 +86,68 @@ jobs:
|
||||
go-version: '1.26'
|
||||
check-latest: true
|
||||
|
||||
# GitHub holds ARNs, not credentials, and ARNs outlive a rotation
|
||||
- name: Configure AWS credentials
|
||||
if: env.HAS_SIGNING_CREDS == 'true'
|
||||
uses: aws-actions/configure-aws-credentials@v6
|
||||
with:
|
||||
role-to-assume: ${{ secrets.APPLE_SIGNING_ROLE_ARN }}
|
||||
aws-region: us-east-2
|
||||
|
||||
# parse-json-secrets unpacks into SIGNING_* and ASC_*, masked on the way in
|
||||
- name: Fetch signing credentials
|
||||
if: env.HAS_SIGNING_CREDS == 'true'
|
||||
uses: aws-actions/aws-secretsmanager-get-secrets@v3
|
||||
with:
|
||||
parse-json-secrets: true
|
||||
secret-ids: |
|
||||
SIGNING,${{ secrets.APPLE_SIGNING_DEVELOPER_ID_ARN }}
|
||||
ASC,${{ secrets.APPLE_NOTARY_KEY_ARN }}
|
||||
|
||||
- name: Import certificates
|
||||
if: env.HAS_SIGNING_CREDS == 'true'
|
||||
uses: Apple-Actions/import-codesign-certs@v7
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
|
||||
p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
|
||||
p12-file-base64: ${{ env.SIGNING_P12_BASE64 }}
|
||||
p12-password: ${{ env.SIGNING_PASSWORD }}
|
||||
|
||||
# The action imports but does not check the chain validates, which is how a p12
|
||||
# missing its intermediate reaches a failing codesign
|
||||
- name: Check the identity is usable
|
||||
if: env.HAS_SIGNING_CREDS == 'true'
|
||||
run: |
|
||||
: "${SIGNING_IDENTITY_SHA1:?empty, so the secret has no identity_sha1}"
|
||||
identities=$(security find-identity -v -p codesigning signing_temp.keychain)
|
||||
case "$identities" in
|
||||
*"$SIGNING_IDENTITY_SHA1"*) ;;
|
||||
*) printf '%s\n' "$identities" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# notarytool wants the key as a file
|
||||
- name: Write the App Store Connect key
|
||||
if: env.HAS_SIGNING_CREDS == 'true'
|
||||
run: |
|
||||
mkdir -p ~/private_keys
|
||||
chmod 700 ~/private_keys
|
||||
key_path="$HOME/private_keys/AuthKey_${ASC_KEY_ID}.p8"
|
||||
(umask 077; printf '%s\n' "$ASC_PRIVATE_KEY" > "$key_path")
|
||||
echo "ASC_P8=$key_path" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Drop the credentials from the environment
|
||||
if: env.HAS_SIGNING_CREDS == 'true'
|
||||
run: |
|
||||
# The action's own inventory, so a new field in a secret is covered
|
||||
python3 -c '
|
||||
import json, os
|
||||
raw = os.environ.get("SECRETS_LIST_CLEAN_UP")
|
||||
if raw is None and os.environ.get("SIGNING_P12_BASE64"):
|
||||
raise SystemExit("SECRETS_LIST_CLEAN_UP is gone, fetched secrets are not being scrubbed")
|
||||
keep = {"SIGNING_IDENTITY_SHA1", "ASC_KEY_ID", "ASC_ISSUER_ID"}
|
||||
names = [n for n in json.loads(raw or "[]") if n not in keep]
|
||||
print("\n".join(f"{n}=" for n in dict.fromkeys(names)))
|
||||
' >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build, sign, and notarize
|
||||
env:
|
||||
AC_USERNAME: ${{ secrets.AC_USERNAME }}
|
||||
AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
|
||||
run: |
|
||||
rm -rf release
|
||||
mkdir release
|
||||
@@ -102,17 +156,34 @@ jobs:
|
||||
lipo -create -output ./release/nebula ./build/darwin-amd64/nebula ./build/darwin-arm64/nebula
|
||||
lipo -create -output ./release/nebula-cert ./build/darwin-amd64/nebula-cert ./build/darwin-arm64/nebula-cert
|
||||
|
||||
if [ -n "$AC_USERNAME" ]; then
|
||||
codesign -s "10BC1FDDEB6CE753550156C0669109FAC49E4D1E" -f -v --timestamp --options=runtime -i "net.defined.nebula" ./release/nebula
|
||||
codesign -s "10BC1FDDEB6CE753550156C0669109FAC49E4D1E" -f -v --timestamp --options=runtime -i "net.defined.nebula-cert" ./release/nebula-cert
|
||||
# Unset in a fork, which has no credentials to sign with
|
||||
if [ -n "$SIGNING_IDENTITY_SHA1" ]; then
|
||||
codesign -s "$SIGNING_IDENTITY_SHA1" -f -v --timestamp --options=runtime -i "net.defined.nebula" ./release/nebula
|
||||
codesign -s "$SIGNING_IDENTITY_SHA1" -f -v --timestamp --options=runtime -i "net.defined.nebula-cert" ./release/nebula-cert
|
||||
fi
|
||||
|
||||
zip -j release/nebula-darwin.zip release/nebula-cert release/nebula
|
||||
|
||||
if [ -n "$AC_USERNAME" ]; then
|
||||
xcrun notarytool submit ./release/nebula-darwin.zip --team-id "576H3XS7FP" --apple-id "$AC_USERNAME" --password "$AC_PASSWORD" --wait
|
||||
if [ -n "$ASC_P8" ]; then
|
||||
xcrun notarytool submit ./release/nebula-darwin.zip --key "$ASC_P8" --key-id "$ASC_KEY_ID" --issuer "$ASC_ISSUER_ID" --wait
|
||||
fi
|
||||
|
||||
- name: Drop the signing key
|
||||
if: always() && env.HAS_SIGNING_CREDS == 'true'
|
||||
run: |
|
||||
# Locked, not deleted: import-codesign-certs deletes it in its own post
|
||||
# step and fails the job if it is already gone. Locked is unusable.
|
||||
security lock-keychain signing_temp.keychain || true
|
||||
rm -f "$ASC_P8"
|
||||
# Nothing later in this job needs AWS
|
||||
python3 -c '
|
||||
import json, os
|
||||
names = json.loads(os.environ.get("SECRETS_LIST_CLEAN_UP") or "[]")
|
||||
names += ["ASC_P8", "SIGNING_IDENTITY_SHA1", "ASC_KEY_ID", "ASC_ISSUER_ID",
|
||||
"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"]
|
||||
print("\n".join(f"{n}=" for n in dict.fromkeys(names)))
|
||||
' >> "$GITHUB_ENV"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
|
||||
@@ -6,11 +6,13 @@ package router
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -22,7 +24,6 @@ import (
|
||||
"github.com/slackhq/nebula"
|
||||
"github.com/slackhq/nebula/header"
|
||||
"github.com/slackhq/nebula/udp"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
// outNatKey is the (from, to) pair used by outNat. Comparable struct, so it works as a map key without the
|
||||
@@ -374,7 +375,7 @@ func (r *R) RenderHostmaps(title string, controls ...*nebula.Control) {
|
||||
}
|
||||
|
||||
func (r *R) renderHostmaps(title string) {
|
||||
c := maps.Values(r.controls)
|
||||
c := slices.AppendSeq(make([]*nebula.Control, 0, len(r.controls)), maps.Values(r.controls))
|
||||
sort.SliceStable(c, func(i, j int) bool {
|
||||
return c[i].GetVpnAddrs()[0].Compare(c[j].GetVpnAddrs()[0]) > 0
|
||||
})
|
||||
|
||||
@@ -16,16 +16,15 @@ require (
|
||||
github.com/miekg/dns v1.1.72
|
||||
github.com/miekg/pkcs11 v1.1.2
|
||||
github.com/nbrownus/go-metrics-prometheus v0.0.0-20210712211119-974a6260965f
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/prometheus/client_golang v1.24.1
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/vishvananda/netlink v1.3.1
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.yaml.in/yaml/v3 v3.0.4
|
||||
go.yaml.in/yaml/v3 v3.0.5
|
||||
golang.org/x/crypto v0.54.0
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090
|
||||
golang.org/x/net v0.57.0
|
||||
golang.org/x/sync v0.22.0
|
||||
golang.org/x/sys v0.47.0
|
||||
@@ -46,10 +45,9 @@ require (
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.66.1 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/prometheus/common v0.70.1 // indirect
|
||||
github.com/prometheus/procfs v0.21.1 // indirect
|
||||
github.com/vishvananda/netns v0.0.5 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/mod v0.36.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.45.0 // indirect
|
||||
|
||||
@@ -70,15 +70,14 @@ github.com/kardianos/service v1.3.0 h1:/LGy+xPP2TM+GLTiCZ2di7cy0Jd/qrawlTUfqKYFd
|
||||
github.com/kardianos/service v1.3.0/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
|
||||
github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
@@ -108,8 +107,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU=
|
||||
github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
@@ -118,18 +117,16 @@ github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvM
|
||||
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=
|
||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY=
|
||||
github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI=
|
||||
github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
@@ -153,10 +150,10 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||
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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -164,8 +161,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
|
||||
+11
-1
@@ -5,6 +5,7 @@ package overlay
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
@@ -483,7 +484,16 @@ func (t *tun) addIPs(link netlink.Link) error {
|
||||
//iterate over remainder, remove whoever shouldn't be there
|
||||
al, err := netlink.AddrList(link, netlink.FAMILY_ALL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get tun address list: %s", err)
|
||||
//RTM_GETADDR dumps the whole system, so any concurrent address change
|
||||
//interrupts it - including the kernel's async tentative->preferred
|
||||
//flip of an IPv6 address the AddrReplace calls above just added,
|
||||
//which makes this a race against our own setup. Partial results are
|
||||
//still returned; the worst case is a stale address surviving until
|
||||
//the next config reload, which beats failing startup over it.
|
||||
if !errors.Is(err, netlink.ErrDumpInterrupted) {
|
||||
return fmt.Errorf("failed to get tun address list: %s", err)
|
||||
}
|
||||
t.l.Warn("tun address list dump was interrupted, stale addresses may remain")
|
||||
}
|
||||
|
||||
for i := range al {
|
||||
|
||||
Reference in New Issue
Block a user