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

Compare commits

..

101 Commits

Author SHA1 Message Date
Hidde Beydals
e3d6461a80 Merge pull request #528 from fluxcd/update-components
Update helm-controller to v0.4.1
2020-11-30 13:21:29 +01:00
fluxcdbot
2bb582f7ed Update toolkit components 2020-11-30 12:10:44 +00:00
Stefan Prodan
2f9a52852f Merge pull request #527 from fluxcd/tenant-e2e
Add e2e test for create tenant
2020-11-30 12:25:31 +02:00
Stefan Prodan
137f083b4d Add e2e test for create tenant
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-30 12:16:01 +02:00
Stefan Prodan
11f4c54a40 Merge pull request #525 from fluxcd/fixes
Fix tenant and reconcile commands
2020-11-30 11:46:36 +02:00
Stefan Prodan
c813eaf6d1 Do not try to reconcile a suspended object
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-30 11:39:55 +02:00
Stefan Prodan
ffdaa9dfe9 Fix tenant service account binding
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-30 10:28:03 +02:00
Stefan Prodan
182928002b Merge pull request #526 from phillebaba/add-maintainer
Add Philip Laine to maintainer list
2020-11-30 10:27:29 +02:00
Philip Laine
7222af2b7e Add Philip Laine to maintainer list
Signed-off-by: Philip Laine <philip.laine@xenit.se>
2020-11-29 19:17:51 +01:00
Stefan Prodan
034ead5272 Merge pull request #521 from fluxcd/improve-install-script-arch-detection
Improve installer list match for arm arches
2020-11-29 14:19:48 +02:00
Aurel Canciu
eca1f19e95 Improve installer list match for arm arches
`uname -m` will print out architecture codenames based on UTS_MACHINE
and COMPAT_UTS_MACHINE kernel defined constants. These extra values will
ensure the right version of the arm binary is installed on most Linux
systems running on ARM CPUs.

Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-11-27 19:38:06 +02:00
Michael Bridgen
ec70c14649 Merge pull request #520 from fluxcd/fluxv2-maintainers
Note the shared Flux v2 maintainers and team
2020-11-27 16:05:07 +00:00
Michael Bridgen
65d906a735 Note the shared Flux v2 maintainers and team
Many of the GitOps Toolkit controllers will share maintainers with
this repo, acting as the central Flux v2 repo. For convenience of
tracking membership and applying permissions, we can share maintainers
by:

 - referring to the MAINTAINERS file here, from elsewhere;
 - making a GitHub team that tracks those shared maintainers.

This commit makes a note of this in the MAINTAINERS file, to inform
people of the arrangement, and remind them to keep the team up to
date.

Signed-off-by: Michael Bridgen <michael@weave.works>
2020-11-27 12:44:17 +00:00
Stefan Prodan
b981bae1db Merge pull request #519 from fluxcd/service-account
Add service account arg to create commands
2020-11-27 12:28:25 +02:00
Stefan Prodan
d2df9ccf33 Add service account arg to create commands
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-27 12:20:55 +02:00
Stefan Prodan
5e51f51449 Merge pull request #518 from fluxcd/docs-upgrade
Add upgrade docs to install guide
2020-11-27 12:20:07 +02:00
Stefan Prodan
2c044a27e4 Add upgrade docs to install guide
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-27 08:44:34 +02:00
Hidde Beydals
d274a1115e Merge pull request #516 from fluxcd/update-components
Update source-controller to v0.4.1
2020-11-26 19:27:32 +01:00
fluxcdbot
bfae2899f3 Update toolkit components 2020-11-26 18:16:36 +00:00
Stefan Prodan
5352a7e13a Merge pull request #513 from fluxcd/update-components
Update toolkit components to v0.4.0
2020-11-26 18:45:38 +02:00
fluxcdbot
c49f9ef26a Update toolkit components 2020-11-26 16:32:23 +00:00
Stefan Prodan
4a7376c5f5 Merge pull request #512 from fluxcd/suspend-sources
Implement suspend/resume commands for sources
2020-11-26 17:25:47 +02:00
Stefan Prodan
567ce7f987 Add suspend status to get sources commands
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-26 17:17:50 +02:00
Stefan Prodan
26bc0a8100 Add source suspend/resume commands to docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-26 16:45:25 +02:00
Stefan Prodan
e7ff319685 Add resume source commands
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-26 16:40:54 +02:00
Stefan Prodan
072138deff Add suspend source commands
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-26 16:22:47 +02:00
Stefan Prodan
dd8dc90c1e Update source-controller to v0.4.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-26 16:20:00 +02:00
Stefan Prodan
8f1da33375 Merge pull request #511 from fluxcd/kubectl
Set kubecontext and kubeconfig for kubectl exec
2020-11-26 12:04:46 +02:00
Stefan Prodan
c02fbc2794 Set kubecontext and kubeconfig for kubectl exec
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-26 11:53:08 +02:00
Stefan Prodan
371db07108 Merge pull request #506 from chanwit/sops-doc
Add a note not to apply SOPS encrypted secrets directly
2020-11-25 17:49:49 +02:00
Chanwit Kaewkasi
99f5dbf16b add a note not to apply encrypted secrets directly
Signed-off-by: Chanwit Kaewkasi <chanwit@gmail.com>
2020-11-25 22:26:52 +07:00
Stefan Prodan
0db06c8962 Merge pull request #505 from fluxcd/tenant-sa
Add service accounts to tenant command
2020-11-25 17:22:49 +02:00
Stefan Prodan
a8e5876b2e Add create tenant to CLI docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-25 16:42:52 +02:00
Stefan Prodan
8273851b73 Add service accounts to tenant command
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-25 16:39:00 +02:00
Stefan Prodan
c2967240bb Merge pull request #501 from mewzherder/patch-6
Update Upcoming events w/ Nov 30 talk
2020-11-25 16:38:35 +02:00
mewzherder
282a6270c8 Update Upcoming events w/ Nov 30 talk
Signed-off-by: mewzherder <tamao@weave.works>
2020-11-24 09:03:10 -08:00
Stefan Prodan
1b299fad90 Merge pull request #498 from fluxcd/gh-action
Add GitHub Action for Flux CLI
2020-11-23 19:15:34 +02:00
Stefan Prodan
aa8dced7ad Add GitHub Action for Flux CLI
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-23 17:58:06 +02:00
Stefan Prodan
050ba951b0 Merge pull request #496 from gtseres/main
Add reference to the bootstrap migration
2020-11-23 15:49:53 +02:00
George Tseres
5e47c16099 Update docs/guides/flux-v1-migration.md
Co-authored-by: Stefan Prodan <stefan.prodan@gmail.com>
Signed-off-by: gtseres <george.tseres@gmail.com>
2020-11-23 15:39:39 +02:00
George Tseres
902db4c732 Add reference to the bootstrap migration
Signed-off-by: gtseres <george.tseres@gmail.com>
2020-11-23 15:28:42 +02:00
Stefan Prodan
86462fbee6 Merge pull request #491 from fluxcd/hr-values-from
Add values-from arg to create helmrelease cmd
2020-11-23 11:57:34 +02:00
Stefan Prodan
48bed79439 Add values-from arg to create helmrelease cmd
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-23 11:29:35 +02:00
Stefan Prodan
26b61c2b6b Merge pull request #492 from fluxcd/hr-kustomize-generators
Add docs on how to use Kustomize to generate Helm values
2020-11-23 10:18:54 +02:00
Stefan Prodan
3b2253ddc0 Add docs on how to use Kustomize to generate Helm values
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-22 11:30:35 +02:00
Stefan Prodan
5ddcb39129 Merge pull request #487 from fluxcd/sops-aws
Add AWS IAM role example to SOPS docs
2020-11-20 15:34:59 +02:00
Stefan Prodan
59adef5bcc Add AWS IAM role example to SOPS docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-20 15:26:10 +02:00
Stefan Prodan
875aefc8dd Merge pull request #486 from relu/add-relu-to-maintainers
Add @relu to maintainers list
2020-11-20 15:20:35 +02:00
Aurel Canciu
0dbc9d213e Add @relu to maintainers list
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-11-20 15:03:15 +02:00
Hidde Beydals
9f4c53e321 Merge pull request #484 from fluxcd/source-reconcile-at
Utilize LastHandledReconcileAt for source reconcile commands
2020-11-20 13:35:27 +01:00
Hidde Beydals
3c8716f6ac Utilize LastHandledReconcileAt for reconcile cmds
Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-11-20 13:28:28 +01:00
Hidde Beydals
1a7f31ae2e Merge pull request #485 from fluxcd/update-components
Update toolkit component manifests to v0.3.0
2020-11-20 13:28:18 +01:00
fluxcdbot
64ad69acfe Update toolkit components 2020-11-20 12:21:02 +00:00
Stefan Prodan
9f47b55aa9 Merge pull request #474 from relu/adopt-k8s-conditions
Update components to v0.3.0
2020-11-20 13:46:11 +02:00
Aurel Canciu
53a1db0703 Adjustments to support new sa name in kustomize
Supporting changes in fluxcd/kustomize-controller#180

Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-11-20 13:36:36 +02:00
Aurel Canciu
2a789ec705 Refactor to adopt k8s standardized Condition type
Updates to use metav1.Condition type and removes references for
deprecated corev1.Condition* constants and uses the new k8s api/meta
helpers in place of the old pkg/apis/meta types.

Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-11-20 13:19:40 +02:00
Hidde Beydals
3047b25193 Merge pull request #476 from fluxcd/update-components
Update helm-controller to v0.2.2
2020-11-18 12:36:12 +01:00
fluxcdbot
f66399cdc0 Update toolkit components 2020-11-18 11:14:54 +00:00
Stefan Prodan
37fb0f632b Merge pull request #473 from fluxcd/update-components
Update helm-controller to v0.2.1
2020-11-17 13:59:54 +02:00
fluxcdbot
e5dd0c7ff8 Update toolkit components 2020-11-17 11:48:54 +00:00
Stefan Prodan
51392cd54c Merge pull request #468 from RossyWhite/fix-dryrun-option
Fix --dry-run option
2020-11-16 17:31:42 +02:00
RossyWhite
02bcb4ff3c Fix --dry-run option
Signed-off-by: RossyWhite <daikishiroi@gmail.com>
2020-11-16 18:03:08 +09:00
Stefan Prodan
d84297a5b5 Merge pull request #463 from fluxcd/update-components
Update source-controller to v0.2.2
2020-11-12 18:24:28 +02:00
fluxcdbot
c3876e30a9 Update toolkit components 2020-11-12 16:11:58 +00:00
Stefan Prodan
10711ed780 Merge pull request #462 from fluxcd/update-components
Update kustomize-controller to v0.2.2
2020-11-12 17:29:43 +02:00
fluxcdbot
de4e266e33 Update toolkit components 2020-11-12 15:17:44 +00:00
Stefan Prodan
15442969f8 Merge pull request #461 from fluxcd/fix-install-path
Fix cluster path in install docs
2020-11-12 16:30:08 +02:00
Stefan Prodan
bed48ada82 Fix cluster path in install docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-12 16:14:05 +02:00
Stefan Prodan
a66004f567 Merge pull request #458 from fluxcd/kind-update
Update engineerd/setup-kind to v0.5.0
2020-11-12 12:16:07 +02:00
Stefan Prodan
72a4e3b3b8 Update engineerd/setup-kind to v0.5.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-12 12:03:25 +02:00
Stefan Prodan
16761e4fca Merge pull request #455 from fluxcd/fix-gh-https
Fix GitHub bootstrap with token auth
2020-11-12 12:01:58 +02:00
Stefan Prodan
ba34a6d401 Fix GitHub bootstrap with token auth
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-12 09:47:04 +02:00
Stefan Prodan
23912e4091 Merge pull request #452 from fluxcd/terraform-provider
Add the Terraform provider to install docs
2020-11-11 17:26:18 +02:00
Stefan Prodan
17468cb5f5 Add the Terraform provider to install docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-11 17:16:14 +02:00
Stefan Prodan
5ea7aa0a75 Merge pull request #450 from fluxcd/ssh-host-github
Add token authentication option to bootstrap
2020-11-11 16:49:43 +02:00
Stefan Prodan
7792cd6a10 Add token authentication option to bootstrap
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-11 16:41:18 +02:00
Stefan Prodan
237d186207 Merge pull request #444 from arodus/patch-1
Fix create tenant command export
2020-11-11 14:27:59 +02:00
Sebastian Karasek
c41487598e Fix create tenant command export
Signed-off-by: Sebastian Karasek <sebastian@karasek.io>
2020-11-11 13:15:17 +01:00
Stefan Prodan
2c0aa3c3af Merge pull request #446 from fluxcd/helm-values-file
Add values file example to Helm docs
2020-11-11 11:46:45 +02:00
Stefan Prodan
cedb33b2b9 Add values file example to Helm docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-11 10:26:03 +02:00
Stefan Prodan
06a3aa2c60 Merge pull request #442 from fluxcd/helm-upgrade-guide-typo
docs: fix typo
2020-11-11 09:08:36 +02:00
Hidde Beydals
3fadc94711 docs: include releaseName in HelmRelease example
Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-11-10 18:27:06 +01:00
Hidde Beydals
61d02bf5e4 docs: fix typo
Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-11-10 18:20:05 +01:00
Stefan Prodan
a62976461e Merge pull request #439 from fluxcd/update-components
Update notification-controller to v0.2.1
2020-11-09 17:46:07 +02:00
fluxcdbot
d7a893acf9 Update toolkit components 2020-11-09 15:37:09 +00:00
Stefan Prodan
0c67e75fb6 Merge pull request #438 from fluxcd/check-print-images
List component images in check cmd
2020-11-09 17:12:13 +02:00
Stefan Prodan
e6b84c4cfc List components images in check cmd
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-09 16:10:06 +02:00
Stefan Prodan
5d2e793386 Merge pull request #437 from nguyenductoan/docs-fix-typo
docs: fix typo
2020-11-09 14:31:43 +02:00
nguyenductoan
f0517906b7 docs: fix typo
Signed-off-by: nguyenductoan <ductoan593@gmail.com>
2020-11-09 18:43:24 +07:00
Stefan Prodan
16fa167931 Merge pull request #435 from phillebaba/sops-azure-auth
Update authentication hint for Azure
2020-11-08 09:47:16 +02:00
Philip Laine
b036999b8c Update authentication hint for Azure
Signed-off-by: Philip Laine <philip.laine@xenit.se>
2020-11-07 16:05:18 +01:00
Stefan Prodan
1911766b7b Merge pull request #434 from fluxcd/target-namespace-ks
Add target namespace to create ks cmd
2020-11-07 14:14:57 +02:00
Stefan Prodan
9f7835d818 Add target namespace to create ks cmd
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-07 14:01:40 +02:00
Stefan Prodan
1df45e4857 Merge pull request #433 from fluxcd/customize-flux-manifests
Add customize Flux manifests section to install docs
2020-11-07 13:58:40 +02:00
Stefan Prodan
47a1743965 Add customize Flux manifests section to install docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-11-07 13:44:47 +02:00
Hidde Beydals
d5844bbdaa Merge pull request #430 from fluxcd/migration-title-fix
Rename migration menu items
2020-11-06 13:08:57 +01:00
Hidde Beydals
128c87ab33 Rename migration menu items
As they are used in the metadata, instead of the title from the
document.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-11-06 12:58:51 +01:00
Hidde Beydals
f4adcae79a Merge pull request #425 from plod/main
docs: fixing command for expected output
2020-11-05 13:09:18 +01:00
Daniel Morgan
ba4df070cf fixing command for expected output
The \ before the comment here means the subsequent lines end up getting commented out (and then not exported), see: https://stackoverflow.com/questions/9522631/how-to-put-a-line-comment-for-a-multi-line-command

Signed-off-by: Daniel Morgan <daniel@morgan.cymru>
2020-11-05 11:53:57 +00:00
Hidde Beydals
ce4ecfb388 Merge pull request #421 from fluxcd/update-roadmap
Update Helm v3 feature parity roadmap
2020-11-04 21:35:10 +01:00
Hidde Beydals
e6006e0833 Update Helm v3 feature parity roadmap
Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-11-04 21:21:58 +01:00
92 changed files with 2582 additions and 424 deletions

