1
0
mirror of synced 2026-03-01 19:26:55 +00:00

Compare commits

..

4 Commits

Author SHA1 Message Date
Stefan Prodan
e0bc754ad0 Refer to authorisation model in RFC-0001
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-12-17 11:58:45 +02:00
Michael Bridgen
a67d19317b Explain authorisation model and mechanisms
The multi-tenancy implementations described rely on impersonation and
remote apply; to make this RFC stand by itself, those need to be
explained, along with the authorisation model (how Flux "decides" what
it's allowed to do).

This commit adds a summary of the authorisation model, impersonation,
and remote apply, and rejigs the headings a little to make space.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-12-17 11:58:39 +02:00
Stefan Prodan
dc7cb189fc Incorporate Michael's suggestions
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-12-17 11:58:39 +02:00
Stefan Prodan
d23d87ac94 Define Flux tenancy models
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-12-17 11:58:38 +02:00
101 changed files with 1083 additions and 1471 deletions

View File

@@ -12,7 +12,7 @@ provides=("flux-bin")
conflicts=("flux-bin") conflicts=("flux-bin")
replaces=("flux-cli") replaces=("flux-cli")
depends=("glibc") depends=("glibc")
makedepends=('go>=1.17', 'kustomize>=3.0') makedepends=('go>=1.16', 'kustomize>=3.0')
optdepends=('bash-completion: auto-completion for flux in Bash', optdepends=('bash-completion: auto-completion for flux in Bash',
'zsh-completions: auto-completion for flux in ZSH') 'zsh-completions: auto-completion for flux in ZSH')
source=( source=(
@@ -30,20 +30,12 @@ build() {
export CGO_CXXFLAGS="$CXXFLAGS" export CGO_CXXFLAGS="$CXXFLAGS"
export CGO_CPPFLAGS="$CPPFLAGS" export CGO_CPPFLAGS="$CPPFLAGS"
export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw" export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw"
make cmd/flux/.manifests.done ./manifests/scripts/bundle.sh "${PWD}/manifests" "${PWD}/cmd/flux/manifests"
go build -ldflags "-linkmode=external -X main.VERSION=${pkgver}" -o ${_srcname} ./cmd/flux go build -ldflags "-linkmode=external -X main.VERSION=${pkgver}" -o ${_srcname} ./cmd/flux
} }
check() { check() {
cd "flux2-${pkgver}" cd "flux2-${pkgver}"
case $CARCH in
aarch64)
export ENVTEST_ARCH=arm64
;;
armv6h|armv7h)
export ENVTEST_ARCH=arm
;;
esac
make test make test
} }

View File

@@ -11,7 +11,7 @@ license=("APACHE")
provides=("flux-bin") provides=("flux-bin")
conflicts=("flux-bin") conflicts=("flux-bin")
depends=("glibc") depends=("glibc")
makedepends=('go>=1.17', 'kustomize>=3.0', 'git') makedepends=('go>=1.16', 'kustomize>=3.0')
optdepends=('bash-completion: auto-completion for flux in Bash', optdepends=('bash-completion: auto-completion for flux in Bash',
'zsh-completions: auto-completion for flux in ZSH') 'zsh-completions: auto-completion for flux in ZSH')
source=( source=(
@@ -32,20 +32,12 @@ build() {
export CGO_CXXFLAGS="$CXXFLAGS" export CGO_CXXFLAGS="$CXXFLAGS"
export CGO_CPPFLAGS="$CPPFLAGS" export CGO_CPPFLAGS="$CPPFLAGS"
export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw" export GOFLAGS="-buildmode=pie -trimpath -mod=readonly -modcacherw"
make cmd/flux/.manifests.done make cmd/flux/manifests
go build -ldflags "-linkmode=external -X main.VERSION=${pkgver}" -o ${_srcname} ./cmd/flux go build -ldflags "-linkmode=external -X main.VERSION=${pkgver}" -o ${_srcname} ./cmd/flux
} }
check() { check() {
cd "flux2" cd "flux2"
case $CARCH in
aarch64)
export ENVTEST_ARCH=arm64
;;
armv6h|armv7h)
export ENVTEST_ARCH=arm
;;
esac
make test make test
} }

View File

@@ -21,7 +21,6 @@ set -eu
KIND_VERSION=0.11.1 KIND_VERSION=0.11.1
KUBECTL_VERSION=1.21.2 KUBECTL_VERSION=1.21.2
KUSTOMIZE_VERSION=4.1.3 KUSTOMIZE_VERSION=4.1.3
HELM_VERSION=3.7.2
GITHUB_RUNNER_VERSION=2.285.1 GITHUB_RUNNER_VERSION=2.285.1
PACKAGES="apt-transport-https ca-certificates software-properties-common build-essential libssl-dev gnupg lsb-release jq" PACKAGES="apt-transport-https ca-certificates software-properties-common build-essential libssl-dev gnupg lsb-release jq"
@@ -53,12 +52,6 @@ curl -Lo ./kustomize.tar.gz https://github.com/kubernetes-sigs/kustomize/release
&& rm kustomize.tar.gz && rm kustomize.tar.gz
install -o root -g root -m 0755 kustomize /usr/local/bin/kustomize install -o root -g root -m 0755 kustomize /usr/local/bin/kustomize
# install helm
curl -Lo ./helm.tar.gz https://get.helm.sh/helm-v${HELM_VERSION}-linux-arm64.tar.gz \
&& tar -zxvf helm.tar.gz \
&& rm helm.tar.gz
install -o root -g root -m 0755 linux-arm64/helm /usr/local/bin/helm
# download runner # download runner
curl -o actions-runner-linux-arm64.tar.gz -L https://github.com/actions/runner/releases/download/v${GITHUB_RUNNER_VERSION}/actions-runner-linux-arm64-${GITHUB_RUNNER_VERSION}.tar.gz \ curl -o actions-runner-linux-arm64.tar.gz -L https://github.com/actions/runner/releases/download/v${GITHUB_RUNNER_VERSION}/actions-runner-linux-arm64-${GITHUB_RUNNER_VERSION}.tar.gz \
&& tar xzf actions-runner-linux-arm64.tar.gz \ && tar xzf actions-runner-linux-arm64.tar.gz \

View File

@@ -17,13 +17,13 @@ jobs:
uses: actions/cache@v1 uses: actions/cache@v1
with: with:
path: ~/go/pkg/mod path: ~/go/pkg/mod
key: ${{ runner.os }}-go1.17-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go1.17- ${{ runner.os }}-go1.16-
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17.x go-version: 1.16.x
- name: Setup Kubernetes - name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0 uses: engineerd/setup-kind@v0.5.0
with: with:
@@ -103,26 +103,13 @@ jobs:
/tmp/flux reconcile image repository podinfo /tmp/flux reconcile image repository podinfo
/tmp/flux reconcile image update flux-system /tmp/flux reconcile image update flux-system
/tmp/flux get images all /tmp/flux get images all
/tmp/flux get images policy podinfo | grep "5.2.1"
retries=10 /tmp/flux get image update flux-system | grep commit
count=0
ok=false
until ${ok}; do
/tmp/flux get image update flux-system | grep 'commit' && ok=true || ok=false
count=$(($count + 1))
if [[ ${count} -eq ${retries} ]]; then
echo "No more retries left"
exit 1
fi
sleep 6
/tmp/flux reconcile image update flux-system
done
env: env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
GITHUB_REPO_NAME: ${{ steps.vars.outputs.test_repo_name }} GITHUB_REPO_NAME: ${{ steps.vars.outputs.test_repo_name }}
GITHUB_ORG_NAME: fluxcd-testing GITHUB_ORG_NAME: fluxcd-testing
- name: delete repository - name: delete repository
if: ${{ always() }}
run: | run: |
curl \ curl \
-X DELETE \ -X DELETE \

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17.x go-version: 1.16.x
- name: Prepare - name: Prepare
id: prep id: prep
run: | run: |

View File

@@ -17,13 +17,13 @@ jobs:
uses: actions/cache@v1 uses: actions/cache@v1
with: with:
path: ~/go/pkg/mod path: ~/go/pkg/mod
key: ${{ runner.os }}-go1.17-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go1.17- ${{ runner.os }}-go1.16-
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17.x go-version: 1.16.x
- name: Install libgit2 - name: Install libgit2
run: | run: |
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 648ACFD622F3D138 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 648ACFD622F3D138

View File

@@ -16,19 +16,23 @@ jobs:
uses: actions/cache@v1 uses: actions/cache@v1
with: with:
path: ~/go/pkg/mod path: ~/go/pkg/mod
key: ${{ runner.os }}-go1.17-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go1.17- ${{ runner.os }}-go1.16-
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17.x go-version: 1.16.x
- name: Setup Kubernetes - name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0 uses: engineerd/setup-kind@v0.5.0
with: with:
version: v0.11.1 version: v0.11.1
image: kindest/node:v1.19.11@sha256:07db187ae84b4b7de440a73886f008cf903fcf5764ba8106a9fd5243d6f32729 image: kindest/node:v1.19.11@sha256:07db187ae84b4b7de440a73886f008cf903fcf5764ba8106a9fd5243d6f32729
config: .github/kind/config.yaml # disable KIND-net config: .github/kind/config.yaml # disable KIND-net
- name: Setup envtest
uses: fluxcd/pkg/actions/envtest@main
with:
version: "1.21.x"
- name: Setup Calico for network policy - name: Setup Calico for network policy
run: | run: |
kubectl apply -f https://docs.projectcalico.org/v3.20/manifests/calico.yaml kubectl apply -f https://docs.projectcalico.org/v3.20/manifests/calico.yaml

View File

@@ -4,11 +4,6 @@ on:
push: push:
tags: [ 'v*' ] tags: [ 'v*' ]
permissions:
contents: write # needed to write releases
id-token: write # needed for keyless signing
packages: write # needed for ghcr access
jobs: jobs:
goreleaser: goreleaser:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -20,18 +15,16 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17.x go-version: 1.16.x
- name: Setup QEMU - name: Setup QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1
with:
platforms: all
- name: Setup Docker Buildx - name: Setup Docker Buildx
id: buildx id: buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Setup Syft with:
uses: anchore/sbom-action/download-syft@v0 buildkitd-flags: "--debug"
- name: Setup Cosign
uses: sigstore/cosign-installer@main
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v1 uses: docker/login-action@v1
with: with:
@@ -43,6 +36,18 @@ jobs:
with: with:
username: fluxcdbot username: fluxcdbot
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }} password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
- name: Download release notes utility
env:
GH_REL_URL: https://github.com/buchanae/github-release-notes/releases/download/0.2.0/github-release-notes-linux-amd64-0.2.0.tar.gz
run: cd /tmp && curl -sSL ${GH_REL_URL} | tar xz && sudo mv github-release-notes /usr/local/bin/
- name: Generate release notes
run: |
echo 'CHANGELOG' > /tmp/release.txt
github-release-notes -org fluxcd -repo toolkit -since-latest-release -include-author >> /tmp/release.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Generate manifests - name: Generate manifests
run: | run: |
make cmd/flux/.manifests.done make cmd/flux/.manifests.done
@@ -61,22 +66,11 @@ jobs:
- name: Archive the OpenAPI JSON schemas - name: Archive the OpenAPI JSON schemas
run: | run: |
tar -czvf ./output/crd-schemas.tar.gz -C schemas . tar -czvf ./output/crd-schemas.tar.gz -C schemas .
- name: Download release notes utility
env:
GH_REL_URL: https://github.com/buchanae/github-release-notes/releases/download/0.2.0/github-release-notes-linux-amd64-0.2.0.tar.gz
run: cd /tmp && curl -sSL ${GH_REL_URL} | tar xz && sudo mv github-release-notes /usr/local/bin/
- name: Generate release notes
run: |
NOTES="./output/notes.md"
echo '## CLI Changelog' > ${NOTES}
github-release-notes -org fluxcd -repo flux2 -since-latest-release -include-author >> ${NOTES}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run GoReleaser - name: Run GoReleaser
uses: goreleaser/goreleaser-action@v1 uses: goreleaser/goreleaser-action@v1
with: with:
version: latest version: latest
args: release --release-notes=output/notes.md --skip-validate args: release --release-notes=/tmp/release.txt --skip-validate
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }} HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}

View File

@@ -16,7 +16,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.17.x go-version: 1.16.x
- name: Update component versions - name: Update component versions
id: update id: update
run: | run: |

1
.gitignore vendored
View File

@@ -20,7 +20,6 @@ bin/
output/ output/
cmd/flux/manifests/ cmd/flux/manifests/
cmd/flux/.manifests.done cmd/flux/.manifests.done
testbin/
# Docs # Docs
site/ site/

View File

@@ -40,36 +40,6 @@ archives:
format: zip format: zip
files: files:
- none* - none*
source:
enabled: true
name_template: '{{ .ProjectName }}_{{ .Version }}_source_code'
sboms:
- id: source
artifacts: source
documents:
- "{{ .ProjectName }}_{{ .Version }}_sbom.spdx.json"
release:
extra_files:
- glob: output/crd-schemas.tar.gz
- glob: output/manifests.tar.gz
- glob: output/install.yaml
checksum:
extra_files:
- glob: output/crd-schemas.tar.gz
- glob: output/manifests.tar.gz
- glob: output/install.yaml
signs:
- cmd: cosign
env:
- COSIGN_EXPERIMENTAL=1
certificate: '${artifact}.pem'
args:
- sign-blob
- '--output-certificate=${certificate}'
- '--output-signature=${signature}'
- '${artifact}'
artifacts: checksum
output: true
brews: brews:
- name: flux - name: flux
tap: tap:
@@ -108,12 +78,17 @@ publishers:
- AUR_BOT_SSH_PRIVATE_KEY={{ .Env.AUR_BOT_SSH_PRIVATE_KEY }} - AUR_BOT_SSH_PRIVATE_KEY={{ .Env.AUR_BOT_SSH_PRIVATE_KEY }}
cmd: | cmd: |
.github/aur/flux-go/publish.sh {{ .Version }} .github/aur/flux-go/publish.sh {{ .Version }}
release:
extra_files:
- glob: ./output/crd-schemas.tar.gz
- glob: ./output/manifests.tar.gz
- glob: ./output/install.yaml
dockers: dockers:
- image_templates: - image_templates:
- 'fluxcd/flux-cli:{{ .Tag }}-amd64' - 'fluxcd/flux-cli:{{ .Tag }}-amd64'
- 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-amd64' - 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-amd64'
dockerfile: Dockerfile dockerfile: Dockerfile
use: buildx use_buildx: true
goos: linux goos: linux
goarch: amd64 goarch: amd64
build_flag_templates: build_flag_templates:
@@ -129,7 +104,7 @@ dockers:
- 'fluxcd/flux-cli:{{ .Tag }}-arm64' - 'fluxcd/flux-cli:{{ .Tag }}-arm64'
- 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm64' - 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm64'
dockerfile: Dockerfile dockerfile: Dockerfile
use: buildx use_buildx: true
goos: linux goos: linux
goarch: arm64 goarch: arm64
build_flag_templates: build_flag_templates:
@@ -145,7 +120,7 @@ dockers:
- 'fluxcd/flux-cli:{{ .Tag }}-arm' - 'fluxcd/flux-cli:{{ .Tag }}-arm'
- 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm' - 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm'
dockerfile: Dockerfile dockerfile: Dockerfile
use: buildx use_buildx: true
goos: linux goos: linux
goarch: arm goarch: arm
goarm: 7 goarm: 7
@@ -169,12 +144,3 @@ docker_manifests:
- 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-amd64' - 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-amd64'
- 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm64' - 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm64'
- 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm' - 'ghcr.io/fluxcd/flux-cli:{{ .Tag }}-arm'
docker_signs:
- cmd: cosign
env:
- COSIGN_EXPERIMENTAL=1
args:
- sign
- '${artifact}'
artifacts: all
output: true

