1
0
mirror of synced 2026-03-01 11:16:56 +00:00

Compare commits

..

131 Commits

Author SHA1 Message Date
Hidde Beydals
a4871724ac Merge pull request #587 from fluxcd/update-components
Update source-controller to v0.5.2
2020-12-11 15:24:35 +01:00
fluxcdbot
a7d6446d8f Update toolkit components 2020-12-11 14:17:20 +00:00
Stefan Prodan
635a17ef1e Merge pull request #586 from fluxcd/kustomize/api-v0.7.0
Update kustomize/api to v0.7.0
2020-12-11 16:16:10 +02:00
Stefan Prodan
6280fbce17 Update kustomize/api to v0.7.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-11 16:07:23 +02:00
Stefan Prodan
daa72e72b0 Merge pull request #585 from fluxcd/update-components
Update kustomize-controller to v0.5.0
2020-12-11 15:30:38 +02:00
fluxcdbot
35bb770697 Update toolkit components 2020-12-11 13:19:36 +00:00
Stefan Prodan
9cc5a7d8de Merge pull request #584 from fluxcd/docs-azure-devops
Rearrange Azure DevOps docs
2020-12-11 15:12:54 +02:00
Stefan Prodan
9b62f01b53 Rearrange Azure DevOps docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-11 14:52:19 +02:00
Stefan Prodan
a643a82006 Merge pull request #566 from fluxcd/feature/libgit2
Add git implementation flag and note about Azure DevOps
2020-12-11 13:58:53 +02:00
Philip Laine
82b74d8689 Add git implementation flag and note about Azure DevOps
Signed-off-by: Philip Laine <philip.laine@gmail.com>
2020-12-11 12:10:30 +01:00
Hidde Beydals
a5825bb9f5 Merge pull request #581 from fluxcd/stdlogger
Log to stderr
2020-12-11 10:34:40 +01:00
Hidde Beydals
88a890d717 Log to stderr
This commit refactors the `printLogger` into a `stderrLogger` that
properly logs to `os.stderr` instead of `os.stdout`.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-12-10 20:21:09 +01:00
Hidde Beydals
be6fab795d Merge pull request #578 from fluxcd/rel-base-path 2020-12-10 18:51:41 +01:00
Hidde Beydals
7a5b9e2991 Use rel filepath in auto generated kustomization
This works around another bug on Windows platforms that would cause the
kustomize-controller to choke on the kustomization.yaml generated by the
bootstrap command due to the filepath being in a Windows format.

By using `filepath.Rel`, the output is _just_ the filename for files
relative to the bootstrap path, which is at the moment sufficient to
make it work.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-12-10 18:37:01 +01:00
Hidde Beydals
ee1f70841c Use path rel to working dir for kustomize build
Work around for a bug in kustomize causing it to not properly
handle absolute paths on Windows.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-12-10 16:54:19 +01:00
Stefan Prodan
adc3d17eab Merge pull request #577 from fluxcd/update-git-pkg
Update fluxcd/pkg/git to v0.1.0
2020-12-10 15:05:16 +02:00
Stefan Prodan
f909d6fde2 Update fluxcd/pkg/git to v0.1.0
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-10 14:11:16 +02:00
Stefan Prodan
016a388147 Merge pull request #573 from fluxcd/update-components
Update toolkit components
2020-12-10 13:27:01 +02:00
fluxcdbot
aea442e7e1 Update toolkit components 2020-12-10 10:50:11 +00:00
Hidde Beydals
bb013ceb28 Merge pull request #576 from sylr/fix-typo
Fix typo in manifests download error message
2020-12-10 11:13:26 +01:00
Sylvain Rabot
dd65e9b89d Fix typo
Signed-off-by: Sylvain Rabot <sylvain@abstraction.fr>
2020-12-10 11:00:54 +01:00
Stefan Prodan
12146eda8c Merge pull request #569 from fluxcd/fix-https-auth
Fix create secret for Git over HTTP/S
2020-12-09 18:15:49 +02:00
Stefan Prodan
cd87fbba0d Fix create secret for Git over HTTP/S
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-09 17:39:04 +02:00
Stefan Prodan
c73541f81f Merge pull request #567 from fluxcd/docs-kustomize-faq
Add Kustomize FAQ to docs
2020-12-09 12:03:49 +02:00
Stefan Prodan
4618998792 Add Kustomize FAQ to docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-09 11:27:25 +02:00
Stefan Prodan
0a3b581aa9 Merge pull request #565 from mewzherder/patch-7
Upcoming events and Featured talks: reorder & update
2020-12-09 08:58:31 +02:00
mewzherder
aaa319b9bf Upcoming events and Featured talks: reorder & update
Signed-off-by: mewzherder <tamao@weave.works>
2020-12-08 08:59:36 -08:00
Hidde Beydals
25e782177b Merge pull request #559 from fluxcd/prevent-aur-publish-parallel-run
Prevent AUR package publishing parallel execution
2020-12-07 14:13:32 +01:00
Aurel Canciu
e940fd3d1f Prevent AUR package publishing parallel execution
Using a lock to prevent parallel executions in GoReleaser's custom
publishers. The custom publisher logic executes the tasks in parallel
for each available artifact.