View File

@@ -21,9 +21,9 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.14.x
go-version: 1.15.x
- name: Setup Kubernetes
uses: engineerd/setup-kind@v0.4.0
uses: engineerd/setup-kind@v0.5.0
- name: Set outputs
id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"

View File

@@ -24,7 +24,7 @@ jobs:
with:
go-version: 1.15.x
- name: Setup Kubernetes
uses: engineerd/setup-kind@v0.4.0
uses: engineerd/setup-kind@v0.5.0
with:
image: kindest/node:v1.16.9
- name: Run test
@@ -136,6 +136,16 @@ jobs:
- name: flux delete source git
run: |
./bin/flux delete source git podinfo --silent
- name: flux create tenant
run: |
./bin/flux create tenant dev-team --with-namespace=apps
./bin/flux -n apps create source helm podinfo \
--url https://stefanprodan.github.io/podinfo
./bin/flux -n apps create hr podinfo-helm \
--source=HelmRepository/podinfo \
--chart=podinfo \
--chart-version="5.0.x" \
--service-account=dev-team
- name: flux check
run: |
./bin/flux check

View File

@@ -2,7 +2,17 @@ The maintainers are generally available in Slack at
https://cloud-native.slack.com in #flux (https://cloud-native.slack.com/messages/CLAJ40HV3)
(obtain an invitation at https://slack.cncf.io/).
These maintainers are shared with other Flux v2-related git
repositories under https://github.com/fluxcd, as noted in their
respective MAINTAINERS files.
For convenience, they are reflected in the GitHub team
@fluxcd/flux2-maintainers -- if the list here changes, that team also
should.
In alphabetical order:
Aurel Canciu, Sortlist <aurel@sortlist.com> (github: @relu, slack: relu)
Hidde Beydals, Weaveworks <hidde@weave.works> (github: @hiddeco, slack: hidde)
Philip Laine, Xenit <philip.laine@xenit.se> (github: @phillebaba, slack: phillebaba)
Stefan Prodan, Weaveworks <stefan@weave.works> (github: @stefanprodan, slack: stefanprodan)

View File

@@ -109,8 +109,6 @@ Depending on what you want to do, some of the following bits might be your first
### Upcoming Events
- 2 Nov 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 2 with Leigh Capili](https://www.meetup.com/GitOps-Community/events/273934676/)
- 12-13 Nov 2020 - [GitOps Days EMEA](https://www.gitopsdays.com/) with talks and workshops on migrating to Flux v2 and Helm Controller
- 19 Nov 2020 - [KubeCon NA: Progressive Delivery Techniques with Flagger and Flux v2 with Stefan Prodan](https://kccncna20.sched.com/event/1b04f8408b49976b843a5d0019cb8112)
- 30 Nov 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 3 with Leigh Capili](https://www.meetup.com/Weave-User-Group/events/274657228/)
We are looking forward to seeing you with us!

6
action/Dockerfile Normal file
View File

@@ -0,0 +1,6 @@
FROM stefanprodan/alpine-base:latest
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

25
action/README.md Normal file
View File

@@ -0,0 +1,25 @@
# Flux GitHub Action
Example workflow:
```yaml
name: e2e
on:
push:
branches:
- '*'
jobs:
kubernetes:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Flux CLI
uses: fluxcd/flux2/action@main
- name: Setup Kubernetes Kind
uses: engineerd/setup-kind@v0.5.0
- name: Install Flux in Kubernetes Kind
run: flux install
```

15
action/action.yml Normal file
View File

@@ -0,0 +1,15 @@
name: 'kustomize'
description: 'A GitHub Action for running Flux commands'
author: 'Flux project'
branding:
icon: 'command'
color: 'blue'
inputs:
version:
description: 'strict semver'
required: false
runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.version }}

40
action/entrypoint.sh Executable file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Copyright 2020 The Flux authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
VERSION=$1
if [ -z $VERSION ]; then
# Find latest release if no version is specified
VERSION=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest -sL | grep tag_name | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
fi
# Download linux binary
BIN_URL="https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_amd64.tar.gz"
curl -sL $BIN_URL | tar xz
# Copy binary to GitHub runner
mkdir -p $GITHUB_WORKSPACE/bin
cp ./flux $GITHUB_WORKSPACE/bin
chmod +x $GITHUB_WORKSPACE/bin/flux
# Print version
$GITHUB_WORKSPACE/bin/flux -v
# Add binary to GitHub runner path
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
echo "$RUNNER_WORKSPACE/$(basename $GITHUB_REPOSITORY)/bin" >> $GITHUB_PATH

View File

@@ -57,6 +57,7 @@ var (
bootstrapArch = flags.Arch(defaults.Arch)
bootstrapLogLevel = flags.LogLevel(defaults.LogLevel)
bootstrapRequiredComponents = []string{"source-controller", "kustomize-controller"}
bootstrapTokenAuth bool
)
const (
@@ -75,14 +76,16 @@ func init() {
bootstrapCmd.PersistentFlags().Var(&bootstrapArch, "arch", bootstrapArch.Description())
bootstrapCmd.PersistentFlags().StringVar(&bootstrapBranch, "branch", bootstrapDefaultBranch,
"default branch (for GitHub this must match the default branch setting for the organization)")
rootCmd.AddCommand(bootstrapCmd)
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapWatchAllNamespaces, "watch-all-namespaces", true,
"watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed")
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapNetworkPolicy, "network-policy", true,
"deny ingress access to the toolkit controllers from other namespaces using network policies")
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapTokenAuth, "token-auth", false,
"when enabled, the personal access token will be used instead of SSH deploy key")
bootstrapCmd.PersistentFlags().Var(&bootstrapLogLevel, "log-level", bootstrapLogLevel.Description())
bootstrapCmd.PersistentFlags().StringVar(&bootstrapManifestsPath, "manifests", "", "path to the manifest directory")
bootstrapCmd.PersistentFlags().MarkHidden("manifests")
rootCmd.AddCommand(bootstrapCmd)
}
func bootstrapValidate() error {
@@ -132,13 +135,13 @@ func generateInstallManifests(targetPath, namespace, tmpDir string, localManifes
func applyInstallManifests(ctx context.Context, manifestPath string, components []string) error {
kubectlArgs := []string{"apply", "-f", manifestPath}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubectlArgs...); err != nil {
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed")
}
for _, deployment := range components {
kubectlArgs = []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubectlArgs...); err != nil {
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed")
}
}
@@ -174,7 +177,7 @@ func generateSyncManifests(url, branch, name, namespace, targetPath, tmpDir stri
func applySyncManifests(ctx context.Context, kubeClient client.Client, name, namespace, targetPath, tmpDir string) error {
kubectlArgs := []string{"apply", "-k", filepath.Join(tmpDir, targetPath, namespace)}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, kubectlArgs...); err != nil {
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, kubeconfig, kubecontext, kubectlArgs...); err != nil {
return err
}

View File

@@ -26,6 +26,8 @@ import (
"time"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/git"
@@ -35,7 +37,7 @@ var bootstrapGitHubCmd = &cobra.Command{
Use: "github",
Short: "Bootstrap toolkit components in a GitHub repository",
Long: `The bootstrap github command creates the GitHub repository if it doesn't exists and
commits the toolkit components manifests to the master branch.
commits the toolkit components manifests to the main branch.
Then it configures the target cluster to synchronize with the repository.
If the toolkit components are present on the cluster,
the bootstrap command will perform an upgrade if needed.`,
@@ -54,8 +56,11 @@ the bootstrap command will perform an upgrade if needed.`,
# Run bootstrap for a public repository on a personal account
flux bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true
# Run bootstrap for a private repo hosted on GitHub Enterprise
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain>
# Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --ssh-hostname=<domain>
# Run bootstrap for a private repo hosted on GitHub Enterprise using HTTPS auth
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --token-auth
# Run bootstrap for a an existing repository with a branch named main
flux bootstrap github --owner=<organization> --repository=<repo name> --branch=main
@@ -64,15 +69,16 @@ the bootstrap command will perform an upgrade if needed.`,
}
var (
ghOwner string
ghRepository string
ghInterval time.Duration
ghPersonal bool
ghPrivate bool
ghHostname string
ghPath string
ghTeams []string
ghDelete bool
ghOwner string
ghRepository string
ghInterval time.Duration
ghPersonal bool
ghPrivate bool
ghHostname string
ghPath string
ghTeams []string
ghDelete bool
ghSSHHostname string
)
const (
@@ -87,6 +93,7 @@ func init() {
bootstrapGitHubCmd.Flags().BoolVar(&ghPrivate, "private", true, "is private repository")
bootstrapGitHubCmd.Flags().DurationVar(&ghInterval, "interval", time.Minute, "sync interval")
bootstrapGitHubCmd.Flags().StringVar(&ghHostname, "hostname", git.GitHubDefaultHostname, "GitHub hostname")
bootstrapGitHubCmd.Flags().StringVar(&ghSSHHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one")
bootstrapGitHubCmd.Flags().StringVar(&ghPath, "path", "", "repository path, when specified the cluster sync will be scoped to this path")
bootstrapGitHubCmd.Flags().BoolVar(&ghDelete, "delete", false, "delete repository (used for testing only)")
@@ -110,6 +117,10 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
return err
}
if ghSSHHostname != "" {
repository.SSHHost = ghSSHHostname
}
provider := &git.GithubProvider{
IsPrivate: ghPrivate,
IsPersonal: ghPersonal,
@@ -155,7 +166,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
}
}
// clone repository and checkout the master branch
// clone repository and checkout the main branch
if err := repository.Checkout(ctx, bootstrapBranch, tmpDir); err != nil {
return err
}
@@ -201,34 +212,54 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("install completed")
}
// setup SSH deploy key
if shouldCreateDeployKey(ctx, kubeClient, namespace) {
logger.Actionf("configuring deploy key")
u, err := url.Parse(repository.GetSSH())
if err != nil {
return fmt.Errorf("git URL parse failed: %w", err)
}
repoURL := repository.GetURL()
key, err := generateDeployKey(ctx, kubeClient, u, namespace)
if err != nil {
return fmt.Errorf("generating deploy key failed: %w", err)
if bootstrapTokenAuth {
// setup HTTPS token auth
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
Namespace: namespace,
},
StringData: map[string]string{
"username": "git",
"password": ghToken,
},
}
keyName := "flux"
if ghPath != "" {
keyName = fmt.Sprintf("flux-%s", ghPath)
}
if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil {
if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err
} else if changed {
logger.Successf("deploy key configured")
}
} else {
// setup SSH deploy key
repoURL = repository.GetSSH()
if shouldCreateDeployKey(ctx, kubeClient, namespace) {
logger.Actionf("configuring deploy key")
u, err := url.Parse(repository.GetSSH())
if err != nil {
return fmt.Errorf("git URL parse failed: %w", err)
}
key, err := generateDeployKey(ctx, kubeClient, u, namespace)
if err != nil {
return fmt.Errorf("generating deploy key failed: %w", err)
}
keyName := "flux"
if ghPath != "" {
keyName = fmt.Sprintf("flux-%s", ghPath)
}
if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil {
return err
} else if changed {
logger.Successf("deploy key configured")
}
}
}
// configure repo synchronization
logger.Actionf("generating sync manifests")
if err := generateSyncManifests(repository.GetSSH(), bootstrapBranch, namespace, namespace, ghPath, tmpDir, ghInterval); err != nil {
if err := generateSyncManifests(repoURL, bootstrapBranch, namespace, namespace, ghPath, tmpDir, ghInterval); err != nil {
return err
}

View File

@@ -45,22 +45,22 @@ the bootstrap command will perform an upgrade if needed.`,
export GITLAB_TOKEN=<my-token>
# Run bootstrap for a private repo using HTTPS token authentication
flux bootstrap gitlab --owner=<group> --repository=<repo name>
flux bootstrap gitlab --owner=<group> --repository=<repo name> --token-auth
# Run bootstrap for a private repo using SSH authentication
flux bootstrap gitlab --owner=<group> --repository=<repo name> --ssh-hostname=gitlab.com
flux bootstrap gitlab --owner=<group> --repository=<repo name>
# Run bootstrap for a repository path
flux bootstrap gitlab --owner=<group> --repository=<repo name> --path=dev-cluster
# Run bootstrap for a public repository on a personal account
flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal=true
flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal --token-auth
# Run bootstrap for a private repo hosted on a GitLab server
flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain>
flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain> --token-auth
# Run bootstrap for a an existing repository with a branch named main
flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main
flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main --token-auth
`,
RunE: bootstrapGitLabCmdRun,
}
@@ -83,7 +83,7 @@ func init() {
bootstrapGitLabCmd.Flags().BoolVar(&glPrivate, "private", true, "is private repository")
bootstrapGitLabCmd.Flags().DurationVar(&glInterval, "interval", time.Minute, "sync interval")
bootstrapGitLabCmd.Flags().StringVar(&glHostname, "hostname", git.GitLabDefaultHostname, "GitLab hostname")
bootstrapGitLabCmd.Flags().StringVar(&glSSHHostname, "ssh-hostname", "", "GitLab SSH hostname, when specified a deploy key will be added to the repository")
bootstrapGitLabCmd.Flags().StringVar(&glSSHHostname, "ssh-hostname", "", "GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one")
bootstrapGitLabCmd.Flags().StringVar(&glPath, "path", "", "repository path, when specified the cluster sync will be scoped to this path")
bootstrapCmd.AddCommand(bootstrapGitLabCmd)
@@ -180,7 +180,22 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
repoURL := repository.GetURL()
if glSSHHostname != "" {
if bootstrapTokenAuth {
// setup HTTPS token auth
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
Namespace: namespace,
},
StringData: map[string]string{
"username": "git",
"password": glToken,
},
}
if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err
}
} else {
// setup SSH deploy key
repoURL = repository.GetSSH()
if shouldCreateDeployKey(ctx, kubeClient, namespace) {
@@ -206,21 +221,6 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("deploy key configured")
}
}
} else {
// setup HTTPS token auth
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
Namespace: namespace,
},
StringData: map[string]string{
"username": "git",
"password": glToken,
},
}
if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err
}
}
// configure repo synchronization

View File

@@ -104,7 +104,7 @@ func kubectlCheck(ctx context.Context, version string) bool {
}
kubectlArgs := []string{"version", "--client", "--output", "json"}
output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubectlArgs...)
output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubeconfig, kubecontext, kubectlArgs...)
if err != nil {
logger.Failuref("kubectl version can't be determined")
return false
@@ -174,12 +174,16 @@ func componentsCheck() bool {
ok := true
for _, deployment := range checkComponents {
kubectlArgs := []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()}
if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubectlArgs...); err != nil {
if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubeconfig, kubecontext, kubectlArgs...); err != nil {
logger.Failuref("%s: %s", deployment, strings.TrimSuffix(output, "\n"))
ok = false
} else {
logger.Successf("%s is healthy", deployment)
}
kubectlArgs = []string{"-n", namespace, "get", "deployment", deployment, "-o", "jsonpath=\"{..image}\""}
if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubeconfig, kubecontext, kubectlArgs...); err == nil {
logger.Actionf(strings.TrimPrefix(strings.TrimSuffix(output, "\""), "\""))
}
}
return ok
}

View File