View File

@@ -1,15 +1,15 @@
FROM alpine:3.15 as builder FROM alpine:3.14 as builder
RUN apk add --no-cache ca-certificates curl RUN apk add --no-cache ca-certificates curl
ARG ARCH=linux/amd64 ARG ARCH=linux/amd64
ARG KUBECTL_VER=1.23.1 ARG KUBECTL_VER=1.22.2
RUN curl -sL https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/${ARCH}/kubectl \ RUN curl -sL https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/${ARCH}/kubectl \
-o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl && \ -o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl && \
kubectl version --client=true kubectl version --client=true
FROM alpine:3.15 as flux-cli FROM alpine:3.14 as flux-cli
# Create minimal nsswitch.conf file to prioritize the usage of /etc/hosts over DNS queries. # Create minimal nsswitch.conf file to prioritize the usage of /etc/hosts over DNS queries.
# https://github.com/gliderlabs/docker-alpine/issues/367#issuecomment-354316460 # https://github.com/gliderlabs/docker-alpine/issues/367#issuecomment-354316460

View File

@@ -1,8 +1,8 @@
VERSION?=$(shell grep 'VERSION' cmd/flux/main.go | awk '{ print $$4 }' | head -n 1 | tr -d '"') VERSION?=$(shell grep 'VERSION' cmd/flux/main.go | awk '{ print $$4 }' | head -n 1 | tr -d '"')
EMBEDDED_MANIFESTS_TARGET=cmd/flux/.manifests.done EMBEDDED_MANIFESTS_TARGET=cmd/flux/.manifests.done
TEST_KUBECONFIG?=/tmp/flux-e2e-test-kubeconfig TEST_KUBECONFIG?=/tmp/flux-e2e-test-kubeconfig
# Architecture to use envtest with ENVTEST_BIN_VERSION?=latest
ENVTEST_ARCH ?= amd64 KUBEBUILDER_ASSETS?=$(shell $(SETUP_ENVTEST) use -i $(ENVTEST_BIN_VERSION) -p path)
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN)) ifeq (,$(shell go env GOBIN))
@@ -17,7 +17,6 @@ all: test build
tidy: tidy:
go mod tidy go mod tidy
cd tests/azure && go mod tidy
fmt: fmt:
go fmt ./... go fmt ./...
@@ -34,7 +33,6 @@ cleanup-kind:
kind delete cluster --name=flux-e2e-test kind delete cluster --name=flux-e2e-test
rm $(TEST_KUBECONFIG) rm $(TEST_KUBECONFIG)
KUBEBUILDER_ASSETS?="$(shell $(ENVTEST) --arch=$(ENVTEST_ARCH) use -i $(ENVTEST_KUBERNETES_VERSION) --bin-dir=$(ENVTEST_ASSETS_DIR) -p path)"
test: $(EMBEDDED_MANIFESTS_TARGET) tidy fmt vet install-envtest test: $(EMBEDDED_MANIFESTS_TARGET) tidy fmt vet install-envtest
KUBEBUILDER_ASSETS="$(KUBEBUILDER_ASSETS)" go test ./... -coverprofile cover.out --tags=unit KUBEBUILDER_ASSETS="$(KUBEBUILDER_ASSETS)" go test ./... -coverprofile cover.out --tags=unit
@@ -60,33 +58,27 @@ install:
install-dev: install-dev:
CGO_ENABLED=0 go build -o /usr/local/bin ./cmd/flux CGO_ENABLED=0 go build -o /usr/local/bin ./cmd/flux
install-envtest: setup-envtest
$(SETUP_ENVTEST) use $(ENVTEST_BIN_VERSION)
setup-bootstrap-patch: setup-bootstrap-patch:
go run ./tests/bootstrap/main.go go run ./tests/bootstrap/main.go
setup-image-automation: setup-image-automation:
cd tests/image-automation && go run main.go cd tests/image-automation && go run main.go
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin # Find or download setup-envtest
ENVTEST_KUBERNETES_VERSION?=latest setup-envtest:
install-envtest: setup-envtest ifeq (, $(shell which setup-envtest))
mkdir -p ${ENVTEST_ASSETS_DIR} @{ \
$(ENVTEST) use $(ENVTEST_KUBERNETES_VERSION) --arch=$(ENVTEST_ARCH) --bin-dir=$(ENVTEST_ASSETS_DIR) set -e ;\
SETUP_ENVTEST_TMP_DIR=$$(mktemp -d) ;\
ENVTEST = $(shell pwd)/bin/setup-envtest cd $$SETUP_ENVTEST_TMP_DIR ;\
.PHONY: envtest go mod init tmp ;\
setup-envtest: ## Download envtest-setup locally if necessary. go get sigs.k8s.io/controller-runtime/tools/setup-envtest@latest ;\
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest) rm -rf $$SETUP_ENVTEST_TMP_DIR ;\
}
# go-install-tool will 'go install' any package $2 and install it to $1. SETUP_ENVTEST=$(GOBIN)/setup-envtest
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) else
define go-install-tool SETUP_ENVTEST=$(shell which setup-envtest)
@[ -f $(1) ] || { \ endif
set -e ;\
TMP_DIR=$$(mktemp -d) ;\
cd $$TMP_DIR ;\
go mod init tmp ;\
echo "Downloading $(2)" ;\
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
rm -rf $$TMP_DIR ;\
}
endef

View File

@@ -12,9 +12,6 @@ inputs:
description: "arch can be amd64, arm64 or arm" description: "arch can be amd64, arm64 or arm"
required: true required: true
default: "amd64" default: "amd64"
bindir:
description: "Optional location of the Flux binary. Will not use sudo if set. Updates System Path."
required: false
runs: runs:
using: composite using: composite
steps: steps:
@@ -32,16 +29,10 @@ runs:
curl -sL ${BIN_URL} -o /tmp/flux.tar.gz curl -sL ${BIN_URL} -o /tmp/flux.tar.gz
mkdir -p /tmp/flux mkdir -p /tmp/flux
tar -C /tmp/flux/ -zxvf /tmp/flux.tar.gz tar -C /tmp/flux/ -zxvf /tmp/flux.tar.gz
- name: "Copy Flux binary to execute location" - name: "Add flux binary to /usr/local/bin"
shell: bash shell: bash
run: | run: |
BINDIR=${{ inputs.bindir }} sudo cp /tmp/flux/flux /usr/local/bin
if [ -z $BINDIR ]; then
sudo cp /tmp/flux/flux /usr/local/bin
else
cp /tmp/flux/flux "${BINDIR}"
echo "${BINDIR}" >> $GITHUB_PATH
fi
- name: "Cleanup tmp" - name: "Cleanup tmp"
shell: bash shell: bash
run: | run: |

View File