https://goreleaser.com/customization/publishers/#how-it-works

Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-07 10:29:17 +02:00
Hidde Beydals
31d5cb4ad8 Merge pull request #557 from fluxcd/build/tmp-dir-rm
Properly clean-up package build dirs
2020-12-04 21:57:26 +01:00
Hidde Beydals
21576fe459 Properly clean-up package build dirs
Signed-off-by: Hidde Beydals <hello@hidde.co>
2020-12-04 21:49:41 +01:00
Hidde Beydals
65863a2cb8 Merge pull request #556 from fluxcd/fix-goreleaser-aur-publish
Use mock archive for aur publishers
2020-12-04 21:19:47 +01:00
Aurel Canciu
cdd055bfa6 Use mock archive for aur publishers
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 22:10:52 +02:00
Hidde Beydals
fedf960a5f Merge pull request #555 from fluxcd/fix-goreleaser-aur-publish
Remove `ids` GoReleaser attr in AUR pkg publisher
2020-12-04 20:31:31 +01:00
Aurel Canciu
4546fa3270 Remove ids GoReleaser attr in AUR pkg publisher
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 21:22:13 +02:00
Hidde Beydals
979f3f557c Merge pull request #554 from fluxcd/fix-goreleaser-aur-publish
Fix GoReleaser AUR publish concurrent exec issue
2020-12-04 20:08:08 +01:00
Aurel Canciu
48a38a8a5d Fix GoReleaser AUR publish concurrent exec issue
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 20:59:55 +02:00
Stefan Prodan
9880b32b0a Merge pull request #553 from fluxcd/fix-goreleaser-aur-publish
Fix GoReleaser AUR package publishing
2020-12-04 20:17:50 +02:00
Aurel Canciu
e664ef7a8d Fix GoReleaser AUR package publishing
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 20:08:32 +02:00
Stefan Prodan
7cfef379d0 Merge pull request #552 from fluxcd/fix-workflow-syntax-error
Fix GitHub Actions release workflow syntax error
2020-12-04 19:46:13 +02:00
Aurel Canciu
093a91c7fc Fix syntax error introduced earlier
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 19:36:01 +02:00
Hidde Beydals
94687a047f Merge pull request #551 from fluxcd/update-components
Update helm-controller to v0.4.2
2020-12-04 18:04:30 +01:00
fluxcdbot
38fdc603ad Update toolkit components 2020-12-04 16:52:10 +00:00
Stefan Prodan
55cecb7f96 Merge pull request #550 from fluxcd/install-with-kubectl
Publish install manifest to GitHub releases
2020-12-04 18:51:01 +02:00
Stefan Prodan
32e949598e Publish install manifest to GitHub releases
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-04 18:33:26 +02:00
Stefan Prodan
6d0c8aff4b Merge pull request #549 from fluxcd/add-priv-key-secret-for-goreleaser
Add AUR_BOT_SSH_PRIVATE_KEY env var for goreleaser
2020-12-04 17:58:54 +02:00
Aurel Canciu
5eecf03af6 Add AUR_BOT_SSH_PRIVATE_KEY env var for goreleaser
The AUR_BOT_SSH_PRIVATE_KEY environment variable needs to be set in
goreleaser so publishing the packages to AUR can work.

Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 17:49:25 +02:00
Stefan Prodan
76e9884032 Merge pull request #547 from fluxcd/create-secret-git
Add create secret git command
2020-12-04 17:39:08 +02:00
Stefan Prodan
9867c4baf0 Add create secret git command
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-04 16:54:13 +02:00
Stefan Prodan
2bc05c8cbd Merge pull request #548 from fluxcd/fix-md-aur-docs
Fix list parsing issue in the docs
2020-12-04 16:53:40 +02:00
Aurel Canciu
d15b0107e4 Fix list parsing issue in the docs
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 16:31:18 +02:00
Aurel Canciu
c64cb1304d Merge pull request #532 from fluxcd/aur-publish
Automated AUR publishing
2020-12-04 16:10:15 +02:00
Aurel Canciu
c1f209c7a5 Add information about the AUR packages to docs
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 16:01:33 +02:00
Aurel Canciu
116ccd6b3b Rename flux-git to flux-scm to prevent collision
A flux-git package already exists in AUR

Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 16:01:32 +02:00
Aurel Canciu
b6f30ae3e1 Move aur package templates to .github/aur
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 16:01:32 +02:00
Aurel Canciu
5c522ed2e1 Add publisher scripts and gorelease config
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 16:01:32 +02:00
Aurel Canciu
bc29b80912 Add PKGBUILD templates
Signed-off-by: Aurel Canciu <aurelcanciu@gmail.com>
2020-12-04 16:01:32 +02:00
Stefan Prodan
cfbc17fbf8 Merge pull request #546 from fluxcd/label-secrets
Add labels to generated secrets
2020-12-04 13:46:42 +02:00
Stefan Prodan
af0c939302 Add labels to generated secrets
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-04 13:15:37 +02:00
Michael Bridgen
e02538d38d Merge pull request #441 from fluxcd/component-readiness-indication
Show the roadmap status more prominently and precisely
2020-12-03 16:32:46 +00:00
Michael Bridgen
001d37567c Provide pointers to the install guides in roadmap
This gives people a way into the software, alongside the idea of how
ready it is.

Signed-off-by: Michael Bridgen <michael@weave.works>
2020-12-03 16:22:56 +00:00
Michael Bridgen
af82ce31a6 Bring image automation roadmap up to date
Specifically,

 - using credentials from a secret is done
 - the CLI integration is underway

I gave the %-complete a decent bump to reflect those, and all the work
on making the image-* controllers have all the GOTK dials and knobs
e.g., suspend.

Signed-off-by: Michael Bridgen <michael@weave.works>
2020-12-03 16:09:27 +00:00
Michael Bridgen
12ad4908fa Separate out "scans at all" from authentication
This makes it a clearer that the component does something worthwhile,
and is lacking mainly in platform-specific support.

Signed-off-by: Michael Bridgen <michael@weave.works>
2020-12-03 16:06:22 +00:00
Hidde Beydals
40ef94ab45 Merge pull request #522 from vfarcic/main
Add link to video review from Viktor Farcic
2020-12-01 14:37:22 +01:00
Viktor Farcic
8834ab0210 Video
Signed-off-by: Viktor Farcic <viktor@farcic.com>
2020-12-01 14:24:45 +01:00
Stefan Prodan
128d23720f Merge pull request #535 from fluxcd/gh-action-auto-updates
Automate Flux upgrades with GitHub Actions
2020-12-01 12:10:36 +02:00
Stefan Prodan
90f4891ca9 Automate Flux upgrades with GitHub Actions
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-01 11:16:26 +02:00
Stefan Prodan
61ac81c4d9 Merge pull request #534 from fluxcd/docs-bootstrap
Specify where to place Kubernetes manifests after bootstrap
2020-12-01 10:30:01 +02:00
Stefan Prodan
bd05a8173c Specify where to place Kubernetes manifests after bootstrap
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2020-12-01 09:46:28 +02:00
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
111 changed files with 3356 additions and 380 deletions

17
.github/aur/flux-bin/.SRCINFO.template vendored Normal file
View File

@@ -0,0 +1,17 @@
pkgbase = flux-bin
pkgdesc = Open and extensible continuous delivery solution for Kubernetes
pkgver = ${PKGVER}
pkgrel = ${PKGREL}
url = https://fluxcd.io/
arch = x86_64
arch = armv6h
arch = armv7h
arch = aarch64
license = APACHE
optdepends = kubectl
source_x86_64 = flux-bin-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v1/flux_${PKGVER}_linux_amd64.tar.gz
source_armv6h = flux-bin-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v1/flux_${PKGVER}_linux_arm.tar.gz
source_armv7h = flux-bin-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v1/flux_${PKGVER}_linux_arm.tar.gz
source_aarch64 = flux-bin-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v1/flux_${PKGVER}_linux_arm64.tar.gz
pkgname = flux-bin

1
.github/aur/flux-bin/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.pkg

39
.github/aur/flux-bin/PKGBUILD.template vendored Normal file
View File

@@ -0,0 +1,39 @@
# Maintainer: Aurel Canciu <aurelcanciu@gmail.com>
# Maintainer: Hidde Beydals <hello@hidde.co>
pkgname=flux-bin
pkgver=${PKGVER}
pkgrel=${PKGREL}
pkgdesc="Open and extensible continuous delivery solution for Kubernetes"
url="https://fluxcd.io/"
arch=("x86_64" "armv6h" "armv7h" "aarch64")
license=("APACHE")
optdepends=("kubectl")
source_x86_64=(
"$pkgname-$pkgver.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${pkgver}/flux_${pkgver}_linux_amd64.tar.gz"
)
source_armv6h=(
"$pkgname-$pkgver.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${pkgver}/flux_${pkgver}_linux_arm.tar.gz"
)
source_armv7h=(
"$pkgname-$pkgver.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${pkgver}/flux_${pkgver}_linux_arm.tar.gz"
)
source_aarch64=(
"$pkgname-$pkgver.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${pkgver}/flux_${pkgver}_linux_arm64.tar.gz"
)
sha256sums_x86_64=(
${SHA256SUM_AMD64}
)
sha256sums_armv6h=(
${SHA256SUM_ARM}
)
sha256sums_armv7h=(
${SHA256SUM_ARM}
)
sha256sums_aarch64=(
${SHA256SUM_ARM64}
)
package() {
install -Dm755 flux "$pkgdir/usr/bin/flux"
}