@@ -26,6 +26,7 @@ import (
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
@@ -179,11 +180,11 @@ func isAlertReady(ctx context.Context, kubeClient client.Client,
return false, err
}
if c := meta.GetCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
@@ -177,11 +178,11 @@ func isAlertProviderReady(ctx context.Context, kubeClient client.Client,
return false, err
}
if c := meta.GetCondition(provider.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(provider.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}

View File

@@ -28,6 +28,7 @@ import (
"github.com/spf13/cobra"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
@@ -67,6 +68,14 @@ var createHelmReleaseCmd = &cobra.Command{
--chart=podinfo \
--values=./my-values.yaml
# Create a HelmRelease with values from a Kubernetes secret
kubectl -n app create secret generic my-secret-values \
--from-file=values.yaml=/path/to/my-secret-values.yaml
flux -n app create hr podinfo \
--source=HelmRepository/podinfo \
--chart=podinfo \
--values-from=Secret/my-secret-values
# Create a HelmRelease with a custom release name
flux create hr podinfo \
--release-name=podinfo-dev
@@ -97,6 +106,8 @@ var (
hrChartVersion string
hrTargetNamespace string
hrValuesFile string
hrValuesFrom flags.HelmReleaseValuesFrom
hrSAName string
)
func init() {
@@ -106,7 +117,9 @@ func init() {
createHelmReleaseCmd.Flags().StringVar(&hrChartVersion, "chart-version", "", "Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)")
createHelmReleaseCmd.Flags().StringArrayVar(&hrDependsOn, "depends-on", nil, "HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'")
createHelmReleaseCmd.Flags().StringVar(&hrTargetNamespace, "target-namespace", "", "namespace to install this release, defaults to the HelmRelease namespace")
createHelmReleaseCmd.Flags().StringVar(&hrSAName, "service-account", "", "the name of the service account to impersonate when reconciling this HelmRelease")
createHelmReleaseCmd.Flags().StringVar(&hrValuesFile, "values", "", "local path to the values.yaml file")
createHelmReleaseCmd.Flags().Var(&hrValuesFrom, "values-from", hrValuesFrom.Description())
createCmd.AddCommand(createHelmReleaseCmd)
}
@@ -156,6 +169,10 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
},
}
if hrSAName != "" {
helmRelease.Spec.ServiceAccountName = hrSAName
}
if hrValuesFile != "" {
data, err := ioutil.ReadFile(hrValuesFile)
if err != nil {
@@ -170,6 +187,13 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
helmRelease.Spec.Values = &apiextensionsv1.JSON{Raw: json}
}
if hrValuesFrom.String() != "" {
helmRelease.Spec.ValuesFrom = []helmv2.ValuesReference{{
Kind: hrValuesFrom.Kind,
Name: hrValuesFrom.Name,
}}
}
if export {
return exportHelmRelease(helmRelease)
}
@@ -243,6 +267,6 @@ func isHelmReleaseReady(ctx context.Context, kubeClient client.Client,
return false, nil
}
return meta.HasReadyCondition(helmRelease.Status.Conditions), nil
return apimeta.IsStatusConditionTrue(helmRelease.Status.Conditions, meta.ReadyCondition), nil
}
}

View File

@@ -25,6 +25,7 @@ import (
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
@@ -80,23 +81,23 @@ var (
ksHealthCheck []string
ksHealthTimeout time.Duration
ksSAName string
ksSANamespace string
ksDecryptionProvider flags.DecryptionProvider
ksDecryptionSecret string
ksTargetNamespace string
)
func init() {
createKsCmd.Flags().Var(&ksSource, "source", ksSource.Description())
createKsCmd.Flags().StringVar(&ksPath, "path", "./", "path to the directory containing the Kustomization file")
createKsCmd.Flags().StringVar(&ksPath, "path", "./", "path to the directory containing a kustomization.yaml file")
createKsCmd.Flags().BoolVar(&ksPrune, "prune", false, "enable garbage collection")
createKsCmd.Flags().StringArrayVar(&ksHealthCheck, "health-check", nil, "workload to be included in the health assessment, in the format '<kind>/<name>.<namespace>'")
createKsCmd.Flags().DurationVar(&ksHealthTimeout, "health-check-timeout", 2*time.Minute, "timeout of health checking operations")
createKsCmd.Flags().StringVar(&ksValidation, "validation", "", "validate the manifests before applying them on the cluster, can be 'client' or 'server'")
createKsCmd.Flags().StringArrayVar(&ksDependsOn, "depends-on", nil, "Kustomization that must be ready before this Kustomization can be applied, supported formats '<name>' and '<namespace>/<name>'")
createKsCmd.Flags().StringVar(&ksSAName, "sa-name", "", "service account name")
createKsCmd.Flags().StringVar(&ksSANamespace, "sa-namespace", "", "service account namespace")
createKsCmd.Flags().StringVar(&ksSAName, "service-account", "", "the name of the service account to impersonate when reconciling this Kustomization")
createKsCmd.Flags().Var(&ksDecryptionProvider, "decryption-provider", ksDecryptionProvider.Description())
createKsCmd.Flags().StringVar(&ksDecryptionSecret, "decryption-secret", "", "set the Kubernetes secret name that contains the OpenPGP private keys used for sops decryption")
createKsCmd.Flags().StringVar(&ksTargetNamespace, "target-namespace", "", "overrides the namespace of all Kustomization objects reconciled by this Kustomization")
createCmd.AddCommand(createKsCmd)
}
@@ -139,8 +140,9 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
Kind: ksSource.Kind,
Name: ksSource.Name,
},
Suspend: false,
Validation: ksValidation,
Suspend: false,
Validation: ksValidation,
TargetNamespace: ksTargetNamespace,
},
}
@@ -185,11 +187,8 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
}
}
if ksSAName != "" && ksSANamespace != "" {
kustomization.Spec.ServiceAccount = &kustomizev1.ServiceAccount{
Name: ksSAName,
Namespace: ksSANamespace,
}
if ksSAName != "" {
kustomization.Spec.ServiceAccountName = ksSAName
}
if ksDecryptionProvider != "" {
@@ -275,11 +274,11 @@ func isKustomizationReady(ctx context.Context, kubeClient client.Client,
return false, nil
}
if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
@@ -189,11 +190,11 @@ func isReceiverReady(ctx context.Context, kubeClient client.Client,
return false, err
}
if c := meta.GetCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}

View File

@@ -34,6 +34,7 @@ import (
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
@@ -375,11 +376,11 @@ func isGitRepositoryReady(ctx context.Context, kubeClient client.Client,
return false, err
}
if c := meta.GetCondition(gitRepository.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(gitRepository.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}

View File

@@ -23,9 +23,11 @@ import (
"net/url"
"os"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
@@ -242,3 +244,28 @@ func upsertHelmRepository(ctx context.Context, kubeClient client.Client,
logger.Successf("source updated")
return namespacedName, nil
}
func isHelmRepositoryReady(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, helmRepository *sourcev1.HelmRepository) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, helmRepository)
if err != nil {
return false, err
}
// Confirm the state we are observing is for the current generation
if helmRepository.Generation != helmRepository.Status.ObservedGeneration {
return false, nil
}
if c := apimeta.FindStatusCondition(helmRepository.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case metav1.ConditionTrue:
return true, nil
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}
return false, nil
}
}

View File

@@ -38,7 +38,7 @@ var createTenantCmd = &cobra.Command{
Use: "tenant",
Short: "Create or update a tenant",
Long: `
The create tenant command generates namespaces and role bindings to limit the
The create tenant command generates namespaces, service accounts and role bindings to limit the
reconcilers scope to the tenant namespaces.`,
Example: ` # Create a tenant with access to a namespace
flux create tenant dev-team \
@@ -55,8 +55,7 @@ reconcilers scope to the tenant namespaces.`,
}
const (
tenantLabel = "toolkit.fluxcd.io/tenant"
tenantRoleBinding = "gotk-reconciler"
tenantLabel = "toolkit.fluxcd.io/tenant"
)
var (
@@ -65,7 +64,6 @@ var (
)
func init() {
createTenantCmd.Hidden = true
createTenantCmd.Flags().StringSliceVar(&tenantNamespaces, "with-namespace", nil, "namespace belonging to this tenant")
createTenantCmd.Flags().StringVar(&tenantClusterRole, "cluster-role", "cluster-admin", "cluster role of the tenant role binding")
createCmd.AddCommand(createTenantCmd)
@@ -89,6 +87,7 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
}
var namespaces []corev1.Namespace
var accounts []corev1.ServiceAccount
var roleBindings []rbacv1.RoleBinding
for _, ns := range tenantNamespaces {
@@ -111,9 +110,19 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
}
namespaces = append(namespaces, namespace)
account := corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: tenant,
Namespace: ns,
Labels: objLabels,
},
}
accounts = append(accounts, account)
roleBinding := rbacv1.RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: tenantRoleBinding,
Name: fmt.Sprintf("%s-reconciler", tenant),
Namespace: ns,
Labels: objLabels,
},
@@ -123,6 +132,11 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
Kind: "User",
Name: fmt.Sprintf("gotk:%s:reconciler", ns),
},
{
Kind: "ServiceAccount",
Name: tenant,
Namespace: ns,
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
@@ -135,7 +149,7 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
if export {
for i, _ := range tenantNamespaces {
if err := exportTenant(namespaces[i], roleBindings[1]); err != nil {
if err := exportTenant(namespaces[i], accounts[i], roleBindings[i]); err != nil {
return err
}
}
@@ -156,6 +170,11 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
return err
}
logger.Actionf("applying service account %s", accounts[i].Name)
if err := upsertServiceAccount(ctx, kubeClient, accounts[i]); err != nil {
return err
}
logger.Actionf("applying role binding %s", roleBindings[i].Name)
if err := upsertRoleBinding(ctx, kubeClient, roleBindings[i]); err != nil {
return err
@@ -195,6 +214,35 @@ func upsertNamespace(ctx context.Context, kubeClient client.Client, namespace co
return nil
}
func upsertServiceAccount(ctx context.Context, kubeClient client.Client, account corev1.ServiceAccount) error {
namespacedName := types.NamespacedName{
Namespace: account.GetNamespace(),
Name: account.GetName(),
}
var existing corev1.ServiceAccount
err := kubeClient.Get(ctx, namespacedName, &existing)
if err != nil {
if errors.IsNotFound(err) {
if err := kubeClient.Create(ctx, &account); err != nil {
return err
} else {
return nil
}
}
return err
}
if !equality.Semantic.DeepDerivative(account.Labels, existing.Labels) {
existing.Labels = account.Labels
if err := kubeClient.Update(ctx, &existing); err != nil {
return err
}
}
return nil
}
func upsertRoleBinding(ctx context.Context, kubeClient client.Client, roleBinding rbacv1.RoleBinding) error {
namespacedName := types.NamespacedName{
Namespace: roleBinding.GetNamespace(),
@@ -228,7 +276,7 @@ func upsertRoleBinding(ctx context.Context, kubeClient client.Client, roleBindin
return nil
}
func exportTenant(namespace corev1.Namespace, roleBinding rbacv1.RoleBinding) error {
func exportTenant(namespace corev1.Namespace, account corev1.ServiceAccount, roleBinding rbacv1.RoleBinding) error {
namespace.TypeMeta = metav1.TypeMeta{
APIVersion: "v1",
Kind: "Namespace",
@@ -242,6 +290,19 @@ func exportTenant(namespace corev1.Namespace, roleBinding rbacv1.RoleBinding) er
data = bytes.Replace(data, []byte("spec: {}\n"), []byte(""), 1)
fmt.Println(resourceToString(data))
account.TypeMeta = metav1.TypeMeta{
APIVersion: "v1",
Kind: "ServiceAccount",
}
data, err = yaml.Marshal(account)
if err != nil {
return err
}
fmt.Println("---")
data = bytes.Replace(data, []byte("spec: {}\n"), []byte(""), 1)
fmt.Println(resourceToString(data))
roleBinding.TypeMeta = metav1.TypeMeta{
APIVersion: "rbac.authorization.k8s.io/v1",
Kind: "RoleBinding",

View File

@@ -23,7 +23,8 @@ import (
"strings"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
@@ -69,28 +70,26 @@ func getAlertCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
header := []string{"Name", "Suspended", "Ready", "Message"}
header := []string{"Name", "Ready", "Message", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, alert := range list.Items {
row := []string{}
if c := meta.GetCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
alert.GetName(),
//alert.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
string(c.Status),
c.Message,
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
}
} else {
row = []string{
alert.GetName(),
//alert.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
string(corev1.ConditionFalse),
string(metav1.ConditionFalse),
"waiting to be reconciled",
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
}
}
if allNamespaces {

View File

@@ -21,7 +21,8 @@ import (
"os"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
@@ -74,7 +75,7 @@ func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
var rows [][]string
for _, provider := range list.Items {
row := []string{}
if c := meta.GetCondition(provider.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(provider.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
provider.GetName(),
string(c.Status),
@@ -83,7 +84,7 @@ func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} else {
row = []string{
provider.GetName(),
string(corev1.ConditionFalse),
string(metav1.ConditionFalse),
"waiting to be reconciled",
}
}

View File

@@ -26,7 +26,8 @@ import (
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
@@ -71,28 +72,28 @@ func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
header := []string{"Name", "Revision", "Suspended", "Ready", "Message"}
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, helmRelease := range list.Items {
row := []string{}
if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
helmRelease.GetName(),
helmRelease.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(helmRelease.Spec.Suspend)),
string(c.Status),
c.Message,
helmRelease.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(helmRelease.Spec.Suspend)),
}
} else {
row = []string{
helmRelease.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
helmRelease.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(helmRelease.Spec.Suspend)),
string(corev1.ConditionFalse),
"waiting to be reconciled",
}
}
if allNamespaces {

View File

@@ -27,7 +27,8 @@ import (
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
@@ -70,28 +71,28 @@ func getKsCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
header := []string{"Name", "Revision", "Suspended", "Ready", "Message"}
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, kustomization := range list.Items {
row := []string{}
if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
kustomization.GetName(),
kustomization.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(kustomization.Spec.Suspend)),
string(c.Status),
c.Message,
kustomization.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(kustomization.Spec.Suspend)),
}
} else {
row = []string{
kustomization.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
kustomization.Status.LastAppliedRevision,
strings.Title(strconv.FormatBool(kustomization.Spec.Suspend)),
string(corev1.ConditionFalse),
"waiting to be reconciled",
}
}
if allNamespaces {

View File

@@ -23,7 +23,8 @@ import (
"strings"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
@@ -69,26 +70,26 @@ func getReceiverCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
header := []string{"Name", "Suspended", "Ready", "Message"}
header := []string{"Name", "Ready", "Message", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, receiver := range list.Items {
row := []string{}
if c := meta.GetCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
receiver.GetName(),
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
string(c.Status),
c.Message,
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
}
} else {
row = []string{
receiver.GetName(),
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
string(corev1.ConditionFalse),
string(metav1.ConditionFalse),
"waiting to be reconciled",
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
}
}
rows = append(rows, row)

View File

@@ -19,13 +19,16 @@ package main
import (
"context"
"os"
"strconv"
"strings"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
@@ -35,6 +38,9 @@ var getSourceBucketCmd = &cobra.Command{
Long: "The get sources bucket command prints the status of the Bucket sources.",
Example: ` # List all Buckets and their status
flux get sources bucket
# List buckets from all namespaces
flux get sources helm --all-namespaces
`,
RunE: getSourceBucketCmdRun,
}
@@ -67,7 +73,7 @@ func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
header := []string{"Name", "Revision", "Ready", "Message"}
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
@@ -78,19 +84,21 @@ func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
if source.GetArtifact() != nil {
revision = source.GetArtifact().Revision
}
if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(source.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
source.GetName(),
revision,
string(c.Status),
c.Message,
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
} else {
row = []string{
source.GetName(),
revision,
string(corev1.ConditionFalse),
string(metav1.ConditionFalse),
"waiting to be reconciled",
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
}
if allNamespaces {

View File

@@ -0,0 +1,111 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"os"
"strconv"
"strings"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
var getSourceHelmChartCmd = &cobra.Command{
Use: "chart",
Short: "Get HelmChart statuses",
Long: "The get sources chart command prints the status of the HelmCharts.",
Example: ` # List all Helm charts and their status
flux get sources chart
# List Helm charts from all namespaces
flux get sources chart --all-namespaces
`,
RunE: getSourceHelmChartCmdRun,
}
func init() {
getSourceCmd.AddCommand(getSourceHelmChartCmd)
}
func getSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
var listOpts []client.ListOption
if !allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace))
}
var list sourcev1.HelmChartList
err = kubeClient.List(ctx, &list, listOpts...)
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no chart sources found in %s namespace", namespace)
return nil
}
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, source := range list.Items {
var row []string
var revision string
if source.GetArtifact() != nil {
revision = source.GetArtifact().Revision
}
if c := apimeta.FindStatusCondition(source.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
source.GetName(),
string(c.Status),
c.Message,
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
} else {
row = []string{
source.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
}
if allNamespaces {
row = append([]string{source.Namespace}, row...)
}
rows = append(rows, row)
}
utils.PrintTable(os.Stdout, header, rows)
return nil
}

View File

@@ -19,13 +19,16 @@ package main
import (
"context"
"os"
"strconv"
"strings"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
@@ -35,6 +38,9 @@ var getSourceGitCmd = &cobra.Command{
Long: "The get sources git command prints the status of the GitRepository sources.",
Example: ` # List all Git repositories and their status
flux get sources git
# List Git repositories from all namespaces
flux get sources git --all-namespaces
`,
RunE: getSourceGitCmdRun,
}
@@ -67,7 +73,7 @@ func getSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
header := []string{"Name", "Revision", "Ready", "Message"}
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
@@ -78,19 +84,21 @@ func getSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if source.GetArtifact() != nil {
revision = source.GetArtifact().Revision
}
if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(source.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
source.GetName(),
revision,
string(c.Status),
c.Message,
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
} else {
row = []string{
source.GetName(),
revision,
string(corev1.ConditionFalse),
string(metav1.ConditionFalse),
"waiting to be reconciled",
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
}
if allNamespaces {

View File

@@ -19,13 +19,16 @@ package main
import (
"context"
"os"
"strconv"
"strings"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
@@ -35,6 +38,9 @@ var getSourceHelmCmd = &cobra.Command{
Long: "The get sources helm command prints the status of the HelmRepository sources.",
Example: ` # List all Helm repositories and their status
flux get sources helm
# List Helm repositories from all namespaces
flux get sources helm --all-namespaces
`,
RunE: getSourceHelmCmdRun,
}
@@ -67,7 +73,7 @@ func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
header := []string{"Name", "Revision", "Ready", "Message"}
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces {
header = append([]string{"Namespace"}, header...)
}
@@ -78,19 +84,21 @@ func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
if source.GetArtifact() != nil {
revision = source.GetArtifact().Revision
}
if c := meta.GetCondition(source.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(source.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
source.GetName(),
revision,
string(c.Status),
c.Message,
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
} else {
row = []string{
source.GetName(),
revision,
string(corev1.ConditionFalse),
string(metav1.ConditionFalse),
"waiting to be reconciled",
revision,
strings.Title(strconv.FormatBool(source.Spec.Suspend)),
}
}
if allNamespaces {

View File

@@ -152,10 +152,10 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
kubectlArgs := []string{"apply", "-f", filepath.Join(tmpDir, manifest.Path)}
if installDryRun {
args = append(args, "--dry-run=client")
kubectlArgs = append(kubectlArgs, "--dry-run=client")
applyOutput = utils.ModeOS
}
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, kubectlArgs...); err != nil {
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, kubeconfig, kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed")
}
@@ -169,7 +169,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
logger.Waitingf("verifying installation")
for _, deployment := range installComponents {
kubectlArgs = []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()}
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, kubectlArgs...); err != nil {
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, kubeconfig, kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed")
} else {
logger.Successf("%s ready", deployment)

View File

@@ -64,13 +64,17 @@ func reconcileAlertCmdRun(cmd *cobra.Command, args []string) error {
Name: name,
}
logger.Actionf("annotating Alert %s in %s namespace", name, namespace)
var alert notificationv1.Alert
err = kubeClient.Get(ctx, namespacedName, &alert)
if err != nil {
return err
}
if alert.Spec.Suspend {
return fmt.Errorf("resource is suspended")
}
logger.Actionf("annotating Alert %s in %s namespace", name, namespace)
if alert.Annotations == nil {
alert.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),
@@ -78,6 +82,7 @@ func reconcileAlertCmdRun(cmd *cobra.Command, args []string) error {
} else {
alert.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano)
}
if err := kubeClient.Update(ctx, &alert); err != nil {
return err
}

View File

@@ -22,7 +22,8 @@ import (
"time"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/retry"
@@ -85,6 +86,10 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error {
return err
}
if helmRelease.Spec.Suspend {
return fmt.Errorf("resource is suspended")
}
if syncHrWithSource {
switch helmRelease.Spec.Chart.Spec.SourceRef.Kind {
case sourcev1.HelmRepositoryKind:
@@ -118,9 +123,9 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionFalse:
case metav1.ConditionFalse:
return fmt.Errorf("HelmRelease reconciliation failed: %s", c.Message)
default:
logger.Successf("reconciled revision %s", helmRelease.Status.LastAppliedRevision)

View File

@@ -21,7 +21,7 @@ import (
"fmt"
"time"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -84,6 +84,10 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error {
return err
}
if kustomization.Spec.Suspend {
return fmt.Errorf("resource is suspended")
}
if syncKsWithSource {
switch kustomization.Spec.SourceRef.Kind {
case sourcev1.GitRepositoryKind:
@@ -112,14 +116,10 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error {
}
logger.Successf("Kustomization reconciliation completed")
if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionFalse:
return fmt.Errorf("Kustomization reconciliation failed")
default:
logger.Successf("reconciled revision %s", kustomization.Status.LastAppliedRevision)
}
if apimeta.IsStatusConditionFalse(kustomization.Status.Conditions, meta.ReadyCondition) {
return fmt.Errorf("Kustomization reconciliation failed")
}
logger.Successf("reconciled revision %s", kustomization.Status.LastAppliedRevision)
return nil
}

View File

@@ -64,13 +64,17 @@ func reconcileReceiverCmdRun(cmd *cobra.Command, args []string) error {
Name: name,
}
logger.Actionf("annotating Receiver %s in %s namespace", name, namespace)
var receiver notificationv1.Receiver
err = kubeClient.Get(ctx, namespacedName, &receiver)
if err != nil {
return err
}
if receiver.Spec.Suspend {
return fmt.Errorf("resource is suspended")
}
logger.Actionf("annotating Receiver %s in %s namespace", name, namespace)
if receiver.Annotations == nil {
receiver.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),

View File

@@ -21,11 +21,14 @@ import (
"fmt"
"time"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
"k8s.io/client-go/util/retry"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -65,35 +68,34 @@ func reconcileSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
Namespace: namespace,
Name: name,
}
logger.Actionf("annotating Bucket source %s in %s namespace", name, namespace)
var bucket sourcev1.Bucket
err = kubeClient.Get(ctx, namespacedName, &bucket)
if err != nil {
return err
}
if bucket.Annotations == nil {
bucket.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),
}
} else {
bucket.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano)
if bucket.Spec.Suspend {
return fmt.Errorf("resource is suspended")
}
if err := kubeClient.Update(ctx, &bucket); err != nil {
lastHandledReconcileAt := bucket.Status.LastHandledReconcileAt
logger.Actionf("annotating Bucket source %s in %s namespace", name, namespace)
if err := requestBucketReconciliation(ctx, kubeClient, namespacedName, &bucket); err != nil {
return err
}
logger.Successf("Bucket source annotated")
logger.Waitingf("waiting for Bucket source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout,
isBucketReady(ctx, kubeClient, namespacedName, &bucket)); err != nil {
if err := wait.PollImmediate(
pollInterval, timeout,
bucketReconciliationHandled(ctx, kubeClient, namespacedName, &bucket, lastHandledReconcileAt),
); err != nil {
return err
}
logger.Successf("Bucket source reconciliation completed")
if bucket.Status.Artifact == nil {
return fmt.Errorf("Bucket source reconciliation completed but no artifact was found")
if apimeta.IsStatusConditionFalse(bucket.Status.Conditions, meta.ReadyCondition) {
return fmt.Errorf("Bucket source reconciliation failed")
}
logger.Successf("fetched revision %s", bucket.Status.Artifact.Revision)
return nil
@@ -112,14 +114,42 @@ func isBucketReady(ctx context.Context, kubeClient client.Client,
return false, nil
}
if c := meta.GetCondition(bucket.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(bucket.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}
return false, nil
}
}
func bucketReconciliationHandled(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, bucket *sourcev1.Bucket, lastHandledReconcileAt string) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, bucket)
if err != nil {
return false, err
}
return bucket.Status.LastHandledReconcileAt != lastHandledReconcileAt, nil
}
}
func requestBucketReconciliation(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, bucket *sourcev1.Bucket) error {
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
if err := kubeClient.Get(ctx, namespacedName, bucket); err != nil {
return err
}
if bucket.Annotations == nil {
bucket.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),
}
} else {
bucket.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano)
}
return kubeClient.Update(ctx, bucket)
})
}

View File

@@ -23,6 +23,9 @@ import (
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
apimeta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
@@ -63,36 +66,61 @@ func reconcileSourceGitCmdRun(cmd *cobra.Command, args []string) error {
Namespace: namespace,
Name: name,
}
logger.Actionf("annotating GitRepository source %s in %s namespace", name, namespace)
var gitRepository sourcev1.GitRepository
err = kubeClient.Get(ctx, namespacedName, &gitRepository)
var repository sourcev1.GitRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
if gitRepository.Annotations == nil {
gitRepository.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),
}
} else {
gitRepository.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano)
if repository.Spec.Suspend {
return fmt.Errorf("resource is suspended")
}
if err := kubeClient.Update(ctx, &gitRepository); err != nil {
logger.Actionf("annotating GitRepository source %s in %s namespace", name, namespace)
if err := requestGitRepositoryReconciliation(ctx, kubeClient, namespacedName, &repository); err != nil {
return err
}
logger.Successf("GitRepository source annotated")
lastHandledReconcileAt := repository.Status.LastHandledReconcileAt
logger.Waitingf("waiting for GitRepository source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout,
isGitRepositoryReady(ctx, kubeClient, namespacedName, &gitRepository)); err != nil {
gitRepositoryReconciliationHandled(ctx, kubeClient, namespacedName, &repository, lastHandledReconcileAt)); err != nil {
return err
}
logger.Successf("GitRepository source reconciliation completed")
if gitRepository.Status.Artifact == nil {
return fmt.Errorf("GitRepository source reconciliation completed but no artifact was found")
if apimeta.IsStatusConditionFalse(repository.Status.Conditions, meta.ReadyCondition) {
return fmt.Errorf("GitRepository source reconciliation failed")
}
logger.Successf("fetched revision %s", gitRepository.Status.Artifact.Revision)
logger.Successf("fetched revision %s", repository.Status.Artifact.Revision)
return nil
}
func gitRepositoryReconciliationHandled(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, repository *sourcev1.GitRepository, lastHandledReconcileAt string) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, repository)
if err != nil {
return false, err
}
return repository.Status.LastHandledReconcileAt != lastHandledReconcileAt, nil
}
}
func requestGitRepositoryReconciliation(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, repository *sourcev1.GitRepository) error {
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
if err := kubeClient.Get(ctx, namespacedName, repository); err != nil {
return err
}
if repository.Annotations == nil {
repository.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),
}
} else {
repository.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano)
}
return kubeClient.Update(ctx, repository)
})
}

View File

@@ -21,11 +21,13 @@ import (
"fmt"
"time"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
"k8s.io/client-go/util/retry"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -65,61 +67,61 @@ func reconcileSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
Namespace: namespace,
Name: name,
}
logger.Actionf("annotating HelmRepository source %s in %s namespace", name, namespace)
var helmRepository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &helmRepository)
var repository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
if helmRepository.Annotations == nil {
helmRepository.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),
}
} else {
helmRepository.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano)
if repository.Spec.Suspend {
return fmt.Errorf("resource is suspended")
}
if err := kubeClient.Update(ctx, &helmRepository); err != nil {
logger.Actionf("annotating HelmRepository source %s in %s namespace", name, namespace)
if err := requestHelmRepositoryReconciliation(ctx, kubeClient, namespacedName, &repository); err != nil {
return err
}
logger.Successf("HelmRepository source annotated")
lastHandledReconcileAt := repository.Status.LastHandledReconcileAt
logger.Waitingf("waiting for HelmRepository source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout,
isHelmRepositoryReady(ctx, kubeClient, namespacedName, &helmRepository)); err != nil {
helmRepositoryReconciliationHandled(ctx, kubeClient, namespacedName, &repository, lastHandledReconcileAt)); err != nil {
return err
}
logger.Successf("HelmRepository source reconciliation completed")
if helmRepository.Status.Artifact == nil {
return fmt.Errorf("HelmRepository source reconciliation completed but no artifact was found")
if apimeta.IsStatusConditionFalse(repository.Status.Conditions, meta.ReadyCondition) {
return fmt.Errorf("HelmRepository source reconciliation failed")
}
logger.Successf("fetched revision %s", helmRepository.Status.Artifact.Revision)
logger.Successf("fetched revision %s", repository.Status.Artifact.Revision)
return nil
}
func isHelmRepositoryReady(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, helmRepository *sourcev1.HelmRepository) wait.ConditionFunc {
func helmRepositoryReconciliationHandled(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, repository *sourcev1.HelmRepository, lastHandledReconcileAt string) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, helmRepository)
err := kubeClient.Get(ctx, namespacedName, repository)
if err != nil {
return false, err
}
// Confirm the state we are observing is for the current generation
if helmRepository.Generation != helmRepository.Status.ObservedGeneration {
return false, nil
}
if c := meta.GetCondition(helmRepository.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}
return false, nil
return repository.Status.LastHandledReconcileAt != lastHandledReconcileAt, nil
}
}
func requestHelmRepositoryReconciliation(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, repository *sourcev1.HelmRepository) error {
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
if err := kubeClient.Get(ctx, namespacedName, repository); err != nil {
return err
}
if repository.Annotations == nil {
repository.Annotations = map[string]string{
meta.ReconcileAtAnnotation: time.Now().Format(time.RFC3339Nano),
}
} else {
repository.Annotations[meta.ReconcileAtAnnotation] = time.Now().Format(time.RFC3339Nano)
}
return kubeClient.Update(ctx, repository)
})
}

