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

Compare commits

..

124 Commits

Author SHA1 Message Date
Stefan Prodan
ff2833c4d1 Merge pull request #993 from fluxcd/air-gapped-install
Document air-gapped install procedure
2021-02-25 19:45:37 +02:00
Stefan Prodan
45ba845f23 Document air-gapped install procedure
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-25 19:23:57 +02:00
Hidde Beydals
771a14fcf6 Merge pull request #998 from fluxcd/update-components
Update image-automation-controller to v0.6.1
2021-02-25 17:55:36 +01:00
fluxcdbot
c8ff861d00 Update toolkit components
- image-automation-controller to v0.6.1
  https://github.com/fluxcd/image-automation-controller/blob/v0.6.1/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2021-02-25 16:43:31 +00:00
Hidde Beydals
0f05ce3605 Merge pull request #994 from fluxcd/update-components
Update toolkit components
2021-02-25 15:16:01 +01:00
fluxcdbot
38a3f3ba11 Update toolkit components
- kustomize-controller to v0.9.1
  https://github.com/fluxcd/kustomize-controller/blob/v0.9.1/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2021-02-25 14:01:37 +00:00
Hidde Beydals
659a19cd80 Merge pull request #992 from fluxcd/status-poller-fix
Update sigs.k8s.io/cli-utils to v0.22.2
2021-02-25 13:20:47 +01:00
Hidde Beydals
baaa466c0f Update sigs.k8s.io/cli-utils to v0.22.2
This is the first release that includes a patch of the
`CachingClusterReader` so that it continues on all list errors.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-25 12:56:16 +01:00
Stefan Prodan
168c65bb6e Merge pull request #987 from fluxcd/embed-install-manifests
Embed the Kubernetes manifests in flux binary
2021-02-25 13:27:12 +02:00
Stefan Prodan
6003d11156 Embed the install manifests in flux binary
- add make target for generating the install manifests using kustomize
- embed the generated manifests in flux binary
- the install and bootstrap commands default to using the embedded manifests
- download the install manifests from GitHub only if the install/bootstrap version arg is set

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-25 12:53:04 +02:00
Stefan Prodan
1f16b6d639 Merge pull request #988 from fluxcd/setup-go-update-ci
Properly setup Go version in update workflow
2021-02-25 12:16:15 +02:00
Hidde Beydals
54bb4b2efd Properly setup Go version in update workflow
To prevent false `go.mod` modifications.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-25 10:48:09 +01:00
Stefan Prodan
f54770c21a Merge pull request #984 from fluxcd/darwin-arm64-build
Publish flux binary for Apple Silicon
2021-02-25 09:21:27 +02:00
Stefan Prodan
1244a62deb Publish flux binary for Apple Silicon
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-24 23:05:46 +02:00
Stefan Prodan
2fe55bcdde Update Go to v1.16
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-24 23:05:42 +02:00
Hidde Beydals
9943690855 Merge pull request #983 from fluxcd/doc-controller-ver-fix 2021-02-24 19:14:39 +01:00
Hidde Beydals
89c46a6379 Fix controller_version helper func
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-24 18:34:52 +01:00
Hidde Beydals
a0d4530cc0 Merge pull request #982 from fluxcd/update-components-plus-ci 2021-02-24 18:31:50 +01:00
Hidde Beydals
6db84269af Update Toolkit component update script
To recognize and correctly replace the versions in the components'
Kustomization files.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-24 18:17:04 +01:00
Hidde Beydals
2cd3c32ca7 Update toolkit components
This includes a change to the components' Kustomization files to make
use of the YAML multi-doc manifests that are now attached to the GitHub
releases.

- helm-controller to v0.8.0
  https://github.com/fluxcd/helm-controller/blob/v0.8.0/CHANGELOG.md
- kustomize-controller to v0.9.0
  https://github.com/fluxcd/kustomize-controller/blob/v0.9.0/CHANGELOG.md
- source-controller to v0.9.0
  https://github.com/fluxcd/source-controller/blob/v0.9.0/CHANGELOG.md
- notification-controller to v0.9.0
  https://github.com/fluxcd/notification-controller/blob/v0.9.0/CHANGELOG.md
- image-reflector-controller to v0.7.0
  https://github.com/fluxcd/image-reflector-controller/blob/v0.7.0/CHANGELOG.md
- image-automation-controller to v0.6.0
  https://github.com/fluxcd/image-automation-controller/blob/v0.6.0/CHANGELOG.md

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-24 18:16:44 +01:00
Stefan Prodan
9740fecc35 Merge pull request #974 from tarioch/patch-1
Add example podMonitor for prometheus
2021-02-24 18:34:36 +02:00
Patrick Ruckstuhl
433492791b Add example podMonitor for prometheus
Signed-off-by: Patrick Ruckstuhl <patrick@ch.tario.org>
2021-02-24 16:01:00 +00:00
Hidde Beydals
7d3c63ad74 Merge pull request #981 from fluxcd/docs/v1-migration-notes
Add notes about flux bootstrap and feature parity
2021-02-24 13:42:51 +01:00
Hidde Beydals
a6538b117e Add notes about flux bootstrap and feature parity
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-24 13:29:04 +01:00
Stefan Prodan
d54e7559a5 Merge pull request #966 from stealthybox/fixup-az-imgup-kustomize-build
Use git remote-base instead of zip-archive for cloud image-update example
2021-02-23 11:39:59 +02:00
Hidde Beydals
bb9eca7232 Merge pull request #967 from fluxcd/ci/tweak-if-cond
Fix detection of PRs from forks
2021-02-23 10:24:25 +01:00
leigh capili
b5027d8f3f Use git remote-base instead of zip-archive for cloud image-update example
Signed-off-by: leigh capili <leigh@null.net>
2021-02-23 10:24:24 +01:00
Hidde Beydals
00a134e23f Fix detection of PRs from forks
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-23 10:10:03 +01:00
Hidde Beydals
aab3452773 Merge pull request #949 from fluxcd/k8s-ver-check
Include prerelease data in k8s version constraints
2021-02-19 12:01:14 +01:00
Hidde Beydals
5903dfc627 Include prerelease data in k8s version constraints
This ensures the advertised version from e.g. GKE or EKS (for example
`v1.17.15-gke.800`) do not trigger a false warning.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-19 11:39:16 +01:00
Stefan Prodan
a5272b2b39 Merge pull request #945 from fluxcd/docs-ga-roadmap
Add production ready and GA sections to roadmap
2021-02-18 19:57:13 +02:00
Stefan Prodan
771fc20bb2 Add production ready and GA sections to roadmap
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-18 19:03:49 +02:00
Hidde Beydals
b5f48bee78 Merge pull request #944 from fluxcd/build/codeql-on-push 2021-02-18 15:55:49 +01:00
Hidde Beydals
ff78af5808 Run bootstrap for trusted PRs
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-18 15:41:37 +01:00
Hidde Beydals
7eab649abc Bundle CodeQL, FOSSA, Snyk as jobs in workflow
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-18 15:41:37 +01:00
Hidde Beydals
1b5db157b1 Align formatting and extensions workflows
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-18 15:41:32 +01:00
Hidde Beydals
0fa9aebf7a Split analysis workflows into CodeQL, FOSSA, Snyk
This reverts #934, but takes into account the mistakes that were fixed
there.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-18 14:36:02 +01:00
Hidde Beydals
9fb9965ffe Merge pull request #943 from fluxcd/disable-darwin-arm64
Exclude ARM archs from Darwin release builds
2021-02-18 12:17:50 +01:00
Hidde Beydals
02c9f29499 Exclude ARM archs from Darwin release builds
As we are not on Go 1.16 yet.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-18 12:04:32 +01:00
Hidde Beydals
c6243ad002 Merge pull request #942 from fluxcd/update-components
Update toolkit components
2021-02-18 11:36:09 +01:00
fluxcdbot
f4650c7a84 Update toolkit components
- kustomize-controller to v0.8.1
  https://github.com/fluxcd/kustomize-controller/blob/v0.8.1/CHANGELOG.md
- source-controller to v0.8.1
  https://github.com/fluxcd/source-controller/blob/v0.8.1/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2021-02-18 10:22:26 +00:00
Stefan Prodan
6df691598e Merge pull request #934 from fluxcd/merge-scan-actions
Merge scanning actions
2021-02-17 14:43:35 +02:00
Stefan Prodan
26964b7f88 Merge scanning actions
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-17 11:12:55 +02:00
Stefan Prodan
71712ae1c3 Merge pull request #935 from Niksko/patch-1
Fix typo in gotk_reconcile_condition status
2021-02-17 09:03:53 +02:00
Nik Skoufis
0b6c979e47 Fix typo in gotk_reconcile_condition status
Signed-off-by: Nikolas Skoufis <nskoufis@seek.com.au>
2021-02-17 15:30:24 +11:00
Stefan Prodan
cc2cbc2519 Merge pull request #929 from fluxcd/flux-action
Refactor Flux GitHub Action
2021-02-17 00:33:56 +02:00
Stefan Prodan
8043ae961a Refactor Flux GitHub Action
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-17 00:07:39 +02:00
Hidde Beydals
b1d1d30cdb Merge pull request #932 from idvoretskyi/idvoretskyi-snyk
Snyk GitHub Action added
2021-02-16 22:50:46 +01:00
Ihor Dvoretskyi
28d606cb0e Snyk GitHub Action added
Signed-off-by: Ihor Dvoretskyi <ihor@linux.com>
2021-02-16 23:38:04 +02:00
Hidde Beydals
e9c5b6e917 Merge pull request #933 from adrian/updates-to-sealed-secrets-docs
A few minor updates to sealed secrets docs
2021-02-16 22:20:11 +01:00
Adrian Smith
68f96235fc A few minor updates to sealed secrets docs
* Update to sealed secrets 1.13 helm chart. 1.10 is no longer available.
* Use `--dry-run=client` with kubectl. `--dry-run` on its own is
deprecated.

Signed-off-by: Adrian Smith <adrian@17od.com>
2021-02-16 21:06:50 +00:00
Hidde Beydals
12f22ddeba Merge pull request #931 from fluxcd/add-codeql
Add CodeQL Security Scanning
2021-02-16 19:06:19 +01:00
Chris Aniszczyk
9db5c644a6 Create codeql-analysis.yml
Add CodeSQL Security Scanning to start.

Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
2021-02-16 11:46:25 -06:00
Hidde Beydals
ef6a1fb09b Merge pull request #923 from arbourd/update-runtime
Use `MergeMaps` from pkg/runtime v0.8.2
2021-02-16 00:43:23 +01:00
Dylan Arbour
99002f92f4 Update pkg/runtime to v0.8.2
pkg/runtime v0.8.2 introduces runtime/transform which includes
`MergeMaps`:
https://github.com/fluxcd/pkg/pull/85

Signed-off-by: Dylan Arbour <arbourd@users.noreply.github.com>
2021-02-15 18:06:54 -05:00
Hidde Beydals
298d6a1a15 Merge pull request #922 from fluxcd/check-improvements 2021-02-15 22:14:00 +01:00
Hidde Beydals
5a21f50230 Remove unused util functions
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-15 21:57:11 +01:00
Hidde Beydals
5263dabd22 Check if targeted version is supported by binary
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-15 21:57:11 +01:00
Hidde Beydals
9b649f6c72 Check if targeted bootstrap/install version exists
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-15 21:57:06 +01:00
Hidde Beydals
b903cd5b68 Check for new Flux binary version
This prints a warning if the user has internet access and is running
an older version of the binary.

It also replaces the `blang/semver` package with `pkg/version` and
`Masterminds/semver` to align with controller dependencies.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-15 21:48:27 +01:00
Hidde Beydals
890b5c5202 Use label selector to check components
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-15 16:39:29 +01:00
Hidde Beydals
a14e88d04d Merge pull request #915 from fluxcd/docs-helm-features 2021-02-13 19:08:11 +01:00
Hidde Beydals
58e09b4c68 docs: list Helm post renderer feature
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-13 15:56:43 +01:00
Stefan Prodan
631201d541 Merge pull request #914 from fluxcd/img-update-roadmap
Update image update feature parity roadmap
2021-02-12 18:35:48 +02:00
Stefan Prodan
0fbeb6d2cd Update semver flag in image update guide
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-12 18:23:25 +02:00
Stefan Prodan
11f8e2ffde Update image update feature parity roadmap
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-12 18:21:29 +02:00
Hidde Beydals
055eb4a61a Merge pull request #806 from fluxcd/image-auto-migration-howto 2021-02-12 17:20:35 +01:00
Hidde Beydals
30c1c5c3d3 Link to image automation guides in menu
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 17:01:43 +01:00
Hidde Beydals
e034ec3207 Add missing link to image update automation ref
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 17:01:08 +01:00
Hidde Beydals
8edc4bd24b Add missing link to SemVer spec
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 16:49:33 +01:00
Hidde Beydals
6e1672f73c Change policy example to numerical in asc order
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 16:47:16 +01:00
Michael Bridgen
5e1f6f7317 Fix up internal links
Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
386780ba12 Make hrefs absolute and spelt correctly
Stray characters here and there threw off the markdown engine.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
e785971ba8 Rewrite to account for numerical sorting
Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
daaae07649 Persuade markdown relative paths are links
Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
6cd567dc66 Remove draft TODO comments
I have moved TODO comments (that still apply) to the PR description.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
a541a7ee85 Remove suggestions of using commit number
Using a commit number is trickier than it sounds. It would need to be
padded to sort correctly, for one thing. It is better to leave it out
than to give an incomplete account.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
43572bba04 Rearrange so that observing an auto commit is last
Previously, creating an automation object was the last instruction. It
is easier to describe what to expect at each step when the last step
is to add an update marker in the file to be updated, since the next
thing that should happen is that the automation makes an update as a
consequence.

This commit shifts the sections around so that setting up the
GitRepository and ImageUpdateAutomation are done earlier, and
migrating each file are done after that, and completes the steps
described including checking the expected status at each stage.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
2a3a4456c1 Separate image tags howto from migration howto
The Flux v1 migration how-to flows better if the section on how to set
builds up to tag images in the right way is its own document. It's a
lot to skim past when you don't need it, and (since it's a different
layer of yak hair) something you might want to figure out first if you
do need it.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Michael Bridgen
15f8e6369b Add image automation migration how-to
This doc describes how to move from using Flux v1 to update image refs
in git, to using Flux v2. There is some overlap with the tutorial on
how to use Flux v2 automation. This how-to spends more time on how to
convert existing configuration to be used with Flux v2.

Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 16:46:30 +01:00
Hidde Beydals
cfad9a19eb Merge pull request #911 from fluxcd/select-numeric-validation
Validate if only one image policy selector is given
2021-02-12 16:14:21 +01:00
Hidde Beydals
e4c3136433 Merge pull request #910 from fluxcd/git-ca-file
Add caFile to create source/secret git commands
2021-02-12 16:01:27 +01:00
Hidde Beydals
73b8a26850 Validate if only 1 image policy selector is given
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 16:01:25 +01:00
Stefan Prodan
aa533b28fb Add caFile to create source/secret git commands
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-12 16:47:00 +02:00
Hidde Beydals
9d70e09a57 Add numeric selector to create image policy cmd
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 15:38:01 +01:00
Stefan Prodan
17e18985e6 Merge pull request #908 from fluxcd/update-kustomize-api
Update sigs.k8s.io/kustomize/api to v0.7.4
2021-02-12 15:49:39 +02:00
Hidde Beydals
7c39aaf463 Update sigs.k8s.io/kustomize/api to v0.7.4
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 14:32:44 +01:00
Hidde Beydals
bae5c125e8 Merge pull request #907 from fluxcd/update-components
Update toolkit components
2021-02-12 14:29:23 +01:00
fluxcdbot
1c84fa0d97 Update toolkit components
- helm-controller to v0.7.0
  https://github.com/fluxcd/helm-controller/blob/v0.7.0/CHANGELOG.md
- kustomize-controller to v0.8.0
  https://github.com/fluxcd/kustomize-controller/blob/v0.8.0/CHANGELOG.md
- source-controller to v0.8.0
  https://github.com/fluxcd/source-controller/blob/v0.8.0/CHANGELOG.md
- notification-controller to v0.8.0
  https://github.com/fluxcd/notification-controller/blob/v0.8.0/CHANGELOG.md
- image-reflector-controller to v0.6.0
  https://github.com/fluxcd/image-reflector-controller/blob/v0.6.0/CHANGELOG.md
- image-automation-controller to v0.5.0
  https://github.com/fluxcd/image-automation-controller/blob/v0.5.0/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2021-02-12 13:16:13 +00:00
Hidde Beydals
6f583f9f0e Merge pull request #878 from fluxcd/pprof-guide 2021-02-12 14:02:36 +01:00
Hidde Beydals
217574b75c Add debugging to dev guides menu
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 13:44:35 +01:00
Hidde Beydals
1378530aeb Add section about resource usage
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 13:44:35 +01:00
Hidde Beydals
0b10ed4d88 Add guide for pprof endpoints
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-12 13:44:35 +01:00
Stefan Prodan
a2887f5776 Merge pull request #891 from fluxcd/refac-uninstall
Refactor flux uninstall command
2021-02-12 14:44:23 +02:00
Stefan Prodan
0f1d27f1e6 Remove network policies on uninstall
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-12 14:30:57 +02:00
Stefan Prodan
850ab0942b Implement uninstall dry run
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-12 14:30:50 +02:00
Stefan Prodan
f5ae8f44b4 Refactor flux uninstall command
- deletes Flux components (deployments and services)
- deletes Flux RBAC (service accounts, cluster roles and cluster role bindings)
- removes the Kubernetes finalizers from Flux custom resources
- deletes Flux custom resource definitions and custom resources
- deletes the namespace where Flux was installed
- preserves the Kubernetes objects and Helm releases that were reconciled on the cluster by Flux

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-12 14:30:50 +02:00
Michael Bridgen
7f98cfd506 Merge pull request #906 from fluxcd/personal-flag
Give more explanation for --personal flag
2021-02-12 12:02:22 +00:00
Michael Bridgen
bc45a79b92 Give more explanation for --personal flag
Signed-off-by: Michael Bridgen <michael@weave.works>
2021-02-12 11:41:27 +00:00
Stefan Prodan
5003cf674d Merge pull request #904 from fluxcd/add-version-to-commits
Add flux version to bootstrap commit messages
2021-02-12 11:38:35 +02:00
Stefan Prodan
bc9cbc387c Add flux version to bootstrap commit messages
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-12 10:47:00 +02:00
Stefan Prodan
60a1e78869 Merge pull request #899 from fluxcd/toleration-keys
Allow Flux to be deployed on tainted Kubernetes nodes
2021-02-11 15:46:45 +02:00
Stefan Prodan
37f5587085 Allow Flux to be deployed on tainted Kubernetes nodes
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-11 15:20:19 +02:00
Hidde Beydals
fa6e3d3706 Merge pull request #898 from fluxcd/docs-fix-list 2021-02-11 13:20:19 +01:00
Hidde Beydals
bb8bc875b4 docs: improve Kustomize behavior FAQ
- Fix the formatting of the list.
- Add a hint block for validating changes locally and/or in CI.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-02-11 12:54:03 +01:00
Stefan Prodan
b3dca737be Merge pull request #897 from fluxcd/fix-timeout
Map timeout arg to bootstrap status check
2021-02-11 13:30:05 +02:00
Stefan Prodan
9094f85487 Add image automation to readme
Sync community section readme/docs index

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-11 13:11:03 +02:00
Stefan Prodan
1256bbfbaf Fix bootstrap status check timeout
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-11 13:09:16 +02:00
Daniel Holbach
24fe74f2f6 Merge pull request #893 from dholbach/link-to-community-page
Link to community page from docs home page
2021-02-10 08:40:15 +01:00
Daniel Holbach
908f501e03 link to community page from toolkit.f.i
Signed-off-by: Daniel Holbach <daniel@weave.works>
2021-02-09 14:52:17 +01:00
Stefan Prodan
35507c7854 Merge pull request #860 from jonathan-innis/joinnis/image-policy
Adding --select-alpha and --extract to create image policy
2021-02-09 15:05:57 +02:00
Jonathan Innis
eb7102ecac Adding extract pattern validation
Signed-off-by: Jonathan Innis <jonathan.innis.ji@gmail.com>
2021-02-08 16:51:45 -08:00
Jonathan Innis
ade6bfcbca Update e2e testing with new cli args
Signed-off-by: Jonathan Innis <jonathan.innis.ji@gmail.com>
2021-02-08 16:49:07 -08:00
Jonathan Innis
fa98403aa8 Add newly generated create image doc
Signed-off-by: Jonathan Innis <jonathan.innis.ji@gmail.com>
2021-02-08 16:49:07 -08:00
jonathan-innis
3f0cb1637c Add select-alpha and extract to create policy
Signed-off-by: jonathan-innis <jonathan.innis.ji@gmail.com>
2021-02-08 16:49:07 -08:00
Stefan Prodan
42011d028e Merge pull request #879 from fluxcd/azure-devops-pat
Add Azure DevOps PAT auth to install docs
2021-02-08 19:01:49 +02:00
Stefan Prodan
307bb0dea1 Add Azure DevOps PAT auth to install docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-08 18:44:22 +02:00
Stefan Prodan
ec2a8347d4 Merge pull request #877 from stealthybox/integrations-registry-credentials-sync
Add ACR auth to Image Updates examples
2021-02-08 18:43:22 +02:00
leigh capili
e99b1c3ed8 Document ACR / AKS Image Update Considerations
Signed-off-by: leigh capili <leigh@null.net>
2021-02-08 09:15:42 -07:00
leigh capili
99825f2663 Add registry cred Deployments/CronJobs for aws/gcp/azure via kustomize
Signed-off-by: leigh capili <leigh@null.net>
2021-02-08 09:15:42 -07:00
Stefan Prodan
afffdfbc5c Merge pull request #880 from chanwit/add_kustomize_fag
Add FAQ to explain the current Kustomize behavior
2021-02-08 17:54:28 +02:00
Chanwit Kaewkasi
cd874acfd5 add FAQ to explain the current Kustomize behavior
Signed-off-by: Chanwit Kaewkasi <chanwit@gmail.com>
2021-02-08 21:24:31 +07:00
Stefan Prodan
34edbf469e Merge pull request #871 from fluxcd/incident-mgmt
Add incident management section to image automation docs
2021-02-06 12:47:10 +02:00
Stefan Prodan
d9ed30e436 Add incident management section to image automation docs
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-02-06 10:51:37 +02:00
100 changed files with 3687 additions and 843 deletions

View File

@@ -2,12 +2,14 @@ name: bootstrap
on: on:
push: push:
branches: branches: [ main ]
- '*' pull_request:
branches: [ main ]
jobs: jobs:
github: github:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -15,23 +17,27 @@ jobs:
uses: actions/cache@v1 uses: actions/cache@v1
with: with:
path: ~/go/pkg/mod path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go- ${{ runner.os }}-go1.16-
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.15.x go-version: 1.16.x
- name: Setup Kubernetes - name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0 uses: engineerd/setup-kind@v0.5.0
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Build
run: |
make build-manifests
go build -o /tmp/flux ./cmd/flux
- name: Set outputs - name: Set outputs
id: vars id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Build
run: sudo go build -o ./bin/flux ./cmd/flux
- name: bootstrap init - name: bootstrap init
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \
@@ -40,7 +46,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: bootstrap no-op - name: bootstrap no-op
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \
@@ -49,10 +55,11 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: uninstall - name: uninstall
run: | run: |
./bin/flux uninstall --resources --crds -s --timeout=10m /tmp/flux uninstall -s --keep-namespace
kubectl delete ns flux-system --timeout=10m --wait=true
- name: bootstrap reinstall - name: bootstrap reinstall
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \
@@ -61,7 +68,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: delete repository - name: delete repository
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \

View File