55
.github/aur/flux-bin/publish.sh vendored Executable file
View File

@@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -e
WD=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)
PKGNAME=$(basename $WD)
ROOT=${WD%/.github/aur/$PKGNAME}
LOCKFILE=/tmp/aur-$PKGNAME.lock
exec 100>$LOCKFILE || exit 0
flock -n 100 || exit 0
trap "rm -f $LOCKFILE" EXIT
export VERSION=$1
echo "Publishing to AUR as version ${VERSION}"
cd $WD
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
eval $(ssh-agent -s)
ssh-add <(echo "$AUR_BOT_SSH_PRIVATE_KEY")
GITDIR=$(mktemp -d /tmp/aur-$PKGNAME-XXX)
trap "rm -rf $GITDIR" EXIT
git clone aur@aur.archlinux.org:$PKGNAME $GITDIR 2>&1
CURRENT_PKGVER=$(cat $GITDIR/.SRCINFO | grep pkgver | awk '{ print $3 }')
CURRENT_PKGREL=$(cat $GITDIR/.SRCINFO | grep pkgrel | awk '{ print $3 }')
export PKGVER=${VERSION/-/}
if [[ "${CURRENT_PKGVER}" == "${PKGVER}" ]]; then
export PKGREL=$((CURRENT_PKGREL+1))
else
export PKGREL=1
fi
export SHA256SUM_ARM=$(sha256sum ${ROOT}/dist/flux_${PKGVER}_linux_arm.tar.gz | awk '{ print $1 }')
export SHA256SUM_ARM64=$(sha256sum ${ROOT}/dist/flux_${PKGVER}_linux_arm64.tar.gz | awk '{ print $1 }')
export SHA256SUM_AMD64=$(sha256sum ${ROOT}/dist/flux_${PKGVER}_linux_amd64.tar.gz | awk '{ print $1 }')
envsubst '$PKGVER $PKGREL $SHA256SUM_AMD64 $SHA256SUM_ARM $SHA256SUM_ARM64' < .SRCINFO.template > $GITDIR/.SRCINFO
envsubst '$PKGVER $PKGREL $SHA256SUM_AMD64 $SHA256SUM_ARM $SHA256SUM_ARM64' < PKGBUILD.template > $GITDIR/PKGBUILD
cd $GITDIR
git config user.name "fluxcdbot"
git config user.email "fluxcdbot@users.noreply.github.com"
git add -A
if [ -z "$(git status --porcelain)" ]; then
echo "No changes."
else
git commit -m "Updated to version v${PKGVER} release ${PKGREL}"
git push origin master
fi

19
.github/aur/flux-go/.SRCINFO.template vendored Normal file
View File

@@ -0,0 +1,19 @@
pkgbase = flux-go
pkgdesc = Open and extensible continuous delivery solution for Kubernetes
pkgver = ${PKGVER}
pkgrel = ${PKGREL}
url = https://fluxcd.io/
arch = x86_64
arch = armv6h
arch = armv7h
arch = aarch64
license = APACHE
makedepends = go
depends = glibc
optdepends = kubectl
provides = flux-bin
conflicts = flux-bin
replaces = flux-cli
source = flux-go-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/archive/v${PKGVER}.tar.gz
pkgname = flux-go

1
.github/aur/flux-go/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.pkg

43
.github/aur/flux-go/PKGBUILD.template vendored Normal file
View File