View File

@@ -24,7 +24,8 @@ import (
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -95,11 +96,11 @@ func isAlertResumed(ctx context.Context, kubeClient client.Client,
return false, err
}
if c := meta.GetCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
if c.Reason == meta.SuspendedReason {
return false, nil
}

View File

@@ -24,7 +24,8 @@ import (
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -103,14 +104,11 @@ func isHelmReleaseResumed(ctx context.Context, kubeClient client.Client,
return false, err
}
if c := meta.GetCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(helmRelease.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
if c.Reason == meta.SuspendedReason {
return false, nil
}
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}

View File

@@ -25,7 +25,8 @@ import (
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -102,14 +103,11 @@ func isKustomizationResumed(ctx context.Context, kubeClient client.Client,
return false, nil
}
if c := meta.GetCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
if c.Reason == meta.SuspendedReason {
return false, nil
}
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}

View File

@@ -24,7 +24,8 @@ import (
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -96,11 +97,11 @@ func isReceiverResumed(ctx context.Context, kubeClient client.Client,
return false, err
}
if c := meta.GetCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
if c := apimeta.FindStatusCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case corev1.ConditionTrue:
case metav1.ConditionTrue:
return true, nil
case corev1.ConditionFalse:
case metav1.ConditionFalse:
if c.Reason == meta.SuspendedReason {
return false, nil
}

31
cmd/flux/resume_source.go Normal file
View File

@@ -0,0 +1,31 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"github.com/spf13/cobra"
)
var resumeSourceCmd = &cobra.Command{
Use: "source",
Short: "Resume sources",
Long: "The resume sub-commands resume a suspended source.",
}
func init() {
resumeCmd.AddCommand(resumeSourceCmd)
}

View File

@@ -0,0 +1,115 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
var resumeSourceBucketCmd = &cobra.Command{
Use: "bucket [name]",
Short: "Resume a suspended Bucket",
Long: `The resume command marks a previously suspended Bucket resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing Bucket
flux resume source bucket podinfo
`,
RunE: resumeSourceBucketCmdRun,
}
func init() {
resumeSourceCmd.AddCommand(resumeSourceBucketCmd)
}
func resumeSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var bucket sourcev1.Bucket
err = kubeClient.Get(ctx, namespacedName, &bucket)
if err != nil {
return err
}
logger.Actionf("resuming source %s in %s namespace", name, namespace)
bucket.Spec.Suspend = false
if err := kubeClient.Update(ctx, &bucket); err != nil {
return err
}
logger.Successf("source resumed")
logger.Waitingf("waiting for Bucket reconciliation")
if err := wait.PollImmediate(pollInterval, timeout,
isBucketResumed(ctx, kubeClient, namespacedName, &bucket)); err != nil {
return err
}
logger.Successf("Bucket reconciliation completed")
logger.Successf("fetched revision %s", bucket.Status.Artifact.Revision)
return nil
}
func isBucketResumed(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, bucket *sourcev1.Bucket) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, bucket)
if err != nil {
return false, err
}
// Confirm the state we are observing is for the current generation
if bucket.Generation != bucket.Status.ObservedGeneration {
return false, nil
}
if c := apimeta.FindStatusCondition(bucket.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case metav1.ConditionTrue:
return true, nil
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}
return false, nil
}
}