@@ -1,9 +1,8 @@
name: Publish docs via GitHub Pages name: Publish docs via GitHub Pages
on: on:
push: push:
branches: branches: [ 'docs*', main ]
- docs*
- main
jobs: jobs:
build: build:
@@ -17,7 +16,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
controller_version() { controller_version() {
sed -n "s/.*$1\/archive\/\(.*\).zip.*/\1/p;n" manifests/bases/$1/kustomization.yaml sed -n "s/.*$1\/releases\/download\/\(.*\)\/.*/\1/p;n" manifests/bases/$1/kustomization.yaml
} }
{ {

View File

@@ -1,10 +1,10 @@
name: e2e name: e2e
on: on:
pull_request:
push: push:
branches: branches: [ main ]
- main pull_request:
branches: [ main ]
jobs: jobs:
kind: kind:
@@ -16,13 +16,13 @@ jobs:
uses: actions/cache@v1 uses: actions/cache@v1
with: with:
path: ~/go/pkg/mod path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go- ${{ runner.os }}-go1.16-
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.15.x go-version: 1.16.x
- name: Setup Kubernetes - name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0 uses: engineerd/setup-kind@v0.5.0
with: with:
@@ -33,6 +33,8 @@ jobs:
run: | run: |
kubectl apply -f https://docs.projectcalico.org/v3.16/manifests/calico.yaml kubectl apply -f https://docs.projectcalico.org/v3.16/manifests/calico.yaml
kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Run test - name: Run test
run: make test run: make test
- name: Check if working tree is dirty - name: Check if working tree is dirty
@@ -43,43 +45,44 @@ jobs:
exit 1 exit 1
fi fi
- name: Build - name: Build
run: sudo go build -o ./bin/flux ./cmd/flux run: |
go build -o /tmp/flux ./cmd/flux
- name: flux check --pre - name: flux check --pre
run: | run: |
./bin/flux check --pre /tmp/flux check --pre
- name: flux install --manifests - name: flux install --manifests
run: | run: |
./bin/flux install --manifests ./manifests/install/ /tmp/flux install --manifests ./manifests/install/
- name: flux create secret - name: flux create secret
run: | run: |
./bin/flux create secret git git-ssh-test \ /tmp/flux create secret git git-ssh-test \
--url ssh://git@github.com/stefanprodan/podinfo --url ssh://git@github.com/stefanprodan/podinfo
./bin/flux create secret git git-https-test \ /tmp/flux create secret git git-https-test \
--url https://github.com/stefanprodan/podinfo \ --url https://github.com/stefanprodan/podinfo \
--username=test --password=test --username=test --password=test
./bin/flux create secret helm helm-test \ /tmp/flux create secret helm helm-test \
--username=test --password=test --username=test --password=test
- name: flux create source git - name: flux create source git
run: | run: |
./bin/flux create source git podinfo \ /tmp/flux create source git podinfo \
--url https://github.com/stefanprodan/podinfo \ --url https://github.com/stefanprodan/podinfo \
--tag-semver=">=3.2.3" --tag-semver=">=3.2.3"
- name: flux create source git export apply - name: flux create source git export apply
run: | run: |
./bin/flux create source git podinfo-export \ /tmp/flux create source git podinfo-export \
--url https://github.com/stefanprodan/podinfo \ --url https://github.com/stefanprodan/podinfo \
--tag-semver=">=3.2.3" \ --tag-semver=">=3.2.3" \
--export | kubectl apply -f - --export | kubectl apply -f -
./bin/flux delete source git podinfo-export --silent /tmp/flux delete source git podinfo-export --silent
- name: flux get sources git - name: flux get sources git
run: | run: |
./bin/flux get sources git /tmp/flux get sources git
- name: flux get sources git --all-namespaces - name: flux get sources git --all-namespaces
run: | run: |
./bin/flux get sources git --all-namespaces /tmp/flux get sources git --all-namespaces
- name: flux create kustomization - name: flux create kustomization
run: | run: |
./bin/flux create kustomization podinfo \ /tmp/flux create kustomization podinfo \
--source=podinfo \ --source=podinfo \
--path="./deploy/overlays/dev" \ --path="./deploy/overlays/dev" \
--prune=true \ --prune=true \
@@ -90,106 +93,112 @@ jobs:
--health-check-timeout=3m --health-check-timeout=3m
- name: flux reconcile kustomization --with-source - name: flux reconcile kustomization --with-source
run: | run: |
./bin/flux reconcile kustomization podinfo --with-source /tmp/flux reconcile kustomization podinfo --with-source
- name: flux get kustomizations - name: flux get kustomizations
run: | run: |
./bin/flux get kustomizations /tmp/flux get kustomizations
- name: flux get kustomizations --all-namespaces - name: flux get kustomizations --all-namespaces
run: | run: |
./bin/flux get kustomizations --all-namespaces /tmp/flux get kustomizations --all-namespaces
- name: flux suspend kustomization - name: flux suspend kustomization
run: | run: |
./bin/flux suspend kustomization podinfo /tmp/flux suspend kustomization podinfo
- name: flux resume kustomization - name: flux resume kustomization
run: | run: |
./bin/flux resume kustomization podinfo /tmp/flux resume kustomization podinfo
- name: flux export - name: flux export
run: | run: |
./bin/flux export source git --all /tmp/flux export source git --all
./bin/flux export kustomization --all /tmp/flux export kustomization --all
- name: flux delete kustomization - name: flux delete kustomization
run: | run: |
./bin/flux delete kustomization podinfo --silent /tmp/flux delete kustomization podinfo --silent
- name: flux create source helm - name: flux create source helm
run: | run: |
./bin/flux create source helm podinfo \ /tmp/flux create source helm podinfo \
--url https://stefanprodan.github.io/podinfo --url https://stefanprodan.github.io/podinfo
- name: flux create helmrelease --source=HelmRepository/podinfo - name: flux create helmrelease --source=HelmRepository/podinfo
run: | run: |
./bin/flux create hr podinfo-helm \ /tmp/flux create hr podinfo-helm \
--target-namespace=default \ --target-namespace=default \
--source=HelmRepository/podinfo \ --source=HelmRepository/podinfo \
--chart=podinfo \ --chart=podinfo \
--chart-version=">4.0.0 <5.0.0" --chart-version=">4.0.0 <5.0.0"
- name: flux create helmrelease --source=GitRepository/podinfo - name: flux create helmrelease --source=GitRepository/podinfo
run: | run: |
./bin/flux create hr podinfo-git \ /tmp/flux create hr podinfo-git \
--target-namespace=default \ --target-namespace=default \
--source=GitRepository/podinfo \ --source=GitRepository/podinfo \
--chart=./charts/podinfo --chart=./charts/podinfo
- name: flux reconcile helmrelease --with-source - name: flux reconcile helmrelease --with-source
run: | run: |
./bin/flux reconcile helmrelease podinfo-git --with-source /tmp/flux reconcile helmrelease podinfo-git --with-source
- name: flux get helmreleases - name: flux get helmreleases
run: | run: |
./bin/flux get helmreleases /tmp/flux get helmreleases
- name: flux get helmreleases --all-namespaces - name: flux get helmreleases --all-namespaces
run: | run: |
./bin/flux get helmreleases --all-namespaces /tmp/flux get helmreleases --all-namespaces
- name: flux export helmrelease - name: flux export helmrelease
run: | run: |
./bin/flux export hr --all /tmp/flux export hr --all
- name: flux delete helmrelease podinfo-helm - name: flux delete helmrelease podinfo-helm
run: | run: |
./bin/flux delete hr podinfo-helm --silent /tmp/flux delete hr podinfo-helm --silent
- name: flux delete helmrelease podinfo-git - name: flux delete helmrelease podinfo-git
run: | run: |
./bin/flux delete hr podinfo-git --silent /tmp/flux delete hr podinfo-git --silent
- name: flux delete source helm - name: flux delete source helm
run: | run: |
./bin/flux delete source helm podinfo --silent /tmp/flux delete source helm podinfo --silent
- name: flux delete source git - name: flux delete source git
run: | run: |
./bin/flux delete source git podinfo --silent /tmp/flux delete source git podinfo --silent
- name: flux create tenant - name: flux create tenant
run: | run: |
./bin/flux create tenant dev-team --with-namespace=apps /tmp/flux create tenant dev-team --with-namespace=apps
./bin/flux -n apps create source helm podinfo \ /tmp/flux -n apps create source helm podinfo \
--url https://stefanprodan.github.io/podinfo --url https://stefanprodan.github.io/podinfo
./bin/flux -n apps create hr podinfo-helm \ /tmp/flux -n apps create hr podinfo-helm \
--source=HelmRepository/podinfo \ --source=HelmRepository/podinfo \
--chart=podinfo \ --chart=podinfo \
--chart-version="5.0.x" \ --chart-version="5.0.x" \
--service-account=dev-team --service-account=dev-team
- name: flux create image repository - name: flux create image repository
run: | run: |
./bin/flux create image repository podinfo \ /tmp/flux create image repository podinfo \
--image=ghcr.io/stefanprodan/podinfo \ --image=ghcr.io/stefanprodan/podinfo \
--interval=1m --interval=1m
- name: flux create image policy - name: flux create image policy
run: | run: |
./bin/flux create image policy podinfo \ /tmp/flux create image policy podinfo \
--image-ref=podinfo \ --image-ref=podinfo \
--interval=1m \ --interval=1m \
--semver=5.0.x --select-semver=5.0.x
- name: flux create image policy podinfo-select-alpha
run: |
/tmp/flux create image policy podinfo-alpha \
--image-ref=podinfo \
--interval=1m \
--select-alpha=desc
- name: flux get image policy - name: flux get image policy
run: | run: |
./bin/flux get image policy podinfo | grep '5.0.3' /tmp/flux get image policy podinfo | grep '5.0.3'
- name: flux2-kustomize-helm-example - name: flux2-kustomize-helm-example
run: | run: |
./bin/flux create source git flux-system \ /tmp/flux create source git flux-system \
--url=https://github.com/fluxcd/flux2-kustomize-helm-example \ --url=https://github.com/fluxcd/flux2-kustomize-helm-example \
--branch=main --branch=main
./bin/flux create kustomization flux-system \ /tmp/flux create kustomization flux-system \
--source=flux-system \ --source=flux-system \
--path=./clusters/staging --path=./clusters/staging
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=2m kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=2m
- name: flux check - name: flux check
run: | run: |
./bin/flux check /tmp/flux check
- name: flux uninstall - name: flux uninstall
run: | run: |
./bin/flux uninstall --crds --silent --timeout=10m /tmp/flux uninstall --silent
- name: Debug failure - name: Debug failure
if: failure() if: failure()
run: | run: |

View File

@@ -1,25 +0,0 @@
name: FOSSA
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "^1.14.x"
- name: Add GOPATH to GITHUB_ENV
run: echo "GOPATH=$(go env GOPATH)" >>"$GITHUB_ENV"
- name: Add GOPATH to GITHUB_PATH
run: echo "$GOPATH/bin" >>"$GITHUB_PATH"
- name: Run FOSSA scan and upload build data
uses: fossa-contrib/fossa-action@v1
with:
# FOSSA Push-Only API Token
fossa-api-key: 5ee8bf422db1471e0bcf2bcb289185de
github-token: ${{ github.token }}

View File

@@ -2,9 +2,9 @@ name: rebase
on: on:
pull_request: pull_request:
types: [opened] types: [ opened ]
issue_comment: issue_comment:
types: [created] types: [ created ]
jobs: jobs:
rebase: rebase:

View File

@@ -2,8 +2,7 @@ name: release
on: on:
push: push:
tags: tags: [ 'v*' ]
- '*'
jobs: jobs:
goreleaser: goreleaser:
@@ -16,7 +15,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.15.x go-version: 1.16.x
- name: Download release notes utility - name: Download release notes utility
env: env:
GH_REL_URL: https://github.com/buchanae/github-release-notes/releases/download/0.2.0/github-release-notes-linux-amd64-0.2.0.tar.gz GH_REL_URL: https://github.com/buchanae/github-release-notes/releases/download/0.2.0/github-release-notes-linux-amd64-0.2.0.tar.gz
@@ -29,38 +28,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Kustomize - name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main uses: fluxcd/pkg//actions/kustomize@main
- name: Generate manifests tarball - name: Generate manifests
run: |
mkdir -p ./output
files=""
# build controllers
for controller in ./manifests/bases/*/; do
output_path="./output/$(basename $controller).yaml"
echo "building $controller to $output_path"
kustomize build $controller > $output_path
files+=" $(basename $output_path)"
done
# build rbac
rbac_path="./manifests/rbac"
rbac_output_path="./output/rbac.yaml"
echo "building $rbac_path to $rbac_output_path"
kustomize build $rbac_path > $rbac_output_path
files+=" $(basename $rbac_output_path)"
# build policies
policies_path="./manifests/policies"
policies_output_path="./output/policies.yaml"
echo "building $policies_path to $policies_output_path"
kustomize build $policies_path > $policies_output_path
files+=" $(basename $policies_output_path)"
# create tarball
cd ./output && tar -cvzf manifests.tar.gz $files
- name: Generate install manifest
run: | run: |
make build-manifests
./manifests/scripts/bundle.sh ./output manifests.tar.gz
kustomize build ./manifests/install > ./output/install.yaml kustomize build ./manifests/install > ./output/install.yaml
- name: Run GoReleaser - name: Run GoReleaser
uses: goreleaser/goreleaser-action@v1 uses: goreleaser/goreleaser-action@v1

60
.github/workflows/scan.yaml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Scan
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '18 10 * * 3'
jobs:
fossa:
name: FOSSA
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run FOSSA scan and upload build data
uses: fossa-contrib/fossa-action@v1
with:
# FOSSA Push-Only API Token
fossa-api-key: 5ee8bf422db1471e0bcf2bcb289185de
github-token: ${{ github.token }}
snyk:
name: Snyk
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
steps:
- uses: actions/checkout@v2
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Build manifests
run: |
make build-manifests
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/golang@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --sarif-file-output=snyk.sarif
- name: Upload result to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: snyk.sarif
codeql:
name: CodeQL
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: go
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -13,7 +13,10 @@ jobs:
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: 1.16.x
- name: Update component versions - name: Update component versions
id: update id: update
run: | run: |
@@ -21,11 +24,11 @@ jobs:
bump_version() { bump_version() {
local RELEASE_VERSION=$(curl -s https://api.github.com/repos/fluxcd/$1/releases | jq -r 'sort_by(.published_at) | .[-1] | .tag_name') local RELEASE_VERSION=$(curl -s https://api.github.com/repos/fluxcd/$1/releases | jq -r 'sort_by(.published_at) | .[-1] | .tag_name')
local CURRENT_VERSION=$(sed -n "s/.*$1\/archive\/\(.*\).zip.*/\1/p;n" manifests/bases/$1/kustomization.yaml) local CURRENT_VERSION=$(sed -n "s/.*$1\/releases\/download\/\(.*\)\/.*/\1/p;n" manifests/bases/$1/kustomization.yaml)
if [[ "${RELEASE_VERSION}" != "${CURRENT_VERSION}" ]]; then if [[ "${RELEASE_VERSION}" != "${CURRENT_VERSION}" ]]; then
# bump kustomize # bump kustomize
sed -i "s/\($1\/archive\/\)v.*\(.zip\/\/$1-\).*\(\/config.*\)/\1${RELEASE_VERSION}\2${RELEASE_VERSION/v}\3/g" "manifests/bases/$1/kustomization.yaml" sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${RELEASE_VERSION}\2/g" "manifests/bases/$1/kustomization.yaml"
if [[ ! -z $(go list -m all | grep "github.com/fluxcd/$1/api" | awk '{print $2}') ]]; then if [[ ! -z $(go list -m all | grep "github.com/fluxcd/$1/api" | awk '{print $2}') ]]; then
# bump go mod # bump go mod

3
.gitignore vendored
View File

@@ -14,4 +14,5 @@
# Dependency directories (remove the comment below to include it) # Dependency directories (remove the comment below to include it)
# vendor/ # vendor/
bin/ bin/
output/ output/
cmd/flux/manifests/

View File

@@ -20,6 +20,9 @@ builds:
id: darwin id: darwin
goos: goos:
- darwin - darwin
goarch:
- amd64
- arm64
- <<: *build_defaults - <<: *build_defaults
id: windows id: windows
goos: goos:

View File

@@ -11,9 +11,12 @@ fmt:
vet: vet:
go vet ./... go vet ./...
test: tidy fmt vet docs test: build-manifests tidy fmt vet docs
go test ./... -coverprofile cover.out go test ./... -coverprofile cover.out
build-manifests:
./manifests/scripts/bundle.sh
build: build:
CGO_ENABLED=0 go build -o ./bin/flux ./cmd/flux CGO_ENABLED=0 go build -o ./bin/flux ./cmd/flux

View File

@@ -60,13 +60,12 @@ To get started with Flux, start [browsing the
documentation](https://toolkit.fluxcd.io) or get started with one of documentation](https://toolkit.fluxcd.io) or get started with one of
the following guides: the following guides:
- [Get started with Flux (deep dive)](https://toolkit.fluxcd.io/get-started/) - [Get started with Flux](https://toolkit.fluxcd.io/get-started/)
- [Installation](https://toolkit.fluxcd.io/guides/installation/)
- [Manage Helm Releases](https://toolkit.fluxcd.io/guides/helmreleases/) - [Manage Helm Releases](https://toolkit.fluxcd.io/guides/helmreleases/)
- [Setup Notifications](https://toolkit.fluxcd.io/guides/notifications/) - [Automate image updates to Git](https://toolkit.fluxcd.io/guides/image-update/)
- [Setup Webhook Receivers](https://toolkit.fluxcd.io/guides/webhook-receivers/) - [Manage Kubernetes secrets with Mozilla SOPS](https://toolkit.fluxcd.io/guides/mozilla-sops/)
If you should need help, please refer to our **[Support page](https://fluxcd.io/support/)**. If you need help, please refer to our **[Support page](https://fluxcd.io/support/)**.
## GitOps Toolkit ## GitOps Toolkit
@@ -96,17 +95,24 @@ guides](https://toolkit.fluxcd.io/dev-guides/source-watcher/).
- [Provider CRD](https://toolkit.fluxcd.io/components/notification/provider/) - [Provider CRD](https://toolkit.fluxcd.io/components/notification/provider/)
- [Alert CRD](https://toolkit.fluxcd.io/components/notification/alert/) - [Alert CRD](https://toolkit.fluxcd.io/components/notification/alert/)
- [Receiver CRD](https://toolkit.fluxcd.io/components/notification/receiver/) - [Receiver CRD](https://toolkit.fluxcd.io/components/notification/receiver/)
- [Image Automation Controllers](https://toolkit.fluxcd.io/components/image/controller/)
- [ImageRepository CRD](https://toolkit.fluxcd.io/components/image/imagerepositories/)
- [ImagePolicy CRD](https://toolkit.fluxcd.io/components/image/imagepolicies/)
- [ImageUpdateAutomation CRD](https://toolkit.fluxcd.io/components/image/imageupdateautomations/)
## Community ## Community
Need help or want to contribute? Please see the links below. The Flux project is always looking for new contributors and there are a multitude of ways to get involved. Need help or want to contribute? Please see the links below. The Flux project is always looking for
new contributors and there are a multitude of ways to get involved.
- Getting Started? - Getting Started?
- Look at our [Get Started guide](https://toolkit.fluxcd.io/get-started/) and give us feedback - Look at our [Get Started guide](https://toolkit.fluxcd.io/get-started/) and give us feedback
- Need help? - Need help?
- First: Ask questions on our [GH Discussions page](https://github.com/fluxcd/flux2/discussions) - First: Ask questions on our [GH Discussions page](https://github.com/fluxcd/flux2/discussions)
- Second: Talk to us in the #flux channel on [CNCF Slack](https://slack.cncf.io/) - Second: Talk to us in the #flux channel on [CNCF Slack](https://slack.cncf.io/)
- Please follow our [Support Guidelines](https://fluxcd.io/support/) (in short: be nice, be respectful of volunteers' time, understand that maintainers and contributors cannot respond to all DMs, and keep discussions in the public #flux channel as much as possible). - Please follow our [Support Guidelines](https://fluxcd.io/support/)
(in short: be nice, be respectful of volunteers' time, understand that maintainers and
contributors cannot respond to all DMs, and keep discussions in the public #flux channel as much as possible).
- Have feature proposals or want to contribute? - Have feature proposals or want to contribute?
- Propose features on our [GH Discussions page](https://github.com/fluxcd/flux2/discussions) - Propose features on our [GH Discussions page](https://github.com/fluxcd/flux2/discussions)
- Join our upcoming dev meetings ([meeting access and agenda](https://docs.google.com/document/d/1l_M0om0qUEN_NNiGgpqJ2tvsF2iioHkaARDeh6b70B0/view)) - Join our upcoming dev meetings ([meeting access and agenda](https://docs.google.com/document/d/1l_M0om0qUEN_NNiGgpqJ2tvsF2iioHkaARDeh6b70B0/view))
@@ -115,6 +121,7 @@ Need help or want to contribute? Please see the links below. The Flux project is
### Events ### Events
Check out our **[events calendar](https://fluxcd.io/community/#talks)**, both with upcoming talks you can attend or past events videos you can watch. Check out our **[events calendar](https://fluxcd.io/community/#talks)**,
both with upcoming talks you can attend or past events videos you can watch.
We look forward to seeing you with us! We look forward to seeing you with us!

View File

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

View File

@@ -10,15 +10,20 @@ Usage:
run: flux -v run: flux -v
``` ```
This action places the `flux` binary inside your repository root under `bin/flux`.
You should add `bin/flux` to your `.gitignore` file, as in the following example:
```gitignore
# ignore flux binary
bin/flux
```
Note that this action can only be used on GitHub **Linux AMD64** runners. Note that this action can only be used on GitHub **Linux AMD64** runners.
The latest stable version of the `flux` binary is downloaded from
GitHub [releases](https://github.com/fluxcd/flux2/releases)
and placed at `/usr/local/bin/flux`.
You can download a specific version with:
```yaml
steps:
- name: Setup Flux CLI
uses: fluxcd/flux2/action@main
with:
version: 0.8.0
```
### Automate Flux updates ### Automate Flux updates

View File

@@ -1,15 +1,38 @@
name: 'kustomize' name: Setup Flux CLI
description: 'A GitHub Action for running Flux commands' description: A GitHub Action for running Flux commands
author: 'Flux project' author: Stefan Prodan
branding: branding:
icon: 'command' color: blue
color: 'blue' icon: command
inputs: inputs:
version: version:
description: 'strict semver' description: "Flux version e.g. 0.8.0 (defaults to latest stable release)"
required: false required: false
runs: runs:
using: 'docker' using: composite
image: 'Dockerfile' steps:
args: - name: "Download flux binary to tmp"
- ${{ inputs.version }} shell: bash
run: |
VERSION=${{ inputs.version }}
if [ -z $VERSION ]; then
VERSION=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest -sL | grep tag_name | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
fi
BIN_URL="https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_amd64.tar.gz"
curl -sL ${BIN_URL} -o /tmp/flux.tar.gz
mkdir -p /tmp/flux
tar -C /tmp/flux/ -zxvf /tmp/flux.tar.gz
- name: "Add flux binary to /usr/local/bin"
shell: bash
run: |
sudo cp /tmp/flux/flux /usr/local/bin
- name: "Cleanup tmp"
shell: bash
run: |
rm -rf /tmp/flux/ /tmp/flux.tar.gz
- name: "Verify correct installation of binary"
shell: bash
run: |
flux -v

View File

@@ -1,40 +0,0 @@
#!/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
mv ./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

@@ -60,6 +60,7 @@ type bootstrapFlags struct {
requiredComponents []string requiredComponents []string
tokenAuth bool tokenAuth bool
clusterDomain string clusterDomain string
tolerationKeys []string
} }
const ( const (
@@ -69,8 +70,8 @@ const (
var bootstrapArgs = NewBootstrapFlags() var bootstrapArgs = NewBootstrapFlags()
func init() { func init() {
bootstrapCmd.PersistentFlags().StringVarP(&bootstrapArgs.version, "version", "v", rootArgs.defaults.Version, bootstrapCmd.PersistentFlags().StringVarP(&bootstrapArgs.version, "version", "v", "",
"toolkit version") "toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases")
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.defaultComponents, "components", rootArgs.defaults.Components, bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.defaultComponents, "components", rootArgs.defaults.Components,
"list of components, accepts comma-separated values") "list of components, accepts comma-separated values")
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.extraComponents, "components-extra", nil, bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.extraComponents, "components-extra", nil,
@@ -91,6 +92,8 @@ func init() {
bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.logLevel, "log-level", bootstrapArgs.logLevel.Description()) bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.logLevel, "log-level", bootstrapArgs.logLevel.Description())
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.manifestsPath, "manifests", "", "path to the manifest directory") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.manifestsPath, "manifests", "", "path to the manifest directory")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.clusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.clusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain")
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.tolerationKeys, "toleration-keys", nil,
"list of toleration keys used to schedule the components pods onto nodes with matching taints")
bootstrapCmd.PersistentFlags().MarkHidden("manifests") bootstrapCmd.PersistentFlags().MarkHidden("manifests")
bootstrapCmd.PersistentFlags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64") bootstrapCmd.PersistentFlags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64")
rootCmd.AddCommand(bootstrapCmd) rootCmd.AddCommand(bootstrapCmd)
@@ -123,6 +126,20 @@ func bootstrapValidate() error {
} }
func generateInstallManifests(targetPath, namespace, tmpDir string, localManifests string) (string, error) { func generateInstallManifests(targetPath, namespace, tmpDir string, localManifests string) (string, error) {
if ver, err := getVersion(bootstrapArgs.version); err != nil {
return "", err
} else {
bootstrapArgs.version = ver
}
manifestsBase := ""
if isEmbeddedVersion(bootstrapArgs.version) {
if err := writeEmbeddedManifests(tmpDir); err != nil {
return "", err
}
manifestsBase = tmpDir
}
opts := install.Options{ opts := install.Options{
BaseURL: localManifests, BaseURL: localManifests,
Version: bootstrapArgs.version, Version: bootstrapArgs.version,
@@ -138,13 +155,14 @@ func generateInstallManifests(targetPath, namespace, tmpDir string, localManifes
Timeout: rootArgs.timeout, Timeout: rootArgs.timeout,
TargetPath: targetPath, TargetPath: targetPath,
ClusterDomain: bootstrapArgs.clusterDomain, ClusterDomain: bootstrapArgs.clusterDomain,
TolerationKeys: bootstrapArgs.tolerationKeys,
} }
if localManifests == "" { if localManifests == "" {
opts.BaseURL = rootArgs.defaults.BaseURL opts.BaseURL = rootArgs.defaults.BaseURL
} }
output, err := install.Generate(opts) output, err := install.Generate(opts, manifestsBase)
if err != nil { if err != nil {
return "", fmt.Errorf("generating install manifests failed: %w", err) return "", fmt.Errorf("generating install manifests failed: %w", err)
} }
@@ -162,7 +180,7 @@ func applyInstallManifests(ctx context.Context, manifestPath string, components
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
statusChecker, err := NewStatusChecker(time.Second, time.Minute) statusChecker, err := NewStatusChecker(time.Second, rootArgs.timeout)
if err != nil { if err != nil {
return fmt.Errorf("install failed: %w", err) return fmt.Errorf("install failed: %w", err)
} }
@@ -252,7 +270,7 @@ func shouldCreateDeployKey(ctx context.Context, kubeClient client.Client, namesp
} }
func generateDeployKey(ctx context.Context, kubeClient client.Client, url *url.URL, namespace string) (string, error) { func generateDeployKey(ctx context.Context, kubeClient client.Client, url *url.URL, namespace string) (string, error) {
pair, err := generateKeyPair(ctx, sourceArgs.GitKeyAlgorithm, sourceArgs.GitRSABits, sourceArgs.GitECDSACurve) pair, err := generateKeyPair(ctx, sourceGitArgs.keyAlgorithm, sourceGitArgs.keyRSABits, sourceGitArgs.keyECDSACurve)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@@ -94,8 +94,8 @@ func init() {
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.owner, "owner", "", "GitHub user or organization name") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.owner, "owner", "", "GitHub user or organization name")
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.repository, "repository", "", "GitHub repository name") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.repository, "repository", "", "GitHub repository name")
bootstrapGitHubCmd.Flags().StringArrayVar(&githubArgs.teams, "team", []string{}, "GitHub team to be given maintainer access") bootstrapGitHubCmd.Flags().StringArrayVar(&githubArgs.teams, "team", []string{}, "GitHub team to be given maintainer access")
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.personal, "personal", false, "is personal repository") bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.personal, "personal", false, "if true, the owner is assumed to be a GitHub user; otherwise an org")
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.private, "private", true, "is private repository") bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.private, "private", true, "if true, the repository is assumed to be private")
bootstrapGitHubCmd.Flags().DurationVar(&githubArgs.interval, "interval", time.Minute, "sync interval") bootstrapGitHubCmd.Flags().DurationVar(&githubArgs.interval, "interval", time.Minute, "sync interval")
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.hostname, "hostname", git.GitHubDefaultHostname, "GitHub hostname") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.hostname, "hostname", git.GitHubDefaultHostname, "GitHub hostname")
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.sshHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.sshHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one")
@@ -125,13 +125,25 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(ctx, kubeClient, rootArgs.namespace, filepath.ToSlash(githubArgs.path.String())) usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(
ctx,
kubeClient,
rootArgs.namespace,
filepath.ToSlash(githubArgs.path.String()),
)
if bootstrapPathDiffers { if bootstrapPathDiffers {
return fmt.Errorf("cluster already bootstrapped to %v path", usedPath) return fmt.Errorf("cluster already bootstrapped to %v path", usedPath)
} }
repository, err := git.NewRepository(githubArgs.repository, githubArgs.owner, githubArgs.hostname, ghToken, "flux", githubArgs.owner+"@users.noreply.github.com") repository, err := git.NewRepository(
githubArgs.repository,
githubArgs.owner,
githubArgs.hostname,
ghToken,
"flux",
githubArgs.owner+"@users.noreply.github.com",
)
if err != nil { if err != nil {
return err return err
} }
@@ -190,13 +202,22 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
// generate install manifests // generate install manifests
logger.Generatef("generating manifests") logger.Generatef("generating manifests")
installManifest, err := generateInstallManifests(githubArgs.path.String(), rootArgs.namespace, tmpDir, bootstrapArgs.manifestsPath) installManifest, err := generateInstallManifests(
githubArgs.path.String(),
rootArgs.namespace,
tmpDir,
bootstrapArgs.manifestsPath,
)
if err != nil { if err != nil {
return err return err
} }
// stage install manifests // stage install manifests
changed, err = repository.Commit(ctx, path.Join(githubArgs.path.String(), rootArgs.namespace), "Add manifests") changed, err = repository.Commit(
ctx,
path.Join(githubArgs.path.String(), rootArgs.namespace),
fmt.Sprintf("Add flux %s components manifests", bootstrapArgs.version),
)
if err != nil { if err != nil {
return err return err
} }
@@ -270,13 +291,25 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
// configure repo synchronization // configure repo synchronization
logger.Actionf("generating sync manifests") logger.Actionf("generating sync manifests")
syncManifests, err := generateSyncManifests(repoURL, bootstrapArgs.branch, rootArgs.namespace, rootArgs.namespace, filepath.ToSlash(githubArgs.path.String()), tmpDir, githubArgs.interval) syncManifests, err := generateSyncManifests(
repoURL,
bootstrapArgs.branch,
rootArgs.namespace,
rootArgs.namespace,
filepath.ToSlash(githubArgs.path.String()),
tmpDir,
githubArgs.interval,
)
if err != nil { if err != nil {
return err return err
} }
// commit and push manifests // commit and push manifests
if changed, err = repository.Commit(ctx, path.Join(githubArgs.path.String(), rootArgs.namespace), "Add manifests"); err != nil { if changed, err = repository.Commit(
ctx,
path.Join(githubArgs.path.String(), rootArgs.namespace),
fmt.Sprintf("Add flux %s sync manifests", bootstrapArgs.version),
); err != nil {
return err return err
} else if changed { } else if changed {
if err := repository.Push(ctx); err != nil { if err := repository.Push(ctx); err != nil {

View File

@@ -89,8 +89,8 @@ var gitlabArgs gitlabFlags
func init() { func init() {
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.owner, "owner", "", "GitLab user or group name") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.owner, "owner", "", "GitLab user or group name")
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.repository, "repository", "", "GitLab repository name") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.repository, "repository", "", "GitLab repository name")
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.personal, "personal", false, "is personal repository") bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.personal, "personal", false, "if true, the owner is assumed to be a GitLab user; otherwise a group")
bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.private, "private", true, "is private repository") bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.private, "private", true, "if true, the repository is assumed to be private")
bootstrapGitLabCmd.Flags().DurationVar(&gitlabArgs.interval, "interval", time.Minute, "sync interval") bootstrapGitLabCmd.Flags().DurationVar(&gitlabArgs.interval, "interval", time.Minute, "sync interval")
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.hostname, "hostname", git.GitLabDefaultHostname, "GitLab hostname") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.hostname, "hostname", git.GitLabDefaultHostname, "GitLab hostname")
bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.sshHostname, "ssh-hostname", "", "GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.sshHostname, "ssh-hostname", "", "GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one")
@@ -131,7 +131,14 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("cluster already bootstrapped to %v path", usedPath) return fmt.Errorf("cluster already bootstrapped to %v path", usedPath)
} }
repository, err := git.NewRepository(gitlabArgs.repository, gitlabArgs.owner, gitlabArgs.hostname, glToken, "flux", gitlabArgs.owner+"@users.noreply.gitlab.com") repository, err := git.NewRepository(
gitlabArgs.repository,
gitlabArgs.owner,
gitlabArgs.hostname,
glToken,
"flux",
gitlabArgs.owner+"@users.noreply.gitlab.com",
)
if err != nil { if err != nil {
return err return err
} }
@@ -169,13 +176,22 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
// generate install manifests // generate install manifests
logger.Generatef("generating manifests") logger.Generatef("generating manifests")
installManifest, err := generateInstallManifests(gitlabArgs.path.String(), rootArgs.namespace, tmpDir, bootstrapArgs.manifestsPath) installManifest, err := generateInstallManifests(
gitlabArgs.path.String(),
rootArgs.namespace,
tmpDir,
bootstrapArgs.manifestsPath,
)
if err != nil { if err != nil {
return err return err
} }
// stage install manifests // stage install manifests
changed, err = repository.Commit(ctx, path.Join(gitlabArgs.path.String(), rootArgs.namespace), "Add manifests") changed, err = repository.Commit(
ctx,
path.Join(gitlabArgs.path.String(), rootArgs.namespace),
fmt.Sprintf("Add flux %s components manifests", bootstrapArgs.version),
)
if err != nil { if err != nil {
return err return err
} }
@@ -249,13 +265,25 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
// configure repo synchronization // configure repo synchronization
logger.Actionf("generating sync manifests") logger.Actionf("generating sync manifests")
syncManifests, err := generateSyncManifests(repoURL, bootstrapArgs.branch, rootArgs.namespace, rootArgs.namespace, filepath.ToSlash(gitlabArgs.path.String()), tmpDir, gitlabArgs.interval) syncManifests, err := generateSyncManifests(
repoURL,
bootstrapArgs.branch,
rootArgs.namespace,
rootArgs.namespace,
filepath.ToSlash(gitlabArgs.path.String()),
tmpDir,
gitlabArgs.interval,
)
if err != nil { if err != nil {
return err return err
} }
// commit and push manifests // commit and push manifests
if changed, err = repository.Commit(ctx, path.Join(gitlabArgs.path.String(), rootArgs.namespace), "Add manifests"); err != nil { if changed, err = repository.Commit(
ctx,
path.Join(gitlabArgs.path.String(), rootArgs.namespace),
fmt.Sprintf("Add flux %s sync manifests", bootstrapArgs.version),
); err != nil {
return err return err
} else if changed { } else if changed {
if err := repository.Push(ctx); err != nil { if err := repository.Push(ctx); err != nil {

View File

@@ -21,14 +21,19 @@ import (
"encoding/json" "encoding/json"
"os" "os"
"os/exec" "os/exec"
"strings"
"time" "time"
"github.com/blang/semver/v4" "github.com/Masterminds/semver/v3"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra" "github.com/spf13/cobra"
v1 "k8s.io/api/apps/v1"
apimachineryversion "k8s.io/apimachinery/pkg/version" apimachineryversion "k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/pkg/version"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/flux2/pkg/manifestgen/install"
) )
var checkCmd = &cobra.Command{ var checkCmd = &cobra.Command{
@@ -74,11 +79,13 @@ func runCheckCmd(cmd *cobra.Command, args []string) error {
logger.Actionf("checking prerequisites") logger.Actionf("checking prerequisites")
checkFailed := false checkFailed := false
if !kubectlCheck(ctx, ">=1.18.0") { fluxCheck()
if !kubectlCheck(ctx, ">=1.18.0-0") {
checkFailed = true checkFailed = true
} }
if !kubernetesCheck(">=1.16.0") { if !kubernetesCheck(">=1.16.0-0") {
checkFailed = true checkFailed = true
} }
@@ -101,7 +108,29 @@ func runCheckCmd(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func kubectlCheck(ctx context.Context, version string) bool { func fluxCheck() {
curSv, err := version.ParseVersion(VERSION)
if err != nil {
return
}
// Exclude development builds.
if curSv.Prerelease() != "" {
return
}
latest, err := install.GetLatestVersion()
if err != nil {
return
}
latestSv, err := version.ParseVersion(latest)
if err != nil {
return
}
if latestSv.GreaterThan(curSv) {
logger.Failuref("flux %s <%s (new version is available, please upgrade)", curSv, latestSv)
}
}
func kubectlCheck(ctx context.Context, constraint string) bool {
_, err := exec.LookPath("kubectl") _, err := exec.LookPath("kubectl")
if err != nil { if err != nil {
logger.Failuref("kubectl not found") logger.Failuref("kubectl not found")
@@ -117,58 +146,58 @@ func kubectlCheck(ctx context.Context, version string) bool {
kv := &kubectlVersion{} kv := &kubectlVersion{}
if err = json.Unmarshal([]byte(output), kv); err != nil { if err = json.Unmarshal([]byte(output), kv); err != nil {
logger.Failuref("kubectl version output can't be unmarshaled") logger.Failuref("kubectl version output can't be unmarshalled")
return false return false
} }
v, err := semver.ParseTolerant(kv.ClientVersion.GitVersion) v, err := version.ParseVersion(kv.ClientVersion.GitVersion)
if err != nil { if err != nil {
logger.Failuref("kubectl version can't be parsed") logger.Failuref("kubectl version can't be parsed")
return false return false
} }
rng, _ := semver.ParseRange(version) c, _ := semver.NewConstraint(constraint)
if !rng(v) { if !c.Check(v) {
logger.Failuref("kubectl version must be %s", version) logger.Failuref("kubectl version %s < %s", v.Original(), constraint)
return false return false
} }
logger.Successf("kubectl %s %s", v.String(), version) logger.Successf("kubectl %s %s", v.String(), constraint)
return true return true
} }
func kubernetesCheck(version string) bool { func kubernetesCheck(constraint string) bool {
cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext) cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
logger.Failuref("Kubernetes client initialization failed: %s", err.Error()) logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
return false return false
} }
client, err := kubernetes.NewForConfig(cfg) clientSet, err := kubernetes.NewForConfig(cfg)
if err != nil { if err != nil {
logger.Failuref("Kubernetes client initialization failed: %s", err.Error()) logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
return false return false
} }
ver, err := client.Discovery().ServerVersion() kv, err := clientSet.Discovery().ServerVersion()
if err != nil { if err != nil {
logger.Failuref("Kubernetes API call failed: %s", err.Error()) logger.Failuref("Kubernetes API call failed: %s", err.Error())
return false return false
} }
v, err := semver.ParseTolerant(ver.String()) v, err := version.ParseVersion(kv.String())
if err != nil { if err != nil {
logger.Failuref("Kubernetes version can't be determined") logger.Failuref("Kubernetes version can't be determined")
return false return false
} }
rng, _ := semver.ParseRange(version) c, _ := semver.NewConstraint(constraint)
if !rng(v) { if !c.Check(v) {
logger.Failuref("Kubernetes version must be %s", version) logger.Failuref("Kubernetes version %s < %s", v.Original(), constraint)
return false return false
} }
logger.Successf("Kubernetes %s %s", v.String(), version) logger.Successf("Kubernetes %s %s", v.String(), constraint)
return true return true
} }
@@ -176,23 +205,29 @@ func componentsCheck() bool {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
statusChecker, err := NewStatusChecker(time.Second, 30*time.Second) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return false
}
statusChecker, err := NewStatusChecker(time.Second, rootArgs.timeout)
if err != nil { if err != nil {
return false return false
} }
ok := true ok := true
deployments := append(checkArgs.components, checkArgs.extraComponents...) selector := client.MatchingLabels{"app.kubernetes.io/instance": rootArgs.namespace}
for _, deployment := range deployments { var list v1.DeploymentList
if err := statusChecker.Assess(deployment); err != nil { if err := kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace), selector); err == nil {
ok = false for _, d := range list.Items {
} else { if err := statusChecker.Assess(d.Name); err != nil {
logger.Successf("%s: healthy", deployment) ok = false
} } else {
logger.Successf("%s: healthy", d.Name)
kubectlArgs := []string{"-n", rootArgs.namespace, "get", "deployment", deployment, "-o", "jsonpath=\"{..image}\""} }
if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err == nil { for _, c := range d.Spec.Template.Spec.Containers {
logger.Actionf(strings.TrimPrefix(strings.TrimSuffix(output, "\""), "\"")) logger.Actionf(c.Image)
}
} }
} }
return ok return ok

View File

@@ -25,6 +25,7 @@ import (
"github.com/fluxcd/flux2/internal/flags" "github.com/fluxcd/flux2/internal/flags"
"github.com/fluxcd/flux2/internal/utils" "github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/transform"
"github.com/spf13/cobra" "github.com/spf13/cobra"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -198,7 +199,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
if valuesMap == nil { if valuesMap == nil {
valuesMap = jsonMap valuesMap = jsonMap
} else { } else {
valuesMap = utils.MergeMaps(valuesMap, jsonMap) valuesMap = transform.MergeMaps(valuesMap, jsonMap)
} }
} }

View File

@@ -18,6 +18,10 @@ package main
import ( import (
"fmt" "fmt"
"regexp/syntax"
"strings"
"unicode"
"unicode/utf8"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -39,9 +43,13 @@ the status of the object.`,
RunE: createImagePolicyRun} RunE: createImagePolicyRun}
type imagePolicyFlags struct { type imagePolicyFlags struct {
imageRef string imageRef string
semver string semver string
filterRegex string alpha string
numeric string
filterRegex string
filterExtract string
filterNumerical string
} }
var imagePolicyArgs = imagePolicyFlags{} var imagePolicyArgs = imagePolicyFlags{}
@@ -49,8 +57,11 @@ var imagePolicyArgs = imagePolicyFlags{}
func init() { func init() {
flags := createImagePolicyCmd.Flags() flags := createImagePolicyCmd.Flags()
flags.StringVar(&imagePolicyArgs.imageRef, "image-ref", "", "the name of an image repository object") flags.StringVar(&imagePolicyArgs.imageRef, "image-ref", "", "the name of an image repository object")
flags.StringVar(&imagePolicyArgs.semver, "semver", "", "a semver range to apply to tags; e.g., '1.x'") flags.StringVar(&imagePolicyArgs.semver, "select-semver", "", "a semver range to apply to tags; e.g., '1.x'")
flags.StringVar(&imagePolicyArgs.filterRegex, "filter-regex", "", " regular expression pattern used to filter the image tags") flags.StringVar(&imagePolicyArgs.alpha, "select-alpha", "", "use alphabetical sorting to select image; either \"asc\" meaning select the last, or \"desc\" meaning select the first")
flags.StringVar(&imagePolicyArgs.numeric, "select-numeric", "", "use numeric sorting to select image; either \"asc\" meaning select the last, or \"desc\" meaning select the first")
flags.StringVar(&imagePolicyArgs.filterRegex, "filter-regex", "", "regular expression pattern used to filter the image tags")
flags.StringVar(&imagePolicyArgs.filterExtract, "filter-extract", "", "replacement pattern (using capture groups from --filter-regex) to use for sorting")
createImageCmd.AddCommand(createImagePolicyCmd) createImageCmd.AddCommand(createImagePolicyCmd)
} }
@@ -90,18 +101,49 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
} }
switch { switch {
case imagePolicyArgs.semver != "" && imagePolicyArgs.alpha != "":
case imagePolicyArgs.semver != "" && imagePolicyArgs.numeric != "":
case imagePolicyArgs.alpha != "" && imagePolicyArgs.numeric != "":
return fmt.Errorf("only one of --select-semver, --select-alpha or --select-numeric can be specified")
case imagePolicyArgs.semver != "": case imagePolicyArgs.semver != "":
policy.Spec.Policy.SemVer = &imagev1.SemVerPolicy{ policy.Spec.Policy.SemVer = &imagev1.SemVerPolicy{
Range: imagePolicyArgs.semver, Range: imagePolicyArgs.semver,
} }
case imagePolicyArgs.alpha != "":
if imagePolicyArgs.alpha != "desc" && imagePolicyArgs.alpha != "asc" {
return fmt.Errorf("--select-alpha must be one of [\"asc\", \"desc\"]")
}
policy.Spec.Policy.Alphabetical = &imagev1.AlphabeticalPolicy{
Order: imagePolicyArgs.alpha,
}
case imagePolicyArgs.numeric != "":
if imagePolicyArgs.numeric != "desc" && imagePolicyArgs.numeric != "asc" {
return fmt.Errorf("--select-numeric must be one of [\"asc\", \"desc\"]")
}
policy.Spec.Policy.Numerical = &imagev1.NumericalPolicy{
Order: imagePolicyArgs.numeric,
}
default: default:
return fmt.Errorf("a policy must be provided with --semver") return fmt.Errorf("a policy must be provided with either --select-semver or --select-alpha")
} }
if imagePolicyArgs.filterRegex != "" { if imagePolicyArgs.filterRegex != "" {
exp, err := syntax.Parse(imagePolicyArgs.filterRegex, syntax.Perl)
if err != nil {
return fmt.Errorf("--filter-regex is an invalid regex pattern")
}
policy.Spec.FilterTags = &imagev1.TagFilter{ policy.Spec.FilterTags = &imagev1.TagFilter{
Pattern: imagePolicyArgs.filterRegex, Pattern: imagePolicyArgs.filterRegex,
} }
if imagePolicyArgs.filterExtract != "" {
if err := validateExtractStr(imagePolicyArgs.filterExtract, exp.CapNames()); err != nil {
return err
}
policy.Spec.FilterTags.Extract = imagePolicyArgs.filterExtract
}
} else if imagePolicyArgs.filterExtract != "" {
return fmt.Errorf("cannot specify --filter-extract without specifying --filter-regex")
} }
if createArgs.export { if createArgs.export {
@@ -117,3 +159,94 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
}) })
return err return err
} }
// Performs a dry-run of the extract function in Regexp to validate the template
func validateExtractStr(template string, capNames []string) error {
for len(template) > 0 {
i := strings.Index(template, "$")
if i < 0 {
return nil
}
template = template[i:]
if len(template) > 1 && template[1] == '$' {
template = template[2:]
continue
}
name, num, rest, ok := extract(template)
if !ok {
// Malformed extract string, assume user didn't want this
template = template[1:]
return fmt.Errorf("--filter-extract is malformed")
}
template = rest
if num >= 0 {
// we won't worry about numbers as we can't validate these
continue
} else {
found := false
for _, capName := range capNames {
if name == capName {
found = true
}
}
if !found {
return fmt.Errorf("capture group $%s used in --filter-extract not found in --filter-regex", name)
}
}
}
return nil
}
// extract method from the regexp package
// returns the name or number of the value prepended by $
func extract(str string) (name string, num int, rest string, ok bool) {
if len(str) < 2 || str[0] != '$' {
return
}
brace := false
if str[1] == '{' {
brace = true
str = str[2:]
} else {
str = str[1:]
}
i := 0
for i < len(str) {
rune, size := utf8.DecodeRuneInString(str[i:])
if !unicode.IsLetter(rune) && !unicode.IsDigit(rune) && rune != '_' {
break
}
i += size
}
if i == 0 {
// empty name is not okay
return
}
name = str[:i]
if brace {
if i >= len(str) || str[i] != '}' {
// missing closing brace
return
}
i++
}
// Parse number.
num = 0
for i := 0; i < len(name); i++ {
if name[i] < '0' || '9' < name[i] || num >= 1e8 {
num = -1
break
}
num = num*10 + int(name[i]) - '0'
}
// Disallow leading zeros.
if name[0] == '0' && len(name) > 1 {
num = -1
}
rest = str[i:]
ok = true
return
}

View File

@@ -20,6 +20,7 @@ import (
"context" "context"
"crypto/elliptic" "crypto/elliptic"
"fmt" "fmt"
"io/ioutil"
"net/url" "net/url"
"time" "time"
@@ -76,6 +77,7 @@ type secretGitFlags struct {
keyAlgorithm flags.PublicKeyAlgorithm keyAlgorithm flags.PublicKeyAlgorithm
rsaBits flags.RSAKeyBits rsaBits flags.RSAKeyBits
ecdsaCurve flags.ECDSACurve ecdsaCurve flags.ECDSACurve
caFile string
} }
var secretGitArgs = NewSecretGitFlags() var secretGitArgs = NewSecretGitFlags()
@@ -87,6 +89,7 @@ func init() {
createSecretGitCmd.Flags().Var(&secretGitArgs.keyAlgorithm, "ssh-key-algorithm", secretGitArgs.keyAlgorithm.Description()) createSecretGitCmd.Flags().Var(&secretGitArgs.keyAlgorithm, "ssh-key-algorithm", secretGitArgs.keyAlgorithm.Description())
createSecretGitCmd.Flags().Var(&secretGitArgs.rsaBits, "ssh-rsa-bits", secretGitArgs.rsaBits.Description()) createSecretGitCmd.Flags().Var(&secretGitArgs.rsaBits, "ssh-rsa-bits", secretGitArgs.rsaBits.Description())
createSecretGitCmd.Flags().Var(&secretGitArgs.ecdsaCurve, "ssh-ecdsa-curve", secretGitArgs.ecdsaCurve.Description()) createSecretGitCmd.Flags().Var(&secretGitArgs.ecdsaCurve, "ssh-ecdsa-curve", secretGitArgs.ecdsaCurve.Description())
createSecretGitCmd.Flags().StringVar(&secretGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates")
createSecretCmd.AddCommand(createSecretGitCmd) createSecretCmd.AddCommand(createSecretGitCmd)
} }
@@ -147,11 +150,19 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("for Git over HTTP/S the username and password are required") 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.StringData = map[string]string{ secret.StringData = map[string]string{
"username": secretGitArgs.username, "username": secretGitArgs.username,
"password": secretGitArgs.password, "password": secretGitArgs.password,
} }
if secretGitArgs.caFile != "" {
ca, err := ioutil.ReadFile(secretGitArgs.caFile)
if err != nil {
return fmt.Errorf("failed to read CA file '%s': %w", secretGitArgs.caFile, err)
}
secret.StringData["caFile"] = string(ca)
}
default: default:
return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme) return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme)
} }

View File

@@ -41,19 +41,19 @@ import (
"github.com/fluxcd/flux2/internal/utils" "github.com/fluxcd/flux2/internal/utils"
) )
type SourceGitFlags struct { type sourceGitFlags struct {
GitURL string url string
GitBranch string branch string
GitTag string tag string
GitSemver string semver string
GitUsername string username string
GitPassword string password string
caFile string
GitKeyAlgorithm flags.PublicKeyAlgorithm keyAlgorithm flags.PublicKeyAlgorithm
GitRSABits flags.RSAKeyBits keyRSABits flags.RSAKeyBits
GitECDSACurve flags.ECDSACurve keyECDSACurve flags.ECDSACurve
GitSecretRef string secretRef string
GitImplementation flags.GitImplementation gitImplementation flags.GitImplementation
} }
var createSourceGitCmd = &cobra.Command{ var createSourceGitCmd = &cobra.Command{
@@ -100,29 +100,30 @@ For private Git repositories, the basic authentication credentials are stored in
RunE: createSourceGitCmdRun, RunE: createSourceGitCmdRun,
} }
var sourceArgs = NewSourceGitFlags() var sourceGitArgs = newSourceGitFlags()
func init() { func init() {
createSourceGitCmd.Flags().StringVar(&sourceArgs.GitURL, "url", "", "git address, e.g. ssh://git@host/org/repository") createSourceGitCmd.Flags().StringVar(&sourceGitArgs.url, "url", "", "git address, e.g. ssh://git@host/org/repository")
createSourceGitCmd.Flags().StringVar(&sourceArgs.GitBranch, "branch", "master", "git branch") createSourceGitCmd.Flags().StringVar(&sourceGitArgs.branch, "branch", "master", "git branch")
createSourceGitCmd.Flags().StringVar(&sourceArgs.GitTag, "tag", "", "git tag") createSourceGitCmd.Flags().StringVar(&sourceGitArgs.tag, "tag", "", "git tag")
createSourceGitCmd.Flags().StringVar(&sourceArgs.GitSemver, "tag-semver", "", "git tag semver range") createSourceGitCmd.Flags().StringVar(&sourceGitArgs.semver, "tag-semver", "", "git tag semver range")
createSourceGitCmd.Flags().StringVarP(&sourceArgs.GitUsername, "username", "u", "", "basic authentication username") createSourceGitCmd.Flags().StringVarP(&sourceGitArgs.username, "username", "u", "", "basic authentication username")
createSourceGitCmd.Flags().StringVarP(&sourceArgs.GitPassword, "password", "p", "", "basic authentication password") createSourceGitCmd.Flags().StringVarP(&sourceGitArgs.password, "password", "p", "", "basic authentication password")
createSourceGitCmd.Flags().Var(&sourceArgs.GitKeyAlgorithm, "ssh-key-algorithm", sourceArgs.GitKeyAlgorithm.Description()) createSourceGitCmd.Flags().Var(&sourceGitArgs.keyAlgorithm, "ssh-key-algorithm", sourceGitArgs.keyAlgorithm.Description())
createSourceGitCmd.Flags().Var(&sourceArgs.GitRSABits, "ssh-rsa-bits", sourceArgs.GitRSABits.Description()) createSourceGitCmd.Flags().Var(&sourceGitArgs.keyRSABits, "ssh-rsa-bits", sourceGitArgs.keyRSABits.Description())
createSourceGitCmd.Flags().Var(&sourceArgs.GitECDSACurve, "ssh-ecdsa-curve", sourceArgs.GitECDSACurve.Description()) createSourceGitCmd.Flags().Var(&sourceGitArgs.keyECDSACurve, "ssh-ecdsa-curve", sourceGitArgs.keyECDSACurve.Description())
createSourceGitCmd.Flags().StringVarP(&sourceArgs.GitSecretRef, "secret-ref", "", "", "the name of an existing secret containing SSH or basic credentials") createSourceGitCmd.Flags().StringVar(&sourceGitArgs.secretRef, "secret-ref", "", "the name of an existing secret containing SSH or basic credentials")
createSourceGitCmd.Flags().Var(&sourceArgs.GitImplementation, "git-implementation", sourceArgs.GitImplementation.Description()) createSourceGitCmd.Flags().Var(&sourceGitArgs.gitImplementation, "git-implementation", sourceGitArgs.gitImplementation.Description())
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates, requires libgit2")
createSourceCmd.AddCommand(createSourceGitCmd) createSourceCmd.AddCommand(createSourceGitCmd)
} }
func NewSourceGitFlags() SourceGitFlags { func newSourceGitFlags() sourceGitFlags {
return SourceGitFlags{ return sourceGitFlags{
GitKeyAlgorithm: "rsa", keyAlgorithm: "rsa",
GitRSABits: 2048, keyRSABits: 2048,
GitECDSACurve: flags.ECDSACurve{Curve: elliptic.P384()}, keyECDSACurve: flags.ECDSACurve{Curve: elliptic.P384()},
} }
} }
@@ -132,17 +133,21 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
if sourceArgs.GitURL == "" { if sourceGitArgs.url == "" {
return fmt.Errorf("url is required") return fmt.Errorf("url is required")
} }
if sourceGitArgs.gitImplementation.String() != sourcev1.LibGit2Implementation && sourceGitArgs.caFile != "" {
return fmt.Errorf("specifing a CA file requires --git-implementation=%s", sourcev1.LibGit2Implementation)
}
tmpDir, err := ioutil.TempDir("", name) tmpDir, err := ioutil.TempDir("", name)
if err != nil { if err != nil {
return err return err
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
u, err := url.Parse(sourceArgs.GitURL) u, err := url.Parse(sourceGitArgs.url)
if err != nil { if err != nil {
return fmt.Errorf("git URL parse failed: %w", err) return fmt.Errorf("git URL parse failed: %w", err)
} }
@@ -159,7 +164,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1.GitRepositorySpec{ Spec: sourcev1.GitRepositorySpec{
URL: sourceArgs.GitURL, URL: sourceGitArgs.url,
Interval: metav1.Duration{ Interval: metav1.Duration{
Duration: createArgs.interval, Duration: createArgs.interval,
}, },
@@ -167,22 +172,22 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
}, },
} }
if sourceArgs.GitImplementation != "" { if sourceGitArgs.gitImplementation != "" {
gitRepository.Spec.GitImplementation = sourceArgs.GitImplementation.String() gitRepository.Spec.GitImplementation = sourceGitArgs.gitImplementation.String()
} }
if sourceArgs.GitSemver != "" { if sourceGitArgs.semver != "" {
gitRepository.Spec.Reference.SemVer = sourceArgs.GitSemver gitRepository.Spec.Reference.SemVer = sourceGitArgs.semver
} else if sourceArgs.GitTag != "" { } else if sourceGitArgs.tag != "" {
gitRepository.Spec.Reference.Tag = sourceArgs.GitTag gitRepository.Spec.Reference.Tag = sourceGitArgs.tag
} else { } else {
gitRepository.Spec.Reference.Branch = sourceArgs.GitBranch gitRepository.Spec.Reference.Branch = sourceGitArgs.branch
} }
if createArgs.export { if createArgs.export {
if sourceArgs.GitSecretRef != "" { if sourceGitArgs.secretRef != "" {
gitRepository.Spec.SecretRef = &meta.LocalObjectReference{ gitRepository.Spec.SecretRef = &meta.LocalObjectReference{
Name: sourceArgs.GitSecretRef, Name: sourceGitArgs.secretRef,
} }
} }
return exportGit(gitRepository) return exportGit(gitRepository)
@@ -198,11 +203,11 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
withAuth := false withAuth := false
// TODO(hidde): move all auth prep to separate func? // TODO(hidde): move all auth prep to separate func?
if sourceArgs.GitSecretRef != "" { if sourceGitArgs.secretRef != "" {
withAuth = true withAuth = true
} else if u.Scheme == "ssh" { } else if u.Scheme == "ssh" {
logger.Generatef("generating deploy key pair") logger.Generatef("generating deploy key pair")
pair, err := generateKeyPair(ctx, sourceArgs.GitKeyAlgorithm, sourceArgs.GitRSABits, sourceArgs.GitECDSACurve) pair, err := generateKeyPair(ctx, sourceGitArgs.keyAlgorithm, sourceGitArgs.keyRSABits, sourceGitArgs.keyECDSACurve)
if err != nil { if err != nil {
return err return err
} }
@@ -240,7 +245,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
withAuth = true withAuth = true
} else if sourceArgs.GitUsername != "" && sourceArgs.GitPassword != "" { } else if sourceGitArgs.username != "" && sourceGitArgs.password != "" {
logger.Actionf("applying secret with basic auth credentials") logger.Actionf("applying secret with basic auth credentials")
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@@ -249,10 +254,19 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
Labels: sourceLabels, Labels: sourceLabels,
}, },
StringData: map[string]string{ StringData: map[string]string{
"username": sourceArgs.GitUsername, "username": sourceGitArgs.username,
"password": sourceArgs.GitPassword, "password": sourceGitArgs.password,
}, },
} }
if sourceGitArgs.caFile != "" {
ca, err := ioutil.ReadFile(sourceGitArgs.caFile)
if err != nil {
return fmt.Errorf("failed to read CA file '%s': %w", sourceGitArgs.caFile, err)
}
secret.StringData["caFile"] = string(ca)
}
if err := upsertSecret(ctx, kubeClient, secret); err != nil { if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err return err
} }
@@ -267,8 +281,8 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if withAuth { if withAuth {
secretName := name secretName := name
if sourceArgs.GitSecretRef != "" { if sourceGitArgs.secretRef != "" {
secretName = sourceArgs.GitSecretRef secretName = sourceGitArgs.secretRef
} }
gitRepository.Spec.SecretRef = &meta.LocalObjectReference{ gitRepository.Spec.SecretRef = &meta.LocalObjectReference{
Name: secretName, Name: secretName,

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

@@ -0,0 +1,31 @@
package main
import (
"embed"
"fmt"
"io/fs"
"os"
"path"
)
//go:embed manifests/*.yaml
var embeddedManifests embed.FS
func writeEmbeddedManifests(dir string) error {
manifests, err := fs.ReadDir(embeddedManifests, "manifests")
if err != nil {
return err
}
for _, manifest := range manifests {
data, err := fs.ReadFile(embeddedManifests, path.Join("manifests", manifest.Name()))
if err != nil {
return fmt.Errorf("reading file failed: %w", err)
}
err = os.WriteFile(path.Join(dir, manifest.Name()), data, 0666)
if err != nil {
return fmt.Errorf("writing file failed: %w", err)
}
}
return nil
}

View File

@@ -34,15 +34,18 @@ import (
var installCmd = &cobra.Command{ var installCmd = &cobra.Command{
Use: "install", Use: "install",
Short: "Install the toolkit components", Short: "Install or upgrade Flux",
Long: `The install command deploys the toolkit components in the specified namespace. Long: `The install command deploys Flux in the specified namespace.
If a previous version is installed, then an in-place upgrade will be performed.`, If a previous version is installed, then an in-place upgrade will be performed.`,
Example: ` # Install the latest version in the flux-system namespace Example: ` # Install the latest version in the flux-system namespace
flux install --version=latest --namespace=flux-system flux install --version=latest --namespace=flux-system
# Dry-run install for a specific version and a series of components # Install a specific version and a series of components
flux install --dry-run --version=v0.0.7 --components="source-controller,kustomize-controller" flux install --dry-run --version=v0.0.7 --components="source-controller,kustomize-controller"
# Install Flux onto tainted Kubernetes nodes
flux install --toleration-keys=node.kubernetes.io/dedicated-to-flux
# Dry-run install with manifests preview # Dry-run install with manifests preview
flux install --dry-run --verbose flux install --dry-run --verbose
@@ -52,91 +55,119 @@ If a previous version is installed, then an in-place upgrade will be performed.`
RunE: installCmdRun, RunE: installCmdRun,
} }
var ( type installFlags struct {
installExport bool export bool
installDryRun bool dryRun bool
installManifestsPath string version string
installVersion string defaultComponents []string
installDefaultComponents []string extraComponents []string
installExtraComponents []string registry string
installRegistry string imagePullSecret string
installImagePullSecret string branch string
installWatchAllNamespaces bool watchAllNamespaces bool
installNetworkPolicy bool networkPolicy bool
installArch flags.Arch manifestsPath string
installLogLevel = flags.LogLevel(rootArgs.defaults.LogLevel) arch flags.Arch
installClusterDomain string logLevel flags.LogLevel
) tokenAuth bool
clusterDomain string
tolerationKeys []string
}
var installArgs = NewInstallFlags()
func init() { func init() {
installCmd.Flags().BoolVar(&installExport, "export", false, installCmd.Flags().BoolVar(&installArgs.export, "export", false,
"write the install manifests to stdout and exit") "write the install manifests to stdout and exit")
installCmd.Flags().BoolVarP(&installDryRun, "dry-run", "", false, installCmd.Flags().BoolVarP(&installArgs.dryRun, "dry-run", "", false,
"only print the object that would be applied") "only print the object that would be applied")
installCmd.Flags().StringVarP(&installVersion, "version", "v", rootArgs.defaults.Version, installCmd.Flags().StringVarP(&installArgs.version, "version", "v", "",
"toolkit version") "toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases")
installCmd.Flags().StringSliceVar(&installDefaultComponents, "components", rootArgs.defaults.Components, installCmd.Flags().StringSliceVar(&installArgs.defaultComponents, "components", rootArgs.defaults.Components,
"list of components, accepts comma-separated values") "list of components, accepts comma-separated values")
installCmd.Flags().StringSliceVar(&installExtraComponents, "components-extra", nil, installCmd.Flags().StringSliceVar(&installArgs.extraComponents, "components-extra", nil,
"list of components in addition to those supplied or defaulted, accepts comma-separated values") "list of components in addition to those supplied or defaulted, accepts comma-separated values")
installCmd.Flags().StringVar(&installManifestsPath, "manifests", "", "path to the manifest directory") installCmd.Flags().StringVar(&installArgs.manifestsPath, "manifests", "", "path to the manifest directory")
installCmd.Flags().StringVar(&installRegistry, "registry", rootArgs.defaults.Registry, installCmd.Flags().StringVar(&installArgs.registry, "registry", rootArgs.defaults.Registry,
"container registry where the toolkit images are published") "container registry where the toolkit images are published")
installCmd.Flags().StringVar(&installImagePullSecret, "image-pull-secret", "", installCmd.Flags().StringVar(&installArgs.imagePullSecret, "image-pull-secret", "",
"Kubernetes secret name used for pulling the toolkit images from a private registry") "Kubernetes secret name used for pulling the toolkit images from a private registry")
installCmd.Flags().Var(&installArch, "arch", installArch.Description()) installCmd.Flags().Var(&installArgs.arch, "arch", installArgs.arch.Description())
installCmd.Flags().BoolVar(&installWatchAllNamespaces, "watch-all-namespaces", rootArgs.defaults.WatchAllNamespaces, installCmd.Flags().BoolVar(&installArgs.watchAllNamespaces, "watch-all-namespaces", rootArgs.defaults.WatchAllNamespaces,
"watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed") "watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed")
installCmd.Flags().Var(&installLogLevel, "log-level", installLogLevel.Description()) installCmd.Flags().Var(&installArgs.logLevel, "log-level", installArgs.logLevel.Description())
installCmd.Flags().BoolVar(&installNetworkPolicy, "network-policy", rootArgs.defaults.NetworkPolicy, installCmd.Flags().BoolVar(&installArgs.networkPolicy, "network-policy", rootArgs.defaults.NetworkPolicy,
"deny ingress access to the toolkit controllers from other namespaces using network policies") "deny ingress access to the toolkit controllers from other namespaces using network policies")
installCmd.Flags().StringVar(&installClusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain") installCmd.Flags().StringVar(&installArgs.clusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain")
installCmd.Flags().StringSliceVar(&installArgs.tolerationKeys, "toleration-keys", nil,
"list of toleration keys used to schedule the components pods onto nodes with matching taints")
installCmd.Flags().MarkHidden("manifests") installCmd.Flags().MarkHidden("manifests")
installCmd.Flags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64") installCmd.Flags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64")
rootCmd.AddCommand(installCmd) rootCmd.AddCommand(installCmd)
} }
func NewInstallFlags() installFlags {
return installFlags{
logLevel: flags.LogLevel(rootArgs.defaults.LogLevel),
}
}
func installCmdRun(cmd *cobra.Command, args []string) error { func installCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
components := append(installArgs.defaultComponents, installArgs.extraComponents...)
err := utils.ValidateComponents(components)
if err != nil {
return err
}
if ver, err := getVersion(installArgs.version); err != nil {
return err
} else {
installArgs.version = ver
}
if !installArgs.export {
logger.Generatef("generating manifests")
}
tmpDir, err := ioutil.TempDir("", rootArgs.namespace) tmpDir, err := ioutil.TempDir("", rootArgs.namespace)
if err != nil { if err != nil {
return err return err
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
if !installExport { manifestsBase := ""
logger.Generatef("generating manifests") if isEmbeddedVersion(installArgs.version) {
} if err := writeEmbeddedManifests(tmpDir); err != nil {
return err
components := append(installDefaultComponents, installExtraComponents...) }
manifestsBase = tmpDir
if err := utils.ValidateComponents(components); err != nil {
return err
} }
opts := install.Options{ opts := install.Options{
BaseURL: installManifestsPath, BaseURL: installArgs.manifestsPath,
Version: installVersion, Version: installArgs.version,
Namespace: rootArgs.namespace, Namespace: rootArgs.namespace,
Components: components, Components: components,
Registry: installRegistry, Registry: installArgs.registry,
ImagePullSecret: installImagePullSecret, ImagePullSecret: installArgs.imagePullSecret,
WatchAllNamespaces: installWatchAllNamespaces, WatchAllNamespaces: installArgs.watchAllNamespaces,
NetworkPolicy: installNetworkPolicy, NetworkPolicy: installArgs.networkPolicy,
LogLevel: installLogLevel.String(), LogLevel: installArgs.logLevel.String(),
NotificationController: rootArgs.defaults.NotificationController, NotificationController: rootArgs.defaults.NotificationController,
ManifestFile: fmt.Sprintf("%s.yaml", rootArgs.namespace), ManifestFile: fmt.Sprintf("%s.yaml", rootArgs.namespace),
Timeout: rootArgs.timeout, Timeout: rootArgs.timeout,
ClusterDomain: installClusterDomain, ClusterDomain: installArgs.clusterDomain,
TolerationKeys: installArgs.tolerationKeys,
} }
if installManifestsPath == "" { if installArgs.manifestsPath == "" {
opts.BaseURL = install.MakeDefaultOptions().BaseURL opts.BaseURL = install.MakeDefaultOptions().BaseURL
} }
manifest, err := install.Generate(opts) manifest, err := install.Generate(opts, manifestsBase)
if err != nil { if err != nil {
return fmt.Errorf("install failed: %w", err) return fmt.Errorf("install failed: %w", err)
} }
@@ -147,9 +178,9 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
if rootArgs.verbose { if rootArgs.verbose {
fmt.Print(manifest.Content) fmt.Print(manifest.Content)
} else if installExport { } else if installArgs.export {
fmt.Println("---") fmt.Println("---")
fmt.Println("# GitOps Toolkit revision", installVersion) fmt.Println("# Flux version:", installArgs.version)
fmt.Println("# Components:", strings.Join(components, ",")) fmt.Println("# Components:", strings.Join(components, ","))
fmt.Print(manifest.Content) fmt.Print(manifest.Content)
fmt.Println("---") fmt.Println("---")
@@ -164,7 +195,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
} }
kubectlArgs := []string{"apply", "-f", filepath.Join(tmpDir, manifest.Path)} kubectlArgs := []string{"apply", "-f", filepath.Join(tmpDir, manifest.Path)}
if installDryRun { if installArgs.dryRun {
kubectlArgs = append(kubectlArgs, "--dry-run=client") kubectlArgs = append(kubectlArgs, "--dry-run=client")
applyOutput = utils.ModeOS applyOutput = utils.ModeOS
} }
@@ -172,7 +203,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
if installDryRun { if installArgs.dryRun {
logger.Successf("install dry-run finished") logger.Successf("install dry-run finished")
return nil return nil
} }

View File

@@ -41,7 +41,7 @@ var rootCmd = &cobra.Command{
Example: ` # Check prerequisites Example: ` # Check prerequisites
flux check --pre flux check --pre
# Install the latest version of the toolkit # Install the latest version of Flux
flux install --version=master flux install --version=master
# Create a source from a public Git repository # Create a source from a public Git repository
@@ -88,8 +88,8 @@ var rootCmd = &cobra.Command{
# Delete a GitRepository source # Delete a GitRepository source
flux delete source git webapp-latest flux delete source git webapp-latest
# Uninstall the toolkit and delete CRDs # Uninstall Flux and delete CRDs
flux uninstall --crds flux uninstall
`, `,
} }
@@ -115,10 +115,12 @@ func init() {
} }
func NewRootFlags() rootFlags { func NewRootFlags() rootFlags {
return rootFlags{ rf := rootFlags{
pollInterval: 2 * time.Second, pollInterval: 2 * time.Second,
defaults: install.MakeDefaultOptions(), defaults: install.MakeDefaultOptions(),
} }
rf.defaults.Version = "v" + VERSION
return rf
} }
func main() { func main() {

View File

@@ -36,8 +36,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/flux2/internal/utils"
) )
// statusable is used to see if a resource is considered ready in the usual way // statusable is used to see if a resource is considered ready in the usual way

View File

@@ -22,8 +22,12 @@ import (
"github.com/manifoldco/promptui" "github.com/manifoldco/promptui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
apierrors "k8s.io/apimachinery/pkg/api/errors" appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/types" corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils" "github.com/fluxcd/flux2/internal/utils"
@@ -34,33 +38,30 @@ import (
var uninstallCmd = &cobra.Command{ var uninstallCmd = &cobra.Command{
Use: "uninstall", Use: "uninstall",
Short: "Uninstall the toolkit components", Short: "Uninstall Flux and its custom resource definitions",
Long: "The uninstall command removes the namespace, cluster roles, cluster role bindings and CRDs from the cluster.", Long: "The uninstall command removes the Flux components and the toolkit.fluxcd.io resources from the cluster.",
Example: ` # Dry-run uninstall of all components Example: ` # Uninstall Flux components, its custom resources and namespace
flux uninstall --dry-run --namespace=flux-system flux uninstall --namespace=flux-system
# Uninstall all components and delete custom resource definitions # Uninstall Flux but keep the namespace
flux uninstall --resources --crds --namespace=flux-system flux uninstall --namespace=infra --keep-namespace=true
`, `,
RunE: uninstallCmdRun, RunE: uninstallCmdRun,
} }
type uninstallFlags struct { type uninstallFlags struct {
crds bool keepNamespace bool
resources bool dryRun bool
dryRun bool silent bool
silent bool
} }
var uninstallArgs uninstallFlags var uninstallArgs uninstallFlags
func init() { func init() {
uninstallCmd.Flags().BoolVar(&uninstallArgs.resources, "resources", true, uninstallCmd.Flags().BoolVar(&uninstallArgs.keepNamespace, "keep-namespace", false,
"removes custom resources such as Kustomizations, GitRepositories and HelmRepositories") "skip namespace deletion")
uninstallCmd.Flags().BoolVar(&uninstallArgs.crds, "crds", false,
"removes all CRDs previously installed")
uninstallCmd.Flags().BoolVar(&uninstallArgs.dryRun, "dry-run", false, uninstallCmd.Flags().BoolVar(&uninstallArgs.dryRun, "dry-run", false,
"only print the object that would be deleted") "only print the objects that would be deleted")
uninstallCmd.Flags().BoolVarP(&uninstallArgs.silent, "silent", "s", false, uninstallCmd.Flags().BoolVarP(&uninstallArgs.silent, "silent", "s", false,
"delete components without asking for confirmation") "delete components without asking for confirmation")
@@ -68,6 +69,16 @@ func init() {
} }
func uninstallCmdRun(cmd *cobra.Command, args []string) error { func uninstallCmdRun(cmd *cobra.Command, args []string) error {
if !uninstallArgs.dryRun && !uninstallArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete Flux and its custom resource definitions",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
@@ -76,96 +87,227 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !uninstallArgs.dryRun && !uninstallArgs.silent { logger.Actionf("deleting components in %s namespace", rootArgs.namespace)
prompt := promptui.Prompt{ uninstallComponents(ctx, kubeClient, rootArgs.namespace, uninstallArgs.dryRun)
Label: fmt.Sprintf("Are you sure you want to delete the %s namespace", rootArgs.namespace),
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
dryRun := "--dry-run=server" logger.Actionf("deleting toolkit.fluxcd.io finalizers in all namespaces")
deleteResources := uninstallArgs.resources || uninstallArgs.crds uninstallFinalizers(ctx, kubeClient, uninstallArgs.dryRun)
// known kinds with finalizers logger.Actionf("deleting toolkit.fluxcd.io custom resource definitions")
namespacedKinds := []string{ uninstallCustomResourceDefinitions(ctx, kubeClient, rootArgs.namespace, uninstallArgs.dryRun)
sourcev1.GitRepositoryKind,
sourcev1.HelmRepositoryKind,
sourcev1.BucketKind,
}
// suspend bootstrap kustomization to avoid finalizers deadlock if !uninstallArgs.keepNamespace {
kustomizationName := types.NamespacedName{ uninstallNamespace(ctx, kubeClient, rootArgs.namespace, uninstallArgs.dryRun)
Namespace: rootArgs.namespace,
Name: rootArgs.namespace,
}
var kustomization kustomizev1.Kustomization
err = kubeClient.Get(ctx, kustomizationName, &kustomization)
if err == nil {
kustomization.Spec.Suspend = true
if err := kubeClient.Update(ctx, &kustomization); err != nil {
return fmt.Errorf("unable to suspend kustomization '%s': %w", kustomizationName.String(), err)
}
}
if err == nil || apierrors.IsNotFound(err) {
namespacedKinds = append(namespacedKinds, kustomizev1.KustomizationKind)
}
// add HelmRelease kind to deletion list if exists
var list helmv2.HelmReleaseList
if err := kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace)); err == nil {
namespacedKinds = append(namespacedKinds, helmv2.HelmReleaseKind)
}
if deleteResources {
logger.Actionf("uninstalling custom resources")
for _, kind := range namespacedKinds {
if err := deleteAll(ctx, kind, uninstallArgs.dryRun); err != nil {
logger.Failuref("kubectl: %s", err.Error())
}
}
}
var kinds []string
if uninstallArgs.crds {
kinds = append(kinds, "crds")
}
kinds = append(kinds, "clusterroles,clusterrolebindings", "namespace")
logger.Actionf("uninstalling components")
for _, kind := range kinds {
kubectlArgs := []string{
"delete", kind,
"-l", fmt.Sprintf("app.kubernetes.io/instance=%s", rootArgs.namespace),
"--ignore-not-found", "--timeout", rootArgs.timeout.String(),
}
if uninstallArgs.dryRun {
kubectlArgs = append(kubectlArgs, dryRun)
}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("uninstall failed: %w", err)
}
} }
logger.Successf("uninstall finished") logger.Successf("uninstall finished")
return nil return nil
} }
func deleteAll(ctx context.Context, kind string, dryRun bool) error { func uninstallComponents(ctx context.Context, kubeClient client.Client, namespace string, dryRun bool) {
kubectlArgs := []string{ opts, dryRunStr := getDeleteOptions(dryRun)
"delete", kind, "--ignore-not-found", selector := client.MatchingLabels{"app.kubernetes.io/instance": namespace}
"--all", "--all-namespaces", {
"--timeout", rootArgs.timeout.String(), var list appsv1.DeploymentList
if err := kubeClient.List(ctx, &list, client.InNamespace(namespace), selector); err == nil {
for _, r := range list.Items {
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
logger.Failuref("Deployment/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
} else {
logger.Successf("Deployment/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
}
}
}
} }
{
if dryRun { var list corev1.ServiceList
kubectlArgs = append(kubectlArgs, "--dry-run=server") if err := kubeClient.List(ctx, &list, client.InNamespace(namespace), selector); err == nil {
for _, r := range list.Items {
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
logger.Failuref("Service/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
} else {
logger.Successf("Service/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list networkingv1.NetworkPolicyList
if err := kubeClient.List(ctx, &list, client.InNamespace(namespace), selector); err == nil {
for _, r := range list.Items {
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
logger.Failuref("NetworkPolicy/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
} else {
logger.Successf("NetworkPolicy/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list corev1.ServiceAccountList
if err := kubeClient.List(ctx, &list, client.InNamespace(namespace), selector); err == nil {
for _, r := range list.Items {
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
logger.Failuref("ServiceAccount/%s/%s deletion failed: %s", r.Namespace, r.Name, err.Error())
} else {
logger.Successf("ServiceAccount/%s/%s deleted %s", r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list rbacv1.ClusterRoleList
if err := kubeClient.List(ctx, &list, selector); err == nil {
for _, r := range list.Items {
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
logger.Failuref("ClusterRole/%s deletion failed: %s", r.Name, err.Error())
} else {
logger.Successf("ClusterRole/%s deleted %s", r.Name, dryRunStr)
}
}
}
}
{
var list rbacv1.ClusterRoleBindingList
if err := kubeClient.List(ctx, &list, selector); err == nil {
for _, r := range list.Items {
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
logger.Failuref("ClusterRoleBinding/%s deletion failed: %s", r.Name, err.Error())
} else {
logger.Successf("ClusterRoleBinding/%s deleted %s", r.Name, dryRunStr)
}
}
}
} }
}
_, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
return err func uninstallFinalizers(ctx context.Context, kubeClient client.Client, dryRun bool) {
opts, dryRunStr := getUpdateOptions(dryRun)
{
var list sourcev1.GitRepositoryList
if err := kubeClient.List(ctx, &list, client.InNamespace("")); err == nil {
for _, r := range list.Items {
r.Finalizers = []string{}
if err := kubeClient.Update(ctx, &r, opts); err != nil {
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
} else {
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list sourcev1.HelmRepositoryList
if err := kubeClient.List(ctx, &list, client.InNamespace("")); err == nil {
for _, r := range list.Items {
r.Finalizers = []string{}
if err := kubeClient.Update(ctx, &r, opts); err != nil {
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
} else {
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list sourcev1.HelmChartList
if err := kubeClient.List(ctx, &list, client.InNamespace("")); err == nil {
for _, r := range list.Items {
r.Finalizers = []string{}
if err := kubeClient.Update(ctx, &r, opts); err != nil {
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
} else {
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list sourcev1.BucketList
if err := kubeClient.List(ctx, &list, client.InNamespace("")); err == nil {
for _, r := range list.Items {
r.Finalizers = []string{}
if err := kubeClient.Update(ctx, &r, opts); err != nil {
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
} else {
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list kustomizev1.KustomizationList
if err := kubeClient.List(ctx, &list, client.InNamespace("")); err == nil {
for _, r := range list.Items {
r.Finalizers = []string{}
if err := kubeClient.Update(ctx, &r, opts); err != nil {
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
} else {
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
}
}
}
}
{
var list helmv2.HelmReleaseList
if err := kubeClient.List(ctx, &list, client.InNamespace("")); err == nil {
for _, r := range list.Items {
r.Finalizers = []string{}
if err := kubeClient.Update(ctx, &r, opts); err != nil {
logger.Failuref("%s/%s/%s removing finalizers failed: %s", r.Kind, r.Namespace, r.Name, err.Error())
} else {
logger.Successf("%s/%s/%s finalizers deleted %s", r.Kind, r.Namespace, r.Name, dryRunStr)
}
}
}
}
}
func uninstallCustomResourceDefinitions(ctx context.Context, kubeClient client.Client, namespace string, dryRun bool) {
opts, dryRunStr := getDeleteOptions(dryRun)
selector := client.MatchingLabels{"app.kubernetes.io/instance": namespace}
{
var list apiextensionsv1.CustomResourceDefinitionList
if err := kubeClient.List(ctx, &list, selector); err == nil {
for _, r := range list.Items {
if err := kubeClient.Delete(ctx, &r, opts); err != nil {
logger.Failuref("CustomResourceDefinition/%s deletion failed: %s", r.Name, err.Error())
} else {
logger.Successf("CustomResourceDefinition/%s deleted %s", r.Name, dryRunStr)
}
}
}
}
}
func uninstallNamespace(ctx context.Context, kubeClient client.Client, namespace string, dryRun bool) {
opts, dryRunStr := getDeleteOptions(dryRun)
ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
if err := kubeClient.Delete(ctx, &ns, opts); err != nil {
logger.Failuref("Namespace/%s deletion failed: %s", namespace, err.Error())
} else {
logger.Successf("Namespace/%s deleted %s", namespace, dryRunStr)
}
}
func getDeleteOptions(dryRun bool) (*client.DeleteOptions, string) {
opts := &client.DeleteOptions{}
var dryRunStr string
if dryRun {
client.DryRunAll.ApplyToDelete(opts)
dryRunStr = "(dry run)"
}
return opts, dryRunStr
}
func getUpdateOptions(dryRun bool) (*client.UpdateOptions, string) {
opts := &client.UpdateOptions{}
var dryRunStr string
if dryRun {
client.DryRunAll.ApplyToUpdate(opts)
dryRunStr = "(dry run)"
}
return opts, dryRunStr
} }

42
cmd/flux/version.go Normal file
View File

@@ -0,0 +1,42 @@
package main
import (
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/flux2/pkg/manifestgen/install"
)
func getVersion(input string) (string, error) {
if input == "" {
return rootArgs.defaults.Version, nil
}
if isEmbeddedVersion(input) {
return input, nil
}
var err error
if input == install.MakeDefaultOptions().Version {
input, err = install.GetLatestVersion()
if err != nil {
return "", err
}
} else {
if ok, err := install.ExistingVersion(input); err != nil || !ok {
if err == nil {
err = fmt.Errorf("targeted version '%s' does not exist", input)
}
return "", err
}
}
if !utils.CompatibleVersion(VERSION, input) {
return "", fmt.Errorf("targeted version '%s' is not compatible with your current version of flux (%s)", input, VERSION)
}
return input, nil
}
func isEmbeddedVersion(input string) bool {
return input == rootArgs.defaults.Version
}

View File

@@ -12,7 +12,7 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.
# Check prerequisites # Check prerequisites
flux check --pre flux check --pre
# Install the latest version of the toolkit # Install the latest version of Flux
flux install --version=master flux install --version=master
# Create a source from a public Git repository # Create a source from a public Git repository
@@ -59,8 +59,8 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.
# Delete a GitRepository source # Delete a GitRepository source
flux delete source git webapp-latest flux delete source git webapp-latest
# Uninstall the toolkit and delete CRDs # Uninstall Flux and delete CRDs
flux uninstall --crds flux uninstall
``` ```
@@ -84,9 +84,9 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.
* [flux delete](flux_delete.md) - Delete sources and resources * [flux delete](flux_delete.md) - Delete sources and resources
* [flux export](flux_export.md) - Export resources in YAML format * [flux export](flux_export.md) - Export resources in YAML format
* [flux get](flux_get.md) - Get sources and resources * [flux get](flux_get.md) - Get sources and resources
* [flux install](flux_install.md) - Install the toolkit components * [flux install](flux_install.md) - Install or upgrade Flux
* [flux reconcile](flux_reconcile.md) - Reconcile sources and resources * [flux reconcile](flux_reconcile.md) - Reconcile sources and resources
* [flux resume](flux_resume.md) - Resume suspended resources * [flux resume](flux_resume.md) - Resume suspended resources
* [flux suspend](flux_suspend.md) - Suspend resources * [flux suspend](flux_suspend.md) - Suspend resources
* [flux uninstall](flux_uninstall.md) - Uninstall the toolkit components * [flux uninstall](flux_uninstall.md) - Uninstall Flux and its custom resource definitions

View File

@@ -19,7 +19,8 @@ The bootstrap sub-commands bootstrap the toolkit components on the targeted Git
--network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true) --network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--token-auth when enabled, the personal access token will be used instead of SSH deploy key --token-auth when enabled, the personal access token will be used instead of SSH deploy key
-v, --version string toolkit version (default "latest") --toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
-v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

View File

@@ -51,8 +51,8 @@ flux bootstrap github [flags]
--interval duration sync interval (default 1m0s) --interval duration sync interval (default 1m0s)
--owner string GitHub user or organization name --owner string GitHub user or organization name
--path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path --path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path
--personal is personal repository --personal if true, the owner is assumed to be a GitHub user; otherwise an org
--private is private repository (default true) --private if true, the repository is assumed to be private (default true)
--repository string GitHub repository name --repository string GitHub repository name
--ssh-hostname string GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one --ssh-hostname string GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one
--team stringArray GitHub team to be given maintainer access --team stringArray GitHub team to be given maintainer access
@@ -74,8 +74,9 @@ flux bootstrap github [flags]
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--timeout duration timeout for this operation (default 5m0s) --timeout duration timeout for this operation (default 5m0s)
--token-auth when enabled, the personal access token will be used instead of SSH deploy key --token-auth when enabled, the personal access token will be used instead of SSH deploy key
--toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
--verbose print generated objects --verbose print generated objects
-v, --version string toolkit version (default "latest") -v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

View File

@@ -48,8 +48,8 @@ flux bootstrap gitlab [flags]
--interval duration sync interval (default 1m0s) --interval duration sync interval (default 1m0s)
--owner string GitLab user or group name --owner string GitLab user or group name
--path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path --path safeRelativePath path relative to the repository root, when specified the cluster sync will be scoped to this path
--personal is personal repository --personal if true, the owner is assumed to be a GitLab user; otherwise a group
--private is private repository (default true) --private if true, the repository is assumed to be private (default true)
--repository string GitLab repository name --repository string GitLab repository name
--ssh-hostname string GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one --ssh-hostname string GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one
``` ```
@@ -70,8 +70,9 @@ flux bootstrap gitlab [flags]
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--timeout duration timeout for this operation (default 5m0s) --timeout duration timeout for this operation (default 5m0s)
--token-auth when enabled, the personal access token will be used instead of SSH deploy key --token-auth when enabled, the personal access token will be used instead of SSH deploy key
--toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
--verbose print generated objects --verbose print generated objects
-v, --version string toolkit version (default "latest") -v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

View File

@@ -18,10 +18,13 @@ flux create image policy <name> [flags]
### Options ### Options
``` ```
--filter-regex string regular expression pattern used to filter the image tags --filter-extract string replacement pattern (using capture groups from --filter-regex) to use for sorting
-h, --help help for policy --filter-regex string regular expression pattern used to filter the image tags
--image-ref string the name of an image repository object -h, --help help for policy
--semver string a semver range to apply to tags; e.g., '1.x' --image-ref string the name of an image repository object
--select-alpha string use alphabetical sorting to select image; either "asc" meaning select the last, or "desc" meaning select the first
--select-numeric string use numeric sorting to select image; either "asc" meaning select the last, or "desc" meaning select the first
--select-semver string a semver range to apply to tags; e.g., '1.x'
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

View File

@@ -50,6 +50,7 @@ flux create secret git [name] [flags]
### Options ### Options
``` ```
--ca-file string path to TLS CA file used for validating self-signed certificates
-h, --help help for git -h, --help help for git
-p, --password string basic authentication password -p, --password string basic authentication password
--ssh-ecdsa-curve ecdsaCurve SSH ECDSA public key curve (p256, p384, p521) (default p384) --ssh-ecdsa-curve ecdsaCurve SSH ECDSA public key curve (p256, p384, p521) (default p384)

View File

@@ -56,6 +56,7 @@ flux create source git [name] [flags]
``` ```
--branch string git branch (default "master") --branch string git branch (default "master")
--ca-file string path to TLS CA file used for validating self-signed certificates, requires libgit2
--git-implementation gitImplementation the Git implementation to use, available options are: (go-git, libgit2) --git-implementation gitImplementation the Git implementation to use, available options are: (go-git, libgit2)
-h, --help help for git -h, --help help for git
-p, --password string basic authentication password -p, --password string basic authentication password

View File

@@ -1,10 +1,10 @@
## flux install ## flux install
Install the toolkit components Install or upgrade Flux
### Synopsis ### Synopsis
The install command deploys the toolkit components in the specified namespace. The install command deploys Flux in the specified namespace.
If a previous version is installed, then an in-place upgrade will be performed. If a previous version is installed, then an in-place upgrade will be performed.
``` ```
@@ -17,9 +17,12 @@ flux install [flags]
# Install the latest version in the flux-system namespace # Install the latest version in the flux-system namespace
flux install --version=latest --namespace=flux-system flux install --version=latest --namespace=flux-system
# Dry-run install for a specific version and a series of components # Install a specific version and a series of components
flux install --dry-run --version=v0.0.7 --components="source-controller,kustomize-controller" flux install --dry-run --version=v0.0.7 --components="source-controller,kustomize-controller"
# Install Flux onto tainted Kubernetes nodes
flux install --toleration-keys=node.kubernetes.io/dedicated-to-flux
# Dry-run install with manifests preview # Dry-run install with manifests preview
flux install --dry-run --verbose flux install --dry-run --verbose
@@ -41,7 +44,8 @@ flux install [flags]
--log-level logLevel log level, available options are: (debug, info, error) (default info) --log-level logLevel log level, available options are: (debug, info, error) (default info)
--network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true) --network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
-v, --version string toolkit version (default "latest") --toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
-v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

View File

@@ -1,10 +1,10 @@
## flux uninstall ## flux uninstall
Uninstall the toolkit components Uninstall Flux and its custom resource definitions
### Synopsis ### Synopsis
The uninstall command removes the namespace, cluster roles, cluster role bindings and CRDs from the cluster. The uninstall command removes the Flux components and the toolkit.fluxcd.io resources from the cluster.
``` ```
flux uninstall [flags] flux uninstall [flags]
@@ -13,22 +13,21 @@ flux uninstall [flags]
### Examples ### Examples
``` ```
# Dry-run uninstall of all components # Uninstall Flux components, its custom resources and namespace
flux uninstall --dry-run --namespace=flux-system flux uninstall --namespace=flux-system
# Uninstall all components and delete custom resource definitions # Uninstall Flux but keep the namespace
flux uninstall --resources --crds --namespace=flux-system flux uninstall --namespace=infra --keep-namespace=true
``` ```
### Options ### Options
``` ```
--crds removes all CRDs previously installed --dry-run only print the objects that would be deleted
--dry-run only print the object that would be deleted -h, --help help for uninstall
-h, --help help for uninstall --keep-namespace skip namespace deletion
--resources removes custom resources such as Kustomizations, GitRepositories and HelmRepositories (default true) -s, --silent delete components without asking for confirmation
-s, --silent delete components without asking for confirmation
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

View File

@@ -20,6 +20,7 @@ Features:
- Runs Helm install/upgrade in a specific order, taking into account the depends-on relationship defined in a set of `HelmRelease` objects - Runs Helm install/upgrade in a specific order, taking into account the depends-on relationship defined in a set of `HelmRelease` objects
- Prunes Helm releases removed from cluster (garbage collection) - Prunes Helm releases removed from cluster (garbage collection)
- Reports Helm releases statuses (alerting provided by [notification-controller](../notification/controller.md)) - Reports Helm releases statuses (alerting provided by [notification-controller](../notification/controller.md))
- Built-in Kustomize compatible Helm post renderer, providing support for strategic merge, JSON 6902 and images patches
Links: Links:

View File

@@ -0,0 +1,42 @@
# Advanced debugging
This guide covers more advanced debugging topics such as collecting
runtime profiling data from GitOps Toolkit components.
As a user, this page normally should be a last resort, but you may
be asked by a maintainer to share a [collected profile](#collecting-a-profile)
to debug e.g. performance issues.
## Pprof
The [GitOps Toolkit components](../components/index.md) serve [`pprof`](https://golang.org/pkg/net/http/pprof/)
runtime profiling data on their metrics HTTP server (default `:8080`).
### Endpoints
| Endpoint | Path |
|-------------|------------------------|
| Index | `/debug/pprof/` |
| CPU profile | `/debug/pprof/profile` |
| Symbol | `/debug/pprof/symbol` |
| Trace | `/debug/pprof/trace` |
### Collecting a profile
To collect a profile, port-forward to the component's metrics endpoint
and collect the data from the [endpoint](#endpoints) of choice:
```console
$ kubectl port-forward -n <namespace> deploy/<component> 8080
$ curl -Sk -v http://localhost:8080/debug/pprof/heap > heap.out
```
The collected profile [can be analyzed using `go`](https://blog.golang.org/pprof),
or shared with one of the maintainers.
## Resource usage
As `kubectl top` gives a limited (and at times inaccurate) overview of
resource usage, it is often better to make use of the Grafana metrics
to gather insights. See [monitoring](../guides/monitoring.md) for a
guide on how to visualize this data with a Grafana dashboard.

View File

@@ -150,6 +150,22 @@ The kustomize-controller creates `kustomization.yaml` files similar to:
cd ./deploy/prod && kustomize create --autodetect --recursive cd ./deploy/prod && kustomize create --autodetect --recursive
``` ```
### What is the behavior of Kustomize used by Flux
We referred to the Kustomization CLI flags here, so that you can replicate the same behavior using the CLI. The behavior of Kustomize used by the controller is currently configured as following:
- `--allow_id_changes` is set to false, so it does not change any resource IDs.
- `--enable_kyaml` is disabled by default, so it currently used `k8sdeps` to process YAMLs.
- `--enable_alpha_plugins` is disabled by default, so it uses only the built-in plugins.
- `--load_restrictor` is set to `LoadRestrictionsNone`, so it allows loading files outside the dir containing `kustomization.yaml`.
- `--reorder` resources is done in the `legacy` mode, so the output will have namespaces and cluster roles/role bindings first, CRDs before CRs, and webhooks last.
!!! hint "`kustomization.yaml` validation"
To validate changes before committing and/or merging, [a validation
utility script is available](https://github.com/fluxcd/flux2-kustomize-helm-example/blob/main/scripts/validate.sh),
it runs `kustomize` locally or in CI with the same set of flags as
the controller and validates the output using `kubeval`.
## Helm questions ## Helm questions
### How to debug "not ready" errors? ### How to debug "not ready" errors?

View File

@@ -0,0 +1,771 @@
<!-- -*- fill-column: 100 -*- -->
# Migrating image update automation to Flux v2
"Image Update Automation" is a process in which Flux makes commits to your Git repository when it
detects that there is a new image to be used in a workload (e.g., a Deployment). In Flux v2 this
works quite differently to how it worked in Flux v1. This guide explains the differences and how to
port your cluster configuration from v1 to v2. There is also a [tutorial for using image update
automation with a new cluster][image-update-tute].
## Overview of changes between v1 and v2
In Flux v1, image update automation (from here, just "automation") was built into the Flux daemon,
which scanned everything it found in the cluster and updated the Git repository it was syncing.
In Flux v2,
- automation is controlled with custom resources, not annotations
- ordering images by build time is not supported (there is [a section
below](#how-to-migrate-annotations-to-image-policies) explaining what to do instead)
- the fields to update in files are marked explicitly, rather than inferred from annotations.
#### Automation is now controlled by custom resources
Flux v2 breaks down the functions in Flux v1's daemon into controllers, with each having a specific
area of concern. Automation is now done by two controllers: one which scans image repositories to
find the latest images, and one which uses that information to commit changes to git
repositories. These are in turn separate to the syncing controllers.
This means that automation in Flux v2 is governed by custom resources. In Flux v1 the daemon scanned
everything, and looked at annotations on the resources to determine what to update. Automation in v2
is more explicit than in v1 -- you have to mention exactly which images you want to be scanned, and
which fields you want to be updated.
A consequence of using custom resources is that with Flux v2 you can have an arbitrary number of
automations, targeting different Git repositories if you wish, and updating different sets of
images. If you run a multitenant cluster, the tenants can define automation in their own namespaces,
for their own Git repositories.
#### Selecting an image is more flexible
The ways in which you choose to select an image have changed. In Flux v1, you generally supply a
filter pattern, and the latest image is the image with the most recent build time out of those
filtered. In Flux v2, you choose an ordering, and separately specify a filter for the tags to
consider. These are dealt with in detail below.
Selecting an image by build time is no longer supported. This is the implicit default in Flux v1. In
Flux v2, you will need to tag images so that they sort in the order you would like -- [see
below](#how-to-use-sortable-image-tags) for how to do this conveniently.
#### Fields to update are explicitly marked
Lastly, in Flux v2 the fields to update in files are marked explicitly. In Flux v1 they are inferred
from the type of the resource, along with the annotations given. The approach in Flux v1 was limited
to the types that had been programmed in, whereas Flux v2 can update any Kubernetes object (and some
files that aren't Kubernetes objects, like `kustomization.yaml`).
## Preparing for migration
It is best to complete migration of your system to _Flux v2 syncing_ first, using the [Flux v1
migration guide][flux-v1-migration]. This will remove Flux v1 from the system, along with its image
automation. You can then reintroduce automation with Flux v2 by following the instructions in this
guide.
It is safe to leave the annotations for Flux v1 in files while you reintroduce automation, because
Flux v2 will ignore them.
To migrate to Flux v2 automation, you will need to do three things:
- make sure you are running the automation controllers; then,
- declare the automation with an `ImageUpdateAutomation` object; and,
- migrate each manifest by translate Flux v1 annotations to Flux v2 `ImageRepository` and
`ImagePolicy` objects, and putting update markers in the manifest file.
### Where to keep `ImageRepository`, `ImagePolicy` and `ImageUpdateAutomation` manifests
This guide assumes you want to manage automation itself via Flux. In the following sections,
manifests for the objects controlling automation are saved in files, committed to Git, and applied
in the cluster with Flux.
A Flux v2 installation will typically have a Git repository structured like this:
```
<...>/flux-system/
gotk-components.yaml
gotk-sync.yaml
<...>/app/
# deployments etc.
```
The `<...>` is the path to a particular cluster's definitions -- this may be simply `.`, or
something like `clusters/my-cluster`. To get the files in the right place, set a variable for this
path:
```bash
$ CLUSTER_PATH=<...> # e.g., "." or "clusters/my-cluster", or ...
$ AUTO_PATH=$CLUSTER_PATH/automation
$ mkdir ./$AUTO_PATH
```
The file `$CLUSTER_PATH/flux-system/gotk-components.yaml` has definitions of all the Flux v2
controllers and custom resource definitions. The file `gotk-sync.yaml` defines a `GitRepository` and
a `Kustomization` which will sync manifests under `$CLUSTER_PATH/`.
To these will be added definitions for automation objects. This guide puts manifest files for
automation in `$CLUSTER_PATH/automation/`, but there is no particular structure required
by Flux. The automation objects do not have to be in the same namespace as the objects to be
updated.
#### Migration on a branch
This guide assumes you will commit changes to the branch that is synced by Flux, as this is the
simplest way to understand.
It may be less disruptive to put migration changes on a branch, then merging when you have completed
the migration. You would need to either change the `GitRepository` to point at the migration branch,
or have separate `GitRepository` and `Kustomization` objects for the migrated parts of your Git
repository. The main thing to avoid is syncing the same objects in two different places; e.g., avoid
having Kustomizations that sync both the unmigrated and migrated application configuration.
### Installing the command-line tool `flux`
The command-line tool `flux` will be used below; see [these instructions][install-cli] for how to
install it.
## Running the automation controllers
The first thing to do is to deploy the automation controllers to your cluster. The best way to
proceed will depend on the approach you took when following the [Flux read-only migration
guide][flux-v1-migration].
- If you used `flux bootstrap` to create a new Git repository, then ported your cluster
configuration to that repository, use [After `flux bootstrap`](#after-flux-bootstrap);
- If you used `flux install` to install the controllers directly, use [After migrating Flux v1 in
place](#after-migrating-flux-v1-in-place);
- If you used `flux install` and exported the configuration to a file, use [After committing Flux
v2 configuration to Git](#after-committing-a-flux-v2-configuration-to-git).
### After `flux bootstrap`
When starting from scratch, you are likely to have used `flux bootstrap`. Rerun the command, and
include the image automation controllers in your starting configuration with the flag
`--components-extra`, [as shown in the installation guide][flux-bootstrap].
This will commit changes to your Git repository and sync them in the cluster.
```bash
flux check --components-extra=image-reflector-controller,image-automation-controller
```
Now jump to the section [Migrating each manifest to Flux v2](#migrating-each-manifest-to-flux-v2).
### After migrating Flux v1 in place
If you followed the [Flux v1 migration guide][flux-v1-migration], you will already be running some
Flux v2 controllers. The automation controllers are currently considered an optional extra to those,
but are installed and run in much the same way. You may or may not have committed the Flux v2
configuration to your Git repository. If you did, go to the section [After committing Flux v2
configuration to Git](#after-committing-flux-v2-configuration-to-git).
If _not_, you will be installing directly to the cluster:
```bash
$ flux install --components-extra=image-reflector-controller,image-automation-controller
```
It is safe to repeat the installation command, or to run it after using `flux bootstrap`, so long as
you repeat any arguments you supplied the first time.
Now jump ahead to [Migrating each manifest to Flux v2](#migrating-each-manifest-to-flux-v2).
#### After committing a Flux v2 configuration to Git
If you added the Flux v2 configuration to your git repository, assuming it's in the file
`$CLUSTER_PATH/flux-system/gotk-components.yaml` as used in the guide, use `flux install` and write
it back to that file:
```bash
$ flux install \
--components-extra=image-reflector-controller,image-automation-controller \
--export > "$CLUSTER_PATH/flux-system/gotk-components.yaml"
```
Commit changes to the `$CLUSTER_PATH/flux-system/gotk-components.yaml` file and sync the cluster:
```bash
$ git add $CLUSTER_PATH/flux-system/gotk-components.yaml
$ git commit -s -m "Add image automation controllers to Flux config"
$ git push
$ flux reconcile kustomization --with-source flux-system
```
## Controlling automation with an `ImageUpdateAutomation` object
In Flux v1, automation was run by default. With Flux v2, you have to explicitly tell the controller
which Git repository to update and how to do so. These are defined in an `ImageUpdateAutomation`
object; but first, you need a `GitRepository` with write access, for the automation to use.
If you followed the [Flux v1 read-only migration guide][flux-v1-migration], you will have a
`GitRepository` defined in the namespace `flux-system`, for syncing to use. This `GitRepository`
will have _read_ access to the Git repository by default, and automation needs _write_ access to
push commits.
To give it write access, you can replace the secret it refers to. How to do this will depend on what
kind of authentication you used to install Flux v2.
### Replacing the Git credentials secret
The secret with Git credentials will be named in the `.spec.secretRef.name` field of the
`GitRepository` object. Say your `GitRepository` is in the _namespace_ `flux-system` and _named_
`flux-system` (these are the defaults if you used `flux bootstrap`); you can retrieve the secret
name and Git URL with:
```bash
$ FLUX_NS=flux-system
$ GIT_NAME=flux-system
$ SECRET_NAME=$(kubectl -n $FLUX_NS get gitrepository $GIT_NAME -o jsonpath={.spec.secretRef.name})
$ GIT_URL=$(kubectl -n $FLUX_NS get gitrepository $GIT_NAME -o jsonpath='{.spec.url}')
$ echo $SECRET_NAME $GIT_URL # make sure they have values
```
If you're not sure which kind of credentials you're using, look at the secret:
```bash
$ kubectl -n $FLUX_NS describe secret $SECRET_NAME
```
An entry at `.data.identity` indicates that you are using an SSH key (the [first
section](#replacing-an-ssh-key-secret) below); an entry at `.data.username` indicates you are using
a username and password or token (the [second section](#replacing-a-usernamepassword-secret)
below).
#### Replacing an SSH key secret
When using an SSH (deploy) key, create a new key:
```bash
$ flux create secret git -n $FLUX_NS $SECRET_NAME --url=$GIT_URL
```
You will need to copy the public key that's printed out, and install that as a deploy key for your
Git repo **making sure to check the 'All write access' box** (or otherwise give the key write
permissions). Remove the old deploy key.
#### Replacing a username/password secret
When you're using a username and password to authenticate, you may be able to change the permissions
associated with that account.
If not, you will need to create a new access token (e.g., ["Personal Access Token"][github-pat] in
GitHub). In this case, once you have the new token you can replace the secret with the following:
```bash
$ flux create secret git -n $FLUX_NS $SECRET_NAME \
--username <username> --password <token> --url $GIT_URL
```
#### Checking the new credentials
To check if your replaced credentials still work, try syncing the `GitRepository` object:
```bash
$ flux reconcile source git -n $FLUX_NS $GIT_NAME
► annotating GitRepository flux-system in flux-system namespace
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ GitRepository reconciliation completed
✔ fetched revision main/d537304e8f5f41f1584ca1e807df5b5752b2577e
```
When this is successful, it tells you the new credentials have at least read access.
### Making an automation object
To set automation running, you create an [`ImageUpdateAutomation`][auto-ref] object. Each object
will update a Git repository, according to the image policies in the namespace.
Here is an `ImageUpdateAutomation` manifest for the example (note: you will have to supply your own
value for at least the host part of the email address):
```yaml
$ # the environment variables $AUTO_PATH and $GIT_NAME are set above
$ FLUXBOT_EMAIL=fluxbot@example.com # supply your own host or address here
$ flux create image update my-app-auto \
--author-name FluxBot --author-email "$FLUXBOT_EMAIL" \
--git-repo-ref $GIT_NAME --branch main \
--interval 5m \
--export > ./$AUTO_PATH/my-app-auto.yaml
$ cat my-app-auto.yaml
---
apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImageUpdateAutomation
metadata:
name: my-app-auto
namespace: flux-system
spec:
checkout:
branch: main
gitRepositoryRef:
name: flux-system
commit:
authorEmail: fluxbot@example.com
authorName: FluxBot
interval: 5m0s
```
#### Commit and check that the automation object works
Commit the manifeat file and push:
```bash
$ git add ./$AUTO_PATH/my-app-auto.yaml
$ git commit -s -m "Add image update automation"
$ git push
# ...
```
Then sync and check the object status:
```bash
$ flux reconcile kustomization --with-source flux-system
► annotating GitRepository flux-system in flux-system namespace
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ GitRepository reconciliation completed
✔ fetched revision main/401dd3b550f82581c7d12bb79ade389089c6422f
► annotating Kustomization flux-system in flux-system namespace
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ Kustomization reconciliation completed
✔ reconciled revision main/401dd3b550f82581c7d12bb79ade389089c6422f
$ flux get image update
NAME READY MESSAGE LAST RUN SUSPENDED
my-app-auto True no updates made 2021-02-08T14:53:43Z False
```
Read on to the next section to see how to change each manifest file to work with Flux v2.
## Migrating each manifest to Flux v2
In Flux v1, the annotation
fluxcd.io/automated: "true"
switches automation on for a manifest (a description of a Kubernetes object). For each manifest that
has that annotation, you will need to create custom resources to scan for the latest image, and to
replace the annotations with field markers.
The following sections explain these steps, using this example Deployment manifest which is
initially annotated to work with Flux v1:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
annotations:
fluxcd.io/automated: "true"
fluxcd.io/tag.app: semver:^5.0
selector:
matchLabels:
app: podinfo
spec:
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: app
image: ghcr.io/stefanprodan/podinfo:5.0.0
```
!!! warning
A YAML file may have more than one manifest in it, separated with
`---`. Be careful to account for each manifest in a file.
You may wish to try migrating the automation of just one file or manifest and follow it through to
the end of the guide, before returning here to do the remainder.
### How to migrate annotations to image policies
For each image repository that is the subject of automation you will need to create an
`ImageRepository` object, so that the image repository is scanned for tags. The image repository in
the example deployment is `ghcr.io/stefanprodan/podinfo`, which is the image reference minus its
tag:
```yaml
$ cat $CLUSTER_PATH/app/my-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
annotations:
fluxcd.io/automated: "true"
fluxcd.io/tag.app: semver:^5.0
selector:
matchLabels:
app: podinfo
spec:
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: app
image: ghcr.io/stefanprodan/podinfo:5.0.0 # <-- image reference
```
The command-line tool `flux` will help create a manifest for you. Note that the output is redirected
to a file under `$AUTO_PATH`, so it can be added to the Git repository and synced to the cluster.
```bash
$ # the environment variable $AUTO_PATH was set earlier
$ flux create image repository podinfo-image \
--image ghcr.io/stefanprodan/podinfo \
--interval 5m \
--export > ./$AUTO_PATH/podinfo-image.yaml
$ cat ./$AUTO_PATH/podinfo-image.yaml
---
apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImageRepository
metadata:
name: podinfo-image
namespace: flux-system
spec:
image: ghcr.io/stefanprodan/podinfo
interval: 5m0s
```
!!! hint
If you are using the same image repository in several manifests, you only need one
`ImageRepository` object for it.
##### Using image registry credentials for scanning
When your image repositories are private, you supply Kubernetes with "image pull secrets" with
credentials for accessing the image registry (e.g., DockerHub). The image reflector controller needs
the same kind of credentials to scan image repositories.
There are several ways that image pull secrets can be made available for the image reflector
controller. The [image update tutorial][image-update-tute-creds] describes how to create or arrange
secrets for scanning to use. Also see later in the tutorial for [instructions specific to some cloud
platforms][image-update-tute-clouds].
##### Committing and checking the ImageRepository
Add the `ImageRepository` manifest to the Git index and commit it:
```bash
$ git add ./$AUTO_PATH/podinfo-image.yaml
$ git commit -s -m "Add image repository object for podinfo"
$ git push
# ...
```
Now you can sync the new commit, and check that the object is working:
```bash
$ flux reocncile kustomization --with-source flux-system
► annotating GitRepository flux-system in flux-system namespace
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ GitRepository reconciliation completed
✔ fetched revision main/fd2fe8a61d4537bcfa349e4d1dbc480ea699ba8a
► annotating Kustomization flux-system in flux-system namespace
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ Kustomization reconciliation completed
✔ reconciled revision main/fd2fe8a61d4537bcfa349e4d1dbc480ea699ba8a
$ flux get image repository podinfo-image
NAME READY MESSAGE LAST SCAN SUSPENDED
podinfo-image True successful scan, found 16 tags 2021-02-08T14:31:38Z False
```
#### Replacing automation annotations
For each _field_ that's being updated by automation, you'll need an `ImagePolicy` object to describe
how to select an image for the field value. In the example, the field `.image` in the container
named `"app"` is the field being updated.
In Flux v1, annotations describe how to select the image to update to, using a prefix. In the
example, the prefix is `semver:`:
```yaml
annotations:
fluxcd.io/automated: "true"
fluxcd.io/tag.app: semver:^5.0
```
These are the prefixes supported in Flux v1, and what to use in Flux v2:
| Flux v1 prefix | Meaning | Flux v2 equivalent |
|----------------|---------|--------------------|
| `glob:` | Filter for tags matching the glob pattern, then select the newest by build time | [Use sortable tags](#how-to-use-sortable-image-tags) |
| `regex:` | Filter for tags matching the regular expression, then select the newest by build time |[Use sortable tags](#how-to-use-sortable-image-tags) |
| `semver:` | Filter for tags that represent versions, and select the highest version in the given range | [Use semver ordering](#how-to-use-semver-image-tags) |
#### How to use sortable image tags
To give image tags a useful ordering, you can use a timestamp or serial number as part of each
image's tag, then sort either alphabetically or numerically.
This is a change from Flux v1, in which the build time was fetched from each image's config, and
didn't need to be included in the image tag. Therefore, this is likely to require a change to your
build process.
The guide [How to make sortable image tags][image-tags-guide] explains how to change your build
process to tag images with a timestamp. This will mean Flux v2 can sort the tags to find the most
recently built image.
##### Filtering the tags in an `ImagePolicy`
The recommended format for image tags using a timestamp is:
<branch>-<sha1>-<timestamp>
The timestamp (or serial number) is the part of the tag that you want to order on. The SHA1 is there
so you can trace an image back to the commit from which it was built. You don't need the branch for
sorting, but you may want to include only builds from a specific branch.
Say you want to filter for only images that are from `main` branch, and pick the most recent. Your
`ImagePolicy` would look like this:
```yaml
apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImagePolicy
metadata:
name: my-app-policy
namespace: flux-system
spec:
imageRepositoryRef:
name: podinfo-image
filterTags:
pattern: '^main-[a-f0-9]+-(?P<ts>[0-9]+)'
extract: '$ts'
policy:
numerical:
order: asc
```
The `.spec.pattern` field gives a regular expression that a tag must match to be included. The
`.spec.extract` field gives a replacement pattern that can refer back to capture groups in the
filter pattern. The extracted values are sorted to find the selected image tag. In this case, the
timestamp part of the tag will be extracted and sorted numerically in ascending order. See [the
reference docs][imagepolicy-ref] for more examples.
Once you have made sure you have image tags and an `ImagePolicy` that works, jump ahead to [Checking
the ImagePolicy works](#checking-that-the-image-policy-works).
### How to use SemVer image tags
The other kind of sorting is by [SemVer][semver], picking the highest version from among those
included by the filter. A semver range will also filter for tags that fit in the range. For example,
```yaml
semver:
range: ^5.0
```
includes only tags that have a major version of `5`, and selects whichever is the highest.
This can be combined with a regular expression pattern, to filter on other parts of the tags. For
example, you might put a target environment as well as the version in your image tags, like
`dev-v1.0.3`.
Then you would use an `ImagePolicy` similar to this one:
```yaml
apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImagePolicy
metadata:
name: my-app-policy
namespace: flux-system
spec:
imageRepositoryRef:
name: podinfo-image
filterTags:
pattern: '^dev-v(?P<version>.*)'
extract: '$version'
policy:
semver:
range: '^1.0'
```
Continue on to the next sections to see an example, and how to check that your `ImagePolicy` works.
#### An `ImagePolicy` for the example
The example Deployment has annotations using `semver:` as a prefix, so the policy object also uses
semver:
```bash
$ # the environment variable $AUTO_PATH was set earlier
$ flux create image policy my-app-policy \
--image-ref podinfo-image \
--semver '^5.0' \
--export > ./$AUTO_PATH/my-app-policy.yaml
$ cat ./$AUTO_PATH/my-app-policy.yaml
---
apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImagePolicy
metadata:
name: my-app-policy
namespace: flux-system
spec:
imageRepositoryRef:
name: podinfo-image
policy:
semver:
range: ^5.0
```
#### Checking that the `ImagePolicy` works
Commit the manifest file, and push:
```bash
$ git add ./$AUTO_PATH/my-app-policy.yaml
$ git commit -s -m "Add image policy for my-app"
$ git push
# ...
```
Then you can reconcile and check that the image policy works:
```bash
$ flux reconcile kustomization --with-source flux-system
► annotating GitRepository flux-system in flux-system namespace
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ GitRepository reconciliation completed
✔ fetched revision main/7dcf50222499be8c97e22cd37e26bbcda8f70b95
► annotating Kustomization flux-system in flux-system namespace
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ Kustomization reconciliation completed
✔ reconciled revision main/7dcf50222499be8c97e22cd37e26bbcda8f70b95
$ flux get image policy flux-system
NAME READY MESSAGE LATEST IMAGE
my-app-policy True Latest image tag for 'ghcr.io/stefanprodan/podinfo' resolved to: 5.1.4 ghcr.io/stefanprodan/podinfo:5.1.4
```
### How to mark up files for update
The last thing to do in each manifest is to mark the fields that you want to be updated.
In Flux v1, the annotations in a manifest determines the fields to be updated. In the example, the
annotations target the image used by the container `app`:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
annotations:
fluxcd.io/automated: "true"
fluxcd.io/tag.app: semver:^5.0 # <-- `.app` here
selector:
matchLabels:
app: podinfo
spec:
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: app # <-- targets `app` here
image: ghcr.io/stefanprodan/podinfo:5.0.0
```
This works straight-forwardly for Deployment manifests, but when it comes to `HelmRelease`
manifests, it [gets complicated][helm-auto], and it doesn't work at all for many kinds of resources.
For Flux v2, you mark the field you want to be updated directly, with the namespaced name of the
image policy to apply. This is the example Deployment, marked up for Flux v2:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: my-app
selector:
matchLabels:
app: podinfo
spec:
template:
metadata:
labels:
app: podinfo
spec:
containers:
- name: app
image: ghcr.io/stefanprodan/podinfo:5.0.0 # {"$imagepolicy": "flux-system:my-app-policy"}
```
The value `flux-system:my-app-policy` names the policy that selects the desired image.
This works in the same way for `DaemonSet` and `CronJob` manifests. For `HelmRelease` manifests, put
the marker alongside the part of the `values` that has the image tag. If the image tag is a separate
field, you can put `:tag` on the end of the name, to replace the value with just the selected
image's tag. The [image automation guide][image-update-tute-custom] has examples for `HelmRelease`
and other custom resources.
### Committing the marker change and checking that automation works
Referring to the image policy created earlier, you can see the example Deployment does not use the
most recent image. When you commit the manifest file with the update marker added, you would expect
automation to update the file.
Commit the change that adds an update marker:
```bash
$ git add app/my-app.yaml # the filename of the example
$ git commit -s -m "Add update marker to my-app manifest"
$ git push
# ...
```
Now to check that the automation makes a change:
```bash
$ flux reconcile image update my-app-auto
► annotating ImageUpdateAutomation my-app-auto in flux-system namespace
✔ ImageUpdateAutomation annotated
◎ waiting for ImageUpdateAutomation reconciliation
✔ ImageUpdateAutomation reconciliation completed
✔ committed and pushed a92a4b654f520c00cb6c46b2d5e4fb4861aa58fc
```
## Troubleshooting
If a change was not pushed by the image automation, there's several things you can check:
- it's possible it made a change that is not reported in the latest status -- pull from the origin
and check the commit log
- check that the name used in the marker corresponds to the namespace and name of an `ImagePolicy`
- check that the `ImageUpdateAutomation` is in the same namespace as the `ImagePolicy` objects
named in markers
- check that the image policy and the image repository are both reported as `Ready`
- check that the credentials referenced by the `GitRepository` object have write permission, and
create new credentials if necessary.
As a fallback, you can scan the logs of the automation controller to see if it logged errors:
```bash
$ kubectl logs -n flux-system deploy/image-automation-controller
```
Once you are satisfied that it is working, you can migrate the rest of the manifests using the steps
from ["Migrating each manifest to Flux v2"](#migrating-each-manifest-to-flux-v2) above.
[image-update-tute]: https://toolkit.fluxcd.io/guides/image-update/
[imagepolicy-ref]: https://toolkit.fluxcd.io/components/image/imagepolicies/
[helm-auto]: https://docs.fluxcd.io/en/1.21.1/references/helm-operator-integration/#automated-image-detection
[image-update-tute-custom]: https://toolkit.fluxcd.io/guides/image-update/#configure-image-update-for-custom-resources
[flux-v1-migration]: https://toolkit.fluxcd.io/guides/flux-v1-migration/
[install-cli]: https://toolkit.fluxcd.io/get-started/#install-the-flux-cli
[flux-bootstrap]: https://toolkit.fluxcd.io/guides/installation/#bootstrap
[github-pat]: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token
[auto-object-ref]: https://toolkit.fluxcd.io/components/image/imageupdateautomations/
[image-update-tute-creds]: https://toolkit.fluxcd.io/guides/image-update/#configure-image-scanning
[image-update-tute-clouds]: https://toolkit.fluxcd.io/guides/image-update/#imagerepository-cloud-providers-authentication
[image-tags-guide]: https://toolkit.fluxcd.io/guides/sortable-image-tags/
[auto-ref]: https://toolkit.fluxcd.io/components/image/imageupdateautomations/
[semver]: https://semver.org

View File

@@ -6,7 +6,16 @@ Read the [FAQ](../faq/index.md) to find out what differences are between v1 and
!!! info "Automated image updates" !!! info "Automated image updates"
The image automation feature is under development in Flux v2. The image automation feature is under development in Flux v2.
Please consult the [roadmap](../roadmap/index.md) for more details. Please consult the [roadmap](../roadmap/index.md) for more details.
!!! info "Feature parity"
"Feature parity" does not mean Flux v2 works exactly the same as v1 (or is
backward-compatible); it means you can accomplish the same results, while
accounting for the fact that it's a system with a substantially different
design.
This may at times mean that you have to make adjustments to the way your
current cluster configuration is structured. If you are in this situation
and need help, please refer to the [support page](https://fluxcd.io/support/).
## Prerequisites ## Prerequisites
You will need a Kubernetes cluster version **1.16** or newer You will need a Kubernetes cluster version **1.16** or newer
@@ -53,6 +62,13 @@ to define the state of your fleet of Kubernetes clusters.
For a detailed walk-through of the bootstrap procedure please see the [installation guide](installation.md). For a detailed walk-through of the bootstrap procedure please see the [installation guide](installation.md).
!!! warning "`flux bootstrap` target"
`flux bootstrap` should not be run against a Git branch or path
that is already being synchronized by Flux v1, as this will make
them fight over the resources. Instead, bootstrap to a **new Git
repository, branch or path**, and continue with moving the
manifests.
After you've installed Flux v2 on your cluster using bootstrap, After you've installed Flux v2 on your cluster using bootstrap,
you can delete the Flux v1 from your clusters and move the manifests from the you can delete the Flux v1 from your clusters and move the manifests from the
Flux v1 repository to the bootstrap one. Flux v1 repository to the bootstrap one.

View File

@@ -170,8 +170,7 @@ Create an `ImagePolicy` to tell Flux which semver range to use when filtering ta
```sh ```sh
flux create image policy podinfo \ flux create image policy podinfo \
--image-ref=podinfo \ --image-ref=podinfo \
--interval=1m \ --select-semver=5.0.x \
--semver=5.0.x \
--export > ./clusters/my-cluster/podinfo-policy.yaml --export > ./clusters/my-cluster/podinfo-policy.yaml
``` ```
@@ -292,7 +291,7 @@ Tell Flux to pull and apply changes:
flux reconcile kustomization flux-system --with-source flux reconcile kustomization flux-system --with-source
``` ```
In a couple of seconds Flux will push a commit to your repository with In a couple of seconds, Flux will push a commit to your repository with
the latest image tag that matches the podinfo policy: the latest image tag that matches the podinfo policy:
```console ```console
@@ -429,6 +428,86 @@ LB and the generated URL `http://<LoadBalancerAddress>/<ReceiverURL>`.
and any other system that supports webhooks e.g. GitHub Actions, Jenkins, CircleCI, etc. and any other system that supports webhooks e.g. GitHub Actions, Jenkins, CircleCI, etc.
See the [Receiver CRD docs](../components/notification/receiver.md) for more details. See the [Receiver CRD docs](../components/notification/receiver.md) for more details.
## Incident management
### Suspend automation
During an incident you may wish to stop Flux from pushing image updates to Git.
You can suspend the image automation directly in-cluster:
```sh
flux suspend image update flux-system
```
Or by editing the `ImageUpdateAutomation` manifest in Git:
```yaml
kind: ImageUpdateAutomation
metadata:
name: flux-system
namespace: flux-system
spec:
suspend: true
```
Once the incident is resolved, you can resume automation with:
```sh
flux resume image update flux-system
```
If you wish to pause the automation for a particular image only,
you can suspend/resume the image scanning:
```sh
flux suspend image repository podinfo
```
### Revert image updates
Assuming you've configured Flux to update an app to its latest stable version:
```sh
flux create image policy podinfo \
--image-ref=podinfo \
--select-semver=">=5.0.0"
```
If the latest version e.g. `5.0.1` causes an incident in production, you can tell Flux to
revert the image tag to a previous version e.g. `5.0.0` with:
```sh
flux create image policy podinfo \
--image-ref=podinfo \
--select-semver=5.0.0
```
Or by changing the semver range in Git:
```yaml
kind: ImagePolicy
metadata:
name: podinfo
namespace: flux-system
spec:
policy:
semver:
range: 5.0.0
```
Based on the above configuration, Flux will patch the podinfo deployment manifest in Git
and roll out `5.0.0` in-cluster.
When a new version is available e.g. `5.0.2`, you can update the policy once more
and tell Flux to consider only versions greater than `5.0.1`:
```sh
flux create image policy podinfo \
--image-ref=podinfo \
--select-semver=">5.0.1"
```
## ImageRepository cloud providers authentication ## ImageRepository cloud providers authentication
If relying on a cloud provider image repository, you might need to do some extra If relying on a cloud provider image repository, you might need to do some extra
@@ -578,7 +657,7 @@ spec:
#### Using access token [short-lived] #### Using access token [short-lived]
!!!note "Workload Identity" !!! note "Workload Identity"
Please ensure that you enable workload identity for your cluster, create a GCP service account that has Please ensure that you enable workload identity for your cluster, create a GCP service account that has
access to the container registry and create an IAM policy binding between the GCP service account and access to the container registry and create an IAM policy binding between the GCP service account and
the Kubernetes service account so that the pods created by the cronjob can access GCP APIs and get the token. the Kubernetes service account so that the pods created by the cronjob can access GCP APIs and get the token.
@@ -713,4 +792,87 @@ or [Sealed Secrets](sealed-secrets.md) , commit and push the encypted file to gi
### Azure Container Registry ### Azure Container Registry
TODO AKS clusters are not able to pull and run images from ACR by default.
Read [Integrating AKS /w ACR](https://docs.microsoft.com/en-us/azure/aks/cluster-container-registry-integration) as a potential pre-requisite
before integrating Flux `ImageRepositories` with ACR.
Note that the resulting ImagePullSecret for Flux could also be specified by Pods within the same Namespace to pull and run ACR images as well.
#### Generating Tokens for Managed Identities [short-lived]
With [AAD Pod-Identity](https://azure.github.io/aad-pod-identity/docs/), we can create Pods that have their own
cloud credentials for accessing Azure services like ACR.
Your cluster should have `--enable-managed-identity` configured.
This software can be [installed via Helm](https://azure.github.io/aad-pod-identity/docs/getting-started/installation/) not managed by Azure.
Use Flux's `HelmRepository` and `HelmRelease` object to manage the aad-pod-identity installation from a bootstrap repository.
!!! As an alternative to Helm, the `--enable-aad-pod-identity` flag for the `az aks create` is currently in Preview.
Follow the Azure guide for [Creating an AKS cluster with AAD Pod Identity](https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity) if you would like to enable this feature with the Azure CLI.
Once we have AAD Pod Identity installed, we can create a Deployment that frequently refreshes an image pull secret into
our desired Namespace.
Create a directory in your control repository and save this `kustomization.yaml`:
```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- git@github.com/fluxcd/flux2//manifests/integrations/registry-credentials-sync/azure
patchesStrategicMerge:
- config-patches.yaml
```
Save and configure the following patch -- note the instructional comments for configuring matching Azure resources:
```yaml
# config-patches.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
ACR_NAME: my-registry
KUBE_SECRET: my-registry # does not yet exist -- will be created in the same Namespace
SYNC_PERIOD: "3600" # ACR tokens expire every 3 hours; refresh faster than that
# Create an identity in Azure and assign it a role to pull from ACR (note: the identity's resourceGroup should match the desired ACR):
# az identity create -n acr-sync
# az role assignment create --role AcrPull --assignee-object-id "$(az identity show -n acr-sync -o tsv --query principalId)"
# Fetch the clientID and resourceID to configure the AzureIdentity spec below:
# az identity show -n acr-sync -otsv --query clientId
# az identity show -n acr-sync -otsv --query resourceId
---
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentity
metadata:
name: credentials-sync # name must match the stub-resource in az-identity.yaml
namespace: flux-system
spec:
clientID: 4ceaa448-d7b9-4a80-8f32-497eaf3d3287
resourceID: /subscriptions/8c69185e-55f9-4d00-8e71-a1b1bb1386a1/resourcegroups/stealthybox/providers/Microsoft.ManagedIdentity/userAssignedIdentities/acr-sync
type: 0 # user-managed identity
```
Verify that `kustomize build .` works, then commit the directory to you control repo.
Flux will apply the Deployment and it will use the AAD managed identity for that Pod to regularly fetch ACR tokens into your configured `KUBE_SECRET` name.
Reference the `KUBE_SECRET` value from any `ImageRepository` objects for that ACR registry.
This example uses the `fluxcd/flux2` github archive as a remote base, but you may copy the [./manifests/integrations/registry-credentials-sync/azure](github.com/fluxcd/flux2/tree/main/manifests/integrations/registry-credentials-sync/azure)
folder into your own repository or use a git submodule to vendor it if preferred.
#### Using Static Credentials [long-lived]
!!! Using a static credential requires a Secrets management solution compatible with your GitOps workflow.
Follow the official Azure documentation for [Creating an Image Pull Secret for ACR](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-kubernetes).
Instead of creating the Secret directly into your Kubernetes cluster, encrypt it using [Mozilla SOPS](mozilla-sops.md)
or [Sealed Secrets](sealed-secrets.md), then commit and push the encypted file to git.
This Secret should be in the same Namespace as your flux `ImageRepository` object.
Update the `ImageRepository.spec.secretRef` to point to it.
It is also possible to create [Repository Scoped Tokens](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-repository-scoped-permissions).
!!! Note that this feature is in preview and does have limitations.

View File

@@ -58,8 +58,7 @@ You can choose what components to install and for which cluster with:
flux bootstrap <GIT-PROVIDER> \ flux bootstrap <GIT-PROVIDER> \
--components=source-controller,kustomize-controller,helm-controller,notification-controller \ --components=source-controller,kustomize-controller,helm-controller,notification-controller \
--components-extra=image-reflector-controller,image-automation-controller \ --components-extra=image-reflector-controller,image-automation-controller \
--path=clusters/my-cluster \ --path=clusters/my-cluster
--version=latest
``` ```
!!! hint "Multi-arch images" !!! hint "Multi-arch images"
@@ -68,7 +67,11 @@ flux bootstrap <GIT-PROVIDER> \
architectures. architectures.
If you wish to install a specific version, use the Flux If you wish to install a specific version, use the Flux
[release tag](https://github.com/fluxcd/flux2/releases) e.g. `--version=v0.2.0`. [release tag](https://github.com/fluxcd/flux2/releases) e.g. `--version=v0.9.0`.
If you wish to deploy the Flux components onto
[tainted Kubernetes nodes](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/),
you can specify the toleration keys with `--toleration-keys=node.kubernetes.io/dedicated-to-flux`.
With `--path` you can configure the directory which will be used to reconcile the target cluster. With `--path` you can configure the directory which will be used to reconcile the target cluster.
To control multiple clusters from the same Git repository, you have to set a unique path per To control multiple clusters from the same Git repository, you have to set a unique path per
@@ -222,9 +225,59 @@ flux bootstrap gitlab \
--path=clusters/my-cluster --path=clusters/my-cluster
``` ```
### Air-gapped Environments
To bootstrap Flux on air-gapped environments without access to github.com and ghcr.io, first you'll need
to download the `flux` binary, and the container images from a computer with access to internet.
List all container images:
```console
$ flux install --export | grep ghcr.io
image: ghcr.io/fluxcd/helm-controller:v0.8.0
image: ghcr.io/fluxcd/kustomize-controller:v0.9.0
image: ghcr.io/fluxcd/notification-controller:v0.9.0
image: ghcr.io/fluxcd/source-controller:v0.9.0
```
Pull the images locally and push them to your container registry:
```sh
docker pull ghcr.io/fluxcd/source-controller:v0.9.0
docker tag ghcr.io/fluxcd/source-controller:v0.9.0 registry.internal/fluxcd/source-controller:v0.9.0
docker push registry.internal/fluxcd/source-controller:v0.9.0
```
Copy `flux` binary to a computer with access to your air-gapped cluster,
and create the pull secret in the `flux-system` namespace:
```sh
kubectl create ns flux-system
kubectl -n flux-system create secret generic regcred \
--from-file=.dockerconfigjson=/.docker/config.json \
--type=kubernetes.io/dockerconfigjson
```
Finally, bootstrap Flux using the images from your private registry:
```sh
flux bootstrap <GIT-PROVIDER> \
--registry=registry.internal/fluxcd \
--image-pull-secret=regcred \
--hostname=my-git-server.internal
```
Note that when running `flux bootstrap` without specifying a `--version`,
the CLI will use the manifests embedded in its binary instead of downloading
them from GitHub. You can determine which version you'll be installing,
with `flux --version`.
### Generic Git Server ### Generic Git Server
For other Git providers such as Bitbucket, Gogs, Gitea, Azure DevOps, 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 deploy key.
Create a Git repository and clone it locally: Create a Git repository and clone it locally:
@@ -242,35 +295,7 @@ mkdir -p ./clusters/my-cluster/flux-system
Generate the Flux manifests with: Generate the Flux manifests with:
```sh ```sh
flux install --version=latest \ flux install \
--export > ./clusters/my-cluster/flux-system/gotk-components.yaml
```
If your cluster must pull images from a private container registry, first you should pull
the toolkit images from GitHub Container Registry and push them to your registry, for example:
```sh
docker pull ghcr.io/fluxcd/source-controller:v0.2.0
docker tag ghcr.io/fluxcd/source-controller:v0.2.0 registry.internal/fluxcd/source-controller:v0.2.0
docker push registry.internal/fluxcd/source-controller:v0.2.0
```
Create the pull secret in the `flux-system` namespace:
```sh
kubectl create ns flux-system
kubectl -n flux-system create secret generic regcred \
--from-file=.dockerconfigjson=/.docker/config.json \
--type=kubernetes.io/dockerconfigjson
```
Set your registry domain, and the pull secret when generating the manifests:
```sh
flux install --version=latest \
--registry=registry.internal/fluxcd \
--image-pull-secret=regcred \
--export > ./clusters/my-cluster/flux-system/gotk-components.yaml --export > ./clusters/my-cluster/flux-system/gotk-components.yaml
``` ```
@@ -310,15 +335,13 @@ If you don't specify the SSH algorithm, then `flux` will generate an RSA 2048 bi
Azure DevOps requires a non-default Git implementation (`libgit2`) to be enabled, so that the Git v2 protocol is supported. 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 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. 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: If you are using Azure DevOps you need to specify a different Git implementation than the default:
```sh ```sh
flux create source git flux-system \ flux create source git flux-system \
--git-implementation=libgit2 \ --git-implementation=libgit2 \
--url=ssh://git@ssh.dev.azure.com/v3/org/project/repository \ --url=ssh://git@ssh.dev.azure.com/v3/<org>/<project>/<repository> \
--branch=master \ --branch=master \
--interval=1m --interval=1m
``` ```
@@ -328,6 +351,21 @@ If you don't specify the SSH algorithm, then `flux` will generate an RSA 2048 bi
(e.g. `ssh.dev.azure.com:v3`). (e.g. `ssh.dev.azure.com:v3`).
Use the [RFC 3986 compatible syntax](https://tools.ietf.org/html/rfc3986#section-3) instead: `ssh.dev.azure.com/v3`. Use the [RFC 3986 compatible syntax](https://tools.ietf.org/html/rfc3986#section-3) instead: `ssh.dev.azure.com/v3`.
If you wish to use Git over HTTPS, then generated a personal access token and supply it as the password:
```sh
flux create source git flux-system \
--git-implementation=libgit2 \
--url=https://dev.azure.com/<org>/<project>/_git/<repository> \
--branch=master \
--username=git \
--password=token \
--interval=1m
```
Please consult the [Azure DevOps documentation](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page)
on how to generate personal access tokens for Git repositories.
If your Git server supports basic auth, you can set the URL to HTTPS and specify the credentials with: If your Git server supports basic auth, you can set the URL to HTTPS and specify the credentials with:
```sh ```sh
@@ -363,10 +401,11 @@ cd ./clusters/my-cluster/flux-system && kustomize create --autodetect
git add -A && git commit -m "add sync manifests" && git push git add -A && git commit -m "add sync manifests" && git push
``` ```
To upgrade the Flux components to a newer version, run the install command and commit the changes: To upgrade the Flux components to a newer version, download the latest `flux` binary,
run the install command and commit the changes:
```sh ```sh
flux install --version=latest \ flux install \
--export > ./clusters/my-cluster/flux-system/gotk-components.yaml --export > ./clusters/my-cluster/flux-system/gotk-components.yaml
git add -A && git commit -m "update flux" && git push git add -A && git commit -m "update flux" && git push
@@ -467,7 +506,7 @@ Flux will detect the change and will update itself on the production cluster.
For testing purposes you can install Flux without storing its manifests in a Git repository: For testing purposes you can install Flux without storing its manifests in a Git repository:
```sh ```sh
flux install --arch=amd64 flux install
``` ```
Or using kubectl: Or using kubectl:
@@ -575,11 +614,10 @@ kubectl annotate --overwrite gitrepository/flux-system reconcile.fluxcd.io/reque
If you've installed Flux directly on the cluster, then rerun the install command: If you've installed Flux directly on the cluster, then rerun the install command:
```sh ```sh
flux install --version=latest flux install
``` ```
The above command will download the latest manifests from The above command will apply the new manifests on your cluster.
[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`. 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, If you've installed Flux directly on the cluster with kubectl,
@@ -591,11 +629,28 @@ kustomize build https://github.com/fluxcd/flux2/manifests/install?ref=main | kub
## Uninstall ## Uninstall
You can uninstall the Flux components with: You can uninstall Flux with:
```sh ```sh
flux uninstall --crds flux uninstall --namespace=flux-system
``` ```
The above command will delete the custom resources definitions, the The above command performs the following operations:
controllers, and the namespace where they were installed.
- deletes Flux components (deployments and services)
- deletes Flux network policies
- deletes Flux RBAC (service accounts, cluster roles and cluster role bindings)
- removes the Kubernetes finalizers from Flux custom resources
- deletes Flux custom resource definitions and custom resources
- deletes the namespace where Flux was installed
If you've installed Flux in a namespace that you wish to preserve, you
can skip the namespace deletion with:
```sh
flux uninstall --namespace=infra --keep-namespace
```
!!! hint
Note that the `uninstall` command will not remove any Kubernetes objects
or Helm releases that were reconciled on the cluster by Flux.

View File

@@ -54,7 +54,24 @@ If you wish to use your own Prometheus and Grafana instances, then you can impor
!!! hint !!! hint
Note that the toolkit controllers expose the `/metrics` endpoint on port `8080`. Note that the toolkit controllers expose the `/metrics` endpoint on port `8080`.
When using Prometheus Operator you should create `PodMonitor` objects to configure scraping. When using Prometheus Operator you should create a `PodMonitor` object for each controller to configure scraping.
```yaml
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: source-controller
namespace: flux-system
spec:
namespaceSelector:
matchNames:
- flux-system
selector:
matchLabels:
app: source-controller
podMetricsEndpoints:
- port: http-prom
```
## Metrics ## Metrics
@@ -67,7 +84,7 @@ Ready status metrics:
```sh ```sh
gotk_reconcile_condition{kind, name, namespace, type="Ready", status="True"} gotk_reconcile_condition{kind, name, namespace, type="Ready", status="True"}
gotk_reconcile_condition{kind, name, namespace, type="Ready", status="False"} gotk_reconcile_condition{kind, name, namespace, type="Ready", status="False"}
gotk_reconcile_condition{kind, name, namespace, type="Ready", status="Unkown"} gotk_reconcile_condition{kind, name, namespace, type="Ready", status="Unknown"}
gotk_reconcile_condition{kind, name, namespace, type="Ready", status="Deleted"} gotk_reconcile_condition{kind, name, namespace, type="Ready", status="Deleted"}
``` ```

View File

@@ -52,10 +52,10 @@ flux create helmrelease sealed-secrets \
--target-namespace=flux-system \ --target-namespace=flux-system \
--source=HelmRepository/sealed-secrets \ --source=HelmRepository/sealed-secrets \
--chart=sealed-secrets \ --chart=sealed-secrets \
--chart-version="1.10.x" --chart-version="1.13.x"
``` ```
With chart version `1.10.x` we configure helm-controller to automatically upgrade the release With chart version `1.13.x` we configure helm-controller to automatically upgrade the release
when a new chart patch version is fetched by source-controller. when a new chart patch version is fetched by source-controller.
At startup, the sealed-secrets controller generates a 4096-bit RSA key pair and At startup, the sealed-secrets controller generates a 4096-bit RSA key pair and
@@ -81,7 +81,7 @@ Generate a Kubernetes secret manifest with kubectl:
kubectl -n default create secret generic basic-auth \ kubectl -n default create secret generic basic-auth \
--from-literal=user=admin \ --from-literal=user=admin \
--from-literal=password=change-me \ --from-literal=password=change-me \
--dry-run \ --dry-run=client \
-o yaml > basic-auth.yaml -o yaml > basic-auth.yaml
``` ```
@@ -141,7 +141,7 @@ spec:
sourceRef: sourceRef:
kind: HelmRepository kind: HelmRepository
name: stable name: stable
version: "1.10.x" version: "1.13.x"
interval: 1h0m0s interval: 1h0m0s
releaseName: sealed-secrets releaseName: sealed-secrets
targetNamespace: flux-system targetNamespace: flux-system

View File

@@ -0,0 +1,157 @@
<!-- -*- fill-column: 100 -*- -->
# How to make sortable image tags to use with automation
Flux v2 does not support selecting the lastest image by build time. Obtaining the build time needs
the container config for each image, and fetching that is subject to strict rate limiting by image
registries (e.g., by [DockerHub][dockerhub-rates]).
This guide explains how to construct image tags so that the most recent image has the tag that comes
last in alphabetical or numerical order. The technique suggested is to put a timestamp or serial
number in each image tag.
## Formats and alternatives
The important properties for sorting are that the parts of the timestamp go from most significant to
least (e.g., the year down to the second). For numbers it is best to use numerical order, since this
will work with values of different width (e.g., '12' sorts after '2').
Image tags are often shown in user interfaces, so readability matters. Here is an example of a
readable timestamp that will sort well:
```bash
$ # date and time (remember ':' is not allowed in a tag)
$ date +%F.%H%M%S
2021-01-28.133158
```
You can use a timestamp that sorts as a number, like [Unix
time](https://en.wikipedia.org/wiki/Unix_time):
```
$ # seconds since Jan 1 1970
$ date +%s
1611840548
```
Alternatively, you can use a serial number as part of the tag. Some CI platforms will provide a
build number in an environment variable, but that may not be reliable to use as a serial number --
check the platform documentation.
A commit count can be a reasonable stand-in for a serial number, if you build an image per commit
and you don't rewrite the branch in question:
```bash
$ # commits in branch
$ git --rev-list --count HEAD
1504
```
Beware: this will not give a useful number if you have a shallow clone.
### Other things to include in the image tag
It is also handy to quickly trace an image to the branch and commit of its source code. Including
the branch also means you can filter for images from a particular branch.
A useful tag format is
<branch>-<sha1>-<timestamp>
The branch and tag will usually be made available in a CI platform as environment variables. See
- [CircleCI's built-in variables `CIRCLE_BRANCH` and `CIRCLE_SHA1`][circle-ci-env]
- [GitHub Actions' `GITHUB_REF` and `GITHUB_SHA`][github-actions-env]
- [Travis CI's `TRAVIS_BRANCH` and `TRAVIS_COMMIT`][travis-env].
## Example of a build process with timestamp tagging
Here is an example of a [GitHub Actions job][gha-syntax] that creates a "build ID" with the git
branch, SHA1, and a timestamp, and uses it as a tag when building an image:
```yaml
jobs:
build-push:
env:
IMAGE: org/my-app
runs-on: ubuntu-latest
steps:
- name: Generate build ID
id: prep
run: |
branch=${GITHUB_REF##*/}
sha=${GITHUB_SHA::8}
ts=$(date +%s)
echo "::set-output name=BUILD_ID::${branch}-${sha}-${ts}"
# These are prerequisites for the docker build step
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and publish container image with tag
uses: docker/build-push-action@v2
with:
push: true
context: .
file: ./Dockerfile
tags: |
${{ env.IMAGE }}:${{ steps.prep.outputs.BUILD_ID }}
```
## Using in an `ImagePolicy` object
When creating an `ImagePolicy` object, you will need to extract just the timestamp part of the tag,
using the `tagFilter` field. You can filter for a particular branch to restrict images to only those
built from that branch.
Here is an example that filters for only images built from `main` branch, and selects the most
recent according the timestamp (created with `date +%s`):
```
apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImagePolicy
metadata:
name: image-repo-policy
namespace: flux-system
spec:
imageRepositoryRef:
name: image-repo
filterTags:
pattern: '^main-[a-f0-9]+-(?P<ts>[0-9]+)'
extract: '$ts'
policy:
numerical:
order: asc
```
If you don't care about the branch, that part can be a wildcard in the pattern:
```
apiVersion: image.toolkit.fluxcd.io/v1alpha1
kind: ImagePolicy
metadata:
name: image-repo-policy
namespace: flux-system
spec:
imageRepositoryRef:
name: image-repo
filterTags:
pattern: '^.+-[a-f0-9]+-(?P<ts>[0-9]+)'
extract: '$ts'
policy:
numerical:
order: asc
```
[circle-ci-env]: https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables
[github-actions-env]: https://docs.github.com/en/actions/reference/environment-variables#default-environment-variables
[travis-env]: https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
[dockerhub-rates]: https://docs.docker.com/docker-hub/billing/faq/#pull-rate-limiting-faqs
[gha-syntax]: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions

View File

@@ -68,26 +68,34 @@ Features:
- Dependency management (infrastructure and workloads) - Dependency management (infrastructure and workloads)
- Alerting to external systems (webhook senders) - Alerting to external systems (webhook senders)
- External events handling (webhook receivers) - External events handling (webhook receivers)
- Configuration update automation (automated patching) - Automated container image updates to Git (image scanning and patching)
- Policy-driven validation (OPA, admission controllers) - Policy-driven validation (OPA, Kyverno, admission controllers)
- Seamless integration with Git providers (GitHub, GitLab, Bitbucket) - Seamless integration with Git providers (GitHub, GitLab, Bitbucket)
- Interoperability with workflow providers (GitHub Actions, Tekton, Argo) - Interoperability with workflow providers (GitHub Actions, Tekton, Argo)
- Interoperability with Cluster API (CAPI) providers - Interoperability with Cluster API (CAPI) providers
## Community ## Community
The Flux project is always looking for new contributors and there are a multitude of ways to get involved. Need help or want to contribute? Please see the links below. The Flux project is always looking for
Depending on what you want to do, some of the following bits might be your first steps: new contributors and there are a multitude of ways to get involved.
- Join our upcoming dev meetings ([meeting access and agenda](https://docs.google.com/document/d/1l_M0om0qUEN_NNiGgpqJ2tvsF2iioHkaARDeh6b70B0/view)) - Getting Started?
- Ask questions and add suggestions in our [GitOps Toolkit Discussions](https://github.com/fluxcd/toolkit/discussions) - Look at our [Get Started guide](https://toolkit.fluxcd.io/get-started/) and give us feedback
- Talk to us in the #flux channel on [CNCF Slack](https://slack.cncf.io/) - Need help?
- Join the [planning discussions](https://github.com/fluxcd/flux2/discussions) - First: Ask questions on our [GH Discussions page](https://github.com/fluxcd/flux2/discussions)
- And if you are completely new to Flux v2 and the GitOps Toolkit, take a look at our [Get Started guide](get-started/index.md) and give us feedback - Second: Talk to us in the #flux channel on [CNCF Slack](https://slack.cncf.io/)
- Check out [how to contribute](contributing/index.md) to the project - Please follow our [Support Guidelines](https://fluxcd.io/support/)
(in short: be nice, be respectful of volunteers' time, understand that maintainers and
contributors cannot respond to all DMs, and keep discussions in the public #flux channel as much as possible).
- Have feature proposals or want to contribute?
- Propose features on our [GH Discussions page](https://github.com/fluxcd/flux2/discussions)
- Join our upcoming dev meetings ([meeting access and agenda](https://docs.google.com/document/d/1l_M0om0qUEN_NNiGgpqJ2tvsF2iioHkaARDeh6b70B0/view))
- [Join the flux-dev mailing list](https://lists.cncf.io/g/cncf-flux-dev).
- Check out [how to contribute](contributing/index.md) to the project
### Events ### Events
Check out our **[events calendar](https://fluxcd.io/community/#talks)**, both with upcoming talks you can attend or past events videos you can watch. Check out our **[events calendar](https://fluxcd.io/community/#talks)**,
both with upcoming talks you can attend or past events videos you can watch.
We look forward to seeing you with us! We look forward to seeing you with us!

View File

@@ -130,7 +130,7 @@ Upgrade procedure:
`fluxcd/flux2`: `fluxcd/flux2`:
1. Update the `github.com/fluxcd/*-controller/api` version in `flux2/go.mod` (automated with [GitHub Actions](../../.github/workflows/update.yml)) 1. Update the `github.com/fluxcd/*-controller/api` version in `flux2/go.mod` (automated with [GitHub Actions](../../.github/workflows/update.yaml))
1. Update the `github.com/fluxcd/pkg/*` version in `flux2/go.mod` 1. Update the `github.com/fluxcd/pkg/*` version in `flux2/go.mod`
1. Update the `k8s.io/*` and `github.com/fluxcd/pkg/runtime` version in `flux2/go.mod` 1. Update the `k8s.io/*` and `github.com/fluxcd/pkg/runtime` version in `flux2/go.mod`

View File

@@ -1,15 +1,49 @@
# Roadmap # Roadmap
In our planning discussions we identified broad three areas of work: !!! hint "Production readiness"
The Flux custom resource definitions which are at `v1beta1` and `v2beta1`
and their controllers are considered stable and production ready.
Going forward, breaking changes to the beta CRDs will be accompanied by a conversion mechanism.
The following components (included by default in [flux bootstrap](../guides/installation.md#bootstrap))
are considered production ready:
- [source-controller](../components/source)
- [kustomize-controller](../components/kustomize)
- [notification-controller](../components/notification)
- [helm-controller](../components/helm)
The following GitOps Toolkit APIs are considered production ready:
- `source.toolkit.fluxcd.io/v1beta1`
- `kustomize.toolkit.fluxcd.io/v1beta1`
- `notification.toolkit.fluxcd.io/v1beta1`
- `helm.toolkit.fluxcd.io/v2beta1`
## The road to Flux v2 GA
In our planning discussions we have identified these possible areas of work,
this list is subject to change while we gather feedback:
- Stabilize the image automation APIs
* Review the spec of `ImageRepository`, `ImagePolicy` and `ImageUpdateAutomation`
* Promote the image automation APIs to `v1beta1`
* Include the image automation controllers in the default components list
- Improve the documentation
* Gather feedback on the [migration guides](https://github.com/fluxcd/flux2/discussions/413) and address more use-cases
* Incident management and troubleshooting guides
* Cloud specific guides (AWS, Azure, Google Cloud, more?)
* Consolidate the docs under [fluxcd.io](https://fluxcd.io) website
## The road to Flux v1 feature parity
In our planning discussions we identified three areas of work:
- Feature parity with Flux v1 in read-only mode - Feature parity with Flux v1 in read-only mode
- Feature parity with the image-update functionality in Flux v1 - Feature parity with the image-update functionality in Flux v1
- Feature parity with Helm Operator v1 - Feature parity with Helm Operator v1
All of the above will constitute "Flux v2".
## The road to Flux v2
### Flux read-only feature parity ### Flux read-only feature parity
[= 100% "100%"] [= 100% "100%"]
@@ -43,12 +77,13 @@ Tasks
- [x] <span style="color:grey">Implement a notification controller for Slack, MS Teams, Discord, Rocket</span> - [x] <span style="color:grey">Implement a notification controller for Slack, MS Teams, Discord, Rocket</span>
- [x] <span style="color:grey">Implement Prometheus metrics in source and kustomize controllers</span> - [x] <span style="color:grey">Implement Prometheus metrics in source and kustomize controllers</span>
- [x] <span style="color:grey">Review the git source and kustomize APIs</span> - [x] <span style="color:grey">Review the git source and kustomize APIs</span>
- [x] <span style="color:grey">Support [bash-style variable substitution](https://toolkit.fluxcd.io/components/kustomize/kustomization/#variable-substitution) as an alternative to `flux.yaml` envsubst/sed usage</span>
- [x] <span style="color:grey">Create a migration guide for `flux.yaml` kustomize users</span> - [x] <span style="color:grey">Create a migration guide for `flux.yaml` kustomize users</span>
- [x] <span style="color:grey">Include support for SOPS</span> - [x] <span style="color:grey">Include support for SOPS</span>
### Flux image update feature parity ### Flux image update feature parity
[= 80% "80%"] [= 100% "100%"]
Image automation is available as a prerelease. See [this Image automation is available as a prerelease. See [this
guide](https://toolkit.fluxcd.io/guides/image-update/) for how to guide](https://toolkit.fluxcd.io/guides/image-update/) for how to
@@ -61,6 +96,7 @@ Goals
Non-Goals Non-Goals
- Maintain backwards compatibility with Flux v1 annotations - Maintain backwards compatibility with Flux v1 annotations
- [Order by timestamps found inside image layers](https://github.com/fluxcd/flux2/discussions/802)
Tasks Tasks
@@ -68,16 +104,12 @@ Tasks
- [x] <span style="color:grey">Implement an image scanning controller</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">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> - [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">Design the automation component</span>
- [x] <span style="color:grey">Implement the image scan/patch/push workflow</span> - [x] <span style="color:grey">Implement the image scan/patch/push workflow</span>
- [x] <span style="color:grey">Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)</span> - [x] <span style="color:grey">Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)</span>
- [x] <span style="color:grey">Write a guide for how to use image automation ([guide here](https://toolkit.fluxcd.io/guides/image-update/))</span> - [x] <span style="color:grey">Write a guide for how to use image automation ([guide here](https://toolkit.fluxcd.io/guides/image-update/))</span>
- [ ] Write a migration guide from Flux annotations - [x] <span style="color:grey">ACR/ECR/GCR integration ([guide here](https://toolkit.fluxcd.io/guides/image-update/#imagerepository-cloud-providers-authentication))</span>
- [x] <span style="color:grey">Write a migration guide from Flux v1 annotations ([guide here](https://toolkit.fluxcd.io/guides/flux-v1-automation-migration/))</span>
## The road to Helm Operator v2
### Helm v3 feature parity ### Helm v3 feature parity
@@ -113,4 +145,3 @@ Tasks
- [x] <span style="color:grey">Implement support for referring to an alternative chart values file</span> - [x] <span style="color:grey">Implement support for referring to an alternative chart values file</span>
- [x] <span style="color:grey">Stabilize API</span> - [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> - [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)

27
go.mod
View File

@@ -1,21 +1,22 @@
module github.com/fluxcd/flux2 module github.com/fluxcd/flux2
go 1.15 go 1.16
require ( require (
github.com/blang/semver/v4 v4.0.0 github.com/Masterminds/semver/v3 v3.1.0
github.com/cyphar/filepath-securejoin v0.2.2 github.com/cyphar/filepath-securejoin v0.2.2
github.com/fluxcd/helm-controller/api v0.6.1 github.com/fluxcd/helm-controller/api v0.8.0
github.com/fluxcd/image-automation-controller/api v0.4.0 github.com/fluxcd/image-automation-controller/api v0.6.1
github.com/fluxcd/image-reflector-controller/api v0.5.0 github.com/fluxcd/image-reflector-controller/api v0.7.0
github.com/fluxcd/kustomize-controller/api v0.7.4 github.com/fluxcd/kustomize-controller/api v0.9.1
github.com/fluxcd/notification-controller/api v0.7.1 github.com/fluxcd/notification-controller/api v0.9.0
github.com/fluxcd/pkg/apis/meta v0.7.0 github.com/fluxcd/pkg/apis/meta v0.8.0
github.com/fluxcd/pkg/git v0.3.0 github.com/fluxcd/pkg/git v0.3.0
github.com/fluxcd/pkg/runtime v0.8.0 github.com/fluxcd/pkg/runtime v0.8.3
github.com/fluxcd/pkg/ssh v0.0.5 github.com/fluxcd/pkg/ssh v0.0.5
github.com/fluxcd/pkg/untar v0.0.5 github.com/fluxcd/pkg/untar v0.0.5
github.com/fluxcd/source-controller/api v0.7.4 github.com/fluxcd/pkg/version v0.0.1
github.com/fluxcd/source-controller/api v0.9.0
github.com/google/go-containerregistry v0.2.0 github.com/google/go-containerregistry v0.2.0
github.com/manifoldco/promptui v0.7.0 github.com/manifoldco/promptui v0.7.0
github.com/olekukonko/tablewriter v0.0.4 github.com/olekukonko/tablewriter v0.0.4
@@ -26,8 +27,8 @@ require (
k8s.io/apimachinery v0.20.2 k8s.io/apimachinery v0.20.2
k8s.io/cli-runtime v0.20.2 // indirect k8s.io/cli-runtime v0.20.2 // indirect
k8s.io/client-go v0.20.2 k8s.io/client-go v0.20.2
sigs.k8s.io/cli-utils v0.20.2 sigs.k8s.io/cli-utils v0.22.2
sigs.k8s.io/controller-runtime v0.8.0 sigs.k8s.io/controller-runtime v0.8.2
sigs.k8s.io/kustomize/api v0.7.0 sigs.k8s.io/kustomize/api v0.7.4
sigs.k8s.io/yaml v1.2.0 sigs.k8s.io/yaml v1.2.0
) )

233
go.sum
View File

@@ -6,7 +6,6 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
@@ -34,8 +33,6 @@ github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest v0.10.2 h1:NuSF3gXetiHyUbVdneJMEVyPUYAe5wh+aN08JYAf1tI=
github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ= github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ=
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
@@ -59,18 +56,18 @@ github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocm
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@@ -91,6 +88,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
@@ -107,23 +105,16 @@ github.com/aws/aws-sdk-go v1.28.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM= github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
@@ -136,11 +127,9 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -195,36 +184,37 @@ github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fluxcd/helm-controller/api v0.6.1 h1:vraSNIXdSiqrjpKs53hnr2NMpL0YKGQcEpuILUZ3SlE= github.com/fluxcd/helm-controller/api v0.8.0 h1:1P9GmneUbTVnKeEt/VJpr69YJfhh67EXqCcFhseJ8JA=
github.com/fluxcd/helm-controller/api v0.6.1/go.mod h1:vd4Nt6ZZlDkXwJLkmHRgvNc1bvBPMEIZ0o1qFyEWglo= github.com/fluxcd/helm-controller/api v0.8.0/go.mod h1:cFceNc/mOBa+Qi3NE8NDY2w3FAEectauTm8c10mcBis=
github.com/fluxcd/image-automation-controller/api v0.4.0 h1:WMPVYfPQTLMvoINdoBDp5u26PJLO1EUZLyeQ95yHKgA= github.com/fluxcd/image-automation-controller/api v0.6.1 h1:LgjjNYXrVojfgjit37GA0SDYre3AaDabYzT7L6lWO7I=
github.com/fluxcd/image-automation-controller/api v0.4.0/go.mod h1:lHGxbFJNIwgK32YWx9uNf4WR/Z92Hdrl8cn6TzixfUI= github.com/fluxcd/image-automation-controller/api v0.6.1/go.mod h1:8Q/baOONPrSJFMq7+zxp/t2WGrqVFRUx4HnTrg37pNE=
github.com/fluxcd/image-reflector-controller/api v0.5.0 h1:xzE+Vi5NevR2TkD9OrEYmjBLTYxeQ28VY5mo0x1Q93Q= github.com/fluxcd/image-reflector-controller/api v0.7.0 h1:Mlu9ybrL+MtWcaIex4+FOcYuk+0vA/7bYj8MxVvLR1A=
github.com/fluxcd/image-reflector-controller/api v0.5.0/go.mod h1:MS3mGjZLnzZsfSqVLGbp0WNJr/k8XRFpw4G6ApLFTbc= github.com/fluxcd/image-reflector-controller/api v0.7.0/go.mod h1:KHWknF2xu/GZ4uLSQcAmfONZYjsbwNqyk3OvMQTmMsA=
github.com/fluxcd/kustomize-controller/api v0.7.4 h1:SbcwYh0041yVmODnHtUFNpqtD8HYPoDm1AhL40WkgB8= github.com/fluxcd/kustomize-controller/api v0.9.1 h1:o6cxtLiXUdEeTJMxoeoLdld7hsgf7L4mNO6+i2MD2U8=
github.com/fluxcd/kustomize-controller/api v0.7.4/go.mod h1:GMdry0llCMT50hDcQ70ujmtd3vOXUWCJMTggPpGNM+I= github.com/fluxcd/kustomize-controller/api v0.9.1/go.mod h1:VhUwaSsgrXVgO8Qcx6ZO0isqb5TpDgbyyitCeXYqSM4=
github.com/fluxcd/notification-controller/api v0.7.1 h1:BDeJ172oJN0LKC6VJlu42NkeBCvTKn9cDPVaUo8M1Xs= github.com/fluxcd/notification-controller/api v0.9.0 h1:aEIZu01EHlDH7I8/TyOkvMknlDV8NBNhuZ9cMQ8Kp0Q=
github.com/fluxcd/notification-controller/api v0.7.1/go.mod h1:n1ow7Mxdcedrio5pf/HhBbaVp/4yGTFACPgfCtiyWoU= github.com/fluxcd/notification-controller/api v0.9.0/go.mod h1:nJqSGiecNkJLxuO2KWMu5YUTLaYT/A57854FMm4oX9Q=
github.com/fluxcd/pkg/apis/meta v0.5.0 h1:FaU++mQY0g4sVVl+hG+vk0CXBLbb4EVfRuzs3IjLXvo= github.com/fluxcd/pkg/apis/kustomize v0.0.1 h1:TkA80R0GopRY27VJqzKyS6ifiKIAfwBd7OHXtV3t2CI=
github.com/fluxcd/pkg/apis/meta v0.5.0/go.mod h1:aEUuZIawboAAFLlYz/juVJ7KNmlWbBtJFYkOWWmGUR4= github.com/fluxcd/pkg/apis/kustomize v0.0.1/go.mod h1:JAFPfnRmcrAoG1gNiA8kmEXsnOBuDyZ/F5X4DAQcVV0=
github.com/fluxcd/pkg/apis/meta v0.7.0 h1:5e8gm4OLqjuKWdrOIY5DEEsjcwzyJFK8rCDesJ+V8IY=
github.com/fluxcd/pkg/apis/meta v0.7.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po= github.com/fluxcd/pkg/apis/meta v0.7.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po=
github.com/fluxcd/pkg/apis/meta v0.8.0 h1:wqWpUsxhKHB1ZztcvOz+vnyhdKW9cWmjFp8Vci/XOdk=
github.com/fluxcd/pkg/apis/meta v0.8.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po=
github.com/fluxcd/pkg/git v0.3.0 h1:nrKZWZ/ymDevud3Wf1LEieO/QcNPnqz1/MrkZBFcg9o= github.com/fluxcd/pkg/git v0.3.0 h1:nrKZWZ/ymDevud3Wf1LEieO/QcNPnqz1/MrkZBFcg9o=
github.com/fluxcd/pkg/git v0.3.0/go.mod h1:ZwG0iLOqNSyNw6lsPIAO+v6+BqqCXyV+r1Oq6Lm+slg= github.com/fluxcd/pkg/git v0.3.0/go.mod h1:ZwG0iLOqNSyNw6lsPIAO+v6+BqqCXyV+r1Oq6Lm+slg=
github.com/fluxcd/pkg/runtime v0.6.2 h1:sWnSv6AhMY30fexRQ37lv2Q9Rvdu05zbiqMSldw+MjQ= github.com/fluxcd/pkg/runtime v0.8.3 h1:Zjk4fyAfBdBQ4GTokjisab7KyHHczCqKSpJi8+oVrNw=
github.com/fluxcd/pkg/runtime v0.6.2/go.mod h1:RuqYOYCvBJwo4rg83d28WOt2vfSaemuZCVpUagAjWQc= github.com/fluxcd/pkg/runtime v0.8.3/go.mod h1:AM/hMD0mKtRqhKPU7NGDzm+3UXPpdnX8oBlcxLt11AY=
github.com/fluxcd/pkg/runtime v0.8.0 h1:cnSBZJLcXlKgjXpFFFExu+4ZncIxmPgNIx+ErLcCLnA=
github.com/fluxcd/pkg/runtime v0.8.0/go.mod h1:tQwEN+RESjJmtwSSv7I+6bkNM9raIXpGsCjruaIVX6A=
github.com/fluxcd/pkg/ssh v0.0.5 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A= github.com/fluxcd/pkg/ssh v0.0.5 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A=
github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs= github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs=
github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk= github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk=
github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw= github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw=
github.com/fluxcd/source-controller/api v0.7.4 h1:Hy29SUyanKNHbb4AQZo7PqzmTx4y8TfkeO0GqBcb5PE= github.com/fluxcd/pkg/version v0.0.1 h1:/8asQoDXSThz3csiwi4Qo8Zb6blAxLXbtxNgeMJ9bCg=
github.com/fluxcd/source-controller/api v0.7.4/go.mod h1:u2sdc/QDm0tzXHL7mZVj928hc3MMU+4mKCuAQg+94Bk= github.com/fluxcd/pkg/version v0.0.1/go.mod h1:WAF4FEEA9xyhngF8TDxg3UPu5fA1qhEYV8Pmi2Il01Q=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/fluxcd/source-controller/api v0.9.0 h1:ohV8AvmvkUK0N7+YKPIOlMSLaNG0SpFcNLtlmW18xuM=
github.com/fluxcd/source-controller/api v0.9.0/go.mod h1:68+cPuz1G45f0SDRwEfTL419011ffveLIDA9nssLlkU=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@@ -340,11 +330,9 @@ github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -353,7 +341,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -365,7 +352,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
@@ -393,7 +379,6 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
@@ -419,9 +404,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
@@ -429,7 +412,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
@@ -440,13 +422,10 @@ github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
@@ -464,8 +443,6 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.7 h1:8/CAEZt/+F7kR7GevNHulKkUjLht3CPmn7egmhieNKo=
github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs=
github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
@@ -481,7 +458,6 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
@@ -492,7 +468,6 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc= github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc=
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
@@ -561,14 +536,14 @@ github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaa
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@@ -611,23 +586,21 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
@@ -637,6 +610,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk= github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -648,29 +622,21 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA= github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA=
@@ -704,7 +670,6 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -713,7 +678,6 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
@@ -736,7 +700,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -764,7 +727,6 @@ github.com/xanzy/go-gitlab v0.43.0 h1:rpOZQjxVJGW/ch+Jy4j7W4o7BB1mxkXJNVGuplZ7PU
github.com/xanzy/go-gitlab v0.43.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= github.com/xanzy/go-gitlab v0.43.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
@@ -778,7 +740,6 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -790,27 +751,17 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
@@ -857,7 +808,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -866,10 +816,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -894,7 +842,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -908,8 +855,7 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
@@ -929,7 +875,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180117170059-2c42eef0765b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -966,6 +911,7 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -976,18 +922,15 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -995,7 +938,6 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1057,7 +999,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3 h1:DywqrEscRX7O2phNjkT0L6lhHKGBoMLCNX+XcAe7t6s=
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1065,7 +1006,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k=
gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
@@ -1131,7 +1071,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
@@ -1145,7 +1084,6 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@@ -1158,7 +1096,6 @@ gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1167,7 +1104,6 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
@@ -1180,110 +1116,79 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48=
k8s.io/api v0.0.0-20191214185829-ca1d04f8b0d3/go.mod h1:itOjKREfmUTvcjantxOsyYU5mbFsU7qUnyUuRfF5+5M=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY= k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= k8s.io/api v0.18.10/go.mod h1:xWtwPX1v47j5RTncmlMFGCx8b0avh+nP8OgZZ9hjo3M=
k8s.io/api v0.19.4 h1:I+1I4cgJYuCDgiLNjKx7SLmIbwgj9w7N7Zr5vSIdwpo=
k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk=
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw= k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw=
k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8=
k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= k8s.io/apiextensions-apiserver v0.18.10/go.mod h1:XOE93YaGrb8Pa+ro00Jx3fhzRJ7UB0bU37jRTQXpTOM=
k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg=
k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
k8s.io/apiextensions-apiserver v0.20.2 h1:rfrMWQ87lhd8EzQWRnbQ4gXrniL/yTRBgYH1x1+BLlo= k8s.io/apiextensions-apiserver v0.20.2 h1:rfrMWQ87lhd8EzQWRnbQ4gXrniL/yTRBgYH1x1+BLlo=
k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs= k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs=
k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4=
k8s.io/apimachinery v0.0.0-20191214185652-442f8fb2f03a/go.mod h1:Ng1IY8TS7sC44KJxT/WUR6qFRfWwahYYYpNXyYRKOCY=
k8s.io/apimachinery v0.0.0-20191216025728-0ee8b4573e3a/go.mod h1:Ng1IY8TS7sC44KJxT/WUR6qFRfWwahYYYpNXyYRKOCY=
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig= k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.18.10/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
k8s.io/apimachinery v0.19.4 h1:+ZoddM7nbzrDCp0T3SWnyxqf8cbWPT2fkZImoyvHUG0=
k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg= k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg=
k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo=
k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM= k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= k8s.io/apiserver v0.18.10/go.mod h1:N4FaJo9BeSgmtvVByXi4fPSQPRqhvvLMGqswwkddob8=
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA= k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA=
k8s.io/cli-runtime v0.0.0-20191214191754-e6dc6d5c8724/go.mod h1:wzlq80lvjgHW9if6MlE4OIGC86MDKsy5jtl9nxz/IYY= k8s.io/cli-runtime v0.18.10/go.mod h1:8awhtXxYzOsxCrxgMTmR3DkIV8M/Gcu/v1aCIzQKIV4=
k8s.io/cli-runtime v0.17.2 h1:YH4txSplyGudvxjhAJeHEtXc7Tr/16clKGfN076ydGk=
k8s.io/cli-runtime v0.17.2/go.mod h1:aa8t9ziyQdbkuizkNLAw3qe3srSyWh9zlSB7zTqRNPI=
k8s.io/cli-runtime v0.20.2 h1:W0/FHdbApnl9oB7xdG643c/Zaf7TZT+43I+zKxwqvhU= k8s.io/cli-runtime v0.20.2 h1:W0/FHdbApnl9oB7xdG643c/Zaf7TZT+43I+zKxwqvhU=
k8s.io/cli-runtime v0.20.2/go.mod h1:FjH6uIZZZP3XmwrXWeeYCbgxcrD6YXxoAykBaWH0VdM= k8s.io/cli-runtime v0.20.2/go.mod h1:FjH6uIZZZP3XmwrXWeeYCbgxcrD6YXxoAykBaWH0VdM=
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
k8s.io/client-go v0.0.0-20191214190045-a32a6f7a3052/go.mod h1:tAaoc/sYuIL0+njJefSAmE28CIcxyaFV4kbIujBlY2s=
k8s.io/client-go v0.0.0-20191219150334-0b8da7416048/go.mod h1:ZEe8ZASDUAuqVGJ+UN0ka0PfaR+b6a6E1PGsSNZRui8=
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
k8s.io/client-go v0.17.2/go.mod h1:QAzRgsa0C2xl4/eVpeVAZMvikCn8Nm81yqVx3Kk9XYI= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU= k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= k8s.io/client-go v0.18.10/go.mod h1:XBkFAqPrzqfwmGkV5ac+mlgBpWcz5TkhLw2808q8C3c=
k8s.io/client-go v0.19.4 h1:85D3mDNoLF+xqpyE9Dh/OtrJDyJrSRKkHmDXIbEzer8=
k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA=
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ= k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ=
k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE= k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE=
k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs= k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs=
k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE=
k8s.io/code-generator v0.0.0-20191214185510-0b9b3c99f9f2/go.mod h1:BjGKcoq1MRUmcssvHiSxodCco1T6nVIt4YeCT5CMSao=
k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
k8s.io/code-generator v0.18.10/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
k8s.io/code-generator v0.20.2/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= k8s.io/code-generator v0.20.2/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg=
k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
k8s.io/component-base v0.0.0-20191214190519-d868452632e2/go.mod h1:wupxkh1T/oUDqyTtcIjiEfpbmIHGm8By/vqpSKC6z8c=
k8s.io/component-base v0.17.2/go.mod h1:zMPW3g5aH7cHJpKYQ/ZsGMcgbsA/VyhEugF3QT1awLs=
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU= k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= k8s.io/component-base v0.18.10/go.mod h1:ZzFXjzUBHKOcF0mnWkxBI1wDu5t+CV3GxXKKvHZBLf0=
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
k8s.io/component-base v0.20.2 h1:LMmu5I0pLtwjpp5009KLuMGFqSc2S2isGw8t1hpYKLE=
k8s.io/component-base v0.20.2/go.mod h1:pzFtCiwe/ASD0iV7ySMu8SYVJjCapNM9bjvk7ptpKh0= k8s.io/component-base v0.20.2/go.mod h1:pzFtCiwe/ASD0iV7ySMu8SYVJjCapNM9bjvk7ptpKh0=
k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4= k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd/go.mod h1:9ehGcuUGjXVZh0qbYSB0vvofQw2JQe6c6cO0k4wu/Oo= k8s.io/kubectl v0.18.10/go.mod h1:VVVSZir1jxZ2t8q6UGp6c+j5Uo3/bce9gL/Qcf67g08=
k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGPF4on0IyICQE= k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGPF4on0IyICQE=
k8s.io/metrics v0.0.0-20191214191643-6b1944c9f765/go.mod h1:5V7rewilItwK0cz4nomU0b3XCcees2Ka5EBYWS1HBeM= k8s.io/metrics v0.18.10/go.mod h1:7FQ0/pv0J15/kp8s8WvaeU6tz6jzAKk+xh1eHGwiaW8=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g=
k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ=
k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
@@ -1296,34 +1201,26 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/cli-utils v0.20.2 h1:jNMu4ExtvFXlmKqZMDJqySqK55vGtVRqoLht6eIMffw= sigs.k8s.io/cli-utils v0.22.2 h1:xPD02b++uK990/dAg/rM0LKDOb2sTWZPI1v8IZPfCn0=
sigs.k8s.io/cli-utils v0.20.2/go.mod h1:uT5cVxMrOoRplL8umtrJx5R51ZWsIKD7lQfPtot80uA= sigs.k8s.io/cli-utils v0.22.2/go.mod h1:unl8itcwGPqo41QSyksbXTWFbfMqap1o/4oiUxPnQfw=
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo=
sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= sigs.k8s.io/controller-runtime v0.8.2 h1:SBWmI0b3uzMIUD/BIXWNegrCeZmPJ503pOtwxY0LPHM=
sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= sigs.k8s.io/controller-runtime v0.8.2/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU=
sigs.k8s.io/controller-runtime v0.8.0 h1:s0dYdo7lQgJiAf+alP82PRwbz+oAqL3oSyMQ18XRDOc= sigs.k8s.io/kind v0.9.0/go.mod h1:cxKQWwmbtRDzQ+RNKnR6gZG6fjbeTtItp5cGf+ww+1Y=
sigs.k8s.io/controller-runtime v0.8.0/go.mod h1:v9Lbj5oX443uR7GXYY46E0EE2o7k2YxQ58GxVNeXSW4=
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/kustomize/api v0.7.0 h1:djxH9k1izeU1BvdP1i23qqKwhmWu2BuKNEKr/Da7Dpw= sigs.k8s.io/kustomize/api v0.7.4 h1:WyuZ7ZI7U978udBWMFdKlxjTMOmF7BjpQA1BuygyArY=
sigs.k8s.io/kustomize/api v0.7.0/go.mod h1:3TxKEyaxwOIfHmRbQF14hDUSRmVQI0iSn8qDA5zaO/0= sigs.k8s.io/kustomize/api v0.7.4/go.mod h1:HkbVkf2FjT4G1iOFnPVsr013Af5RFD6dEJg/cUIWiM0=
sigs.k8s.io/kustomize/kyaml v0.8.1/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw= sigs.k8s.io/kustomize/kyaml v0.10.4/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg=
sigs.k8s.io/kustomize/kyaml v0.10.3 h1:ARSJUMN/c3k31DYxRfZ+vp/UepUQjg9zCwny7Oj908I= sigs.k8s.io/kustomize/kyaml v0.10.9 h1:n3WNdvPPReRNDxW+XXd2JlyZ8EII721I21D1DBpBVBE=
sigs.k8s.io/kustomize/kyaml v0.10.3/go.mod h1:RA+iCHA2wPCOfv6uG6TfXXWhYsHpgErq/AljxWKuxtg= sigs.k8s.io/kustomize/kyaml v0.10.9/go.mod h1:K9yg1k/HB/6xNOf5VH3LhTo1DK9/5ykSZO5uIv+Y/1k=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -21,7 +21,6 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/fluxcd/flux2/pkg/manifestgen/install"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
@@ -32,8 +31,11 @@ import (
"text/template" "text/template"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiruntime "k8s.io/apimachinery/pkg/runtime" apiruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
@@ -50,7 +52,10 @@ import (
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/fluxcd/pkg/runtime/dependency" "github.com/fluxcd/pkg/runtime/dependency"
"github.com/fluxcd/pkg/version"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/fluxcd/flux2/pkg/manifestgen/install"
) )
type Utils struct { type Utils struct {
@@ -163,8 +168,11 @@ func KubeClient(kubeConfigPath string, kubeContext string) (client.Client, error
} }
scheme := apiruntime.NewScheme() scheme := apiruntime.NewScheme()
_ = apiextensionsv1.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme) _ = corev1.AddToScheme(scheme)
_ = rbacv1.AddToScheme(scheme) _ = rbacv1.AddToScheme(scheme)
_ = appsv1.AddToScheme(scheme)
_ = networkingv1.AddToScheme(scheme)
_ = sourcev1.AddToScheme(scheme) _ = sourcev1.AddToScheme(scheme)
_ = kustomizev1.AddToScheme(scheme) _ = kustomizev1.AddToScheme(scheme)
_ = helmv2.AddToScheme(scheme) _ = helmv2.AddToScheme(scheme)
@@ -197,41 +205,6 @@ func SplitKubeConfigPath(path string) []string {
return strings.Split(path, sep) return strings.Split(path, sep)
} }
func WriteFile(content, filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err = io.WriteString(file, content)
if err != nil {
return err
}
return file.Sync()
}
func CopyFile(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
return out.Close()
}
func ContainsItemString(s []string, e string) bool { func ContainsItemString(s []string, e string) bool {
for _, a := range s { for _, a := range s {
if a == e { if a == e {
@@ -394,23 +367,22 @@ func ValidateComponents(components []string) error {
return nil return nil
} }
// TODO(stefan): move this to fluxcd/pkg // CompatibleVersion returns if the provided binary version is compatible
// taken from: https://github.com/fluxcd/helm-controller/blob/main/internal/util/util.go // with the given target version. At present, this is true if the target
func MergeMaps(a, b map[string]interface{}) map[string]interface{} { // version is equal to the MINOR range of the binary, or if the binary
out := make(map[string]interface{}, len(a)) // version is a prerelease.
for k, v := range a { func CompatibleVersion(binary, target string) bool {
out[k] = v binSv, err := version.ParseVersion(binary)
if err != nil {
return false
} }
for k, v := range b { // Assume prerelease builds are compatible.
if v, ok := v.(map[string]interface{}); ok { if binSv.Prerelease() != "" {
if bv, ok := out[k]; ok { return true
if bv, ok := bv.(map[string]interface{}); ok {
out[k] = MergeMaps(bv, v)
continue
}
}
}
out[k] = v
} }
return out targetSv, err := version.ParseVersion(target)
if err != nil {
return false
}
return binSv.Major() == targetSv.Major() && binSv.Minor() == targetSv.Minor()
} }

View File

@@ -0,0 +1,42 @@
/*
Copyright 2021 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 utils
import "testing"
func TestCompatibleVersion(t *testing.T) {
tests := []struct {
name string
binary string
target string
want bool
}{
{"different major version", "1.1.0", "0.1.0", false},
{"different minor version", "0.1.0", "0.2.0", false},
{"same version", "0.1.0", "0.1.0", true},
{"binary patch version ahead", "0.1.1", "0.1.0", true},
{"target patch version ahead", "0.1.1", "0.1.2", true},
{"prerelease binary", "0.0.0-dev.0", "0.1.0", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := CompatibleVersion(tt.binary, tt.target); got != tt.want {
t.Errorf("CompatibleVersion() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/helm-controller/archive/v0.6.1.zip//helm-controller-0.6.1/config/crd - https://github.com/fluxcd/helm-controller/releases/download/v0.8.0/helm-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/archive/v0.6.1.zip//helm-controller-0.6.1/config/manager - https://github.com/fluxcd/helm-controller/releases/download/v0.8.0/helm-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/image-automation-controller/archive/v0.4.0.zip//image-automation-controller-0.4.0/config/crd - https://github.com/fluxcd/image-automation-controller/releases/download/v0.6.1/image-automation-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/archive/v0.4.0.zip//image-automation-controller-0.4.0/config/manager - https://github.com/fluxcd/image-automation-controller/releases/download/v0.6.1/image-automation-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/image-reflector-controller/archive/v0.5.0.zip//image-reflector-controller-0.5.0/config/crd - https://github.com/fluxcd/image-reflector-controller/releases/download/v0.7.0/image-reflector-controller.crds.yaml
- https://github.com/fluxcd/image-reflector-controller/archive/v0.5.0.zip//image-reflector-controller-0.5.0/config/manager - https://github.com/fluxcd/image-reflector-controller/releases/download/v0.7.0/image-reflector-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/kustomize-controller/archive/v0.7.4.zip//kustomize-controller-0.7.4/config/crd - https://github.com/fluxcd/kustomize-controller/releases/download/v0.9.1/kustomize-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/archive/v0.7.4.zip//kustomize-controller-0.7.4/config/manager - https://github.com/fluxcd/kustomize-controller/releases/download/v0.9.1/kustomize-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/notification-controller/archive/v0.7.1.zip//notification-controller-0.7.1/config/crd - https://github.com/fluxcd/notification-controller/releases/download/v0.9.0/notification-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/archive/v0.7.1.zip//notification-controller-0.7.1/config/manager - https://github.com/fluxcd/notification-controller/releases/download/v0.9.0/notification-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1 apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- https://github.com/fluxcd/source-controller/archive/v0.7.4.zip//source-controller-0.7.4/config/crd - https://github.com/fluxcd/source-controller/releases/download/v0.9.0/source-controller.crds.yaml
- https://github.com/fluxcd/source-controller/archive/v0.7.4.zip//source-controller-0.7.4/config/manager - https://github.com/fluxcd/source-controller/releases/download/v0.9.0/source-controller.deployment.yaml
- account.yaml - account.yaml
patchesJson6902: patchesJson6902:
- target: - target:

View File

@@ -0,0 +1,20 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
app: credentials-sync
resources:
- sync.yaml
vars:
- name: KUBE_SECRET
objref:
kind: ConfigMap
name: credentials-sync
apiVersion: v1
fieldref:
fieldpath: data.KUBE_SECRET
configurations:
- kustomizeconfig.yaml

View File

@@ -0,0 +1,3 @@
varReference:
- path: rules/resourceNames
kind: Role

View File

@@ -0,0 +1,125 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
# Patch this ConfigMap with additional values needed for your cloud
KUBE_SECRET: my-registry-token # does not yet exist -- will be created in the same Namespace
SYNC_PERIOD: "3600" # tokens expire; refresh faster than that
---
# This Deployment frequently fetches registry tokens and applies them as an imagePullSecret.
# It's done as a 1-replica Deployment rather than a CronJob, because CronJob scheduling can
# block cluster bootstraps and cold-reboots from obtaining registry tokens for a considerable time.
# This deployment will immediately fetch a token, which reduces latency for working image updates.
apiVersion: apps/v1
kind: Deployment
metadata:
name: credentials-sync
namespace: flux-system
spec:
replicas: 1
strategy:
type: Recreate
template:
spec:
serviceAccount: credentials-sync
containers:
- image: busybox # override this with a cloud-specific image
name: sync
envFrom:
- configMapRef:
name: credentials-sync
env:
- name: RECONCILE_SH # override this env var with a shell function in a kustomize patch
value: |-
reconcile() {
echo reconciling...
}
command:
- bash
- -ceu
- |-
# template reconcile() into the script
# env var is expanded by k8s before the pod starts
$(RECONCILE_SH)
apply-secret() {
/kbin/kubectl create secret docker-registry "${1}" \
--docker-server="${2}" \
--docker-username="${3}" \
--docker-password="${4}" \
--dry-run=client -o=yaml \
| grep -v "creationTimestamp:" \
| /kbin/kubectl apply -f -
}
pause_loop() {
sleep "${SYNC_PERIOD:-3600}" || true
}
graceful_exit() {
echo "Trapped signal -- $(date)"
job_ids="$(
jobs \
| grep "pause_loop" \
| cut -d] -f1 \
| tr [ %
)"
# shellcheck disable=SC2086
if [ "${job_ids}" ]; then
kill ${job_ids}
fi
wait
echo "Graceful exit -- $(date)"
}
trap graceful_exit INT TERM
echo "Loop started (period: ${SYNC_PERIOD} s) -- $(date)"
while true; do
reconcile & wait $!
pause_loop & wait $!
done
resources: {}
# RBAC necessary for our Deployment to apply our imagePullSecret
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: credentials-sync
namespace: flux-system
rules:
- apiGroups: [""]
resources:
- secrets
verbs:
- get
- create
- update
- patch
# # Lock this down to the specific Secret name (Optional)
resourceNames:
- $(KUBE_SECRET) # templated from kustomize vars referencing ConfigMap, also see kustomizeconfig.yaml
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: credentials-sync
namespace: flux-system
subjects:
- kind: ServiceAccount
name: credentials-sync
roleRef:
kind: Role
name: credentials-sync
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: credentials-sync
namespace: flux-system

View File

@@ -0,0 +1,20 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
app: credentials-sync
resources:
- sync.yaml
vars:
- name: KUBE_SECRET
objref:
kind: ConfigMap
name: credentials-sync
apiVersion: v1
fieldref:
fieldpath: data.KUBE_SECRET
configurations:
- kustomizeconfig.yaml

View File

@@ -0,0 +1,3 @@
varReference:
- path: rules/resourceNames
kind: Role

View File

@@ -0,0 +1,101 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
# Patch this ConfigMap with additional values needed for your cloud
KUBE_SECRET: my-registry-token # does not yet exist -- will be created in the same Namespace
---
# This CronJob frequently fetches registry tokens and applies them as an imagePullSecret.
# note: CronJob scheduling can block cluster bootstraps and cold-reboots from obtaining registry tokens for a considerable time.
# To run the job immediately, do `kubectl create job --from=cronjob/credentials-sync -n flux-system credentials-sync-init`
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
suspend: false
schedule: 0 */6 * * *
failedJobsHistoryLimit: 1
successfulJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
serviceAccountName: credentials-sync
restartPolicy: Never
containers:
- image: busybox # override this with a cloud-specific image
name: sync
envFrom:
- configMapRef:
name: credentials-sync
env:
- name: RECONCILE_SH # override this env var with a shell function in a kustomize patch
value: |-
reconcile() {
echo reconciling...
}
command:
- bash
- -ceu
- |-
# template reconcile() into the script
# env var is expanded by k8s before the pod starts
$(RECONCILE_SH)
apply-secret() {
/kbin/kubectl create secret docker-registry "${1}" \
--docker-server="${2}" \
--docker-username="${3}" \
--docker-password="${4}" \
--dry-run=client -o=yaml \
| grep -v "creationTimestamp:" \
| /kbin/kubectl apply -f -
}
reconcile
resources: {}
# RBAC necessary for our Deployment to apply our imagePullSecret
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: credentials-sync
namespace: flux-system
rules:
- apiGroups: [""]
resources:
- secrets
verbs:
- get
- create
- update
- patch
# # Lock this down to the specific Secret name (Optional)
resourceNames:
- $(KUBE_SECRET) # templated from kustomize vars referencing ConfigMap, also see kustomizeconfig.yaml
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: credentials-sync
namespace: flux-system
subjects:
- kind: ServiceAccount
name: credentials-sync
roleRef:
kind: Role
name: credentials-sync
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: credentials-sync
namespace: flux-system

View File

@@ -0,0 +1,52 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
ECR_REGION: us-east-1 # set the region
ECR_REGISTRY: <account id>.dkr.ecr.<region>.amazonaws.com # fill in the account id and region
KUBE_SECRET: ecr-credentials # does not yet exist -- will be created in the same Namespace
# Bind IRSA for the ServiceAccount
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: credentials-sync
namespace: flux-system
annotations:
eks.amazonaws.com/role-arn: <role arn> # set the ARN for your role
# Set the reconcile period
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
schedule: 0 */6 * * * # every 6hrs -- ECR tokens expire every 12 hours; refresh faster than that
## If not using IRSA, set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables
## Store these values in a Secret and load them in the container using envFrom.
## For managing this secret via GitOps, consider using SOPS or SealedSecrets and add that manifest in a resource file for this kustomize build.
## https://toolkit.fluxcd.io/guides/mozilla-sops/
## https://toolkit.fluxcd.io/guides/sealed-secrets/
# ---
# apiVersion: apps/v1
# kind: Deployment
# metadata:
# name: credentials-sync
# namespace: flux-system
# spec:
# template:
# spec:
# containers:
# - name: sync
# envFrom:
# secretRef:
# name: $(ECR_SECRET_NAME) # uncomment the var for this in kustomization.yaml

View File

@@ -0,0 +1,30 @@
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
jobTemplate:
spec:
template:
spec:
initContainers:
- image: bitnami/kubectl
name: copy-kubectl
# it's okay to do this because kubectl is a statically linked binary
command:
- sh
- -ceu
- cp $(which kubectl) /kbin/
resources: {}
volumeMounts:
- name: kbin
mountPath: /kbin
containers:
- name: sync
volumeMounts:
- name: kbin
mountPath: /kbin
volumes:
- name: kbin
emptyDir: {}

View File

@@ -0,0 +1,26 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: ecr-
commonLabels:
app: ecr-credentials-sync
namespace: flux-system
bases:
- ../_base
## If not using IRSA, consider creating the following file via SOPS or SealedSecrets
# - encrypted-secret.yaml
patchesStrategicMerge:
- config-patches.yaml
- kubectl-patch.yaml
- reconcile-patch.yaml
## uncomment if using encrypted-secret.yaml
# vars:
# - name: ECR_SECRET_NAME
# objref:
# kind: Secret
# name: credentials-sync
# apiVersion: v1

View File

@@ -0,0 +1,29 @@
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
jobTemplate:
spec:
template:
spec:
containers:
- name: sync
image: mcr.microsoft.com/azure-cli
env:
- name: RECONCILE_SH
value: |-
reconcile() {
echo "Starting ECR token sync -- $(date)"
echo "Logging into ECR: ${ECR_REGION} -- ${ECR_REGISTRY}"
token="$(aws ecr get-login-password --region "${ECR_REGION}")"
user="AWS"
server="${ECR_REGISTRY}"
echo "Creating secret: ${KUBE_SECRET}"
apply-secret "${KUBE_SECRET}" "${token}" "${user}" "${server}"
echo "Finished ECR token sync -- $(date)"
echo
}

View File

@@ -0,0 +1,7 @@
# This is a stub resource patched by config-patches.yaml, so that all config is visible in one file
---
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentity
metadata:
name: credentials-sync # if this is changed, also change in config-patches.yaml
namespace: flux-system

View File

@@ -0,0 +1,41 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
ACR_NAME: my-registry
KUBE_SECRET: acr-my-registry # does not yet exist -- will be created in the same Namespace
# Create an identity in Azure and assign it a role to pull from ACR (note: the identity's resourceGroup should match the desired ACR):
# az identity create -n acr-sync
# az role assignment create --role AcrPull --assignee-object-id "$(az identity show -n acr-sync -o tsv --query principalId)"
# Fetch the clientID and resourceID to configure the AzureIdentity spec below:
# az identity show -n acr-sync -otsv --query clientId
# az identity show -n acr-sync -otsv --query resourceId
---
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentity
metadata:
name: credentials-sync # name must match the stub-resource in az-identity.yaml
namespace: flux-system
spec:
clientID: 82d01fb0-7799-4d9d-92c7-21e7632c0000
resourceID: /subscriptions/873c7e7f-76cd-4805-ae86-b923850b0000/resourcegroups/stealthybox/providers/Microsoft.ManagedIdentity/userAssignedIdentities/acr-sync
type: 0 # user-managed identity
# Set the reconcile period + specify the pod-identity via the aadpodidbinding label
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
schedule: 0 * * * * # ACR tokens expire every 3 hours; refresh faster than that
jobTemplate:
spec:
template:
metadata:
labels:
aadpodidbinding: $(AZ_IDENTITY_NAME) # match the AzureIdentity name

View File

@@ -0,0 +1,30 @@
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
jobTemplate:
spec:
template:
spec:
initContainers:
- image: bitnami/kubectl
name: copy-kubectl
# it's okay to do this because kubectl is a statically linked binary
command:
- sh
- -ceu
- cp $(which kubectl) /kbin/
resources: {}
volumeMounts:
- name: kbin
mountPath: /kbin
containers:
- name: sync
volumeMounts:
- name: kbin
mountPath: /kbin
volumes:
- name: kbin
emptyDir: {}

View File

@@ -0,0 +1,28 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: acr-
commonLabels:
app: acr-credentials-sync
namespace: flux-system
bases:
- ../_base
resources:
- az-identity.yaml
patchesStrategicMerge:
- config-patches.yaml
- kubectl-patch.yaml
- reconcile-patch.yaml
vars:
- name: AZ_IDENTITY_NAME
objref:
kind: AzureIdentity
name: credentials-sync
apiVersion: aadpodidentity.k8s.io/v1
configurations:
- kustomizeconfig.yaml

View File

@@ -0,0 +1,3 @@
varReference:
- path: spec/jobTemplate/spec/template/metadata/labels
kind: Deployment

View File

@@ -0,0 +1,37 @@
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
jobTemplate:
spec:
template:
spec:
containers:
- name: sync
image: mcr.microsoft.com/azure-cli
env:
- name: RECONCILE_SH
value: |-
reconcile() {
echo "Starting ACR token sync -- $(date)"
echo "Logging into Azure"
az login --identity
echo "Logging into ACR: ${ACR_NAME}"
output="$(az acr login --expose-token -o=tsv -n "${ACR_NAME}")"
read token server <<< "${output}"
user="00000000-0000-0000-0000-000000000000"
echo "Creating secret: ${KUBE_SECRET}"
/kbin/kubectl create secret docker-registry "${KUBE_SECRET}" \
--docker-server="${server}" \
--docker-username="00000000-0000-0000-0000-000000000000" \
--docker-password="${token}" \
--dry-run=client -o=yaml \
| grep -v "creationTimestamp:" \
| /kbin/kubectl apply -f -
echo "Finished ACR token sync -- $(date)"
echo
}

View File

@@ -0,0 +1,28 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
GCR_REGISTRY: gcr.io # set the registry
KUBE_SECRET: gcr-credentials # does not yet exist -- will be created in the same Namespace
# Bind to the GCP service-account
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: credentials-sync
namespace: flux-system
annotations:
iam.gke.io/gcp-service-account: <name>@<project-id>.iam.gserviceaccount.com # set the GCP service-account
# Set the reconcile period
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
schedule: 0,30 * * * * # 30m interval -- GCR tokens expire every hour; refresh faster than that

View File

@@ -0,0 +1,15 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: gcr-
commonLabels:
app: gcr-credentials-sync
namespace: flux-system
bases:
- ../_base
patchesStrategicMerge:
- config-patches.yaml
- reconcile-patch.yaml

View File

@@ -0,0 +1,29 @@
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: credentials-sync
namespace: flux-system
spec:
jobTemplate:
spec:
template:
spec:
containers:
- name: sync
image: aws/aws-cli
env:
- name: RECONCILE_SH
value: |-
reconcile() {
echo "Starting GCR token sync -- $(date)"
echo "Logging into ECR: ${ECR_REGION} -- ${ECR_REGISTRY}"
token="$(gcloud auth print-access-token)"
user="oauth2accesstoken "
server="${GCR_REGISTRY}"
echo "Creating secret: ${KUBE_SECRET}"
apply-secret "${KUBE_SECRET}" "${token}" "${user}" "${server}"
echo "Finished GCR token sync -- $(date)"
echo
}

View File

@@ -0,0 +1,42 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
ECR_REGION: us-east-1 # set the region
ECR_REGISTRY: <account id>.dkr.ecr.<region>.amazonaws.com # fill in the account id and region
KUBE_SECRET: ecr-credentials # does not yet exist -- will be created in the same Namespace
SYNC_PERIOD: "21600" # 6hrs -- ECR tokens expire every 12 hours; refresh faster than that
# Bind IRSA for the ServiceAccount
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: credentials-sync
namespace: flux-system
annotations:
eks.amazonaws.com/role-arn: <role arn> # set the ARN for your role
## If not using IRSA, set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables
## Store these values in a Secret and load them in the container using envFrom.
## For managing this secret via GitOps, consider using SOPS or SealedSecrets and add that manifest in a resource file for this kustomize build.
## https://toolkit.fluxcd.io/guides/mozilla-sops/
## https://toolkit.fluxcd.io/guides/sealed-secrets/
# ---
# apiVersion: apps/v1
# kind: Deployment
# metadata:
# name: credentials-sync
# namespace: flux-system
# spec:
# template:
# spec:
# containers:
# - name: sync
# envFrom:
# secretRef:
# name: $(ECR_SECRET_NAME) # uncomment the var for this in kustomization.yaml

View File

@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: credentials-sync
namespace: flux-system
spec:
template:
spec:
initContainers:
- image: bitnami/kubectl
name: copy-kubectl
# it's okay to do this because kubectl is a statically linked binary
command:
- sh
- -ceu
- cp $(which kubectl) /kbin/
resources: {}
volumeMounts:
- name: kbin
mountPath: /kbin
containers:
- name: sync
volumeMounts:
- name: kbin
mountPath: /kbin
volumes:
- name: kbin
emptyDir: {}

View File

@@ -0,0 +1,26 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: ecr-
commonLabels:
app: ecr-credentials-sync
namespace: flux-system
bases:
- ../_base
## If not using IRSA, consider creating the following file via SOPS or SealedSecrets
# - encrypted-secret.yaml
patchesStrategicMerge:
- config-patches.yaml
- kubectl-patch.yaml
- reconcile-patch.yaml
## uncomment if using encrypted-secret.yaml
# vars:
# - name: ECR_SECRET_NAME
# objref:
# kind: Secret
# name: credentials-sync
# apiVersion: v1

View File

@@ -0,0 +1,28 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: credentials-sync
namespace: flux-system
spec:
template:
spec:
containers:
- name: sync
image: aws/aws-cli
env:
- name: RECONCILE_SH
value: |-
reconcile() {
echo "Starting ECR token sync -- $(date)"
echo "Logging into ECR: ${ECR_REGION} -- ${ECR_REGISTRY}"
token="$(aws ecr get-login-password --region "${ECR_REGION}")"
user="AWS"
server="${ECR_REGISTRY}"
echo "Creating secret: ${KUBE_SECRET}"
apply-secret "${KUBE_SECRET}" "${token}" "${user}" "${server}"
echo "Finished ECR token sync -- $(date)"
echo
}

View File

@@ -0,0 +1,7 @@
# This is a stub resource patched by config-patches.yaml, so that all config is visible in one file
---
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentity
metadata:
name: credentials-sync # if this is changed, also change in config-patches.yaml
namespace: flux-system

View File

@@ -0,0 +1,39 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
ACR_NAME: my-registry
KUBE_SECRET: acr-my-registry # does not yet exist -- will be created in the same Namespace
SYNC_PERIOD: "3600" # ACR tokens expire every 3 hours; refresh faster than that
# Create an identity in Azure and assign it a role to pull from ACR (note: the identity's resourceGroup should match the desired ACR):
# az identity create -n acr-sync
# az role assignment create --role AcrPull --assignee-object-id "$(az identity show -n acr-sync -o tsv --query principalId)"
# Fetch the clientID and resourceID to configure the AzureIdentity spec below:
# az identity show -n acr-sync -otsv --query clientId
# az identity show -n acr-sync -otsv --query resourceId
---
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentity
metadata:
name: credentials-sync # name must match the stub-resource in az-identity.yaml
namespace: flux-system
spec:
clientID: 82d01fb0-7799-4d9d-92c7-21e7632c0000
resourceID: /subscriptions/873c7e7f-76cd-4805-ae86-b923850b0000/resourcegroups/stealthybox/providers/Microsoft.ManagedIdentity/userAssignedIdentities/acr-sync
type: 0 # user-managed identity
# Specify the pod-identity via the aadpodidbinding label
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: credentials-sync
namespace: flux-system
spec:
template:
metadata:
labels:
aadpodidbinding: $(AZ_IDENTITY_NAME) # match the AzureIdentity name

View File

@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: credentials-sync
namespace: flux-system
spec:
template:
spec:
initContainers:
- image: bitnami/kubectl
name: copy-kubectl
# it's okay to do this because kubectl is a statically linked binary
command:
- sh
- -ceu
- cp $(which kubectl) /kbin/
resources: {}
volumeMounts:
- name: kbin
mountPath: /kbin
containers:
- name: sync
volumeMounts:
- name: kbin
mountPath: /kbin
volumes:
- name: kbin
emptyDir: {}

View File

@@ -0,0 +1,28 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: acr-
commonLabels:
app: acr-credentials-sync
namespace: flux-system
bases:
- ../_base
resources:
- az-identity.yaml
patchesStrategicMerge:
- config-patches.yaml
- kubectl-patch.yaml
- reconcile-patch.yaml
vars:
- name: AZ_IDENTITY_NAME
objref:
kind: AzureIdentity
name: credentials-sync
apiVersion: aadpodidentity.k8s.io/v1
configurations:
- kustomizeconfig.yaml

View File

@@ -0,0 +1,3 @@
varReference:
- path: spec/template/metadata/labels
kind: Deployment

View File

@@ -0,0 +1,30 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: credentials-sync
namespace: flux-system
spec:
template:
spec:
containers:
- name: sync
image: mcr.microsoft.com/azure-cli
env:
- name: RECONCILE_SH
value: |-
reconcile() {
echo "Starting ACR token sync -- $(date)"
echo "Logging into Azure"
az login --identity
echo "Logging into ACR: ${ACR_NAME}"
output="$(az acr login --expose-token -o=tsv -n "${ACR_NAME}")"
read token server <<< "${output}"
user="00000000-0000-0000-0000-000000000000"
echo "Creating secret: ${KUBE_SECRET}"
apply-secret "${KUBE_SECRET}" "${token}" "${user}" "${server}"
echo "Finished ECR token sync -- $(date)"
echo
}

View File

@@ -0,0 +1,20 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: credentials-sync
data:
GCR_REGISTRY: gcr.io # set the registry
KUBE_SECRET: gcr-credentials # does not yet exist -- will be created in the same Namespace
SYNC_PERIOD: "1800" # 30m -- GCR tokens expire every hour; refresh faster than that
# Bind to the GCP service-account
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: credentials-sync
namespace: flux-system
annotations:
iam.gke.io/gcp-service-account: <name>@<project-id>.iam.gserviceaccount.com # set the GCP service-account

View File

@@ -0,0 +1,15 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: gcr-
commonLabels:
app: gcr-credentials-sync
namespace: flux-system
bases:
- ../_base
patchesStrategicMerge:
- config-patches.yaml
- reconcile-patch.yaml

View File

@@ -0,0 +1,28 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: credentials-sync
namespace: flux-system
spec:
template:
spec:
containers:
- name: sync
image: aws/aws-cli
env:
- name: RECONCILE_SH
value: |-
reconcile() {
echo "Starting GCR token sync -- $(date)"
echo "Logging into ECR: ${ECR_REGION} -- ${ECR_REGISTRY}"
token="$(gcloud auth print-access-token)"
user="oauth2accesstoken "
server="${GCR_REGISTRY}"
echo "Creating secret: ${KUBE_SECRET}"
apply-secret "${KUBE_SECRET}" "${token}" "${user}" "${server}"
echo "Finished GCR token sync -- $(date)"
echo
}

70
manifests/scripts/bundle.sh Executable file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Copyright 2020 The Flux authors. All rights reserved.
#
# 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
REPO_ROOT=$(git rev-parse --show-toplevel)
OUT_PATH=${1:-"${REPO_ROOT}/cmd/flux/manifests"}
TAR=${2}
info() {
echo '[INFO] ' "$@"
}
fatal() {
echo '[ERROR] ' "$@" >&2
exit 1
}
build() {
info "building $(basename $2)"
kustomize build "$1" > "$2"
}
if ! [ -x "$(command -v kustomize)" ]; then
fatal 'kustomize is not installed'
fi
rm -rf $OUT_PATH
mkdir -p $OUT_PATH
files=""
info using "$(kustomize version --short)"
# build controllers
for controller in ${REPO_ROOT}/manifests/bases/*/; do
output_path="${OUT_PATH}/$(basename $controller).yaml"
build $controller $output_path
files+=" $(basename $output_path)"
done
# build rbac
rbac_path="${REPO_ROOT}/manifests/rbac"
rbac_output_path="${OUT_PATH}/rbac.yaml"
build $rbac_path $rbac_output_path
files+=" $(basename $rbac_output_path)"
# build policies
policies_path="${REPO_ROOT}/manifests/policies"
policies_output_path="${OUT_PATH}/policies.yaml"
build $policies_path $policies_output_path
files+=" $(basename $policies_output_path)"
# create tarball
if [[ -n $TAR ]];then
info "archiving $TAR"
cd ${OUT_PATH} && tar -czf $TAR $files
fi

View File

@@ -48,6 +48,7 @@ nav:
- Get Started: get-started/index.md - Get Started: get-started/index.md
- Migration: - Migration:
- Migrate from Flux v1: guides/flux-v1-migration.md - Migrate from Flux v1: guides/flux-v1-migration.md
- Migrate from Flux v1 image update automation: guides/flux-v1-automation-migration.md
- Migrate from the Helm Operator: guides/helm-operator-migration.md - Migrate from the Helm Operator: guides/helm-operator-migration.md
- Guides: - Guides:
- Installation: guides/installation.md - Installation: guides/installation.md
@@ -58,6 +59,7 @@ nav:
- Sealed Secrets: guides/sealed-secrets.md - Sealed Secrets: guides/sealed-secrets.md
- Mozilla SOPS: guides/mozilla-sops.md - Mozilla SOPS: guides/mozilla-sops.md
- Automate image updates to Git: guides/image-update.md - Automate image updates to Git: guides/image-update.md
- Sortable image tags to use with automation: guides/sortable-image-tags.md
- Toolkit Components: - Toolkit Components:
- Overview: components/index.md - Overview: components/index.md
- Source Controller: - Source Controller:
@@ -196,6 +198,7 @@ nav:
- Uninstall: cmd/flux_uninstall.md - Uninstall: cmd/flux_uninstall.md
- Dev Guides: - Dev Guides:
- Watching for source changes: dev-guides/source-watcher.md - Watching for source changes: dev-guides/source-watcher.md
- Advanced debugging: dev-guides/debugging.md
- Roadmap: roadmap/index.md - Roadmap: roadmap/index.md
- Contributing: contributing/index.md - Contributing: contributing/index.md
- FAQ: faq/index.md - FAQ: faq/index.md

View File

@@ -18,11 +18,14 @@ package install
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"path" "path"
"strings" "strings"
"time"
securejoin "github.com/cyphar/filepath-securejoin" securejoin "github.com/cyphar/filepath-securejoin"
@@ -32,17 +35,15 @@ import (
// Generate returns the install manifests as a multi-doc YAML. // Generate returns the install manifests as a multi-doc YAML.
// The manifests are built from a GitHub release or from a // The manifests are built from a GitHub release or from a
// Kustomize overlay if the supplied Options.BaseURL is a local path. // Kustomize overlay if the supplied Options.BaseURL is a local path.
func Generate(options Options) (*manifestgen.Manifest, error) { // The manifestsBase should be set to an empty string when Generate is
// called by consumers that don't embed the manifests.
func Generate(options Options, manifestsBase string) (*manifestgen.Manifest, error) {
ctx, cancel := context.WithTimeout(context.Background(), options.Timeout) ctx, cancel := context.WithTimeout(context.Background(), options.Timeout)
defer cancel() defer cancel()
tmpDir, err := ioutil.TempDir("", options.Namespace) var err error
if err != nil {
return nil, fmt.Errorf("temp dir error: %w", err)
}
defer os.RemoveAll(tmpDir)
output, err := securejoin.SecureJoin(tmpDir, options.ManifestFile) output, err := securejoin.SecureJoin(manifestsBase, options.ManifestFile)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -52,15 +53,27 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
return nil, err return nil, err
} }
} else { } else {
if err := fetch(ctx, options.BaseURL, options.Version, tmpDir); err != nil { // download the manifests base from GitHub
if manifestsBase == "" {
manifestsBase, err = ioutil.TempDir("", options.Namespace)
if err != nil {
return nil, fmt.Errorf("temp dir error: %w", err)
}
defer os.RemoveAll(manifestsBase)
output, err = securejoin.SecureJoin(manifestsBase, options.ManifestFile)
if err != nil {
return nil, err
}
if err := fetch(ctx, options.BaseURL, options.Version, manifestsBase); err != nil {
return nil, err
}
}
if err := generate(manifestsBase, options); err != nil {
return nil, err return nil, err
} }
if err := generate(tmpDir, options); err != nil { if err := build(manifestsBase, output); err != nil {
return nil, err
}
if err := build(tmpDir, output); err != nil {
return nil, err return nil, err
} }
} }
@@ -75,3 +88,58 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
Content: string(content), Content: string(content),
}, nil }, nil
} }
// GetLatestVersion calls the GitHub API and returns the latest released version.
func GetLatestVersion() (string, error) {
ghURL := "https://api.github.com/repos/fluxcd/flux2/releases/latest"
c := http.DefaultClient
c.Timeout = 15 * time.Second
res, err := c.Get(ghURL)
if err != nil {
return "", fmt.Errorf("GitHub API call failed: %w", err)
}
if res.Body != nil {
defer res.Body.Close()
}
type meta struct {
Tag string `json:"tag_name"`
}
var m meta
if err := json.NewDecoder(res.Body).Decode(&m); err != nil {
return "", fmt.Errorf("decoding GitHub API response failed: %w", err)
}
return m.Tag, err
}
// ExistingVersion calls the GitHub API to confirm the given version does exist.
func ExistingVersion(version string) (bool, error) {
if !strings.HasPrefix(version, "v") {
version = "v" + version
}
ghURL := fmt.Sprintf("https://api.github.com/repos/fluxcd/flux2/releases/tags/%s", version)
c := http.DefaultClient
c.Timeout = 15 * time.Second
res, err := c.Get(ghURL)
if err != nil {
return false, fmt.Errorf("GitHub API call failed: %w", err)
}
if res.Body != nil {
defer res.Body.Close()
}
switch res.StatusCode {
case http.StatusOK:
return true, nil
case http.StatusNotFound:
return false, nil
default:
return false, fmt.Errorf("GitHub API returned an unexpected status code (%d)", res.StatusCode)
}
}

View File

@@ -24,7 +24,8 @@ import (
func TestGenerate(t *testing.T) { func TestGenerate(t *testing.T) {
opts := MakeDefaultOptions() opts := MakeDefaultOptions()
output, err := Generate(opts) opts.TolerationKeys = []string{"node.kubernetes.io/controllers"}
output, err := Generate(opts, "")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -36,5 +37,9 @@ func TestGenerate(t *testing.T) {
} }
} }
if !strings.Contains(output.Content, opts.TolerationKeys[0]) {
t.Errorf("toleration key '%s' not found", opts.TolerationKeys[0])
}
fmt.Println(output) fmt.Println(output)
} }

View File

@@ -35,6 +35,7 @@ type Options struct {
Timeout time.Duration Timeout time.Duration
TargetPath string TargetPath string
ClusterDomain string ClusterDomain string
TolerationKeys []string
} }
func MakeDefaultOptions() Options { func MakeDefaultOptions() Options {

View File

@@ -137,6 +137,13 @@ spec:
imagePullSecrets: imagePullSecrets:
- name: {{.ImagePullSecret}} - name: {{.ImagePullSecret}}
{{- end }} {{- end }}
{{ if gt (len .TolerationKeys) 0 }}
tolerations:
{{- range $i, $key := .TolerationKeys }}
- key: "{{$key}}"
operator: "Exists"
{{- end }}
{{- end }}
` `
var labelsTmpl = `--- var labelsTmpl = `---