1
0
mirror of synced 2026-03-03 03:46:56 +00:00

Compare commits

...

32 Commits

Author SHA1 Message Date
Hidde Beydals
64e7a857b8 Merge pull request #1164 from fluxcd/update-components
Update toolkit components
2021-03-26 16:55:26 +01:00
fluxcdbot
7da24932ab Update toolkit components
- helm-controller to v0.9.0
  https://github.com/fluxcd/helm-controller/blob/v0.9.0/CHANGELOG.md
- kustomize-controller to v0.10.0
  https://github.com/fluxcd/kustomize-controller/blob/v0.10.0/CHANGELOG.md
- source-controller to v0.10.0
  https://github.com/fluxcd/source-controller/blob/v0.10.0/CHANGELOG.md
- notification-controller to v0.11.0
  https://github.com/fluxcd/notification-controller/blob/v0.11.0/CHANGELOG.md

Signed-off-by: GitHub <noreply@github.com>
2021-03-26 15:41:29 +00:00
Daniel Holbach
1a2ea8407b Merge pull request #1163 from dholbach/fix-cmd-links
Fix cmd links
2021-03-26 16:40:59 +01:00
Daniel Holbach
32f94bab97 fix links
- change links in cli docs to be relative (making mkdocs AND hugo happy)
	- run 'make docs'
	- fix other links

Signed-off-by: Daniel Holbach <daniel@weave.works>
2021-03-26 16:28:33 +01:00
Hidde Beydals
dea4a67639 Merge pull request #1162 from fluxcd/tidy-cmd-docs
Tidy up command descriptions
2021-03-26 10:38:02 +01:00
Hidde Beydals
236ffd1767 Tidy up command descriptions
Rewordings and removal of superfluous newlines.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-03-26 10:20:42 +01:00
Hidde Beydals
1b2ffad2f1 Merge pull request #1157 from fluxcd/create-secret-source-git-pk
Allow supplying PK from file for Git source/secret
2021-03-26 10:02:23 +01:00
Hidde Beydals
4750d0d81c Allow supplying PK from file for Git source/secret
This commit adds support for supplying a path to an existing private
key file to both the `flux create secret git` and `flux create source
git` commands.