View File

@@ -0,0 +1,115 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
var resumeSourceHelmChartCmd = &cobra.Command{
Use: "chart [name]",
Short: "Resume a suspended HelmChart",
Long: `The resume command marks a previously suspended HelmChart resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing HelmChart
flux resume source chart podinfo
`,
RunE: resumeSourceHelmChartCmdRun,
}
func init() {
resumeSourceCmd.AddCommand(resumeSourceHelmChartCmd)
}
func resumeSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var repository sourcev1.HelmChart
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
logger.Actionf("resuming source %s in %s namespace", name, namespace)
repository.Spec.Suspend = false
if err := kubeClient.Update(ctx, &repository); err != nil {
return err
}
logger.Successf("source resumed")
logger.Waitingf("waiting for HelmChart reconciliation")
if err := wait.PollImmediate(pollInterval, timeout,
isHelmChartResumed(ctx, kubeClient, namespacedName, &repository)); err != nil {
return err
}
logger.Successf("HelmChart reconciliation completed")
logger.Successf("fetched revision %s", repository.Status.Artifact.Revision)
return nil
}
func isHelmChartResumed(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, chart *sourcev1.HelmChart) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, chart)
if err != nil {
return false, err
}
// Confirm the state we are observing is for the current generation
if chart.Generation != chart.Status.ObservedGeneration {
return false, nil
}
if c := apimeta.FindStatusCondition(chart.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case metav1.ConditionTrue:
return true, nil
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}
return false, nil
}
}

View File

@@ -0,0 +1,115 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
var resumeSourceGitCmd = &cobra.Command{
Use: "git [name]",
Short: "Resume a suspended GitRepository",
Long: `The resume command marks a previously suspended GitRepository resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing GitRepository
flux resume source git podinfo
`,
RunE: resumeSourceGitCmdRun,
}
func init() {
resumeSourceCmd.AddCommand(resumeSourceGitCmd)
}
func resumeSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var repository sourcev1.GitRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
logger.Actionf("resuming source %s in %s namespace", name, namespace)
repository.Spec.Suspend = false
if err := kubeClient.Update(ctx, &repository); err != nil {
return err
}
logger.Successf("source resumed")
logger.Waitingf("waiting for GitRepository reconciliation")
if err := wait.PollImmediate(pollInterval, timeout,
isGitRepositoryResumed(ctx, kubeClient, namespacedName, &repository)); err != nil {
return err
}
logger.Successf("GitRepository reconciliation completed")
logger.Successf("fetched revision %s", repository.Status.Artifact.Revision)
return nil
}
func isGitRepositoryResumed(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, repository *sourcev1.GitRepository) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, repository)
if err != nil {
return false, err
}
// Confirm the state we are observing is for the current generation
if repository.Generation != repository.Status.ObservedGeneration {
return false, nil
}
if c := apimeta.FindStatusCondition(repository.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case metav1.ConditionTrue:
return true, nil
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}
return false, nil
}
}

View File

@@ -0,0 +1,115 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
var resumeSourceHelmCmd = &cobra.Command{
Use: "helm [name]",
Short: "Resume a suspended HelmRepository",
Long: `The resume command marks a previously suspended HelmRepository resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing HelmRepository
flux resume source helm bitnami
`,
RunE: resumeSourceHelmCmdRun,
}
func init() {
resumeSourceCmd.AddCommand(resumeSourceHelmCmd)
}
func resumeSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var repository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
logger.Actionf("resuming source %s in %s namespace", name, namespace)
repository.Spec.Suspend = false
if err := kubeClient.Update(ctx, &repository); err != nil {
return err
}
logger.Successf("source resumed")
logger.Waitingf("waiting for HelmRepository reconciliation")
if err := wait.PollImmediate(pollInterval, timeout,
isHelmRepositoryResumed(ctx, kubeClient, namespacedName, &repository)); err != nil {
return err
}
logger.Successf("HelmRepository reconciliation completed")
logger.Successf("fetched revision %s", repository.Status.Artifact.Revision)
return nil
}
func isHelmRepositoryResumed(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, repository *sourcev1.HelmRepository) wait.ConditionFunc {
return func() (bool, error) {
err := kubeClient.Get(ctx, namespacedName, repository)
if err != nil {
return false, err
}
// Confirm the state we are observing is for the current generation
if repository.Generation != repository.Status.ObservedGeneration {
return false, nil
}
if c := apimeta.FindStatusCondition(repository.Status.Conditions, meta.ReadyCondition); c != nil {
switch c.Status {
case metav1.ConditionTrue:
return true, nil
case metav1.ConditionFalse:
return false, fmt.Errorf(c.Message)
}
}
return false, nil
}
}

View File

@@ -0,0 +1,31 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"github.com/spf13/cobra"
)
var suspendSourceCmd = &cobra.Command{
Use: "source",
Short: "Suspend sources",
Long: "The suspend sub-commands suspend the reconciliation of a source.",
}
func init() {
suspendCmd.AddCommand(suspendSourceCmd)
}

View File

@@ -0,0 +1,75 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
)
var suspendSourceBucketCmd = &cobra.Command{
Use: "bucket [name]",
Short: "Suspend reconciliation of a Bucket",
Long: "The suspend command disables the reconciliation of a Bucket resource.",
Example: ` # Suspend reconciliation for an existing Bucket
flux suspend source bucket podinfo
`,
RunE: suspendSourceBucketCmdRun,
}
func init() {
suspendSourceCmd.AddCommand(suspendSourceBucketCmd)
}
func suspendSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var bucket sourcev1.Bucket
err = kubeClient.Get(ctx, namespacedName, &bucket)
if err != nil {
return err
}
logger.Actionf("suspending source %s in %s namespace", name, namespace)
bucket.Spec.Suspend = true
if err := kubeClient.Update(ctx, &bucket); err != nil {
return err
}
logger.Successf("source suspended")
return nil
}

View File

@@ -0,0 +1,75 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
)
var suspendSourceHelmChartCmd = &cobra.Command{
Use: "chart [name]",
Short: "Suspend reconciliation of a HelmChart",
Long: "The suspend command disables the reconciliation of a HelmChart resource.",
Example: ` # Suspend reconciliation for an existing HelmChart
flux suspend source chart podinfo
`,
RunE: suspendSourceHelmChartCmdRun,
}
func init() {
suspendSourceCmd.AddCommand(suspendSourceHelmChartCmd)
}
func suspendSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var chart sourcev1.HelmChart
err = kubeClient.Get(ctx, namespacedName, &chart)
if err != nil {
return err
}
logger.Actionf("suspending source %s in %s namespace", name, namespace)
chart.Spec.Suspend = true
if err := kubeClient.Update(ctx, &chart); err != nil {
return err
}
logger.Successf("source suspended")
return nil
}

View File

@@ -0,0 +1,75 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
)
var suspendSourceGitCmd = &cobra.Command{
Use: "git [name]",
Short: "Suspend reconciliation of a GitRepository",
Long: "The suspend command disables the reconciliation of a GitRepository resource.",
Example: ` # Suspend reconciliation for an existing GitRepository
flux suspend source git podinfo
`,
RunE: suspendSourceGitCmdRun,
}
func init() {
suspendSourceCmd.AddCommand(suspendSourceGitCmd)
}
func suspendSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var repository sourcev1.GitRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
logger.Actionf("suspending source %s in %s namespace", name, namespace)
repository.Spec.Suspend = true
if err := kubeClient.Update(ctx, &repository); err != nil {
return err
}
logger.Successf("source suspended")
return nil
}

View File

@@ -0,0 +1,75 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"fmt"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
)
var suspendSourceHelmCmd = &cobra.Command{
Use: "helm [name]",
Short: "Suspend reconciliation of a HelmRepository",
Long: "The suspend command disables the reconciliation of a HelmRepository resource.",
Example: ` # Suspend reconciliation for an existing HelmRepository
flux suspend source helm bitnami
`,
RunE: suspendSourceHelmCmdRun,
}
func init() {
suspendSourceCmd.AddCommand(suspendSourceHelmCmd)
}
func suspendSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("source name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var repository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
logger.Actionf("suspending source %s in %s namespace", name, namespace)
repository.Spec.Suspend = true
if err := kubeClient.Update(ctx, &repository); err != nil {
return err
}
logger.Successf("source suspended")
return nil
}

View File

@@ -144,7 +144,7 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
if uninstallDryRun {
kubectlArgs = append(kubectlArgs, dryRun)
}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubectlArgs...); err != nil {
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("uninstall failed: %w", err)
}
}
@@ -164,6 +164,6 @@ func deleteAll(ctx context.Context, kind string, dryRun bool) error {
kubectlArgs = append(kubectlArgs, "--dry-run=server")
}
_, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubectlArgs...)
_, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...)
return err
}

View File

@@ -17,6 +17,7 @@ The bootstrap sub-commands bootstrap the toolkit components on the targeted Git
--log-level logLevel log level, available options are: (debug, info, error) (default info)
--network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--token-auth when enabled, the personal access token will be used instead of SSH deploy key
-v, --version string toolkit version (default "latest")
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
```

View File

@@ -5,7 +5,7 @@ Bootstrap toolkit components in a GitHub repository
### Synopsis
The bootstrap github command creates the GitHub repository if it doesn't exists and
commits the toolkit components manifests to the master branch.
commits the toolkit components manifests to the main branch.
Then it configures the target cluster to synchronize with the repository.
If the toolkit components are present on the cluster,
the bootstrap command will perform an upgrade if needed.
@@ -32,8 +32,11 @@ flux bootstrap github [flags]
# Run bootstrap for a public repository on a personal account
flux bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true
# Run bootstrap for a private repo hosted on GitHub Enterprise
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain>
# Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --ssh-hostname=<domain>
# Run bootstrap for a private repo hosted on GitHub Enterprise using HTTPS auth
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --token-auth
# Run bootstrap for a an existing repository with a branch named main
flux bootstrap github --owner=<organization> --repository=<repo name> --branch=main
@@ -43,15 +46,16 @@ flux bootstrap github [flags]
### Options
```
-h, --help help for github
--hostname string GitHub hostname (default "github.com")
--interval duration sync interval (default 1m0s)
--owner string GitHub user or organization name
--path string repository path, when specified the cluster sync will be scoped to this path
--personal is personal repository
--private is private repository (default true)
--repository string GitHub repository name
--team stringArray GitHub team to be given maintainer access
-h, --help help for github
--hostname string GitHub hostname (default "github.com")
--interval duration sync interval (default 1m0s)
--owner string GitHub user or organization name
--path string repository path, when specified the cluster sync will be scoped to this path
--personal is personal repository
--private is private repository (default true)
--repository string GitHub repository name
--ssh-hostname string GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one
--team stringArray GitHub team to be given maintainer access
```
### Options inherited from parent commands
@@ -68,6 +72,7 @@ flux bootstrap github [flags]
--network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--timeout duration timeout for this operation (default 5m0s)
--token-auth when enabled, the personal access token will be used instead of SSH deploy key
--verbose print generated objects
-v, --version string toolkit version (default "latest")
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)

View File

@@ -21,22 +21,22 @@ flux bootstrap gitlab [flags]
export GITLAB_TOKEN=<my-token>
# Run bootstrap for a private repo using HTTPS token authentication
flux bootstrap gitlab --owner=<group> --repository=<repo name>
flux bootstrap gitlab --owner=<group> --repository=<repo name> --token-auth
# Run bootstrap for a private repo using SSH authentication
flux bootstrap gitlab --owner=<group> --repository=<repo name> --ssh-hostname=gitlab.com
flux bootstrap gitlab --owner=<group> --repository=<repo name>
# Run bootstrap for a repository path
flux bootstrap gitlab --owner=<group> --repository=<repo name> --path=dev-cluster
# Run bootstrap for a public repository on a personal account
flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal=true
flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal --token-auth
# Run bootstrap for a private repo hosted on a GitLab server
flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain>
flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain> --token-auth
# Run bootstrap for a an existing repository with a branch named main
flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main
flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main --token-auth
```
@@ -51,7 +51,7 @@ flux bootstrap gitlab [flags]
--personal is personal repository
--private is private repository (default true)
--repository string GitLab repository name
--ssh-hostname string GitLab SSH hostname, when specified a deploy key will be added to the repository
--ssh-hostname string GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one
```
### Options inherited from parent commands
@@ -68,6 +68,7 @@ flux bootstrap gitlab [flags]
--network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--timeout duration timeout for this operation (default 5m0s)
--token-auth when enabled, the personal access token will be used instead of SSH deploy key
--verbose print generated objects
-v, --version string toolkit version (default "latest")
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)

View File

@@ -34,4 +34,5 @@ The create sub-commands generate sources and resources.
* [flux create kustomization](flux_create_kustomization.md) - Create or update a Kustomization resource
* [flux create receiver](flux_create_receiver.md) - Create or update a Receiver resource
* [flux create source](flux_create_source.md) - Create or update sources
* [flux create tenant](flux_create_tenant.md) - Create or update a tenant

View File

@@ -38,6 +38,14 @@ flux create helmrelease [name] [flags]
--chart=podinfo \
--values=./my-values.yaml
# Create a HelmRelease with values from a Kubernetes secret
kubectl -n app create secret generic my-secret-values \
--from-file=values.yaml=/path/to/my-secret-values.yaml
flux -n app create hr podinfo \
--source=HelmRepository/podinfo \
--chart=podinfo \
--values-from=Secret/my-secret-values
# Create a HelmRelease with a custom release name
flux create hr podinfo \
--release-name=podinfo-dev
@@ -62,14 +70,16 @@ flux create helmrelease [name] [flags]
### Options
```
--chart string Helm chart name or path
--chart-version string Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)
--depends-on stringArray HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'
-h, --help help for helmrelease
--release-name string name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'
--source helmChartSource source that contains the chart in the format '<kind>/<name>',where kind can be one of: (HelmRepository, GitRepository, Bucket)
--target-namespace string namespace to install this release, defaults to the HelmRelease namespace
--values string local path to the values.yaml file
--chart string Helm chart name or path
--chart-version string Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)
--depends-on stringArray HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'
-h, --help help for helmrelease
--release-name string name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'
--service-account string the name of the service account to impersonate when reconciling this HelmRelease
--source helmChartSource source that contains the chart in the format '<kind>/<name>',where kind can be one of: (HelmRepository, GitRepository, Bucket)
--target-namespace string namespace to install this release, defaults to the HelmRelease namespace
--values string local path to the values.yaml file
--values-from helmReleaseValuesFrom Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>',where kind can be one of: (Secret, ConfigMap)
```
### Options inherited from parent commands

View File

@@ -50,11 +50,11 @@ flux create kustomization [name] [flags]
--health-check stringArray workload to be included in the health assessment, in the format '<kind>/<name>.<namespace>'
--health-check-timeout duration timeout of health checking operations (default 2m0s)
-h, --help help for kustomization
--path string path to the directory containing the Kustomization file (default "./")
--path string path to the directory containing a kustomization.yaml file (default "./")
--prune enable garbage collection
--sa-name string service account name
--sa-namespace string service account namespace
--service-account string the name of the service account to impersonate when reconciling this Kustomization
--source kustomizationSource source that contains the Kubernetes manifests in the format '[<kind>/]<name>',where kind can be one of: (GitRepository, Bucket), if kind is not specified it defaults to GitRepository
--target-namespace string overrides the namespace of all Kustomization objects reconciled by this Kustomization
--validation string validate the manifests before applying them on the cluster, can be 'client' or 'server'
```

