mirror of
https://github.com/siderolabs/discovery-service.git
synced 2025-03-14 09:55:08 +00:00
refactor: kresify, fix linter and rename to Kubespan manager
Tried to limit the scope of changes. Signed-off-by: Artem Chernyshev <artem.chernyshev@talos-systems.com>
This commit is contained in:
18
.codecov.yml
Normal file
18
.codecov.yml
Normal file
@ -0,0 +1,18 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:22:39Z by kres 907039b.
|
||||
|
||||
codecov:
|
||||
require_ci_to_pass: false
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 50%
|
||||
threshold: 0.5%
|
||||
base: auto
|
||||
if_ci_failed: success
|
||||
patch: off
|
||||
|
||||
comment: false
|
35
.conform.yaml
Normal file
35
.conform.yaml
Normal file
@ -0,0 +1,35 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:22:39Z by kres 907039b.
|
||||
|
||||
policies:
|
||||
- type: commit
|
||||
spec:
|
||||
dco: true
|
||||
gpg: false
|
||||
spellcheck:
|
||||
locale: US
|
||||
maximumOfOneCommit: true
|
||||
header:
|
||||
length: 89
|
||||
imperative: true
|
||||
case: lower
|
||||
invalidLastCharacters: .
|
||||
body:
|
||||
required: true
|
||||
conventional:
|
||||
types: ["chore","docs","perf","refactor","style","test","release"]
|
||||
scopes: [".*"]
|
||||
- type: license
|
||||
spec:
|
||||
skipPaths:
|
||||
- .git/
|
||||
includeSuffixes:
|
||||
- .go
|
||||
excludeSuffixes:
|
||||
- .pb.go
|
||||
- .pb.gw.go
|
||||
header: |
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@ -0,0 +1,13 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:32:42Z by kres 907039b.
|
||||
|
||||
**
|
||||
!internal
|
||||
!pkg
|
||||
!cmd
|
||||
!go.mod
|
||||
!go.sum
|
||||
!.golangci.yml
|
||||
!README.md
|
||||
!.markdownlint.json
|
340
.drone.yml
Normal file
340
.drone.yml
Normal file
@ -0,0 +1,340 @@
|
||||
---
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:23:41Z by kres 907039b.
|
||||
|
||||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: default
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: setup-ci
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- sleep 5
|
||||
- git fetch --tags
|
||||
- install-ci-key
|
||||
- docker buildx create --driver docker-container --platform linux/amd64 --name local --use unix:///var/outer-run/docker.sock
|
||||
- docker buildx inspect --bootstrap
|
||||
environment:
|
||||
SSH_KEY:
|
||||
from_secret: ssh_key
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
|
||||
- name: base
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make base
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
depends_on:
|
||||
- setup-ci
|
||||
|
||||
- name: unit-tests
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make unit-tests
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
depends_on:
|
||||
- base
|
||||
|
||||
- name: unit-tests-race
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make unit-tests-race
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
depends_on:
|
||||
- base
|
||||
|
||||
- name: coverage
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make coverage
|
||||
environment:
|
||||
CODECOV_TOKEN:
|
||||
from_secret: CODECOV_TOKEN
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
depends_on:
|
||||
- unit-tests
|
||||
|
||||
- name: kubespan-manager
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make kubespan-manager
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
depends_on:
|
||||
- base
|
||||
|
||||
- name: lint
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make lint
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
depends_on:
|
||||
- base
|
||||
|
||||
- name: image-kubespan-manager
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make image-kubespan-manager
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
depends_on:
|
||||
- kubespan-manager
|
||||
- lint
|
||||
- unit-tests
|
||||
|
||||
- name: push-kubespan-manager
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- docker login ghcr.io --username "$${GHCR_USERNAME}" --password "$${GHCR_PASSWORD}"
|
||||
- make image-kubespan-manager
|
||||
environment:
|
||||
GHCR_PASSWORD:
|
||||
from_secret: ghcr_token
|
||||
GHCR_USERNAME:
|
||||
from_secret: ghcr_username
|
||||
PUSH: true
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
depends_on:
|
||||
- image-kubespan-manager
|
||||
|
||||
- name: push-kubespan-manager-latest
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- docker login ghcr.io --username "$${GHCR_USERNAME}" --password "$${GHCR_PASSWORD}"
|
||||
- make image-kubespan-manager TAG=latest
|
||||
environment:
|
||||
GHCR_PASSWORD:
|
||||
from_secret: ghcr_token
|
||||
GHCR_USERNAME:
|
||||
from_secret: ghcr_username
|
||||
PUSH: true
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
depends_on:
|
||||
- push-kubespan-manager
|
||||
|
||||
- name: release-notes
|
||||
pull: always
|
||||
image: autonomy/build-container:latest
|
||||
commands:
|
||||
- make release-notes
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
depends_on:
|
||||
- unit-tests
|
||||
- coverage
|
||||
- kubespan-manager
|
||||
- image-kubespan-manager
|
||||
- lint
|
||||
|
||||
- name: release
|
||||
pull: always
|
||||
image: plugins/github-release
|
||||
settings:
|
||||
api_key:
|
||||
from_secret: github_token
|
||||
checksum:
|
||||
- sha256
|
||||
- sha512
|
||||
draft: true
|
||||
files:
|
||||
- _out/*
|
||||
note: _out/RELEASE_NOTES.md
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
depends_on:
|
||||
- release-notes
|
||||
|
||||
services:
|
||||
- name: docker
|
||||
image: docker:19.03-dind
|
||||
entrypoint:
|
||||
- dockerd
|
||||
commands:
|
||||
- --dns=8.8.8.8
|
||||
- --dns=8.8.4.4
|
||||
- --mtu=1500
|
||||
- --log-level=error
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
path: /var/outer-run
|
||||
- name: docker-socket
|
||||
path: /var/run
|
||||
- name: buildx
|
||||
path: /root/.docker/buildx
|
||||
- name: ssh
|
||||
path: /root/.ssh
|
||||
|
||||
volumes:
|
||||
- name: outer-docker-socket
|
||||
host:
|
||||
path: /var/ci-docker
|
||||
- name: docker-socket
|
||||
temp:
|
||||
medium: memory
|
||||
- name: buildx
|
||||
temp:
|
||||
medium: memory
|
||||
- name: ssh
|
||||
temp:
|
||||
medium: memory
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: notify
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps:
|
||||
- name: slack
|
||||
image: plugins/slack
|
||||
settings:
|
||||
channel: proj-talos-maintainers
|
||||
link_names: true
|
||||
template: "{{#if build.pull }}\n*{{#success build.status}}✓ Success{{else}}✕ Fail{{/success}}*: {{ repo.owner }}/{{ repo.name }} - <https://github.com/{{ repo.owner }}/{{ repo.name }}/pull/{{ build.pull }}|Pull Request #{{ build.pull }}>\n{{else}}\n*{{#success build.status}}✓ Success{{else}}✕ Fail{{/success}}: {{ repo.owner }}/{{ repo.name }} - Build #{{ build.number }}* (type: `{{ build.event }}`)\n{{/if}}\nCommit: <https://github.com/{{ repo.owner }}/{{ repo.name }}/commit/{{ build.commit }}|{{ truncate build.commit 8 }}>\nBranch: <https://github.com/{{ repo.owner }}/{{ repo.name }}/commits/{{ build.branch }}|{{ build.branch }}>\nAuthor: {{ build.author }}\n<{{ build.link }}|Visit build page>"
|
||||
webhook:
|
||||
from_secret: slack_webhook
|
||||
when:
|
||||
status:
|
||||
- success
|
||||
- failure
|
||||
|
||||
trigger:
|
||||
status:
|
||||
- success
|
||||
- failure
|
||||
|
||||
depends_on:
|
||||
- default
|
||||
|
||||
...
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1 +1,5 @@
|
||||
/wglan-manager
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:22:39Z by kres 907039b.
|
||||
|
||||
_out
|
||||
|
150
.golangci.yml
Normal file
150
.golangci.yml
Normal file
@ -0,0 +1,150 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:32:42Z by kres 907039b.
|
||||
|
||||
|
||||
# options for analysis running
|
||||
run:
|
||||
timeout: 10m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
build-tags: []
|
||||
skip-dirs: []
|
||||
skip-dirs-use-default: true
|
||||
skip-files: []
|
||||
modules-download-mode: readonly
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
format: colored-line-number
|
||||
print-issued-lines: true
|
||||
print-linter-name: true
|
||||
uniq-by-line: true
|
||||
path-prefix: ""
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
dogsled:
|
||||
max-blank-identifiers: 2
|
||||
dupl:
|
||||
threshold: 150
|
||||
errcheck:
|
||||
check-type-assertions: true
|
||||
check-blank: true
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: false
|
||||
funlen:
|
||||
lines: 60
|
||||
statements: 40
|
||||
gci:
|
||||
local-prefixes: github.com/talos-systems/kubespan-manager
|
||||
gocognit:
|
||||
min-complexity: 30
|
||||
nestif:
|
||||
min-complexity: 5
|
||||
goconst:
|
||||
min-len: 3
|
||||
min-occurrences: 3
|
||||
gocritic:
|
||||
disabled-checks: []
|
||||
gocyclo:
|
||||
min-complexity: 20
|
||||
godot:
|
||||
check-all: false
|
||||
godox:
|
||||
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
|
||||
- NOTE
|
||||
- OPTIMIZE # marks code that should be optimized before merging
|
||||
- HACK # marks hack-arounds that should be removed before merging
|
||||
gofmt:
|
||||
simplify: true
|
||||
goimports:
|
||||
local-prefixes: github.com/talos-systems/kubespan-manager
|
||||
golint:
|
||||
min-confidence: 0.8
|
||||
gomnd:
|
||||
settings: {}
|
||||
gomodguard: {}
|
||||
govet:
|
||||
check-shadowing: true
|
||||
enable-all: true
|
||||
depguard:
|
||||
list-type: blacklist
|
||||
include-go-root: false
|
||||
lll:
|
||||
line-length: 200
|
||||
tab-width: 4
|
||||
misspell:
|
||||
locale: US
|
||||
ignore-words: []
|
||||
nakedret:
|
||||
max-func-lines: 30
|
||||
prealloc:
|
||||
simple: true
|
||||
range-loops: true # Report preallocation suggestions on range loops, true by default
|
||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
||||
nolintlint:
|
||||
allow-unused: false
|
||||
allow-leading-space: false
|
||||
allow-no-explanation: []
|
||||
require-explanation: false
|
||||
require-specific: true
|
||||
rowserrcheck: {}
|
||||
testpackage:
|
||||
unparam:
|
||||
check-exported: false
|
||||
unused:
|
||||
check-exported: false
|
||||
whitespace:
|
||||
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
|
||||
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
|
||||
wsl:
|
||||
strict-append: true
|
||||
allow-assign-and-call: true
|
||||
allow-multiline-assign: true
|
||||
allow-cuddle-declarations: false
|
||||
allow-trailing-comment: false
|
||||
force-case-trailing-whitespace: 0
|
||||
force-err-cuddling: false
|
||||
allow-separated-leading-comment: false
|
||||
gofumpt:
|
||||
extra-rules: false
|
||||
cyclop:
|
||||
# the maximal code complexity to report
|
||||
max-complexity: 20
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- gas
|
||||
- typecheck
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- funlen
|
||||
- godox
|
||||
- gomnd
|
||||
- goerr113
|
||||
- nestif
|
||||
- wrapcheck
|
||||
- paralleltest
|
||||
- exhaustivestruct
|
||||
- forbidigo
|
||||
disable-all: false
|
||||
fast: false
|
||||
|
||||
|
||||
issues:
|
||||
exclude: []
|
||||
exclude-rules: []
|
||||
exclude-use-default: false
|
||||
exclude-case-sensitive: false
|
||||
max-issues-per-linter: 10
|
||||
max-same-issues: 3
|
||||
|
||||
new: false
|
||||
|
||||
severity:
|
||||
default-severity: error
|
||||
|
||||
case-sensitive: false
|
9
.markdownlint.json
Normal file
9
.markdownlint.json
Normal file
@ -0,0 +1,9 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:22:39Z by kres 907039b.
|
||||
|
||||
{
|
||||
"MD013": false,
|
||||
"MD033": false,
|
||||
"default": true
|
||||
}
|
106
Dockerfile
106
Dockerfile
@ -1,12 +1,96 @@
|
||||
FROM golang:alpine AS builder
|
||||
ENV GO111MODULE on
|
||||
RUN apk add --no-cache git
|
||||
WORKDIR $GOPATH/src/github.com/talos-systems/wglan-manager
|
||||
COPY . .
|
||||
RUN go get -d -v
|
||||
RUN go build -o /go/bin/web
|
||||
# syntax = docker/dockerfile-upstream:1.2.0-labs
|
||||
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:32:42Z by kres 907039b.
|
||||
|
||||
ARG TOOLCHAIN
|
||||
|
||||
# cleaned up specs and compiled versions
|
||||
FROM scratch AS generate
|
||||
|
||||
FROM ghcr.io/talos-systems/ca-certificates:v0.3.0-12-g90722c3 AS image-ca-certificates
|
||||
|
||||
FROM ghcr.io/talos-systems/fhs:v0.3.0-12-g90722c3 AS image-fhs
|
||||
|
||||
# runs markdownlint
|
||||
FROM node:14.8.0-alpine AS lint-markdown
|
||||
RUN npm i -g markdownlint-cli@0.23.2
|
||||
RUN npm i sentences-per-line@0.2.1
|
||||
WORKDIR /src
|
||||
COPY .markdownlint.json .
|
||||
COPY ./README.md ./README.md
|
||||
RUN markdownlint --ignore "CHANGELOG.md" --ignore "**/node_modules/**" --ignore '**/hack/chglog/**' --rules /node_modules/sentences-per-line/index.js .
|
||||
|
||||
# base toolchain image
|
||||
FROM ${TOOLCHAIN} AS toolchain
|
||||
RUN apk --update --no-cache add bash curl build-base protoc protobuf-dev
|
||||
|
||||
# build tools
|
||||
FROM toolchain AS tools
|
||||
ENV GO111MODULE on
|
||||
ENV CGO_ENABLED 0
|
||||
ENV GOPATH /go
|
||||
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b /bin v1.38.0
|
||||
ARG GOFUMPT_VERSION
|
||||
RUN cd $(mktemp -d) \
|
||||
&& go mod init tmp \
|
||||
&& go get mvdan.cc/gofumpt/gofumports@${GOFUMPT_VERSION} \
|
||||
&& mv /go/bin/gofumports /bin/gofumports
|
||||
|
||||
# tools and sources
|
||||
FROM tools AS base
|
||||
WORKDIR /src
|
||||
COPY ./go.mod .
|
||||
COPY ./go.sum .
|
||||
RUN --mount=type=cache,target=/go/pkg go mod download
|
||||
RUN --mount=type=cache,target=/go/pkg go mod verify
|
||||
COPY ./internal ./internal
|
||||
COPY ./pkg ./pkg
|
||||
COPY ./cmd ./cmd
|
||||
RUN --mount=type=cache,target=/go/pkg go list -mod=readonly all >/dev/null
|
||||
|
||||
# builds kubespan-manager-linux-amd64
|
||||
FROM base AS kubespan-manager-linux-amd64-build
|
||||
COPY --from=generate / /
|
||||
WORKDIR /src/cmd/kubespan-manager
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go build -ldflags "-s -w" -o /kubespan-manager-linux-amd64
|
||||
|
||||
# runs gofumpt
|
||||
FROM base AS lint-gofumpt
|
||||
RUN find . -name '*.pb.go' | xargs -r rm
|
||||
RUN find . -name '*.pb.gw.go' | xargs -r rm
|
||||
RUN FILES="$(gofumports -l -local github.com/talos-systems/kubespan-manager .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumports -w -local github.com/talos-systems/kubespan-manager .':\n${FILES}"; exit 1)
|
||||
|
||||
# runs golangci-lint
|
||||
FROM base AS lint-golangci-lint
|
||||
COPY .golangci.yml .
|
||||
ENV GOGC 50
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/root/.cache/golangci-lint --mount=type=cache,target=/go/pkg golangci-lint run --config .golangci.yml
|
||||
|
||||
# runs unit-tests with race detector
|
||||
FROM base AS unit-tests-race
|
||||
ARG TESTPKGS
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg --mount=type=cache,target=/tmp CGO_ENABLED=1 go test -v -race -count 1 ${TESTPKGS}
|
||||
|
||||
# runs unit-tests
|
||||
FROM base AS unit-tests-run
|
||||
ARG TESTPKGS
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg --mount=type=cache,target=/tmp go test -v -covermode=atomic -coverprofile=coverage.txt -coverpkg=${TESTPKGS} -count 1 ${TESTPKGS}
|
||||
|
||||
FROM scratch AS kubespan-manager-linux-amd64
|
||||
COPY --from=kubespan-manager-linux-amd64-build /kubespan-manager-linux-amd64 /kubespan-manager-linux-amd64
|
||||
|
||||
FROM scratch AS unit-tests
|
||||
COPY --from=unit-tests-run /src/coverage.txt /coverage.txt
|
||||
|
||||
FROM kubespan-manager-linux-${TARGETARCH} AS kubespan-manager
|
||||
|
||||
FROM scratch AS image-kubespan-manager
|
||||
ARG TARGETARCH
|
||||
COPY --from=kubespan-manager kubespan-manager-linux-${TARGETARCH} /kubespan-manager
|
||||
COPY --from=image-fhs / /
|
||||
COPY --from=image-ca-certificates / /
|
||||
LABEL org.opencontainers.image.source https://github.com/talos-systems/wglan-manager
|
||||
ENTRYPOINT ["/kubespan-manager"]
|
||||
|
||||
FROM alpine
|
||||
RUN apk add --no-cache ca-certificates
|
||||
COPY --from=builder /go/bin/web /go/bin/web
|
||||
ENTRYPOINT ["/go/bin/web"]
|
||||
|
154
Makefile
Normal file
154
Makefile
Normal file
@ -0,0 +1,154 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:32:42Z by kres 907039b.
|
||||
|
||||
# common variables
|
||||
|
||||
SHA := $(shell git describe --match=none --always --abbrev=8 --dirty)
|
||||
TAG := $(shell git describe --tag --always --dirty)
|
||||
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
||||
ARTIFACTS := _out
|
||||
REGISTRY ?= ghcr.io
|
||||
USERNAME ?= talos-systems
|
||||
REGISTRY_AND_USERNAME ?= $(REGISTRY)/$(USERNAME)
|
||||
GOFUMPT_VERSION ?= abc0db2c416aca0f60ea33c23c76665f6e7ba0b6
|
||||
GO_VERSION ?= 1.16
|
||||
PROTOBUF_GO_VERSION ?= 1.25.0
|
||||
GRPC_GO_VERSION ?= 1.1.0
|
||||
GRPC_GATEWAY_VERSION ?= 2.4.0
|
||||
TESTPKGS ?= ./...
|
||||
KRES_IMAGE ?= ghcr.io/talos-systems/kres:latest
|
||||
|
||||
# docker build settings
|
||||
|
||||
BUILD := docker buildx build
|
||||
PLATFORM ?= linux/amd64
|
||||
PROGRESS ?= auto
|
||||
PUSH ?= false
|
||||
CI_ARGS ?=
|
||||
COMMON_ARGS = --file=Dockerfile
|
||||
COMMON_ARGS += --progress=$(PROGRESS)
|
||||
COMMON_ARGS += --platform=$(PLATFORM)
|
||||
COMMON_ARGS += --push=$(PUSH)
|
||||
COMMON_ARGS += --build-arg=ARTIFACTS=$(ARTIFACTS)
|
||||
COMMON_ARGS += --build-arg=SHA=$(SHA)
|
||||
COMMON_ARGS += --build-arg=TAG=$(TAG)
|
||||
COMMON_ARGS += --build-arg=USERNAME=$(USERNAME)
|
||||
COMMON_ARGS += --build-arg=TOOLCHAIN=$(TOOLCHAIN)
|
||||
COMMON_ARGS += --build-arg=GOFUMPT_VERSION=$(GOFUMPT_VERSION)
|
||||
COMMON_ARGS += --build-arg=PROTOBUF_GO_VERSION=$(PROTOBUF_GO_VERSION)
|
||||
COMMON_ARGS += --build-arg=GRPC_GO_VERSION=$(GRPC_GO_VERSION)
|
||||
COMMON_ARGS += --build-arg=GRPC_GATEWAY_VERSION=$(GRPC_GATEWAY_VERSION)
|
||||
COMMON_ARGS += --build-arg=TESTPKGS=$(TESTPKGS)
|
||||
TOOLCHAIN ?= docker.io/golang:1.16-alpine
|
||||
|
||||
# help menu
|
||||
|
||||
export define HELP_MENU_HEADER
|
||||
# Getting Started
|
||||
|
||||
To build this project, you must have the following installed:
|
||||
|
||||
- git
|
||||
- make
|
||||
- docker (19.03 or higher)
|
||||
|
||||
## Creating a Builder Instance
|
||||
|
||||
The build process makes use of experimental Docker features (buildx).
|
||||
To enable experimental features, add 'experimental: "true"' to '/etc/docker/daemon.json' on
|
||||
Linux or enable experimental features in Docker GUI for Windows or Mac.
|
||||
|
||||
To create a builder instance, run:
|
||||
|
||||
docker buildx create --name local --use
|
||||
|
||||
|
||||
If you already have a compatible builder instance, you may use that instead.
|
||||
|
||||
## Artifacts
|
||||
|
||||
All artifacts will be output to ./$(ARTIFACTS). Images will be tagged with the
|
||||
registry "$(REGISTRY)", username "$(USERNAME)", and a dynamic tag (e.g. $(IMAGE):$(TAG)).
|
||||
The registry and username can be overridden by exporting REGISTRY, and USERNAME
|
||||
respectively.
|
||||
|
||||
endef
|
||||
|
||||
all: unit-tests kubespan-manager image-kubespan-manager lint
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## Cleans up all artifacts.
|
||||
@rm -rf $(ARTIFACTS)
|
||||
|
||||
target-%: ## Builds the specified target defined in the Dockerfile. The build result will only remain in the build cache.
|
||||
@$(BUILD) --target=$* $(COMMON_ARGS) $(TARGET_ARGS) $(CI_ARGS) .
|
||||
|
||||
local-%: ## Builds the specified target defined in the Dockerfile using the local output type. The build result will be output to the specified local destination.
|
||||
@$(MAKE) target-$* TARGET_ARGS="--output=type=local,dest=$(DEST) $(TARGET_ARGS)"
|
||||
|
||||
lint-golangci-lint: ## Runs golangci-lint linter.
|
||||
@$(MAKE) target-$@
|
||||
|
||||
lint-gofumpt: ## Runs gofumpt linter.
|
||||
@$(MAKE) target-$@
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Formats the source code
|
||||
@docker run --rm -it -v $(PWD):/src -w /src golang:$(GO_VERSION) \
|
||||
bash -c "export GO111MODULE=on; export GOPROXY=https://proxy.golang.org; \
|
||||
cd /tmp && go mod init tmp && go get mvdan.cc/gofumpt/gofumports@$(GOFUMPT_VERSION) && \
|
||||
cd - && gofumports -w -local github.com/talos-systems/kubespan-manager ."
|
||||
|
||||
.PHONY: base
|
||||
base: ## Prepare base toolchain
|
||||
@$(MAKE) target-$@
|
||||
|
||||
.PHONY: unit-tests
|
||||
unit-tests: ## Performs unit tests
|
||||
@$(MAKE) local-$@ DEST=$(ARTIFACTS)
|
||||
|
||||
.PHONY: unit-tests-race
|
||||
unit-tests-race: ## Performs unit tests with race detection enabled.
|
||||
@$(MAKE) target-$@
|
||||
|
||||
.PHONY: coverage
|
||||
coverage: ## Upload coverage data to codecov.io.
|
||||
bash -c "bash <(curl -s https://codecov.io/bash) -f $(ARTIFACTS)/coverage.txt -X fix"
|
||||
|
||||
.PHONY: $(ARTIFACTS)/kubespan-manager-linux-amd64
|
||||
$(ARTIFACTS)/kubespan-manager-linux-amd64:
|
||||
@$(MAKE) local-kubespan-manager-linux-amd64 DEST=$(ARTIFACTS)
|
||||
|
||||
.PHONY: kubespan-manager-linux-amd64
|
||||
kubespan-manager-linux-amd64: $(ARTIFACTS)/kubespan-manager-linux-amd64 ## Builds executable for kubespan-manager-linux-amd64.
|
||||
|
||||
.PHONY: kubespan-manager
|
||||
kubespan-manager: kubespan-manager-linux-amd64
|
||||
|
||||
.PHONY: lint-markdown
|
||||
lint-markdown: ## Runs markdownlint.
|
||||
@$(MAKE) target-$@
|
||||
|
||||
.PHONY: lint
|
||||
lint: lint-golangci-lint lint-gofumpt lint-markdown ## Run all linters for the project.
|
||||
|
||||
.PHONY: image-kubespan-manager
|
||||
image-kubespan-manager: ## Builds image for kubespan-manager.
|
||||
@$(MAKE) target-$@ TARGET_ARGS="--tag=$(REGISTRY)/$(USERNAME)/kubespan-manager:$(TAG)"
|
||||
|
||||
.PHONY: rekres
|
||||
rekres:
|
||||
@docker pull $(KRES_IMAGE)
|
||||
@docker run --rm -v $(PWD):/src -w /src -e GITHUB_TOKEN $(KRES_IMAGE)
|
||||
|
||||
.PHONY: help
|
||||
help: ## This help menu.
|
||||
@echo "$$HELP_MENU_HEADER"
|
||||
@grep -E '^[a-zA-Z%_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: release-notes
|
||||
release-notes:
|
||||
mkdir -p $(ARTIFACTS)
|
||||
@ARTIFACTS=$(ARTIFACTS) ./hack/release.sh $@ $(ARTIFACTS)/RELEASE_NOTES.md $(TAG)
|
||||
|
@ -1,6 +1,11 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -8,15 +13,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/talos-systems/wglan-manager/db"
|
||||
"github.com/talos-systems/wglan-manager/types"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/talos-systems/kubespan-manager/internal/db"
|
||||
"github.com/talos-systems/kubespan-manager/pkg/types"
|
||||
)
|
||||
|
||||
var listenAddr = ":3000"
|
||||
var devMode bool
|
||||
|
||||
const defaultPort = 5000
|
||||
var (
|
||||
listenAddr = ":3000"
|
||||
devMode bool
|
||||
)
|
||||
|
||||
var nodeDB db.DB
|
||||
|
||||
@ -25,31 +31,29 @@ func init() {
|
||||
flag.BoolVar(&devMode, "debug", false, "enable debug mode")
|
||||
}
|
||||
|
||||
//nolint:gocognit
|
||||
func main() {
|
||||
|
||||
flag.Parse()
|
||||
|
||||
logger, err := zap.NewProduction()
|
||||
if err != nil {
|
||||
log.Fatalln("failed to initialise logger:", err)
|
||||
log.Fatalln("failed to initialize logger:", err)
|
||||
}
|
||||
|
||||
if os.Getenv("MODE") == "dev" {
|
||||
devMode = true
|
||||
logger, err = zap.NewDevelopment()
|
||||
if err != nil {
|
||||
log.Fatalln("failed to initialise development logger:", err)
|
||||
}
|
||||
}
|
||||
|
||||
defer logger.Sync() // nolint: errcheck
|
||||
if err != nil {
|
||||
log.Fatalln("failed to initialize development logger:", err)
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("REDIS_ADDR") != "" {
|
||||
nodeDB, err = db.NewRedis(os.Getenv("REDIS_ADDR"), logger)
|
||||
if err != nil {
|
||||
log.Fatalln("failed to connect to redis: %w", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
nodeDB = db.New(logger)
|
||||
}
|
||||
@ -60,31 +64,37 @@ func main() {
|
||||
cluster := c.Params("cluster")
|
||||
if cluster == "" {
|
||||
logger.Error("empty cluster for node list")
|
||||
|
||||
return c.SendStatus(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
list, err := nodeDB.List(c.Context(), cluster)
|
||||
if len(list) < 1 {
|
||||
list, e := nodeDB.List(c.Context(), cluster)
|
||||
if e != nil {
|
||||
if errors.Is(e, db.ErrNotFound) {
|
||||
logger.Warn("cluster not found",
|
||||
zap.String("cluster", cluster),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
return c.SendStatus(http.StatusNotFound)
|
||||
}
|
||||
|
||||
return c.SendStatus(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
logger.Info("listing cluster nodes",
|
||||
zap.String("cluster", c.Params("cluster", "")),
|
||||
zap.Int("count", len(list)),
|
||||
)
|
||||
|
||||
return c.JSON(list)
|
||||
|
||||
})
|
||||
|
||||
app.Get("/:cluster/:node", func(c *fiber.Ctx) error {
|
||||
cluster := c.Params("cluster", "")
|
||||
if cluster == "" {
|
||||
logger.Error("empty cluster for node get")
|
||||
|
||||
return c.SendStatus(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
@ -93,19 +103,25 @@ func main() {
|
||||
logger.Error("empty node for node get",
|
||||
zap.String("cluster", c.Params("cluster", "")),
|
||||
)
|
||||
|
||||
return c.SendStatus(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
n, err := nodeDB.Get(c.Context(), cluster, node)
|
||||
if err != nil {
|
||||
n, e := nodeDB.Get(c.Context(), cluster, node)
|
||||
if e != nil {
|
||||
if errors.Is(e, db.ErrNotFound) {
|
||||
logger.Warn("node not found",
|
||||
zap.String("cluster", cluster),
|
||||
zap.String("node", node),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
return c.SendStatus(http.StatusNotFound)
|
||||
}
|
||||
|
||||
return c.SendStatus(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
logger.Info("returning cluster node",
|
||||
zap.String("cluster", c.Params("cluster", "")),
|
||||
zap.String("node", n.ID),
|
||||
@ -121,12 +137,13 @@ func main() {
|
||||
app.Put("/:cluster/:node", func(c *fiber.Ctx) error {
|
||||
var addresses []*types.Address
|
||||
|
||||
if err := c.BodyParser(&addresses); err != nil {
|
||||
if e := c.BodyParser(&addresses); e != nil {
|
||||
logger.Error("failed to parse node PUT",
|
||||
zap.String("cluster", c.Params("cluster", "")),
|
||||
zap.String("node", c.Params("node", "")),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
return c.SendStatus(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
@ -146,6 +163,7 @@ func main() {
|
||||
zap.Strings("addresses", addressToString(addresses)),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
return c.SendStatus(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@ -160,6 +178,7 @@ func main() {
|
||||
zap.String("cluster", c.Params("cluster", "")),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
return c.SendStatus(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
@ -171,6 +190,7 @@ func main() {
|
||||
zap.Strings("addresses", addressToString(n.Addresses)),
|
||||
zap.Error(err),
|
||||
)
|
||||
|
||||
return c.SendStatus(http.StatusInternalServerError)
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -1,4 +1,4 @@
|
||||
module github.com/talos-systems/wglan-manager
|
||||
module github.com/talos-systems/kubespan-manager
|
||||
|
||||
go 1.16
|
||||
|
||||
|
26
hack/git-chglog/CHANGELOG.tpl.md
Normal file
26
hack/git-chglog/CHANGELOG.tpl.md
Normal file
@ -0,0 +1,26 @@
|
||||
<!-- THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. -->
|
||||
<!-- -->
|
||||
<!-- Generated on 2021-08-13T12:22:39Z by kres 907039b. -->
|
||||
|
||||
{{ range .Versions }}
|
||||
<a name="{{ .Tag.Name }}"></a>
|
||||
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]({{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}){{ else }}{{ .Tag.Name }}{{ end }} ({{ datetime "2006-01-02" .Tag.Date }})
|
||||
|
||||
{{ range .CommitGroups -}}
|
||||
### {{ .Title }}
|
||||
|
||||
{{ range .Commits -}}
|
||||
* {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
|
||||
{{ end }}
|
||||
{{ end -}}
|
||||
|
||||
{{- if .NoteGroups -}}
|
||||
{{ range .NoteGroups -}}
|
||||
### {{ .Title }}
|
||||
|
||||
{{ range .Notes }}
|
||||
{{ .Body }}
|
||||
{{ end }}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
32
hack/git-chglog/config.yaml
Normal file
32
hack/git-chglog/config.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:22:39Z by kres 907039b.
|
||||
|
||||
style: github
|
||||
template: CHANGELOG.tpl.md
|
||||
info:
|
||||
title: CHANGELOG
|
||||
repository_url: https://github.com/talos-systems/wglan-manager
|
||||
options:
|
||||
commits:
|
||||
# filters:
|
||||
# Type:
|
||||
# - feat
|
||||
# - fix
|
||||
# - perf
|
||||
# - refactor
|
||||
commit_groups:
|
||||
# title_maps:
|
||||
# feat: Features
|
||||
# fix: Bug Fixes
|
||||
# perf: Performance Improvements
|
||||
# refactor: Code Refactoring
|
||||
header:
|
||||
pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$"
|
||||
pattern_maps:
|
||||
- Type
|
||||
- Scope
|
||||
- Subject
|
||||
notes:
|
||||
keywords:
|
||||
- BREAKING CHANGE
|
68
hack/release.sh
Executable file
68
hack/release.sh
Executable file
@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:22:39Z by kres 907039b.
|
||||
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
RELEASE_TOOL_IMAGE="ghcr.io/talos-systems/release-tool:latest"
|
||||
|
||||
function release-tool {
|
||||
docker pull "${RELEASE_TOOL_IMAGE}" >/dev/null
|
||||
docker run --rm -w /src -v "${PWD}":/src:ro "${RELEASE_TOOL_IMAGE}" -l -d -n -t "${1}" ./hack/release.toml
|
||||
}
|
||||
|
||||
function changelog {
|
||||
if [ "$#" -eq 1 ]; then
|
||||
(release-tool ${1}; echo; cat CHANGELOG.md) > CHANGELOG.md- && mv CHANGELOG.md- CHANGELOG.md
|
||||
else
|
||||
echo 1>&2 "Usage: $0 changelog [tag]"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function release-notes {
|
||||
release-tool "${2}" > "${1}"
|
||||
}
|
||||
|
||||
function cherry-pick {
|
||||
if [ $# -ne 2 ]; then
|
||||
echo 1>&2 "Usage: $0 cherry-pick <commit> <branch>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git checkout $2
|
||||
git fetch
|
||||
git rebase upstream/$2
|
||||
git cherry-pick -x $1
|
||||
}
|
||||
|
||||
function commit {
|
||||
if [ $# -ne 1 ]; then
|
||||
echo 1>&2 "Usage: $0 commit <tag>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git commit -s -m "release($1): prepare release" -m "This is the official $1 release."
|
||||
}
|
||||
|
||||
if declare -f "$1" > /dev/null
|
||||
then
|
||||
cmd="$1"
|
||||
shift
|
||||
$cmd "$@"
|
||||
else
|
||||
cat <<EOF
|
||||
Usage:
|
||||
commit: Create the official release commit message.
|
||||
cherry-pick: Cherry-pick a commit into a release branch.
|
||||
changelog: Update the specified CHANGELOG.
|
||||
release-notes: Create release notes for GitHub release.
|
||||
EOF
|
||||
|
||||
exit 1
|
||||
fi
|
16
hack/release.toml
Normal file
16
hack/release.toml
Normal file
@ -0,0 +1,16 @@
|
||||
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
|
||||
#
|
||||
# Generated on 2021-08-13T12:22:39Z by kres 907039b.
|
||||
|
||||
|
||||
# commit to be tagged for the new release
|
||||
commit = "HEAD"
|
||||
|
||||
project_name = "wglan-manager"
|
||||
github_repo = "talos-systems/wglan-manager"
|
||||
match_deps = "^github.com/(talos-systems/[a-zA-Z0-9-]+)$"
|
||||
|
||||
# previous = -
|
||||
# pre_release = true
|
||||
|
||||
# [notes]
|
@ -1,30 +1,41 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package db contains state storage logic.
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/talos-systems/wglan-manager/types"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/talos-systems/kubespan-manager/pkg/types"
|
||||
)
|
||||
|
||||
// ErrNotFound means that record is not found in DB.
|
||||
var ErrNotFound = errors.New("not found")
|
||||
|
||||
// AddressExpirationTimeout is the amount of time after which addresses of a node should be expired.
|
||||
const AddressExpirationTimeout = 10 * time.Minute
|
||||
|
||||
// DB manager state persistent storage interface.
|
||||
type DB interface {
|
||||
// Add adds a set of known Endpoints to a node, creating the node, if it does not exist.
|
||||
Add(ctx context.Context, cluster string, n *types.Node) error
|
||||
|
||||
// AddAddresses adds a set of addresses for a node.
|
||||
AddAddresses(ctx context.Context, cluster string, id string, ep ...*types.Address) error
|
||||
AddAddresses(ctx context.Context, cluster, id string, ep ...*types.Address) error
|
||||
|
||||
// Clean executes a database cleanup routine.
|
||||
Clean()
|
||||
|
||||
// Get returns the details of the node.
|
||||
Get(ctx context.Context, cluster string, id string) (*types.Node, error)
|
||||
Get(ctx context.Context, cluster, id string) (*types.Node, error)
|
||||
|
||||
// List returns the set of Nodes for the given Cluster.
|
||||
List(ctx context.Context, cluster string) ([]*types.Node, error)
|
||||
@ -44,7 +55,7 @@ func New(logger *zap.Logger) DB {
|
||||
}
|
||||
}
|
||||
|
||||
// Add implements DB
|
||||
// Add implements DB.
|
||||
func (d *ramDB) Add(ctx context.Context, cluster string, n *types.Node) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
@ -66,7 +77,7 @@ func (d *ramDB) Add(ctx context.Context, cluster string, n *types.Node) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *ramDB) AddAddresses(ctx context.Context, cluster string, id string, addresses ...*types.Address) error {
|
||||
func (d *ramDB) AddAddresses(ctx context.Context, cluster, id string, addresses ...*types.Address) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
@ -85,6 +96,7 @@ func (d *ramDB) AddAddresses(ctx context.Context, cluster string, id string, add
|
||||
return nil
|
||||
}
|
||||
|
||||
// List implements DB.
|
||||
func (d *ramDB) List(ctx context.Context, cluster string) (list []*types.Node, err error) {
|
||||
c, ok := d.db[cluster]
|
||||
if !ok {
|
||||
@ -99,11 +111,15 @@ func (d *ramDB) List(ctx context.Context, cluster string) (list []*types.Node, e
|
||||
}
|
||||
}
|
||||
|
||||
if len(list) == 0 {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Get implements DB
|
||||
func (d *ramDB) Get(ctx context.Context, cluster string, id string) (*types.Node, error) {
|
||||
// Get implements DB.
|
||||
func (d *ramDB) Get(ctx context.Context, cluster, id string) (*types.Node, error) {
|
||||
d.mu.RLock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
@ -114,7 +130,7 @@ func (d *ramDB) Get(ctx context.Context, cluster string, id string) (*types.Node
|
||||
|
||||
n, ok := c[id]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("node %q in cluster %q not found", id, cluster)
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
return n, nil
|
||||
@ -131,7 +147,6 @@ func (d *ramDB) Clean() {
|
||||
var nodeDeleteList []string
|
||||
|
||||
for id, n := range c {
|
||||
|
||||
n.ExpireAddressesOlderThan(AddressExpirationTimeout)
|
||||
|
||||
if len(n.Addresses) < 1 {
|
||||
@ -144,7 +159,7 @@ func (d *ramDB) Clean() {
|
||||
delete(c, id)
|
||||
}
|
||||
|
||||
if len(c) < 0 {
|
||||
if len(c) == 0 {
|
||||
clusterDeleteList = append(clusterDeleteList, clusterID)
|
||||
}
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
@ -7,8 +11,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/talos-systems/wglan-manager/types"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/talos-systems/kubespan-manager/pkg/types"
|
||||
)
|
||||
|
||||
const redisTTL = 12 * time.Minute
|
||||
@ -19,6 +24,7 @@ type redisDB struct {
|
||||
rc *redis.Client
|
||||
}
|
||||
|
||||
// NewRedis creates new redis DB.
|
||||
func NewRedis(addr string, logger *zap.Logger) (DB, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
@ -53,7 +59,7 @@ func (d *redisDB) clusterAddressKey(cluster string, addr *types.Address) string
|
||||
return fmt.Sprintf("cluster:%s:address:%s", cluster, addr.Name)
|
||||
}
|
||||
|
||||
// Add implements db.DB
|
||||
// Add implements db.DB.
|
||||
func (d *redisDB) Add(ctx context.Context, cluster string, n *types.Node) error {
|
||||
tx := d.rc.TxPipeline()
|
||||
|
||||
@ -77,8 +83,8 @@ func (d *redisDB) Add(ctx context.Context, cluster string, n *types.Node) error
|
||||
return err
|
||||
}
|
||||
|
||||
// AddAddresses implements db.DB
|
||||
func (d *redisDB) AddAddresses(ctx context.Context, cluster string, id string, ep ...*types.Address) error {
|
||||
// AddAddresses implements db.DB.
|
||||
func (d *redisDB) AddAddresses(ctx context.Context, cluster, id string, ep ...*types.Address) error {
|
||||
n, err := d.Get(ctx, cluster, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve node %q from cluster %q: %w", id, cluster, err)
|
||||
@ -89,19 +95,19 @@ func (d *redisDB) AddAddresses(ctx context.Context, cluster string, id string, e
|
||||
return d.Add(ctx, cluster, n)
|
||||
}
|
||||
|
||||
// Clean implements db.DB
|
||||
// Clean implements db.DB.
|
||||
func (d *redisDB) Clean() {
|
||||
return // no-op
|
||||
}
|
||||
|
||||
// Get implements db.DB
|
||||
func (d *redisDB) Get(ctx context.Context, cluster string, id string) (*types.Node, error) {
|
||||
// Get implements db.DB.
|
||||
func (d *redisDB) Get(ctx context.Context, cluster, id string) (*types.Node, error) {
|
||||
n := new(types.Node)
|
||||
|
||||
if err := d.rc.Get(ctx, d.clusterNodeKey(cluster, id)).Scan(n); err != nil {
|
||||
if errors.Is(redis.Nil, err) {
|
||||
return nil, err
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to parse node %q of cluster %q: %w", id, cluster, err)
|
||||
}
|
||||
|
||||
@ -119,14 +125,18 @@ func (d *redisDB) Get(ctx context.Context, cluster string, id string) (*types.No
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// List implements db.DB
|
||||
// List implements db.DB.
|
||||
func (d *redisDB) List(ctx context.Context, cluster string) ([]*types.Node, error) {
|
||||
nodeList, err := d.rc.SMembers(ctx, d.clusterNodesKey(cluster)).Result()
|
||||
if err != nil {
|
||||
if errors.Is(redis.Nil, err) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to get members of cluster %q: %w", cluster, err)
|
||||
}
|
||||
|
||||
var ret []*types.Node
|
||||
ret := make([]*types.Node, 0, len(nodeList))
|
||||
|
||||
for _, id := range nodeList {
|
||||
n, err := d.Get(ctx, cluster, id)
|
||||
@ -158,5 +168,9 @@ func (d *redisDB) List(ctx context.Context, cluster string) ([]*types.Node, erro
|
||||
ret = append(ret, n)
|
||||
}
|
||||
|
||||
if len(ret) == 0 {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
@ -1,24 +1,35 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package client implements http client for the manager API.
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/talos-systems/wglan-manager/types"
|
||||
"github.com/talos-systems/kubespan-manager/pkg/types"
|
||||
)
|
||||
|
||||
// Add adds a Node to the Cluster database, updating it if it already exists.
|
||||
func Add(rootURL, clusterID string, n *types.Node) error {
|
||||
|
||||
body := new(bytes.Buffer)
|
||||
|
||||
if err := json.NewEncoder(body).Encode(n); err != nil {
|
||||
return fmt.Errorf("failed to encode Node information: %w", err)
|
||||
}
|
||||
|
||||
resp, err := http.Post(fmt.Sprintf("%s/%s", rootURL, clusterID), "application/json", body); if err != nil {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodPost, fmt.Sprintf("%s/%s", rootURL, clusterID), body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to post Node information: %w", err)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to post Node information: %w", err)
|
||||
}
|
||||
defer resp.Body.Close() //nolint:errcheck
|
||||
@ -31,14 +42,14 @@ func Add(rootURL, clusterID string, n *types.Node) error {
|
||||
}
|
||||
|
||||
// AddAddresses adds a list of addresses to a node.
|
||||
func AddAddresses(rootURL, clusterID string, id string, epList ... *types.Address) error {
|
||||
func AddAddresses(rootURL, clusterID, id string, epList ...*types.Address) error {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
if err := json.NewEncoder(buf).Encode(epList); err != nil {
|
||||
return fmt.Errorf("failed to encode known endpoints: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%s/%s/%s", rootURL, clusterID, id), buf)
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodPut, fmt.Sprintf("%s/%s/%s", rootURL, clusterID, id), buf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to make PUT request: %w", err)
|
||||
}
|
||||
@ -47,23 +58,28 @@ func AddAddresses(rootURL, clusterID string, id string, epList ... *types.Addres
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add endpoints to node %q/%q: %w", clusterID, id, err)
|
||||
}
|
||||
defer resp.Body.Close() //nolint:errcheck
|
||||
|
||||
if resp.StatusCode > 299 {
|
||||
return fmt.Errorf("server rejected new endpoints for node %q/%q: %s", clusterID, id, resp.Status)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// Get returns the Node defined by the given public key, if and only if it exists within the given Cluster ID.
|
||||
func Get(rootURL, clusterID string, publicKey string) (*types.Node, error) {
|
||||
|
||||
resp, err := http.Get(fmt.Sprintf("%s/%s/%s", rootURL, clusterID, publicKey))
|
||||
func Get(rootURL, clusterID, publicKey string) (*types.Node, error) {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, fmt.Sprintf("%s/%s/%s", rootURL, clusterID, publicKey), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to request node %q/%q from server %q: %w", clusterID, publicKey, rootURL, err)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to request node %q/%q from server %q: %w", clusterID, publicKey, rootURL, err)
|
||||
}
|
||||
defer resp.Body.Close() //nolint:errcheck
|
||||
|
||||
node := new(types.Node)
|
||||
if err = json.NewDecoder(resp.Body).Decode(node); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response from server: %w", err)
|
||||
@ -73,9 +89,13 @@ func Get(rootURL, clusterID string, publicKey string) (*types.Node, error) {
|
||||
}
|
||||
|
||||
// List returns the set of Nodes associated with the given Cluster ID.
|
||||
func List(rootURL string, clusterID string) ([]*types.Node,error) {
|
||||
func List(rootURL, clusterID string) ([]*types.Node, error) {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, fmt.Sprintf("%s/%s", rootURL, clusterID), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to request list from server %q: %w", rootURL, err)
|
||||
}
|
||||
|
||||
resp, err := http.Get(fmt.Sprintf("%s/%s", rootURL, clusterID))
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to request list from server %q: %w", rootURL, err)
|
||||
}
|
||||
@ -87,6 +107,4 @@ func List(rootURL string, clusterID string) ([]*types.Node,error) {
|
||||
}
|
||||
|
||||
return list, nil
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package types contains all manager data types.
|
||||
package types
|
||||
|
||||
import (
|
||||
@ -12,17 +17,14 @@ import (
|
||||
|
||||
// Address describes an IP or DNS address with optional Port.
|
||||
type Address struct {
|
||||
// Name is the DNS name of this NodeAddress, if known.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// IP is the IP address of this NodeAddress, if known.
|
||||
IP netaddr.IP `json:"ip,omitempty"`
|
||||
|
||||
// Port is the port number for this NodeAddress, if known.
|
||||
Port uint16 `json:"port,omitempty"`
|
||||
|
||||
// LastReported indicates the time at which this address was last reported.
|
||||
LastReported time.Time `json:"lastReported"`
|
||||
// IP is the IP address of this NodeAddress, if known.
|
||||
IP netaddr.IP `json:"ip,omitempty"`
|
||||
// Name is the DNS name of this NodeAddress, if known.
|
||||
Name string `json:"name,omitempty"`
|
||||
// Port is the port number for this NodeAddress, if known.
|
||||
Port uint16 `json:"port,omitempty"`
|
||||
}
|
||||
|
||||
// EqualHost indicates whether two addresses have the same host portion, ignoring the ports.
|
||||
@ -67,7 +69,7 @@ func (a *Address) Endpoint(defaultPort uint16) (*net.UDPAddr, error) {
|
||||
return net.ResolveUDPAddr(proto, fmt.Sprintf("%s:%d", addr, port))
|
||||
}
|
||||
|
||||
// Node describes a Wireguard Peer
|
||||
// Node describes a Wireguard Peer.
|
||||
type Node struct {
|
||||
// Name is the human-readable identifier of this Node.
|
||||
// Usually, this is the kubernetes Node name.
|
||||
@ -134,19 +136,17 @@ func (n *Node) ExpireAddressesOlderThan(maxAge time.Duration) {
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
a = nil
|
||||
}
|
||||
|
||||
n.Addresses = n.Addresses[:i]
|
||||
}
|
||||
|
||||
// MarshalBinary implements encoding.BinaryMarshaler
|
||||
// MarshalBinary implements encoding.BinaryMarshaler.
|
||||
func (n *Node) MarshalBinary() ([]byte, error) {
|
||||
return json.Marshal(n)
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler
|
||||
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
|
||||
func (n *Node) UnmarshalBinary(data []byte) error {
|
||||
*n = Node{}
|
||||
|
@ -1,11 +1,16 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/talos-systems/wglan-manager/types"
|
||||
"inet.af/netaddr"
|
||||
|
||||
"github.com/talos-systems/kubespan-manager/pkg/types"
|
||||
)
|
||||
|
||||
func TestEncoderDecoder(t *testing.T) {
|
Reference in New Issue
Block a user