From 0c3ae5f9f82b9ef3d3da1ffbf9b78550f390d5bf Mon Sep 17 00:00:00 2001 From: Noel Georgi Date: Thu, 28 Mar 2024 18:57:38 +0530 Subject: [PATCH] chore: enable kres Enable kres and update repo branch settings. Fixes: #14 Signed-off-by: Noel Georgi --- .codecov.yml | 18 +++ .conform.yaml | 33 ++++ .dockerignore | 17 +- .github/renovate.json | 31 ++++ .github/workflows/ci.yaml | 107 +++++++++++++ .github/workflows/ghcr.yaml | 42 ----- .github/workflows/slack-notify.yaml | 92 +++++++++++ .github/workflows/test.yaml | 11 -- .gitignore | 7 +- .kres.yaml | 46 ++++++ .license-header.go.txt | 3 + .markdownlint.json | 9 ++ Dockerfile | 164 ++++++++++++++++--- Makefile | 236 +++++++++++++++++++++++++--- README.md | 57 ++++--- cmd/talos-vmtoolsd/main.go | 2 +- hack/release.sh | 66 ++++++++ hack/release.toml | 11 ++ internal/tboxcmds/vix.go | 2 +- internal/version/data/sha | 1 + internal/version/data/tag | 1 + internal/version/version.go | 42 ++++- 22 files changed, 872 insertions(+), 126 deletions(-) create mode 100644 .codecov.yml create mode 100644 .conform.yaml create mode 100644 .github/renovate.json create mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/ghcr.yaml create mode 100644 .github/workflows/slack-notify.yaml delete mode 100644 .github/workflows/test.yaml create mode 100644 .kres.yaml create mode 100644 .license-header.go.txt create mode 100644 .markdownlint.json create mode 100755 hack/release.sh create mode 100644 hack/release.toml create mode 100644 internal/version/data/sha create mode 100644 internal/version/data/tag diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..6aedb92 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,18 @@ +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-03-28T12:14:24Z by kres 88d1199. + +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 diff --git a/.conform.yaml b/.conform.yaml new file mode 100644 index 0000000..ac3238c --- /dev/null +++ b/.conform.yaml @@ -0,0 +1,33 @@ +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-03-28T13:32:59Z by kres latest. + +policies: + - type: commit + spec: + dco: true + gpg: + required: false + identity: + gitHubOrganization: siderolabs + 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: + - .* diff --git a/.dockerignore b/.dockerignore index 8bbc7b0..d225aed 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,14 @@ -.git -.github -deploy +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-04-01T09:05:42Z by kres latest. + +* +!cmd +!internal +!go.mod +!go.sum +!.golangci.yml +!README.md +!.markdownlint.json +!manifest.yaml +!talos-vmtoolsd.yaml diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..445c57f --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + ":dependencyDashboard", + ":gitSignOff", + ":semanticCommitScopeDisabled", + "schedule:earlyMondays" + ], + "prHeader": "Update Request | Renovate Bot", + "packageRules": [ + { + "matchPackagePatterns": [ + "*" + ], + "matchDatasources": [ + "docker" + ], + "groupName": "container images" + }, + { + "matchPackagePatterns": [ + "*" + ], + "matchDatasources": [ + "go", + "golang-version" + ], + "groupName": "go packages" + } + ] +} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..4b2dcef --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,107 @@ +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-03-28T13:52:01Z by kres latest. + +name: default +concurrency: + group: ${{ github.head_ref || github.run_id }} + cancel-in-progress: true +"on": + push: + branches: + - main + - release-* + tags: + - v* + pull_request: + branches: + - main + - release-* +jobs: + default: + permissions: + actions: read + contents: write + issues: read + packages: write + pull-requests: read + runs-on: + - self-hosted + - generic + if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/')) + services: + buildkitd: + image: moby/buildkit:v0.13.1 + options: --privileged + ports: + - 1234:1234 + volumes: + - /var/lib/buildkit/${{ github.repository }}:/var/lib/buildkit + - /usr/etc/buildkit/buildkitd.toml:/etc/buildkit/buildkitd.toml + steps: + - name: checkout + uses: actions/checkout@v4 + - name: Unshallow + run: | + git fetch --prune --unshallow + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver: remote + endpoint: tcp://127.0.0.1:1234 + timeout-minutes: 10 + - name: base + run: | + make base + - name: unit-tests + run: | + make unit-tests + - name: unit-tests-race + run: | + make unit-tests-race + - name: talos-vmtoolsd + run: | + make talos-vmtoolsd + - name: lint + run: | + make lint + - name: Login to registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io + username: ${{ github.repository_owner }} + - name: image-talos-vmtoolsd + run: | + make image-talos-vmtoolsd + - name: push-talos-vmtoolsd + if: github.event_name != 'pull_request' + env: + PUSH: "true" + run: | + make image-talos-vmtoolsd + - name: push-talos-vmtoolsd-latest + if: github.event_name != 'pull_request' + env: + PUSH: "true" + run: | + make image-talos-vmtoolsd TAG=latest + - name: Generate Checksums + if: startsWith(github.ref, 'refs/tags/') + run: | + sha256sum _out/talos-vmtoolsd-* > _out/sha256sum.txt + sha512sum _out/talos-vmtoolsd-* > _out/sha512sum.txt + - name: release-notes + if: startsWith(github.ref, 'refs/tags/') + run: | + make release-notes + - name: Release + if: startsWith(github.ref, 'refs/tags/') + uses: crazy-max/ghaction-github-release@v2 + with: + body_path: _out/RELEASE_NOTES.md + draft: "true" + files: |- + _out/talos-vmtoolsd-* + _out/sha*.txt diff --git a/.github/workflows/ghcr.yaml b/.github/workflows/ghcr.yaml deleted file mode 100644 index 75067fd..0000000 --- a/.github/workflows/ghcr.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: GitHub Container Registry - -on: - push: - paths-ignore: - - '.github/**' - - '.gitignore' - - 'deploy/**' - - 'docs/**' - - 'LICENSE' - - 'README.md' - -jobs: - ghr_push: - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v4 - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - # publish tags to talos-vmtoolsd:version and talos-vmtoolsd:latest - # publish branches to talos-vmtoolsd-unstable:branch - # requires GitHub actions access to packages to be configured - - name: Publish - run: | - VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') - if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - IMGPATH=ghcr.io/${{ github.repository }} - VERSION=$(echo $VERSION | sed -e 's/^v//') - docker build . -t $IMGPATH:$VERSION -t $IMGPATH:latest - docker push $IMGPATH:$VERSION - docker push $IMGPATH:latest - else - IMGPATH=ghcr.io/${{ github.repository }}-unstable - [ "$VERSION" == "main" ] && VERSION=latest - docker build . -t $IMGPATH:$VERSION - docker push $IMGPATH:$VERSION - fi diff --git a/.github/workflows/slack-notify.yaml b/.github/workflows/slack-notify.yaml new file mode 100644 index 0000000..3809a5c --- /dev/null +++ b/.github/workflows/slack-notify.yaml @@ -0,0 +1,92 @@ +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-03-28T12:14:24Z by kres 88d1199. + +name: slack-notify +"on": + workflow_run: + workflows: + - default + types: + - completed +jobs: + slack-notify: + runs-on: + - self-hosted + - generic + if: github.event.workflow_run.conclusion != 'skipped' + steps: + - name: Get PR number + id: get-pr-number + if: github.event.workflow_run.event == 'pull_request' + env: + GH_TOKEN: ${{ github.token }} + run: | + echo pull_request_number=$(gh pr view -R ${{ github.repository }} ${{ github.event.workflow_run.head_repository.owner.login }}:${{ github.event.workflow_run.head_branch }} --json number --jq .number) >> $GITHUB_OUTPUT + - name: Slack Notify + uses: slackapi/slack-github-action@v1 + with: + channel-id: proj-talos-maintainers + payload: | + { + "attachments": [ + { + "color": "${{ github.event.workflow_run.conclusion == 'success' && '#2EB886' || github.event.workflow_run.conclusion == 'failure' && '#A30002' || '#FFCC00' }}", + "fallback": "test", + "blocks": [ + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "${{ github.event.workflow_run.event == 'pull_request' && format('*Pull Request:* {0} (`{1}`)\n<{2}/pull/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, steps.get-pr-number.outputs.pull_request_number, github.event.workflow_run.display_title) || format('*Build:* {0} (`{1}`)\n<{2}/commit/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, github.sha, github.event.workflow_run.display_title) }}" + }, + { + "type": "mrkdwn", + "text": "*Status:*\n`${{ github.event.workflow_run.conclusion }}`" + } + ] + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Author:*\n`${{ github.actor }}`" + }, + { + "type": "mrkdwn", + "text": "*Event:*\n`${{ github.event.workflow_run.event }}`" + } + ] + }, + { + "type": "divider" + }, + { + "type": "actions", + "elements": [ + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Logs" + }, + "url": "${{ github.event.workflow_run.html_url }}" + }, + { + "type": "button", + "text": { + "type": "plain_text", + "text": "Commit" + }, + "url": "${{ github.event.repository.html_url }}/commit/${{ github.sha }}" + } + ] + } + ] + } + ] + } + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 2e0103f..0000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: Test -on: [pull_request] -jobs: - test_container: - name: Build a container test image - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v4 - - name: Docker - run: docker build . --file Dockerfile --tag talos-vmtoolsd:test diff --git a/.gitignore b/.gitignore index ad02d1d..0a016d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -/talos-vmtoolsd -/.idea +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-03-28T12:14:24Z by kres 88d1199. + +_out diff --git a/.kres.yaml b/.kres.yaml new file mode 100644 index 0000000..436877d --- /dev/null +++ b/.kres.yaml @@ -0,0 +1,46 @@ +--- +kind: common.Repository +spec: + licenses: [] + conformGPGSignatureCheck: false +--- +kind: golang.Generate +spec: + versionPackagePath: internal/version +--- +kind: service.CodeCov +spec: + enabled: false +--- +kind: common.Image +spec: + additionalImages: [] + allowedLocalPaths: + - manifest.yaml + - talos-vmtoolsd.yaml + copyFrom: + - stage: extension + entrypoint: /rootfs/usr/local/lib/containers/talos-vmtoolsd/talos-vmtoolsd +--- +kind: auto.CustomSteps +spec: + steps: + - name: extension + toplevel: true +--- +kind: custom.Step +name: extension +spec: + docker: + enabled: true + stages: + - name: extension + description: copies the required files for the extension + steps: + - copy: + src: manifest.yaml + dst: / + - copy: + src: talos-vmtoolsd.yaml + dst: /rootfs/usr/local/etc/containers/talos-vmtoolsd.yaml +--- diff --git a/.license-header.go.txt b/.license-header.go.txt new file mode 100644 index 0000000..66e0819 --- /dev/null +++ b/.license-header.go.txt @@ -0,0 +1,3 @@ +// 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/. diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..ca94939 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,9 @@ +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-03-28T12:14:24Z by kres 88d1199. + +{ + "MD013": false, + "MD033": false, + "default": true + } diff --git a/Dockerfile b/Dockerfile index 929f21b..e4481c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,144 @@ -#### Build binary -FROM golang:1.22.1-alpine AS builder -WORKDIR /build -COPY . . +# syntax = docker/dockerfile-upstream:1.7.0-labs + +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-04-01T09:12:09Z by kres latest. + +ARG TOOLCHAIN + +# copies the required files for the extension +FROM scratch AS extension +COPY manifest.yaml / +COPY talos-vmtoolsd.yaml /rootfs/usr/local/etc/containers/talos-vmtoolsd.yaml + +# runs markdownlint +FROM docker.io/node:21.7.1-alpine3.19 AS lint-markdown +WORKDIR /src +RUN npm i -g markdownlint-cli@0.39.0 +RUN npm i sentences-per-line@0.2.1 +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 --platform=${BUILDPLATFORM} toolchain AS tools +ENV GO111MODULE on +ARG CGO_ENABLED +ENV CGO_ENABLED ${CGO_ENABLED} +ARG GOTOOLCHAIN +ENV GOTOOLCHAIN ${GOTOOLCHAIN} +ARG GOEXPERIMENT +ENV GOEXPERIMENT ${GOEXPERIMENT} +ENV GOPATH /go +ARG DEEPCOPY_VERSION +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/siderolabs/deep-copy@${DEEPCOPY_VERSION} \ + && mv /go/bin/deep-copy /bin/deep-copy +ARG GOLANGCILINT_VERSION +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCILINT_VERSION} \ + && mv /go/bin/golangci-lint /bin/golangci-lint +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install golang.org/x/vuln/cmd/govulncheck@latest \ + && mv /go/bin/govulncheck /bin/govulncheck +ARG GOIMPORTS_VERSION +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install golang.org/x/tools/cmd/goimports@${GOIMPORTS_VERSION} \ + && mv /go/bin/goimports /bin/goimports +ARG GOFUMPT_VERSION +RUN go install mvdan.cc/gofumpt@${GOFUMPT_VERSION} \ + && mv /go/bin/gofumpt /bin/gofumpt + +# tools and sources +FROM tools AS base +WORKDIR /src +COPY go.mod go.mod +COPY go.sum go.sum +RUN cd . +RUN --mount=type=cache,target=/go/pkg go mod download +RUN --mount=type=cache,target=/go/pkg go mod verify +COPY ./cmd ./cmd +COPY ./internal ./internal +RUN --mount=type=cache,target=/go/pkg go list -mod=readonly all >/dev/null + +FROM tools AS embed-generate +ARG SHA +ARG TAG +WORKDIR /src +RUN mkdir -p internal/version/data && \ + echo -n ${SHA} > internal/version/data/sha && \ + echo -n ${TAG} > internal/version/data/tag + +# runs gofumpt +FROM base AS lint-gofumpt +RUN FILES="$(gofumpt -l .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumpt -w .':\n${FILES}"; exit 1) + +# runs goimports +FROM base AS lint-goimports +RUN FILES="$(goimports -l -local github.com/siderolabs/talos-vmtoolsd/ .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'goimports -w -local github.com/siderolabs/talos-vmtoolsd/ .':\n${FILES}"; exit 1) + +# runs golangci-lint +FROM base AS lint-golangci-lint +WORKDIR /src +COPY .golangci.yml . +ENV GOGC 50 +RUN golangci-lint config verify --config .golangci.yml +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 govulncheck +FROM base AS lint-govulncheck +WORKDIR /src +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg govulncheck ./... + +# runs unit-tests with race detector +FROM base AS unit-tests-race +WORKDIR /src +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 +WORKDIR /src +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 embed-generate AS embed-abbrev-generate +WORKDIR /src +ARG ABBREV_TAG +RUN echo -n 'undefined' > internal/version/data/sha && \ + echo -n ${ABBREV_TAG} > internal/version/data/tag + +FROM scratch AS unit-tests +COPY --from=unit-tests-run /src/coverage.txt /coverage-unit-tests.txt + +# cleaned up specs and compiled versions +FROM scratch AS generate +COPY --from=embed-abbrev-generate /src/internal/version internal/version + +# builds talos-vmtoolsd-linux-amd64 +FROM base AS talos-vmtoolsd-linux-amd64-build +COPY --from=generate / / +COPY --from=embed-generate / / +WORKDIR /src/cmd/talos-vmtoolsd +ARG GO_BUILDFLAGS +ARG GO_LDFLAGS +ARG VERSION_PKG="internal/version" +ARG SHA +ARG TAG +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS} -X ${VERSION_PKG}.Name=talos-vmtoolsd -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG}" -o /talos-vmtoolsd-linux-amd64 + +FROM scratch AS talos-vmtoolsd-linux-amd64 +COPY --from=talos-vmtoolsd-linux-amd64-build /talos-vmtoolsd-linux-amd64 /talos-vmtoolsd-linux-amd64 + +FROM talos-vmtoolsd-linux-${TARGETARCH} AS talos-vmtoolsd + +FROM scratch AS talos-vmtoolsd-all +COPY --from=talos-vmtoolsd-linux-amd64 / / + +FROM scratch AS image-talos-vmtoolsd ARG TARGETARCH -ARG CGO_ENABLED=0 -ARG GOARCH=$TARGETARCH -ARG GOOS=linux -RUN go test -v ./... && \ - go vet ./... && \ - go build -ldflags="-s -w" -trimpath -o talos-vmtoolsd ./cmd/talos-vmtoolsd - -#### Build system extension tree -FROM alpine:3.19 AS stage -RUN mkdir -p /stage/rootfs/usr/local/etc/containers -RUN mkdir -p /stage/rootfs/usr/local/lib/containers/talos-vmtoolsd -COPY --from=builder /build/talos-vmtoolsd /stage/rootfs/usr/local/lib/containers/talos-vmtoolsd/ -COPY ./manifest.yaml /stage/ -COPY ./talos-vmtoolsd.yaml /stage/rootfs/usr/local/etc/containers/ - -#### Build final container -FROM scratch -COPY --from=stage /stage / +COPY --from=talos-vmtoolsd talos-vmtoolsd-linux-${TARGETARCH} /rootfs/usr/local/lib/containers/talos-vmtoolsd/talos-vmtoolsd +COPY --from=extension / / +LABEL org.opencontainers.image.source https://github.com/siderolabs/talos-vmtoolsd ENTRYPOINT ["/rootfs/usr/local/lib/containers/talos-vmtoolsd/talos-vmtoolsd"] + diff --git a/Makefile b/Makefile index f5724d9..5841d1d 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,218 @@ +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-04-01T09:10:24Z by kres latest. + +# common variables + +SHA := $(shell git describe --match=none --always --abbrev=8 --dirty) +TAG := $(shell git describe --tag --always --dirty --match v[0-9]\*) +ABBREV_TAG := $(shell git describe --tags >/dev/null 2>/dev/null && git describe --tag --always --match v[0-9]\* --abbrev=0 || echo 'undefined') +BRANCH := $(shell git rev-parse --abbrev-ref HEAD) +ARTIFACTS := _out +WITH_DEBUG ?= false +WITH_RACE ?= false REGISTRY ?= ghcr.io -USERNAME ?= sidereolabs -SHA ?= $(shell git describe --match=none --always --abbrev=8 --dirty) -TAG ?= $(shell git describe --tag --always --dirty --match v[0-9]\*) -ABBREV_TAG ?= $(shell git describe --tag --always --match v[0-9]\* --abbrev=0 ) -TAG_SUFFIX ?= -SOURCE_DATE_EPOCH ?= $(shell git log -1 --pretty=%ct) -IMAGE_REGISTRY ?= $(REGISTRY) -IMAGE_NAME = talos-vmtoolsd -IMAGE_TAG ?= $(TAG)$(TAG_SUFFIX) -BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) -REGISTRY_AND_USERNAME := $(IMAGE_REGISTRY)/$(USERNAME) - -talos-vmtoolsd: - go build -ldflags="-s -w" -trimpath -o $@ ./cmd/$@ - -docker-build: - docker buildx build . --tag $(REGISTRY_AND_USERNAME)/${IMAGE_NAME}:$(IMAGE_TAG) - -.PHONY: talos-vmtoolsd docker-build +USERNAME ?= siderolabs +REGISTRY_AND_USERNAME ?= $(REGISTRY)/$(USERNAME) +PROTOBUF_GO_VERSION ?= 1.33.0 +GRPC_GO_VERSION ?= 1.3.0 +GRPC_GATEWAY_VERSION ?= 2.19.1 +VTPROTOBUF_VERSION ?= 0.6.0 +DEEPCOPY_VERSION ?= v0.5.6 +GOLANGCILINT_VERSION ?= v1.57.0 +GOFUMPT_VERSION ?= v0.6.0 +GO_VERSION ?= 1.22.1 +GOIMPORTS_VERSION ?= v0.19.0 +GO_BUILDFLAGS ?= +GO_LDFLAGS ?= +CGO_ENABLED ?= 0 +GOTOOLCHAIN ?= local +TESTPKGS ?= ./... +KRES_IMAGE ?= ghcr.io/siderolabs/kres:latest +CONFORMANCE_IMAGE ?= ghcr.io/siderolabs/conform:latest + +# docker build settings + +BUILD := docker buildx build +PLATFORM ?= linux/amd64 +PROGRESS ?= auto +PUSH ?= false +CI_ARGS ?= +COMMON_ARGS = --file=Dockerfile +COMMON_ARGS += --provenance=false +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=ABBREV_TAG="$(ABBREV_TAG)" +COMMON_ARGS += --build-arg=USERNAME="$(USERNAME)" +COMMON_ARGS += --build-arg=REGISTRY="$(REGISTRY)" +COMMON_ARGS += --build-arg=TOOLCHAIN="$(TOOLCHAIN)" +COMMON_ARGS += --build-arg=CGO_ENABLED="$(CGO_ENABLED)" +COMMON_ARGS += --build-arg=GO_BUILDFLAGS="$(GO_BUILDFLAGS)" +COMMON_ARGS += --build-arg=GO_LDFLAGS="$(GO_LDFLAGS)" +COMMON_ARGS += --build-arg=GOTOOLCHAIN="$(GOTOOLCHAIN)" +COMMON_ARGS += --build-arg=GOEXPERIMENT="$(GOEXPERIMENT)" +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=VTPROTOBUF_VERSION="$(VTPROTOBUF_VERSION)" +COMMON_ARGS += --build-arg=DEEPCOPY_VERSION="$(DEEPCOPY_VERSION)" +COMMON_ARGS += --build-arg=GOLANGCILINT_VERSION="$(GOLANGCILINT_VERSION)" +COMMON_ARGS += --build-arg=GOIMPORTS_VERSION="$(GOIMPORTS_VERSION)" +COMMON_ARGS += --build-arg=GOFUMPT_VERSION="$(GOFUMPT_VERSION)" +COMMON_ARGS += --build-arg=TESTPKGS="$(TESTPKGS)" +TOOLCHAIN ?= docker.io/golang:1.22-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 running builds that needs to be cached aggresively create a builder instance with the following: + + docker buildx create --name local --use --config=config.toml + +config.toml contents: + +[worker.oci] + gc = true + gckeepstorage = 50000 + + [[worker.oci.gcpolicy]] + keepBytes = 10737418240 + keepDuration = 604800 + filters = [ "type==source.local", "type==exec.cachemount", "type==source.git.checkout"] + [[worker.oci.gcpolicy]] + all = true + keepBytes = 53687091200 + +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 + +ifneq (, $(filter $(WITH_RACE), t true TRUE y yes 1)) +GO_BUILDFLAGS += -race +CGO_ENABLED := 1 +GO_LDFLAGS += -linkmode=external -extldflags '-static' +endif + +ifneq (, $(filter $(WITH_DEBUG), t true TRUE y yes 1)) +GO_BUILDFLAGS += -tags sidero.debug +else +GO_LDFLAGS += -s +endif + +all: unit-tests talos-vmtoolsd image-talos-vmtoolsd extension 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)" + +generate: ## Generate .proto definitions. + @$(MAKE) local-$@ DEST=./ + +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 GOTOOLCHAIN=local; \ + export GO111MODULE=on; export GOPROXY=https://proxy.golang.org; \ + go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) && \ + gofumpt -w ." + +lint-govulncheck: ## Runs govulncheck linter. + @$(MAKE) target-$@ + +lint-goimports: ## Runs goimports linter. + @$(MAKE) target-$@ + +.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: $(ARTIFACTS)/talos-vmtoolsd-linux-amd64 +$(ARTIFACTS)/talos-vmtoolsd-linux-amd64: + @$(MAKE) local-talos-vmtoolsd-linux-amd64 DEST=$(ARTIFACTS) + +.PHONY: talos-vmtoolsd-linux-amd64 +talos-vmtoolsd-linux-amd64: $(ARTIFACTS)/talos-vmtoolsd-linux-amd64 ## Builds executable for talos-vmtoolsd-linux-amd64. + +.PHONY: talos-vmtoolsd +talos-vmtoolsd: talos-vmtoolsd-linux-amd64 ## Builds executables for talos-vmtoolsd. + +.PHONY: lint-markdown +lint-markdown: ## Runs markdownlint. + @$(MAKE) target-$@ + +.PHONY: lint +lint: lint-golangci-lint lint-gofumpt lint-govulncheck lint-goimports lint-markdown ## Run all linters for the project. + +.PHONY: image-talos-vmtoolsd +image-talos-vmtoolsd: ## Builds image for talos-vmtoolsd. + @$(MAKE) target-$@ TARGET_ARGS="--tag=$(REGISTRY)/$(USERNAME)/talos-vmtoolsd:$(TAG)" + +.PHONY: rekres +rekres: + @docker pull $(KRES_IMAGE) + @docker run --rm --net=host --user $(shell id -u):$(shell id -g) -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) + +.PHONY: conformance +conformance: + @docker pull $(CONFORMANCE_IMAGE) + @docker run --rm -it -v $(PWD):/src -w /src $(CONFORMANCE_IMAGE) enforce + diff --git a/README.md b/README.md index 2520ea2..354b61a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ # talos-vmtoolsd -**A VMware tools implementation for the Talos Kubernetes platform, using govmomi and Talos' apid** +## A VMware tools implementation for the Talos Kubernetes platform, using govmomi and Talos' apid -[Talos](https://talos.dev/) ships as OVA file for VMware platforms, but by design lacks first-party hypervisor integration packages. Restart/stop buttons for Talos nodes will not function and VM details are not available in vCenter. +[Talos](https://talos.dev/) ships as OVA file for VMware platforms, but by design lacks first-party hypervisor integration packages. +Restart/stop buttons for Talos nodes will not function and VM details are not available in vCenter. Deploying this program on your Talos cluster provides native integration of Talos with vSphere/vCenter. -# Installation as a Talos System Extension +## Installation as a Talos System Extension The preferred use is as a [System Extension](https://www.talos.dev/latest/talos-guides/configuration/system-extensions/). Please refer to the Talos documentation on how to build [Boot Assets](https://www.talos.dev/latest/talos-guides/install/boot-assets/#imager) @@ -14,7 +15,7 @@ that include `talos-vmtoolsd`. Basically, for a node upgrade, it boils down to something like this: -``` +```bash # Generate installer image including `talos-vmtoolsd` docker run --rm --tty \ --volume $PWD/_out:/out ghcr.io/siderolabs/imager: \ @@ -29,12 +30,12 @@ talosctl upgrade --nodes \ --image ghcr.io//talos-installer: ``` -# Installation as a DaemonSet +## Installation as a DaemonSet Start by providing authorization credentials to enable talos-vmtoolsd to talk with apid. Admin credentials are required in order to issue reboot/shutdown commands. -``` +```bash # Create new Talos API credentials talosctl --nodes config new vmtoolsd-secret.yaml --roles os:admin @@ -49,20 +50,20 @@ rm vmtoolsd-secret.yaml Install or upgrade `talos-vmtoolsd`: -``` +```bash kubectl apply --filename https://raw.githubusercontent.com/siderolabs/talos-vmtoolsd/master/deploy/latest.yaml ``` -# Talos Compatibility Matrix +## Talos Compatibility Matrix -| ⬇️ Tools \ Talos ➡️ | 0.7 - 0.10 | 0.11 - 0.13 | 0.14 - 1.4 | 1.4 | 1.5 | 1.6+ -| ------------------ | ---------- | ----------- | ---------- | --- | --- | ---- -| **0.5** (current) | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | -| **0.4** | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | -| **0.3** | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | -| **0.2** | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | +| ⬇️ Tools \ Talos ➡️ | 0.7 - 0.10 | 0.11 - 0.13 | 0.14 - 1.4 | 1.4 | 1.5 | 1.6+ | +| ----------------- | ---------- | ----------- | ---------- | --- | --- | ---- | +| **0.5** (current) | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | +| **0.4** | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | +| **0.3** | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | +| **0.2** | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | -# Roadmap +## Roadmap * [x] Feature-complete integration of Talos apid and ESXi (restart/stop, IP, DNS, heartbeats) * [x] Continuous Integration & Deployment via GitHub Actions @@ -70,22 +71,34 @@ kubectl apply --filename https://raw.githubusercontent.com/siderolabs/talos-vmto * [ ] Warn about unsafe VM config (Talos config accessible to all pods) * [ ] Unit testing beyond govmomi-provided tests -# Why not open-vm-tools? +## Why not open-vm-tools? The standard open-vm-tools package in a container has multiple shortcomings under Talos: 1. It wants a shutdown binary, but there is none that works properly with Talos. 2. Its out-of-band process and file management goes against Talos' immutability principle. -3. Exposing virtual network adapters to vSphere can cause issues like described in the [VMware CPI documentation](https://cloud-provider-vsphere.sigs.k8s.io/known_issues.html). No workarounds are necessary for talos-vmtoolsd. +3. Exposing virtual network adapters to vSphere can cause issues like described in the [VMware CPI documentation](https:// + cloud-provider-vsphere.sigs.k8s.io/known_issues.html). + No workarounds are necessary for talos-vmtoolsd. -The standard open-vm-tools package expects to run on the host and have some program (e.g. `/usr/bin/shutdown`) to handle shutdown requests. Running open-vm-tools in a privileged container may work, but it provides mediocre results with Talos. For example, I have observed shutdown commands from containers to bypass apid and be either ignored or lead to unclean termination of pods. +The standard open-vm-tools package expects to run on the host and have some program (e.g. `/usr/bin/shutdown`) to handle shutdown requests. +Running open-vm-tools in a privileged container may work, but it provides mediocre results with Talos. +For example, I have observed shutdown commands from containers to bypass apid and be either ignored or lead to unclean termination of pods. -Talos' apid may be used to talk to local services by omitting a node context. This feature is not supported by talosctl. Incidentally, VMware provides a guest tools implementation in Go as part of the govmomi project. Combining both, talos-vmtoolsd was born: A single lightweight process that can talk to both ESXi and Talos' apid. It simply translates between both interfaces and thereby seamlessly integrates them. +Talos' apid may be used to talk to local services by omitting a node context. +This feature is not supported by talosctl. +Incidentally, VMware provides a guest tools implementation in Go as part of the govmomi project. +Combining both, talos-vmtoolsd was born: A single lightweight process that can talk to both ESXi and Talos' apid. +It simply translates between both interfaces and thereby seamlessly integrates them. -# Attribution +## Attribution -Talos-vmtoolsd is based on VMware's custom VIC toolbox of the govmomi project. I have reduced the toolbox's functionality to the bare minimum required by vSphere. Its main service has been refactored for plugin support. A basic plugin is provided serve requests from vSphere using Talos' apid. Code to access apid is imported from Talos' official toolchain and shared by e.g. talosctl. +Talos-vmtoolsd is based on VMware's custom VIC toolbox of the govmomi project. +I have reduced the toolbox's functionality to the bare minimum required by vSphere. +Its main service has been refactored for plugin support. +A basic plugin is provided serve requests from vSphere using Talos' apid. +Code to access apid is imported from Talos' official toolchain and shared by e.g. talosctl. -# License +## License This program is licensed under the Apache 2.0 license like its dependency govmomi. diff --git a/cmd/talos-vmtoolsd/main.go b/cmd/talos-vmtoolsd/main.go index e0c7485..24394f5 100644 --- a/cmd/talos-vmtoolsd/main.go +++ b/cmd/talos-vmtoolsd/main.go @@ -50,7 +50,7 @@ func main() { l.Infof("talos-vmtoolsd version %v\n"+ "Copyright 2020-2022 Oliver Kuckertz \n"+ "This program is free software and available under the Apache 2.0 license.", - version.Version) + version.Tag) // Simplify deployment to mixed vSphere and non-vSphere clusters by detecting ESXi and stopping // early for other platforms. Admins can avoid the overhead of this idle process by labeling diff --git a/hack/release.sh b/hack/release.sh new file mode 100755 index 0000000..92f0848 --- /dev/null +++ b/hack/release.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT. +# +# Generated on 2024-03-28T12:14:24Z by kres 88d1199. + +set -e + +RELEASE_TOOL_IMAGE="ghcr.io/siderolabs/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 " + 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 " + 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 <