View File

@@ -0,0 +1,55 @@
## flux create tenant
Create or update a tenant
### Synopsis
The create tenant command generates namespaces, service accounts and role bindings to limit the
reconcilers scope to the tenant namespaces.
```
flux create tenant [flags]
```
### Examples
```
# Create a tenant with access to a namespace
flux create tenant dev-team \
--with-namespace=frontend \
--label=environment=dev
# Generate tenant namespaces and role bindings in YAML format
flux create tenant dev-team \
--with-namespace=frontend \
--with-namespace=backend \
--export > dev-team.yaml
```
### Options
```
--cluster-role string cluster role of the tenant role binding (default "cluster-admin")
-h, --help help for tenant
--with-namespace strings namespace belonging to this tenant
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--export export in YAML format to stdout
--interval duration source sync interval (default 1m0s)
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
--label strings set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux create](flux_create.md) - Create or update sources and resources

View File

@@ -27,6 +27,7 @@ The get source sub-commands print the statuses of the sources.
* [flux get](flux_get.md) - Get sources and resources
* [flux get sources bucket](flux_get_sources_bucket.md) - Get Bucket source statuses
* [flux get sources chart](flux_get_sources_chart.md) - Get HelmChart statuses
* [flux get sources git](flux_get_sources_git.md) - Get GitRepository source statuses
* [flux get sources helm](flux_get_sources_helm.md) - Get HelmRepository source statuses

View File

@@ -16,6 +16,9 @@ flux get sources bucket [flags]
# List all Buckets and their status
flux get sources bucket
# List buckets from all namespaces
flux get sources helm --all-namespaces
```
### Options

View File

@@ -0,0 +1,44 @@
## flux get sources chart
Get HelmChart statuses
### Synopsis
The get sources chart command prints the status of the HelmCharts.
```
flux get sources chart [flags]
```
### Examples
```
# List all Helm charts and their status
flux get sources chart
# List Helm charts from all namespaces
flux get sources chart --all-namespaces
```
### Options
```
-h, --help help for chart
```
### Options inherited from parent commands
```
-A, --all-namespaces list the requested object(s) across all namespaces
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux get sources](flux_get_sources.md) - Get source statuses

View File

@@ -16,6 +16,9 @@ flux get sources git [flags]
# List all Git repositories and their status
flux get sources git
# List Git repositories from all namespaces
flux get sources git --all-namespaces
```
### Options

View File

@@ -16,6 +16,9 @@ flux get sources helm [flags]
# List all Helm repositories and their status
flux get sources helm
# List Helm repositories from all namespaces
flux get sources helm --all-namespaces
```
### Options

View File

@@ -29,4 +29,5 @@ The resume sub-commands resume a suspended resource.
* [flux resume helmrelease](flux_resume_helmrelease.md) - Resume a suspended HelmRelease
* [flux resume kustomization](flux_resume_kustomization.md) - Resume a suspended Kustomization
* [flux resume receiver](flux_resume_receiver.md) - Resume a suspended Receiver
* [flux resume source](flux_resume_source.md) - Resume sources

View File

@@ -0,0 +1,32 @@
## flux resume source
Resume sources
### Synopsis
The resume sub-commands resume a suspended source.
### Options
```
-h, --help help for source
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux resume](flux_resume.md) - Resume suspended resources
* [flux resume source bucket](flux_resume_source_bucket.md) - Resume a suspended Bucket
* [flux resume source chart](flux_resume_source_chart.md) - Resume a suspended HelmChart
* [flux resume source git](flux_resume_source_git.md) - Resume a suspended GitRepository
* [flux resume source helm](flux_resume_source_helm.md) - Resume a suspended HelmRepository

View File

@@ -0,0 +1,40 @@
## flux resume source bucket
Resume a suspended Bucket
### Synopsis
The resume command marks a previously suspended Bucket resource for reconciliation and waits for it to finish.
```
flux resume source bucket [name] [flags]
```
### Examples
```
# Resume reconciliation for an existing Bucket
flux resume source bucket podinfo
```
### Options
```
-h, --help help for bucket
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux resume source](flux_resume_source.md) - Resume sources

View File

@@ -0,0 +1,40 @@
## flux resume source chart
Resume a suspended HelmChart
### Synopsis
The resume command marks a previously suspended HelmChart resource for reconciliation and waits for it to finish.
```
flux resume source chart [name] [flags]
```
### Examples
```
# Resume reconciliation for an existing HelmChart
flux resume source chart podinfo
```
### Options
```
-h, --help help for chart
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux resume source](flux_resume_source.md) - Resume sources

View File

@@ -0,0 +1,40 @@
## flux resume source git
Resume a suspended GitRepository
### Synopsis
The resume command marks a previously suspended GitRepository resource for reconciliation and waits for it to finish.
```
flux resume source git [name] [flags]
```
### Examples
```
# Resume reconciliation for an existing GitRepository
flux resume source git podinfo
```
### Options
```
-h, --help help for git
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux resume source](flux_resume_source.md) - Resume sources

View File

@@ -0,0 +1,40 @@
## flux resume source helm
Resume a suspended HelmRepository
### Synopsis
The resume command marks a previously suspended HelmRepository resource for reconciliation and waits for it to finish.
```
flux resume source helm [name] [flags]
```
### Examples
```
# Resume reconciliation for an existing HelmRepository
flux resume source helm bitnami
```
### Options
```
-h, --help help for helm
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux resume source](flux_resume_source.md) - Resume sources

View File

@@ -29,4 +29,5 @@ The suspend sub-commands suspend the reconciliation of a resource.
* [flux suspend helmrelease](flux_suspend_helmrelease.md) - Suspend reconciliation of HelmRelease
* [flux suspend kustomization](flux_suspend_kustomization.md) - Suspend reconciliation of Kustomization
* [flux suspend receiver](flux_suspend_receiver.md) - Suspend reconciliation of Receiver
* [flux suspend source](flux_suspend_source.md) - Suspend sources

View File

@@ -0,0 +1,32 @@
## flux suspend source
Suspend sources
### Synopsis
The suspend sub-commands suspend the reconciliation of a source.
### Options
```
-h, --help help for source
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux suspend](flux_suspend.md) - Suspend resources
* [flux suspend source bucket](flux_suspend_source_bucket.md) - Suspend reconciliation of a Bucket
* [flux suspend source chart](flux_suspend_source_chart.md) - Suspend reconciliation of a HelmChart
* [flux suspend source git](flux_suspend_source_git.md) - Suspend reconciliation of a GitRepository
* [flux suspend source helm](flux_suspend_source_helm.md) - Suspend reconciliation of a HelmRepository

View File

@@ -0,0 +1,40 @@
## flux suspend source bucket
Suspend reconciliation of a Bucket
### Synopsis
The suspend command disables the reconciliation of a Bucket resource.
```
flux suspend source bucket [name] [flags]
```
### Examples
```
# Suspend reconciliation for an existing Bucket
flux suspend source bucket podinfo
```
### Options
```
-h, --help help for bucket
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux suspend source](flux_suspend_source.md) - Suspend sources

View File

@@ -0,0 +1,40 @@
## flux suspend source chart
Suspend reconciliation of a HelmChart
### Synopsis
The suspend command disables the reconciliation of a HelmChart resource.
```
flux suspend source chart [name] [flags]
```
### Examples
```
# Suspend reconciliation for an existing HelmChart
flux suspend source chart podinfo
```
### Options
```
-h, --help help for chart
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux suspend source](flux_suspend_source.md) - Suspend sources

View File

@@ -0,0 +1,40 @@
## flux suspend source git
Suspend reconciliation of a GitRepository
### Synopsis
The suspend command disables the reconciliation of a GitRepository resource.
```
flux suspend source git [name] [flags]
```
### Examples
```
# Suspend reconciliation for an existing GitRepository
flux suspend source git podinfo
```
### Options
```
-h, --help help for git
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux suspend source](flux_suspend_source.md) - Suspend sources

View File