If a path is given, any private key generation configuration options
are ignored by the manifest generator. The SSH host will however still
be scanned for server keys.

Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-03-26 09:49:30 +01:00
Hidde Beydals
63a210a0b2 Merge pull request #1149 from SomtochiAma/refactor-cmd 2021-03-25 22:39:46 +01:00
Somtochi Onyekwere
465eaa24d3 Refactor all remaining create, delete, export, get command to use adapter
Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
2021-03-25 21:54:58 +01:00
Hidde Beydals
c23e8c7ee1 Merge pull request #1156 from Legion2/patch-1
Fix CRD deletion instruction in Helm Operator migration docs
2021-03-25 18:41:35 +01:00
Leon Kiefer
974f01cb46 fix crd deletion command in v2 migration docs
Signed-off-by: Leon Kiefer <leon.k97@gmx.de>
2021-03-25 18:27:33 +01:00
Stefan Prodan
16fa9b2753 Merge pull request #1150 from fluxcd/dev-guide-update
Update dev guide to controller-runtime v0.8
2021-03-24 15:15:20 +02:00
Stefan Prodan
9deab1c415 Update dev guide to controller-runtime v0.8
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-03-24 14:59:17 +02:00
Hidde Beydals
7c01eeb115 Merge pull request #1141 from fluxcd/cmd-docs-frontmatter
Add frontmatter to command documentation
2021-03-24 13:53:06 +01:00
Hidde Beydals
998f0c7d53 Add frontmatter to command documentation
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-03-24 13:31:14 +01:00
Hidde Beydals
bd41406aaa Merge pull request #1134 from kingdonb/fixup-azure-doc 2021-03-22 10:23:15 +01:00
Kingdon Barrett
f17801753d Fixup a broken reference and a typo in Azure doc
Signed-off-by: Kingdon Barrett <kingdon@weave.works>
2021-03-21 13:53:27 -04:00
Hidde Beydals
92891fd340 Merge pull request #1128 from jestallin/patch-1 2021-03-20 21:22:04 +01:00
Jim Stallings
aa122455f7 Remove branch switch for image update cmd in guide
Signed-off-by: James Stallings <jstallings@constantcontact.com>
2021-03-20 15:35:31 -04:00
Stefan Prodan
880e70c19c Merge pull request #1122 from fluxcd/aws-sops
Add AWS IAM role binding example to SOPS guide
2021-03-19 12:19:42 +02:00
Stefan Prodan
968f249562 Move GOTK diagram to docs/files
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-03-19 12:02:09 +02:00
Stefan Prodan
bb9f476be2 Fix typo in image automation guide
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-03-19 12:01:33 +02:00
Stefan Prodan
276f43fdeb Add AWS IAM role binding example to SOPS guide
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
2021-03-19 12:01:01 +02:00
Stefan Prodan
150d1c2a5a Merge pull request #1064 from stealthybox/azure
Document Azure + Flux Installs
2021-03-19 10:47:37 +02:00
leigh capili
1bf3814701 Cleanup note sections
Signed-off-by: leigh capili <leigh@null.net>
2021-03-18 12:29:08 -06:00
leigh capili
166181c745 Add Azure Use-Case doc to new section
Signed-off-by: leigh capili <leigh@null.net>
2021-03-18 12:29:07 -06:00
leigh capili
bfff977d41 Improve Azure DevOps install notes
Signed-off-by: leigh capili <leigh@null.net>
2021-03-18 12:29:07 -06:00
leigh capili
787d755261 Document Flux + SOPS + Azure Key Vault (#851)
Signed-off-by: leigh capili <leigh@null.net>
2021-03-18 12:29:04 -06:00
Hidde Beydals
acf7173959 Merge pull request #1119 from anovateam/azure-acr-secret-reconcile-script 2021-03-18 18:35:21 +01:00
Marco Amador
e6132e36ba fix: revert azure patch and fix the order parameters in the function
Signed-off-by: Marco Amador <amador.marco@gmail.com>
2021-03-18 16:59:17 +00:00
Marco Amador
585b97c462 fix: parameter order
Signed-off-by: Marco Amador <amador.marco@gmail.com>
2021-03-18 15:01:58 +00:00
236 changed files with 1823 additions and 1890 deletions

View File

@@ -74,7 +74,7 @@ runtime for Flux v2. The APIs comprise Kubernetes custom resources,
which can be created and updated by a cluster user, or by other which can be created and updated by a cluster user, or by other
automation tooling. automation tooling.
![overview](docs/diagrams/gitops-toolkit.png) ![overview](docs/_files/gitops-toolkit.png)
You can use the toolkit to extend Flux, or to build your own systems You can use the toolkit to extend Flux, or to build your own systems
for continuous delivery -- see [the developer for continuous delivery -- see [the developer

51
cmd/flux/alert.go Normal file
View File

@@ -0,0 +1,51 @@
/*
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 main
import (
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// notificationv1.Alert
var alertType = apiType{
kind: notificationv1.AlertKind,
humanKind: "alert",
}
type alertAdapter struct {
*notificationv1.Alert
}
func (a alertAdapter) asClientObject() client.Object {
return a.Alert
}
// notificationv1.Alert
type alertListAdapter struct {
*notificationv1.AlertList
}
func (a alertListAdapter) asClientList() client.ObjectList {
return a.AlertList
}
func (a alertListAdapter) len() int {
return len(a.AlertList.Items)
}

View File

@@ -0,0 +1,51 @@
/*
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 main
import (
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// notificationv1.Provider
var alertProviderType = apiType{
kind: notificationv1.ProviderKind,
humanKind: "alert provider",
}
type alertProviderAdapter struct {
*notificationv1.Provider
}
func (a alertProviderAdapter) asClientObject() client.Object {
return a.Provider
}
// notificationv1.Provider
type alertProviderListAdapter struct {
*notificationv1.ProviderList
}
func (a alertProviderListAdapter) asClientList() client.ObjectList {
return a.ProviderList
}
func (a alertProviderListAdapter) len() int {
return len(a.ProviderList.Items)
}

View File

@@ -47,27 +47,26 @@ the bootstrap command will perform an upgrade if needed.`,
Example: ` # Create a GitHub personal access token and export it as an env var Example: ` # Create a GitHub personal access token and export it as an env var
export GITHUB_TOKEN=<my-token> export GITHUB_TOKEN=<my-token>
# Run bootstrap for a private repo owned by a GitHub organization # Run bootstrap for a private repository owned by a GitHub organization
flux bootstrap github --owner=<organization> --repository=<repo name> flux bootstrap github --owner=<organization> --repository=<repository name>
# Run bootstrap for a private repo and assign organization teams to it # Run bootstrap for a private repository and assign organization teams to it
flux bootstrap github --owner=<organization> --repository=<repo name> --team=<team1 slug> --team=<team2 slug> flux bootstrap github --owner=<organization> --repository=<repository name> --team=<team1 slug> --team=<team2 slug>
# Run bootstrap for a repository path # Run bootstrap for a repository path
flux bootstrap github --owner=<organization> --repository=<repo name> --path=dev-cluster flux bootstrap github --owner=<organization> --repository=<repository name> --path=dev-cluster
# Run bootstrap for a public repository on a personal account # Run bootstrap for a public repository on a personal account
flux bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true flux bootstrap github --owner=<user> --repository=<repository name> --private=false --personal=true
# Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth # Run bootstrap for a private repository hosted on GitHub Enterprise using SSH auth
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --ssh-hostname=<domain> flux bootstrap github --owner=<organization> --repository=<repository name> --hostname=<domain> --ssh-hostname=<domain>
# Run bootstrap for a private repo hosted on GitHub Enterprise using HTTPS auth # Run bootstrap for a private repository hosted on GitHub Enterprise using HTTPS auth
flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --token-auth flux bootstrap github --owner=<organization> --repository=<repository name> --hostname=<domain> --token-auth
# Run bootstrap for a an existing repository with a branch named main # Run bootstrap for an existing repository with a branch named main
flux bootstrap github --owner=<organization> --repository=<repo name> --branch=main flux bootstrap github --owner=<organization> --repository=<repository name> --branch=main`,
`,
RunE: bootstrapGitHubCmdRun, RunE: bootstrapGitHubCmdRun,
} }
@@ -220,7 +219,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("components are up to date") logger.Successf("components are up to date")
} }
// determine if repo synchronization is working // determine if repository synchronization is working
isInstall := shouldInstallManifests(ctx, kubeClient, rootArgs.namespace) isInstall := shouldInstallManifests(ctx, kubeClient, rootArgs.namespace)
if isInstall { if isInstall {
@@ -281,7 +280,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
// configure repo synchronization // configure repository synchronization
logger.Actionf("generating sync manifests") logger.Actionf("generating sync manifests")
syncManifests, err := generateSyncManifests( syncManifests, err := generateSyncManifests(
repoURL, repoURL,

View File

@@ -49,24 +49,23 @@ the bootstrap command will perform an upgrade if needed.`,
Example: ` # Create a GitLab API token and export it as an env var Example: ` # Create a GitLab API token and export it as an env var
export GITLAB_TOKEN=<my-token> export GITLAB_TOKEN=<my-token>
# Run bootstrap for a private repo using HTTPS token authentication # Run bootstrap for a private repository using HTTPS token authentication
flux bootstrap gitlab --owner=<group> --repository=<repo name> --token-auth flux bootstrap gitlab --owner=<group> --repository=<repository name> --token-auth
# Run bootstrap for a private repo using SSH authentication # Run bootstrap for a private repository using SSH authentication
flux bootstrap gitlab --owner=<group> --repository=<repo name> flux bootstrap gitlab --owner=<group> --repository=<repository name>
# Run bootstrap for a repository path # Run bootstrap for a repository path
flux bootstrap gitlab --owner=<group> --repository=<repo name> --path=dev-cluster flux bootstrap gitlab --owner=<group> --repository=<repository name> --path=dev-cluster
# Run bootstrap for a public repository on a personal account # Run bootstrap for a public repository on a personal account
flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal --token-auth flux bootstrap gitlab --owner=<user> --repository=<repository name> --private=false --personal --token-auth
# Run bootstrap for a private repo hosted on a GitLab server # Run bootstrap for a private repository hosted on a GitLab server
flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain> --token-auth flux bootstrap gitlab --owner=<group> --repository=<repository name> --hostname=<domain> --token-auth
# Run bootstrap for a an existing repository with a branch named main # Run bootstrap for a an existing repository with a branch named main
flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main --token-auth flux bootstrap gitlab --owner=<organization> --repository=<repository name> --branch=main --token-auth`,
`,
RunE: bootstrapGitLabCmdRun, RunE: bootstrapGitLabCmdRun,
} }
@@ -207,7 +206,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("components are up to date") logger.Successf("components are up to date")
} }
// determine if repo synchronization is working // determine if repository synchronization is working
isInstall := shouldInstallManifests(ctx, kubeClient, rootArgs.namespace) isInstall := shouldInstallManifests(ctx, kubeClient, rootArgs.namespace)
if isInstall { if isInstall {
@@ -268,7 +267,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
// configure repo synchronization // configure repository synchronization
logger.Actionf("generating sync manifests") logger.Actionf("generating sync manifests")
syncManifests, err := generateSyncManifests( syncManifests, err := generateSyncManifests(
repoURL, repoURL,

View File

@@ -46,8 +46,7 @@ the local environment is configured correctly and if the installed components ar
flux check --pre flux check --pre
# Run installation checks # Run installation checks
flux check flux check`,
`,
RunE: runCheckCmd, RunE: runCheckCmd,
} }

View File

@@ -32,8 +32,7 @@ var completionBashCmd = &cobra.Command{
To configure your bash shell to load completions for each session add to your bashrc To configure your bash shell to load completions for each session add to your bashrc
# ~/.bashrc or ~/.profile # ~/.bashrc or ~/.profile
command -v flux >/dev/null && . <(flux completion bash) command -v flux >/dev/null && . <(flux completion bash)`,
`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenBashCompletion(os.Stdout) rootCmd.GenBashCompletion(os.Stdout)
}, },

View File

@@ -29,8 +29,7 @@ var completionFishCmd = &cobra.Command{
flux completion fish > ~/.config/fish/completions/flux.fish flux completion fish > ~/.config/fish/completions/flux.fish
See http://fishshell.com/docs/current/index.html#completion-own for more details See http://fishshell.com/docs/current/index.html#completion-own for more details`,
`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenFishCompletion(os.Stdout, true) rootCmd.GenFishCompletion(os.Stdout, true)
}, },

View File

@@ -39,8 +39,7 @@ flux completion >> flux-completion.ps1
Linux: Linux:
cd "${XDG_CONFIG_HOME:-"$HOME/.config/"}/powershell/modules" cd "${XDG_CONFIG_HOME:-"$HOME/.config/"}/powershell/modules"
flux completion >> flux-completions.ps1 flux completion >> flux-completions.ps1`,
`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenPowerShellCompletion(os.Stdout) rootCmd.GenPowerShellCompletion(os.Stdout)
}, },

View File

@@ -40,8 +40,7 @@ echo "${fpath// /\n}" | grep -i completion
flux completion zsh > _flux flux completion zsh > _flux
mv _flux ~/.oh-my-zsh/completions # oh-my-zsh mv _flux ~/.oh-my-zsh/completions # oh-my-zsh
mv _flux ~/.zprezto/modules/completion/external/src/ # zprezto mv _flux ~/.zprezto/modules/completion/external/src/ # zprezto`,
`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
rootCmd.GenZshCompletion(os.Stdout) rootCmd.GenZshCompletion(os.Stdout)
}, },

View File

@@ -43,8 +43,7 @@ var createAlertCmd = &cobra.Command{
--event-severity info \ --event-severity info \
--event-source Kustomization/flux-system \ --event-source Kustomization/flux-system \
--provider-ref slack \ --provider-ref slack \
flux-system flux-system`,
`,
RunE: createAlertCmdRun, RunE: createAlertCmdRun,
} }
@@ -116,7 +115,7 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportAlert(alert) return printExport(exportAlert(&alert))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

View File

@@ -49,8 +49,7 @@ var createAlertProviderCmd = &cobra.Command{
flux create alert-provider github-podinfo \ flux create alert-provider github-podinfo \
--type github \ --type github \
--address https://github.com/stefanprodan/podinfo \ --address https://github.com/stefanprodan/podinfo \
--secret-ref github-token --secret-ref github-token`,
`,
RunE: createAlertProviderCmdRun, RunE: createAlertProviderCmdRun,
} }
@@ -113,7 +112,7 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportAlertProvider(provider) return printExport(exportAlertProvider(&provider))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

View File

@@ -96,8 +96,7 @@ var createHelmReleaseCmd = &cobra.Command{
--source=HelmRepository/podinfo \ --source=HelmRepository/podinfo \
--chart=podinfo \ --chart=podinfo \
--values=./values.yaml \ --values=./values.yaml \
--export > podinfo-release.yaml --export > podinfo-release.yaml`,
`,
RunE: createHelmReleaseCmdRun, RunE: createHelmReleaseCmdRun,
} }
@@ -219,7 +218,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportHelmRelease(helmRelease) return printExport(exportHelmRelease(&helmRelease))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

View File

@@ -17,20 +17,17 @@ limitations under the License.
package main package main
import ( import (
"strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const createImageLong = ` const createImageLong = `The create image sub-commands work with image automation objects; that is,
The create image sub-commands work with image automation objects; that is,
object controlling updates to git based on e.g., new container images object controlling updates to git based on e.g., new container images
being available.` being available.`
var createImageCmd = &cobra.Command{ var createImageCmd = &cobra.Command{
Use: "image", Use: "image",
Short: "Create or update resources dealing with image automation", Short: "Create or update resources dealing with image automation",
Long: strings.TrimSpace(createImageLong), Long: createImageLong,
} }
func init() { func init() {

View File

@@ -50,8 +50,7 @@ the status of the object.`,
--image-ref=podinfo \ --image-ref=podinfo \
--select-numeric=asc \ --select-numeric=asc \
--filter-regex='^main-[a-f0-9]+-(?P<ts>[0-9]+)' \ --filter-regex='^main-[a-f0-9]+-(?P<ts>[0-9]+)' \
--filter-extract='$ts' --filter-extract='$ts'`,
`,
RunE: createImagePolicyRun} RunE: createImagePolicyRun}
type imagePolicyFlags struct { type imagePolicyFlags struct {

View File

@@ -57,8 +57,7 @@ An ImageRepository object specifies an image repository to scan.`,
--cert-file client.crt --key-file client.key --cert-file client.crt --key-file client.key
flux create image repository app-repo \ flux create image repository app-repo \
--cert-secret-ref client-cert \ --cert-secret-ref client-cert \
--image registry.example.com/private/app --interval 5m --image registry.example.com/private/app --interval 5m`,
`,
RunE: createImageRepositoryRun, RunE: createImageRepositoryRun,
} }

View File

@@ -50,8 +50,7 @@ mentioned in YAMLs in a git repository.`,
--push-branch=image-updates \ --push-branch=image-updates \
--author-name=flux \ --author-name=flux \
--author-email=flux@example.com \ --author-email=flux@example.com \
--commit-template="{{range .Updated.Images}}{{println .}}{{end}}" --commit-template="{{range .Updated.Images}}{{println .}}{{end}}"`,
`,
RunE: createImageUpdateRun, RunE: createImageUpdateRun,
} }

View File

@@ -68,8 +68,7 @@ var createKsCmd = &cobra.Command{
flux create kustomization secrets \ flux create kustomization secrets \
--source=Bucket/secrets \ --source=Bucket/secrets \
--prune=true \ --prune=true \
--interval=5m --interval=5m`,
`,
RunE: createKsCmdRun, RunE: createKsCmdRun,
} }
@@ -211,7 +210,7 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportKs(kustomization) return printExport(exportKs(&kustomization))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

View File

@@ -45,8 +45,7 @@ var createReceiverCmd = &cobra.Command{
--event push \ --event push \
--secret-ref webhook-token \ --secret-ref webhook-token \
--resource GitRepository/webapp \ --resource GitRepository/webapp \
--resource HelmRepository/webapp --resource HelmRepository/webapp`,
`,
RunE: createReceiverCmdRun, RunE: createReceiverCmdRun,
} }
@@ -125,7 +124,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportReceiver(receiver) return printExport(exportReceiver(&receiver))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

View File

@@ -34,8 +34,7 @@ import (
var createSecretGitCmd = &cobra.Command{ var createSecretGitCmd = &cobra.Command{
Use: "git [name]", Use: "git [name]",
Short: "Create or update a Kubernetes secret for Git authentication", Short: "Create or update a Kubernetes secret for Git authentication",
Long: ` Long: `The create secret git command generates a Kubernetes secret with Git credentials.
The create secret git command generates a Kubernetes secret with Git credentials.
For Git over SSH, the host and SSH keys are automatically generated and stored in the secret. For Git over SSH, the host and SSH keys are automatically generated and stored in the secret.
For Git over HTTP/S, the provided basic authentication credentials are stored in the secret.`, For Git over HTTP/S, the provided basic authentication credentials are stored in the secret.`,
Example: ` # Create a Git SSH authentication secret using an ECDSA P-521 curve public key Example: ` # Create a Git SSH authentication secret using an ECDSA P-521 curve public key
@@ -45,6 +44,12 @@ For Git over HTTP/S, the provided basic authentication credentials are stored in
--ssh-key-algorithm=ecdsa \ --ssh-key-algorithm=ecdsa \
--ssh-ecdsa-curve=p521 --ssh-ecdsa-curve=p521
# Create a Git SSH authentication secret with a passwordless private key from file
# The public SSH host key will still be gathered from the host
flux create secret git podinfo-auth \
--url=ssh://git@github.com/stefanprodan/podinfo \
--private-key-file=./private.key
# Create a secret for a Git repository using basic authentication # Create a secret for a Git repository using basic authentication
flux create secret git podinfo-auth \ flux create secret git podinfo-auth \
--url=https://github.com/stefanprodan/podinfo \ --url=https://github.com/stefanprodan/podinfo \
@@ -65,19 +70,19 @@ For Git over HTTP/S, the provided basic authentication credentials are stored in
--export > podinfo-auth.yaml --export > podinfo-auth.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' \ sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place podinfo-auth.yaml --in-place podinfo-auth.yaml`,
`,
RunE: createSecretGitCmdRun, RunE: createSecretGitCmdRun,
} }
type secretGitFlags struct { type secretGitFlags struct {
url string url string
username string username string
password string password string
keyAlgorithm flags.PublicKeyAlgorithm keyAlgorithm flags.PublicKeyAlgorithm
rsaBits flags.RSAKeyBits rsaBits flags.RSAKeyBits
ecdsaCurve flags.ECDSACurve ecdsaCurve flags.ECDSACurve
caFile string caFile string
privateKeyFile string
} }
var secretGitArgs = NewSecretGitFlags() var secretGitArgs = NewSecretGitFlags()
@@ -90,6 +95,7 @@ func init() {
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") createSecretGitCmd.Flags().StringVar(&secretGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates")
createSecretGitCmd.Flags().StringVar(&secretGitArgs.privateKeyFile, "private-key-file", "", "path to a passwordless private key file used for authenticating to the Git SSH server")
createSecretCmd.AddCommand(createSecretGitCmd) createSecretCmd.AddCommand(createSecretGitCmd)
} }
@@ -130,6 +136,7 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
switch u.Scheme { switch u.Scheme {
case "ssh": case "ssh":
opts.SSHHostname = u.Host opts.SSHHostname = u.Host
opts.PrivateKeyPath = secretGitArgs.privateKeyFile
opts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(secretGitArgs.keyAlgorithm) opts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(secretGitArgs.keyAlgorithm)
opts.RSAKeyBits = int(secretGitArgs.rsaBits) opts.RSAKeyBits = int(secretGitArgs.rsaBits)
opts.ECDSACurve = secretGitArgs.ecdsaCurve.Curve opts.ECDSACurve = secretGitArgs.ecdsaCurve.Curve

View File

@@ -31,10 +31,8 @@ import (
var createSecretHelmCmd = &cobra.Command{ var createSecretHelmCmd = &cobra.Command{
Use: "helm [name]", Use: "helm [name]",
Short: "Create or update a Kubernetes secret for Helm repository authentication", Short: "Create or update a Kubernetes secret for Helm repository authentication",
Long: ` Long: `The create secret helm command generates a Kubernetes secret with basic authentication credentials.`,
The create secret helm command generates a Kubernetes secret with basic authentication credentials.`, Example: ` # Create a Helm authentication secret on disk and encrypt it with Mozilla SOPS
Example: `
# Create a Helm authentication secret on disk and encrypt it with Mozilla SOPS
flux create secret helm repo-auth \ flux create secret helm repo-auth \
--namespace=my-namespace \ --namespace=my-namespace \
--username=my-username \ --username=my-username \
@@ -44,14 +42,13 @@ The create secret helm command generates a Kubernetes secret with basic authenti
sops --encrypt --encrypted-regex '^(data|stringData)$' \ sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place repo-auth.yaml --in-place repo-auth.yaml
# Create an authentication secret using a custom TLS cert # Create a Helm authentication secret using a custom TLS cert
flux create secret helm repo-auth \ flux create secret helm repo-auth \
--username=username \ --username=username \
--password=password \ --password=password \
--cert-file=./cert.crt \ --cert-file=./cert.crt \
--key-file=./key.crt \ --key-file=./key.crt \
--ca-file=./ca.crt --ca-file=./ca.crt`,
`,
RunE: createSecretHelmCmdRun, RunE: createSecretHelmCmdRun,
} }

View File

@@ -32,10 +32,8 @@ import (
var createSecretTLSCmd = &cobra.Command{ var createSecretTLSCmd = &cobra.Command{
Use: "tls [name]", Use: "tls [name]",
Short: "Create or update a Kubernetes secret with TLS certificates", Short: "Create or update a Kubernetes secret with TLS certificates",
Long: ` Long: `The create secret tls command generates a Kubernetes secret with certificates for use with TLS.`,
The create secret tls command generates a Kubernetes secret with certificates for use with TLS.`, Example: ` # Create a TLS secret on disk and encrypt it with Mozilla SOPS.
Example: `
# Create a TLS secret on disk and encrypt it with Mozilla SOPS.
# Files are expected to be PEM-encoded. # Files are expected to be PEM-encoded.
flux create secret tls certs \ flux create secret tls certs \
--namespace=my-namespace \ --namespace=my-namespace \
@@ -44,8 +42,7 @@ The create secret tls command generates a Kubernetes secret with certificates fo
--export > certs.yaml --export > certs.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' \ sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place certs.yaml --in-place certs.yaml`,
`,
RunE: createSecretTLSCmdRun, RunE: createSecretTLSCmdRun,
} }

View File

@@ -40,10 +40,9 @@ import (
var createSourceBucketCmd = &cobra.Command{ var createSourceBucketCmd = &cobra.Command{
Use: "bucket [name]", Use: "bucket [name]",
Short: "Create or update a Bucket source", Short: "Create or update a Bucket source",
Long: ` Long: `The create source bucket command generates a Bucket resource and waits for it to be downloaded.
The create source bucket command generates a Bucket resource and waits for it to be downloaded.
For Buckets with static authentication, the credentials are stored in a Kubernetes secret.`, For Buckets with static authentication, the credentials are stored in a Kubernetes secret.`,
Example: ` # Create a source from a Buckets using static authentication Example: ` # Create a source for a Bucket using static authentication
flux create source bucket podinfo \ flux create source bucket podinfo \
--bucket-name=podinfo \ --bucket-name=podinfo \
--endpoint=minio.minio.svc.cluster.local:9000 \ --endpoint=minio.minio.svc.cluster.local:9000 \
@@ -52,14 +51,13 @@ For Buckets with static authentication, the credentials are stored in a Kubernet
--secret-key=mysecretkey \ --secret-key=mysecretkey \
--interval=10m --interval=10m
# Create a source from an Amazon S3 Bucket using IAM authentication # Create a source for an Amazon S3 Bucket using IAM authentication
flux create source bucket podinfo \ flux create source bucket podinfo \
--bucket-name=podinfo \ --bucket-name=podinfo \
--provider=aws \ --provider=aws \
--endpoint=s3.amazonaws.com \ --endpoint=s3.amazonaws.com \
--region=us-east-1 \ --region=us-east-1 \
--interval=10m --interval=10m`,
`,
RunE: createSourceBucketCmdRun, RunE: createSourceBucketCmdRun,
} }
@@ -144,7 +142,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportBucket(*bucket) return printExport(exportBucket(bucket))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

View File

@@ -49,19 +49,19 @@ type sourceGitFlags struct {
semver string semver string
username string username string
password string password string
caFile string
keyAlgorithm flags.PublicKeyAlgorithm keyAlgorithm flags.PublicKeyAlgorithm
keyRSABits flags.RSAKeyBits keyRSABits flags.RSAKeyBits
keyECDSACurve flags.ECDSACurve keyECDSACurve flags.ECDSACurve
secretRef string secretRef string
gitImplementation flags.GitImplementation gitImplementation flags.GitImplementation
caFile string
privateKeyFile string
} }
var createSourceGitCmd = &cobra.Command{ var createSourceGitCmd = &cobra.Command{
Use: "git [name]", Use: "git [name]",
Short: "Create or update a GitRepository source", Short: "Create or update a GitRepository source",
Long: ` Long: `The create source git command generates a GitRepository resource and waits for it to sync.
The create source git command generates a GitRepository resource and waits for it to sync.
For Git over SSH, host and SSH keys are automatically generated and stored in a Kubernetes secret. For Git over SSH, host and SSH keys are automatically generated and stored in a Kubernetes secret.
For private Git repositories, the basic authentication credentials are stored in a Kubernetes secret.`, For private Git repositories, the basic authentication credentials are stored in a Kubernetes secret.`,
Example: ` # Create a source from a public Git repository master branch Example: ` # Create a source from a public Git repository master branch
@@ -69,7 +69,7 @@ For private Git repositories, the basic authentication credentials are stored in
--url=https://github.com/stefanprodan/podinfo \ --url=https://github.com/stefanprodan/podinfo \
--branch=master --branch=master
# Create a source from a Git repository pinned to specific git tag # Create a source for a Git repository pinned to specific git tag
flux create source git podinfo \ flux create source git podinfo \
--url=https://github.com/stefanprodan/podinfo \ --url=https://github.com/stefanprodan/podinfo \
--tag="3.2.3" --tag="3.2.3"
@@ -79,12 +79,12 @@ For private Git repositories, the basic authentication credentials are stored in
--url=https://github.com/stefanprodan/podinfo \ --url=https://github.com/stefanprodan/podinfo \
--tag-semver=">=3.2.0 <3.3.0" --tag-semver=">=3.2.0 <3.3.0"
# Create a source from a Git repository using SSH authentication # Create a source for a Git repository using SSH authentication
flux create source git podinfo \ flux create source git podinfo \
--url=ssh://git@github.com/stefanprodan/podinfo \ --url=ssh://git@github.com/stefanprodan/podinfo \
--branch=master --branch=master
# Create a source from a Git repository using SSH authentication and an # Create a source for a Git repository using SSH authentication and an
# ECDSA P-521 curve public key # ECDSA P-521 curve public key
flux create source git podinfo \ flux create source git podinfo \
--url=ssh://git@github.com/stefanprodan/podinfo \ --url=ssh://git@github.com/stefanprodan/podinfo \
@@ -92,12 +92,19 @@ For private Git repositories, the basic authentication credentials are stored in
--ssh-key-algorithm=ecdsa \ --ssh-key-algorithm=ecdsa \
--ssh-ecdsa-curve=p521 --ssh-ecdsa-curve=p521
# Create a source from a Git repository using basic authentication # Create a source for a Git repository using SSH authentication and a
# passwordless private key from file
# The public SSH host key will still be gathered from the host
flux create source git podinfo \
--url=ssh://git@github.com/stefanprodan/podinfo \
--branch=master \
--private-key-file=./private.key
# Create a source for a Git repository using basic authentication
flux create source git podinfo \ flux create source git podinfo \
--url=https://github.com/stefanprodan/podinfo \ --url=https://github.com/stefanprodan/podinfo \
--username=username \ --username=username \
--password=password --password=password`,
`,
RunE: createSourceGitCmdRun, RunE: createSourceGitCmdRun,
} }
@@ -116,6 +123,7 @@ func init() {
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.secretRef, "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(&sourceGitArgs.gitImplementation, "git-implementation", sourceGitArgs.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") createSourceGitCmd.Flags().StringVar(&sourceGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates, requires libgit2")
createSourceGitCmd.Flags().StringVar(&sourceGitArgs.privateKeyFile, "private-key-file", "", "path to a passwordless private key file used for authenticating to the Git SSH server")
createSourceCmd.AddCommand(createSourceGitCmd) createSourceCmd.AddCommand(createSourceGitCmd)
} }
@@ -195,7 +203,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportGit(gitRepository) return printExport(exportGit(&gitRepository))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
@@ -216,6 +224,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
switch u.Scheme { switch u.Scheme {
case "ssh": case "ssh":
secretOpts.SSHHostname = u.Host secretOpts.SSHHostname = u.Host
secretOpts.PrivateKeyPath = sourceGitArgs.privateKeyFile
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(sourceGitArgs.keyAlgorithm) secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(sourceGitArgs.keyAlgorithm)
secretOpts.RSAKeyBits = int(sourceGitArgs.keyRSABits) secretOpts.RSAKeyBits = int(sourceGitArgs.keyRSABits)
secretOpts.ECDSACurve = sourceGitArgs.keyECDSACurve.Curve secretOpts.ECDSACurve = sourceGitArgs.keyECDSACurve.Curve

View File

@@ -43,27 +43,25 @@ import (
var createSourceHelmCmd = &cobra.Command{ var createSourceHelmCmd = &cobra.Command{
Use: "helm [name]", Use: "helm [name]",
Short: "Create or update a HelmRepository source", Short: "Create or update a HelmRepository source",
Long: ` Long: `The create source helm command generates a HelmRepository resource and waits for it to fetch the index.
The create source helm command generates a HelmRepository resource and waits for it to fetch the index.
For private Helm repositories, the basic authentication credentials are stored in a Kubernetes secret.`, For private Helm repositories, the basic authentication credentials are stored in a Kubernetes secret.`,
Example: ` # Create a source from a public Helm repository Example: ` # Create a source for a public Helm repository
flux create source helm podinfo \ flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \ --url=https://stefanprodan.github.io/podinfo \
--interval=10m --interval=10m
# Create a source from a Helm repository using basic authentication # Create a source for a Helm repository using basic authentication
flux create source helm podinfo \ flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \ --url=https://stefanprodan.github.io/podinfo \
--username=username \ --username=username \
--password=password --password=password
# Create a source from a Helm repository using TLS authentication # Create a source for a Helm repository using TLS authentication
flux create source helm podinfo \ flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \ --url=https://stefanprodan.github.io/podinfo \
--cert-file=./cert.crt \ --cert-file=./cert.crt \
--key-file=./key.crt \ --key-file=./key.crt \
--ca-file=./ca.crt --ca-file=./ca.crt`,
`,
RunE: createSourceHelmCmdRun, RunE: createSourceHelmCmdRun,
} }
@@ -137,7 +135,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
if createArgs.export { if createArgs.export {
return exportHelmRepository(*helmRepository) return printExport(exportHelmRepository(helmRepository))
} }
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

View File

@@ -37,8 +37,7 @@ import (
var createTenantCmd = &cobra.Command{ var createTenantCmd = &cobra.Command{
Use: "tenant", Use: "tenant",
Short: "Create or update a tenant", Short: "Create or update a tenant",
Long: ` Long: `The create tenant command generates namespaces, service accounts and role bindings to limit the
The create tenant command generates namespaces, service accounts and role bindings to limit the
reconcilers scope to the tenant namespaces.`, reconcilers scope to the tenant namespaces.`,
Example: ` # Create a tenant with access to a namespace Example: ` # Create a tenant with access to a namespace
flux create tenant dev-team \ flux create tenant dev-team \
@@ -49,8 +48,7 @@ reconcilers scope to the tenant namespaces.`,
flux create tenant dev-team \ flux create tenant dev-team \
--with-namespace=frontend \ --with-namespace=frontend \
--with-namespace=backend \ --with-namespace=backend \
--export > dev-team.yaml --export > dev-team.yaml`,
`,
RunE: createTenantCmdRun, RunE: createTenantCmdRun,
} }

View File

@@ -17,15 +17,8 @@ limitations under the License.
package main package main
import ( import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/spf13/cobra"
) )
var deleteAlertCmd = &cobra.Command{ var deleteAlertCmd = &cobra.Command{
@@ -33,56 +26,13 @@ var deleteAlertCmd = &cobra.Command{
Short: "Delete a Alert resource", Short: "Delete a Alert resource",
Long: "The delete alert command removes the given Alert from the cluster.", Long: "The delete alert command removes the given Alert from the cluster.",
Example: ` # Delete an Alert and the Kubernetes resources created by it Example: ` # Delete an Alert and the Kubernetes resources created by it
flux delete alert main flux delete alert main`,
`, RunE: deleteCommand{
RunE: deleteAlertCmdRun, apiType: alertType,
object: universalAdapter{&notificationv1.Alert{}},
}.run,
} }
func init() { func init() {
deleteCmd.AddCommand(deleteAlertCmd) deleteCmd.AddCommand(deleteAlertCmd)
} }
func deleteAlertCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("alert name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alert notificationv1.Alert
err = kubeClient.Get(ctx, namespacedName, &alert)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Alert",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting alert %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &alert)
if err != nil {
return err
}
logger.Successf("alert deleted")
return nil
}

View File

@@ -17,15 +17,8 @@ limitations under the License.
package main package main
import ( import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/spf13/cobra"
) )
var deleteAlertProviderCmd = &cobra.Command{ var deleteAlertProviderCmd = &cobra.Command{
@@ -33,56 +26,13 @@ var deleteAlertProviderCmd = &cobra.Command{
Short: "Delete a Provider resource", Short: "Delete a Provider resource",
Long: "The delete alert-provider command removes the given Provider from the cluster.", Long: "The delete alert-provider command removes the given Provider from the cluster.",
Example: ` # Delete a Provider and the Kubernetes resources created by it Example: ` # Delete a Provider and the Kubernetes resources created by it
flux delete alert-provider slack flux delete alert-provider slack`,
`, RunE: deleteCommand{
RunE: deleteAlertProviderCmdRun, apiType: alertProviderType,
object: universalAdapter{&notificationv1.Provider{}},
}.run,
} }
func init() { func init() {
deleteCmd.AddCommand(deleteAlertProviderCmd) deleteCmd.AddCommand(deleteAlertProviderCmd)
} }
func deleteAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("provider name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alertProvider notificationv1.Provider
err = kubeClient.Get(ctx, namespacedName, &alertProvider)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Provider",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting provider %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &alertProvider)
if err != nil {
return err
}
logger.Successf("provider deleted")
return nil
}

View File

@@ -27,8 +27,7 @@ var deleteHelmReleaseCmd = &cobra.Command{
Short: "Delete a HelmRelease resource", Short: "Delete a HelmRelease resource",
Long: "The delete helmrelease command removes the given HelmRelease from the cluster.", Long: "The delete helmrelease command removes the given HelmRelease from the cluster.",
Example: ` # Delete a Helm release and the Kubernetes resources created by it Example: ` # Delete a Helm release and the Kubernetes resources created by it
flux delete hr podinfo flux delete hr podinfo`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: helmReleaseType, apiType: helmReleaseType,
object: universalAdapter{&helmv2.HelmRelease{}}, object: universalAdapter{&helmv2.HelmRelease{}},

View File

@@ -27,8 +27,7 @@ var deleteImagePolicyCmd = &cobra.Command{
Short: "Delete an ImagePolicy object", Short: "Delete an ImagePolicy object",
Long: "The delete image policy command deletes the given ImagePolicy from the cluster.", Long: "The delete image policy command deletes the given ImagePolicy from the cluster.",
Example: ` # Delete an image policy Example: ` # Delete an image policy
flux delete image policy alpine3.x flux delete image policy alpine3.x`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: imagePolicyType, apiType: imagePolicyType,
object: universalAdapter{&imagev1.ImagePolicy{}}, object: universalAdapter{&imagev1.ImagePolicy{}},

View File

@@ -27,8 +27,7 @@ var deleteImageRepositoryCmd = &cobra.Command{
Short: "Delete an ImageRepository object", Short: "Delete an ImageRepository object",
Long: "The delete image repository command deletes the given ImageRepository from the cluster.", Long: "The delete image repository command deletes the given ImageRepository from the cluster.",
Example: ` # Delete an image repository Example: ` # Delete an image repository
flux delete image repository alpine flux delete image repository alpine`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: imageRepositoryType, apiType: imageRepositoryType,
object: universalAdapter{&imagev1.ImageRepository{}}, object: universalAdapter{&imagev1.ImageRepository{}},

View File

@@ -27,8 +27,7 @@ var deleteImageUpdateCmd = &cobra.Command{
Short: "Delete an ImageUpdateAutomation object", Short: "Delete an ImageUpdateAutomation object",
Long: "The delete image update command deletes the given ImageUpdateAutomation from the cluster.", Long: "The delete image update command deletes the given ImageUpdateAutomation from the cluster.",
Example: ` # Delete an image update automation Example: ` # Delete an image update automation
flux delete image update latest-images flux delete image update latest-images`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: imageUpdateAutomationType, apiType: imageUpdateAutomationType,
object: universalAdapter{&autov1.ImageUpdateAutomation{}}, object: universalAdapter{&autov1.ImageUpdateAutomation{}},

View File

@@ -27,8 +27,7 @@ var deleteKsCmd = &cobra.Command{
Short: "Delete a Kustomization resource", Short: "Delete a Kustomization resource",
Long: "The delete kustomization command deletes the given Kustomization from the cluster.", Long: "The delete kustomization command deletes the given Kustomization from the cluster.",
Example: ` # Delete a kustomization and the Kubernetes resources created by it Example: ` # Delete a kustomization and the Kubernetes resources created by it
flux delete kustomization podinfo flux delete kustomization podinfo`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: kustomizationType, apiType: kustomizationType,
object: universalAdapter{&kustomizev1.Kustomization{}}, object: universalAdapter{&kustomizev1.Kustomization{}},

View File

@@ -17,15 +17,8 @@ limitations under the License.
package main package main
import ( import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/spf13/cobra"
) )
var deleteReceiverCmd = &cobra.Command{ var deleteReceiverCmd = &cobra.Command{
@@ -33,56 +26,13 @@ var deleteReceiverCmd = &cobra.Command{
Short: "Delete a Receiver resource", Short: "Delete a Receiver resource",
Long: "The delete receiver command removes the given Receiver from the cluster.", Long: "The delete receiver command removes the given Receiver from the cluster.",
Example: ` # Delete an Receiver and the Kubernetes resources created by it Example: ` # Delete an Receiver and the Kubernetes resources created by it
flux delete receiver main flux delete receiver main`,
`, RunE: deleteCommand{
RunE: deleteReceiverCmdRun, apiType: receiverType,
object: universalAdapter{&notificationv1.Receiver{}},
}.run,
} }
func init() { func init() {
deleteCmd.AddCommand(deleteReceiverCmd) deleteCmd.AddCommand(deleteReceiverCmd)
} }
func deleteReceiverCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("receiver name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var receiver notificationv1.Receiver
err = kubeClient.Get(ctx, namespacedName, &receiver)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Receiver",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting receiver %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &receiver)
if err != nil {
return err
}
logger.Successf("receiver deleted")
return nil
}

View File

@@ -26,8 +26,7 @@ var deleteSourceBucketCmd = &cobra.Command{
Short: "Delete a Bucket source", Short: "Delete a Bucket source",
Long: "The delete source bucket command deletes the given Bucket from the cluster.", Long: "The delete source bucket command deletes the given Bucket from the cluster.",
Example: ` # Delete a Bucket source Example: ` # Delete a Bucket source
flux delete source bucket podinfo flux delete source bucket podinfo`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: bucketType, apiType: bucketType,
object: universalAdapter{&sourcev1.Bucket{}}, object: universalAdapter{&sourcev1.Bucket{}},

View File

@@ -26,8 +26,7 @@ var deleteSourceGitCmd = &cobra.Command{
Short: "Delete a GitRepository source", Short: "Delete a GitRepository source",
Long: "The delete source git command deletes the given GitRepository from the cluster.", Long: "The delete source git command deletes the given GitRepository from the cluster.",
Example: ` # Delete a Git repository Example: ` # Delete a Git repository
flux delete source git podinfo flux delete source git podinfo`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: gitRepositoryType, apiType: gitRepositoryType,
object: universalAdapter{&sourcev1.GitRepository{}}, object: universalAdapter{&sourcev1.GitRepository{}},

View File

@@ -17,14 +17,8 @@ limitations under the License.
package main package main
import ( import (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
) )
var deleteSourceHelmCmd = &cobra.Command{ var deleteSourceHelmCmd = &cobra.Command{
@@ -32,8 +26,7 @@ var deleteSourceHelmCmd = &cobra.Command{
Short: "Delete a HelmRepository source", Short: "Delete a HelmRepository source",
Long: "The delete source helm command deletes the given HelmRepository from the cluster.", Long: "The delete source helm command deletes the given HelmRepository from the cluster.",
Example: ` # Delete a Helm repository Example: ` # Delete a Helm repository
flux delete source helm podinfo flux delete source helm podinfo`,
`,
RunE: deleteCommand{ RunE: deleteCommand{
apiType: helmRepositoryType, apiType: helmRepositoryType,
object: universalAdapter{&sourcev1.HelmRepository{}}, object: universalAdapter{&sourcev1.HelmRepository{}},
@@ -43,48 +36,3 @@ var deleteSourceHelmCmd = &cobra.Command{
func init() { func init() {
deleteSourceCmd.AddCommand(deleteSourceHelmCmd) deleteSourceCmd.AddCommand(deleteSourceHelmCmd)
} }
func deleteSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var helmRepository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &helmRepository)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this source",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting source %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &helmRepository)
if err != nil {
return err
}
logger.Successf("source deleted")
return nil
}

69
cmd/flux/docgen.go Normal file
View File

@@ -0,0 +1,69 @@
/*
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 main
import (
"fmt"
"path"
"path/filepath"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/cobra/doc"
)
const fmTemplate = `---
title: "%s"
---
`
var (
cmdDocPath string
)
var docgenCmd = &cobra.Command{
Use: "docgen",
Short: "Generate the documentation for the CLI commands.",
Hidden: true,
RunE: docgenCmdRun,
}
func init() {
docgenCmd.Flags().StringVar(&cmdDocPath, "path", "./docs/cmd", "path to write the generated documentation to")
rootCmd.AddCommand(docgenCmd)
}
func docgenCmdRun(cmd *cobra.Command, args []string) error {
err := doc.GenMarkdownTreeCustom(rootCmd, cmdDocPath, frontmatterPrepender, linkHandler)
if err != nil {
return err
}
return nil
}
func frontmatterPrepender(filename string) string {
name := filepath.Base(filename)
base := strings.TrimSuffix(name, path.Ext(name))
title := strings.Replace(base, "_", " ", -1) + " command"
return fmt.Sprintf(fmTemplate, title)
}
func linkHandler(name string) string {
base := strings.TrimSuffix(name, path.Ext(name))
return "../" + strings.ToLower(base) + "/"
}

View File

@@ -20,7 +20,6 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
@@ -86,8 +85,7 @@ func (export exportCommand) run(cmd *cobra.Command, args []string) error {
} }
if export.list.len() == 0 { if export.list.len() == 0 {
logger.Failuref("no objects found in %s namespace", rootArgs.namespace) return fmt.Errorf("no objects found in %s namespace", rootArgs.namespace)
return nil
} }
for i := 0; i < export.list.len(); i++ { for i := 0; i < export.list.len(); i++ {

View File

@@ -17,17 +17,9 @@ limitations under the License.
package main package main
import ( import (
"context" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
) )
var exportAlertCmd = &cobra.Command{ var exportAlertCmd = &cobra.Command{
@@ -38,62 +30,18 @@ var exportAlertCmd = &cobra.Command{
flux export alert --all > alerts.yaml flux export alert --all > alerts.yaml
# Export a Alert # Export a Alert
flux export alert main > main.yaml flux export alert main > main.yaml`,
`, RunE: exportCommand{
RunE: exportAlertCmdRun, object: alertAdapter{&notificationv1.Alert{}},
list: alertListAdapter{&notificationv1.AlertList{}},
}.run,
} }
func init() { func init() {
exportCmd.AddCommand(exportAlertCmd) exportCmd.AddCommand(exportAlertCmd)
} }
func exportAlertCmdRun(cmd *cobra.Command, args []string) error { func exportAlert(alert *notificationv1.Alert) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list notificationv1.AlertList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no alerts found in %s namespace", rootArgs.namespace)
return nil
}
for _, alert := range list.Items {
if err := exportAlert(alert); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alert notificationv1.Alert
err = kubeClient.Get(ctx, namespacedName, &alert)
if err != nil {
return err
}
return exportAlert(alert)
}
return nil
}
func exportAlert(alert notificationv1.Alert) error {
gvk := notificationv1.GroupVersion.WithKind("Alert") gvk := notificationv1.GroupVersion.WithKind("Alert")
export := notificationv1.Alert{ export := notificationv1.Alert{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -109,12 +57,13 @@ func exportAlert(alert notificationv1.Alert) error {
Spec: alert.Spec, Spec: alert.Spec,
} }
data, err := yaml.Marshal(export) return export
if err != nil { }
return err
} func (ex alertAdapter) export() interface{} {
return exportAlert(ex.Alert)
fmt.Println("---") }
fmt.Println(resourceToString(data))
return nil func (ex alertListAdapter) exportItem(i int) interface{} {
return exportAlert(&ex.AlertList.Items[i])
} }

View File

@@ -17,17 +17,9 @@ limitations under the License.
package main package main
import ( import (
"context" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
) )
var exportAlertProviderCmd = &cobra.Command{ var exportAlertProviderCmd = &cobra.Command{
@@ -38,62 +30,18 @@ var exportAlertProviderCmd = &cobra.Command{
flux export alert-provider --all > alert-providers.yaml flux export alert-provider --all > alert-providers.yaml
# Export a Provider # Export a Provider
flux export alert-provider slack > slack.yaml flux export alert-provider slack > slack.yaml`,
`, RunE: exportCommand{
RunE: exportAlertProviderCmdRun, object: alertProviderAdapter{&notificationv1.Provider{}},
list: alertProviderListAdapter{&notificationv1.ProviderList{}},
}.run,
} }
func init() { func init() {
exportCmd.AddCommand(exportAlertProviderCmd) exportCmd.AddCommand(exportAlertProviderCmd)
} }
func exportAlertProviderCmdRun(cmd *cobra.Command, args []string) error { func exportAlertProvider(alertProvider *notificationv1.Provider) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list notificationv1.ProviderList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no alertproviders found in %s namespace", rootArgs.namespace)
return nil
}
for _, alertProvider := range list.Items {
if err := exportAlertProvider(alertProvider); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alertProvider notificationv1.Provider
err = kubeClient.Get(ctx, namespacedName, &alertProvider)
if err != nil {
return err
}
return exportAlertProvider(alertProvider)
}
return nil
}
func exportAlertProvider(alertProvider notificationv1.Provider) error {
gvk := notificationv1.GroupVersion.WithKind("Provider") gvk := notificationv1.GroupVersion.WithKind("Provider")
export := notificationv1.Provider{ export := notificationv1.Provider{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -108,13 +56,13 @@ func exportAlertProvider(alertProvider notificationv1.Provider) error {
}, },
Spec: alertProvider.Spec, Spec: alertProvider.Spec,
} }
return export
data, err := yaml.Marshal(export) }
if err != nil {
return err func (ex alertProviderAdapter) export() interface{} {
} return exportAlertProvider(ex.Provider)
}
fmt.Println("---")
fmt.Println(resourceToString(data)) func (ex alertProviderListAdapter) exportItem(i int) interface{} {
return nil return exportAlertProvider(&ex.ProviderList.Items[i])
} }

View File

@@ -17,17 +17,9 @@ limitations under the License.
package main package main
import ( import (
"context" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
) )
var exportHelmReleaseCmd = &cobra.Command{ var exportHelmReleaseCmd = &cobra.Command{
@@ -39,62 +31,18 @@ var exportHelmReleaseCmd = &cobra.Command{
flux export helmrelease --all > kustomizations.yaml flux export helmrelease --all > kustomizations.yaml
# Export a HelmRelease # Export a HelmRelease
flux export hr my-app > app-release.yaml flux export hr my-app > app-release.yaml`,
`, RunE: exportCommand{
RunE: exportHelmReleaseCmdRun, object: helmReleaseAdapter{&helmv2.HelmRelease{}},
list: helmReleaseListAdapter{&helmv2.HelmReleaseList{}},
}.run,
} }
func init() { func init() {
exportCmd.AddCommand(exportHelmReleaseCmd) exportCmd.AddCommand(exportHelmReleaseCmd)
} }
func exportHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { func exportHelmRelease(helmRelease *helmv2.HelmRelease) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list helmv2.HelmReleaseList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no helmrelease found in %s namespace", rootArgs.namespace)
return nil
}
for _, helmRelease := range list.Items {
if err := exportHelmRelease(helmRelease); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var helmRelease helmv2.HelmRelease
err = kubeClient.Get(ctx, namespacedName, &helmRelease)
if err != nil {
return err
}
return exportHelmRelease(helmRelease)
}
return nil
}
func exportHelmRelease(helmRelease helmv2.HelmRelease) error {
gvk := helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind) gvk := helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)
export := helmv2.HelmRelease{ export := helmv2.HelmRelease{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -109,13 +57,13 @@ func exportHelmRelease(helmRelease helmv2.HelmRelease) error {
}, },
Spec: helmRelease.Spec, Spec: helmRelease.Spec,
} }
return export
data, err := yaml.Marshal(export) }
if err != nil {
return err func (ex helmReleaseAdapter) export() interface{} {
} return exportHelmRelease(ex.HelmRelease)
}
fmt.Println("---")
fmt.Println(resourceToString(data)) func (ex helmReleaseListAdapter) exportItem(i int) interface{} {
return nil return exportHelmRelease(&ex.HelmReleaseList.Items[i])
} }

View File

@@ -31,8 +31,7 @@ var exportImagePolicyCmd = &cobra.Command{
flux export image policy --all > image-policies.yaml flux export image policy --all > image-policies.yaml
# Export a specific policy # Export a specific policy
flux export image policy alpine1x > alpine1x.yaml flux export image policy alpine1x > alpine1x.yaml`,
`,
RunE: exportCommand{ RunE: exportCommand{
object: imagePolicyAdapter{&imagev1.ImagePolicy{}}, object: imagePolicyAdapter{&imagev1.ImagePolicy{}},
list: imagePolicyListAdapter{&imagev1.ImagePolicyList{}}, list: imagePolicyListAdapter{&imagev1.ImagePolicyList{}},

View File

@@ -31,8 +31,7 @@ var exportImageRepositoryCmd = &cobra.Command{
flux export image repository --all > image-repositories.yaml flux export image repository --all > image-repositories.yaml
# Export a specific ImageRepository resource # Export a specific ImageRepository resource
flux export image repository alpine > alpine.yaml flux export image repository alpine > alpine.yaml`,
`,
RunE: exportCommand{ RunE: exportCommand{
object: imageRepositoryAdapter{&imagev1.ImageRepository{}}, object: imageRepositoryAdapter{&imagev1.ImageRepository{}},
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}}, list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},

View File

@@ -31,8 +31,7 @@ var exportImageUpdateCmd = &cobra.Command{
flux export image update --all > updates.yaml flux export image update --all > updates.yaml
# Export a specific automation # Export a specific automation
flux export image update latest-images > latest.yaml flux export image update latest-images > latest.yaml`,
`,
RunE: exportCommand{ RunE: exportCommand{
object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}}, object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}},
list: imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}}, list: imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},

View File

@@ -17,17 +17,9 @@ limitations under the License.
package main package main
import ( import (
"context" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
) )
var exportKsCmd = &cobra.Command{ var exportKsCmd = &cobra.Command{
@@ -39,62 +31,18 @@ var exportKsCmd = &cobra.Command{
flux export kustomization --all > kustomizations.yaml flux export kustomization --all > kustomizations.yaml
# Export a Kustomization # Export a Kustomization
flux export kustomization my-app > kustomization.yaml flux export kustomization my-app > kustomization.yaml`,
`, RunE: exportCommand{
RunE: exportKsCmdRun, object: kustomizationAdapter{&kustomizev1.Kustomization{}},
list: kustomizationListAdapter{&kustomizev1.KustomizationList{}},
}.run,
} }
func init() { func init() {
exportCmd.AddCommand(exportKsCmd) exportCmd.AddCommand(exportKsCmd)
} }
func exportKsCmdRun(cmd *cobra.Command, args []string) error { func exportKs(kustomization *kustomizev1.Kustomization) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("kustomization name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list kustomizev1.KustomizationList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no kustomizations found in %s namespace", rootArgs.namespace)
return nil
}
for _, kustomization := range list.Items {
if err := exportKs(kustomization); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var kustomization kustomizev1.Kustomization
err = kubeClient.Get(ctx, namespacedName, &kustomization)
if err != nil {
return err
}
return exportKs(kustomization)
}
return nil
}
func exportKs(kustomization kustomizev1.Kustomization) error {
gvk := kustomizev1.GroupVersion.WithKind("Kustomization") gvk := kustomizev1.GroupVersion.WithKind("Kustomization")
export := kustomizev1.Kustomization{ export := kustomizev1.Kustomization{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -110,12 +58,13 @@ func exportKs(kustomization kustomizev1.Kustomization) error {
Spec: kustomization.Spec, Spec: kustomization.Spec,
} }
data, err := yaml.Marshal(export) return export
if err != nil { }
return err
} func (ex kustomizationAdapter) export() interface{} {
return exportKs(ex.Kustomization)
fmt.Println("---") }
fmt.Println(resourceToString(data))
return nil func (ex kustomizationListAdapter) exportItem(i int) interface{} {
return exportKs(&ex.KustomizationList.Items[i])
} }

View File

@@ -17,17 +17,9 @@ limitations under the License.
package main package main
import ( import (
"context" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
) )
var exportReceiverCmd = &cobra.Command{ var exportReceiverCmd = &cobra.Command{
@@ -38,62 +30,18 @@ var exportReceiverCmd = &cobra.Command{
flux export receiver --all > receivers.yaml flux export receiver --all > receivers.yaml
# Export a Receiver # Export a Receiver
flux export receiver main > main.yaml flux export receiver main > main.yaml`,
`, RunE: exportCommand{
RunE: exportReceiverCmdRun, list: receiverListAdapter{&notificationv1.ReceiverList{}},
object: receiverAdapter{&notificationv1.Receiver{}},
}.run,
} }
func init() { func init() {
exportCmd.AddCommand(exportReceiverCmd) exportCmd.AddCommand(exportReceiverCmd)
} }
func exportReceiverCmdRun(cmd *cobra.Command, args []string) error { func exportReceiver(receiver *notificationv1.Receiver) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list notificationv1.ReceiverList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no receivers found in %s namespace", rootArgs.namespace)
return nil
}
for _, receiver := range list.Items {
if err := exportReceiver(receiver); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var receiver notificationv1.Receiver
err = kubeClient.Get(ctx, namespacedName, &receiver)
if err != nil {
return err
}
return exportReceiver(receiver)
}
return nil
}
func exportReceiver(receiver notificationv1.Receiver) error {
gvk := notificationv1.GroupVersion.WithKind("Receiver") gvk := notificationv1.GroupVersion.WithKind("Receiver")
export := notificationv1.Receiver{ export := notificationv1.Receiver{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -109,12 +57,13 @@ func exportReceiver(receiver notificationv1.Receiver) error {
Spec: receiver.Spec, Spec: receiver.Spec,
} }
data, err := yaml.Marshal(export) return export
if err != nil { }
return err
} func (ex receiverAdapter) export() interface{} {
return exportReceiver(ex.Receiver)
fmt.Println("---") }
fmt.Println(resourceToString(data))
return nil func (ex receiverListAdapter) exportItem(i int) interface{} {
return exportReceiver(&ex.ReceiverList.Items[i])
} }

133
cmd/flux/export_secret.go Normal file
View File

@@ -0,0 +1,133 @@
/*
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 main
import (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// exportableWithSecret represents a type that you can fetch from the Kubernetes
// API, get a secretRef from the spec, then tidy up for serialising.
type exportableWithSecret interface {
adapter
exportable
secret() *types.NamespacedName
}
// exportableWithSecretList represents a type that has a list of values, each of
// which is exportableWithSecret.
type exportableWithSecretList interface {
listAdapter
exportableList
secretItem(i int) *types.NamespacedName
}
type exportWithSecretCommand struct {
apiType
object exportableWithSecret
list exportableWithSecretList
}
func (export exportWithSecretCommand) run(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if export.list.len() == 0 {
return fmt.Errorf("no objects found in %s namespace", rootArgs.namespace)
}
for i := 0; i < export.list.len(); i++ {
if err = printExport(export.list.exportItem(i)); err != nil {
return err
}
if exportSourceWithCred {
if export.list.secretItem(i) != nil {
namespacedName := *export.list.secretItem(i)
return printSecretCredentials(ctx, kubeClient, namespacedName)
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject())
if err != nil {
return err
}
if err := printExport(export.object.export()); err != nil {
return err
}
if exportSourceWithCred {
if export.object.secret() != nil {
namespacedName := *export.object.secret()
return printSecretCredentials(ctx, kubeClient, namespacedName)
}
}
}
return nil
}
func printSecretCredentials(ctx context.Context, kubeClient client.Client, nsName types.NamespacedName) error {
var cred corev1.Secret
err := kubeClient.Get(ctx, nsName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", nsName.Name, err)
}
exported := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: nsName.Name,
Namespace: nsName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
return printExport(exported)
}

View File

@@ -17,18 +17,10 @@ limitations under the License.
package main package main
import ( import (
"context" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
) )
var exportSourceBucketCmd = &cobra.Command{ var exportSourceBucketCmd = &cobra.Command{
@@ -39,72 +31,18 @@ var exportSourceBucketCmd = &cobra.Command{
flux export source bucket --all > sources.yaml flux export source bucket --all > sources.yaml
# Export a Bucket source including the static credentials # Export a Bucket source including the static credentials
flux export source bucket my-bucket --with-credentials > source.yaml flux export source bucket my-bucket --with-credentials > source.yaml`,
`, RunE: exportWithSecretCommand{
RunE: exportSourceBucketCmdRun, list: bucketListAdapter{&sourcev1.BucketList{}},
object: bucketAdapter{&sourcev1.Bucket{}},
}.run,
} }
func init() { func init() {
exportSourceCmd.AddCommand(exportSourceBucketCmd) exportSourceCmd.AddCommand(exportSourceBucketCmd)
} }
func exportSourceBucketCmdRun(cmd *cobra.Command, args []string) error { func exportBucket(source *sourcev1.Bucket) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list sourcev1.BucketList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil
}
for _, bucket := range list.Items {
if err := exportBucket(bucket); err != nil {
return err
}
if exportSourceWithCred {
if err := exportBucketCredentials(ctx, kubeClient, bucket); err != nil {
return err
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var bucket sourcev1.Bucket
err = kubeClient.Get(ctx, namespacedName, &bucket)
if err != nil {
return err
}
if err := exportBucket(bucket); err != nil {
return err
}
if exportSourceWithCred {
return exportBucketCredentials(ctx, kubeClient, bucket)
}
}
return nil
}
func exportBucket(source sourcev1.Bucket) error {
gvk := sourcev1.GroupVersion.WithKind(sourcev1.BucketKind) gvk := sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)
export := sourcev1.Bucket{ export := sourcev1.Bucket{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -119,49 +57,34 @@ func exportBucket(source sourcev1.Bucket) error {
}, },
Spec: source.Spec, Spec: source.Spec,
} }
return export
data, err := yaml.Marshal(export)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
} }
func exportBucketCredentials(ctx context.Context, kubeClient client.Client, source sourcev1.Bucket) error { func getBucketSecret(source *sourcev1.Bucket) *types.NamespacedName {
if source.Spec.SecretRef != nil { if source.Spec.SecretRef != nil {
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: source.Namespace, Namespace: source.Namespace,
Name: source.Spec.SecretRef.Name, Name: source.Spec.SecretRef.Name,
} }
var cred corev1.Secret
err := kubeClient.Get(ctx, namespacedName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", namespacedName.Name, err)
}
exported := corev1.Secret{ return &namespacedName
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
data, err := yaml.Marshal(exported)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
} }
return nil return nil
} }
func (ex bucketAdapter) secret() *types.NamespacedName {
return getBucketSecret(ex.Bucket)
}
func (ex bucketListAdapter) secretItem(i int) *types.NamespacedName {
return getBucketSecret(&ex.BucketList.Items[i])
}
func (ex bucketAdapter) export() interface{} {
return exportBucket(ex.Bucket)
}
func (ex bucketListAdapter) exportItem(i int) interface{} {
return exportBucket(&ex.BucketList.Items[i])
}

View File

@@ -17,18 +17,10 @@ limitations under the License.
package main package main
import ( import (
"context" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
) )
var exportSourceGitCmd = &cobra.Command{ var exportSourceGitCmd = &cobra.Command{
@@ -39,72 +31,18 @@ var exportSourceGitCmd = &cobra.Command{
flux export source git --all > sources.yaml flux export source git --all > sources.yaml
# Export a GitRepository source including the SSH key pair or basic auth credentials # Export a GitRepository source including the SSH key pair or basic auth credentials
flux export source git my-private-repo --with-credentials > source.yaml flux export source git my-private-repo --with-credentials > source.yaml`,
`, RunE: exportWithSecretCommand{
RunE: exportSourceGitCmdRun, object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
list: gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
}.run,
} }
func init() { func init() {
exportSourceCmd.AddCommand(exportSourceGitCmd) exportSourceCmd.AddCommand(exportSourceGitCmd)
} }
func exportSourceGitCmdRun(cmd *cobra.Command, args []string) error { func exportGit(source *sourcev1.GitRepository) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list sourcev1.GitRepositoryList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil
}
for _, repository := range list.Items {
if err := exportGit(repository); err != nil {
return err
}
if exportSourceWithCred {
if err := exportGitCredentials(ctx, kubeClient, repository); err != nil {
return err
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var repository sourcev1.GitRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
if err := exportGit(repository); err != nil {
return err
}
if exportSourceWithCred {
return exportGitCredentials(ctx, kubeClient, repository)
}
}
return nil
}
func exportGit(source sourcev1.GitRepository) error {
gvk := sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind) gvk := sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)
export := sourcev1.GitRepository{ export := sourcev1.GitRepository{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -120,48 +58,33 @@ func exportGit(source sourcev1.GitRepository) error {
Spec: source.Spec, Spec: source.Spec,
} }
data, err := yaml.Marshal(export) return export
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
} }
func exportGitCredentials(ctx context.Context, kubeClient client.Client, source sourcev1.GitRepository) error { func getGitSecret(source *sourcev1.GitRepository) *types.NamespacedName {
if source.Spec.SecretRef != nil { if source.Spec.SecretRef != nil {
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: source.Namespace, Namespace: source.Namespace,
Name: source.Spec.SecretRef.Name, Name: source.Spec.SecretRef.Name,
} }
var cred corev1.Secret return &namespacedName
err := kubeClient.Get(ctx, namespacedName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", namespacedName.Name, err)
}
exported := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
data, err := yaml.Marshal(exported)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
} }
return nil return nil
} }
func (ex gitRepositoryAdapter) secret() *types.NamespacedName {
return getGitSecret(ex.GitRepository)
}
func (ex gitRepositoryListAdapter) secretItem(i int) *types.NamespacedName {
return getGitSecret(&ex.GitRepositoryList.Items[i])
}
func (ex gitRepositoryAdapter) export() interface{} {
return exportGit(ex.GitRepository)
}
func (ex gitRepositoryListAdapter) exportItem(i int) interface{} {
return exportGit(&ex.GitRepositoryList.Items[i])
}

View File

@@ -17,18 +17,10 @@ limitations under the License.
package main package main
import ( import (
"context" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
) )
var exportSourceHelmCmd = &cobra.Command{ var exportSourceHelmCmd = &cobra.Command{
@@ -39,72 +31,18 @@ var exportSourceHelmCmd = &cobra.Command{
flux export source helm --all > sources.yaml flux export source helm --all > sources.yaml
# Export a HelmRepository source including the basic auth credentials # Export a HelmRepository source including the basic auth credentials
flux export source helm my-private-repo --with-credentials > source.yaml flux export source helm my-private-repo --with-credentials > source.yaml`,
`, RunE: exportWithSecretCommand{
RunE: exportSourceHelmCmdRun, list: helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}},
}.run,
} }
func init() { func init() {
exportSourceCmd.AddCommand(exportSourceHelmCmd) exportSourceCmd.AddCommand(exportSourceHelmCmd)
} }
func exportSourceHelmCmdRun(cmd *cobra.Command, args []string) error { func exportHelmRepository(source *sourcev1.HelmRepository) interface{} {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list sourcev1.HelmRepositoryList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil
}
for _, repository := range list.Items {
if err := exportHelmRepository(repository); err != nil {
return err
}
if exportSourceWithCred {
if err := exportHelmCredentials(ctx, kubeClient, repository); err != nil {
return err
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var repository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
if err := exportHelmRepository(repository); err != nil {
return err
}
if exportSourceWithCred {
return exportHelmCredentials(ctx, kubeClient, repository)
}
}
return nil
}
func exportHelmRepository(source sourcev1.HelmRepository) error {
gvk := sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind) gvk := sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)
export := sourcev1.HelmRepository{ export := sourcev1.HelmRepository{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -119,49 +57,32 @@ func exportHelmRepository(source sourcev1.HelmRepository) error {
}, },
Spec: source.Spec, Spec: source.Spec,
} }
return export
data, err := yaml.Marshal(export)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
} }
func exportHelmCredentials(ctx context.Context, kubeClient client.Client, source sourcev1.HelmRepository) error { func getHelmSecret(source *sourcev1.HelmRepository) *types.NamespacedName {
if source.Spec.SecretRef != nil { if source.Spec.SecretRef != nil {
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: source.Namespace, Namespace: source.Namespace,
Name: source.Spec.SecretRef.Name, Name: source.Spec.SecretRef.Name,
} }
var cred corev1.Secret return &namespacedName
err := kubeClient.Get(ctx, namespacedName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", namespacedName.Name, err)
}
exported := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
data, err := yaml.Marshal(exported)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
} }
return nil return nil
} }
func (ex helmRepositoryAdapter) secret() *types.NamespacedName {
return getHelmSecret(ex.HelmRepository)
}
func (ex helmRepositoryListAdapter) secretItem(i int) *types.NamespacedName {
return getHelmSecret(&ex.HelmRepositoryList.Items[i])
}
func (ex helmRepositoryAdapter) export() interface{} {
return exportHelmRepository(ex.HelmRepository)
}
func (ex helmRepositoryListAdapter) exportItem(i int) interface{} {
return exportHelmRepository(&ex.HelmRepositoryList.Items[i])
}

View File

@@ -17,19 +17,11 @@ limitations under the License.
package main package main
import ( import (
"context"
"os"
"strconv" "strconv"
"strings" "strings"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/fluxcd/pkg/apis/meta" "github.com/spf13/cobra"
) )
var getAlertCmd = &cobra.Command{ var getAlertCmd = &cobra.Command{
@@ -38,66 +30,27 @@ var getAlertCmd = &cobra.Command{
Short: "Get Alert statuses", Short: "Get Alert statuses",
Long: "The get alert command prints the statuses of the resources.", Long: "The get alert command prints the statuses of the resources.",
Example: ` # List all Alerts and their status Example: ` # List all Alerts and their status
flux get alerts flux get alerts`,
`, RunE: getCommand{
RunE: getAlertCmdRun, apiType: alertType,
list: &alertListAdapter{&notificationv1.AlertList{}},
}.run,
} }
func init() { func init() {
getCmd.AddCommand(getAlertCmd) getCmd.AddCommand(getAlertCmd)
} }
func getAlertCmdRun(cmd *cobra.Command, args []string) error { func (s alertListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) item := s.Items[i]
defer cancel() status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), status, msg, strings.Title(strconv.FormatBool(item.Spec.Suspend)))
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext) }
if err != nil {
return err func (s alertListAdapter) headers(includeNamespace bool) []string {
} headers := []string{"Name", "Ready", "Message", "Suspended"}
if includeNamespace {
var listOpts []client.ListOption return append(namespaceHeader, headers...)
if !getArgs.allNamespaces { }
listOpts = append(listOpts, client.InNamespace(rootArgs.namespace)) return headers
}
var list notificationv1.AlertList
err = kubeClient.List(ctx, &list, listOpts...)
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no alerts found in %s namespace", rootArgs.namespace)
return nil
}
header := []string{"Name", "Ready", "Message", "Suspended"}
if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, alert := range list.Items {
row := []string{}
if c := apimeta.FindStatusCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
alert.GetName(),
string(c.Status),
c.Message,
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
}
} else {
row = []string{
alert.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
}
}
if getArgs.allNamespaces {
row = append([]string{alert.Namespace}, row...)
}
rows = append(rows, row)
}
utils.PrintTable(os.Stdout, header, rows)
return nil
} }

View File

@@ -17,17 +17,8 @@ limitations under the License.
package main package main
import ( import (
"context"
"os"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/fluxcd/pkg/apis/meta" "github.com/spf13/cobra"
) )
var getAlertProviderCmd = &cobra.Command{ var getAlertProviderCmd = &cobra.Command{
@@ -36,64 +27,27 @@ var getAlertProviderCmd = &cobra.Command{
Short: "Get Provider statuses", Short: "Get Provider statuses",
Long: "The get alert-provider command prints the statuses of the resources.", Long: "The get alert-provider command prints the statuses of the resources.",
Example: ` # List all Providers and their status Example: ` # List all Providers and their status
flux get alert-providers flux get alert-providers`,
`, RunE: getCommand{
RunE: getAlertProviderCmdRun, apiType: alertProviderType,
list: alertProviderListAdapter{&notificationv1.ProviderList{}},
}.run,
} }
func init() { func init() {
getCmd.AddCommand(getAlertProviderCmd) getCmd.AddCommand(getAlertProviderCmd)
} }
func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error { func (s alertProviderListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) item := s.Items[i]
defer cancel() status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), status, msg)
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext) }
if err != nil {
return err func (s alertProviderListAdapter) headers(includeNamespace bool) []string {
} headers := []string{"Name", "Ready", "Message"}
if includeNamespace {
var listOpts []client.ListOption return append(namespaceHeader, headers...)
if !getArgs.allNamespaces { }
listOpts = append(listOpts, client.InNamespace(rootArgs.namespace)) return headers
}
var list notificationv1.ProviderList
err = kubeClient.List(ctx, &list, listOpts...)
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no providers found in %s namespace", rootArgs.namespace)
return nil
}
header := []string{"Name", "Ready", "Message"}
if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, provider := range list.Items {
row := []string{}
if c := apimeta.FindStatusCondition(provider.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
provider.GetName(),
string(c.Status),
c.Message,
}
} else {
row = []string{
provider.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
}
}
if getArgs.allNamespaces {
row = append([]string{provider.Namespace}, row...)
}
rows = append(rows, row)
}
utils.PrintTable(os.Stdout, header, rows)
return nil
} }

View File

@@ -30,8 +30,7 @@ var getHelmReleaseCmd = &cobra.Command{
Short: "Get HelmRelease statuses", Short: "Get HelmRelease statuses",
Long: "The get helmreleases command prints the statuses of the resources.", Long: "The get helmreleases command prints the statuses of the resources.",
Example: ` # List all Helm releases and their status Example: ` # List all Helm releases and their status
flux get helmreleases flux get helmreleases`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: helmReleaseType, apiType: helmReleaseType,
list: &helmReleaseListAdapter{&helmv2.HelmReleaseList{}}, list: &helmReleaseListAdapter{&helmv2.HelmReleaseList{}},

View File

@@ -30,8 +30,7 @@ var getImageAllCmd = &cobra.Command{
flux get images all --namespace=flux-system flux get images all --namespace=flux-system
# List all image objects in all namespaces # List all image objects in all namespaces
flux get images all --all-namespaces flux get images all --all-namespaces`,
`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
c := getCommand{ c := getCommand{
apiType: imageRepositoryType, apiType: imageRepositoryType,

View File

@@ -30,8 +30,7 @@ var getImagePolicyCmd = &cobra.Command{
flux get image policy flux get image policy
# List image policies from all namespaces # List image policies from all namespaces
flux get image policy --all-namespaces flux get image policy --all-namespaces`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: imagePolicyType, apiType: imagePolicyType,
list: &imagePolicyListAdapter{&imagev1.ImagePolicyList{}}, list: &imagePolicyListAdapter{&imagev1.ImagePolicyList{}},

View File

@@ -34,8 +34,7 @@ var getImageRepositoryCmd = &cobra.Command{
flux get image repository flux get image repository
# List image repositories from all namespaces # List image repositories from all namespaces
flux get image repository --all-namespaces flux get image repository --all-namespaces`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: imageRepositoryType, apiType: imageRepositoryType,
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}}, list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},

View File

@@ -34,8 +34,7 @@ var getImageUpdateCmd = &cobra.Command{
flux get image update flux get image update
# List image update automations from all namespaces # List image update automations from all namespaces
flux get image update --all-namespaces flux get image update --all-namespaces`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: imageUpdateAutomationType, apiType: imageUpdateAutomationType,
list: &imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}}, list: &imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},

View File

@@ -30,8 +30,7 @@ var getKsCmd = &cobra.Command{
Short: "Get Kustomization statuses", Short: "Get Kustomization statuses",
Long: "The get kustomizations command prints the statuses of the resources.", Long: "The get kustomizations command prints the statuses of the resources.",
Example: ` # List all kustomizations and their status Example: ` # List all kustomizations and their status
flux get kustomizations flux get kustomizations`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: kustomizationType, apiType: kustomizationType,
list: &kustomizationListAdapter{&kustomizev1.KustomizationList{}}, list: &kustomizationListAdapter{&kustomizev1.KustomizationList{}},

View File

@@ -17,19 +17,11 @@ limitations under the License.
package main package main
import ( import (
"context"
"os"
"strconv" "strconv"
"strings" "strings"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/fluxcd/pkg/apis/meta" "github.com/spf13/cobra"
) )
var getReceiverCmd = &cobra.Command{ var getReceiverCmd = &cobra.Command{
@@ -38,63 +30,27 @@ var getReceiverCmd = &cobra.Command{
Short: "Get Receiver statuses", Short: "Get Receiver statuses",
Long: "The get receiver command prints the statuses of the resources.", Long: "The get receiver command prints the statuses of the resources.",
Example: ` # List all Receiver and their status Example: ` # List all Receiver and their status
flux get receivers flux get receivers`,
`, RunE: getCommand{
RunE: getReceiverCmdRun, apiType: receiverType,
list: receiverListAdapter{&notificationv1.ReceiverList{}},
}.run,
} }
func init() { func init() {
getCmd.AddCommand(getReceiverCmd) getCmd.AddCommand(getReceiverCmd)
} }
func getReceiverCmdRun(cmd *cobra.Command, args []string) error { func (s receiverListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) item := s.Items[i]
defer cancel() status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), status, msg, strings.Title(strconv.FormatBool(item.Spec.Suspend)))
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext) }
if err != nil {
return err func (s receiverListAdapter) headers(includeNamespace bool) []string {
} headers := []string{"Name", "Ready", "Message", "Suspended"}
if includeNamespace {
var listOpts []client.ListOption return append(namespaceHeader, headers...)
if !getArgs.allNamespaces { }
listOpts = append(listOpts, client.InNamespace(rootArgs.namespace)) return headers
}
var list notificationv1.ReceiverList
err = kubeClient.List(ctx, &list, listOpts...)
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no receivers found in %s namespace", rootArgs.namespace)
return nil
}
header := []string{"Name", "Ready", "Message", "Suspended"}
if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, receiver := range list.Items {
var row []string
if c := apimeta.FindStatusCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
receiver.GetName(),
string(c.Status),
c.Message,
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
}
} else {
row = []string{
receiver.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
}
}
rows = append(rows, row)
}
utils.PrintTable(os.Stdout, header, rows)
return nil
} }

View File

@@ -29,8 +29,7 @@ var getSourceAllCmd = &cobra.Command{
flux get sources all --namespace=flux-system flux get sources all --namespace=flux-system
# List all sources in all namespaces # List all sources in all namespaces
flux get sources all --all-namespaces flux get sources all --all-namespaces`,
`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
c := getCommand{ c := getCommand{
apiType: bucketType, apiType: bucketType,

View File

@@ -32,8 +32,7 @@ var getSourceBucketCmd = &cobra.Command{
flux get sources bucket flux get sources bucket
# List buckets from all namespaces # List buckets from all namespaces
flux get sources helm --all-namespaces flux get sources helm --all-namespaces`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: bucketType, apiType: bucketType,
list: &bucketListAdapter{&sourcev1.BucketList{}}, list: &bucketListAdapter{&sourcev1.BucketList{}},

View File

@@ -32,8 +32,7 @@ var getSourceHelmChartCmd = &cobra.Command{
flux get sources chart flux get sources chart
# List Helm charts from all namespaces # List Helm charts from all namespaces
flux get sources chart --all-namespaces flux get sources chart --all-namespaces`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: helmChartType, apiType: helmChartType,
list: &helmChartListAdapter{&sourcev1.HelmChartList{}}, list: &helmChartListAdapter{&sourcev1.HelmChartList{}},

View File

@@ -32,8 +32,7 @@ var getSourceGitCmd = &cobra.Command{
flux get sources git flux get sources git
# List Git repositories from all namespaces # List Git repositories from all namespaces
flux get sources git --all-namespaces flux get sources git --all-namespaces`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: gitRepositoryType, apiType: gitRepositoryType,
list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}}, list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},

View File

@@ -32,8 +32,7 @@ var getSourceHelmCmd = &cobra.Command{
flux get sources helm flux get sources helm
# List Helm repositories from all namespaces # List Helm repositories from all namespaces
flux get sources helm --all-namespaces flux get sources helm --all-namespaces`,
`,
RunE: getCommand{ RunE: getCommand{
apiType: helmRepositoryType, apiType: helmRepositoryType,
list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}}, list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},

View File

@@ -51,8 +51,7 @@ If a previous version is installed, then an in-place upgrade will be performed.`
flux install --dry-run --verbose flux install --dry-run --verbose
# Write install manifests to file # Write install manifests to file
flux install --export > flux-system.yaml flux install --export > flux-system.yaml`,
`,
RunE: installCmdRun, RunE: installCmdRun,
} }

View File

@@ -23,7 +23,6 @@ import (
"time" "time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/cobra/doc"
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
"github.com/fluxcd/flux2/pkg/manifestgen/install" "github.com/fluxcd/flux2/pkg/manifestgen/install"
@@ -37,14 +36,15 @@ var rootCmd = &cobra.Command{
SilenceUsage: true, SilenceUsage: true,
SilenceErrors: true, SilenceErrors: true,
Short: "Command line utility for assembling Kubernetes CD pipelines", Short: "Command line utility for assembling Kubernetes CD pipelines",
Long: `Command line utility for assembling Kubernetes CD pipelines the GitOps way.`, Long: `
Command line utility for assembling Kubernetes CD pipelines the GitOps way.`,
Example: ` # Check prerequisites Example: ` # Check prerequisites
flux check --pre flux check --pre
# Install the latest version of Flux # 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 for a public Git repository
flux create source git webapp-latest \ flux create source git webapp-latest \
--url=https://github.com/stefanprodan/podinfo \ --url=https://github.com/stefanprodan/podinfo \
--branch=master \ --branch=master \
@@ -89,8 +89,7 @@ var rootCmd = &cobra.Command{
flux delete source git webapp-latest flux delete source git webapp-latest
# Uninstall Flux and delete CRDs # Uninstall Flux and delete CRDs
flux uninstall flux uninstall`,
`,
} }
var logger = stderrLogger{stderr: os.Stderr} var logger = stderrLogger{stderr: os.Stderr}
@@ -111,7 +110,11 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&rootArgs.namespace, "namespace", "n", rootArgs.defaults.Namespace, "the namespace scope for this operation") rootCmd.PersistentFlags().StringVarP(&rootArgs.namespace, "namespace", "n", rootArgs.defaults.Namespace, "the namespace scope for this operation")
rootCmd.PersistentFlags().DurationVar(&rootArgs.timeout, "timeout", 5*time.Minute, "timeout for this operation") rootCmd.PersistentFlags().DurationVar(&rootArgs.timeout, "timeout", 5*time.Minute, "timeout for this operation")
rootCmd.PersistentFlags().BoolVar(&rootArgs.verbose, "verbose", false, "print generated objects") rootCmd.PersistentFlags().BoolVar(&rootArgs.verbose, "verbose", false, "print generated objects")
rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", "",
"absolute path to the kubeconfig file")
rootCmd.PersistentFlags().StringVarP(&rootArgs.kubecontext, "context", "", "", "kubernetes context to use") rootCmd.PersistentFlags().StringVarP(&rootArgs.kubecontext, "context", "", "", "kubernetes context to use")
rootCmd.DisableAutoGenTag = true
} }
func NewRootFlags() rootFlags { func NewRootFlags() rootFlags {
@@ -125,39 +128,22 @@ func NewRootFlags() rootFlags {
func main() { func main() {
log.SetFlags(0) log.SetFlags(0)
generateDocs() configureKubeconfig()
kubeconfigFlag()
if err := rootCmd.Execute(); err != nil { if err := rootCmd.Execute(); err != nil {
logger.Failuref("%v", err) logger.Failuref("%v", err)
os.Exit(1) os.Exit(1)
} }
} }
func kubeconfigFlag() { func configureKubeconfig() {
if home := homeDir(); home != "" { switch {
rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", filepath.Join(home, ".kube", "config"), case len(rootArgs.kubeconfig) > 0:
"path to the kubeconfig file") case len(os.Getenv("KUBECONFIG")) > 0:
} else {
rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", "",
"absolute path to the kubeconfig file")
}
if len(os.Getenv("KUBECONFIG")) > 0 {
rootArgs.kubeconfig = os.Getenv("KUBECONFIG") rootArgs.kubeconfig = os.Getenv("KUBECONFIG")
} default:
} if home := homeDir(); len(home) > 0 {
rootArgs.kubeconfig = filepath.Join(home, ".kube", "config")
func generateDocs() {
args := os.Args[1:]
if len(args) > 0 && args[0] == "docgen" {
rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", "~/.kube/config",
"path to the kubeconfig file")
rootCmd.DisableAutoGenTag = true
err := doc.GenMarkdownTree(rootCmd, "./docs/cmd")
if err != nil {
log.Fatal(err)
} }
os.Exit(0)
} }
} }

51
cmd/flux/receiver.go Normal file
View File

@@ -0,0 +1,51 @@
/*
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 main
import (
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// notificationv1.Receiver
var receiverType = apiType{
kind: notificationv1.ReceiverKind,
humanKind: "receiver",
}
type receiverAdapter struct {
*notificationv1.Receiver
}
func (a receiverAdapter) asClientObject() client.Object {
return a.Receiver
}
// notificationv1.Receiver
type receiverListAdapter struct {
*notificationv1.ReceiverList
}
func (a receiverListAdapter) asClientList() client.ObjectList {
return a.ReceiverList
}
func (a receiverListAdapter) len() int {
return len(a.ReceiverList.Items)
}

View File

@@ -36,8 +36,7 @@ var reconcileAlertCmd = &cobra.Command{
Short: "Reconcile an Alert", Short: "Reconcile an Alert",
Long: `The reconcile alert command triggers a reconciliation of an Alert resource and waits for it to finish.`, Long: `The reconcile alert command triggers a reconciliation of an Alert resource and waits for it to finish.`,
Example: ` # Trigger a reconciliation for an existing alert Example: ` # Trigger a reconciliation for an existing alert
flux reconcile alert main flux reconcile alert main`,
`,
RunE: reconcileAlertCmdRun, RunE: reconcileAlertCmdRun,
} }

View File

@@ -36,8 +36,7 @@ var reconcileAlertProviderCmd = &cobra.Command{
Short: "Reconcile a Provider", Short: "Reconcile a Provider",
Long: `The reconcile alert-provider command triggers a reconciliation of a Provider resource and waits for it to finish.`, Long: `The reconcile alert-provider command triggers a reconciliation of a Provider resource and waits for it to finish.`,
Example: ` # Trigger a reconciliation for an existing provider Example: ` # Trigger a reconciliation for an existing provider
flux reconcile alert-provider slack flux reconcile alert-provider slack`,
`,
RunE: reconcileAlertProviderCmdRun, RunE: reconcileAlertProviderCmdRun,
} }

View File

@@ -46,8 +46,7 @@ The reconcile kustomization command triggers a reconciliation of a HelmRelease r
flux reconcile hr podinfo flux reconcile hr podinfo
# Trigger a reconciliation of the HelmRelease's source and apply changes # Trigger a reconciliation of the HelmRelease's source and apply changes
flux reconcile hr podinfo --with-source flux reconcile hr podinfo --with-source`,
`,
RunE: reconcileHrCmdRun, RunE: reconcileHrCmdRun,
} }

View File

@@ -29,8 +29,7 @@ var reconcileImageRepositoryCmd = &cobra.Command{
Short: "Reconcile an ImageRepository", Short: "Reconcile an ImageRepository",
Long: `The reconcile image repository command triggers a reconciliation of an ImageRepository resource and waits for it to finish.`, Long: `The reconcile image repository command triggers a reconciliation of an ImageRepository resource and waits for it to finish.`,
Example: ` # Trigger an scan for an existing image repository Example: ` # Trigger an scan for an existing image repository
flux reconcile image repository alpine flux reconcile image repository alpine`,
`,
RunE: reconcileCommand{ RunE: reconcileCommand{
apiType: imageRepositoryType, apiType: imageRepositoryType,
object: imageRepositoryAdapter{&imagev1.ImageRepository{}}, object: imageRepositoryAdapter{&imagev1.ImageRepository{}},

View File

@@ -31,8 +31,7 @@ var reconcileImageUpdateCmd = &cobra.Command{
Short: "Reconcile an ImageUpdateAutomation", Short: "Reconcile an ImageUpdateAutomation",
Long: `The reconcile image update command triggers a reconciliation of an ImageUpdateAutomation resource and waits for it to finish.`, Long: `The reconcile image update command triggers a reconciliation of an ImageUpdateAutomation resource and waits for it to finish.`,
Example: ` # Trigger an automation run for an existing image update automation Example: ` # Trigger an automation run for an existing image update automation
flux reconcile image update latest-images flux reconcile image update latest-images`,
`,
RunE: reconcileCommand{ RunE: reconcileCommand{
apiType: imageUpdateAutomationType, apiType: imageUpdateAutomationType,
object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}}, object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}},

View File

@@ -45,8 +45,7 @@ The reconcile kustomization command triggers a reconciliation of a Kustomization
flux reconcile kustomization podinfo flux reconcile kustomization podinfo
# Trigger a sync of the Kustomization's source and apply changes # Trigger a sync of the Kustomization's source and apply changes
flux reconcile kustomization podinfo --with-source flux reconcile kustomization podinfo --with-source`,
`,
RunE: reconcileKsCmdRun, RunE: reconcileKsCmdRun,
} }

View File

@@ -36,8 +36,7 @@ var reconcileReceiverCmd = &cobra.Command{
Short: "Reconcile a Receiver", Short: "Reconcile a Receiver",
Long: `The reconcile receiver command triggers a reconciliation of a Receiver resource and waits for it to finish.`, Long: `The reconcile receiver command triggers a reconciliation of a Receiver resource and waits for it to finish.`,
Example: ` # Trigger a reconciliation for an existing receiver Example: ` # Trigger a reconciliation for an existing receiver
flux reconcile receiver main flux reconcile receiver main`,
`,
RunE: reconcileReceiverCmdRun, RunE: reconcileReceiverCmdRun,
} }

View File

@@ -35,8 +35,7 @@ var reconcileSourceBucketCmd = &cobra.Command{
Short: "Reconcile a Bucket source", Short: "Reconcile a Bucket source",
Long: `The reconcile source command triggers a reconciliation of a Bucket resource and waits for it to finish.`, Long: `The reconcile source command triggers a reconciliation of a Bucket resource and waits for it to finish.`,
Example: ` # Trigger a reconciliation for an existing source Example: ` # Trigger a reconciliation for an existing source
flux reconcile source bucket podinfo flux reconcile source bucket podinfo`,
`,
RunE: reconcileCommand{ RunE: reconcileCommand{
apiType: bucketType, apiType: bucketType,
object: bucketAdapter{&sourcev1.Bucket{}}, object: bucketAdapter{&sourcev1.Bucket{}},

View File

@@ -27,8 +27,7 @@ var reconcileSourceGitCmd = &cobra.Command{
Short: "Reconcile a GitRepository source", Short: "Reconcile a GitRepository source",
Long: `The reconcile source command triggers a reconciliation of a GitRepository resource and waits for it to finish.`, Long: `The reconcile source command triggers a reconciliation of a GitRepository resource and waits for it to finish.`,
Example: ` # Trigger a git pull for an existing source Example: ` # Trigger a git pull for an existing source
flux reconcile source git podinfo flux reconcile source git podinfo`,
`,
RunE: reconcileCommand{ RunE: reconcileCommand{
apiType: gitRepositoryType, apiType: gitRepositoryType,
object: gitRepositoryAdapter{&sourcev1.GitRepository{}}, object: gitRepositoryAdapter{&sourcev1.GitRepository{}},

View File

@@ -27,8 +27,7 @@ var reconcileSourceHelmCmd = &cobra.Command{
Short: "Reconcile a HelmRepository source", Short: "Reconcile a HelmRepository source",
Long: `The reconcile source command triggers a reconciliation of a HelmRepository resource and waits for it to finish.`, Long: `The reconcile source command triggers a reconciliation of a HelmRepository resource and waits for it to finish.`,
Example: ` # Trigger a reconciliation for an existing source Example: ` # Trigger a reconciliation for an existing source
flux reconcile source helm podinfo flux reconcile source helm podinfo`,
`,
RunE: reconcileCommand{ RunE: reconcileCommand{
apiType: helmRepositoryType, apiType: helmRepositoryType,
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}}, object: helmRepositoryAdapter{&sourcev1.HelmRepository{}},

View File

@@ -39,8 +39,7 @@ var resumeAlertCmd = &cobra.Command{
Long: `The resume command marks a previously suspended Alert resource for reconciliation and waits for it to Long: `The resume command marks a previously suspended Alert resource for reconciliation and waits for it to
finish the apply.`, finish the apply.`,
Example: ` # Resume reconciliation for an existing Alert Example: ` # Resume reconciliation for an existing Alert
flux resume alert main flux resume alert main`,
`,
RunE: resumeAlertCmdRun, RunE: resumeAlertCmdRun,
} }

View File

@@ -29,8 +29,7 @@ var resumeHrCmd = &cobra.Command{
Long: `The resume command marks a previously suspended HelmRelease resource for reconciliation and waits for it to Long: `The resume command marks a previously suspended HelmRelease resource for reconciliation and waits for it to
finish the apply.`, finish the apply.`,
Example: ` # Resume reconciliation for an existing Helm release Example: ` # Resume reconciliation for an existing Helm release
flux resume hr podinfo flux resume hr podinfo`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: helmReleaseType, apiType: helmReleaseType,
object: helmReleaseAdapter{&helmv2.HelmRelease{}}, object: helmReleaseAdapter{&helmv2.HelmRelease{}},

View File

@@ -27,8 +27,7 @@ var resumeImageRepositoryCmd = &cobra.Command{
Short: "Resume a suspended ImageRepository", Short: "Resume a suspended ImageRepository",
Long: `The resume command marks a previously suspended ImageRepository resource for reconciliation and waits for it to finish.`, Long: `The resume command marks a previously suspended ImageRepository resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing ImageRepository Example: ` # Resume reconciliation for an existing ImageRepository
flux resume image repository alpine flux resume image repository alpine`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: imageRepositoryType, apiType: imageRepositoryType,
object: imageRepositoryAdapter{&imagev1.ImageRepository{}}, object: imageRepositoryAdapter{&imagev1.ImageRepository{}},

View File

@@ -27,8 +27,7 @@ var resumeImageUpdateCmd = &cobra.Command{
Short: "Resume a suspended ImageUpdateAutomation", Short: "Resume a suspended ImageUpdateAutomation",
Long: `The resume command marks a previously suspended ImageUpdateAutomation resource for reconciliation and waits for it to finish.`, Long: `The resume command marks a previously suspended ImageUpdateAutomation resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing ImageUpdateAutomation Example: ` # Resume reconciliation for an existing ImageUpdateAutomation
flux resume image update latest-images flux resume image update latest-images`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: imageUpdateAutomationType, apiType: imageUpdateAutomationType,
object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}}, object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}},

View File

@@ -30,8 +30,7 @@ var resumeKsCmd = &cobra.Command{
Long: `The resume command marks a previously suspended Kustomization resource for reconciliation and waits for it to Long: `The resume command marks a previously suspended Kustomization resource for reconciliation and waits for it to
finish the apply.`, finish the apply.`,
Example: ` # Resume reconciliation for an existing Kustomization Example: ` # Resume reconciliation for an existing Kustomization
flux resume ks podinfo flux resume ks podinfo`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: kustomizationType, apiType: kustomizationType,
object: kustomizationAdapter{&kustomizev1.Kustomization{}}, object: kustomizationAdapter{&kustomizev1.Kustomization{}},

View File

@@ -39,8 +39,7 @@ var resumeReceiverCmd = &cobra.Command{
Long: `The resume command marks a previously suspended Receiver resource for reconciliation and waits for it to Long: `The resume command marks a previously suspended Receiver resource for reconciliation and waits for it to
finish the apply.`, finish the apply.`,
Example: ` # Resume reconciliation for an existing Receiver Example: ` # Resume reconciliation for an existing Receiver
flux resume receiver main flux resume receiver main`,
`,
RunE: resumeReceiverCmdRun, RunE: resumeReceiverCmdRun,
} }

View File

@@ -26,8 +26,7 @@ var resumeSourceBucketCmd = &cobra.Command{
Short: "Resume a suspended Bucket", Short: "Resume a suspended Bucket",
Long: `The resume command marks a previously suspended Bucket resource for reconciliation and waits for it to finish.`, Long: `The resume command marks a previously suspended Bucket resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing Bucket Example: ` # Resume reconciliation for an existing Bucket
flux resume source bucket podinfo flux resume source bucket podinfo`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: bucketType, apiType: bucketType,
object: &bucketAdapter{&sourcev1.Bucket{}}, object: &bucketAdapter{&sourcev1.Bucket{}},

View File

@@ -28,8 +28,7 @@ var resumeSourceHelmChartCmd = &cobra.Command{
Short: "Resume a suspended HelmChart", Short: "Resume a suspended HelmChart",
Long: `The resume command marks a previously suspended HelmChart resource for reconciliation and waits for it to finish.`, Long: `The resume command marks a previously suspended HelmChart resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing HelmChart Example: ` # Resume reconciliation for an existing HelmChart
flux resume source chart podinfo flux resume source chart podinfo`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: helmChartType, apiType: helmChartType,
object: &helmChartAdapter{&sourcev1.HelmChart{}}, object: &helmChartAdapter{&sourcev1.HelmChart{}},

View File

@@ -26,8 +26,7 @@ var resumeSourceGitCmd = &cobra.Command{
Short: "Resume a suspended GitRepository", Short: "Resume a suspended GitRepository",
Long: `The resume command marks a previously suspended GitRepository resource for reconciliation and waits for it to finish.`, Long: `The resume command marks a previously suspended GitRepository resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing GitRepository Example: ` # Resume reconciliation for an existing GitRepository
flux resume source git podinfo flux resume source git podinfo`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: gitRepositoryType, apiType: gitRepositoryType,
object: gitRepositoryAdapter{&sourcev1.GitRepository{}}, object: gitRepositoryAdapter{&sourcev1.GitRepository{}},

View File

@@ -26,8 +26,7 @@ var resumeSourceHelmCmd = &cobra.Command{
Short: "Resume a suspended HelmRepository", Short: "Resume a suspended HelmRepository",
Long: `The resume command marks a previously suspended HelmRepository resource for reconciliation and waits for it to finish.`, Long: `The resume command marks a previously suspended HelmRepository resource for reconciliation and waits for it to finish.`,
Example: ` # Resume reconciliation for an existing HelmRepository Example: ` # Resume reconciliation for an existing HelmRepository
flux resume source helm bitnami flux resume source helm bitnami`,
`,
RunE: resumeCommand{ RunE: resumeCommand{
apiType: helmRepositoryType, apiType: helmRepositoryType,
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}}, object: helmRepositoryAdapter{&sourcev1.HelmRepository{}},

View File

@@ -32,8 +32,7 @@ var suspendAlertCmd = &cobra.Command{
Short: "Suspend reconciliation of Alert", Short: "Suspend reconciliation of Alert",
Long: "The suspend command disables the reconciliation of a Alert resource.", Long: "The suspend command disables the reconciliation of a Alert resource.",
Example: ` # Suspend reconciliation for an existing Alert Example: ` # Suspend reconciliation for an existing Alert
flux suspend alert main flux suspend alert main`,
`,
RunE: suspendAlertCmdRun, RunE: suspendAlertCmdRun,
} }

View File

@@ -27,8 +27,7 @@ var suspendHrCmd = &cobra.Command{
Short: "Suspend reconciliation of HelmRelease", Short: "Suspend reconciliation of HelmRelease",
Long: "The suspend command disables the reconciliation of a HelmRelease resource.", Long: "The suspend command disables the reconciliation of a HelmRelease resource.",
Example: ` # Suspend reconciliation for an existing Helm release Example: ` # Suspend reconciliation for an existing Helm release
flux suspend hr podinfo flux suspend hr podinfo`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: helmReleaseType, apiType: helmReleaseType,
object: &helmReleaseAdapter{&helmv2.HelmRelease{}}, object: &helmReleaseAdapter{&helmv2.HelmRelease{}},

View File

@@ -27,8 +27,7 @@ var suspendImageRepositoryCmd = &cobra.Command{
Short: "Suspend reconciliation of an ImageRepository", Short: "Suspend reconciliation of an ImageRepository",
Long: "The suspend image repository command disables the reconciliation of a ImageRepository resource.", Long: "The suspend image repository command disables the reconciliation of a ImageRepository resource.",
Example: ` # Suspend reconciliation for an existing ImageRepository Example: ` # Suspend reconciliation for an existing ImageRepository
flux suspend image repository alpine flux suspend image repository alpine`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: imageRepositoryType, apiType: imageRepositoryType,
object: imageRepositoryAdapter{&imagev1.ImageRepository{}}, object: imageRepositoryAdapter{&imagev1.ImageRepository{}},

View File

@@ -27,8 +27,7 @@ var suspendImageUpdateCmd = &cobra.Command{
Short: "Suspend reconciliation of an ImageUpdateAutomation", Short: "Suspend reconciliation of an ImageUpdateAutomation",
Long: "The suspend image update command disables the reconciliation of a ImageUpdateAutomation resource.", Long: "The suspend image update command disables the reconciliation of a ImageUpdateAutomation resource.",
Example: ` # Suspend reconciliation for an existing ImageUpdateAutomation Example: ` # Suspend reconciliation for an existing ImageUpdateAutomation
flux suspend image update latest-images flux suspend image update latest-images`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: imageUpdateAutomationType, apiType: imageUpdateAutomationType,
object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}}, object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}},

View File

@@ -27,8 +27,7 @@ var suspendKsCmd = &cobra.Command{
Short: "Suspend reconciliation of Kustomization", Short: "Suspend reconciliation of Kustomization",
Long: "The suspend command disables the reconciliation of a Kustomization resource.", Long: "The suspend command disables the reconciliation of a Kustomization resource.",
Example: ` # Suspend reconciliation for an existing Kustomization Example: ` # Suspend reconciliation for an existing Kustomization
flux suspend ks podinfo flux suspend ks podinfo`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: kustomizationType, apiType: kustomizationType,
object: kustomizationAdapter{&kustomizev1.Kustomization{}}, object: kustomizationAdapter{&kustomizev1.Kustomization{}},

View File

@@ -32,8 +32,7 @@ var suspendReceiverCmd = &cobra.Command{
Short: "Suspend reconciliation of Receiver", Short: "Suspend reconciliation of Receiver",
Long: "The suspend command disables the reconciliation of a Receiver resource.", Long: "The suspend command disables the reconciliation of a Receiver resource.",
Example: ` # Suspend reconciliation for an existing Receiver Example: ` # Suspend reconciliation for an existing Receiver
flux suspend receiver main flux suspend receiver main`,
`,
RunE: suspendReceiverCmdRun, RunE: suspendReceiverCmdRun,
} }

View File

@@ -26,8 +26,7 @@ var suspendSourceBucketCmd = &cobra.Command{
Short: "Suspend reconciliation of a Bucket", Short: "Suspend reconciliation of a Bucket",
Long: "The suspend command disables the reconciliation of a Bucket resource.", Long: "The suspend command disables the reconciliation of a Bucket resource.",
Example: ` # Suspend reconciliation for an existing Bucket Example: ` # Suspend reconciliation for an existing Bucket
flux suspend source bucket podinfo flux suspend source bucket podinfo`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: bucketType, apiType: bucketType,
object: bucketAdapter{&sourcev1.Bucket{}}, object: bucketAdapter{&sourcev1.Bucket{}},

View File

@@ -27,8 +27,7 @@ var suspendSourceHelmChartCmd = &cobra.Command{
Short: "Suspend reconciliation of a HelmChart", Short: "Suspend reconciliation of a HelmChart",
Long: "The suspend command disables the reconciliation of a HelmChart resource.", Long: "The suspend command disables the reconciliation of a HelmChart resource.",
Example: ` # Suspend reconciliation for an existing HelmChart Example: ` # Suspend reconciliation for an existing HelmChart
flux suspend source chart podinfo flux suspend source chart podinfo`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: helmChartType, apiType: helmChartType,
object: helmChartAdapter{&sourcev1.HelmChart{}}, object: helmChartAdapter{&sourcev1.HelmChart{}},

View File

@@ -27,8 +27,7 @@ var suspendSourceGitCmd = &cobra.Command{
Short: "Suspend reconciliation of a GitRepository", Short: "Suspend reconciliation of a GitRepository",
Long: "The suspend command disables the reconciliation of a GitRepository resource.", Long: "The suspend command disables the reconciliation of a GitRepository resource.",
Example: ` # Suspend reconciliation for an existing GitRepository Example: ` # Suspend reconciliation for an existing GitRepository
flux suspend source git podinfo flux suspend source git podinfo`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: gitRepositoryType, apiType: gitRepositoryType,
object: gitRepositoryAdapter{&sourcev1.GitRepository{}}, object: gitRepositoryAdapter{&sourcev1.GitRepository{}},

View File

@@ -27,8 +27,7 @@ var suspendSourceHelmCmd = &cobra.Command{
Short: "Suspend reconciliation of a HelmRepository", Short: "Suspend reconciliation of a HelmRepository",
Long: "The suspend command disables the reconciliation of a HelmRepository resource.", Long: "The suspend command disables the reconciliation of a HelmRepository resource.",
Example: ` # Suspend reconciliation for an existing HelmRepository Example: ` # Suspend reconciliation for an existing HelmRepository
flux suspend source helm bitnami flux suspend source helm bitnami`,
`,
RunE: suspendCommand{ RunE: suspendCommand{
apiType: helmRepositoryType, apiType: helmRepositoryType,
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}}, object: helmRepositoryAdapter{&sourcev1.HelmRepository{}},

View File

@@ -44,8 +44,7 @@ var uninstallCmd = &cobra.Command{
flux uninstall --namespace=flux-system flux uninstall --namespace=flux-system
# Uninstall Flux but keep the namespace # Uninstall Flux but keep the namespace
flux uninstall --namespace=infra --keep-namespace=true flux uninstall --namespace=infra --keep-namespace=true`,
`,
RunE: uninstallCmdRun, RunE: uninstallCmdRun,
} }

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

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