@@ -121,7 +121,7 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -179,7 +179,7 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
installOptions := install.Options{ installOptions := install.Options{
BaseURL: rootArgs.defaults.BaseURL, BaseURL: rootArgs.defaults.BaseURL,
Version: bootstrapArgs.version, Version: bootstrapArgs.version,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
@@ -200,7 +200,7 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
// Source generation and secret config // Source generation and secret config
secretOpts := sourcesecret.Options{ secretOpts := sourcesecret.Options{
Name: bootstrapArgs.secretName, Name: bootstrapArgs.secretName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
TargetPath: bServerArgs.path.String(), TargetPath: bServerArgs.path.String(),
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile, ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
} }
@@ -232,8 +232,8 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
// Sync manifest config // Sync manifest config
syncOpts := sync.Options{ syncOpts := sync.Options{
Interval: bServerArgs.interval, Interval: bServerArgs.interval,
Name: *kubeconfigArgs.Namespace, Name: rootArgs.namespace,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Branch: bootstrapArgs.branch, Branch: bootstrapArgs.branch,
Secret: bootstrapArgs.secretName, Secret: bootstrapArgs.secretName,
TargetPath: bServerArgs.path.ToSlash(), TargetPath: bServerArgs.path.ToSlash(),
@@ -251,7 +251,7 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix), bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
bootstrap.WithProviderTeamPermissions(mapTeamSlice(bServerArgs.teams, bServerDefaultPermission)), bootstrap.WithProviderTeamPermissions(mapTeamSlice(bServerArgs.teams, bServerDefaultPermission)),
bootstrap.WithReadWriteKeyPermissions(bServerArgs.readWriteKey), bootstrap.WithReadWriteKeyPermissions(bServerArgs.readWriteKey),
bootstrap.WithKubeconfig(kubeconfigArgs), bootstrap.WithKubeconfig(rootArgs.kubeconfig, rootArgs.kubecontext),
bootstrap.WithLogger(logger), bootstrap.WithLogger(logger),
bootstrap.WithCABundle(caBundle), bootstrap.WithCABundle(caBundle),
} }

View File

@@ -101,7 +101,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -128,7 +128,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
installOptions := install.Options{ installOptions := install.Options{
BaseURL: rootArgs.defaults.BaseURL, BaseURL: rootArgs.defaults.BaseURL,
Version: bootstrapArgs.version, Version: bootstrapArgs.version,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
@@ -149,7 +149,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
// Source generation and secret config // Source generation and secret config
secretOpts := sourcesecret.Options{ secretOpts := sourcesecret.Options{
Name: bootstrapArgs.secretName, Name: bootstrapArgs.secretName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
TargetPath: gitArgs.path.String(), TargetPath: gitArgs.path.String(),
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile, ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
} }
@@ -161,15 +161,10 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
secretOpts.CAFilePath = bootstrapArgs.caFile secretOpts.CAFilePath = bootstrapArgs.caFile
} }
// Remove port of the given host when not syncing over HTTP/S to not assume port for protocol
// This _might_ be overwritten later on by e.g. --ssh-hostname
if repositoryURL.Scheme != "https" && repositoryURL.Scheme != "http" {
repositoryURL.Host = repositoryURL.Hostname()
}
// Configure repository URL to match auth config for sync. // Configure repository URL to match auth config for sync.
repositoryURL.User = nil repositoryURL.User = nil
repositoryURL.Scheme = "https" repositoryURL.Scheme = "https"
repositoryURL.Host = repositoryURL.Hostname()
} else { } else {
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm) secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(bootstrapArgs.keyAlgorithm)
secretOpts.Password = gitArgs.password secretOpts.Password = gitArgs.password
@@ -199,8 +194,8 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
// Sync manifest config // Sync manifest config
syncOpts := sync.Options{ syncOpts := sync.Options{
Interval: gitArgs.interval, Interval: gitArgs.interval,
Name: *kubeconfigArgs.Namespace, Name: rootArgs.namespace,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
URL: repositoryURL.String(), URL: repositoryURL.String(),
Branch: bootstrapArgs.branch, Branch: bootstrapArgs.branch,
Secret: bootstrapArgs.secretName, Secret: bootstrapArgs.secretName,
@@ -225,7 +220,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
bootstrap.WithBranch(bootstrapArgs.branch), bootstrap.WithBranch(bootstrapArgs.branch),
bootstrap.WithAuthor(bootstrapArgs.authorName, bootstrapArgs.authorEmail), bootstrap.WithAuthor(bootstrapArgs.authorName, bootstrapArgs.authorEmail),
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix), bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
bootstrap.WithKubeconfig(kubeconfigArgs), bootstrap.WithKubeconfig(rootArgs.kubeconfig, rootArgs.kubecontext),
bootstrap.WithPostGenerateSecretFunc(promptPublicKey), bootstrap.WithPostGenerateSecretFunc(promptPublicKey),
bootstrap.WithLogger(logger), bootstrap.WithLogger(logger),
bootstrap.WithCABundle(caBundle), bootstrap.WithCABundle(caBundle),

View File

@@ -125,7 +125,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -175,7 +175,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
installOptions := install.Options{ installOptions := install.Options{
BaseURL: rootArgs.defaults.BaseURL, BaseURL: rootArgs.defaults.BaseURL,
Version: bootstrapArgs.version, Version: bootstrapArgs.version,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
@@ -196,7 +196,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
// Source generation and secret config // Source generation and secret config
secretOpts := sourcesecret.Options{ secretOpts := sourcesecret.Options{
Name: bootstrapArgs.secretName, Name: bootstrapArgs.secretName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
TargetPath: githubArgs.path.ToSlash(), TargetPath: githubArgs.path.ToSlash(),
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile, ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
} }
@@ -221,8 +221,8 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
// Sync manifest config // Sync manifest config
syncOpts := sync.Options{ syncOpts := sync.Options{
Interval: githubArgs.interval, Interval: githubArgs.interval,
Name: *kubeconfigArgs.Namespace, Name: rootArgs.namespace,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Branch: bootstrapArgs.branch, Branch: bootstrapArgs.branch,
Secret: bootstrapArgs.secretName, Secret: bootstrapArgs.secretName,
TargetPath: githubArgs.path.ToSlash(), TargetPath: githubArgs.path.ToSlash(),
@@ -240,7 +240,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix), bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
bootstrap.WithProviderTeamPermissions(mapTeamSlice(githubArgs.teams, ghDefaultPermission)), bootstrap.WithProviderTeamPermissions(mapTeamSlice(githubArgs.teams, ghDefaultPermission)),
bootstrap.WithReadWriteKeyPermissions(githubArgs.readWriteKey), bootstrap.WithReadWriteKeyPermissions(githubArgs.readWriteKey),
bootstrap.WithKubeconfig(kubeconfigArgs), bootstrap.WithKubeconfig(rootArgs.kubeconfig, rootArgs.kubecontext),
bootstrap.WithLogger(logger), bootstrap.WithLogger(logger),
bootstrap.WithCABundle(caBundle), bootstrap.WithCABundle(caBundle),
} }

View File

@@ -129,7 +129,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -186,7 +186,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
installOptions := install.Options{ installOptions := install.Options{
BaseURL: rootArgs.defaults.BaseURL, BaseURL: rootArgs.defaults.BaseURL,
Version: bootstrapArgs.version, Version: bootstrapArgs.version,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
@@ -207,7 +207,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
// Source generation and secret config // Source generation and secret config
secretOpts := sourcesecret.Options{ secretOpts := sourcesecret.Options{
Name: bootstrapArgs.secretName, Name: bootstrapArgs.secretName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
TargetPath: gitlabArgs.path.String(), TargetPath: gitlabArgs.path.String(),
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile, ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
} }
@@ -235,8 +235,8 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
// Sync manifest config // Sync manifest config
syncOpts := sync.Options{ syncOpts := sync.Options{
Interval: gitlabArgs.interval, Interval: gitlabArgs.interval,
Name: *kubeconfigArgs.Namespace, Name: rootArgs.namespace,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Branch: bootstrapArgs.branch, Branch: bootstrapArgs.branch,
Secret: bootstrapArgs.secretName, Secret: bootstrapArgs.secretName,
TargetPath: gitlabArgs.path.ToSlash(), TargetPath: gitlabArgs.path.ToSlash(),
@@ -254,7 +254,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix), bootstrap.WithCommitMessageAppendix(bootstrapArgs.commitMessageAppendix),
bootstrap.WithProviderTeamPermissions(mapTeamSlice(gitlabArgs.teams, glDefaultPermission)), bootstrap.WithProviderTeamPermissions(mapTeamSlice(gitlabArgs.teams, glDefaultPermission)),
bootstrap.WithReadWriteKeyPermissions(gitlabArgs.readWriteKey), bootstrap.WithReadWriteKeyPermissions(gitlabArgs.readWriteKey),
bootstrap.WithKubeconfig(kubeconfigArgs), bootstrap.WithKubeconfig(rootArgs.kubeconfig, rootArgs.kubecontext),
bootstrap.WithLogger(logger), bootstrap.WithLogger(logger),
bootstrap.WithCABundle(caBundle), bootstrap.WithCABundle(caBundle),
} }

View File

@@ -128,7 +128,7 @@ func fluxCheck() {
} }
func kubernetesCheck(constraints []string) bool { func kubernetesCheck(constraints []string) bool {
cfg, err := utils.KubeConfig(kubeconfigArgs) cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
logger.Failuref("Kubernetes client initialization failed: %s", err.Error()) logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
return false return false
@@ -176,7 +176,7 @@ func componentsCheck() bool {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeConfig, err := utils.KubeConfig(kubeconfigArgs) kubeConfig, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return false return false
} }
@@ -186,7 +186,7 @@ func componentsCheck() bool {
return false return false
} }
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return false return false
} }
@@ -194,7 +194,7 @@ func componentsCheck() bool {
ok := true ok := true
selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue}
var list v1.DeploymentList var list v1.DeploymentList
if err := kubeClient.List(ctx, &list, client.InNamespace(*kubeconfigArgs.Namespace), selector); err == nil { if err := kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace), selector); err == nil {
for _, d := range list.Items { for _, d := range list.Items {
if ref, err := buildComponentObjectRefs(d.Name); err == nil { if ref, err := buildComponentObjectRefs(d.Name); err == nil {
if err := statusChecker.Assess(ref...); err != nil { if err := statusChecker.Assess(ref...); err != nil {

View File

@@ -1,4 +1,3 @@
//go:build e2e
// +build e2e // +build e2e
/* /*
@@ -30,7 +29,7 @@ import (
) )
func TestCheckPre(t *testing.T) { func TestCheckPre(t *testing.T) {
jsonOutput, err := utils.ExecKubectlCommand(context.TODO(), utils.ModeCapture, *kubeconfigArgs.KubeConfig, *kubeconfigArgs.Context, "version", "--output", "json") jsonOutput, err := utils.ExecKubectlCommand(context.TODO(), utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, "version", "--output", "json")
if err != nil { if err != nil {
t.Fatalf("Error running utils.ExecKubectlCommand: %v", err.Error()) t.Fatalf("Error running utils.ExecKubectlCommand: %v", err.Error())
} }

View File

@@ -25,7 +25,10 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
memory "k8s.io/client-go/discovery/cached"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
"k8s.io/client-go/restmapper"
) )
var completionCmd = &cobra.Command{ var completionCmd = &cobra.Command{
@@ -39,7 +42,7 @@ func init() {
} }
func contextsCompletionFunc(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { func contextsCompletionFunc(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
rawConfig, err := kubeconfigArgs.ToRawKubeConfigLoader().RawConfig() rawConfig, err := utils.ClientConfig(rootArgs.kubeconfig, rootArgs.kubecontext).RawConfig()
if err != nil { if err != nil {
return completionError(err) return completionError(err)
} }
@@ -60,15 +63,16 @@ func resourceNamesCompletionFunc(gvk schema.GroupVersionKind) func(cmd *cobra.Co
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
cfg, err := utils.KubeConfig(kubeconfigArgs) cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return completionError(err) return completionError(err)
} }
mapper, err := kubeconfigArgs.ToRESTMapper() dc, err := discovery.NewDiscoveryClientForConfig(cfg)
if err != nil { if err != nil {
return completionError(err) return completionError(err)
} }
mapper := restmapper.NewDeferredDiscoveryRESTMapper(memory.NewMemCacheClient(dc))
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil { if err != nil {
@@ -82,7 +86,7 @@ func resourceNamesCompletionFunc(gvk schema.GroupVersionKind) func(cmd *cobra.Co
var dr dynamic.ResourceInterface var dr dynamic.ResourceInterface
if mapping.Scope.Name() == meta.RESTScopeNameNamespace { if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
dr = client.Resource(mapping.Resource).Namespace(*kubeconfigArgs.Namespace) dr = client.Resource(mapping.Resource).Namespace(rootArgs.namespace)
} else { } else {
dr = client.Resource(mapping.Resource) dr = client.Resource(mapping.Resource)
} }

View File

@@ -104,7 +104,7 @@ func (names apiType) upsertAndWait(object upsertWaitable, mutate func() error) e
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) // NB globals kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext) // NB globals
if err != nil { if err != nil {
return err return err
} }

View File

@@ -102,7 +102,7 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
alert := notificationv1.Alert{ alert := notificationv1.Alert{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: notificationv1.AlertSpec{ Spec: notificationv1.AlertSpec{
@@ -122,7 +122,7 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -94,7 +94,7 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
provider := notificationv1.Provider{ provider := notificationv1.Provider{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: notificationv1.ProviderSpec{ Spec: notificationv1.ProviderSpec{
@@ -118,7 +118,7 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -160,7 +160,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
helmRelease := helmv2.HelmRelease{ helmRelease := helmv2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: helmv2.HelmReleaseSpec{ Spec: helmv2.HelmReleaseSpec{
@@ -250,7 +250,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -101,7 +101,7 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
var policy = imagev1.ImagePolicy{ var policy = imagev1.ImagePolicy{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: objectName, Name: objectName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
}, },
Spec: imagev1.ImagePolicySpec{ Spec: imagev1.ImagePolicySpec{

View File

@@ -104,7 +104,7 @@ func createImageRepositoryRun(cmd *cobra.Command, args []string) error {
var repo = imagev1.ImageRepository{ var repo = imagev1.ImageRepository{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: objectName, Name: objectName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
}, },
Spec: imagev1.ImageRepositorySpec{ Spec: imagev1.ImageRepositorySpec{

View File

@@ -108,7 +108,7 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
var update = autov1.ImageUpdateAutomation{ var update = autov1.ImageUpdateAutomation{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: objectName, Name: objectName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
}, },
Spec: autov1.ImageUpdateAutomationSpec{ Spec: autov1.ImageUpdateAutomationSpec{

View File

@@ -143,7 +143,7 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
kustomization := kustomizev1.Kustomization{ kustomization := kustomizev1.Kustomization{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: kslabels, Labels: kslabels,
}, },
Spec: kustomizev1.KustomizationSpec{ Spec: kustomizev1.KustomizationSpec{
@@ -232,7 +232,7 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -109,7 +109,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
receiver := notificationv1.Receiver{ receiver := notificationv1.Receiver{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: notificationv1.ReceiverSpec{ Spec: notificationv1.ReceiverSpec{
@@ -130,7 +130,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -132,7 +132,7 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
opts := sourcesecret.Options{ opts := sourcesecret.Options{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile, ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
} }
@@ -176,14 +176,14 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if err := upsertSecret(ctx, kubeClient, s); err != nil { if err := upsertSecret(ctx, kubeClient, s); err != nil {
return err return err
} }
logger.Actionf("git secret '%s' created in '%s' namespace", name, *kubeconfigArgs.Namespace) logger.Actionf("git secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil return nil
} }

View File

@@ -80,7 +80,7 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
opts := sourcesecret.Options{ opts := sourcesecret.Options{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
Username: secretHelmArgs.username, Username: secretHelmArgs.username,
Password: secretHelmArgs.password, Password: secretHelmArgs.password,
@@ -100,7 +100,7 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -112,6 +112,6 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("helm secret '%s' created in '%s' namespace", name, *kubeconfigArgs.Namespace) logger.Actionf("helm secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil return nil
} }

View File

@@ -79,7 +79,7 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
opts := sourcesecret.Options{ opts := sourcesecret.Options{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
CAFilePath: secretTLSArgs.caFile, CAFilePath: secretTLSArgs.caFile,
CertFilePath: secretTLSArgs.certFile, CertFilePath: secretTLSArgs.certFile,
@@ -97,7 +97,7 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -109,6 +109,6 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("tls secret '%s' created in '%s' namespace", name, *kubeconfigArgs.Namespace) logger.Actionf("tls secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil return nil
} }

View File

@@ -120,7 +120,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
bucket := &sourcev1.Bucket{ bucket := &sourcev1.Bucket{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1.BucketSpec{ Spec: sourcev1.BucketSpec{
@@ -152,7 +152,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -165,7 +165,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: secretName, Name: secretName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
StringData: map[string]string{}, StringData: map[string]string{},

View File

@@ -193,7 +193,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
gitRepository := sourcev1.GitRepository{ gitRepository := sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1.GitRepositorySpec{ Spec: sourcev1.GitRepositorySpec{
@@ -235,7 +235,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -244,7 +244,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if sourceGitArgs.secretRef == "" { if sourceGitArgs.secretRef == "" {
secretOpts := sourcesecret.Options{ secretOpts := sourcesecret.Options{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile, ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
} }
switch u.Scheme { switch u.Scheme {

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
/* /*

View File

@@ -118,7 +118,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
helmRepository := &sourcev1.HelmRepository{ helmRepository := &sourcev1.HelmRepository{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1.HelmRepositorySpec{ Spec: sourcev1.HelmRepositorySpec{
@@ -147,7 +147,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -157,7 +157,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
secretName := fmt.Sprintf("helm-%s", name) secretName := fmt.Sprintf("helm-%s", name)
secretOpts := sourcesecret.Options{ secretOpts := sourcesecret.Options{
Name: secretName, Name: secretName,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Username: sourceHelmArgs.username, Username: sourceHelmArgs.username,
Password: sourceHelmArgs.password, Password: sourceHelmArgs.password,
CertFilePath: sourceHelmArgs.certFile, CertFilePath: sourceHelmArgs.certFile,

View File

@@ -159,7 +159,7 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -60,13 +60,13 @@ func (del deleteCommand) run(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@@ -85,7 +85,7 @@ func (del deleteCommand) run(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting %s %s in %s namespace", del.humanKind, name, *kubeconfigArgs.Namespace) logger.Actionf("deleting %s %s in %s namespace", del.humanKind, name, rootArgs.namespace)
err = kubeClient.Delete(ctx, del.object.asClientObject()) err = kubeClient.Delete(ctx, del.object.asClientObject())
if err != nil { if err != nil {
return err return err

View File

@@ -20,7 +20,6 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
@@ -74,19 +73,19 @@ func (export exportCommand) run(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportArgs.all { if exportArgs.all {
err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(*kubeconfigArgs.Namespace)) err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if export.list.len() == 0 { if export.list.len() == 0 {
return fmt.Errorf("no objects found in %s namespace", *kubeconfigArgs.Namespace) return fmt.Errorf("no objects found in %s namespace", rootArgs.namespace)
} }
for i := 0; i < export.list.len(); i++ { for i := 0; i < export.list.len(); i++ {
@@ -97,7 +96,7 @@ func (export exportCommand) run(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject()) err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject())

View File

@@ -19,7 +19,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -59,19 +58,19 @@ func (export exportWithSecretCommand) run(cmd *cobra.Command, args []string) err
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportArgs.all { if exportArgs.all {
err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(*kubeconfigArgs.Namespace)) err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if export.list.len() == 0 { if export.list.len() == 0 {
return fmt.Errorf("no objects found in %s namespace", *kubeconfigArgs.Namespace) return fmt.Errorf("no objects found in %s namespace", rootArgs.namespace)
} }
for i := 0; i < export.list.len(); i++ { for i := 0; i < export.list.len(); i++ {
@@ -89,7 +88,7 @@ func (export exportWithSecretCommand) run(cmd *cobra.Command, args []string) err
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject()) err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject())

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
package main package main

View File

@@ -135,14 +135,14 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !getArgs.allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(*kubeconfigArgs.Namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
if len(args) > 0 { if len(args) > 0 {
@@ -162,7 +162,7 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
if get.list.len() == 0 { if get.list.len() == 0 {
if !getAll { if !getAll {
logger.Failuref("no %s objects found in %s namespace", get.kind, *kubeconfigArgs.Namespace) logger.Failuref("no %s objects found in %s namespace", get.kind, rootArgs.namespace)
} }
return nil return nil
} }

View File

@@ -1,4 +1,3 @@
//go:build e2e
// +build e2e // +build e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build e2e
// +build e2e // +build e2e
package main package main

View File

@@ -131,7 +131,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
logger.Generatef("generating manifests") logger.Generatef("generating manifests")
} }
tmpDir, err := os.MkdirTemp("", *kubeconfigArgs.Namespace) tmpDir, err := os.MkdirTemp("", rootArgs.namespace)
if err != nil { if err != nil {
return err return err
} }
@@ -148,7 +148,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
opts := install.Options{ opts := install.Options{
BaseURL: installArgs.manifestsPath, BaseURL: installArgs.manifestsPath,
Version: installArgs.version, Version: installArgs.version,
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Components: components, Components: components,
Registry: installArgs.registry, Registry: installArgs.registry,
ImagePullSecret: installArgs.imagePullSecret, ImagePullSecret: installArgs.imagePullSecret,
@@ -156,7 +156,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
NetworkPolicy: installArgs.networkPolicy, NetworkPolicy: installArgs.networkPolicy,
LogLevel: installArgs.logLevel.String(), LogLevel: installArgs.logLevel.String(),
NotificationController: rootArgs.defaults.NotificationController, NotificationController: rootArgs.defaults.NotificationController,
ManifestFile: fmt.Sprintf("%s.yaml", *kubeconfigArgs.Namespace), ManifestFile: fmt.Sprintf("%s.yaml", rootArgs.namespace),
Timeout: rootArgs.timeout, Timeout: rootArgs.timeout,
ClusterDomain: installArgs.clusterDomain, ClusterDomain: installArgs.clusterDomain,
TolerationKeys: installArgs.tolerationKeys, TolerationKeys: installArgs.tolerationKeys,
@@ -183,21 +183,21 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Successf("manifests build completed") logger.Successf("manifests build completed")
logger.Actionf("installing components in %s namespace", *kubeconfigArgs.Namespace) logger.Actionf("installing components in %s namespace", rootArgs.namespace)
if installArgs.dryRun { if installArgs.dryRun {
logger.Successf("install dry-run finished") logger.Successf("install dry-run finished")
return nil return nil
} }
applyOutput, err := utils.Apply(ctx, kubeconfigArgs, filepath.Join(tmpDir, manifest.Path)) applyOutput, err := utils.Apply(ctx, rootArgs.kubeconfig, rootArgs.kubecontext, filepath.Join(tmpDir, manifest.Path))
if err != nil { if err != nil {
return fmt.Errorf("install failed: %w", err) return fmt.Errorf("install failed: %w", err)
} }
fmt.Fprintln(os.Stderr, applyOutput) fmt.Fprintln(os.Stderr, applyOutput)
kubeConfig, err := utils.KubeConfig(kubeconfigArgs) kubeConfig, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return fmt.Errorf("install failed: %w", err) return fmt.Errorf("install failed: %w", err)
} }

View File

@@ -1,4 +1,3 @@
//go:build e2e
// +build e2e // +build e2e
/* /*

View File

@@ -99,7 +99,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
cfg, err := utils.KubeConfig(kubeconfigArgs) cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@@ -278,7 +278,7 @@ func filterPrintLog(t *template.Template, l *ControllerLogEntry) {
if logsArgs.logLevel != "" && logsArgs.logLevel != l.Level || if logsArgs.logLevel != "" && logsArgs.logLevel != l.Level ||
logsArgs.kind != "" && strings.ToLower(logsArgs.kind) != strings.ToLower(l.Kind) || logsArgs.kind != "" && strings.ToLower(logsArgs.kind) != strings.ToLower(l.Kind) ||
logsArgs.name != "" && strings.ToLower(logsArgs.name) != strings.ToLower(l.Name) || logsArgs.name != "" && strings.ToLower(logsArgs.name) != strings.ToLower(l.Name) ||
!logsArgs.allNamespaces && strings.ToLower(*kubeconfigArgs.Namespace) != strings.ToLower(l.Namespace) { !logsArgs.allNamespaces && strings.ToLower(rootArgs.namespace) != strings.ToLower(l.Namespace) {
return return
} }

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
/* /*

View File

@@ -21,13 +21,13 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"path/filepath"
"strings" "strings"
"time" "time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/term" "golang.org/x/term"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
"github.com/fluxcd/flux2/pkg/manifestgen/install" "github.com/fluxcd/flux2/pkg/manifestgen/install"
@@ -99,6 +99,9 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.`,
var logger = stderrLogger{stderr: os.Stderr} var logger = stderrLogger{stderr: os.Stderr}
type rootFlags struct { type rootFlags struct {
kubeconfig string
kubecontext string
namespace string
timeout time.Duration timeout time.Duration
verbose bool verbose bool
pollInterval time.Duration pollInterval time.Duration
@@ -106,26 +109,19 @@ type rootFlags struct {
} }
var rootArgs = NewRootFlags() var rootArgs = NewRootFlags()
var kubeconfigArgs = genericclioptions.NewConfigFlags(false)
func init() { func init() {
rootCmd.PersistentFlags().StringVarP(&rootArgs.namespace, "namespace", "n", rootArgs.defaults.Namespace,
"the namespace scope for this operation, can be set with FLUX_SYSTEM_NAMESPACE env var")
rootCmd.RegisterFlagCompletionFunc("namespace", resourceNamesCompletionFunc(corev1.SchemeGroupVersion.WithKind("Namespace")))
rootCmd.PersistentFlags().DurationVar(&rootArgs.timeout, "timeout", 5*time.Minute, "timeout for this operation") rootCmd.PersistentFlags().DurationVar(&rootArgs.timeout, "timeout", 5*time.Minute, "timeout for this operation")
rootCmd.PersistentFlags().BoolVar(&rootArgs.verbose, "verbose", false, "print generated objects") rootCmd.PersistentFlags().BoolVar(&rootArgs.verbose, "verbose", false, "print generated objects")
rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", "",
"absolute path to the kubeconfig file")
configureDefaultNamespace() rootCmd.PersistentFlags().StringVarP(&rootArgs.kubecontext, "context", "", "", "kubernetes context to use")
kubeconfigArgs.APIServer = nil // prevent AddFlags from configuring --server flag
kubeconfigArgs.Timeout = nil // prevent AddFlags from configuring --request-timeout flag, we have --timeout instead
kubeconfigArgs.AddFlags(rootCmd.PersistentFlags())
// Since some subcommands use the `-s` flag as a short version for `--silent`, we manually configure the server flag
// without the `-s` short version. While we're no longer on par with kubectl's flags, we maintain backwards compatibility
// on the CLI interface.
apiServer := ""
kubeconfigArgs.APIServer = &apiServer
rootCmd.PersistentFlags().StringVar(kubeconfigArgs.APIServer, "server", *kubeconfigArgs.APIServer, "The address and port of the Kubernetes API server")
rootCmd.RegisterFlagCompletionFunc("context", contextsCompletionFunc) rootCmd.RegisterFlagCompletionFunc("context", contextsCompletionFunc)
rootCmd.RegisterFlagCompletionFunc("namespace", resourceNamesCompletionFunc(corev1.SchemeGroupVersion.WithKind("Namespace")))
rootCmd.DisableAutoGenTag = true rootCmd.DisableAutoGenTag = true
rootCmd.SetOut(os.Stdout) rootCmd.SetOut(os.Stdout)
@@ -142,17 +138,30 @@ func NewRootFlags() rootFlags {
func main() { func main() {
log.SetFlags(0) log.SetFlags(0)
configureKubeconfig()
configureDefaultNamespace()
if err := rootCmd.Execute(); err != nil { if err := rootCmd.Execute(); err != nil {
logger.Failuref("%v", err) logger.Failuref("%v", err)
os.Exit(1) os.Exit(1)
} }
} }
func configureKubeconfig() {
switch {
case len(rootArgs.kubeconfig) > 0:
case len(os.Getenv("KUBECONFIG")) > 0:
rootArgs.kubeconfig = os.Getenv("KUBECONFIG")
default:
if home := homeDir(); len(home) > 0 {
rootArgs.kubeconfig = filepath.Join(home, ".kube", "config")
}
}
}
func configureDefaultNamespace() { func configureDefaultNamespace() {
*kubeconfigArgs.Namespace = rootArgs.defaults.Namespace
fromEnv := os.Getenv("FLUX_SYSTEM_NAMESPACE") fromEnv := os.Getenv("FLUX_SYSTEM_NAMESPACE")
if fromEnv != "" { if fromEnv != "" && rootArgs.namespace == rootArgs.defaults.Namespace {
kubeconfigArgs.Namespace = &fromEnv rootArgs.namespace = fromEnv
} }
} }

View File

@@ -1,4 +1,3 @@
//go:build e2e
// +build e2e // +build e2e
/* /*
@@ -36,7 +35,7 @@ func TestMain(m *testing.M) {
if err != nil { if err != nil {
panic(fmt.Errorf("error creating kube manager: '%w'", err)) panic(fmt.Errorf("error creating kube manager: '%w'", err))
} }
kubeconfigArgs.KubeConfig = &testEnv.kubeConfigPath rootArgs.kubeconfig = testEnv.kubeConfigPath
// Install Flux. // Install Flux.
output, err := executeCommand("install --components-extra=image-reflector-controller,image-automation-controller") output, err := executeCommand("install --components-extra=image-reflector-controller,image-automation-controller")
@@ -55,7 +54,7 @@ func TestMain(m *testing.M) {
// Delete namespace and wait for finalisation // Delete namespace and wait for finalisation
kubectlArgs := []string{"delete", "namespace", "flux-system"} kubectlArgs := []string{"delete", "namespace", "flux-system"}
_, err = utils.ExecKubectlCommand(context.TODO(), utils.ModeStderrOS, *kubeconfigArgs.KubeConfig, *kubeconfigArgs.Context, kubectlArgs...) _, err = utils.ExecKubectlCommand(context.TODO(), utils.ModeStderrOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
if err != nil { if err != nil {
panic(fmt.Errorf("delete namespace error:'%w'", err)) panic(fmt.Errorf("delete namespace error:'%w'", err))
} }
@@ -67,13 +66,13 @@ func TestMain(m *testing.M) {
func setupTestNamespace(namespace string) (func(), error) { func setupTestNamespace(namespace string) (func(), error) {
kubectlArgs := []string{"create", "namespace", namespace} kubectlArgs := []string{"create", "namespace", namespace}
_, err := utils.ExecKubectlCommand(context.TODO(), utils.ModeStderrOS, *kubeconfigArgs.KubeConfig, *kubeconfigArgs.Context, kubectlArgs...) _, err := utils.ExecKubectlCommand(context.TODO(), utils.ModeStderrOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return func() { return func() {
kubectlArgs := []string{"delete", "namespace", namespace} kubectlArgs := []string{"delete", "namespace", namespace}
utils.ExecKubectlCommand(context.TODO(), utils.ModeCapture, *kubeconfigArgs.KubeConfig, *kubeconfigArgs.Context, kubectlArgs...) utils.ExecKubectlCommand(context.TODO(), utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
}, nil }, nil
} }

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
/* /*
@@ -43,8 +42,7 @@ func TestMain(m *testing.M) {
panic(fmt.Errorf("error creating kube manager: '%w'", err)) panic(fmt.Errorf("error creating kube manager: '%w'", err))
} }
testEnv = km testEnv = km
// rootArgs.kubeconfig = testEnv.kubeConfigPath rootArgs.kubeconfig = testEnv.kubeConfigPath
kubeconfigArgs.KubeConfig = &testEnv.kubeConfigPath
// Run tests // Run tests
code := m.Run() code := m.Run()

View File

@@ -75,13 +75,13 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@@ -94,7 +94,7 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
logger.Actionf("annotating %s %s in %s namespace", reconcile.kind, name, *kubeconfigArgs.Namespace) logger.Actionf("annotating %s %s in %s namespace", reconcile.kind, name, rootArgs.namespace)
if err := requestReconciliation(ctx, kubeClient, namespacedName, reconcile.object); err != nil { if err := requestReconciliation(ctx, kubeClient, namespacedName, reconcile.object); err != nil {
return err return err
} }

View File

@@ -54,17 +54,17 @@ func reconcileAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
logger.Actionf("annotating Provider %s in %s namespace", name, *kubeconfigArgs.Namespace) logger.Actionf("annotating Provider %s in %s namespace", name, rootArgs.namespace)
var alertProvider notificationv1.Provider var alertProvider notificationv1.Provider
err = kubeClient.Get(ctx, namespacedName, &alertProvider) err = kubeClient.Get(ctx, namespacedName, &alertProvider)
if err != nil { if err != nil {

View File

@@ -54,13 +54,13 @@ func reconcileReceiverCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@@ -74,7 +74,7 @@ func reconcileReceiverCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
logger.Actionf("annotating Receiver %s in %s namespace", name, *kubeconfigArgs.Namespace) logger.Actionf("annotating Receiver %s in %s namespace", name, rootArgs.namespace)
if receiver.Annotations == nil { if receiver.Annotations == nil {
receiver.Annotations = map[string]string{ receiver.Annotations = map[string]string{
meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano), meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano),

View File

@@ -36,13 +36,13 @@ func (reconcile reconcileWithSourceCommand) run(cmd *cobra.Command, args []strin
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@@ -57,20 +57,20 @@ func (reconcile reconcileWithSourceCommand) run(cmd *cobra.Command, args []strin
if reconcile.object.reconcileSource() { if reconcile.object.reconcileSource() {
reconcileCmd, nsName := reconcile.object.getSource() reconcileCmd, nsName := reconcile.object.getSource()
nsCopy := *kubeconfigArgs.Namespace nsCopy := rootArgs.namespace
if nsName.Namespace != "" { if nsName.Namespace != "" {
*kubeconfigArgs.Namespace = nsName.Namespace rootArgs.namespace = nsName.Namespace
} }
err := reconcileCmd.run(nil, []string{nsName.Name}) err := reconcileCmd.run(nil, []string{nsName.Name})
if err != nil { if err != nil {
return err return err
} }
*kubeconfigArgs.Namespace = nsCopy rootArgs.namespace = nsCopy
} }
lastHandledReconcileAt := reconcile.object.lastHandledReconcileRequest() lastHandledReconcileAt := reconcile.object.lastHandledReconcileRequest()
logger.Actionf("annotating %s %s in %s namespace", reconcile.kind, name, *kubeconfigArgs.Namespace) logger.Actionf("annotating %s %s in %s namespace", reconcile.kind, name, rootArgs.namespace)
if err := requestReconciliation(ctx, kubeClient, namespacedName, reconcile.object); err != nil { if err := requestReconciliation(ctx, kubeClient, namespacedName, reconcile.object); err != nil {
return err return err
} }

View File

@@ -72,13 +72,13 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
listOpts = append(listOpts, client.InNamespace(*kubeconfigArgs.Namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
if len(args) > 0 { if len(args) > 0 {
listOpts = append(listOpts, client.MatchingFields{ listOpts = append(listOpts, client.MatchingFields{
"metadata.name": args[0], "metadata.name": args[0],
@@ -91,12 +91,12 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
} }
if resume.list.len() == 0 { if resume.list.len() == 0 {
logger.Failuref("no %s objects found in %s namespace", resume.kind, *kubeconfigArgs.Namespace) logger.Failuref("no %s objects found in %s namespace", resume.kind, rootArgs.namespace)
return nil return nil
} }
for i := 0; i < resume.list.len(); i++ { for i := 0; i < resume.list.len(); i++ {
logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, resume.list.resumeItem(i).asClientObject().GetName(), *kubeconfigArgs.Namespace) logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, resume.list.resumeItem(i).asClientObject().GetName(), rootArgs.namespace)
resume.list.resumeItem(i).setUnsuspended() resume.list.resumeItem(i).setUnsuspended()
if err := kubeClient.Update(ctx, resume.list.resumeItem(i).asClientObject()); err != nil { if err := kubeClient.Update(ctx, resume.list.resumeItem(i).asClientObject()); err != nil {
return err return err
@@ -105,7 +105,7 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Name: resume.list.resumeItem(i).asClientObject().GetName(), Name: resume.list.resumeItem(i).asClientObject().GetName(),
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
} }
logger.Waitingf("waiting for %s reconciliation", resume.kind) logger.Waitingf("waiting for %s reconciliation", resume.kind)

View File

@@ -69,11 +69,11 @@ func isReady(ctx context.Context, kubeClient client.Client,
func buildComponentObjectRefs(components ...string) ([]object.ObjMetadata, error) { func buildComponentObjectRefs(components ...string) ([]object.ObjMetadata, error) {
var objRefs []object.ObjMetadata var objRefs []object.ObjMetadata
for _, deployment := range components { for _, deployment := range components {
objRefs = append(objRefs, object.ObjMetadata{ objMeta, err := object.CreateObjMetadata(rootArgs.namespace, deployment, schema.GroupKind{Group: "apps", Kind: "Deployment"})
Namespace: *kubeconfigArgs.Namespace, if err != nil {
Name: deployment, return nil, err
GroupKind: schema.GroupKind{Group: "apps", Kind: "Deployment"}, }
}) objRefs = append(objRefs, objMeta)
} }
return objRefs, nil return objRefs, nil
} }

View File

@@ -69,13 +69,13 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
listOpts = append(listOpts, client.InNamespace(*kubeconfigArgs.Namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
if len(args) > 0 { if len(args) > 0 {
listOpts = append(listOpts, client.MatchingFields{ listOpts = append(listOpts, client.MatchingFields{
"metadata.name": args[0], "metadata.name": args[0],
@@ -88,12 +88,12 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
} }
if suspend.list.len() == 0 { if suspend.list.len() == 0 {
logger.Failuref("no %s objects found in %s namespace", suspend.kind, *kubeconfigArgs.Namespace) logger.Failuref("no %s objects found in %s namespace", suspend.kind, rootArgs.namespace)
return nil return nil
} }
for i := 0; i < suspend.list.len(); i++ { for i := 0; i < suspend.list.len(); i++ {
logger.Actionf("suspending %s %s in %s namespace", suspend.humanKind, suspend.list.item(i).asClientObject().GetName(), *kubeconfigArgs.Namespace) logger.Actionf("suspending %s %s in %s namespace", suspend.humanKind, suspend.list.item(i).asClientObject().GetName(), rootArgs.namespace)
suspend.list.item(i).setSuspended() suspend.list.item(i).setSuspended()
if err := kubeClient.Update(ctx, suspend.list.item(i).asClientObject()); err != nil { if err := kubeClient.Update(ctx, suspend.list.item(i).asClientObject()); err != nil {
return err return err

View File

@@ -27,10 +27,8 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/cli-runtime/pkg/resource"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils" "github.com/fluxcd/flux2/internal/utils"
@@ -41,26 +39,20 @@ import (
) )
var traceCmd = &cobra.Command{ var traceCmd = &cobra.Command{
Use: "trace <resource> <name> [<name> ...]", Use: "trace [name]",
Short: "Trace in-cluster objects throughout the GitOps delivery pipeline", Short: "Trace an in-cluster object throughout the GitOps delivery pipeline",
Long: `The trace command shows how one or more objects are managed by Flux, Long: `The trace command shows how an object is managed by Flux,
from which source and revision they come, and what the latest reconciliation status is. from which source and revision it comes, and what's the latest reconciliation status.'`,
You can also trace multiple objects with different resource kinds using <resource>/<name> multiple times.`,
Example: ` # Trace a Kubernetes Deployment Example: ` # Trace a Kubernetes Deployment
flux trace -n apps deployment my-app flux trace my-app --kind=deployment --api-version=apps/v1 --namespace=apps
# Trace a Kubernetes Pod and a config map # Trace a Kubernetes Pod
flux trace -n redis pod/redis-master-0 cm/redis flux trace redis-master-0 --kind=pod --api-version=v1 -n redis
# Trace a Kubernetes global object # Trace a Kubernetes global object
flux trace namespace redis flux trace redis --kind=namespace --api-version=v1
# Trace a Kubernetes custom resource # Trace a Kubernetes custom resource
flux trace -n redis helmrelease redis
# API Version and Kind can also be specified explicitly
# Note that either both, kind and api-version, or neither have to be specified.
flux trace redis --kind=helmrelease --api-version=helm.toolkit.fluxcd.io/v2beta1 -n redis`, flux trace redis --kind=helmrelease --api-version=helm.toolkit.fluxcd.io/v2beta1 -n redis`,
RunE: traceCmdRun, RunE: traceCmdRun,
} }
@@ -81,43 +73,49 @@ func init() {
} }
func traceCmdRun(cmd *cobra.Command, args []string) error { func traceCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("object name is required")
}
name := args[0]
if traceArgs.kind == "" {
return fmt.Errorf("object kind is required (--kind)")
}
if traceArgs.apiVersion == "" {
return fmt.Errorf("object apiVersion is required (--api-version)")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var objects []*unstructured.Unstructured gv, err := schema.ParseGroupVersion(traceArgs.apiVersion)
if traceArgs.kind != "" || traceArgs.apiVersion != "" {
var obj *unstructured.Unstructured
obj, err = getObjectStatic(ctx, kubeClient, args)
objects = []*unstructured.Unstructured{obj}
} else {
objects, err = getObjectDynamic(args)
}
if err != nil { if err != nil {
return err return fmt.Errorf("invaild apiVersion: %w", err)
} }
return traceObjects(ctx, kubeClient, objects) obj := &unstructured.Unstructured{}
} obj.SetGroupVersionKind(schema.GroupVersionKind{
Group: gv.Group,
Version: gv.Version,
Kind: traceArgs.kind,
})
func traceObjects(ctx context.Context, kubeClient client.Client, objects []*unstructured.Unstructured) error { objName := types.NamespacedName{
for i, obj := range objects { Namespace: rootArgs.namespace,
err := traceObject(ctx, kubeClient, obj) Name: name,
if err != nil { }
rootCmd.PrintErrf("failed to trace %v/%v in namespace %v: %v", obj.GetKind(), obj.GetName(), obj.GetNamespace(), err)
} err = kubeClient.Get(ctx, objName, obj)
if i < len(objects)-1 { if err != nil {
rootCmd.Println("---") return fmt.Errorf("failed to find object: %w", err)
}
} }
return nil
}
func traceObject(ctx context.Context, kubeClient client.Client, obj *unstructured.Unstructured) error {
if ks, ok := isOwnerManagedByFlux(ctx, kubeClient, obj, kustomizev1.GroupVersion.Group); ok { if ks, ok := isOwnerManagedByFlux(ctx, kubeClient, obj, kustomizev1.GroupVersion.Group); ok {
report, err := traceKustomization(ctx, kubeClient, ks, obj) report, err := traceKustomization(ctx, kubeClient, ks, obj)
if err != nil { if err != nil {
@@ -139,85 +137,14 @@ func traceObject(ctx context.Context, kubeClient client.Client, obj *unstructure
return fmt.Errorf("object not managed by Flux") return fmt.Errorf("object not managed by Flux")
} }
func getObjectStatic(ctx context.Context, kubeClient client.Client, args []string) (*unstructured.Unstructured, error) {
if len(args) < 1 {
return nil, fmt.Errorf("object name is required")
}
if traceArgs.kind == "" {
return nil, fmt.Errorf("object kind is required (--kind)")
}
if traceArgs.apiVersion == "" {
return nil, fmt.Errorf("object apiVersion is required (--api-version)")
}
gv, err := schema.ParseGroupVersion(traceArgs.apiVersion)
if err != nil {
return nil, fmt.Errorf("invaild apiVersion: %w", err)
}
obj := &unstructured.Unstructured{}
obj.SetGroupVersionKind(schema.GroupVersionKind{
Group: gv.Group,
Version: gv.Version,
Kind: traceArgs.kind,
})
objName := types.NamespacedName{
Namespace: *kubeconfigArgs.Namespace,
Name: args[0],
}
if err = kubeClient.Get(ctx, objName, obj); err != nil {
return nil, fmt.Errorf("failed to find object: %w", err)
}
return obj, nil
}
func getObjectDynamic(args []string) ([]*unstructured.Unstructured, error) {
r := resource.NewBuilder(kubeconfigArgs).
Unstructured().
NamespaceParam(*kubeconfigArgs.Namespace).DefaultNamespace().
ResourceTypeOrNameArgs(false, args...).
ContinueOnError().
Latest().
Do()
if err := r.Err(); err != nil {
if resource.IsUsageError(err) {
return nil, fmt.Errorf("either `<resource>/<name>` or `<resource> <name>` is required as an argument")
}
return nil, err
}
infos, err := r.Infos()
if err != nil {
return nil, fmt.Errorf("x: %v", err)
}
if len(infos) == 0 {
return nil, fmt.Errorf("failed to find object: %w", err)
}
objects := []*unstructured.Unstructured{}
for _, info := range infos {
obj := &unstructured.Unstructured{}
obj.Object, err = runtime.DefaultUnstructuredConverter.ToUnstructured(info.Object)
if err != nil {
return objects, err
}
objects = append(objects, obj)
}
return objects, nil
}
func traceKustomization(ctx context.Context, kubeClient client.Client, ksName types.NamespacedName, obj *unstructured.Unstructured) (string, error) { func traceKustomization(ctx context.Context, kubeClient client.Client, ksName types.NamespacedName, obj *unstructured.Unstructured) (string, error) {
ks := &kustomizev1.Kustomization{} ks := &kustomizev1.Kustomization{}
ksReady := &metav1.Condition{}
err := kubeClient.Get(ctx, ksName, ks) err := kubeClient.Get(ctx, ksName, ks)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to find kustomization: %w", err) return "", fmt.Errorf("failed to find kustomization: %w", err)
} }
ksReady := meta.FindStatusCondition(ks.Status.Conditions, fluxmeta.ReadyCondition) ksReady = meta.FindStatusCondition(ks.Status.Conditions, fluxmeta.ReadyCondition)
var ksRepository *sourcev1.GitRepository var ksRepository *sourcev1.GitRepository
var ksRepositoryReady *metav1.Condition var ksRepositoryReady *metav1.Condition
@@ -325,11 +252,12 @@ Status: Unknown
func traceHelm(ctx context.Context, kubeClient client.Client, hrName types.NamespacedName, obj *unstructured.Unstructured) (string, error) { func traceHelm(ctx context.Context, kubeClient client.Client, hrName types.NamespacedName, obj *unstructured.Unstructured) (string, error) {
hr := &helmv2.HelmRelease{} hr := &helmv2.HelmRelease{}
hrReady := &metav1.Condition{}
err := kubeClient.Get(ctx, hrName, hr) err := kubeClient.Get(ctx, hrName, hr)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to find HelmRelease: %w", err) return "", fmt.Errorf("failed to find HelmRelease: %w", err)
} }
hrReady := meta.FindStatusCondition(hr.Status.Conditions, fluxmeta.ReadyCondition) hrReady = meta.FindStatusCondition(hr.Status.Conditions, fluxmeta.ReadyCondition)
var hrChart *sourcev1.HelmChart var hrChart *sourcev1.HelmChart
var hrChartReady *metav1.Condition var hrChartReady *metav1.Condition

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
package main package main
@@ -10,7 +9,7 @@ import (
func TestTraceNoArgs(t *testing.T) { func TestTraceNoArgs(t *testing.T) {
cmd := cmdTestCase{ cmd := cmdTestCase{
args: "trace", args: "trace",
assert: assertError("either `<resource>/<name>` or `<resource> <name>` is required as an argument"), assert: assertError("object name is required"),
} }
cmd.runTestCmd(t) cmd.runTestCmd(t)
} }

View File

@@ -77,26 +77,27 @@ func treeKsCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
k := &kustomizev1.Kustomization{} k := &kustomizev1.Kustomization{}
err = kubeClient.Get(ctx, client.ObjectKey{ err = kubeClient.Get(ctx, client.ObjectKey{
Namespace: *kubeconfigArgs.Namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
}, k) }, k)
if err != nil { if err != nil {
return err return err
} }
kTree := tree.New(object.ObjMetadata{ kMeta, err := object.CreateObjMetadata(k.Namespace, k.Name,
Namespace: k.Namespace, schema.GroupKind{Group: kustomizev1.GroupVersion.Group, Kind: kustomizev1.KustomizationKind})
Name: k.Name, if err != nil {
GroupKind: schema.GroupKind{Group: kustomizev1.GroupVersion.Group, Kind: kustomizev1.KustomizationKind}, return err
}) }
kTree := tree.New(kMeta)
err = treeKustomization(ctx, kTree, k, kubeClient, treeKsArgs.compact) err = treeKustomization(ctx, kTree, k, kubeClient, treeKsArgs.compact)
if err != nil { if err != nil {
return err return err
@@ -272,5 +273,5 @@ func getHelmReleaseInventory(ctx context.Context, objectKey client.ObjectKey, ku
return nil, fmt.Errorf("failed to read the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err) return nil, fmt.Errorf("failed to read the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
} }
return object.UnstructuredSetToObjMetadataSet(objects), nil return object.UnstructuredsToObjMetas(objects)
} }

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
/* /*

View File

@@ -82,13 +82,13 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
logger.Actionf("deleting components in %s namespace", *kubeconfigArgs.Namespace) logger.Actionf("deleting components in %s namespace", rootArgs.namespace)
uninstallComponents(ctx, kubeClient, *kubeconfigArgs.Namespace, uninstallArgs.dryRun) uninstallComponents(ctx, kubeClient, rootArgs.namespace, uninstallArgs.dryRun)
logger.Actionf("deleting toolkit.fluxcd.io finalizers in all namespaces") logger.Actionf("deleting toolkit.fluxcd.io finalizers in all namespaces")
uninstallFinalizers(ctx, kubeClient, uninstallArgs.dryRun) uninstallFinalizers(ctx, kubeClient, uninstallArgs.dryRun)
@@ -97,7 +97,7 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
uninstallCustomResourceDefinitions(ctx, kubeClient, uninstallArgs.dryRun) uninstallCustomResourceDefinitions(ctx, kubeClient, uninstallArgs.dryRun)
if !uninstallArgs.keepNamespace { if !uninstallArgs.keepNamespace {
uninstallNamespace(ctx, kubeClient, *kubeconfigArgs.Namespace, uninstallArgs.dryRun) uninstallNamespace(ctx, kubeClient, rootArgs.namespace, uninstallArgs.dryRun)
} }
logger.Successf("uninstall finished") logger.Successf("uninstall finished")

View File

@@ -74,19 +74,19 @@ func versionCmdRun(cmd *cobra.Command, args []string) error {
info["flux"] = rootArgs.defaults.Version info["flux"] = rootArgs.defaults.Version
if !versionArgs.client { if !versionArgs.client {
kubeClient, err := utils.KubeClient(kubeconfigArgs) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue} selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue}
var list v1.DeploymentList var list v1.DeploymentList
if err := kubeClient.List(ctx, &list, client.InNamespace(*kubeconfigArgs.Namespace), selector); err != nil { if err := kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace), selector); err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
return fmt.Errorf("no deployments found in %s namespace", *kubeconfigArgs.Namespace) return fmt.Errorf("no deployments found in %s namespace", rootArgs.namespace)
} }
for _, d := range list.Items { for _, d := range list.Items {

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
/* /*

148
go.mod
View File

@@ -1,140 +1,42 @@
module github.com/fluxcd/flux2 module github.com/fluxcd/flux2
go 1.17 go 1.16
require ( require (
github.com/Masterminds/semver/v3 v3.1.0 github.com/Masterminds/semver/v3 v3.1.0
github.com/ProtonMail/go-crypto v0.0.0-20211221144345-a4f6767435ab github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7
github.com/cyphar/filepath-securejoin v0.2.2 github.com/cyphar/filepath-securejoin v0.2.2
github.com/fluxcd/go-git-providers v0.5.2 github.com/fluxcd/go-git-providers v0.4.0
github.com/fluxcd/helm-controller/api v0.15.0 github.com/fluxcd/helm-controller/api v0.14.1
github.com/fluxcd/image-automation-controller/api v0.19.0 github.com/fluxcd/image-automation-controller/api v0.18.0
github.com/fluxcd/image-reflector-controller/api v0.15.0 github.com/fluxcd/image-reflector-controller/api v0.14.0
github.com/fluxcd/kustomize-controller/api v0.19.1 github.com/fluxcd/kustomize-controller/api v0.18.2
github.com/fluxcd/notification-controller/api v0.20.1 github.com/fluxcd/notification-controller/api v0.19.0
github.com/fluxcd/pkg/apis/meta v0.10.2 github.com/fluxcd/pkg/apis/meta v0.10.1
github.com/fluxcd/pkg/runtime v0.12.3 github.com/fluxcd/pkg/runtime v0.12.2
github.com/fluxcd/pkg/ssa v0.10.0 github.com/fluxcd/pkg/ssa v0.3.1
github.com/fluxcd/pkg/ssh v0.3.1 github.com/fluxcd/pkg/ssh v0.0.5
github.com/fluxcd/pkg/untar v0.0.5 github.com/fluxcd/pkg/untar v0.0.5
github.com/fluxcd/pkg/version v0.0.1 github.com/fluxcd/pkg/version v0.0.1
github.com/fluxcd/source-controller/api v0.20.1 github.com/fluxcd/source-controller/api v0.19.2
github.com/go-errors/errors v1.4.0 // indirect
github.com/go-git/go-git/v5 v5.4.2 github.com/go-git/go-git/v5 v5.4.2
github.com/google/go-cmp v0.5.6 github.com/google/go-cmp v0.5.6
github.com/google/go-containerregistry v0.2.0 github.com/google/go-containerregistry v0.2.0
github.com/manifoldco/promptui v0.9.0 github.com/manifoldco/promptui v0.9.0
github.com/mattn/go-shellwords v1.0.12 github.com/mattn/go-shellwords v1.0.12
github.com/olekukonko/tablewriter v0.0.4 github.com/olekukonko/tablewriter v0.0.4
github.com/spf13/cobra v1.2.1 github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
k8s.io/api v0.23.1 k8s.io/api v0.22.2
k8s.io/apiextensions-apiserver v0.23.1 k8s.io/apiextensions-apiserver v0.22.2
k8s.io/apimachinery v0.23.1 k8s.io/apimachinery v0.22.2
k8s.io/cli-runtime v0.23.1 k8s.io/client-go v0.22.2
k8s.io/client-go v0.23.1 k8s.io/kubectl v0.21.1
k8s.io/kubectl v0.23.1 sigs.k8s.io/cli-utils v0.26.0
sigs.k8s.io/cli-utils v0.27.0 sigs.k8s.io/controller-runtime v0.10.2
sigs.k8s.io/controller-runtime v0.11.0 sigs.k8s.io/kustomize/api v0.8.10
sigs.k8s.io/kustomize/api v0.10.1
sigs.k8s.io/yaml v1.3.0 sigs.k8s.io/yaml v1.3.0
) )
require (
cloud.google.com/go v0.81.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect
github.com/fluxcd/pkg/apis/kustomize v0.3.1 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/fvbommel/sortorder v1.0.1 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-git/go-billy/v5 v5.3.1 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/go-github/v41 v41.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.6.8 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-runewidth v0.0.7 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday v1.5.2 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/stretchr/testify v1.7.0 // indirect
github.com/xanzy/go-gitlab v0.54.3 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/component-base v0.23.1 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
k8s.io/utils v0.0.0-20211208161948-7d6a63dca704 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect
)
// Fix for CVE-2020-29652: https://github.com/golang/crypto/commit/8b5274cf687fd9316b4108863654cc57385531e8
// Fix for CVE-2021-43565: https://github.com/golang/crypto/commit/5770296d904e90f15f38f77dfc2e43fdf5efc083
replace golang.org/x/crypto => golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3

605
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,6 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/cli-runtime/pkg/genericclioptions"
"sigs.k8s.io/cli-utils/pkg/object" "sigs.k8s.io/cli-utils/pkg/object"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/kustomize/api/filesys" "sigs.k8s.io/kustomize/api/filesys"
@@ -58,7 +57,8 @@ type PlainGitBootstrapper struct {
gpgPassphrase string gpgPassphrase string
gpgKeyID string gpgKeyID string
restClientGetter genericclioptions.RESTClientGetter kubeconfig string
kubecontext string
postGenerateSecret []PostGenerateSecretFunc postGenerateSecret []PostGenerateSecretFunc
@@ -167,12 +167,12 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
if _, err := os.Stat(kfile); err == nil { if _, err := os.Stat(kfile); err == nil {
// Apply the components and their patches // Apply the components and their patches
b.logger.Actionf("installing components in %q namespace", options.Namespace) b.logger.Actionf("installing components in %q namespace", options.Namespace)
if _, err := utils.Apply(ctx, b.restClientGetter, kfile); err != nil { if _, err := utils.Apply(ctx, b.kubeconfig, b.kubecontext, kfile); err != nil {
return err return err
} }
} else { } else {
// Apply the CRDs and controllers // Apply the CRDs and controllers
if _, err := utils.Apply(ctx, b.restClientGetter, componentsYAML); err != nil { if _, err := utils.Apply(ctx, b.kubeconfig, b.kubecontext, componentsYAML); err != nil {
return err return err
} }
} }
@@ -299,7 +299,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
// Apply to cluster // Apply to cluster
b.logger.Actionf("applying sync manifests") b.logger.Actionf("applying sync manifests")
if _, err := utils.Apply(ctx, b.restClientGetter, filepath.Join(b.git.Path(), kusManifests.Path)); err != nil { if _, err := utils.Apply(ctx, b.kubeconfig, b.kubecontext, filepath.Join(b.git.Path(), kusManifests.Path)); err != nil {
return err return err
} }
@@ -332,7 +332,7 @@ func (b *PlainGitBootstrapper) ReportKustomizationHealth(ctx context.Context, op
} }
func (b *PlainGitBootstrapper) ReportComponentsHealth(ctx context.Context, install install.Options, timeout time.Duration) error { func (b *PlainGitBootstrapper) ReportComponentsHealth(ctx context.Context, install install.Options, timeout time.Duration) error {
cfg, err := utils.KubeConfig(b.restClientGetter) cfg, err := utils.KubeConfig(b.kubeconfig, b.kubecontext)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -200,10 +200,8 @@ func (b *GitProviderBootstrapper) ReconcileSyncConfig(ctx context.Context, optio
if err != nil { if err != nil {
return err return err
} }
options.URL = syncURL options.URL = syncURL
} }
return b.PlainGitBootstrapper.ReconcileSyncConfig(ctx, options) return b.PlainGitBootstrapper.ReconcileSyncConfig(ctx, options)
} }
@@ -416,11 +414,14 @@ func (b *GitProviderBootstrapper) getOrganization(ctx context.Context, subOrgs [
func (b *GitProviderBootstrapper) getCloneURL(repository gitprovider.UserRepository, transport gitprovider.TransportType) (string, error) { func (b *GitProviderBootstrapper) getCloneURL(repository gitprovider.UserRepository, transport gitprovider.TransportType) (string, error) {
var url string var url string
if cloner, ok := repository.(gitprovider.CloneableURL); ok { if cloner, ok := repository.(gitprovider.CloneableURL); ok {
url = cloner.GetCloneURL("", transport) return cloner.GetCloneURL("", transport), nil
} else {
url = repository.Repository().GetCloneURL(transport)
} }
url = repository.Repository().GetCloneURL(transport)
// TODO(hidde): https://github.com/fluxcd/go-git-providers/issues/55
if strings.HasPrefix(url, "https://https://") {
url = strings.TrimPrefix(url, "https://")
}
var err error var err error
if transport == gitprovider.TransportTypeSSH && b.sshHostname != "" { if transport == gitprovider.TransportTypeSSH && b.sshHostname != "" {
if url, err = setHostname(url, b.sshHostname); err != nil { if url, err = setHostname(url, b.sshHostname); err != nil {

View File

@@ -1,4 +1,3 @@
//go:build unit
// +build unit // +build unit
package gogit package gogit

View File

@@ -19,7 +19,6 @@ package bootstrap
import ( import (
"github.com/fluxcd/flux2/internal/bootstrap/git" "github.com/fluxcd/flux2/internal/bootstrap/git"
"github.com/fluxcd/flux2/pkg/log" "github.com/fluxcd/flux2/pkg/log"
"k8s.io/cli-runtime/pkg/genericclioptions"
) )
type Option interface { type Option interface {
@@ -91,18 +90,21 @@ func (o commitMessageAppendixOption) applyGitProvider(b *GitProviderBootstrapper
o.applyGit(b.PlainGitBootstrapper) o.applyGit(b.PlainGitBootstrapper)
} }
func WithKubeconfig(rcg genericclioptions.RESTClientGetter) Option { func WithKubeconfig(kubeconfig, kubecontext string) Option {
return kubeconfigOption{ return kubeconfigOption{
rcg: rcg, kubeconfig: kubeconfig,
kubecontext: kubecontext,
} }
} }
type kubeconfigOption struct { type kubeconfigOption struct {
rcg genericclioptions.RESTClientGetter kubeconfig string
kubecontext string
} }
func (o kubeconfigOption) applyGit(b *PlainGitBootstrapper) { func (o kubeconfigOption) applyGit(b *PlainGitBootstrapper) {
b.restClientGetter = o.rcg b.kubeconfig = o.kubeconfig
b.kubecontext = o.kubecontext
} }
func (o kubeconfigOption) applyGitProvider(b *GitProviderBootstrapper) { func (o kubeconfigOption) applyGitProvider(b *GitProviderBootstrapper) {

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -26,9 +26,9 @@ import (
"github.com/fluxcd/pkg/ssa" "github.com/fluxcd/pkg/ssa"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/cli-runtime/pkg/genericclioptions"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling" "sigs.k8s.io/cli-utils/pkg/kstatus/polling"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/kustomize/api/konfig" "sigs.k8s.io/kustomize/api/konfig"
"github.com/fluxcd/flux2/pkg/manifestgen/kustomization" "github.com/fluxcd/flux2/pkg/manifestgen/kustomization"
@@ -36,12 +36,12 @@ import (
// Apply is the equivalent of 'kubectl apply --server-side -f'. // Apply is the equivalent of 'kubectl apply --server-side -f'.
// If the given manifest is a kustomization.yaml, then apply performs the equivalent of 'kubectl apply --server-side -k'. // If the given manifest is a kustomization.yaml, then apply performs the equivalent of 'kubectl apply --server-side -k'.
func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, manifestPath string) (string, error) { func Apply(ctx context.Context, kubeConfigPath string, kubeContext string, manifestPath string) (string, error) {
cfg, err := KubeConfig(rcg) cfg, err := KubeConfig(kubeConfigPath, kubeContext)
if err != nil { if err != nil {
return "", err return "", err
} }
restMapper, err := rcg.ToRESTMapper() restMapper, err := apiutil.NewDynamicRESTMapper(cfg)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -49,7 +49,7 @@ func Apply(ctx context.Context, rcg genericclioptions.RESTClientGetter, manifest
if err != nil { if err != nil {
return "", err return "", err
} }
kubePoller := polling.NewStatusPoller(kubeClient, restMapper, nil) kubePoller := polling.NewStatusPoller(kubeClient, restMapper)
resourceManager := ssa.NewResourceManager(kubeClient, kubePoller, ssa.Owner{ resourceManager := ssa.NewResourceManager(kubeClient, kubePoller, ssa.Owner{
Field: "flux", Field: "flux",

View File

@@ -37,8 +37,8 @@ import (
apiruntime "k8s.io/apimachinery/pkg/runtime" apiruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
sigyaml "k8s.io/apimachinery/pkg/util/yaml" sigyaml "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
@@ -107,8 +107,22 @@ func ExecKubectlCommand(ctx context.Context, mode ExecMode, kubeConfigPath strin
return "", nil return "", nil
} }
func KubeConfig(rcg genericclioptions.RESTClientGetter) (*rest.Config, error) { func ClientConfig(kubeConfigPath string, kubeContext string) clientcmd.ClientConfig {
cfg, err := rcg.ToRESTConfig() configFiles := SplitKubeConfigPath(kubeConfigPath)
configOverrides := clientcmd.ConfigOverrides{}
if len(kubeContext) > 0 {
configOverrides.CurrentContext = kubeContext
}
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{Precedence: configFiles},
&configOverrides,
)
}
func KubeConfig(kubeConfigPath string, kubeContext string) (*rest.Config, error) {
cfg, err := ClientConfig(kubeConfigPath, kubeContext).ClientConfig()
if err != nil { if err != nil {
return nil, fmt.Errorf("kubernetes configuration load failed: %w", err) return nil, fmt.Errorf("kubernetes configuration load failed: %w", err)
} }
@@ -138,10 +152,10 @@ func NewScheme() *apiruntime.Scheme {
return scheme return scheme
} }
func KubeClient(rcg genericclioptions.RESTClientGetter) (client.WithWatch, error) { func KubeClient(kubeConfigPath string, kubeContext string) (client.WithWatch, error) {
cfg, err := rcg.ToRESTConfig() cfg, err := KubeConfig(kubeConfigPath, kubeContext)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("kubernetes client initialization failed: %w", err)
} }
scheme := NewScheme() scheme := NewScheme()

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/helm-controller/releases/download/v0.15.0/helm-controller.crds.yaml - https://github.com/fluxcd/helm-controller/releases/download/v0.14.1/helm-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v0.15.0/helm-controller.deployment.yaml - https://github.com/fluxcd/helm-controller/releases/download/v0.14.1/helm-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.19.0/image-automation-controller.crds.yaml - https://github.com/fluxcd/image-automation-controller/releases/download/v0.18.0/image-automation-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.19.0/image-automation-controller.deployment.yaml - https://github.com/fluxcd/image-automation-controller/releases/download/v0.18.0/image-automation-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.15.0/image-reflector-controller.crds.yaml - https://github.com/fluxcd/image-reflector-controller/releases/download/v0.14.0/image-reflector-controller.crds.yaml
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.15.0/image-reflector-controller.deployment.yaml - https://github.com/fluxcd/image-reflector-controller/releases/download/v0.14.0/image-reflector-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.19.1/kustomize-controller.crds.yaml - https://github.com/fluxcd/kustomize-controller/releases/download/v0.18.2/kustomize-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.19.1/kustomize-controller.deployment.yaml - https://github.com/fluxcd/kustomize-controller/releases/download/v0.18.2/kustomize-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/notification-controller/releases/download/v0.20.1/notification-controller.crds.yaml - https://github.com/fluxcd/notification-controller/releases/download/v0.19.0/notification-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v0.20.1/notification-controller.deployment.yaml - https://github.com/fluxcd/notification-controller/releases/download/v0.19.0/notification-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/source-controller/releases/download/v0.20.1/source-controller.crds.yaml - https://github.com/fluxcd/source-controller/releases/download/v0.19.2/source-controller.crds.yaml
- https://github.com/fluxcd/source-controller/releases/download/v0.20.1/source-controller.deployment.yaml - https://github.com/fluxcd/source-controller/releases/download/v0.19.2/source-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,9 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/source-controller/releases/download/v0.20.1/source-controller.crds.yaml - https://github.com/fluxcd/source-controller/releases/download/v0.19.2/source-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.19.1/kustomize-controller.crds.yaml - https://github.com/fluxcd/kustomize-controller/releases/download/v0.18.2/kustomize-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v0.15.0/helm-controller.crds.yaml - https://github.com/fluxcd/helm-controller/releases/download/v0.14.1/helm-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v0.20.1/notification-controller.crds.yaml - https://github.com/fluxcd/notification-controller/releases/download/v0.19.0/notification-controller.crds.yaml
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.15.0/image-reflector-controller.crds.yaml - https://github.com/fluxcd/image-reflector-controller/releases/download/v0.14.0/image-reflector-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.19.0/image-automation-controller.crds.yaml - https://github.com/fluxcd/image-automation-controller/releases/download/v0.18.0/image-automation-controller.crds.yaml

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -1,4 +1,3 @@
//go:build !e2e
// +build !e2e // +build !e2e
/* /*

View File

@@ -58,7 +58,7 @@ func NewStatusChecker(kubeConfig *rest.Config, pollInterval time.Duration, timeo
pollInterval: pollInterval, pollInterval: pollInterval,
timeout: timeout, timeout: timeout,
client: c, client: c,
statusPoller: polling.NewStatusPoller(c, restMapper, nil), statusPoller: polling.NewStatusPoller(c, restMapper),
logger: log, logger: log,
}, nil }, nil
} }

View File

@@ -1,166 +0,0 @@
# RFC-0001 Memorandum on Flux Authorization
## Summary
This RFC describes in detail, for [Flux version 0.24][] (Nov 2021), how Flux determines which
operations are allowed to proceed, and how this interacts with Kubernetes' access control.
## Motivation
To this point, the Flux project has provided [examples of how to make a multi-tenant
system](https://github.com/fluxcd/flux2-multi-tenancy/tree/v0.1.0), but not explained exactly how
they relate to Flux's authorization model; nor has the authorization model itself been
documented. Further work on support for multi-tenancy, among other things, requires a full account
of Flux's authorization model as a baseline.
### Goals
- Give a comprehensive account of Flux's authorization model
### Non-Goals
- Justify the model as it stands; this RFC simply records the state as at v0.24.
## Flux's authorization model
The Flux controllers undertake operations as specified by custom resources of the kinds defined in
the [Flux API][]. Most of the operations are through the Kubernetes API. Authorization for
operations on external systems is not accounted for here.
Flux controllers defer to [Kubernetes' native RBAC][k8s-rbac] and [namespace isolation][k8s-ns] to
determine which operations are authorized, when processing the custom resources in the Flux API.
In general, **Kubernetes API operations are constrained by the service account under which each
controller pod runs**. In the [default deployment of Flux][flux-rbac] each controller has its own
service account; and, the service accounts for the Kustomize controller and Helm controller have the
[`cluster-admin` cluster role][k8s-cluster-admin] bound to it.
Both the Kustomize controller and the Helm controller create, update and delete arbitrary sets of
configuration that they take as user input. For example, a Kustomization object that references a
GitRepository is processed by taking whatever is in the specified Git repository and applying it to
the cluster. This is informally called "syncing", and these user-supplied configurations will be
called "sync configurations" in the following.
There are five types of access that have a distinct treatment with respect to RBAC and namespace
isolation:
- reading and writing the Flux API object to be processed
- accessing dependencies of a Flux API object; for example, a secret that holds a decryption key
- accessing Flux API objects related to the object being processed; for example, a GitRepository
referenced by a Kustomization
- creating, updating and deleting Flux API objects as part of processing; for example, each
`HelmRelease` object contains a template for a Helm chart spec, which the Helm controller uses to
create a `HelmChart` object
- creating, updating, deleting, and health-checking of arbitrary objects as specified by _sync
configurations_ (as mentioned above).
This table summarises how these operations are subject to RBAC and namespace isolation.
| Type of operation | Accessed via | Namespace isolation |
|------------------------------------------------|----------------------------|------------------------------|
| Reading and writing the object to be processed | Controller service account | N/A |
| Dependencies of object to be processed | Controller service account | Same namespace only |
| Access to related Flux API objects | Controller service account | Some cross-namespace refs[1] |
| CRUD of Flux API objects | Controller service account | Created in same namespace |
| CRUD and healthcheck of sync configurations | Impersonation[2] | As directed by spec[2] |
[1] See "Cross-namespace references" below<br>
[2] See "Impersonation" below
There are two related mechanisms that affect the service account used for the operations marked with
"Impersonation" above: "impersonation" and "remote apply". These are explained in the following
sections.
### Impersonation
The Kustomize controller and Helm controller both apply arbitrary sets of Kubernetes configuration
("_synced configuration_" as above) to a cluster. These controllers use the service account named in
the field `.spec.serviceAccountName` in the `Kustomization` and `HelmRelease` objects respectively,
while applying and health-checking the synced configuration. This mechanism is called
"impersonation".
The `.spec.serviceAccountName` field is optional. If empty, the controller's service account is
used.
### Remote apply
The Kustomize controller and Helm controller are able to apply a set of configuration to a cluster
other than the cluster in which they run. If the `Kustomization` or `HelmRelease` object [refers to
a secret containing a "kubeconfig" file][kubeconfig], the controller will construct a client using
that kubeconfig, and the client is used to apply the prepared set of configuration. The effect of
this is that the configuration will be applied as the user given in the kubeconfig; often this is a
user with the `cluster-admin` role bound to it, but not necessarily so.
All accesses that would use impersonation use the remote client instead.
### Cross-namespace references
Some Flux API kinds have fields which can refer to a Flux API object in another namespace. The Flux
controllers do not respect namespace isolation when dereferencing these fields. The following are
fields that are not restricted to the namespace of the containing object, listed by API kind.
| API kind | field | explanation |
|----------|-------|-------------|
| **`kustomizations.kustomize.toolkit.fluxcd.io/v1beta2`** | `.spec.dependsOn` | Items are references that can include a namespace |
| | `.spec.healthChecks` | Items are references that can include a namespace (note: these are accessed using impersonation) |
| | `.spec.sourceRef` | This is a reference that can include a namespace |
| | `.spec.targetNamespace` | This sets or overrides the namespace given in the top-most `kustomization.yaml` |
| **`helmreleases.helm.toolkit.fluxcd/v2beta1`** | `.spec.dependsOn` | Items are references that can include a namespace |
| | `.spec.targetNamespace` | This gives the namespace into which a Helm chart is installed (note: using impersonation) |
| | `.spec.storageNamespace` | This gives the namespace in which the record of a Helm install is created (note: using impersonation) |
| | `.spec.chart.spec.sourceRef` | This is a reference (in the created `HelmChart` object) that can include a namespace |
| **`alerts.notification.toolkit.fluxcd.io/v1beta1`** | `.spec.eventSources` | Items are references that can include a namespace |
| **`receivers.notification.toolkit.fluxcd.io/v1beta1`** | `.spec.resources` | Items in this field are references that can include a namespace |
| **`imagepolicies.image.toolkit.fluxcd.io/v1beta1`** | `.spec.imageRepositoryRef` | This reference can include a namespace[1] |
[1] This particular cross-namespace reference is subject to additional access control; see "Access
control for cross-namespace references" below.
Note that the field `.spec.sourceRef` of **`imageupdateautomation.image.toolkit.fluxcd.io`** does
_not_ include a namespace.
#### Access control for cross-namespace references
In v0.24, an `ImagePolicy` object can refer to a `ImageRepository` object in another
namespace. Unlike most cross-namespace references, the controller processing `ImagePolicy` objects
applies additional access control, as given in the referenced `ImageRepository`: the field
[`.spec.accessFrom`][access-from-ref] grants access to the namespaces selected therein. Access is
denied unless granted.
## Security considerations
### Impersonation is optional
Flux does not insist on a service account to be supplied in `Kustomization` and `HelmRelease`
specifications, and the default is to use the controller's service account. That means a user with
the ability to create either of those objects can trivially arrange for a configuration to be
applied with the controller service account, which in the default deployment of Flux will have
`cluster-admin` bound to it. This represents a privilege escalation vulnerability in the default
deployment of Flux. To guard against it, an admission controller can be used to make the
`.spec.serviceAccountName` field mandatory; an example which uses Kyverno is given in [the
multi-tenancy implementation][multi-tenancy-eg].
### Cross-namespace references side-step namespace isolation
`HelmRelease` and `Kustomization` objects can refer to `GitRepository`, `HelmRepository`, or
`Bucket` (collectively "sources") in any other namespace. The referenced objects are accessed
through the controller's service account, which by default has `cluster-admin` bound to it. This
means all sources in a cluster are by default usable as a synced configuration, from any
namespace. To restrict access, an admission controller can be used to block cross-namespace
references; the [example using Kyverno][multi-tenancy-eg] from above also does this.
## References
- [CVE-2021-41254](https://github.com/fluxcd/kustomize-controller/security/advisories/GHSA-35rf-v2jv-gfg7)
"Privilege escalation to cluster admin on multi-tenant environments" was fixed in flux2 **v0.15.0**.
[Flux version 0.24]: https://github.com/fluxcd/flux2/releases/tag/v0.24.0
[serviceAccountName]: https://fluxcd.io/docs/components/kustomize/api/#kustomize.toolkit.fluxcd.io/v1beta2.KustomizationSpec
[kubeconfig]: https://fluxcd.io/docs/components/kustomize/api/#kustomize.toolkit.fluxcd.io/v1beta2.KubeConfig
[access-from-ref]: https://fluxcd.io/docs/components/image/imagerepositories/#allow-cross-namespace-references
[Flux API]: https://fluxcd.io/docs/components/
[flux-rbac]: https://github.com/fluxcd/flux2/tree/v0.24.0/manifests/rbac
[k8s-ns]: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
[k8s-rbac]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
[k8s-cluster-admin]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles
[multi-tenancy-eg]: https://github.com/fluxcd/flux2-multi-tenancy/blob/main/infrastructure/kyverno-policies/flux-multi-tenancy.yaml

View File

@@ -0,0 +1,225 @@
# RFC-0004 Flux Multi-Tenancy
**Status:** provisional
**Creation date:** 2021-11-15
**Last update:** 2021-12-17
## Summary
This RFC explains the mechanisms available in Flux for implementing multi-tenancy, defines two
models for multi-tenancy, and gives reference implementations for those models.
## Motivation
To this point, the Flux project has provided [examples of multi-tenancy][mt], but not explained exactly
how they relate to Flux's authorisation model. This RFC explains two multi-tenancy implementations,
their security properties, and how they are implemented within the authorisation model
as defined in [RFC-0001](https://github.com/fluxcd/flux2/pull/2212).
### Goals
- Explain the mechanisms available in Flux for supporting multi-tenancy
- Define two models for multi-tenancy, "soft multi-tenancy" and "hard multi-tenancy".
- Explain when each model is appropriate.
- Describe a reference implementation of each model with Flux.
### Non-Goals
- Give an exhaustive account of multi-tenancy implementations in general.
- Provide an [end-to-end workflow][mt] of
how to set up multi-tenancy with Flux.
## Introduction
Flux allows different organizations and/or teams to share the same Kubernetes control plane; this is
referred to as "multi-tenancy". To make this safe, Flux supports segmentation and isolation of
resources by using namespaces and role-based access control ("RBAC"), and integrating with
Kubernetes Cluster API.
The following subsections explain the existing mechanisms used for safe multi-tenancy.
### Flux's authorisation model
Flux defers to Kubernetes' native RBAC to specify which operations are authorised when processing
the custom resources in the Flux API. By default, this means operations are constrained by the
service account under which the controllers run, which (again, by default) has the `cluster-admin`
role bound to it. This is convenient for a deployment in which all users are trusted.
In a multi-tenant deployment, each tenant needs to be restricted in the operations that can be done
on their behalf. Since tenants control Flux via its API objects, this becomes a matter of attaching
RBAC rules to Flux API objects. There are two mechanisms that do this, "impersonation" and "remote
apply".
#### Impersonation
The Kustomize controller and Helm controller both apply arbitrary sets of Kubernetes configuration
to a cluster. These controllers are subject to authorisation on two counts:
- when accessing Kubernetes resources that are needed for a
particular "apply" operation -- for example, a secret referenced in
the field `.spec.valuesFrom` in a `HelmRelease`;
- when creating, watching, updating and deleting Kubernetes resources
in the process of applying a piece of configuration.
To give users control over this authorisation, these two controllers will _impersonate_ (assume the
identity of) a service account mentioned in the apply specification (e.g., the field
`.spec.serviceAccountName` in a [`Kustomization` object][kcsa]
or in a [`HelmRelease` object][hcsa]) for both accessing resources and applying configuration.
This lets a user constrain the operations mentioned above with RBAC.
As stated in [RFC-0003](https://github.com/fluxcd/flux2/pull/2093),
the platform admins can configure Flux to enforce service account impersonation
by setting a default service account name when `.spec.serviceAccountName` is not specified.
#### Remote apply
The Kustomize controller and Helm controller are able to apply a set of configuration to a cluster
other than the cluster in which they run. If the specification [refers to a secret containing a
"kubeconfig" file][kubeconfig], the controller will construct a client using that kubeconfig, then
the client used to apply the specified set of configuration. The effect of this is that the
configuration will be applied as the user given in the kubeconfig; often this is a user with the
`cluster-admin` role bound to it, but not necessarily so.
## Assumptions made by the multi-tenancy models
### User Roles
The tenancy models assume two types of user: platform admins and tenants.
Besides installing Flux, all the other operations (deploy applications, configure ingress, policies, etc)
do not require users to have direct access to the Kubernetes API. Flux acts as a proxy between users and
the Kubernetes API, using Git as source of truth for the cluster desired state. Changes to the clusters
and workloads configuration can be made in a collaborative manner, where the various teams responsible for
the delivery process propose, review and approve changes via pull request workflows.
#### Platform Admins
The platform admins have unrestricted access to Kubernetes API.
They are responsible for installing Flux and granting Flux
access to the sources (Git, Helm, OCI repositories) that make up the cluster(s) control plane desired state.
The repository(s) owned by the platform admins are reconciled on the cluster(s) by Flux, under
the [cluster-admin](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
Kubernetes cluster role.
Example of operations performed by platform admins:
- Bootstrap Flux onto cluster(s).
- Extend the Kubernetes API with custom resource definitions and validation webhooks.
- Configure various controllers for ingress, storage, logging, monitoring, progressive delivery, etc.
- Set up namespaces for tenants and define their level of access with Kubernetes RBAC.
- Onboard tenants by registering their Git repositories with Flux.
#### Tenants
The tenants have restricted access to the cluster(s) according to the Kubernetes RBAC configured
by the platform admins. The repositories owned by tenants are reconciled on the cluster(s) by Flux,
under the Kubernetes account(s) assigned by platform admins.
Example of operations performed by tenants:
- Register their sources with Flux (`GitRepositories`, `HelmRepositories` and `Buckets`).
- Deploy workload(s) into their namespace(s) using Flux custom resources (`Kustomizations` and `HelmReleases`).
- Automate application updates using Flux custom resources (`ImageRepositories`, `ImagePolicies` and `ImageUpdateAutomations`).
- Configure the release pipeline(s) using Flagger custom resources (`Canaries` and `MetricsTemplates`).
- Setup webhooks and alerting for their release pipeline(s) using Flux custom resources (`Receivers` and `Alerts`).
## Tenancy Models
The Kubernetes tenancy models supported by Flux are: soft multi-tenancy and hard multi-tenancy.
For an overview of the Kubernetes multi-tenant architecture please consult the following documentation:
- [Three Tenancy Models For Kubernetes](https://kubernetes.io/blog/2021/04/15/three-tenancy-models-for-kubernetes/)
- [GKE multi-tenancy overview](https://cloud.google.com/kubernetes-engine/docs/concepts/multitenancy-overview)
- [EKS multi-tenancy best practices](https://aws.github.io/aws-eks-best-practices/security/docs/multitenancy/)
### Soft Multi-Tenancy
With soft multi-tenancy, the platform admins use Kubernetes constructs such as namespaces, accounts,
roles and role bindings to create a logical separation between tenants.
When Flux deploys workloads from a repository belonging to a tenant, it uses the Kubernetes account assigned to that
tenant to perform the git-to-cluster reconciliation. By leveraging Kubernetes RBAC, Flux can ensure
that the operations performed by tenants are restricted to their namespaces.
Note that with this model, tenants share cluster-wide resources such as
`ClusterRoles`, `CustomResourceDefinitions`, `IngressClasses`, `StorageClasses`,
and they cannot create or alter these resources.
If a tenant adds a cluster-scoped resource definition to their repository,
Flux will fail the git-to-cluster reconciliation due to Kubernetes RBAC restrictions.
To restrict the reconciliation of tenant's sources, a Kubernetes service account name can be specified
in Flux `Kustomizations` and `HelmReleases` under `.spec.serviceAccountName`. Please consult the Flux
documentation for more details:
- [Kustomization API: Role-based access control][kcsa]
- [HelmRelease API: Role-based access control][hcsa]
- [Flux multi-tenancy example repository][mt]
Note that with soft multi-tenancy, true tenant isolation requires security measures beyond Kubernetes RBAC.
Please refer to the Kubernetes [security considerations documentation](https://kubernetes.io/blog/2021/04/15/three-tenancy-models-for-kubernetes/#security-considerations)
for more details on how to harden shared clusters.
#### Tenants Onboarding
When onboarding tenants, platform admins have the option to assign namespaces, set
permissions and register the tenants main repositories onto clusters.
The Flux CLI offers an easy way of generating all the Kubernetes manifests needed to onboard tenants:
- `flux create tenant` command generates namespaces, service accounts and Kubernetes RBAC
with restricted access to the cluster resources, given tenants access only to their namespaces.
- `flux create secret git` command generates SSH keys used by Flux to clone the tenants repositories.
- `flux create source git` command generates the configuration that tells Flux which repositories belong to tenants.
- `flux create kustomization` command generates the configuration that tells Flux how to reconcile the manifests found in the tenants repositories.
Once the tenants main repositories are registered on the cluster(s), the tenants can configure their app delivery
in Git using Kubernetes namespace-scoped resources such as `Deployments`, `Services`, Flagger `Canaries`,
Flux `GitRepositories`, `Kustomizations`, `HelmRepositories`, `HelmReleases`, `ImageUpdateAutomations`,
`Alerts`, `Receivers`, etc.
### Hard Multi-Tenancy
With hard multi-tenancy, the platform admins create dedicated clusters for each tenant.
When the tenants's clusters are created with Kubernetes Cluster API, the Flux instance
installed on the management cluster is responsible for reconciling the cluster
definitions belonging to tenants.
To enable GitOps for the tenant's clusters, the platform admins can configure the Flux instance running on the
management cluster to connect to the tenant's cluster using the kubeconfig generated by the Cluster API provider
or by creating kubeconfig secrets for the clusters created by other means than Cluster API.
To configure Flux reconciliation of remote clusters, a Kubernetes secret containing a `kubeConfig` can be specified
in Flux `Kustomizations` and `HelmReleases` under `.spec.kubeConfig.secretRef`. Please consult the Flux API
documentation for more details:
- [Kustomization API: Remote Clusters](https://fluxcd.io/docs/components/kustomize/kustomization/#remote-clusters--cluster-api)
- [HelmRelease API: Remote Clusters](https://fluxcd.io/docs/components/helm/helmreleases/#remote-clusters--cluster-api)
Note that with hard multi-tenancy, tenants have full access to cluster-wide resources, so they have the option
to manage Flux independently of platform admins, by deploying a Flux instance on each cluster.
#### Caveats
When using a Kubernetes Cluster API provider, the `kubeConfig` secret is automatically generated and Flux can
make use of it without any manual actions. For clusters created by other means than Cluster API, the
platform team has to create the `kubeConfig` secrets to allow Flux access to the remote clusters.
As of Flux v0.24 (Nov 2021), we don't provide any guidance for cluster admins on how to generate the `kubeConfig` secrets.
## Implementation History
- Soft multi-tenancy based on service account impersonation was first released in flux2 **v0.0.1**.
- Generating namespaces and RBAC for defining tenants with `flux create tenant` was first released in flux2 **v0.1.0**.
- Hard multi-tenancy based on remote cluster reconciliation was first released in flux2 **v0.2.0**.
- Soft multi-tenancy end-to-end workflow example was first published on 27 Nov 2020 at
[fluxcd/flux2-multi-tenancy](https://github.com/fluxcd/flux2-multi-tenancy).
- Soft multi-tenancy [CVE-2021-41254](https://github.com/fluxcd/kustomize-controller/security/advisories/GHSA-35rf-v2jv-gfg7)
"Privilege escalation to cluster admin on multi-tenant environments" was fixed in flux2 **v0.15.0**.
[mt]: https://github.com/fluxcd/flux2-multi-tenancy/tree/v0.1.0
[kcsa]: https://fluxcd.io/docs/components/kustomize/kustomization/#role-based-access-control
[hcsa]: https://fluxcd.io/docs/components/helm/helmreleases/#role-based-access-control
[kubeconfig]: https://fluxcd.io/docs/components/kustomize/api/#kustomize.toolkit.fluxcd.io/v1beta2.KubeConfig

View File

@@ -1,112 +1,25 @@
module github.com/fluxcd/flux2/tests/azure module github.com/fluxcd/flux2/tests/azure
go 1.17 go 1.16
require ( require (
github.com/Azure/azure-event-hubs-go/v3 v3.3.13 github.com/Azure/azure-event-hubs-go/v3 v3.3.13
github.com/fluxcd/helm-controller/api v0.15.0 github.com/fluxcd/helm-controller/api v0.14.0
github.com/fluxcd/image-automation-controller/api v0.19.0 github.com/fluxcd/image-automation-controller/api v0.18.0
github.com/fluxcd/image-reflector-controller/api v0.15.0 github.com/fluxcd/image-reflector-controller/api v0.14.0
github.com/fluxcd/kustomize-controller/api v0.19.1 github.com/fluxcd/kustomize-controller/api v0.18.1
github.com/fluxcd/notification-controller/api v0.20.1 github.com/fluxcd/notification-controller/api v0.19.0
github.com/fluxcd/pkg/apis/meta v0.10.2 github.com/fluxcd/pkg/apis/meta v0.10.1
github.com/fluxcd/pkg/runtime v0.12.3 github.com/fluxcd/pkg/runtime v0.12.2
github.com/fluxcd/source-controller/api v0.20.1 github.com/fluxcd/source-controller/api v0.19.0
github.com/hashicorp/terraform-exec v0.14.0 github.com/hashicorp/terraform-exec v0.14.0
github.com/libgit2/git2go/v31 v31.6.1 github.com/libgit2/git2go/v31 v31.6.1
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/whilp/git-urls v1.0.0 github.com/whilp/git-urls v1.0.0
go.uber.org/multierr v1.6.0 go.uber.org/multierr v1.6.0
k8s.io/api v0.23.1 k8s.io/api v0.22.2
k8s.io/apimachinery v0.23.1 k8s.io/apimachinery v0.22.2
k8s.io/client-go v0.23.1 k8s.io/client-go v0.22.2
sigs.k8s.io/controller-runtime v0.11.0 sigs.k8s.io/controller-runtime v0.10.2
) )
require (
cloud.google.com/go v0.81.0 // indirect
cloud.google.com/go/storage v1.10.0 // indirect
github.com/Azure/azure-amqp-common-go/v3 v3.0.1 // indirect
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible // indirect
github.com/Azure/go-amqp v0.13.12 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/aws/aws-sdk-go v1.15.78 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/devigned/tab v0.1.1 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect
github.com/fluxcd/pkg/apis/kustomize v0.3.1 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/googleapis/gax-go/v2 v2.0.5 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter v1.5.3 // indirect
github.com/hashicorp/go-retryablehttp v0.6.8 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-uuid v1.0.1 // indirect
github.com/hashicorp/go-version v1.3.0 // indirect
github.com/hashicorp/terraform-json v0.12.0 // indirect
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jstemmer/go-junit-report v0.9.1 // indirect
github.com/klauspost/compress v1.11.2 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/ulikunitz/xz v0.5.8 // indirect
github.com/zclconf/go-cty v1.8.4 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 // indirect
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/api v0.44.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 // indirect
google.golang.org/grpc v1.40.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/apiextensions-apiserver v0.23.1 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
k8s.io/utils v0.0.0-20211208161948-7d6a63dca704 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
// Fix for CVE-2020-29652: https://github.com/golang/crypto/commit/8b5274cf687fd9316b4108863654cc57385531e8
// Fix for CVE-2021-43565: https://github.com/golang/crypto/commit/5770296d904e90f15f38f77dfc2e43fdf5efc083
replace golang.org/x/crypto => golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3

Some files were not shown because too many files have changed in this diff Show More