@@ -0,0 +1,40 @@
## flux suspend source helm
Suspend reconciliation of a HelmRepository
### Synopsis
The suspend command disables the reconciliation of a HelmRepository resource.
```
flux suspend source helm [name] [flags]
```
### Examples
```
# Suspend reconciliation for an existing HelmRepository
flux suspend source helm bitnami
```
### Options
```
-h, --help help for helm
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux suspend source](flux_suspend_source.md) - Suspend sources

View File

@@ -60,7 +60,7 @@ Flux v1 repository to the bootstrap one.
## In-place migration
!!! warning
For production use we recommend using the **bootstrap** procedure,
For production use we recommend using the **bootstrap** procedure (see the [Gitops migration](#gitops-migration) section above),
but if you wish to install Flux v2 in the
same way as Flux v1 then follow along.
@@ -112,7 +112,7 @@ $ flux install \
--arch=amd64 \
--network-policy=true \
--watch-all-namespaces=true \
--namespace=flux-systen
--namespace=flux-system
✚ generating manifests
✔ manifests build completed
► installing components in flux-system namespace

View File

@@ -710,7 +710,7 @@ The custom resources for the Helm Controller would be:
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metdata:
metadata:
name: podinfo
namespace: default
spec:
@@ -724,6 +724,7 @@ metadata:
namespace: default
spec:
interval: 5m
releaseName: default-podinfo
chart:
spec:
chart: podinfo

View File

@@ -257,6 +257,115 @@ The definition of the listed keys is as follows:
You can read more about the available formats and limitations in
the [Helm documentation](https://helm.sh/docs/intro/using_helm/#the-format-and-limitations-of---set).
## Refer to values in `ConfigMaps` generated with Kustomize
It is possible to use Kustomize [ConfigMap generator](https://kubectl.docs.kubernetes.io/references/kustomize/configmapgenerator/)
to trigger a Helm release upgrade every time the encoded values change.
First create a `kustomizeconfig.yaml` for Kustomize to be able to patch
`ConfigMaps` referenced in `HelmRelease` manifests:
```yaml
nameReference:
- kind: ConfigMap
version: v1
fieldSpecs:
- path: spec/valuesFrom/name
kind: HelmRelease
```
Create a `HelmRelease` definition that references a `ConfigMap`:
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: podinfo
namespace: podinfo
spec:
interval: 5m
releaseName: podinfo
chart:
spec:
chart: podinfo
sourceRef:
kind: HelmRepository
name: podinfo
valuesFrom:
- kind: ConfigMap
name: podinfo-values
```
Create a `kustomization.yaml` that generates the `ConfigMap` using our kustomize config:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: podinfo
resources:
- namespace.yaml
- repository.yaml
- release.yaml
configMapGenerator:
- name: podinfo-values
files:
- values.yaml=my-values.yaml
configurations:
- kustomizeconfig.yaml
```
When [kustomize-controller](../components/kustomize/controller.md) reconciles the above manifests, it will generate
a unique name of the `ConfigMap` every time `my-values.yaml` content is updated in Git:
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: podinfo
namespace: podinfo
spec:
valuesFrom:
- kind: ConfigMap
name: podinfo-values-2mh2t8m94h
```
!!! hint "Note"
Stale `ConfigMaps`, previously generated by Kustomize, will be
removed from the cluster by kustomize-controller if
[pruning](../components/kustomize/kustomization/#garbage-collection) is enabled.
## Refer to values inside the chart
It is possible to replace the `values.yaml` with a different file present inside the Helm chart.
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: mongodb
namespace: mongodb
spec:
interval: 5m
chart:
spec:
chart: mongodb
sourceRef:
kind: HelmRepository
name: bitnami
valuesFile: values-production.yaml
values:
replicaCount: 5
```
If the `spec.chart.spec.valuesFile` doesn't exists inside the chart, helm-controller will not be able to
fetch the chart. To determine why the `HelmChart` fails to produce an artifact, you can inspect the status with:
```console
$ kubectl get helmcharts --all-namespaces
NAME READY STATUS
mongodb False failed to locate override values file: values-prod.yaml
```
## Configure notifications
The default toolkit installation configures the helm-controller to

View File

@@ -44,12 +44,12 @@ Kubernetes cluster and configure it to manage itself from a Git
repository.
The bootstrap creates a Git repository if one doesn't exist and
commits the Flux components manifests to the main branch. Then it
commits the Flux components manifests to the main branch. Then it
configures the target cluster to synchronize with that repository by
setting up SSH deploy keys.
If the Flux components are present on the cluster, the bootstrap
command will perform an upgrade if needed. The bootstrap is
command will perform an upgrade if needed. The bootstrap is
idempotent, it's safe to run the command as many times as you want.
You can choose what components to install and for which cluster with:
@@ -57,7 +57,7 @@ You can choose what components to install and for which cluster with:
```sh
flux bootstrap <GIT-PROVIDER> \
--components=source-controller,kustomize-controller,helm-controller,notification-controller \
--path=my-cluster \
--path=clusters/my-cluster \
--version=latest
```
@@ -71,15 +71,16 @@ If you wish to install a specific version, use the Flux
With `--path` you can configure the directory which will be used to reconcile the target cluster.
To control multiple clusters from the same Git repository, you have to set a unique path per
cluster e.g. `staging-cluster` and `production-cluster`:
cluster e.g. `clusters/staging` and `clusters/production`:
```sh
├── staging-cluster # <- path=staging-cluster
./clusters/
├── staging # <- path=clusters/staging
│   └── flux-system # <- namespace dir generated by bootstrap
│   ├── gotk-components.yaml
│   ├── gotk-sync.yaml
│   └── kustomization.yaml
└── production-cluster # <- path=production-cluster
└── production-cluster # <- path=clusters/production
└── flux-system
```
@@ -87,6 +88,9 @@ cluster e.g. `staging-cluster` and `production-cluster`:
If you wish to change the branch to something else than main, create the repository manually,
push a branch to origin and then use `flux bootstrap <GIT-PROVIDER> --branch=your-branch`.
For examples on how you can structure your Git repository see:
* [flux2-kustomize-helm-example](https://github.com/fluxcd/flux2-kustomize-helm-example)
### GitHub and GitHub Enterprise
Generate a [personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)
@@ -104,7 +108,7 @@ Run the bootstrap for a repository on your personal GitHub account:
flux bootstrap github \
--owner=my-github-username \
--repository=my-repository \
--path=my-cluster \
--path=clusters/my-cluster \
--personal
```
@@ -116,7 +120,7 @@ flux bootstrap github \
--repository=my-repository \
--team=team1-slug \
--team=team2-slug \
--path=my-cluster
--path=clusters/my-cluster
```
When you specify a list of teams, those teams will be granted maintainer access to the repository.
@@ -126,10 +130,23 @@ To run the bootstrap for a repository hosted on GitHub Enterprise, you have to s
```sh
flux bootstrap github \
--hostname=my-github-enterprise.com \
--ssh-hostname=my-github-enterprise.com \
--owner=my-github-organization \
--repository=my-repository \
--branch=main \
--path=my-cluster
--path=clusters/my-cluster
```
If your GitHub Enterprise has SSH access disabled, you can use HTTPS and token authentication with:
```sh
flux bootstrap github \
--token-auth \
--hostname=my-github-enterprise.com \
--owner=my-github-organization \
--repository=my-repository \
--branch=main \
--path=clusters/my-cluster
```
### GitLab and GitLab Enterprise
@@ -150,7 +167,8 @@ flux bootstrap gitlab \
--owner=my-gitlab-username \
--repository=my-repository \
--branch=master \
--path=my-cluster \
--path=clusters/my-cluster \
--token-auth \
--personal
```
@@ -162,7 +180,7 @@ flux bootstrap gitlab \
--owner=my-gitlab-username \
--repository=my-repository \
--branch=master \
--path=my-cluster
--path=clusters/my-cluster
```
!!! hint "Authentication"
@@ -177,7 +195,7 @@ flux bootstrap gitlab \
--owner=my-gitlab-group \
--repository=my-repository \
--branch=master \
--path=my-cluster
--path=clusters/my-cluster
```
To run the bootstrap for a repository hosted on GitLab on-prem or enterprise, you have to specify your GitLab hostname:
@@ -185,10 +203,11 @@ To run the bootstrap for a repository hosted on GitLab on-prem or enterprise, yo
```sh
flux bootstrap gitlab \
--hostname=my-gitlab.com \
--token-auth \
--owner=my-gitlab-group \
--repository=my-repository \
--branch=master \
--path=my-cluster
--path=clusters/my-cluster
```
### Generic Git Server
@@ -205,15 +224,16 @@ cd my-repository
Create a directory inside the repository:
```sh
mkdir -p ./my-cluster/flux-system
mkdir -p ./clusters/my-cluster/flux-system
```
Generate the Flux manifests with:
```sh
# on ARM64/AARCH64 clusters use --arch=arm64
flux install --version=latest \
--arch=amd64 \ # on ARM64/AARCH64 clusters use --arch=arm64
--export > ./my-cluster/flux-system/gotk-components.yaml
--arch=amd64 \
--export > ./clusters/my-cluster/flux-system/gotk-components.yaml
```
If your cluster must pull images from a private container registry, first you should pull
@@ -241,7 +261,7 @@ Set your registry domain, and the pull secret when generating the manifests:
flux install --version=latest \
--registry=registry.internal/fluxcd \
--image-pull-secret=regcred \
--export > ./my-cluster/flux-system/gotk-components.yaml
--export > ./clusters/my-cluster/flux-system/gotk-components.yaml
```
Commit and push the manifest to the master branch:
@@ -253,7 +273,7 @@ git add -A && git commit -m "add components" && git push
Apply the manifests on your cluster:
```sh
kubectl apply -f ./my-cluster/flux-system/gotk-components.yaml
kubectl apply -f ./clusters/my-cluster/flux-system/gotk-components.yaml
```
Verify that the controllers have started:
@@ -292,7 +312,7 @@ Create a `Kustomization` object on your cluster:
```sh
flux create kustomization flux-system \
--source=flux-system \
--path="./my-cluster" \
--path="./clusters/my-cluster" \
--prune=true \
--interval=10m
```
@@ -301,12 +321,12 @@ Export both objects, generate a `kustomization.yaml`, commit and push the manife
```sh
flux export source git flux-system \
> ./my-cluster/flux-system/gotk-sync.yaml
> ./clusters/my-cluster/flux-system/gotk-sync.yaml
flux export kustomization flux-system \
>> ./my-cluster/flux-system/gotk-sync.yaml
>> ./clusters/my-cluster/flux-system/gotk-sync.yaml
cd ./my-cluster/flux-system && kustomize create --autodetect
cd ./clusters/my-cluster/flux-system && kustomize create --autodetect
git add -A && git commit -m "add sync manifests" && git push
```
@@ -315,7 +335,7 @@ To upgrade the Flux components to a newer version, run the install command and c
```sh
flux install --version=latest \
--export > ./my-cluster/flux-system/gotk-components.yaml
--export > ./clusters/my-cluster/flux-system/gotk-components.yaml
git add -A && git commit -m "update flux" && git push
```
@@ -323,15 +343,106 @@ git add -A && git commit -m "update flux" && git push
The source-controller will pull the changes on the cluster, then the kustomize-controller
will perform a rolling update of all Flux components including itself.
## Dev install
## Bootstrap with Terraform
For testing purposes you can install Flux without storing its manifests in a Git repository.
The bootstrap procedure can be implemented with Terraform using the Flux provider published on
[registry.terraform.io](https://registry.terraform.io/providers/fluxcd/flux).
Here is the equivalent to `fluxctl install`:
The provider consists of two data sources (`flux_install` and `flux_sync`) for generating the
Kubernetes manifests that can be used to install or upgrade Flux:
```hcl
data "flux_install" "main" {
target_path = "clusters/my-cluster"
arch = "amd64"
network_policy = false
version = "latest"
}
data "flux_sync" "main" {
target_path = "clusters/my-cluster"
url = "https://github.com/${var.github_owner}/${var.repository_name}"
branch = "main"
}
```
For more details on how to use the Terraform provider
please see [fluxcd/terraform-provider-flux](https://github.com/fluxcd/terraform-provider-flux).
## Customize Flux manifests
You can customize the Flux components in the Git repository where you've run bootstrap with Kustomize patches.
First clone the repository locally and generate a `kustomization.yaml` file with:
```sh
flux install \
--components=source-controller,kustomize-controller
cd ./clusters/production && kustomize create --autodetect
```
Assuming you want to add custom annotations and labels to the Flux controllers in `clusters/production`.
Create a Kustomize patch and set the metadata for source-controller and kustomize-controller pods:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: source-controller
namespace: flux-system
spec:
template:
metadata:
annotations:
custom: annotation
labels:
custom: label
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kustomize-controller
namespace: flux-system
spec:
template:
metadata:
annotations:
custom: annotation
labels:
custom: label
```
Save the above file as `flux-system-patch.yaml` inside the `clusters/production` dir.
Edit `clusters/production/kustomization.yaml` and add the patch:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- flux-system
patchesStrategicMerge:
- flux-system-patch.yaml
```
Push the changes to main branch:
```sh
git add -A && git commit -m "add production metadata" && git push
```
Flux will detect the change and will update itself on the production cluster.
## Dev install
For testing purposes you can install Flux without storing its manifests in a Git repository:
```sh
flux install --arch=amd64
```
Or using kustomize and kubectl:
```sh
kustomize build https://github.com/fluxcd/flux2/manifests/install?ref=main | kubectl apply -f-
```
Then you can register Git repositories and reconcile them on your cluster:
@@ -352,35 +463,91 @@ flux create kustomization podinfo-default \
--health-check-timeout=2m
```
Here is the equivalent to `helm install helm-operator`:
You can register Helm repositories and create Helm releases:
```sh
flux install \
--components=source-controller,kustomize-controller,helm-controller
flux create source helm bitnami \
--interval=1h \
--url=https://charts.bitnami.com/bitnami
flux create helmrelease nginx \
--interval=1h \
--release-name=nginx-ingress-controller \
--target-namespace=kube-system \
--source=HelmRepository/bitnami \
--chart=nginx-ingress-controller \
--chart-version="5.x.x"
```
Then you can register Helm repositories and create Helm releases:
## Upgrade
Update Flux CLI to the latest release with `brew upgrade fluxcd/tap/flux` or by
downloading the binary from [GitHub](https://github.com/fluxcd/flux2/releases).
Verify that you are running the latest version with:
```sh
flux create source helm stable \
--interval=1h \
--url=https://charts.helm.sh/stable
flux create helmrelease sealed-secrets \
--interval=1h \
--release-name=sealed-secrets \
--target-namespace=flux-system \
--source=HelmRepository/stable \
--chart=sealed-secrets \
--chart-version="1.10.x"
flux --version
```
## Monitoring with Prometheus and Grafana
### Bootstrap upgrade
Flux comes with a monitoring stack composed of Prometheus and Grafana. The controllers expose
metrics that can be used to track the readiness of the cluster reconciliation process.
If you've used the [bootstrap](#bootstrap) procedure to deploy Flux,
then rerun the bootstrap command for each cluster using the same arguments as before:
To install the monitoring stack please follow this [guide](monitoring.md).
```sh
flux bootstrap github \
--owner=my-github-username \
--repository=my-repository \
--branch=main \
--path=clusters/my-cluster \
--personal
```
The above command will clone the repository, it will update the components manifest in
`<path>/flux-system/gotk-components.yaml` and it will push the changes to the remote branch.
Tell Flux to pull the manifests from Git and upgrade itself with:
```sh
flux reconcile source git flux-system
```
Verify that the controllers have been upgrade with:
```sh
flux check
```
### Terraform upgrade
Update the Flux provider to the [latest release](https://github.com/fluxcd/terraform-provider-flux/releases)
and run `terraform apply`.
Tell Flux to upgrade itself in-cluster or wait for it to pull the latest commit from Git:
```sh
kubectl annotate --overwrite gitrepository/flux-system reconcile.fluxcd.io/requestedAt="$(date +%s)"
```
### In-cluster upgrade
If you've installed Flux directly on the cluster, then rerun the install command:
```sh
flux install --version=latest
```
The above command will download the latest manifests from
[GitHub](https://github.com/fluxcd/flux2/releases) and it will apply them on your cluster.
You can verify that the controllers have been upgraded to the latest version with `flux check`.
If you've installed Flux directly on the cluster with kubectl,
then rerun the command using the latest manifests from the `main` branch:
```sh
kustomize build https://github.com/fluxcd/flux2/manifests/install?ref=main | kubectl apply -f-
```
## Uninstall

View File

@@ -1,12 +1,12 @@
# Manage Kubernetes secrets with Mozilla SOPS
In order to store secrets safely in a public or private Git repository, you can use
Mozilla's [SOPS](https://github.com/mozilla/sops) CLI to encrypt
Mozilla's [SOPS](https://github.com/mozilla/sops) CLI to encrypt
Kubernetes secrets with OpenPGP, AWS KMS, GCP KMS and Azure Key Vault.
## Prerequisites
To follow this guide you'll need a Kubernetes cluster with the GitOps
To follow this guide you'll need a Kubernetes cluster with the GitOps
toolkit controllers installed on it.
Please see the [get started guide](../get-started/index.md)
or the [installation guide](installation.md).
@@ -26,7 +26,7 @@ $ gpg --full-generate-key
Real name: stefanprodan
Email address: stefanprodan@users.noreply.github.com
Comment:
Comment:
You selected this USER-ID:
"stefanprodan <stefanprodan@users.noreply.github.com>"
```
@@ -48,7 +48,7 @@ gpg --export-secret-keys \
--armor 1F3D1CED2F865F5E59CA564553241F147E7C5FA4 |
kubectl create secret generic sops-gpg \
--namespace=flux-system \
--from-file=sops.asc=/dev/stdin
--from-file=sops.asc=/dev/stdin
```
## Encrypt secrets
@@ -78,6 +78,9 @@ sops --encrypt \
You can now commit the encrypted secret to your Git repository.
!!! hint
Note that you shouldn't apply the encrypted secrets onto the cluster with kubectl. SOPS encrypted secrets are designed to be consumed by kustomize-controller.
## Configure secrets decryption
Registry the Git repository on your cluster:
@@ -101,11 +104,36 @@ flux create kustomization my-secrets \
Note that the `sops-gpg` can contain more than one key, sops will try to decrypt the
secrets by iterating over all the private keys until it finds one that works.
!!! hint KMS
When using AWS/GCP KMS or Azure Key Vault, you'll have to bind an IAM Role
with read access to the KMS keys to the `default` service account of the
`flux-system` namespace for kustomize-controller to be able to fetch
keys from KMS.
### AWS/Azure/GCP
When using AWS/GCP KMS, you'll have to bind an IAM Role with access to the KMS
keys to the `default` service account of the `flux-system` namespace for
kustomize-controller to be able to fetch keys from KMS.
AWS IAM Role example:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Effect": "Allow",
"Resource": "arn:aws:kms:eu-west-1:XXXXX209540:key/4f581f5b-7f78-45e9-a543-83a7022e8105"
}
]
}
```
When using Azure Key Vault you need to authenticate the kustomize controller either by passing
[Service Principal credentials as environment variables](https://github.com/mozilla/sops#encrypting-using-azure-key-vault)
or with [add-pod-identity](https://github.com/Azure/aad-pod-identity).
## GitOps workflow
@@ -161,6 +189,6 @@ to a database using a username and password, they'll be doing the following:
Once the manifests have been pushed to the Git repository, the following happens:
* source-controller pulls the changes from Git
* kustomize-controller loads the GPG keys from the `sops-pgp` secret
* kustomize-controller loads the GPG keys from the `sops-pgp` secret
* kustomize-controller decrypts the Kubernetes secrets with sops and applies them on the cluster
* kubelet creates the pods and mounts the secret as a volume or env variable inside the app container

View File

@@ -92,4 +92,5 @@ Tasks
- [x] <span style="color:grey">Implement support for Helm charts from Git</span>
- [x] <span style="color:grey">Implement support for referring to an alternative chart values file</span>
- [x] <span style="color:grey">Stabilize API</span>
- [ ] Create a migration guide for Helm Operator users
- [x] <span style="color:grey">[Create a migration guide for Helm Operator users](../guides/helm-operator-migration.md)</span>
- [ ] [Gather feedback on the migration guide](https://github.com/fluxcd/flux2/discussions/413)

12
go.mod
View File

@@ -4,15 +4,15 @@ go 1.15
require (
github.com/blang/semver/v4 v4.0.0
github.com/fluxcd/helm-controller/api v0.2.0
github.com/fluxcd/kustomize-controller/api v0.2.1
github.com/fluxcd/notification-controller/api v0.2.0
github.com/fluxcd/pkg/apis/meta v0.2.0
github.com/fluxcd/helm-controller/api v0.4.1
github.com/fluxcd/kustomize-controller/api v0.4.0
github.com/fluxcd/notification-controller/api v0.4.0
github.com/fluxcd/pkg/apis/meta v0.4.0
github.com/fluxcd/pkg/git v0.0.7
github.com/fluxcd/pkg/runtime v0.2.0
github.com/fluxcd/pkg/runtime v0.3.1
github.com/fluxcd/pkg/ssh v0.0.5
github.com/fluxcd/pkg/untar v0.0.5
github.com/fluxcd/source-controller/api v0.2.1
github.com/fluxcd/source-controller/api v0.4.1
github.com/manifoldco/promptui v0.7.0
github.com/olekukonko/tablewriter v0.0.4
github.com/spf13/cobra v1.0.0

69
go.sum
View File

@@ -1,6 +1,5 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
@@ -15,20 +14,16 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0=
github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest/adal v0.5.0 h1:q2gDruN08/guU9vAjuPWff0+QIrpH6ediguzdAzXAUU=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0=
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/date v0.1.0 h1:YGrhWfrgtFs84+h0o46rJrlmsZtyZRg470CqAXTZaGM=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0 h1:Ww5g4zThfD/6cLb4z6xxgeyDa7QDkizMkJKe0ysZXp0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
@@ -67,7 +62,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@@ -138,30 +132,25 @@ github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fluxcd/helm-controller/api v0.2.0 h1:HWfqy4rUlo4ck+YnTIMcwWBrfeK2sW7lHCwNBcEI5Y4=
github.com/fluxcd/helm-controller/api v0.2.0/go.mod h1:02vw8JOlzdOysJ8p5AMp7XhPqtH9DS12VIeN46yzHY0=
github.com/fluxcd/kustomize-controller/api v0.2.1 h1:9qtOFdUXIF1j0PW+3c9c/VU+fA4EibnL4Ogz1qgazPw=
github.com/fluxcd/kustomize-controller/api v0.2.1/go.mod h1:rNS7iETBnm3BvZmPtaLM1otIIyiu4SPeJEL2H2X0uAc=
github.com/fluxcd/notification-controller/api v0.2.0 h1:8bToM5qayZHWdayxC+/xKgIWTqW1scc6hk86sCvspa0=
github.com/fluxcd/notification-controller/api v0.2.0/go.mod h1:ygBRvQxylsFhYxcot2sbX29B3H2g9WYlWRX0DKtI/lQ=
github.com/fluxcd/pkg/apis/meta v0.0.2 h1:kyA4Y0IzNjf1joBOnFqpWG7aNDHvtLExZcaHQM7qhRI=
github.com/fluxcd/pkg/apis/meta v0.0.2/go.mod h1:nCNps5JJOcEQr3MNDmZqI4o0chjePSUYL6Q2ktDtotU=
github.com/fluxcd/pkg/apis/meta v0.1.0 h1:CfOYHYaHslhcb3QlzgKCOXl4ziCbA5zG/fUa1qFlHis=
github.com/fluxcd/pkg/apis/meta v0.1.0/go.mod h1:nCNps5JJOcEQr3MNDmZqI4o0chjePSUYL6Q2ktDtotU=
github.com/fluxcd/pkg/apis/meta v0.2.0 h1:bxoFQtZM6OLLj0+n3h6ga7IEWUtGEDJPc65OWiXSMvY=
github.com/fluxcd/pkg/apis/meta v0.2.0/go.mod h1:50RLLSfqM4LlQrh/+5LiJVf7Hjdthee8WDdXBvpjBdA=
github.com/fluxcd/helm-controller/api v0.4.1 h1:XOYJQQDukRmMXDuqSusSoW3gOQr7BEPKJfpiUnBQzvQ=
github.com/fluxcd/helm-controller/api v0.4.1/go.mod h1:2oU4Q26TW39IGC7tmJehCNJpISj8ovpU0DoRI7Y76wE=
github.com/fluxcd/kustomize-controller/api v0.4.0 h1:QBilPNIFf5VCmJrt0L96iPWfV0lRT28n6vD+W7Kz88s=
github.com/fluxcd/kustomize-controller/api v0.4.0/go.mod h1:NB4aJ+hSWyg6Tx6p47ZWExzjwq4sPRRYvaP02JrHrNU=
github.com/fluxcd/notification-controller/api v0.4.0 h1:x7QwF7F/uG0JuaMaEBWqHWhy5DLJEsC3zWlj5rK6kB8=
github.com/fluxcd/notification-controller/api v0.4.0/go.mod h1:D/PyTHO0LiwEKwpBqbzJbjolJs1Ggw/tCMaLc7BHQi4=
github.com/fluxcd/pkg/apis/meta v0.3.0/go.mod h1:wOzQQx8CdtUQCGaLzqGu4QgnNxYkI6/wvdvlovxWhF0=
github.com/fluxcd/pkg/apis/meta v0.4.0 h1:JChqB9GGgorW9HWKxirTVV0rzrcLyzBaVjinmqZ0iHA=
github.com/fluxcd/pkg/apis/meta v0.4.0/go.mod h1:wOzQQx8CdtUQCGaLzqGu4QgnNxYkI6/wvdvlovxWhF0=
github.com/fluxcd/pkg/git v0.0.7 h1:tFSYPy7tcIYfOt8H5EUERXIRz7fk0id302oQZde1NtU=
github.com/fluxcd/pkg/git v0.0.7/go.mod h1:5Vu92x6Q3CpxDUllmB69kAkVY5jAtPpXcY2TSZ/oCJI=
github.com/fluxcd/pkg/runtime v0.1.2 h1:bKhjJGVOJgTQTWjqhwasyt69lBItq1ZWjX04rUkiypo=
github.com/fluxcd/pkg/runtime v0.1.2/go.mod h1:HXYTNdkK8ulcT1mhuGhio9tsX65ACKaealtd/MsnkhM=
github.com/fluxcd/pkg/runtime v0.2.0 h1:aZmSLuyA9pF/KANf4wi7pZIICE19BKTYFSPRbl6WHtY=
github.com/fluxcd/pkg/runtime v0.2.0/go.mod h1:P1/S8TOSuJgVPU0SRahWzbNxLWYoUwvBcPCNGc+dWWg=
github.com/fluxcd/pkg/runtime v0.3.1 h1:UI+FQd1OgipZ6N8YxXHtKYMAu1NRFWaR/Gp1M3T6RZA=
github.com/fluxcd/pkg/runtime v0.3.1/go.mod h1:wg33L6k5FkGEYoZta7hbUlBIscM5VZd/PfCbaEi+wK4=
github.com/fluxcd/pkg/ssh v0.0.5 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A=
github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs=
github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk=
github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw=
github.com/fluxcd/source-controller/api v0.2.1 h1:CK2vpnEHa1nB1cqc3dAuO+hL6HGcSnh2xGmQfzmGef4=
github.com/fluxcd/source-controller/api v0.2.1/go.mod h1:1ac/vj49YVPKF+xBHTo/9pfFj64TcLc1RLaxi4MwVEM=
github.com/fluxcd/source-controller/api v0.4.1 h1:HiMg8XNqGEDeelGG22GfCUGgfyXffiXyluDYsRrjvLQ=
github.com/fluxcd/source-controller/api v0.4.1/go.mod h1:MYmvbADJp/21m4C+PEY7WXCeqEErMYuhns+jnKyewqs=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -190,13 +179,10 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v0.2.1 h1:fV3MLmabKIZ383XifUjFSwcoGee0v9qgPp8wy5svibE=
github.com/go-logr/logr v0.2.1/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/zapr v0.1.0 h1:h+WVe9j6HAA01niTJPA/kKH0i7e0rLZBCwauQFcRE54=
github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
github.com/go-logr/zapr v0.2.0 h1:v6Ji8yBW77pva6NkJKQdHLAJKrIJKRHz0RXwPqCHSR4=
github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU=
@@ -274,7 +260,6 @@ github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA=
@@ -339,11 +324,9 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk=
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@@ -359,7 +342,6 @@ github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVo
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY=
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo=
github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
@@ -439,7 +421,6 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
@@ -491,7 +472,6 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -501,7 +481,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
@@ -512,14 +491,12 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
@@ -692,14 +669,12 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -742,7 +717,6 @@ golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8=
@@ -809,7 +783,6 @@ google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
@@ -838,7 +811,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
@@ -880,35 +852,24 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
k8s.io/api v0.18.9 h1:7VDtivqwbvLOf8hmXSd/PDSSbpCBq49MELg84EYBYiQ=
k8s.io/api v0.18.9/go.mod h1:9u/h6sUh6FxfErv7QqetX1EB3yBMIYOBXzdcf0Gf0rc=
k8s.io/api v0.19.3 h1:GN6ntFnv44Vptj/b+OnMW7FmzkpDoIDLZRvKX3XH9aU=
k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs=
k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M=
k8s.io/apiextensions-apiserver v0.18.9 h1:tVEf8rVKh5BnXORnYYCztjbf6CSyGNMt/rAIEyfU00Q=
k8s.io/apiextensions-apiserver v0.18.9/go.mod h1:JagmAhU0TVENzgUZqHJsjCSDh7YuV5o6g01G1Fwh7zI=
k8s.io/apiextensions-apiserver v0.19.3 h1:WZxBypSHW4SdXHbdPTS/Jy7L2la6Niggs8BuU5o+avo=
k8s.io/apiextensions-apiserver v0.19.3/go.mod h1:igVEkrE9TzInc1tYE7qSqxaLg/rEAp6B5+k9Q7+IC8Q=
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/apimachinery v0.18.9 h1:3ZABKQx3F3xPWlsGhCfUl8W+JXRRblV6Wo2A3zn0pvY=
k8s.io/apimachinery v0.18.9/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc=
k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg=
k8s.io/apiserver v0.18.9/go.mod h1:vXQzMtUCLsGg1Bh+7Jo2mZKHpHZFCZn8eTNSepcIA1M=
k8s.io/apiserver v0.19.3/go.mod h1:bx6dMm+H6ifgKFpCQT/SAhPwhzoeIMlHIaibomUDec0=
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
k8s.io/client-go v0.18.9 h1:sPHX49yOtUqv1fl49TwV3f8cC0N3etSnwgFGsIsXnZc=
k8s.io/client-go v0.18.9/go.mod h1:UjkEetDmr40P9NX0Ok3Idt08FCf2I4mIHgjFsot77uY=
k8s.io/client-go v0.19.3 h1:ctqR1nQ52NUs6LpI0w+a5U+xjYwflFwA13OJKcicMxg=
k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM=
k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/code-generator v0.18.9/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/code-generator v0.19.3/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk=
k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14=
k8s.io/component-base v0.18.9/go.mod h1:tUo4qZtV8m7t/U+0DgY+fcnn4BFZ480fZdzxOkWH4zk=
k8s.io/component-base v0.19.3/go.mod h1:WhLWSIefQn8W8jxSLl5WNiR6z8oyMe/8Zywg7alOkRc=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@@ -918,18 +879,15 @@ k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUc
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.0.0 h1:Foj74zO6RbjjP4hBEKjnYtjjAhGg4jNynUdYF6fJrok=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE=
k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
@@ -948,7 +906,6 @@ sigs.k8s.io/kustomize/kyaml v0.9.3/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKW
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=

View File

@@ -42,7 +42,10 @@ setup_verify_arch() {
ARCH=$(uname -m)
fi
case ${ARCH} in
arm64)
arm|armv6l|armv7l)
ARCH=arm
;;
arm64|aarch64|armv8l)
ARCH=arm64
;;
amd64)

View File

@@ -0,0 +1,71 @@
/*
Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package flags
import (
"fmt"
"strings"
"github.com/fluxcd/flux2/internal/utils"
)
var supportedHelmReleaseValuesFromKinds = []string{"Secret", "ConfigMap"}
type HelmReleaseValuesFrom struct {
Kind string
Name string
}
func (h *HelmReleaseValuesFrom) String() string {
if h.Name == "" {
return ""
}
return fmt.Sprintf("%s/%s", h.Kind, h.Name)
}
func (h *HelmReleaseValuesFrom) Set(str string) error {
if strings.TrimSpace(str) == "" {
return fmt.Errorf("no values given, please specify %s",
h.Description())
}
sourceKind, sourceName := utils.ParseObjectKindName(str)
if sourceKind == "" {
return fmt.Errorf("invalid Kubernetes object reference '%s', must be in format <kind>/<name>", str)
}
if !utils.ContainsItemString(supportedHelmReleaseValuesFromKinds, sourceKind) {
return fmt.Errorf("reference kind '%s' is not supported, can be one of: %s",
sourceKind, strings.Join(supportedHelmReleaseValuesFromKinds, ", "))
}
h.Name = sourceName
h.Kind = sourceKind
return nil
}
func (h *HelmReleaseValuesFrom) Type() string {
return "helmReleaseValuesFrom"
}
func (h *HelmReleaseValuesFrom) Description() string {
return fmt.Sprintf(
"Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>',"+
"where kind can be one of: (%s)",
strings.Join(supportedHelmReleaseValuesFromKinds, ", "),
)
}

View File

@@ -60,9 +60,17 @@ const (
ModeCapture ExecMode = "capture.stderr|stdout"
)
func ExecKubectlCommand(ctx context.Context, mode ExecMode, args ...string) (string, error) {
func ExecKubectlCommand(ctx context.Context, mode ExecMode, kubeConfigPath string, kubeContext string, args ...string) (string, error) {
var stdoutBuf, stderrBuf bytes.Buffer
if kubeConfigPath != "" {
args = append(args, "--kubeconfig="+kubeConfigPath)
}
if kubeContext != "" {
args = append(args, "--context="+kubeContext)
}
c := exec.CommandContext(ctx, "kubectl", args...)
if mode == ModeStderrOS {

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/helm-controller/archive/v0.2.0.zip//helm-controller-0.2.0/config/crd
- https://github.com/fluxcd/helm-controller/archive/v0.2.0.zip//helm-controller-0.2.0/config/manager
- https://github.com/fluxcd/helm-controller/archive/v0.4.1.zip//helm-controller-0.4.1/config/crd
- https://github.com/fluxcd/helm-controller/archive/v0.4.1.zip//helm-controller-0.4.1/config/manager
patchesJson6902:
- target:
group: apps

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/kustomize-controller/archive/v0.2.1.zip//kustomize-controller-0.2.1/config/crd
- https://github.com/fluxcd/kustomize-controller/archive/v0.2.1.zip//kustomize-controller-0.2.1/config/manager
- https://github.com/fluxcd/kustomize-controller/archive/v0.4.0.zip//kustomize-controller-0.4.0/config/crd
- https://github.com/fluxcd/kustomize-controller/archive/v0.4.0.zip//kustomize-controller-0.4.0/config/manager
patchesJson6902:
- target:
group: apps

View File

@@ -1,5 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/notification-controller/archive/v0.2.0.zip//notification-controller-0.2.0/config/crd
- https://github.com/fluxcd/notification-controller/archive/v0.2.0.zip//notification-controller-0.2.0/config/manager
- https://github.com/fluxcd/notification-controller/archive/v0.4.0.zip//notification-controller-0.4.0/config/crd
- https://github.com/fluxcd/notification-controller/archive/v0.4.0.zip//notification-controller-0.4.0/config/manager

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/source-controller/archive/v0.2.1.zip//source-controller-0.2.1/config/crd
- https://github.com/fluxcd/source-controller/archive/v0.2.1.zip//source-controller-0.2.1/config/manager
- https://github.com/fluxcd/source-controller/archive/v0.4.1.zip//source-controller-0.4.1/config/crd
- https://github.com/fluxcd/source-controller/archive/v0.4.1.zip//source-controller-0.4.1/config/manager
patchesJson6902:
- target:
group: apps

View File

@@ -52,9 +52,9 @@ nav:
- Monitoring with Prometheus: guides/monitoring.md
- Sealed Secrets: guides/sealed-secrets.md
- Mozilla SOPS: guides/mozilla-sops.md
- Migrate:
- From Flux v1: guides/flux-v1-migration.md
- From the Helm Operator: guides/helm-operator-migration.md
- Migration:
- Migrate from Flux v1: guides/flux-v1-migration.md
- Migrate from the Helm Operator: guides/helm-operator-migration.md
- Toolkit Components:
- Overview: components/index.md
- Source Controller:
@@ -95,7 +95,7 @@ nav:
- Create alert provider: cmd/flux_create_alert-provider.md
- Create alert: cmd/flux_create_alert.md
- Create receiver: cmd/flux_create_receiver.md
#- Create tenant: cmd/flux_create_tenant.md
- Create tenant: cmd/flux_create_tenant.md
- Delete: cmd/flux_delete.md
- Delete kustomization: cmd/flux_delete_kustomization.md
- Delete helmrelease: cmd/flux_delete_helmrelease.md
@@ -119,6 +119,7 @@ nav:
- Get sources: cmd/flux_get_sources.md
- Get sources git: cmd/flux_get_sources_git.md
- Get sources helm: cmd/flux_get_sources_helm.md
- Get sources chart: cmd/flux_get_sources_chart.md
- Get sources bucket: cmd/flux_get_sources_bucket.md
- Get alert provider: cmd/flux_get_alert-provider.md
- Get alert: cmd/flux_get_alert.md
@@ -127,12 +128,22 @@ nav:
- Resume: cmd/flux_resume.md
- Resume kustomization: cmd/flux_resume_kustomization.md
- Resume helmrelease: cmd/flux_resume_helmrelease.md
- Resume source: cmd/flux_resume_source.md
- Resume source git: cmd/flux_resume_source_git.md
- Resume source helm: cmd/flux_resume_source_helm.md
- Resume source chart: cmd/flux_resume_source_chart.md
- Resume source bucket: cmd/flux_resume_source_bucket.md
- Resume alert provider: cmd/flux_resume_alert-provider.md
- Resume alert: cmd/flux_resume_alert.md
- Resume receiver: cmd/flux_resume_receiver.md
- Suspend: cmd/flux_suspend.md
- Suspend kustomization: cmd/flux_suspend_kustomization.md
- Suspend helmrelease: cmd/flux_suspend_helmrelease.md
- Suspend source: cmd/flux_suspend_source.md
- Suspend source git: cmd/flux_suspend_source_git.md
- Suspend source helm: cmd/flux_suspend_source_helm.md
- Suspend source chart: cmd/flux_suspend_source_chart.md
- Suspend source bucket: cmd/flux_suspend_source_bucket.md
- Suspend alert provider: cmd/flux_suspend_alert-provider.md
- Suspend alert: cmd/flux_suspend_alert.md
- Suspend receiver: cmd/flux_suspend_receiver.md