@@ -0,0 +1,43 @@
# Maintainer: Aurel Canciu <aurelcanciu@gmail.com>
# Maintainer: Hidde Beydals <hello@hidde.co>
pkgname=flux-go
pkgver=${PKGVER}
pkgrel=${PKGREL}
pkgdesc="Open and extensible continuous delivery solution for Kubernetes"
url="https://fluxcd.io/"
arch=("x86_64" "armv6h" "armv7h" "aarch64")
license=("APACHE")
provides=("flux-bin")
conflicts=("flux-bin")
replaces=("flux-cli")
depends=("glibc")
makedepends=("go")
optdepends=("kubectl")
source=(
"$pkgname-$pkgver.tar.gz::https://github.com/fluxcd/flux2/archive/v$pkgver.tar.gz"
)
sha256sums=(
${SHA256SUM}
)
build() {
cd "flux2-$pkgver"
export CGO_LDFLAGS="$LDFLAGS"
export CGO_CFLAGS="$CFLAGS"
export CGO_CXXFLAGS="$CXXFLAGS"
export CGO_CPPFLAGS="$CPPFLAGS"
export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
go build -ldflags "-X main.VERSION=$pkgver" -o flux-bin ./cmd/flux
}
check() {
cd "flux2-$pkgver"
make test
}
package() {
cd "flux2-$pkgver"
install -Dm755 flux-bin "$pkgdir/usr/bin/flux"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

53
.github/aur/flux-go/publish.sh vendored Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -e
WD=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)
PKGNAME=$(basename $WD)
ROOT=${WD%/.github/aur/$PKGNAME}
LOCKFILE=/tmp/aur-$PKGNAME.lock
exec 100>$LOCKFILE || exit 0
flock -n 100 || exit 0
trap "rm -f $LOCKFILE" EXIT
export VERSION=$1
echo "Publishing to AUR as version ${VERSION}"
cd $WD
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
eval $(ssh-agent -s)
ssh-add <(echo "$AUR_BOT_SSH_PRIVATE_KEY")
GITDIR=$(mktemp -d /tmp/aur-$PKGNAME-XXX)
trap "rm -rf $GITDIR" EXIT
git clone aur@aur.archlinux.org:$PKGNAME $GITDIR 2>&1
CURRENT_PKGVER=$(cat $GITDIR/.SRCINFO | grep pkgver | awk '{ print $3 }')
CURRENT_PKGREL=$(cat $GITDIR/.SRCINFO | grep pkgrel | awk '{ print $3 }')
export PKGVER=${VERSION/-/}
if [[ "${CURRENT_PKGVER}" == "${PKGVER}" ]]; then
export PKGREL=$((CURRENT_PKGREL+1))
else
export PKGREL=1
fi
export SHA256SUM=$(curl -sL https://github.com/fluxcd/flux2/archive/v$PKGVER.tar.gz | sha256sum | awk '{ print $1 }')
envsubst '$PKGVER $PKGREL $SHA256SUM' < .SRCINFO.template > $GITDIR/.SRCINFO
envsubst '$PKGVER $PKGREL $SHA256SUM' < PKGBUILD.template > $GITDIR/PKGBUILD
cd $GITDIR
git config user.name "fluxcdbot"
git config user.email "fluxcdbot@users.noreply.github.com"
git add -A
if [ -z "$(git status --porcelain)" ]; then
echo "No changes."
else
git commit -m "Updated to version v${PKGVER} release ${PKGREL}"
git push origin master
fi

19
.github/aur/flux-scm/.SRCINFO.template vendored Normal file
View File

@@ -0,0 +1,19 @@
pkgbase = flux-scm
pkgdesc = Open and extensible continuous delivery solution for Kubernetes
pkgver = ${PKGVER}
pkgrel = ${PKGREL}
url = https://fluxcd.io/
arch = x86_64
arch = armv6h
arch = armv7h
arch = aarch64
license = APACHE
makedepends = go
depends = glibc
optdepends = kubectl
provides = flux-bin
conflicts = flux-bin
source = git+https://github.com/fluxcd/flux2.git
md5sums = SKIP
pkgname = flux-scm

1
.github/aur/flux-scm/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.pkg

45
.github/aur/flux-scm/PKGBUILD.template vendored Normal file
View File

@@ -0,0 +1,45 @@
# Maintainer: Aurel Canciu <aurelcanciu@gmail.com>
# Maintainer: Hidde Beydals <hello@hidde.co>
pkgname=flux-scm
pkgver=${PKGVER}
pkgrel=${PKGREL}
pkgdesc="Open and extensible continuous delivery solution for Kubernetes"
url="https://fluxcd.io/"
arch=("x86_64" "armv6h" "armv7h" "aarch64")
license=("APACHE")
provides=("flux-bin")
conflicts=("flux-bin")
depends=("glibc")
makedepends=("go")
optdepends=("kubectl")
source=(
"git+https://github.com/fluxcd/flux2.git"
)
md5sums=('SKIP')
pkgver() {
cd "flux2"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
build() {
cd "flux2"
export CGO_LDFLAGS="$LDFLAGS"
export CGO_CFLAGS="$CFLAGS"
export CGO_CXXFLAGS="$CXXFLAGS"
export CGO_CPPFLAGS="$CPPFLAGS"
export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
go build -ldflags "-X main.VERSION=$pkgver" -o flux-bin ./cmd/flux
}
check() {
cd "flux2"
make test
}
package() {
cd "flux2"
install -Dm755 flux-bin "$pkgdir/usr/bin/flux"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

51
.github/aur/flux-scm/publish.sh vendored Executable file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
set -e
WD=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd)
PKGNAME=$(basename $WD)
ROOT=${WD%/.github/aur/$PKGNAME}
LOCKFILE=/tmp/aur-$PKGNAME.lock
exec 100>$LOCKFILE || exit 0
flock -n 100 || exit 0
trap "rm -f $LOCKFILE" EXIT
export VERSION=$1
echo "Publishing to AUR as version ${VERSION}"
cd $WD
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
eval $(ssh-agent -s)
ssh-add <(echo "$AUR_BOT_SSH_PRIVATE_KEY")
GITDIR=$(mktemp -d /tmp/aur-$PKGNAME-XXX)
trap "rm -rf $GITDIR" EXIT
git clone aur@aur.archlinux.org:$PKGNAME $GITDIR 2>&1
CURRENT_PKGVER=$(cat $GITDIR/.SRCINFO | grep pkgver | awk '{ print $3 }')
CURRENT_PKGREL=$(cat $GITDIR/.SRCINFO | grep pkgrel | awk '{ print $3 }')
export PKGVER=${VERSION/-/}
if [[ "${CURRENT_PKGVER}" == "${PKGVER}" ]]; then
export PKGREL=$((CURRENT_PKGREL+1))
else
export PKGREL=1
fi
envsubst '$PKGVER $PKGREL' < .SRCINFO.template > $GITDIR/.SRCINFO
envsubst '$PKGVER $PKGREL' < PKGBUILD.template > $GITDIR/PKGBUILD
cd $GITDIR
git config user.name "fluxcdbot"
git config user.email "fluxcdbot@users.noreply.github.com"
git add -A
if [ -z "$(git status --porcelain)" ]; then
echo "No changes."
else
git commit -m "Updated to version v${PKGVER} release ${PKGREL}"
git push origin master
fi

View File

@@ -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

@@ -59,24 +59,9 @@ jobs:
# create tarball
cd ./output && tar -cvzf manifests.tar.gz $files
- name: Create release
id: create_release
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
- name: Upload artifacts
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/manifests.tar.gz
asset_name: manifests.tar.gz
asset_content_type: application/gzip
- name: Generate install manifest
run: |
kustomize build ./manifests/install > ./output/install.yaml
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v1
with:
@@ -85,3 +70,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
AUR_BOT_SSH_PRIVATE_KEY: ${{ secrets.AUR_BOT_SSH_PRIVATE_KEY }}

View File

@@ -50,3 +50,23 @@ brews:
type: optional
test: |
system "#{bin}/flux --version"
publishers:
- name: aur-pkg-bin
env:
- AUR_BOT_SSH_PRIVATE_KEY={{ .Env.AUR_BOT_SSH_PRIVATE_KEY }}
cmd: |
.github/aur/flux-bin/publish.sh {{ .Version }}
- name: aur-pkg-scm
env:
- AUR_BOT_SSH_PRIVATE_KEY={{ .Env.AUR_BOT_SSH_PRIVATE_KEY }}
cmd: |
.github/aur/flux-scm/publish.sh {{ .Version }}
- name: aur-pkg-go
env:
- AUR_BOT_SSH_PRIVATE_KEY={{ .Env.AUR_BOT_SSH_PRIVATE_KEY }}
cmd: |
.github/aur/flux-go/publish.sh {{ .Version }}
release:
extra_files:
- glob: ./output/manifests.tar.gz
- glob: ./output/install.yaml

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

@@ -36,6 +36,15 @@ curl -s https://toolkit.fluxcd.io/install.sh | sudo bash
. <(flux completion bash)
```
Arch Linux (AUR) packages:
- [flux-bin](https://aur.archlinux.org/packages/flux-bin): install the latest
stable version using a pre-build binary (recommended)
- [flux-go](https://aur.archlinux.org/packages/flux-go): build the latest
stable version from source code
- [flux-scm](https://aur.archlinux.org/packages/flux-scm): build the latest
(unstable) version from source code from our git `main` branch
Binaries for macOS, Windows and Linux AMD64/ARM are available to download on the
[release page](https://github.com/fluxcd/flux2/releases).
@@ -98,19 +107,18 @@ Depending on what you want to do, some of the following bits might be your first
- To be part of the conversation about Flux's development, [join the flux-dev mailing list](https://lists.cncf.io/g/cncf-flux-dev).
- Check out [how to contribute](CONTRIBUTING.md) to the project
### Upcoming Events
- 14 Dec 2020 - [The Power of GitOps with Flux and Flagger with Leigh Capili](https://www.meetup.com/GitOps-Community/events/274924513/)
### Featured Talks
- 24 Nov 2020 - [Flux CD v2 with GitOps Toolkit - Kubernetes Deployment and Sync Mechanism](https://youtu.be/R6OeIgb7lUI)
- 28 Oct 2020 - [The Kubelist Podcast: Flux with Michael Bridgen](https://www.heavybit.com/library/podcasts/the-kubelist-podcast/ep-5-flux-with-michael-bridgen-of-weaveworks/)
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 1 with Leigh Capili](https://youtu.be/0v5bjysXTL8)
- 30 Nov 2020 - [The Power of GitOps with Flux 2 - Part 3 with Leigh Capili](https://youtu.be/N_K5g7o9JKg)
- 12 Oct 2020 - [Rawkode Live: Introduction to GitOps Toolkit with Stefan Prodan](https://youtu.be/HqTzuOBP0eY)
- 4 Sep 2020 - [KubeCon Europe: The road to Flux v2 and Progressive Delivery with Stefan Prodan & Hidde Beydals](https://youtu.be/8v94nUkXsxU)
- 25 June 2020 - [Cloud Native Nordics: Introduction to GitOps & GitOps Toolkit with Alexis Richardson & Stefan Prodan](https://youtu.be/qQBtSkgl7tI)
- 7 May 2020 - [GitOps Days - Community Special: GitOps Toolkit Experimentation with Stefan Prodan](https://youtu.be/WHzxunv4DKk?t=6521)
### 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)
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"]

79
action/README.md Normal file
View File

@@ -0,0 +1,79 @@
# Flux GitHub Action
Usage:
```yaml
steps:
- name: Setup Flux CLI
uses: fluxcd/flux2/action@main
- name: Run Flux commands
run: flux -v
```
### Automate Flux updates
Example workflow for updating Flux's components generated with `flux bootstrap --arch=amd64 --path=clusters/production`:
```yaml
name: update-flux
on:
workflow_dispatch:
schedule:
- cron: "0 * * * *"
jobs:
components:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Setup Flux CLI
uses: fluxcd/flux2/action@main
- name: Check for updates
id: update
run: |
flux install --arch=amd64 \
--export > ./clusters/production/flux-system/gotk-components.yaml
VERSION="$(flux -v)"
echo "::set-output name=flux_version::$VERSION"
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: update-flux
commit-message: Update to ${{ steps.update.outputs.flux_version }}
title: Update to ${{ steps.update.outputs.flux_version }}
body: |
${{ steps.update.outputs.flux_version }}
```
### End-to-end testing
Example workflow for running Flux in Kubernetes Kind:
```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
```
A complete e2e testing workflow is available here
[flux2-kustomize-helm-example](https://github.com/fluxcd/flux2-kustomize-helm-example/blob/main/.github/workflows/e2e.yaml)

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

@@ -135,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")
}
}
@@ -177,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

@@ -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,14 +174,14 @@ 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, kubectlArgs...); err == nil {
if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubeconfig, kubecontext, kubectlArgs...); err == nil {
logger.Actionf(strings.TrimPrefix(strings.TrimSuffix(output, "\""), "\""))
}
}

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,7 +81,6 @@ var (
ksHealthCheck []string
ksHealthTimeout time.Duration
ksSAName string
ksSANamespace string
ksDecryptionProvider flags.DecryptionProvider
ksDecryptionSecret string
ksTargetNamespace string
@@ -88,14 +88,13 @@ var (
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")
@@ -188,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 != "" {
@@ -278,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)
}
}

52
cmd/flux/create_secret.go Normal file
View File

@@ -0,0 +1,52 @@
/*
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 (
"fmt"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
)
var createSecretCmd = &cobra.Command{
Use: "secret",
Short: "Create or update Kubernetes secrets",
Long: "The create source sub-commands generate Kubernetes secrets specific to Flux.",
}
func init() {
createCmd.AddCommand(createSecretCmd)
}
func exportSecret(secret corev1.Secret) error {
secret.TypeMeta = metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
}
data, err := yaml.Marshal(secret)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
}

View File

@@ -0,0 +1,173 @@
/*
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"
"crypto/elliptic"
"fmt"
"net/url"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fluxcd/flux2/internal/flags"
"github.com/fluxcd/flux2/internal/utils"
)
var createSecretGitCmd = &cobra.Command{
Use: "git [name]",
Short: "Create or update a Kubernetes secret for Git authentication",
Long: `
The create secret git command generates a Kubernetes secret with Git credentials.
For Git over SSH, the host and SSH keys are automatically generated and stored in the secret.
For Git over HTTP/S, the provided basic authentication credentials are stored in the secret.`,
Example: ` # Create a Git SSH authentication secret using an ECDSA P-521 curve public key
flux create secret git podinfo-auth \
--url=ssh://git@github.com/stefanprodan/podinfo \
--ssh-key-algorithm=ecdsa \
--ssh-ecdsa-curve=p521
# Create a secret for a Git repository using basic authentication
flux create secret git podinfo-auth \
--url=https://github.com/stefanprodan/podinfo \
--username=username \
--password=password
# Create a Git SSH secret on disk and print the deploy key
flux create secret git podinfo-auth \
--url=ssh://git@github.com/stefanprodan/podinfo \
--export > podinfo-auth.yaml
yq read podinfo-auth.yaml 'data."identity.pub"' | base64 --decode
# Create a Git SSH secret on disk and encrypt it with Mozilla SOPS
flux create secret git podinfo-auth \
--namespace=apps \
--url=ssh://git@github.com/stefanprodan/podinfo \
--export > podinfo-auth.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place podinfo-auth.yaml
`,
RunE: createSecretGitCmdRun,
}
var (
secretGitURL string
secretGitUsername string
secretGitPassword string
secretGitKeyAlgorithm flags.PublicKeyAlgorithm = "rsa"
secretGitRSABits flags.RSAKeyBits = 2048
secretGitECDSACurve = flags.ECDSACurve{Curve: elliptic.P384()}
)
func init() {
createSecretGitCmd.Flags().StringVar(&secretGitURL, "url", "", "git address, e.g. ssh://git@host/org/repository")
createSecretGitCmd.Flags().StringVarP(&secretGitUsername, "username", "u", "", "basic authentication username")
createSecretGitCmd.Flags().StringVarP(&secretGitPassword, "password", "p", "", "basic authentication password")
createSecretGitCmd.Flags().Var(&secretGitKeyAlgorithm, "ssh-key-algorithm", sourceGitKeyAlgorithm.Description())
createSecretGitCmd.Flags().Var(&secretGitRSABits, "ssh-rsa-bits", sourceGitRSABits.Description())
createSecretGitCmd.Flags().Var(&secretGitECDSACurve, "ssh-ecdsa-curve", sourceGitECDSACurve.Description())
createSecretCmd.AddCommand(createSecretGitCmd)
}
func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("secret name is required")
}
name := args[0]
if secretGitURL == "" {
return fmt.Errorf("url is required")
}
u, err := url.Parse(secretGitURL)
if err != nil {
return fmt.Errorf("git URL parse failed: %w", err)
}
secretLabels, err := parseLabels()
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: secretLabels,
},
}
switch u.Scheme {
case "ssh":
pair, err := generateKeyPair(ctx)
if err != nil {
return err
}
hostKey, err := scanHostKey(ctx, u)
if err != nil {
return err
}
secret.Data = map[string][]byte{
"identity": pair.PrivateKey,
"identity.pub": pair.PublicKey,
"known_hosts": hostKey,
}
if !export {
logger.Generatef("deploy key: %s", string(pair.PublicKey))
}
case "http", "https":
if secretGitUsername == "" || secretGitPassword == "" {
return fmt.Errorf("for Git over HTTP/S the username and password are required")
}
// TODO: add cert data when it's implemented in source-controller
secret.Data = map[string][]byte{
"username": []byte(secretGitUsername),
"password": []byte(secretGitPassword),
}
default:
return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme)
}
if export {
return exportSecret(secret)
}
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err
}
logger.Actionf("secret '%s' created in '%s' namespace", name, namespace)
return nil
}

View File

@@ -154,6 +154,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: namespace,
Labels: sourceLabels,
},
StringData: map[string]string{},
}

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"
@@ -94,10 +95,11 @@ var (
sourceGitUsername string
sourceGitPassword string
sourceGitKeyAlgorithm flags.PublicKeyAlgorithm = "rsa"
sourceGitRSABits flags.RSAKeyBits = 2048
sourceGitECDSACurve = flags.ECDSACurve{Curve: elliptic.P384()}
sourceGitSecretRef string
sourceGitKeyAlgorithm flags.PublicKeyAlgorithm = "rsa"
sourceGitRSABits flags.RSAKeyBits = 2048
sourceGitECDSACurve = flags.ECDSACurve{Curve: elliptic.P384()}
sourceGitSecretRef string
sourceGitImplementation string
)
func init() {
@@ -111,6 +113,7 @@ func init() {
createSourceGitCmd.Flags().Var(&sourceGitRSABits, "ssh-rsa-bits", sourceGitRSABits.Description())
createSourceGitCmd.Flags().Var(&sourceGitECDSACurve, "ssh-ecdsa-curve", sourceGitECDSACurve.Description())
createSourceGitCmd.Flags().StringVarP(&sourceGitSecretRef, "secret-ref", "", "", "the name of an existing secret containing SSH or basic credentials")
createSourceGitCmd.Flags().StringVar(&sourceGitImplementation, "git-implementation", "", "the git implementation to use, can be 'go-git' or 'libgit2'")
createSourceCmd.AddCommand(createSourceGitCmd)
}
@@ -141,6 +144,10 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return err
}
if !utils.ContainsItemString([]string{sourcev1.GoGitImplementation, sourcev1.LibGit2Implementation, ""}, sourceGitImplementation) {
return fmt.Errorf("Invalid git implementation %q", sourceGitImplementation)
}
gitRepository := sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@@ -152,7 +159,8 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
Interval: metav1.Duration{
Duration: interval,
},
Reference: &sourcev1.GitRepositoryRef{},
Reference: &sourcev1.GitRepositoryRef{},
GitImplementation: sourceGitImplementation,
},
}
@@ -186,13 +194,13 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if sourceGitSecretRef != "" {
withAuth = true
} else if u.Scheme == "ssh" {
logger.Actionf("generating deploy key pair")
logger.Generatef("generating deploy key pair")
pair, err := generateKeyPair(ctx)
if err != nil {
return err
}
fmt.Printf("%s", pair.PublicKey)
logger.Successf("deploy key: %s", pair.PublicKey)
prompt := promptui.Prompt{
Label: "Have you added the deploy key to your repository",
IsConfirm: true,
@@ -206,14 +214,14 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
logger.Successf("collected public key from SSH server:")
fmt.Printf("%s", hostKey)
logger.Successf("collected public key from SSH server:\n%s", hostKey)
logger.Actionf("applying secret with keys")
secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: sourceLabels,
},
StringData: map[string]string{
"identity": string(pair.PrivateKey),
@@ -231,6 +239,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: sourceLabels,
},
StringData: map[string]string{
"username": sourceGitUsername,
@@ -375,11 +384,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"
@@ -149,6 +151,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: namespace,
Labels: sourceLabels,
},
StringData: map[string]string{},
}
@@ -242,3 +245,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[i]); 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

@@ -16,26 +16,31 @@ limitations under the License.
package main
import "fmt"
import (
"fmt"
"io"
)
type printLogger struct{}
func (l printLogger) Actionf(format string, a ...interface{}) {
fmt.Println(``, fmt.Sprintf(format, a...))
type stderrLogger struct {
stderr io.Writer
}
func (l printLogger) Generatef(format string, a ...interface{}) {
fmt.Println(``, fmt.Sprintf(format, a...))
func (l stderrLogger) Actionf(format string, a ...interface{}) {
fmt.Fprintln(l.stderr, ``, fmt.Sprintf(format, a...))
}
func (l printLogger) Waitingf(format string, a ...interface{}) {
fmt.Println(``, fmt.Sprintf(format, a...))
func (l stderrLogger) Generatef(format string, a ...interface{}) {
fmt.Fprintln(l.stderr, ``, fmt.Sprintf(format, a...))
}
func (l printLogger) Successf(format string, a ...interface{}) {
fmt.Println(``, fmt.Sprintf(format, a...))
func (l stderrLogger) Waitingf(format string, a ...interface{}) {
fmt.Fprintln(l.stderr, ``, fmt.Sprintf(format, a...))
}
func (l printLogger) Failuref(format string, a ...interface{}) {
fmt.Println(``, fmt.Sprintf(format, a...))
func (l stderrLogger) Successf(format string, a ...interface{}) {
fmt.Fprintln(l.stderr, ``, fmt.Sprintf(format, a...))
}
func (l stderrLogger) Failuref(format string, a ...interface{}) {
fmt.Fprintln(l.stderr, ``, fmt.Sprintf(format, a...))
}

View File

@@ -101,7 +101,7 @@ var (
timeout time.Duration
verbose bool
pollInterval = 2 * time.Second
logger fluxlog.Logger = printLogger{}
logger fluxlog.Logger = stderrLogger{stderr: os.Stderr}
defaults = install.MakeDefaultOptions()
)

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

@@ -33,5 +33,7 @@ The create sub-commands generate sources and resources.
* [flux create helmrelease](flux_create_helmrelease.md) - Create or update a HelmRelease resource
* [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 secret](flux_create_secret.md) - Create or update Kubernetes secrets
* [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,10 +50,9 @@ 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,32 @@
## flux create secret
Create or update Kubernetes secrets
### Synopsis
The create source sub-commands generate Kubernetes secrets specific to Flux.
### Options
```
-h, --help help for secret
```
### 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
* [flux create secret git](flux_create_secret_git.md) - Create or update a Kubernetes secret for Git authentication

View File

@@ -0,0 +1,78 @@
## flux create secret git
Create or update a Kubernetes secret for Git authentication
### Synopsis
The create secret git command generates a Kubernetes secret with Git credentials.
For Git over SSH, the host and SSH keys are automatically generated and stored in the secret.
For Git over HTTP/S, the provided basic authentication credentials are stored in the secret.
```
flux create secret git [name] [flags]
```
### Examples
```
# Create a Git SSH authentication secret using an ECDSA P-521 curve public key
flux create secret git podinfo-auth \
--url=ssh://git@github.com/stefanprodan/podinfo \
--ssh-key-algorithm=ecdsa \
--ssh-ecdsa-curve=p521
# Create a secret for a Git repository using basic authentication
flux create secret git podinfo-auth \
--url=https://github.com/stefanprodan/podinfo \
--username=username \
--password=password
# Create a Git SSH secret on disk and print the deploy key
flux create secret git podinfo-auth \
--url=ssh://git@github.com/stefanprodan/podinfo \
--export > podinfo-auth.yaml
yq read podinfo-auth.yaml 'data."identity.pub"' | base64 --decode
# Create a Git SSH secret on disk and encrypt it with Mozilla SOPS
flux create secret git podinfo-auth \
--namespace=apps \
--url=ssh://git@github.com/stefanprodan/podinfo \
--export > podinfo-auth.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place podinfo-auth.yaml
```
### Options
```
-h, --help help for git
-p, --password string basic authentication password
--ssh-ecdsa-curve ecdsaCurve SSH ECDSA public key curve (p256, p384, p521) (default p384)
--ssh-key-algorithm publicKeyAlgorithm SSH public key algorithm (rsa, ecdsa, ed25519) (default rsa)
--ssh-rsa-bits rsaKeyBits SSH RSA public key bit size (multiplies of 8) (default 2048)
--url string git address, e.g. ssh://git@host/org/repository
-u, --username string basic authentication username
```
### 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 secret](flux_create_secret.md) - Create or update Kubernetes secrets

View File

@@ -56,6 +56,7 @@ flux create source git [name] [flags]
```
--branch string git branch (default "master")
--git-implementation string the git implementation to use, can be 'go-git' or 'libgit2'
-h, --help help for git
-p, --password string basic authentication password
--secret-ref string the name of an existing secret containing SSH or basic credentials

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

@@ -92,3 +92,153 @@ There are a variety of ways and we look forward to having you on board building
In an announcement in August 2019, the expectation was set that the Flux project would integrate the GitOps Engine, then being factored out of ArgoCD. Since the result would be backward-incompatible, it would require a major version bump: Flux v2.
After experimentation and considerable thought, we (the maintainers) have found a path to Flux v2 that we think better serves our vision of GitOps: the GitOps Toolkit. In consequence, we do not now plan to integrate GitOps Engine into Flux.
## Kustomize questions
### Are there two Kustomization types?
Yes, the `kustomization.kustomize.toolkit.fluxcd.io` is a Kubernetes
[custom resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
while `kustomization.kustomize.config.k8s.io` is the type used to configure a
[Kustomize overlay](https://kubectl.docs.kubernetes.io/references/kustomize/).
The `kustomization.kustomize.toolkit.fluxcd.io` object refers to a `kustomization.yaml`
file path inside a Git repository or Bucket source.
### How do I use them together?
Assuming an app repository with `./deploy/prod/kustomization.yaml`:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- ingress.yaml
```
Define a source of type `gitrepository.source.toolkit.fluxcd.io`
that pulls changes from the app repository every 5 minutes inside the cluster:
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
name: my-app
namespace: default
spec:
interval: 5m
url: https://github.com/my-org/my-app
ref:
branch: main
```
Then define a `kustomization.kustomize.toolkit.fluxcd.io` that uses the `kustomization.yaml`
from `./deploy/prod` to determine which resources to create, update or delete:
```yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
name: my-app
namespace: default
spec:
interval: 15m
path: "./deploy/prod"
prune: true
sourceRef:
kind: GitRepository
name: my-app
```
### What is a Kustomization reconciliation?
In the above example, we pull changes from Git every 5 minutes,
and a new commit will trigger a reconciliation of
all the `Kustomization` objects using that source.
Depending on your configuration, a reconciliation can mean:
* generating a kustomization.yaml file in the specified path
* building the kustomize overlay
* decrypting secrets
* validating the manifests with client or server-side dry-run
* applying changes on the cluster
* health checking of deployed workloads
* garbage collection of resources removed from Git
* issuing events about the reconciliation result
* recoding metrics about the reconciliation process
The 15 minutes reconciliation interval, is the interval at which you want to undo manual changes
.e.g. `kubectl set image deployment/my-app` by reapplying the latest commit on the cluster.
Note that a reconciliation will override all fields of a Kubernetes object, that diverge from Git.
For example, you'll have to omit the `spec.replicas` field from your `Deployments` YAMLs if you
are using a `HorizontalPodAutoscaler` that changes the replicas in-cluster.
### Can I use repositories with plain YAMLs?
Yes, you can specify the path where the Kubernetes manifests are,
and kustomize-controller will generate a `kustomization.yaml` if one doesn't exist.
Assuming an app repository with the following structure:
```
├── deploy
│   └── prod
│   ├── .yamllint.yaml
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ingress.yaml
└── src
```
Create a `GitRepository` definition and exclude all the files that are not Kubernetes manifests:
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
name: my-app
namespace: default
spec:
interval: 5m
url: https://github.com/my-org/my-app
ref:
branch: main
ignore: |
# exclude all
/*
# include deploy dir
!/deploy
# exclude non-Kubernetes YAMLs
/deploy/**/.yamllint.yaml
```
Then create a `Kustomization` definition to reconcile the `./deploy/prod` dir:
```yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
name: my-app
namespace: default
spec:
interval: 15m
path: "./deploy/prod"
prune: true
sourceRef:
kind: GitRepository
name: my-app
```
With the above configuration, source-controller will pull the Kubernetes manifests
from the app repository and kustomize-controller will generate a
`kustomization.yaml` including all the resources found with `./deploy/prod/**/*.yaml`.
The kustomize-controller creates `kustomization.yaml` files similar to:
```sh
cd ./deploy/prod && kustomize create --autodetect --recursive
```

View File

@@ -34,6 +34,11 @@ curl -s https://toolkit.fluxcd.io/install.sh | sudo bash
The install script downloads the flux binary to `/usr/local/bin`.
If using Arch Linux, install the latest stable version from **AUR** using
either [flux-bin](https://aur.archlinux.org/packages/flux-bin) (pre-built
binary) or [flux-go](https://aur.archlinux.org/packages/flux-go) (locally built
binary).
Binaries for **macOS**, **Windows** and **Linux** AMD64/ARM are available for download on the
[release page](https://github.com/fluxcd/flux2/releases).

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.

View File

@@ -257,6 +257,83 @@ 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.

View File

@@ -84,12 +84,17 @@ cluster e.g. `clusters/staging` and `clusters/production`:
└── flux-system
```
After running bootstrap you can place Kubernetes YAMLs inside a dir under path
e.g. `clusters/staging/my-app`, and Flux will reconcile them on your cluster.
!!! hint "Change the default branch"
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)
* [flux2-multi-tenancy](https://github.com/fluxcd/flux2-multi-tenancy)
### GitHub and GitHub Enterprise
@@ -212,7 +217,7 @@ flux bootstrap gitlab \
### Generic Git Server
For other Git providers such as Bitbucket, Gogs, Gitea, etc you can manually setup the repository and the deploy key.
For other Git providers such as Bitbucket, Gogs, Gitea, Azure DevOps, etc you can manually setup the repository and the deploy key.
Create a Git repository and clone it locally:
@@ -293,6 +298,25 @@ flux create source git flux-system \
--interval=1m
```
!!! hint "Azure DevOps"
Azure DevOps requires a non-default Git implementation (`libgit2`) to be enabled, so that the Git v2 protocol is supported.
Note that this implementation does not support shallow cloning, and it is therefore advised to only resort to this option if a
connection fails with the default configuration.
Additionally, the current implementation of image automation does not support Azure DevOps as has no Git implementation with
this protocol. This limitation will likely change in the future.
If you are using Azure DevOps you need to specify a different git implementation than the default:
```sh
flux create source git flux-system \
--url= ssh://<host>/<org>/my-repository \
--ssh-key-algorithm=ecdsa \
--ssh-ecdsa-curve=p521 \
--branch=master \
--interval=1m \
--git-implementation=libgit2
```
You will be prompted to add a deploy key to your repository.
If you don't specify the SSH algorithm, then `flux` will generate an RSA 2048 bits key.
@@ -345,7 +369,7 @@ will perform a rolling update of all Flux components including itself.
## Bootstrap with Terraform
The bootstrap procedure can be implemented with Terraform using the Flux provider published on
The bootstrap procedure can be implemented with Terraform using the Flux provider published on
[registry.terraform.io](https://registry.terraform.io/providers/fluxcd/flux).
The provider consists of two data sources (`flux_install` and `flux_sync`) for generating the
@@ -439,6 +463,12 @@ For testing purposes you can install Flux without storing its manifests in a Git
flux install --arch=amd64
```
Or using kubectl:
```sh
kubectl apply -f https://github.com/fluxcd/flux2/releases/latest/download/install.yaml
```
Then you can register Git repositories and reconcile them on your cluster:
```sh
@@ -473,12 +503,80 @@ flux create helmrelease nginx \
--chart-version="5.x.x"
```
## Monitoring with Prometheus and Grafana
## 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.
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).
To install the monitoring stack please follow this [guide](monitoring.md).
Verify that you are running the latest version with:
```sh
flux --version
```
### Bootstrap upgrade
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:
```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
```
!!! hint "Automated upgrades"
You can automate the components manifest update with GitHub Actions
and open a PR when there is a new Flux version available.
For more details please see [Flux GitHub Action docs](https://github.com/fluxcd/flux2/tree/main/action).
### 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

@@ -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,13 +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, 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. 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).
### 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

View File

@@ -86,6 +86,7 @@ Depending on what you want to do, some of the following bits might be your first
### Featured Talks
- 24 Nov 2020 - [Flux CD v2 with GitOps Toolkit - Kubernetes Deployment and Sync Mechanism](https://youtu.be/R6OeIgb7lUI)
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 2 with Leigh Capili](https://youtu.be/fC2YCxQRUwU)
- 28 Oct 2020 - [The Kubelist Podcast: Flux with Michael Bridgen](https://www.heavybit.com/library/podcasts/the-kubelist-podcast/ep-5-flux-with-michael-bridgen-of-weaveworks/)
- 19 Oct 2020 - [The Power of GitOps with Flux & GitOps Toolkit - Part 1 with Leigh Capili](https://youtu.be/0v5bjysXTL8)

View File

@@ -14,6 +14,11 @@ All of the above will constitute "Flux v2".
[= 100% "100%"]
Flux v2 read-only is ready to try. See the [Getting
Started](https://toolkit.fluxcd.io/get-started/) how-to, and the
[Migration
guide](https://toolkit.fluxcd.io/guides/flux-v1-migration/).
This would be the first stepping stone: we want Flux v2 to be on-par with today's Flux in
[read-only mode](https://github.com/fluxcd/flux/blob/master/docs/faq.md#can-i-run-flux-with-readonly-git-access)
and [FluxCloud](https://github.com/justinbarrick/fluxcloud) notifications.
@@ -43,7 +48,11 @@ Tasks
### Flux image update feature parity
[= 30% "30%"]
[= 70% "70%"]
Image automation is available as a prerelease. See [the
README](https://github.com/fluxcd/image-automation-controller#readme)
for instructions on installing it.
Goals
@@ -55,12 +64,17 @@ Non-Goals
Tasks
- [x] <span style="color:grey">[Design the image scanning and automation API](https://github.com/fluxcd/flux2/discussions/107)</span>
- [ ] Implement an image scanning controller
- [x] <span style="color:grey">Design the automation component</span>
- [ ] Implement the image scan/patch/push workflow
- [ ] Integrate the new components in the Flux CLI
- [ ] Create a migration guide from Flux annotations
- [x] <span style="color:grey">[Design the image scanning and automation API](https://github.com/fluxcd/flux2/discussions/107)</span>
- [x] <span style="color:grey">Implement an image scanning controller</span>
- [x] <span style="color:grey">Public image repo support</span>
- [x] <span style="color:grey">Credentials from Secret [fluxcd/image-reflector-controller#35](https://github.com/fluxcd/image-reflector-controller/pull/35)</span>
- [ ] ECR-specific support [fluxcd/image-reflector-controller#11](https://github.com/fluxcd/image-reflector-controller/issues/11)
- [ ] GCR-specific support [fluxcd/image-reflector-controller#11](https://github.com/fluxcd/image-reflector-controller/issues/11)
- [ ] Azure-specific support [fluxcd/image-reflector-controller#11](https://github.com/fluxcd/image-reflector-controller/issues/11)
- [x] <span style="color:grey">Design the automation component</span>
- [x] <span style="color:grey">Implement the image scan/patch/push workflow</span>
- [ ] Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)
- [ ] Write a migration guide from Flux annotations
## The road to Helm Operator v2
@@ -68,6 +82,11 @@ Tasks
[= 100% "100%"]
Helm support in Flux v2 is ready to try. See the [Helm controller
guide](https://toolkit.fluxcd.io/guides/helmreleases/), and the [Helm
controller migration
guide](https://toolkit.fluxcd.io/guides/helm-operator-migration/).
Goals
- Offer a migration guide for those that are using Helm Operator with Helm v3 and charts from
@@ -93,4 +112,4 @@ Tasks
- [x] <span style="color:grey">Implement support for referring to an alternative chart values file</span>
- [x] <span style="color:grey">Stabilize API</span>
- [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)
- [ ] [Gather feedback on the migration guide](https://github.com/fluxcd/flux2/discussions/413)

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