From eb3f6e512a0eb5e607ae95b599025ad2239a7223 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Jun 2024 14:55:08 +0000 Subject: [PATCH 1/7] chore(deps): update grouped non-major updates (#236) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---|---|---| | [actions/checkout](https://togithub.com/actions/checkout) | action | patch | `v4.1.6` -> `v4.1.7` | [![age](https://developer.mend.io/api/mc/badges/age/github-tags/actions%2fcheckout/v4.1.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/github-tags/actions%2fcheckout/v4.1.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/github-tags/actions%2fcheckout/v4.1.6/v4.1.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/actions%2fcheckout/v4.1.6/v4.1.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [docker/build-push-action](https://togithub.com/docker/build-push-action) | action | minor | `v5.3.0` -> `v5.4.0` | [![age](https://developer.mend.io/api/mc/badges/age/github-tags/docker%2fbuild-push-action/v5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/github-tags/docker%2fbuild-push-action/v5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/github-tags/docker%2fbuild-push-action/v5.3.0/v5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/docker%2fbuild-push-action/v5.3.0/v5.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [golangci/golangci-lint](https://togithub.com/golangci/golangci-lint) | | patch | `v1.59.0` -> `v1.59.1` | [![age](https://developer.mend.io/api/mc/badges/age/github-tags/golangci%2fgolangci-lint/v1.59.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/github-tags/golangci%2fgolangci-lint/v1.59.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/github-tags/golangci%2fgolangci-lint/v1.59.0/v1.59.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/golangci%2fgolangci-lint/v1.59.0/v1.59.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [helm/helm](https://togithub.com/helm/helm) | | patch | `v3.15.1` -> `v3.15.2` | [![age](https://developer.mend.io/api/mc/badges/age/github-tags/helm%2fhelm/v3.15.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/github-tags/helm%2fhelm/v3.15.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/github-tags/helm%2fhelm/v3.15.1/v3.15.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/helm%2fhelm/v3.15.1/v3.15.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [k8s.io/api](https://togithub.com/kubernetes/api) | require | patch | `v0.30.1` -> `v0.30.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/k8s.io%2fapi/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/k8s.io%2fapi/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/k8s.io%2fapi/v0.30.1/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/k8s.io%2fapi/v0.30.1/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [k8s.io/apimachinery](https://togithub.com/kubernetes/apimachinery) | require | patch | `v0.30.1` -> `v0.30.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/k8s.io%2fapimachinery/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/k8s.io%2fapimachinery/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/k8s.io%2fapimachinery/v0.30.1/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/k8s.io%2fapimachinery/v0.30.1/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [k8s.io/client-go](https://togithub.com/kubernetes/client-go) | require | patch | `v0.30.1` -> `v0.30.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/k8s.io%2fclient-go/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/k8s.io%2fclient-go/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/k8s.io%2fclient-go/v0.30.1/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/k8s.io%2fclient-go/v0.30.1/v0.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [kubernetes/kubernetes](https://togithub.com/kubernetes/kubernetes) | | patch | `v1.30.0` -> `v1.30.2` | [![age](https://developer.mend.io/api/mc/badges/age/github-tags/kubernetes%2fkubernetes/v1.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/github-tags/kubernetes%2fkubernetes/v1.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/github-tags/kubernetes%2fkubernetes/v1.30.0/v1.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/kubernetes%2fkubernetes/v1.30.0/v1.30.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [losisin/helm-values-schema-json](https://togithub.com/losisin/helm-values-schema-json) | | patch | `v1.4.0` -> `v1.4.1` | [![age](https://developer.mend.io/api/mc/badges/age/github-tags/losisin%2fhelm-values-schema-json/v1.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/github-tags/losisin%2fhelm-values-schema-json/v1.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/github-tags/losisin%2fhelm-values-schema-json/v1.4.0/v1.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/github-tags/losisin%2fhelm-values-schema-json/v1.4.0/v1.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
actions/checkout (actions/checkout) ### [`v4.1.7`](https://togithub.com/actions/checkout/blob/HEAD/CHANGELOG.md#v417) [Compare Source](https://togithub.com/actions/checkout/compare/v4.1.6...v4.1.7) - Bump the minor-npm-dependencies group across 1 directory with 4 updates by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/actions/checkout/pull/1739](https://togithub.com/actions/checkout/pull/1739) - Bump actions/checkout from 3 to 4 by [@​dependabot](https://togithub.com/dependabot) in [https://github.com/actions/checkout/pull/1697](https://togithub.com/actions/checkout/pull/1697) - Check out other refs/\* by commit by [@​orhantoy](https://togithub.com/orhantoy) in [https://github.com/actions/checkout/pull/1774](https://togithub.com/actions/checkout/pull/1774) - Pin actions/checkout's own workflows to a known, good, stable version. by [@​jww3](https://togithub.com/jww3) in [https://github.com/actions/checkout/pull/1776](https://togithub.com/actions/checkout/pull/1776)
docker/build-push-action (docker/build-push-action) ### [`v5.4.0`](https://togithub.com/docker/build-push-action/compare/v5.3.0...v5.4.0) [Compare Source](https://togithub.com/docker/build-push-action/compare/v5.3.0...v5.4.0)
golangci/golangci-lint (golangci/golangci-lint) ### [`v1.59.1`](https://togithub.com/golangci/golangci-lint/releases/tag/v1.59.1) [Compare Source](https://togithub.com/golangci/golangci-lint/compare/v1.59.0...v1.59.1) `golangci-lint` is a free and open-source project built by volunteers. If you value it, consider supporting us, the [maintainers](https://opencollective.com/golangci-lint) and [linter authors](https://golangci-lint.run/product/thanks/). We appreciate it! :heart: For key updates, see the [changelog](https://golangci-lint.run/product/changelog/#​1591). #### Changelog - [`f738736`](https://togithub.com/golangci/golangci-lint/commit/f7387361) build(deps): bump github.com/Antonboom/testifylint from 1.3.0 to 1.3.1 ([#​4759](https://togithub.com/golangci/golangci-lint/issues/4759)) - [`44b3cdd`](https://togithub.com/golangci/golangci-lint/commit/44b3cdd1) build(deps): bump github.com/go-viper/mapstructure/v2 from 2.0.0-alpha.1 to 2.0.0 ([#​4788](https://togithub.com/golangci/golangci-lint/issues/4788)) - [`1a55854`](https://togithub.com/golangci/golangci-lint/commit/1a55854a) build(deps): bump github.com/golangci/misspell from 0.5.1 to 0.6.0 ([#​4804](https://togithub.com/golangci/golangci-lint/issues/4804)) - [`9a7a1ad`](https://togithub.com/golangci/golangci-lint/commit/9a7a1ad4) build(deps): bump github.com/polyfloyd/go-errorlint from 1.5.1 to 1.5.2 ([#​4785](https://togithub.com/golangci/golangci-lint/issues/4785)) - [`aaff918`](https://togithub.com/golangci/golangci-lint/commit/aaff9184) build(deps): bump github.com/sashamelentyev/usestdlibvars from 1.25.0 to 1.26.0 ([#​4801](https://togithub.com/golangci/golangci-lint/issues/4801)) - [`a0d2c83`](https://togithub.com/golangci/golangci-lint/commit/a0d2c830) build(deps): bump github.com/shirou/gopsutil/v3 from 3.24.4 to 3.24.5 ([#​4782](https://togithub.com/golangci/golangci-lint/issues/4782)) - [`2042b1f`](https://togithub.com/golangci/golangci-lint/commit/2042b1f1) build(deps): bump go-simpler.org/sloglint from 0.7.0 to 0.7.1 ([#​4784](https://togithub.com/golangci/golangci-lint/issues/4784)) - [`327a78a`](https://togithub.com/golangci/golangci-lint/commit/327a78a8) build(deps): bump golang.org/x/tools from 0.21.0 to 0.22.0 ([#​4802](https://togithub.com/golangci/golangci-lint/issues/4802)) - [`e1a8055`](https://togithub.com/golangci/golangci-lint/commit/e1a80557) fix: SARIF format require issue column >= 1 ([#​4775](https://togithub.com/golangci/golangci-lint/issues/4775)) - [`88f60c8`](https://togithub.com/golangci/golangci-lint/commit/88f60c8c) fix: gomnd deprecated configuration compatibility ([#​4768](https://togithub.com/golangci/golangci-lint/issues/4768)) - [`8173166`](https://togithub.com/golangci/golangci-lint/commit/81731668) fix: init empty result slice for SARIF printer ([#​4758](https://togithub.com/golangci/golangci-lint/issues/4758)) - [`02740ea`](https://togithub.com/golangci/golangci-lint/commit/02740ea1) intrange: add style preset ([#​4797](https://togithub.com/golangci/golangci-lint/issues/4797)) - [`615b873`](https://togithub.com/golangci/golangci-lint/commit/615b873d) unparam: bump to HEAD ([#​4786](https://togithub.com/golangci/golangci-lint/issues/4786))
helm/helm (helm/helm) ### [`v3.15.2`](https://togithub.com/helm/helm/releases/tag/v3.15.2): Helm v3.15.2 [Compare Source](https://togithub.com/helm/helm/compare/v3.15.1...v3.15.2) Helm v3.15.2 is a security (patch) release. Users are strongly recommended to update to this release. The community keeps growing, and we'd love to see you there! - Join the discussion in [Kubernetes Slack](https://kubernetes.slack.com): - for questions and just to hang out - for discussing PRs, code, and bugs - Hang out at the Public Developer Call: Thursday, 9:30 Pacific via [Zoom](https://zoom.us/j/696660622) - Test, debug, and contribute charts: [ArtifactHub/packages](https://artifacthub.io/packages/search?kind=0) #### Installation and Upgrading Download Helm v3.15.2. The common platform binaries are here: - [MacOS amd64](https://get.helm.sh/helm-v3.15.2-darwin-amd64.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-darwin-amd64.tar.gz.sha256sum) / e99a9266a5328cb575d81ef10247911f42d9e90c76ef6eef154c5c535565658b) - [MacOS arm64](https://get.helm.sh/helm-v3.15.2-darwin-arm64.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-darwin-arm64.tar.gz.sha256sum) / 30143dabc1da9d32c7d6c589fad04b1f1ecc73841393d5823fa21c5d7f5bf8f6) - [Linux amd64](https://get.helm.sh/helm-v3.15.2-linux-amd64.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-linux-amd64.tar.gz.sha256sum) / 2694b91c3e501cff57caf650e639604a274645f61af2ea4d601677b746b44fe2) - [Linux arm](https://get.helm.sh/helm-v3.15.2-linux-arm.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-linux-arm.tar.gz.sha256sum) / 2b28fda1d8c6f087011bc7ec820051a13409dadce8385529f306476632e24e85) - [Linux arm64](https://get.helm.sh/helm-v3.15.2-linux-arm64.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-linux-arm64.tar.gz.sha256sum) / adcf07b08484b52508e5cbc8b5f4b0b0db50342f7bc487ecd88b8948b680e6a7) - [Linux i386](https://get.helm.sh/helm-v3.15.2-linux-386.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-linux-386.tar.gz.sha256sum) / 8e0bb5a08c7c227a8e285026b6283726ddc0e1f406e2af4d4d600fa1dd85c21e) - [Linux ppc64le](https://get.helm.sh/helm-v3.15.2-linux-ppc64le.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-linux-ppc64le.tar.gz.sha256sum) / 9d95528fb797f6429f7f9b6dee0cf87bf8c71f6470e1db4a51e844c169c285a3) - [Linux s390x](https://get.helm.sh/helm-v3.15.2-linux-s390x.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-linux-s390x.tar.gz.sha256sum) / 5b42bc3d08fd0ffaf4f9ed810f28464f52ec4ea431b809c7179071d76f3d6f16) - [Linux riscv64](https://get.helm.sh/helm-v3.15.2-linux-riscv64.tar.gz) ([checksum](https://get.helm.sh/helm-v3.15.2-linux-riscv64.tar.gz.sha256sum) / 2998bae9971a55f862c21bff337c325cb6a44f28ef76e11bffc93d16989e11e6) - [Windows amd64](https://get.helm.sh/helm-v3.15.2-windows-amd64.zip) ([checksum](https://get.helm.sh/helm-v3.15.2-windows-amd64.zip.sha256sum) / cbf40b79fa2a7dbd6e24201f8660b56261d10d6e7b5cadc3ff78100fb45b3c69) This release was signed with ` 672C 657B E06B 4B30 969C 4A57 4614 49C2 5E36 B98E ` and can be found at [@​mattfarina](https://togithub.com/mattfarina) [keybase account](https://keybase.io/mattfarina). Please use the attached signatures for verifying this release using `gpg`. The [Quickstart Guide](https://helm.sh/docs/intro/quickstart/) will get you going from there. For **upgrade instructions** or detailed installation notes, check the [install guide](https://helm.sh/docs/intro/install/). You can also use a [script to install](https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3) on any system with `bash`. #### What's Next - 3.15.3 will contain only bug fixes and be released on July 10, 2024. - 3.16.0 is the next feature release and will be on September 11, 2024. #### Changelog - fix: wrong cli description [`1a500d5`](https://togithub.com/helm/helm/commit/1a500d5625419a524fdae4b33de351cc4f58ec35) (yyzxw) - fix typo in load_plugins.go [`70b225c`](https://togithub.com/helm/helm/commit/70b225c9abc014cfeb73f7c9f506b0e73e912b61) (yxxhero) - fix docs of DeployedAll [`b3640f1`](https://togithub.com/helm/helm/commit/b3640f196a2cf77136ab01295bffe76fa184991d) (Daniel Strobusch) - Bump github.com/docker/docker [`46e2ba0`](https://togithub.com/helm/helm/commit/46e2ba0341d43e19493b2f90c86126da8ad8a64e) (dependabot\[bot]) - bump oras minor version [`fb311d3`](https://togithub.com/helm/helm/commit/fb311d331f66f7f9153b5d0c7aa07a77bc9528ca) (Austin Abro) - feat(load.go): add warning on requirements.lock [`23552a7`](https://togithub.com/helm/helm/commit/23552a7de6f45aacec47bc2bfe70de02b9d7ab70) (Aaron U'Ren)
kubernetes/api (k8s.io/api) ### [`v0.30.2`](https://togithub.com/kubernetes/api/compare/v0.30.1...v0.30.2) [Compare Source](https://togithub.com/kubernetes/api/compare/v0.30.1...v0.30.2)
kubernetes/apimachinery (k8s.io/apimachinery) ### [`v0.30.2`](https://togithub.com/kubernetes/apimachinery/compare/v0.30.1...v0.30.2) [Compare Source](https://togithub.com/kubernetes/apimachinery/compare/v0.30.1...v0.30.2)
kubernetes/client-go (k8s.io/client-go) ### [`v0.30.2`](https://togithub.com/kubernetes/client-go/compare/v0.30.1...v0.30.2) [Compare Source](https://togithub.com/kubernetes/client-go/compare/v0.30.1...v0.30.2)
kubernetes/kubernetes (kubernetes/kubernetes) ### [`v1.30.2`](https://togithub.com/kubernetes/kubernetes/releases/tag/v1.30.2): Kubernetes v1.30.2 [Compare Source](https://togithub.com/kubernetes/kubernetes/compare/v1.30.1...v1.30.2) See [kubernetes-announce@](https://groups.google.com/forum/#!forum/kubernetes-announce). Additional binary downloads are linked in the [CHANGELOG](https://togithub.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md). See [the CHANGELOG](https://togithub.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md) for more details. ### [`v1.30.1`](https://togithub.com/kubernetes/kubernetes/releases/tag/v1.30.1): Kubernetes v1.30.1 [Compare Source](https://togithub.com/kubernetes/kubernetes/compare/v1.30.0...v1.30.1) See [kubernetes-announce@](https://groups.google.com/forum/#!forum/kubernetes-announce). Additional binary downloads are linked in the [CHANGELOG](https://togithub.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md). See [the CHANGELOG](https://togithub.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md) for more details.
losisin/helm-values-schema-json (losisin/helm-values-schema-json) ### [`v1.4.1`](https://togithub.com/losisin/helm-values-schema-json/releases/tag/v1.4.1) [Compare Source](https://togithub.com/losisin/helm-values-schema-json/compare/v1.4.0...v1.4.1) #### Changelog ##### Other - [`4106fe3`](https://togithub.com/losisin/helm-values-schema-json/commit/4106fe3) Add documentation and another test case - [`c08b884`](https://togithub.com/losisin/helm-values-schema-json/commit/c08b884) Add: option to apply enum on array items - [`ad5fbbd`](https://togithub.com/losisin/helm-values-schema-json/commit/ad5fbbd) bump version to 1.4.1
--- ### Configuration 📅 **Schedule**: Branch creation - "* * * * 6" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/aenix-io/etcd-operator). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Hidden Marten --- .github/workflows/docker-publish.yaml | 4 ++-- .github/workflows/helm-publish.yaml | 2 +- .github/workflows/hugo.yaml | 2 +- .github/workflows/make-test-e2e.yaml | 2 +- .github/workflows/make-test.yaml | 2 +- .github/workflows/nilaway-lint.yaml | 2 +- .github/workflows/pre-commit.yaml | 2 +- .github/workflows/release-assets.yaml | 2 +- Makefile | 6 +++--- go.mod | 6 +++--- go.sum | 12 ++++++------ 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/docker-publish.yaml b/.github/workflows/docker-publish.yaml index 0b6f370f..7064cbba 100644 --- a/.github/workflows/docker-publish.yaml +++ b/.github/workflows/docker-publish.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 # Install the cosign tool except on PR # https://github.com/sigstore/cosign-installer @@ -67,7 +67,7 @@ jobs: # https://github.com/docker/build-push-action - name: Build and push Docker image id: build-and-push - uses: docker/build-push-action@v5.3.0 + uses: docker/build-push-action@v5.4.0 with: context: . push: ${{ github.event_name != 'pull_request' }} diff --git a/.github/workflows/helm-publish.yaml b/.github/workflows/helm-publish.yaml index 98d7cf28..42168f94 100644 --- a/.github/workflows/helm-publish.yaml +++ b/.github/workflows/helm-publish.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Install Helm uses: azure/setup-helm@v4.2.0 diff --git a/.github/workflows/hugo.yaml b/.github/workflows/hugo.yaml index 6fe53973..e7081f4d 100644 --- a/.github/workflows/hugo.yaml +++ b/.github/workflows/hugo.yaml @@ -41,7 +41,7 @@ jobs: - name: Install Dart Sass run: sudo snap install dart-sass - name: Checkout - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 with: submodules: recursive fetch-depth: 0 diff --git a/.github/workflows/make-test-e2e.yaml b/.github/workflows/make-test-e2e.yaml index ccac6da4..31448122 100644 --- a/.github/workflows/make-test-e2e.yaml +++ b/.github/workflows/make-test-e2e.yaml @@ -23,7 +23,7 @@ jobs: attribute: latest runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: actions/setup-go@v5.0.1 with: go-version: 1.22.4 diff --git a/.github/workflows/make-test.yaml b/.github/workflows/make-test.yaml index 8d58d1bd..2942f6c8 100644 --- a/.github/workflows/make-test.yaml +++ b/.github/workflows/make-test.yaml @@ -23,7 +23,7 @@ jobs: attribute: latest runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: actions/setup-go@v5.0.1 with: go-version: 1.22.4 diff --git a/.github/workflows/nilaway-lint.yaml b/.github/workflows/nilaway-lint.yaml index 3da57c48..5600b56a 100644 --- a/.github/workflows/nilaway-lint.yaml +++ b/.github/workflows/nilaway-lint.yaml @@ -7,7 +7,7 @@ jobs: nilaway-lint: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: actions/setup-go@v5.0.1 with: go-version: 1.22.4 diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index d5479a01..ca967c13 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -7,7 +7,7 @@ jobs: pre-commit: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: actions/setup-go@v5.0.1 with: go-version: 1.22.4 diff --git a/.github/workflows/release-assets.yaml b/.github/workflows/release-assets.yaml index 8d58970d..589380d5 100644 --- a/.github/workflows/release-assets.yaml +++ b/.github/workflows/release-assets.yaml @@ -14,7 +14,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: actions/setup-go@v5.0.1 with: go-version: 1.22.4 diff --git a/Makefile b/Makefile index 722b17f4..b2e24953 100644 --- a/Makefile +++ b/Makefile @@ -254,13 +254,13 @@ KUSTOMIZE_VERSION ?= v5.3.0 CONTROLLER_TOOLS_VERSION ?= v0.15.0 ENVTEST_VERSION ?= latest # renovate: datasource=github-tags depName=golangci/golangci-lint -GOLANGCI_LINT_VERSION ?= v1.59.0 +GOLANGCI_LINT_VERSION ?= v1.59.1 # renovate: datasource=github-tags depName=kubernetes-sigs/kind KIND_VERSION ?= v0.23.0 # renovate: datasource=github-tags depName=helm/helm -HELM_VERSION ?= v3.15.1 +HELM_VERSION ?= v3.15.2 # renovate: datasource=github-tags depName=losisin/helm-values-schema-json -HELM_SCHEMA_VERSION ?= v1.4.0 +HELM_SCHEMA_VERSION ?= v1.4.1 # renovate: datasource=github-tags depName=norwoodj/helm-docs HELM_DOCS_VERSION ?= v1.13.1 # renovate: datasource=github-tags depName=mikefarah/yq diff --git a/go.mod b/go.mod index c4454997..ae9ce48c 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,9 @@ require ( go.etcd.io/etcd/client/v3 v3.5.14 go.uber.org/zap v1.27.0 go.uber.org/zap/exp v0.2.0 - k8s.io/api v0.30.1 - k8s.io/apimachinery v0.30.1 - k8s.io/client-go v0.30.1 + k8s.io/api v0.30.2 + k8s.io/apimachinery v0.30.2 + k8s.io/client-go v0.30.2 k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 sigs.k8s.io/controller-runtime v0.18.4 ) diff --git a/go.sum b/go.sum index ed763278..a0c4a088 100644 --- a/go.sum +++ b/go.sum @@ -234,14 +234,14 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY= -k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM= +k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= +k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI= k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws= k8s.io/apiextensions-apiserver v0.30.1/go.mod h1:R4GuSrlhgq43oRY9sF2IToFh7PVlF1JjfWdoG3pixk4= -k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U= -k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q= -k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= +k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= +k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50= +k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= From df56b4d5f78ec381a5b671376c88802f8d033f36 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Tue, 18 Jun 2024 10:27:06 +0200 Subject: [PATCH 2/7] Add kubectl-etcd plugin (#220) fixes https://github.com/aenix-io/etcd-operator/issues/212 ``` Manage etcd pods spawned by etcd-operator Usage: kubectl-etcd [command] Available Commands: alarm Manage etcd alarms completion Generate the autocompletion script for the specified shell defrag Defragment etcd database on the node forfeit-leadership Tell node to forfeit etcd cluster leadership help Help about any command leave Tell node to leave etcd cluster members Get the list of etcd cluster members remove-member Remove a node from the etcd cluster snapshot Stream snapshot of the etcd node to the path. status Get the status of etcd cluster member Flags: -h, --help help for kubectl-etcd -k, --kubeconfig string Path to the kubeconfig file (default "/Users/kvaps/git/clients/fin-dev/infra/clusters/dev2/kubeconfig") -n, --namespace string Namespace of the etcd pod (default is the current namespace from kubeconfig) -p, --pod string Name of the etcd pod Use "kubectl-etcd [command] --help" for more information about a command. ``` Signed-off-by: Andrei Kvapil --- Dockerfile | 2 +- Makefile | 5 +- cmd/kubectl-etcd/main.go | 702 ++++++++++++++++++++++++++++++++++++++ cmd/{ => manager}/main.go | 0 go.mod | 6 + go.sum | 17 + 6 files changed, 730 insertions(+), 2 deletions(-) create mode 100644 cmd/kubectl-etcd/main.go rename cmd/{ => manager}/main.go (100%) diff --git a/Dockerfile b/Dockerfile index f3175bcf..ab23db9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ COPY internal/ ./internal/ # was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO # the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, # by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. -RUN CGO_ENABLED=0 GOOS="${TARGETOS:-linux}" GOARCH="${TARGETARCH}" go build -a -o manager cmd/main.go +RUN CGO_ENABLED=0 GOOS="${TARGETOS:-linux}" GOARCH="${TARGETARCH}" go build -a -o manager cmd/manager/main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details diff --git a/Makefile b/Makefile index b2e24953..b324f38c 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,10 @@ helm-crd-copy: yq kustomize ## Copy CRDs from kustomize to helm-chart .PHONY: build build: manifests generate fmt vet ## Build manager binary. - go build -o bin/manager cmd/main.go + go build -o bin/manager cmd/manager/main.go + +build-plugin: + go build -o bin/kubectl-etcd cmd/kubectl-etcd/main.go .PHONY: run run: manifests generate fmt vet ## Run a controller from your host. diff --git a/cmd/kubectl-etcd/main.go b/cmd/kubectl-etcd/main.go new file mode 100644 index 00000000..05be2e06 --- /dev/null +++ b/cmd/kubectl-etcd/main.go @@ -0,0 +1,702 @@ +package main + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "io" + "net/http" + "net/url" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/dustin/go-humanize" + "github.com/spf13/cobra" + clientv3 "go.etcd.io/etcd/client/v3" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/portforward" + "k8s.io/client-go/transport/spdy" + "k8s.io/client-go/util/homedir" +) + +func main() { + var rootCmd = &cobra.Command{ + Use: "kubectl-etcd", + Short: "Kubectl etcd plugin", + Long: `Manage etcd pods spawned by etcd-operator`, + } + + // Initialize configuration + config := initializeConfig(rootCmd) + + // Register subcommands + rootCmd.AddCommand( + createStatusCmd(config), + createDefragCmd(config), + createCompactCmd(config), + createAlarmCmd(config), + createForfeitLeadershipCmd(config), + createLeaveCmd(config), + createMembersCmd(config), + createRemoveMemberCmd(config), + createAddMemberCmd(config), + createSnapshotCmd(config), + ) + + // Execute the root command + if err := rootCmd.Execute(); err != nil { + fmt.Println("Error:", err) + os.Exit(1) + } +} + +func createStatusCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "status", + Short: "Get the status of etcd cluster member", + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println(err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + status, err := etcdClient.Status(ctx, etcdClient.Endpoints()[0]) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to get etcd status: %v\n", err) + return + } + + fmt.Printf("%-17s %-9s %-15s %-18s %-11s %-20s %-8s %-s\n", + "MEMBER", "DB SIZE", "IN USE", "LEADER", "RAFT INDEX", "RAFT APPLIED INDEX", "LEARNER", "ERRORS") + inUse := fmt.Sprintf("%.2f%%", float64(status.DbSizeInUse)/float64(status.DbSize)*100) + fmt.Printf("%-17x %-9s %-15s %-18x %-11d %-20d %-8v\n", + status.Header.MemberId, humanize.Bytes(uint64(status.DbSize)), + fmt.Sprintf("%s (%s)", humanize.Bytes(uint64(status.DbSizeInUse)), inUse), + status.Leader, status.RaftIndex, status.RaftAppliedIndex, status.IsLearner) + }, + } +} + +func createDefragCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "defrag", + Short: "Defragment etcd database on the node", + Long: `Defragmentation is a maintenance operation that compacts the historical +records and optimizes the database storage.`, + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println(err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + + _, err = etcdClient.Defragment(ctx, etcdClient.Endpoints()[0]) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to defragment etcd database: %v\n", err) + return + } + }, + } +} + +func createCompactCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "compact", + Short: "Compact the etcd database", + Long: `Compacts the etcd database up to the latest revision to free up space. +This removes old versions of keys and their associated data.`, + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Fetch the latest revision + statusResp, err := etcdClient.Status(ctx, etcdClient.Endpoints()[0]) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to get etcd status: %v\n", err) + return + } + + // Compact the etcd database up to the latest revision + _, err = etcdClient.Compact(ctx, statusResp.Header.Revision) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to compact etcd database: %v\n", err) + return + } + }, + } +} + +func createAlarmCmd(config *Config) *cobra.Command { + alarmCmd := &cobra.Command{ + Use: "alarm", + Short: "Manage etcd alarms", + Long: `Manage the alarms of an etcd cluster.`, + } + + alarmCmd.AddCommand( + createAlarmsListCmd(config), + createAlarmsDisarmCmd(config), + ) + + return alarmCmd +} + +func createAlarmsListCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "list", + Short: "List the etcd alarms for the node", + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Call to etcd client to list alarms + resp, err := etcdClient.AlarmList(ctx) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to list etcd alarms: %v\n", err) + return + } + + for _, alarm := range resp.Alarms { + fmt.Printf("Alarm: %v, MemberID: %x\n", alarm.Alarm, alarm.MemberID) + } + }, + } +} + +func createAlarmsDisarmCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "disarm", + Short: "Disarm the etcd alarms for the node", + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Call to etcd client to disarm alarms + _, err = etcdClient.AlarmDisarm(ctx, &clientv3.AlarmMember{}) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to disarm etcd alarms: %v\n", err) + return + } + }, + } +} + +// setupEtcdClient sets up the port forwarding and creates an etcd client. +func setupEtcdClient(config *Config) (*clientv3.Client, error) { + if config.PodName == "" { + return nil, fmt.Errorf("You must specify the pod name") + } + + clientConfig, err := clientcmd.BuildConfigFromFlags("", config.Kubeconfig) + if err != nil { + return nil, fmt.Errorf("error building kubeconfig: %s", err) + } + + clientset, err := kubernetes.NewForConfig(clientConfig) + if err != nil { + return nil, fmt.Errorf("error creating Kubernetes client: %s", err) + } + + tlsConfig, localPort, err := setupPortForwarding(config, clientset) + if err != nil { + return nil, fmt.Errorf("failed to setup port forwarding: %s", err) + } + + etcdConfig := clientv3.Config{ + Endpoints: []string{fmt.Sprintf("localhost:%d", localPort)}, + DialTimeout: 5 * time.Second, + } + if tlsConfig != nil { + etcdConfig.TLS = tlsConfig + } + + etcdClient, err := clientv3.New(etcdConfig) + if err != nil { + return nil, fmt.Errorf("failed to connect to etcd server: %s", err) + } + + return etcdClient, nil +} + +func createForfeitLeadershipCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "forfeit-leadership", + Short: "Tell node to forfeit etcd cluster leadership", + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Retrieve the current status to find the leader + status, err := etcdClient.Status(ctx, etcdClient.Endpoints()[0]) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to get current etcd status: %v\n", err) + return + } + + // Retrieve member list to find a member to transfer leadership to + members, err := etcdClient.MemberList(ctx) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to get etcd member list: %v\n", err) + return + } + + for _, member := range members.Members { + if member.ID != status.Leader { + _, err = etcdClient.MoveLeader(ctx, member.ID) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to forfeit leadership: %v\n", err) + return + } + return + } + } + fmt.Println("No eligible member found to transfer leadership to or already not the leader.") + }, + } +} + +func createLeaveCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "leave", + Short: "Tell node to leave etcd cluster", + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // This operation might require administrative privileges on the etcd cluster. + memberListResp, err := etcdClient.MemberList(ctx) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to retrieve member list: %v\n", err) + return + } + + for _, member := range memberListResp.Members { + if member.Name == config.PodName { // Assuming PodName is set as the member name + _, err = etcdClient.MemberRemove(ctx, member.ID) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to remove member from cluster: %v\n", err) + return + } + return + } + } + + fmt.Println("Specified pod is not a member of the etcd cluster.") + }, + } +} + +func createMembersCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "members", + Short: "Get the list of etcd cluster members", + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + membersResp, err := etcdClient.MemberList(ctx) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to list etcd members: %v\n", err) + return + } + + // Header for the table + fmt.Printf("%-19s %-10s %-30s %-30s %-7s\n", "ID", "HOSTNAME", "PEER URLS", "CLIENT URLS", "LEARNER") + for _, member := range membersResp.Members { + fmt.Printf("%-19x %-10s %-30s %-30s %-7v\n", + member.ID, member.Name, strings.Join(member.PeerURLs, ","), strings.Join(member.ClientURLs, ","), member.IsLearner) + } + }, + } +} + +func createRemoveMemberCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "remove-member ", + Short: "Remove a node from the etcd cluster", + Long: `Remove a member from the etcd cluster using its member ID.`, + Args: cobra.ExactArgs(1), // Ensures exactly one argument is passed + Run: func(cmd *cobra.Command, args []string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Parse the member ID from the command line argument + memberID, err := strconv.ParseUint(args[0], 16, 64) + if err != nil { + fmt.Fprintf(os.Stderr, "Invalid member ID format: %v\n", err) + return + } + + // Remove the member using the provided member ID + _, err = etcdClient.MemberRemove(ctx, memberID) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to remove member: %v\n", err) + return + } + }, + } +} + +func createAddMemberCmd(config *Config) *cobra.Command { + return &cobra.Command{ + Use: "add-member [urls]", + Short: "Add a new member to the etcd cluster", + Long: `Add a new member to the etcd cluster using specified peer URLs.`, + Args: cobra.ExactArgs(1), // Requires exactly one argument: the new member URL + Run: func(cmd *cobra.Command, args []string) { + addMember(config, args[0]) + }, + } +} + +func addMember(config *Config, memberURL string) { + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Printf("Failed to set up etcd client: %s\n", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + urls := []string{memberURL} + _, err = etcdClient.MemberAdd(ctx, urls) + if err != nil { + fmt.Printf("Failed to add member: %s\n", err) + return + } + + fmt.Println("Member successfully added") +} + +func createSnapshotCmd(config *Config) *cobra.Command { + var snapshotCmd = &cobra.Command{ + Use: "snapshot ", + Short: "Stream snapshot of the etcd node to the path.", + Long: `Take a snapshot of the etcd database and save it to a specified file path. +This operation is typically used for backup purposes.`, + Args: cobra.ExactArgs(1), // This command requires exactly one argument for the file path + Run: func(cmd *cobra.Command, args []string) { + path := args[0] // The file path where the snapshot will be saved + + etcdClient, err := setupEtcdClient(config) + if err != nil { + fmt.Println("Error setting up etcd client:", err) + return + } + //nolint:errcheck + defer etcdClient.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) // Snapshot can take time + defer cancel() + + // Requesting a snapshot from the etcd server + r, err := etcdClient.Snapshot(ctx) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to create snapshot: %v\n", err) + return + } + //nolint:errcheck + defer r.Close() // Make sure to close the snapshot reader + + // Open the file for writing the snapshot + f, err := os.Create(path) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to open file %s for writing: %v\n", path, err) + return + } + //nolint:errcheck + defer f.Close() // Ensure file is closed after writing + + // Copy the snapshot stream to the file + if _, err = io.Copy(f, r); err != nil { + fmt.Fprintf(os.Stderr, "Failed to write snapshot to file: %v\n", err) + return + } + }, + } + + // Optional flags can be added here + + return snapshotCmd +} + +func setupPortForwarding(config *Config, clientset *kubernetes.Clientset) (*tls.Config, uint16, error) { + pod, err := clientset.CoreV1().Pods(config.Namespace).Get(context.Background(), config.PodName, metav1.GetOptions{}) + if err != nil { + return nil, 0, fmt.Errorf("failed to get pod: %w", err) + } + + path := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/portforward", config.Namespace, config.PodName) + clientConfig, err := clientcmd.BuildConfigFromFlags("", config.Kubeconfig) + if err != nil { + return nil, 0, fmt.Errorf("error building kubeconfig: %w", err) + } + + transport, upgrader, err := spdy.RoundTripperFor(clientConfig) + if err != nil { + return nil, 0, fmt.Errorf("failed to create round tripper: %w", err) + } + + hostURL, err := url.Parse(clientConfig.Host) + if err != nil { + return nil, 0, fmt.Errorf("failed to parse host URL: %w", err) + } + + hostURL.Path = path + + stopChan, readyChan := make(chan struct{}, 1), make(chan struct{}, 1) + dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", hostURL) + + silentOut := &silentWriter{} + portForwarder, err := portforward.New(dialer, []string{"0:2379"}, stopChan, readyChan, silentOut, os.Stderr) + if err != nil { + return nil, 0, fmt.Errorf("failed to create port forwarder: %w", err) + } + + // Starting port forwarding + go func() { + if err := portForwarder.ForwardPorts(); err != nil { + fmt.Printf("Failed to start port forwarding: %s\n", err) + } + }() + + <-readyChan // Waiting for port forwarding to be ready + + // Obtaining the local port used for forwarding + forwardedPorts, err := portForwarder.GetPorts() + if err != nil { + return nil, 0, fmt.Errorf("failed to get forwarded ports: %w", err) + } + + localPort := forwardedPorts[0].Local + + tlsConfig, err := getTLSConfig(clientset, pod, config.Namespace) + if err != nil { + return nil, 0, fmt.Errorf("failed to get TLS config: %w", err) + } + + return tlsConfig, localPort, nil +} + +// Initialize configuration via Cobra command +func initializeConfig(cmd *cobra.Command) *Config { + var kubeconfig, namespace, podName string + + // Checking environment variable first + envKubeconfig := os.Getenv("KUBECONFIG") + if envKubeconfig != "" { + kubeconfig = envKubeconfig + } else { + // Use default kubeconfig from home directory + kubeconfig = filepath.Join(homedir.HomeDir(), ".kube", "config") + } + + // Binding flags + cmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "k", kubeconfig, "Path to the kubeconfig file") + cmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", + "Namespace of the etcd pod (default is the current namespace from kubeconfig)") + cmd.PersistentFlags().StringVarP(&podName, "pod", "p", "", "Name of the etcd pod") + + // Parse flags + if err := cmd.ParseFlags(os.Args[1:]); err != nil { + fmt.Fprintf(os.Stderr, "Failed to parse flags: %v\n", err) + os.Exit(1) + } + + // If namespace is not specified, fetch it from kubeconfig context + if namespace == "" { + configLoader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + clientcmd.NewDefaultClientConfigLoadingRules(), + &clientcmd.ConfigOverrides{}) + ns, _, err := configLoader.Namespace() + if err != nil { + fmt.Printf("Error fetching namespace from kubeconfig: %s\n", err) + os.Exit(1) + } + namespace = ns + if namespace == "" { + namespace = "default" // Default to "default" if not specified + } + } + + return &Config{ + Kubeconfig: kubeconfig, + Namespace: namespace, + PodName: podName, + } +} + +// Config struct to hold configuration +type Config struct { + Kubeconfig string + Namespace string + PodName string +} + +func getTLSConfig(clientset *kubernetes.Clientset, pod *corev1.Pod, namespace string) (*tls.Config, error) { + for _, container := range pod.Spec.Containers { + if container.Name == "etcd" { + secretName, err := findSecretNameForTLS(pod, container) + if err != nil { + if err.Error() == "trusted CA file path not specified in container args" { + return nil, nil + } + return nil, err + } + + caCertPool, clientCert, err := extractTLSFiles(clientset, namespace, secretName) + if err != nil { + return nil, err + } + + return &tls.Config{ + Certificates: []tls.Certificate{*clientCert}, + RootCAs: caCertPool, + }, nil + } + } + return nil, fmt.Errorf("etcd container not found") +} + +func findSecretNameForTLS(pod *corev1.Pod, container corev1.Container) (string, error) { + caFilePath := "" + for _, arg := range append(container.Command, container.Args...) { + if strings.HasPrefix(arg, "--trusted-ca-file=") { + caFilePath = strings.TrimPrefix(arg, "--trusted-ca-file=") + break + } + } + + if caFilePath == "" { + return "", fmt.Errorf("trusted CA file path not specified in container args") + } + + for _, vm := range container.VolumeMounts { + if strings.HasPrefix(caFilePath, vm.MountPath) { + // We found the mount path, now find the volume + for _, vol := range pod.Spec.Volumes { + if vol.Name == vm.Name && vol.Secret != nil { + return vol.Secret.SecretName, nil + } + } + } + } + + return "", fmt.Errorf("secret for the trusted CA file not found") +} + +func extractTLSFiles(clientset *kubernetes.Clientset, namespace, secretName string) ( + *x509.CertPool, *tls.Certificate, error) { + secret, err := clientset.CoreV1().Secrets(namespace).Get(context.Background(), secretName, metav1.GetOptions{}) + if err != nil { + return nil, nil, err + } + + caPem, ok := secret.Data["ca.crt"] + if !ok { + return nil, nil, fmt.Errorf("CA certificate not found in secret") + } + caCertPool := x509.NewCertPool() + if !caCertPool.AppendCertsFromPEM(caPem) { + return nil, nil, fmt.Errorf("failed to parse CA certificate") + } + + certPem, ok := secret.Data["tls.crt"] + if !ok { + return nil, nil, fmt.Errorf("TLS certificate not found in secret") + } + keyPem, ok := secret.Data["tls.key"] + if !ok { + return nil, nil, fmt.Errorf("TLS key not found in secret") + } + + clientCert, err := tls.X509KeyPair(certPem, keyPem) + if err != nil { + return nil, nil, fmt.Errorf("failed to create X509 key pair: %s", err) + } + + return caCertPool, &clientCert, nil +} + +type silentWriter struct{} + +func (sw *silentWriter) Write(p []byte) (int, error) { + return len(p), nil +} diff --git a/cmd/main.go b/cmd/manager/main.go similarity index 100% rename from cmd/main.go rename to cmd/manager/main.go diff --git a/go.mod b/go.mod index ae9ce48c..d74f4195 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,12 @@ module github.com/aenix-io/etcd-operator go 1.22.4 require ( + github.com/dustin/go-humanize v1.0.1 github.com/go-logr/logr v1.4.2 github.com/google/uuid v1.6.0 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 + github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 go.etcd.io/etcd/client/v3 v3.5.14 @@ -40,17 +42,21 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.6 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 // indirect diff --git a/go.sum b/go.sum index a0c4a088..a13159d3 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -6,11 +8,14 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= @@ -55,10 +60,15 @@ github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQN github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -80,6 +90,8 @@ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvls github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -87,6 +99,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= @@ -108,6 +122,7 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -118,6 +133,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= From 087b4a3eeceef1df605c27fb7a377aa4f88ce0eb Mon Sep 17 00:00:00 2001 From: Artem Bortnikov Date: Thu, 20 Jun 2024 14:28:37 +0300 Subject: [PATCH 3/7] run kind for e2e tests with kube-proxy in ipvs mode Signed-off-by: Artem Bortnikov --- Makefile | 7 +++---- test/e2e/config.yaml | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 test/e2e/config.yaml diff --git a/Makefile b/Makefile index b324f38c..89b9ff1c 100644 --- a/Makefile +++ b/Makefile @@ -203,11 +203,10 @@ kind-load: docker-build kind ## Build and upload docker image to the local Kind .PHONY: kind-create kind-create: kind yq ## Create kubernetes cluster using Kind. @if ! $(KIND) get clusters | grep -q $(KIND_CLUSTER_NAME); then \ - $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --image kindest/node:$(K8S_VERSION); \ - fi - @if ! $(CONTAINER_TOOL) container inspect $$($(KIND) get nodes) | $(YQ) e '.[0].Config.Image' | grep -q $(K8S_VERSION); then \ + $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --image kindest/node:$(K8S_VERSION) --config test/e2e/config.yaml; \ + elif ! $(CONTAINER_TOOL) container inspect $$($(KIND) get nodes --name $(KIND_CLUSTER_NAME)) | $(YQ) e '.[0].Config.Image' | grep -q $(K8S_VERSION); then \ $(KIND) delete cluster --name $(KIND_CLUSTER_NAME); \ - $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --image kindest/node:$(K8S_VERSION); \ + $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --image kindest/node:$(K8S_VERSION) --config test/e2e/config.yaml; \ fi .PHONY: kind-delete diff --git a/test/e2e/config.yaml b/test/e2e/config.yaml new file mode 100644 index 00000000..afe81483 --- /dev/null +++ b/test/e2e/config.yaml @@ -0,0 +1,4 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +networking: + kubeProxyMode: "ipvs" From 2ef99eeb4807a446b384ab3da1151268dbdf7ebe Mon Sep 17 00:00:00 2001 From: Artem Bortnikov Date: Thu, 6 Jun 2024 15:26:43 +0300 Subject: [PATCH 4/7] add volumeClaimTemplates only if storage.EmptyDir is nil Signed-off-by: Artem Bortnikov --- internal/controller/factory/statefulset.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/controller/factory/statefulset.go b/internal/controller/factory/statefulset.go index 68dc9b1c..4fd5c91e 100644 --- a/internal/controller/factory/statefulset.go +++ b/internal/controller/factory/statefulset.go @@ -59,8 +59,9 @@ func CreateOrUpdateStatefulSet( podMetadata.Annotations = cluster.Spec.PodTemplate.Annotations } - volumeClaimTemplates := []corev1.PersistentVolumeClaim{ - { + volumeClaimTemplates := make([]corev1.PersistentVolumeClaim, 0) + if cluster.Spec.Storage.EmptyDir == nil { + volumeClaimTemplates = append(volumeClaimTemplates, corev1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ Name: GetPVCName(cluster), Labels: cluster.Spec.Storage.VolumeClaimTemplate.Labels, @@ -68,7 +69,7 @@ func CreateOrUpdateStatefulSet( }, Spec: cluster.Spec.Storage.VolumeClaimTemplate.Spec, Status: cluster.Spec.Storage.VolumeClaimTemplate.Status, - }, + }) } volumes := generateVolumes(cluster) From a5f7cb9c7c07bbbedd818f3ddbd77e2e246fa175 Mon Sep 17 00:00:00 2001 From: Artem Bortnikov Date: Thu, 20 Jun 2024 17:44:57 +0300 Subject: [PATCH 5/7] e2e test for etcd cluster with empydir storage Signed-off-by: Artem Bortnikov --- examples/manifests/etcdcluster-emptydir.yaml | 10 ++++ test/e2e/e2e_test.go | 51 +++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 examples/manifests/etcdcluster-emptydir.yaml diff --git a/examples/manifests/etcdcluster-emptydir.yaml b/examples/manifests/etcdcluster-emptydir.yaml new file mode 100644 index 00000000..06871b89 --- /dev/null +++ b/examples/manifests/etcdcluster-emptydir.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: etcd.aenix.io/v1alpha1 +kind: EtcdCluster +metadata: + name: test +spec: + storage: + emptyDir: + sizeLimit: 1Gi + replicas: 3 diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index c9967858..aadc826f 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -62,7 +62,7 @@ var _ = Describe("etcd-operator", Ordered, func() { }) - if os.Getenv("DO_NOT_CLEANUP_AFTER_E2E") == "true" { + if os.Getenv("DO_CLEANUP_AFTER_E2E") == "true" { AfterAll(func() { By("Delete kind environment", func() { cmd := exec.Command("make", "kind-delete") @@ -120,6 +120,55 @@ var _ = Describe("etcd-operator", Ordered, func() { }) }) + Context("With emptyDir", func() { + It("should deploy etcd cluster", func() { + var err error + const namespace = "test-emtydir-etcd-cluster" + var wg sync.WaitGroup + wg.Add(1) + + By("create namespace", func() { + cmd := exec.Command("sh", "-c", + fmt.Sprintf("kubectl create namespace %s --dry-run=client -o yaml | kubectl apply -f -", namespace)) // nolint:lll + _, err = utils.Run(cmd) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) + }) + + By("apply etcd cluster with emptydir manifest", func() { + dir, _ := utils.GetProjectDir() + cmd := exec.Command("kubectl", "apply", + "--filename", dir+"/examples/manifests/etcdcluster-emptydir.yaml", + "--namespace", namespace, + ) + _, err = utils.Run(cmd) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) + }) + + By("wait for statefulset is ready", func() { + cmd := exec.Command("kubectl", "wait", + "statefulset/test", + "--for", "jsonpath={.status.readyReplicas}=3", + "--namespace", namespace, + "--timeout", "5m", + ) + _, err = utils.Run(cmd) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) + }) + + client, err := utils.GetEtcdClient(ctx, client.ObjectKey{Namespace: namespace, Name: "test"}) + Expect(err).NotTo(HaveOccurred()) + defer func() { + err := client.Close() + Expect(err).NotTo(HaveOccurred()) + }() + + By("check etcd cluster is healthy", func() { + Expect(utils.IsEtcdClusterHealthy(ctx, client)).To(BeTrue()) + }) + + }) + }) + Context("TLS and enabled auth", func() { It("should deploy etcd cluster with auth", func() { var err error From 5e27419dab668bb003448562bb8b0a0962e65434 Mon Sep 17 00:00:00 2001 From: Artem Bortnikov Date: Thu, 20 Jun 2024 21:06:58 +0300 Subject: [PATCH 6/7] upd golangci-lint rules Signed-off-by: Artem Bortnikov --- .golangci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index aed8644d..32eec7ed 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -16,6 +16,9 @@ issues: linters: - dupl - lll + - path: _test\.go + linters: + - dupl linters: disable-all: true enable: From f86a17a4ac5acf58088868617973a83069c3f5d2 Mon Sep 17 00:00:00 2001 From: Artem Bortnikov Date: Thu, 20 Jun 2024 22:17:10 +0300 Subject: [PATCH 7/7] set cosign-installer to use default (latest) cosign version Signed-off-by: Artem Bortnikov --- .github/workflows/docker-publish.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/docker-publish.yaml b/.github/workflows/docker-publish.yaml index 7064cbba..5c676a57 100644 --- a/.github/workflows/docker-publish.yaml +++ b/.github/workflows/docker-publish.yaml @@ -36,8 +36,6 @@ jobs: - name: Install cosign if: github.event_name != 'pull_request' uses: sigstore/cosign-installer@v3.5.0 - with: - cosign-release: 'v2.1.1' # Set up BuildKit Docker container builder to be able to build # multi-platform images and export cache