Refactor cmd global variables into structs

Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
pull/755/head
Somtochi Onyekwere 4 years ago
parent 77db369213
commit a7586e69fd

@ -45,62 +45,71 @@ var bootstrapCmd = &cobra.Command{
Long: "The bootstrap sub-commands bootstrap the toolkit components on the targeted Git provider.", Long: "The bootstrap sub-commands bootstrap the toolkit components on the targeted Git provider.",
} }
var ( type bootstrapFlags struct {
bootstrapVersion string version string
bootstrapDefaultComponents []string defaultComponents []string
bootstrapExtraComponents []string extraComponents []string
bootstrapRegistry string registry string
bootstrapImagePullSecret string imagePullSecret string
bootstrapBranch string branch string
bootstrapWatchAllNamespaces bool watchAllNamespaces bool
bootstrapNetworkPolicy bool networkPolicy bool
bootstrapManifestsPath string manifestsPath string
bootstrapArch flags.Arch arch flags.Arch
bootstrapLogLevel = flags.LogLevel(defaults.LogLevel) logLevel flags.LogLevel
bootstrapRequiredComponents = []string{"source-controller", "kustomize-controller"} requiredComponents []string
bootstrapTokenAuth bool tokenAuth bool
bootstrapClusterDomain string clusterDomain string
) }
const ( const (
bootstrapDefaultBranch = "main" bootstrapDefaultBranch = "main"
) )
var bootstrapArgs = NewBootstrapFlags()
func init() { func init() {
bootstrapCmd.PersistentFlags().StringVarP(&bootstrapVersion, "version", "v", defaults.Version, bootstrapCmd.PersistentFlags().StringVarP(&bootstrapArgs.version, "version", "v", rootArgs.defaults.Version,
"toolkit version") "toolkit version")
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapDefaultComponents, "components", defaults.Components, bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.defaultComponents, "components", rootArgs.defaults.Components,
"list of components, accepts comma-separated values") "list of components, accepts comma-separated values")
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapExtraComponents, "components-extra", nil, bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.extraComponents, "components-extra", nil,
"list of components in addition to those supplied or defaulted, accepts comma-separated values") "list of components in addition to those supplied or defaulted, accepts comma-separated values")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapRegistry, "registry", "ghcr.io/fluxcd", bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.registry, "registry", "ghcr.io/fluxcd",
"container registry where the toolkit images are published") "container registry where the toolkit images are published")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapImagePullSecret, "image-pull-secret", "", bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.imagePullSecret, "image-pull-secret", "",
"Kubernetes secret name used for pulling the toolkit images from a private registry") "Kubernetes secret name used for pulling the toolkit images from a private registry")
bootstrapCmd.PersistentFlags().Var(&bootstrapArch, "arch", bootstrapArch.Description()) bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.arch, "arch", bootstrapArgs.arch.Description())
bootstrapCmd.PersistentFlags().StringVar(&bootstrapBranch, "branch", bootstrapDefaultBranch, bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.branch, "branch", bootstrapDefaultBranch,
"default branch (for GitHub this must match the default branch setting for the organization)") "default branch (for GitHub this must match the default branch setting for the organization)")
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapWatchAllNamespaces, "watch-all-namespaces", true, bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.watchAllNamespaces, "watch-all-namespaces", true,
"watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed") "watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed")
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapNetworkPolicy, "network-policy", true, bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.networkPolicy, "network-policy", true,
"deny ingress access to the toolkit controllers from other namespaces using network policies") "deny ingress access to the toolkit controllers from other namespaces using network policies")
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapTokenAuth, "token-auth", false, bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.tokenAuth, "token-auth", false,
"when enabled, the personal access token will be used instead of SSH deploy key") "when enabled, the personal access token will be used instead of SSH deploy key")
bootstrapCmd.PersistentFlags().Var(&bootstrapLogLevel, "log-level", bootstrapLogLevel.Description()) bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.logLevel, "log-level", bootstrapArgs.logLevel.Description())
bootstrapCmd.PersistentFlags().StringVar(&bootstrapManifestsPath, "manifests", "", "path to the manifest directory") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.manifestsPath, "manifests", "", "path to the manifest directory")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapClusterDomain, "cluster-domain", defaults.ClusterDomain, "internal cluster domain") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.clusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain")
bootstrapCmd.PersistentFlags().MarkHidden("manifests") bootstrapCmd.PersistentFlags().MarkHidden("manifests")
bootstrapCmd.PersistentFlags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64") bootstrapCmd.PersistentFlags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64")
rootCmd.AddCommand(bootstrapCmd) rootCmd.AddCommand(bootstrapCmd)
} }
func NewBootstrapFlags() bootstrapFlags {
return bootstrapFlags{
logLevel: flags.LogLevel(rootArgs.defaults.LogLevel),
requiredComponents: []string{"source-controller", "kustomize-controller"},
}
}
func bootstrapComponents() []string { func bootstrapComponents() []string {
return append(bootstrapDefaultComponents, bootstrapExtraComponents...) return append(bootstrapArgs.defaultComponents, bootstrapArgs.extraComponents...)
} }
func bootstrapValidate() error { func bootstrapValidate() error {
components := bootstrapComponents() components := bootstrapComponents()
for _, component := range bootstrapRequiredComponents { for _, component := range bootstrapArgs.requiredComponents {
if !utils.ContainsItemString(components, component) { if !utils.ContainsItemString(components, component) {
return fmt.Errorf("component %s is required", component) return fmt.Errorf("component %s is required", component)
} }
@ -116,23 +125,23 @@ func bootstrapValidate() error {
func generateInstallManifests(targetPath, namespace, tmpDir string, localManifests string) (string, error) { func generateInstallManifests(targetPath, namespace, tmpDir string, localManifests string) (string, error) {
opts := install.Options{ opts := install.Options{
BaseURL: localManifests, BaseURL: localManifests,
Version: bootstrapVersion, Version: bootstrapArgs.version,
Namespace: namespace, Namespace: rootArgs.namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapRegistry, Registry: bootstrapArgs.registry,
ImagePullSecret: bootstrapImagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
WatchAllNamespaces: bootstrapWatchAllNamespaces, WatchAllNamespaces: bootstrapArgs.watchAllNamespaces,
NetworkPolicy: bootstrapNetworkPolicy, NetworkPolicy: bootstrapArgs.networkPolicy,
LogLevel: bootstrapLogLevel.String(), LogLevel: bootstrapArgs.logLevel.String(),
NotificationController: defaults.NotificationController, NotificationController: rootArgs.defaults.NotificationController,
ManifestFile: defaults.ManifestFile, ManifestFile: rootArgs.defaults.ManifestFile,
Timeout: timeout, Timeout: rootArgs.timeout,
TargetPath: targetPath, TargetPath: targetPath,
ClusterDomain: bootstrapClusterDomain, ClusterDomain: bootstrapArgs.clusterDomain,
} }
if localManifests == "" { if localManifests == "" {
opts.BaseURL = defaults.BaseURL opts.BaseURL = rootArgs.defaults.BaseURL
} }
output, err := install.Generate(opts) output, err := install.Generate(opts)
@ -149,13 +158,13 @@ func generateInstallManifests(targetPath, namespace, tmpDir string, localManifes
func applyInstallManifests(ctx context.Context, manifestPath string, components []string) error { func applyInstallManifests(ctx context.Context, manifestPath string, components []string) error {
kubectlArgs := []string{"apply", "-f", manifestPath} kubectlArgs := []string{"apply", "-f", manifestPath}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...); err != nil { if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
for _, deployment := range components { for _, deployment := range components {
kubectlArgs = []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()} kubectlArgs = []string{"-n", rootArgs.namespace, "rollout", "status", "deployment", deployment, "--timeout", rootArgs.timeout.String()}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...); err != nil { if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
} }
@ -191,20 +200,20 @@ func generateSyncManifests(url, branch, name, namespace, targetPath, tmpDir stri
func applySyncManifests(ctx context.Context, kubeClient client.Client, name, namespace, manifestsPath string) error { func applySyncManifests(ctx context.Context, kubeClient client.Client, name, namespace, manifestsPath string) error {
kubectlArgs := []string{"apply", "-k", manifestsPath} kubectlArgs := []string{"apply", "-k", manifestsPath}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, kubeconfig, kubecontext, kubectlArgs...); err != nil { if _, err := utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return err return err
} }
logger.Waitingf("waiting for cluster sync") logger.Waitingf("waiting for cluster sync")
var gitRepository sourcev1.GitRepository var gitRepository sourcev1.GitRepository
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isGitRepositoryReady(ctx, kubeClient, types.NamespacedName{Name: name, Namespace: namespace}, &gitRepository)); err != nil { isGitRepositoryReady(ctx, kubeClient, types.NamespacedName{Name: name, Namespace: namespace}, &gitRepository)); err != nil {
return err return err
} }
var kustomization kustomizev1.Kustomization var kustomization kustomizev1.Kustomization
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isKustomizationReady(ctx, kubeClient, types.NamespacedName{Name: name, Namespace: namespace}, &kustomization)); err != nil { isKustomizationReady(ctx, kubeClient, types.NamespacedName{Name: name, Namespace: namespace}, &kustomization)); err != nil {
return err return err
} }
@ -239,7 +248,7 @@ func shouldCreateDeployKey(ctx context.Context, kubeClient client.Client, namesp
} }
func generateDeployKey(ctx context.Context, kubeClient client.Client, url *url.URL, namespace string) (string, error) { func generateDeployKey(ctx context.Context, kubeClient client.Client, url *url.URL, namespace string) (string, error) {
pair, err := generateKeyPair(ctx, sourceGitKeyAlgorithm, sourceGitRSABits, sourceGitECDSACurve) pair, err := generateKeyPair(ctx, sourceArgs.GitKeyAlgorithm, sourceArgs.GitRSABits, sourceArgs.GitECDSACurve)
if err != nil { if err != nil {
return "", err return "", err
} }

@ -71,35 +71,37 @@ the bootstrap command will perform an upgrade if needed.`,
RunE: bootstrapGitHubCmdRun, RunE: bootstrapGitHubCmdRun,
} }
var ( type githubFlags struct {
ghOwner string owner string
ghRepository string repository string
ghInterval time.Duration interval time.Duration
ghPersonal bool personal bool
ghPrivate bool private bool
ghHostname string hostname string
ghPath flags.SafeRelativePath path flags.SafeRelativePath
ghTeams []string teams []string
ghDelete bool delete bool
ghSSHHostname string sshHostname string
) }
const ( const (
ghDefaultPermission = "maintain" ghDefaultPermission = "maintain"
) )
var githubArgs githubFlags
func init() { func init() {
bootstrapGitHubCmd.Flags().StringVar(&ghOwner, "owner", "", "GitHub user or organization name") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.owner, "owner", "", "GitHub user or organization name")
bootstrapGitHubCmd.Flags().StringVar(&ghRepository, "repository", "", "GitHub repository name") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.repository, "repository", "", "GitHub repository name")
bootstrapGitHubCmd.Flags().StringArrayVar(&ghTeams, "team", []string{}, "GitHub team to be given maintainer access") bootstrapGitHubCmd.Flags().StringArrayVar(&githubArgs.teams, "team", []string{}, "GitHub team to be given maintainer access")
bootstrapGitHubCmd.Flags().BoolVar(&ghPersonal, "personal", false, "is personal repository") bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.personal, "personal", false, "is personal repository")
bootstrapGitHubCmd.Flags().BoolVar(&ghPrivate, "private", true, "is private repository") bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.private, "private", true, "is private repository")
bootstrapGitHubCmd.Flags().DurationVar(&ghInterval, "interval", time.Minute, "sync interval") bootstrapGitHubCmd.Flags().DurationVar(&githubArgs.interval, "interval", time.Minute, "sync interval")
bootstrapGitHubCmd.Flags().StringVar(&ghHostname, "hostname", git.GitHubDefaultHostname, "GitHub hostname") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.hostname, "hostname", git.GitHubDefaultHostname, "GitHub hostname")
bootstrapGitHubCmd.Flags().StringVar(&ghSSHHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one") bootstrapGitHubCmd.Flags().StringVar(&githubArgs.sshHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one")
bootstrapGitHubCmd.Flags().Var(&ghPath, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path") bootstrapGitHubCmd.Flags().Var(&githubArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path")
bootstrapGitHubCmd.Flags().BoolVar(&ghDelete, "delete", false, "delete repository (used for testing only)") bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.delete, "delete", false, "delete repository (used for testing only)")
bootstrapGitHubCmd.Flags().MarkHidden("delete") bootstrapGitHubCmd.Flags().MarkHidden("delete")
bootstrapCmd.AddCommand(bootstrapGitHubCmd) bootstrapCmd.AddCommand(bootstrapGitHubCmd)
@ -115,41 +117,41 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(ctx, kubeClient, namespace, filepath.ToSlash(ghPath.String())) usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(ctx, kubeClient, rootArgs.namespace, filepath.ToSlash(githubArgs.path.String()))
if bootstrapPathDiffers { if bootstrapPathDiffers {
return fmt.Errorf("cluster already bootstrapped to %v path", usedPath) return fmt.Errorf("cluster already bootstrapped to %v path", usedPath)
} }
repository, err := git.NewRepository(ghRepository, ghOwner, ghHostname, ghToken, "flux", ghOwner+"@users.noreply.github.com") repository, err := git.NewRepository(githubArgs.repository, githubArgs.owner, githubArgs.hostname, ghToken, "flux", githubArgs.owner+"@users.noreply.github.com")
if err != nil { if err != nil {
return err return err
} }
if ghSSHHostname != "" { if githubArgs.sshHostname != "" {
repository.SSHHost = ghSSHHostname repository.SSHHost = githubArgs.sshHostname
} }
provider := &git.GithubProvider{ provider := &git.GithubProvider{
IsPrivate: ghPrivate, IsPrivate: githubArgs.private,
IsPersonal: ghPersonal, IsPersonal: githubArgs.personal,
} }
tmpDir, err := ioutil.TempDir("", namespace) tmpDir, err := ioutil.TempDir("", rootArgs.namespace)
if err != nil { if err != nil {
return err return err
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
if ghDelete { if githubArgs.delete {
if err := provider.DeleteRepository(ctx, repository); err != nil { if err := provider.DeleteRepository(ctx, repository); err != nil {
return err return err
} }
@ -158,7 +160,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
} }
// create GitHub repository if doesn't exists // create GitHub repository if doesn't exists
logger.Actionf("connecting to %s", ghHostname) logger.Actionf("connecting to %s", githubArgs.hostname)
changed, err := provider.CreateRepository(ctx, repository) changed, err := provider.CreateRepository(ctx, repository)
if err != nil { if err != nil {
return err return err
@ -169,8 +171,8 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
withErrors := false withErrors := false
// add teams to org repository // add teams to org repository
if !ghPersonal { if !githubArgs.personal {
for _, team := range ghTeams { for _, team := range githubArgs.teams {
if changed, err := provider.AddTeam(ctx, repository, team, ghDefaultPermission); err != nil { if changed, err := provider.AddTeam(ctx, repository, team, ghDefaultPermission); err != nil {
logger.Failuref(err.Error()) logger.Failuref(err.Error())
withErrors = true withErrors = true
@ -181,20 +183,20 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
} }
// clone repository and checkout the main branch // clone repository and checkout the main branch
if err := repository.Checkout(ctx, bootstrapBranch, tmpDir); err != nil { if err := repository.Checkout(ctx, bootstrapArgs.branch, tmpDir); err != nil {
return err return err
} }
logger.Successf("repository cloned") logger.Successf("repository cloned")
// generate install manifests // generate install manifests
logger.Generatef("generating manifests") logger.Generatef("generating manifests")
installManifest, err := generateInstallManifests(ghPath.String(), namespace, tmpDir, bootstrapManifestsPath) installManifest, err := generateInstallManifests(githubArgs.path.String(), rootArgs.namespace, tmpDir, bootstrapArgs.manifestsPath)
if err != nil { if err != nil {
return err return err
} }
// stage install manifests // stage install manifests
changed, err = repository.Commit(ctx, path.Join(ghPath.String(), namespace), "Add manifests") changed, err = repository.Commit(ctx, path.Join(githubArgs.path.String(), rootArgs.namespace), "Add manifests")
if err != nil { if err != nil {
return err return err
} }
@ -210,11 +212,11 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
} }
// determine if repo synchronization is working // determine if repo synchronization is working
isInstall := shouldInstallManifests(ctx, kubeClient, namespace) isInstall := shouldInstallManifests(ctx, kubeClient, rootArgs.namespace)
if isInstall { if isInstall {
// apply install manifests // apply install manifests
logger.Actionf("installing components in %s namespace", namespace) logger.Actionf("installing components in %s namespace", rootArgs.namespace)
if err := applyInstallManifests(ctx, installManifest, bootstrapComponents()); err != nil { if err := applyInstallManifests(ctx, installManifest, bootstrapComponents()); err != nil {
return err return err
} }
@ -223,12 +225,12 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
repoURL := repository.GetURL() repoURL := repository.GetURL()
if bootstrapTokenAuth { if bootstrapArgs.tokenAuth {
// setup HTTPS token auth // setup HTTPS token auth
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: namespace, Name: rootArgs.namespace,
Namespace: namespace, Namespace: rootArgs.namespace,
}, },
StringData: map[string]string{ StringData: map[string]string{
"username": "git", "username": "git",
@ -241,21 +243,21 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
// setup SSH deploy key // setup SSH deploy key
repoURL = repository.GetSSH() repoURL = repository.GetSSH()
if shouldCreateDeployKey(ctx, kubeClient, namespace) { if shouldCreateDeployKey(ctx, kubeClient, rootArgs.namespace) {
logger.Actionf("configuring deploy key") logger.Actionf("configuring deploy key")
u, err := url.Parse(repository.GetSSH()) u, err := url.Parse(repository.GetSSH())
if err != nil { if err != nil {
return fmt.Errorf("git URL parse failed: %w", err) return fmt.Errorf("git URL parse failed: %w", err)
} }
key, err := generateDeployKey(ctx, kubeClient, u, namespace) key, err := generateDeployKey(ctx, kubeClient, u, rootArgs.namespace)
if err != nil { if err != nil {
return fmt.Errorf("generating deploy key failed: %w", err) return fmt.Errorf("generating deploy key failed: %w", err)
} }
keyName := "flux" keyName := "flux"
if ghPath != "" { if githubArgs.path != "" {
keyName = fmt.Sprintf("flux-%s", ghPath) keyName = fmt.Sprintf("flux-%s", githubArgs.path)
} }
if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil { if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil {
@ -268,13 +270,13 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
// configure repo synchronization // configure repo synchronization
logger.Actionf("generating sync manifests") logger.Actionf("generating sync manifests")
syncManifests, err := generateSyncManifests(repoURL, bootstrapBranch, namespace, namespace, filepath.ToSlash(ghPath.String()), tmpDir, ghInterval) syncManifests, err := generateSyncManifests(repoURL, bootstrapArgs.branch, rootArgs.namespace, rootArgs.namespace, filepath.ToSlash(githubArgs.path.String()), tmpDir, githubArgs.interval)
if err != nil { if err != nil {
return err return err
} }
// commit and push manifests // commit and push manifests
if changed, err = repository.Commit(ctx, path.Join(ghPath.String(), namespace), "Add manifests"); err != nil { if changed, err = repository.Commit(ctx, path.Join(githubArgs.path.String(), rootArgs.namespace), "Add manifests"); err != nil {
return err return err
} else if changed { } else if changed {
if err := repository.Push(ctx); err != nil { if err := repository.Push(ctx); err != nil {
@ -285,7 +287,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
// apply manifests and waiting for sync // apply manifests and waiting for sync
logger.Actionf("applying sync manifests") logger.Actionf("applying sync manifests")
if err := applySyncManifests(ctx, kubeClient, namespace, namespace, syncManifests); err != nil { if err := applySyncManifests(ctx, kubeClient, rootArgs.namespace, rootArgs.namespace, syncManifests); err != nil {
return err return err
} }

@ -73,26 +73,28 @@ const (
gitlabProjectRegex = `\A[[:alnum:]\x{00A9}-\x{1f9ff}_][[:alnum:]\p{Pd}\x{00A9}-\x{1f9ff}_\.]*\z` gitlabProjectRegex = `\A[[:alnum:]\x{00A9}-\x{1f9ff}_][[:alnum:]\p{Pd}\x{00A9}-\x{1f9ff}_\.]*\z`
) )
var ( type gitlabFlags struct {
glOwner string owner string
glRepository string repository string
glInterval time.Duration interval time.Duration
glPersonal bool personal bool
glPrivate bool private bool
glHostname string hostname string
glSSHHostname string sshHostname string
glPath flags.SafeRelativePath path flags.SafeRelativePath
) }
var gitlabArgs gitlabFlags
func init() { func init() {
bootstrapGitLabCmd.Flags().StringVar(&glOwner, "owner", "", "GitLab user or group name") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.owner, "owner", "", "GitLab user or group name")
bootstrapGitLabCmd.Flags().StringVar(&glRepository, "repository", "", "GitLab repository name") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.repository, "repository", "", "GitLab repository name")
bootstrapGitLabCmd.Flags().BoolVar(&glPersonal, "personal", false, "is personal repository") bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.personal, "personal", false, "is personal repository")
bootstrapGitLabCmd.Flags().BoolVar(&glPrivate, "private", true, "is private repository") bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.private, "private", true, "is private repository")
bootstrapGitLabCmd.Flags().DurationVar(&glInterval, "interval", time.Minute, "sync interval") bootstrapGitLabCmd.Flags().DurationVar(&gitlabArgs.interval, "interval", time.Minute, "sync interval")
bootstrapGitLabCmd.Flags().StringVar(&glHostname, "hostname", git.GitLabDefaultHostname, "GitLab hostname") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.hostname, "hostname", git.GitLabDefaultHostname, "GitLab hostname")
bootstrapGitLabCmd.Flags().StringVar(&glSSHHostname, "ssh-hostname", "", "GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one") bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.sshHostname, "ssh-hostname", "", "GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one")
bootstrapGitLabCmd.Flags().Var(&glPath, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path") bootstrapGitLabCmd.Flags().Var(&gitlabArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path")
bootstrapCmd.AddCommand(bootstrapGitLabCmd) bootstrapCmd.AddCommand(bootstrapGitLabCmd)
} }
@ -103,54 +105,54 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("%s environment variable not found", git.GitLabTokenName) return fmt.Errorf("%s environment variable not found", git.GitLabTokenName)
} }
projectNameIsValid, err := regexp.MatchString(gitlabProjectRegex, glRepository) projectNameIsValid, err := regexp.MatchString(gitlabProjectRegex, gitlabArgs.repository)
if err != nil { if err != nil {
return err return err
} }
if !projectNameIsValid { if !projectNameIsValid {
return fmt.Errorf("%s is an invalid project name for gitlab.\nIt can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'.", glRepository) return fmt.Errorf("%s is an invalid project name for gitlab.\nIt can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'.", gitlabArgs.repository)
} }
if err := bootstrapValidate(); err != nil { if err := bootstrapValidate(); err != nil {
return err return err
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(ctx, kubeClient, namespace, filepath.ToSlash(glPath.String())) usedPath, bootstrapPathDiffers := checkIfBootstrapPathDiffers(ctx, kubeClient, rootArgs.namespace, filepath.ToSlash(gitlabArgs.path.String()))
if bootstrapPathDiffers { if bootstrapPathDiffers {
return fmt.Errorf("cluster already bootstrapped to %v path", usedPath) return fmt.Errorf("cluster already bootstrapped to %v path", usedPath)
} }
repository, err := git.NewRepository(glRepository, glOwner, glHostname, glToken, "flux", glOwner+"@users.noreply.gitlab.com") repository, err := git.NewRepository(gitlabArgs.repository, gitlabArgs.owner, gitlabArgs.hostname, glToken, "flux", gitlabArgs.owner+"@users.noreply.gitlab.com")
if err != nil { if err != nil {
return err return err
} }
if glSSHHostname != "" { if gitlabArgs.sshHostname != "" {
repository.SSHHost = glSSHHostname repository.SSHHost = gitlabArgs.sshHostname
} }
tmpDir, err := ioutil.TempDir("", namespace) tmpDir, err := ioutil.TempDir("", rootArgs.namespace)
if err != nil { if err != nil {
return err return err
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
provider := &git.GitLabProvider{ provider := &git.GitLabProvider{
IsPrivate: glPrivate, IsPrivate: gitlabArgs.private,
IsPersonal: glPersonal, IsPersonal: gitlabArgs.personal,
} }
// create GitLab project if doesn't exists // create GitLab project if doesn't exists
logger.Actionf("connecting to %s", glHostname) logger.Actionf("connecting to %s", gitlabArgs.hostname)
changed, err := provider.CreateRepository(ctx, repository) changed, err := provider.CreateRepository(ctx, repository)
if err != nil { if err != nil {
return err return err
@ -160,20 +162,20 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
} }
// clone repository and checkout the master branch // clone repository and checkout the master branch
if err := repository.Checkout(ctx, bootstrapBranch, tmpDir); err != nil { if err := repository.Checkout(ctx, bootstrapArgs.branch, tmpDir); err != nil {
return err return err
} }
logger.Successf("repository cloned") logger.Successf("repository cloned")
// generate install manifests // generate install manifests
logger.Generatef("generating manifests") logger.Generatef("generating manifests")
installManifest, err := generateInstallManifests(glPath.String(), namespace, tmpDir, bootstrapManifestsPath) installManifest, err := generateInstallManifests(gitlabArgs.path.String(), rootArgs.namespace, tmpDir, bootstrapArgs.manifestsPath)
if err != nil { if err != nil {
return err return err
} }
// stage install manifests // stage install manifests
changed, err = repository.Commit(ctx, path.Join(glPath.String(), namespace), "Add manifests") changed, err = repository.Commit(ctx, path.Join(gitlabArgs.path.String(), rootArgs.namespace), "Add manifests")
if err != nil { if err != nil {
return err return err
} }
@ -189,11 +191,11 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
} }
// determine if repo synchronization is working // determine if repo synchronization is working
isInstall := shouldInstallManifests(ctx, kubeClient, namespace) isInstall := shouldInstallManifests(ctx, kubeClient, rootArgs.namespace)
if isInstall { if isInstall {
// apply install manifests // apply install manifests
logger.Actionf("installing components in %s namespace", namespace) logger.Actionf("installing components in %s namespace", rootArgs.namespace)
if err := applyInstallManifests(ctx, installManifest, bootstrapComponents()); err != nil { if err := applyInstallManifests(ctx, installManifest, bootstrapComponents()); err != nil {
return err return err
} }
@ -202,12 +204,12 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
repoURL := repository.GetURL() repoURL := repository.GetURL()
if bootstrapTokenAuth { if bootstrapArgs.tokenAuth {
// setup HTTPS token auth // setup HTTPS token auth
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: namespace, Name: rootArgs.namespace,
Namespace: namespace, Namespace: rootArgs.namespace,
}, },
StringData: map[string]string{ StringData: map[string]string{
"username": "git", "username": "git",
@ -220,21 +222,21 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
// setup SSH deploy key // setup SSH deploy key
repoURL = repository.GetSSH() repoURL = repository.GetSSH()
if shouldCreateDeployKey(ctx, kubeClient, namespace) { if shouldCreateDeployKey(ctx, kubeClient, rootArgs.namespace) {
logger.Actionf("configuring deploy key") logger.Actionf("configuring deploy key")
u, err := url.Parse(repoURL) u, err := url.Parse(repoURL)
if err != nil { if err != nil {
return fmt.Errorf("git URL parse failed: %w", err) return fmt.Errorf("git URL parse failed: %w", err)
} }
key, err := generateDeployKey(ctx, kubeClient, u, namespace) key, err := generateDeployKey(ctx, kubeClient, u, rootArgs.namespace)
if err != nil { if err != nil {
return fmt.Errorf("generating deploy key failed: %w", err) return fmt.Errorf("generating deploy key failed: %w", err)
} }
keyName := "flux" keyName := "flux"
if glPath != "" { if gitlabArgs.path != "" {
keyName = fmt.Sprintf("flux-%s", glPath) keyName = fmt.Sprintf("flux-%s", gitlabArgs.path)
} }
if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil { if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil {
@ -247,13 +249,13 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
// configure repo synchronization // configure repo synchronization
logger.Actionf("generating sync manifests") logger.Actionf("generating sync manifests")
syncManifests, err := generateSyncManifests(repoURL, bootstrapBranch, namespace, namespace, filepath.ToSlash(glPath.String()), tmpDir, glInterval) syncManifests, err := generateSyncManifests(repoURL, bootstrapArgs.branch, rootArgs.namespace, rootArgs.namespace, filepath.ToSlash(gitlabArgs.path.String()), tmpDir, gitlabArgs.interval)
if err != nil { if err != nil {
return err return err
} }
// commit and push manifests // commit and push manifests
if changed, err = repository.Commit(ctx, path.Join(glPath.String(), namespace), "Add manifests"); err != nil { if changed, err = repository.Commit(ctx, path.Join(gitlabArgs.path.String(), rootArgs.namespace), "Add manifests"); err != nil {
return err return err
} else if changed { } else if changed {
if err := repository.Push(ctx); err != nil { if err := repository.Push(ctx); err != nil {
@ -264,7 +266,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
// apply manifests and waiting for sync // apply manifests and waiting for sync
logger.Actionf("applying sync manifests") logger.Actionf("applying sync manifests")
if err := applySyncManifests(ctx, kubeClient, namespace, namespace, syncManifests); err != nil { if err := applySyncManifests(ctx, kubeClient, rootArgs.namespace, rootArgs.namespace, syncManifests); err != nil {
return err return err
} }

@ -44,25 +44,27 @@ the local environment is configured correctly and if the installed components ar
RunE: runCheckCmd, RunE: runCheckCmd,
} }
var ( type checkFlags struct {
checkPre bool pre bool
checkComponents []string components []string
) }
type kubectlVersion struct { type kubectlVersion struct {
ClientVersion *apimachineryversion.Info `json:"clientVersion"` ClientVersion *apimachineryversion.Info `json:"clientVersion"`
} }
var checkArgs checkFlags
func init() { func init() {
checkCmd.Flags().BoolVarP(&checkPre, "pre", "", false, checkCmd.Flags().BoolVarP(&checkArgs.pre, "pre", "", false,
"only run pre-installation checks") "only run pre-installation checks")
checkCmd.Flags().StringSliceVar(&checkComponents, "components", defaults.Components, checkCmd.Flags().StringSliceVar(&checkArgs.components, "components", rootArgs.defaults.Components,
"list of components, accepts comma-separated values") "list of components, accepts comma-separated values")
rootCmd.AddCommand(checkCmd) rootCmd.AddCommand(checkCmd)
} }
func runCheckCmd(cmd *cobra.Command, args []string) error { func runCheckCmd(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
logger.Actionf("checking prerequisites") logger.Actionf("checking prerequisites")
@ -76,7 +78,7 @@ func runCheckCmd(cmd *cobra.Command, args []string) error {
checkFailed = true checkFailed = true
} }
if checkPre { if checkArgs.pre {
if checkFailed { if checkFailed {
os.Exit(1) os.Exit(1)
} }
@ -103,7 +105,7 @@ func kubectlCheck(ctx context.Context, version string) bool {
} }
kubectlArgs := []string{"version", "--client", "--output", "json"} kubectlArgs := []string{"version", "--client", "--output", "json"}
output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubeconfig, kubecontext, kubectlArgs...) output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
if err != nil { if err != nil {
logger.Failuref("kubectl version can't be determined") logger.Failuref("kubectl version can't be determined")
return false return false
@ -132,7 +134,7 @@ func kubectlCheck(ctx context.Context, version string) bool {
} }
func kubernetesCheck(version string) bool { func kubernetesCheck(version string) bool {
cfg, err := utils.KubeConfig(kubeconfig, kubecontext) cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
logger.Failuref("Kubernetes client initialization failed: %s", err.Error()) logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
return false return false
@ -167,20 +169,20 @@ func kubernetesCheck(version string) bool {
} }
func componentsCheck() bool { func componentsCheck() bool {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
ok := true ok := true
for _, deployment := range checkComponents { for _, deployment := range checkArgs.components {
kubectlArgs := []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()} kubectlArgs := []string{"-n", rootArgs.namespace, "rollout", "status", "deployment", deployment, "--timeout", rootArgs.timeout.String()}
if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubeconfig, kubecontext, kubectlArgs...); err != nil { if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
logger.Failuref("%s: %s", deployment, strings.TrimSuffix(output, "\n")) logger.Failuref("%s: %s", deployment, strings.TrimSuffix(output, "\n"))
ok = false ok = false
} else { } else {
logger.Successf("%s is healthy", deployment) logger.Successf("%s is healthy", deployment)
} }
kubectlArgs = []string{"-n", namespace, "get", "deployment", deployment, "-o", "jsonpath=\"{..image}\""} kubectlArgs = []string{"-n", rootArgs.namespace, "get", "deployment", deployment, "-o", "jsonpath=\"{..image}\""}
if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, kubeconfig, kubecontext, kubectlArgs...); err == nil { if output, err := utils.ExecKubectlCommand(ctx, utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err == nil {
logger.Actionf(strings.TrimPrefix(strings.TrimSuffix(output, "\""), "\"")) logger.Actionf(strings.TrimPrefix(strings.TrimSuffix(output, "\""), "\""))
} }
} }

@ -38,16 +38,18 @@ var createCmd = &cobra.Command{
Long: "The create sub-commands generate sources and resources.", Long: "The create sub-commands generate sources and resources.",
} }
var ( type createFlags struct {
interval time.Duration interval time.Duration
export bool export bool
labels []string labels []string
) }
var createArgs createFlags
func init() { func init() {
createCmd.PersistentFlags().DurationVarP(&interval, "interval", "", time.Minute, "source sync interval") createCmd.PersistentFlags().DurationVarP(&createArgs.interval, "interval", "", time.Minute, "source sync interval")
createCmd.PersistentFlags().BoolVar(&export, "export", false, "export in YAML format to stdout") createCmd.PersistentFlags().BoolVar(&createArgs.export, "export", false, "export in YAML format to stdout")
createCmd.PersistentFlags().StringSliceVar(&labels, "label", nil, createCmd.PersistentFlags().StringSliceVar(&createArgs.labels, "label", nil,
"set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)") "set labels on the resource (can specify multiple labels with commas: label1=value1,label2=value2)")
rootCmd.AddCommand(createCmd) rootCmd.AddCommand(createCmd)
} }
@ -99,10 +101,10 @@ type upsertWaitable interface {
// resource, then waiting for it to reconcile. See the note on // resource, then waiting for it to reconcile. See the note on
// `upsert` for how to work with the `mutate` argument. // `upsert` for how to work with the `mutate` argument.
func (names apiType) upsertAndWait(object upsertWaitable, mutate func() error) error { func (names apiType) upsertAndWait(object upsertWaitable, mutate func() error) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) // NB globals kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext) // NB globals
if err != nil { if err != nil {
return err return err
} }
@ -116,7 +118,7 @@ func (names apiType) upsertAndWait(object upsertWaitable, mutate func() error) e
} }
logger.Waitingf("waiting for %s reconciliation", names.kind) logger.Waitingf("waiting for %s reconciliation", names.kind)
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isReady(ctx, kubeClient, namespacedName, object)); err != nil { isReady(ctx, kubeClient, namespacedName, object)); err != nil {
return err return err
} }
@ -126,7 +128,7 @@ func (names apiType) upsertAndWait(object upsertWaitable, mutate func() error) e
func parseLabels() (map[string]string, error) { func parseLabels() (map[string]string, error) {
result := make(map[string]string) result := make(map[string]string)
for _, label := range labels { for _, label := range createArgs.labels {
// validate key value pair // validate key value pair
parts := strings.Split(label, "=") parts := strings.Split(label, "=")
if len(parts) != 2 { if len(parts) != 2 {

@ -49,16 +49,18 @@ var createAlertCmd = &cobra.Command{
RunE: createAlertCmdRun, RunE: createAlertCmdRun,
} }
var ( type alertFlags struct {
aProviderRef string providerRef string
aEventSeverity string eventSeverity string
aEventSources []string eventSources []string
) }
var alertArgs alertFlags
func init() { func init() {
createAlertCmd.Flags().StringVar(&aProviderRef, "provider-ref", "", "reference to provider") createAlertCmd.Flags().StringVar(&alertArgs.providerRef, "provider-ref", "", "reference to provider")
createAlertCmd.Flags().StringVar(&aEventSeverity, "event-severity", "", "severity of events to send alerts for") createAlertCmd.Flags().StringVar(&alertArgs.eventSeverity, "event-severity", "", "severity of events to send alerts for")
createAlertCmd.Flags().StringArrayVar(&aEventSources, "event-source", []string{}, "sources that should generate alerts (<kind>/<name>)") createAlertCmd.Flags().StringArrayVar(&alertArgs.eventSources, "event-source", []string{}, "sources that should generate alerts (<kind>/<name>)")
createCmd.AddCommand(createAlertCmd) createCmd.AddCommand(createAlertCmd)
} }
@ -68,12 +70,12 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
if aProviderRef == "" { if alertArgs.providerRef == "" {
return fmt.Errorf("provider ref is required") return fmt.Errorf("provider ref is required")
} }
eventSources := []notificationv1.CrossNamespaceObjectReference{} eventSources := []notificationv1.CrossNamespaceObjectReference{}
for _, eventSource := range aEventSources { for _, eventSource := range alertArgs.eventSources {
kind, name := utils.ParseObjectKindName(eventSource) kind, name := utils.ParseObjectKindName(eventSource)
if kind == "" { if kind == "" {
return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", eventSource) return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", eventSource)
@ -94,34 +96,34 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !export { if !createArgs.export {
logger.Generatef("generating Alert") logger.Generatef("generating Alert")
} }
alert := notificationv1.Alert{ alert := notificationv1.Alert{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: notificationv1.AlertSpec{ Spec: notificationv1.AlertSpec{
ProviderRef: corev1.LocalObjectReference{ ProviderRef: corev1.LocalObjectReference{
Name: aProviderRef, Name: alertArgs.providerRef,
}, },
EventSeverity: aEventSeverity, EventSeverity: alertArgs.eventSeverity,
EventSources: eventSources, EventSources: eventSources,
Suspend: false, Suspend: false,
}, },
} }
if export { if createArgs.export {
return exportAlert(alert) return exportAlert(alert)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@ -133,7 +135,7 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for Alert reconciliation") logger.Waitingf("waiting for Alert reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isAlertReady(ctx, kubeClient, namespacedName, &alert)); err != nil { isAlertReady(ctx, kubeClient, namespacedName, &alert)); err != nil {
return err return err
} }

@ -54,20 +54,22 @@ var createAlertProviderCmd = &cobra.Command{
RunE: createAlertProviderCmdRun, RunE: createAlertProviderCmdRun,
} }
var ( type alertProviderFlags struct {
apType string alertType string
apChannel string channel string
apUsername string username string
apAddress string address string
apSecretRef string secretRef string
) }
var alertProviderArgs alertProviderFlags
func init() { func init() {
createAlertProviderCmd.Flags().StringVar(&apType, "type", "", "type of provider") createAlertProviderCmd.Flags().StringVar(&alertProviderArgs.alertType, "type", "", "type of provider")
createAlertProviderCmd.Flags().StringVar(&apChannel, "channel", "", "channel to send messages to in the case of a chat provider") createAlertProviderCmd.Flags().StringVar(&alertProviderArgs.channel, "channel", "", "channel to send messages to in the case of a chat provider")
createAlertProviderCmd.Flags().StringVar(&apUsername, "username", "", "bot username used by the provider") createAlertProviderCmd.Flags().StringVar(&alertProviderArgs.username, "username", "", "bot username used by the provider")
createAlertProviderCmd.Flags().StringVar(&apAddress, "address", "", "path to either the git repository, chat provider or webhook") createAlertProviderCmd.Flags().StringVar(&alertProviderArgs.address, "address", "", "path to either the git repository, chat provider or webhook")
createAlertProviderCmd.Flags().StringVar(&apSecretRef, "secret-ref", "", "name of secret containing authentication token") createAlertProviderCmd.Flags().StringVar(&alertProviderArgs.secretRef, "secret-ref", "", "name of secret containing authentication token")
createCmd.AddCommand(createAlertProviderCmd) createCmd.AddCommand(createAlertProviderCmd)
} }
@ -77,7 +79,7 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
if apType == "" { if alertProviderArgs.alertType == "" {
return fmt.Errorf("Provider type is required") return fmt.Errorf("Provider type is required")
} }
@ -86,38 +88,38 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !export { if !createArgs.export {
logger.Generatef("generating Provider") logger.Generatef("generating Provider")
} }
provider := notificationv1.Provider{ provider := notificationv1.Provider{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: notificationv1.ProviderSpec{ Spec: notificationv1.ProviderSpec{
Type: apType, Type: alertProviderArgs.alertType,
Channel: apChannel, Channel: alertProviderArgs.channel,
Username: apUsername, Username: alertProviderArgs.username,
Address: apAddress, Address: alertProviderArgs.address,
}, },
} }
if apSecretRef != "" { if alertProviderArgs.secretRef != "" {
provider.Spec.SecretRef = &corev1.LocalObjectReference{ provider.Spec.SecretRef = &corev1.LocalObjectReference{
Name: apSecretRef, Name: alertProviderArgs.secretRef,
} }
} }
if export { if createArgs.export {
return exportAlertProvider(provider) return exportAlertProvider(provider)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@ -129,7 +131,7 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for Provider reconciliation") logger.Waitingf("waiting for Provider reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isAlertProviderReady(ctx, kubeClient, namespacedName, &provider)); err != nil { isAlertProviderReady(ctx, kubeClient, namespacedName, &provider)); err != nil {
return err return err
} }

@ -98,28 +98,30 @@ var createHelmReleaseCmd = &cobra.Command{
RunE: createHelmReleaseCmdRun, RunE: createHelmReleaseCmdRun,
} }
var ( type helmReleaseFlags struct {
hrName string name string
hrSource flags.HelmChartSource source flags.HelmChartSource
hrDependsOn []string dependsOn []string
hrChart string chart string
hrChartVersion string chartVersion string
hrTargetNamespace string targetNamespace string
hrValuesFile string valuesFile string
hrValuesFrom flags.HelmReleaseValuesFrom valuesFrom flags.HelmReleaseValuesFrom
hrSAName string saName string
) }
var helmReleaseArgs helmReleaseFlags
func init() { func init() {
createHelmReleaseCmd.Flags().StringVar(&hrName, "release-name", "", "name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.name, "release-name", "", "name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'")
createHelmReleaseCmd.Flags().Var(&hrSource, "source", hrSource.Description()) createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.source, "source", helmReleaseArgs.source.Description())
createHelmReleaseCmd.Flags().StringVar(&hrChart, "chart", "", "Helm chart name or path") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.chart, "chart", "", "Helm chart name or path")
createHelmReleaseCmd.Flags().StringVar(&hrChartVersion, "chart-version", "", "Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.chartVersion, "chart-version", "", "Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)")
createHelmReleaseCmd.Flags().StringArrayVar(&hrDependsOn, "depends-on", nil, "HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'") createHelmReleaseCmd.Flags().StringArrayVar(&helmReleaseArgs.dependsOn, "depends-on", nil, "HelmReleases that must be ready before this release can be installed, supported formats '<name>' and '<namespace>/<name>'")
createHelmReleaseCmd.Flags().StringVar(&hrTargetNamespace, "target-namespace", "", "namespace to install this release, defaults to the HelmRelease namespace") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.targetNamespace, "target-namespace", "", "namespace to install this release, defaults to the HelmRelease namespace")
createHelmReleaseCmd.Flags().StringVar(&hrSAName, "service-account", "", "the name of the service account to impersonate when reconciling this HelmRelease") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.saName, "service-account", "", "the name of the service account to impersonate when reconciling this HelmRelease")
createHelmReleaseCmd.Flags().StringVar(&hrValuesFile, "values", "", "local path to the values.yaml file") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.valuesFile, "values", "", "local path to the values.yaml file")
createHelmReleaseCmd.Flags().Var(&hrValuesFrom, "values-from", hrValuesFrom.Description()) createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.valuesFrom, "values-from", helmReleaseArgs.valuesFrom.Description())
createCmd.AddCommand(createHelmReleaseCmd) createCmd.AddCommand(createHelmReleaseCmd)
} }
@ -129,7 +131,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
if hrChart == "" { if helmReleaseArgs.chart == "" {
return fmt.Errorf("chart name or path is required") return fmt.Errorf("chart name or path is required")
} }
@ -138,30 +140,30 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !export { if !createArgs.export {
logger.Generatef("generating HelmRelease") logger.Generatef("generating HelmRelease")
} }
helmRelease := helmv2.HelmRelease{ helmRelease := helmv2.HelmRelease{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: helmv2.HelmReleaseSpec{ Spec: helmv2.HelmReleaseSpec{
ReleaseName: hrName, ReleaseName: helmReleaseArgs.name,
DependsOn: utils.MakeDependsOn(hrDependsOn), DependsOn: utils.MakeDependsOn(helmReleaseArgs.dependsOn),
Interval: metav1.Duration{ Interval: metav1.Duration{
Duration: interval, Duration: createArgs.interval,
}, },
TargetNamespace: hrTargetNamespace, TargetNamespace: helmReleaseArgs.targetNamespace,
Chart: helmv2.HelmChartTemplate{ Chart: helmv2.HelmChartTemplate{
Spec: helmv2.HelmChartTemplateSpec{ Spec: helmv2.HelmChartTemplateSpec{
Chart: hrChart, Chart: helmReleaseArgs.chart,
Version: hrChartVersion, Version: helmReleaseArgs.chartVersion,
SourceRef: helmv2.CrossNamespaceObjectReference{ SourceRef: helmv2.CrossNamespaceObjectReference{
Kind: hrSource.Kind, Kind: helmReleaseArgs.source.Kind,
Name: hrSource.Name, Name: helmReleaseArgs.source.Name,
}, },
}, },
}, },
@ -169,39 +171,39 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
}, },
} }
if hrSAName != "" { if helmReleaseArgs.saName != "" {
helmRelease.Spec.ServiceAccountName = hrSAName helmRelease.Spec.ServiceAccountName = helmReleaseArgs.saName
} }
if hrValuesFile != "" { if helmReleaseArgs.valuesFile != "" {
data, err := ioutil.ReadFile(hrValuesFile) data, err := ioutil.ReadFile(helmReleaseArgs.valuesFile)
if err != nil { if err != nil {
return fmt.Errorf("reading values from %s failed: %w", hrValuesFile, err) return fmt.Errorf("reading values from %s failed: %w", helmReleaseArgs.valuesFile, err)
} }
json, err := yaml.YAMLToJSON(data) json, err := yaml.YAMLToJSON(data)
if err != nil { if err != nil {
return fmt.Errorf("converting values to JSON from %s failed: %w", hrValuesFile, err) return fmt.Errorf("converting values to JSON from %s failed: %w", helmReleaseArgs.valuesFile, err)
} }
helmRelease.Spec.Values = &apiextensionsv1.JSON{Raw: json} helmRelease.Spec.Values = &apiextensionsv1.JSON{Raw: json}
} }
if hrValuesFrom.String() != "" { if helmReleaseArgs.valuesFrom.String() != "" {
helmRelease.Spec.ValuesFrom = []helmv2.ValuesReference{{ helmRelease.Spec.ValuesFrom = []helmv2.ValuesReference{{
Kind: hrValuesFrom.Kind, Kind: helmReleaseArgs.valuesFrom.Kind,
Name: hrValuesFrom.Name, Name: helmReleaseArgs.valuesFrom.Name,
}} }}
} }
if export { if createArgs.export {
return exportHelmRelease(helmRelease) return exportHelmRelease(helmRelease)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@ -213,7 +215,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for HelmRelease reconciliation") logger.Waitingf("waiting for HelmRelease reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isHelmReleaseReady(ctx, kubeClient, namespacedName, &helmRelease)); err != nil { isHelmReleaseReady(ctx, kubeClient, namespacedName, &helmRelease)); err != nil {
return err return err
} }

@ -78,7 +78,7 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
var policy = imagev1.ImagePolicy{ var policy = imagev1.ImagePolicy{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: objectName, Name: objectName,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
}, },
Spec: imagev1.ImagePolicySpec{ Spec: imagev1.ImagePolicySpec{
@ -103,7 +103,7 @@ func createImagePolicyRun(cmd *cobra.Command, args []string) error {
} }
} }
if export { if createArgs.export {
return printExport(exportImagePolicy(&policy)) return printExport(exportImagePolicy(&policy))
} }

@ -77,12 +77,12 @@ func createImageRepositoryRun(cmd *cobra.Command, args []string) error {
var repo = imagev1.ImageRepository{ var repo = imagev1.ImageRepository{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: objectName, Name: objectName,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
}, },
Spec: imagev1.ImageRepositorySpec{ Spec: imagev1.ImageRepositorySpec{
Image: imageRepoArgs.image, Image: imageRepoArgs.image,
Interval: metav1.Duration{Duration: interval}, Interval: metav1.Duration{Duration: createArgs.interval},
}, },
} }
if imageRepoArgs.timeout != 0 { if imageRepoArgs.timeout != 0 {
@ -94,7 +94,7 @@ func createImageRepositoryRun(cmd *cobra.Command, args []string) error {
} }
} }
if export { if createArgs.export {
return printExport(exportImageRepository(&repo)) return printExport(exportImageRepository(&repo))
} }

@ -80,7 +80,7 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
var update = autov1.ImageUpdateAutomation{ var update = autov1.ImageUpdateAutomation{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: objectName, Name: objectName,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: labels, Labels: labels,
}, },
Spec: autov1.ImageUpdateAutomationSpec{ Spec: autov1.ImageUpdateAutomationSpec{
@ -90,7 +90,7 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
}, },
Branch: imageUpdateArgs.branch, Branch: imageUpdateArgs.branch,
}, },
Interval: metav1.Duration{Duration: interval}, Interval: metav1.Duration{Duration: createArgs.interval},
Update: autov1.UpdateStrategy{ Update: autov1.UpdateStrategy{
Setters: &autov1.SettersStrategy{}, Setters: &autov1.SettersStrategy{},
}, },
@ -102,7 +102,7 @@ func createImageUpdateRun(cmd *cobra.Command, args []string) error {
}, },
} }
if export { if createArgs.export {
return printExport(exportImageUpdate(&update)) return printExport(exportImageUpdate(&update))
} }

@ -72,53 +72,61 @@ var createKsCmd = &cobra.Command{
RunE: createKsCmdRun, RunE: createKsCmdRun,
} }
var ( type kustomizationFlags struct {
ksSource flags.KustomizationSource source flags.KustomizationSource
ksPath flags.SafeRelativePath = "./" path flags.SafeRelativePath
ksPrune bool prune bool
ksDependsOn []string dependsOn []string
ksValidation string validation string
ksHealthCheck []string healthCheck []string
ksHealthTimeout time.Duration healthTimeout time.Duration
ksSAName string saName string
ksDecryptionProvider flags.DecryptionProvider decryptionProvider flags.DecryptionProvider
ksDecryptionSecret string decryptionSecret string
ksTargetNamespace string targetNamespace string
) }
var kustomizationArgs = NewKustomizationFlags()
func init() { func init() {
createKsCmd.Flags().Var(&ksSource, "source", ksSource.Description()) createKsCmd.Flags().Var(&kustomizationArgs.source, "source", kustomizationArgs.source.Description())
createKsCmd.Flags().Var(&ksPath, "path", "path to the directory containing a kustomization.yaml file") createKsCmd.Flags().Var(&kustomizationArgs.path, "path", "path to the directory containing a kustomization.yaml file")
createKsCmd.Flags().BoolVar(&ksPrune, "prune", false, "enable garbage collection") createKsCmd.Flags().BoolVar(&kustomizationArgs.prune, "prune", false, "enable garbage collection")
createKsCmd.Flags().StringArrayVar(&ksHealthCheck, "health-check", nil, "workload to be included in the health assessment, in the format '<kind>/<name>.<namespace>'") createKsCmd.Flags().StringArrayVar(&kustomizationArgs.healthCheck, "health-check", nil, "workload to be included in the health assessment, in the format '<kind>/<name>.<namespace>'")
createKsCmd.Flags().DurationVar(&ksHealthTimeout, "health-check-timeout", 2*time.Minute, "timeout of health checking operations") createKsCmd.Flags().DurationVar(&kustomizationArgs.healthTimeout, "health-check-timeout", 2*time.Minute, "timeout of health checking operations")
createKsCmd.Flags().StringVar(&ksValidation, "validation", "", "validate the manifests before applying them on the cluster, can be 'client' or 'server'") createKsCmd.Flags().StringVar(&kustomizationArgs.validation, "validation", "", "validate the manifests before applying them on the cluster, can be 'client' or 'server'")
createKsCmd.Flags().StringArrayVar(&ksDependsOn, "depends-on", nil, "Kustomization that must be ready before this Kustomization can be applied, supported formats '<name>' and '<namespace>/<name>'") createKsCmd.Flags().StringArrayVar(&kustomizationArgs.dependsOn, "depends-on", nil, "Kustomization that must be ready before this Kustomization can be applied, supported formats '<name>' and '<namespace>/<name>'")
createKsCmd.Flags().StringVar(&ksSAName, "service-account", "", "the name of the service account to impersonate when reconciling this Kustomization") createKsCmd.Flags().StringVar(&kustomizationArgs.saName, "service-account", "", "the name of the service account to impersonate when reconciling this Kustomization")
createKsCmd.Flags().Var(&ksDecryptionProvider, "decryption-provider", ksDecryptionProvider.Description()) createKsCmd.Flags().Var(&kustomizationArgs.decryptionProvider, "decryption-provider", kustomizationArgs.decryptionProvider.Description())
createKsCmd.Flags().StringVar(&ksDecryptionSecret, "decryption-secret", "", "set the Kubernetes secret name that contains the OpenPGP private keys used for sops decryption") createKsCmd.Flags().StringVar(&kustomizationArgs.decryptionSecret, "decryption-secret", "", "set the Kubernetes secret name that contains the OpenPGP private keys used for sops decryption")
createKsCmd.Flags().StringVar(&ksTargetNamespace, "target-namespace", "", "overrides the namespace of all Kustomization objects reconciled by this Kustomization") createKsCmd.Flags().StringVar(&kustomizationArgs.targetNamespace, "target-namespace", "", "overrides the namespace of all Kustomization objects reconciled by this Kustomization")
createCmd.AddCommand(createKsCmd) createCmd.AddCommand(createKsCmd)
} }
func NewKustomizationFlags() kustomizationFlags {
return kustomizationFlags{
path: "./",
}
}
func createKsCmdRun(cmd *cobra.Command, args []string) error { func createKsCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 { if len(args) < 1 {
return fmt.Errorf("Kustomization name is required") return fmt.Errorf("Kustomization name is required")
} }
name := args[0] name := args[0]
if ksPath == "" { if kustomizationArgs.path == "" {
return fmt.Errorf("path is required") return fmt.Errorf("path is required")
} }
if !strings.HasPrefix(ksPath.String(), "./") { if !strings.HasPrefix(kustomizationArgs.path.String(), "./") {
return fmt.Errorf("path must begin with ./") return fmt.Errorf("path must begin with ./")
} }
if !export { if !createArgs.export {
logger.Generatef("generating Kustomization") logger.Generatef("generating Kustomization")
} }
ksLabels, err := parseLabels() kslabels, err := parseLabels()
if err != nil { if err != nil {
return err return err
} }
@ -126,29 +134,29 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
kustomization := kustomizev1.Kustomization{ kustomization := kustomizev1.Kustomization{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: ksLabels, Labels: kslabels,
}, },
Spec: kustomizev1.KustomizationSpec{ Spec: kustomizev1.KustomizationSpec{
DependsOn: utils.MakeDependsOn(ksDependsOn), DependsOn: utils.MakeDependsOn(kustomizationArgs.dependsOn),
Interval: metav1.Duration{ Interval: metav1.Duration{
Duration: interval, Duration: createArgs.interval,
}, },
Path: ksPath.String(), Path: kustomizationArgs.path.String(),
Prune: ksPrune, Prune: kustomizationArgs.prune,
SourceRef: kustomizev1.CrossNamespaceSourceReference{ SourceRef: kustomizev1.CrossNamespaceSourceReference{
Kind: ksSource.Kind, Kind: kustomizationArgs.source.Kind,
Name: ksSource.Name, Name: kustomizationArgs.source.Name,
}, },
Suspend: false, Suspend: false,
Validation: ksValidation, Validation: kustomizationArgs.validation,
TargetNamespace: ksTargetNamespace, TargetNamespace: kustomizationArgs.targetNamespace,
}, },
} }
if len(ksHealthCheck) > 0 { if len(kustomizationArgs.healthCheck) > 0 {
healthChecks := make([]kustomizev1.CrossNamespaceObjectReference, 0) healthChecks := make([]kustomizev1.CrossNamespaceObjectReference, 0)
for _, w := range ksHealthCheck { for _, w := range kustomizationArgs.healthCheck {
kindObj := strings.Split(w, "/") kindObj := strings.Split(w, "/")
if len(kindObj) != 2 { if len(kindObj) != 2 {
return fmt.Errorf("invalid health check '%s' must be in the format 'kind/name.namespace' %v", w, kindObj) return fmt.Errorf("invalid health check '%s' must be in the format 'kind/name.namespace' %v", w, kindObj)
@ -183,32 +191,32 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
} }
kustomization.Spec.HealthChecks = healthChecks kustomization.Spec.HealthChecks = healthChecks
kustomization.Spec.Timeout = &metav1.Duration{ kustomization.Spec.Timeout = &metav1.Duration{
Duration: ksHealthTimeout, Duration: kustomizationArgs.healthTimeout,
} }
} }
if ksSAName != "" { if kustomizationArgs.saName != "" {
kustomization.Spec.ServiceAccountName = ksSAName kustomization.Spec.ServiceAccountName = kustomizationArgs.saName
} }
if ksDecryptionProvider != "" { if kustomizationArgs.decryptionProvider != "" {
kustomization.Spec.Decryption = &kustomizev1.Decryption{ kustomization.Spec.Decryption = &kustomizev1.Decryption{
Provider: ksDecryptionProvider.String(), Provider: kustomizationArgs.decryptionProvider.String(),
} }
if ksDecryptionSecret != "" { if kustomizationArgs.decryptionSecret != "" {
kustomization.Spec.Decryption.SecretRef = &corev1.LocalObjectReference{Name: ksDecryptionSecret} kustomization.Spec.Decryption.SecretRef = &corev1.LocalObjectReference{Name: kustomizationArgs.decryptionSecret}
} }
} }
if export { if createArgs.export {
return exportKs(kustomization) return exportKs(kustomization)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@ -220,7 +228,7 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for Kustomization reconciliation") logger.Waitingf("waiting for Kustomization reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isKustomizationReady(ctx, kubeClient, namespacedName, &kustomization)); err != nil { isKustomizationReady(ctx, kubeClient, namespacedName, &kustomization)); err != nil {
return err return err
} }

@ -50,18 +50,20 @@ var createReceiverCmd = &cobra.Command{
RunE: createReceiverCmdRun, RunE: createReceiverCmdRun,
} }
var ( type receiverFlags struct {
rcvType string receiverType string
rcvSecretRef string secretRef string
rcvEvents []string events []string
rcvResources []string resources []string
) }
var receiverArgs receiverFlags
func init() { func init() {
createReceiverCmd.Flags().StringVar(&rcvType, "type", "", "") createReceiverCmd.Flags().StringVar(&receiverArgs.receiverType, "type", "", "")
createReceiverCmd.Flags().StringVar(&rcvSecretRef, "secret-ref", "", "") createReceiverCmd.Flags().StringVar(&receiverArgs.secretRef, "secret-ref", "", "")
createReceiverCmd.Flags().StringArrayVar(&rcvEvents, "event", []string{}, "") createReceiverCmd.Flags().StringArrayVar(&receiverArgs.events, "event", []string{}, "")
createReceiverCmd.Flags().StringArrayVar(&rcvResources, "resource", []string{}, "") createReceiverCmd.Flags().StringArrayVar(&receiverArgs.resources, "resource", []string{}, "")
createCmd.AddCommand(createReceiverCmd) createCmd.AddCommand(createReceiverCmd)
} }
@ -71,16 +73,16 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
if rcvType == "" { if receiverArgs.receiverType == "" {
return fmt.Errorf("Receiver type is required") return fmt.Errorf("Receiver type is required")
} }
if rcvSecretRef == "" { if receiverArgs.secretRef == "" {
return fmt.Errorf("secret ref is required") return fmt.Errorf("secret ref is required")
} }
resources := []notificationv1.CrossNamespaceObjectReference{} resources := []notificationv1.CrossNamespaceObjectReference{}
for _, resource := range rcvResources { for _, resource := range receiverArgs.resources {
kind, name := utils.ParseObjectKindName(resource) kind, name := utils.ParseObjectKindName(resource)
if kind == "" { if kind == "" {
return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", resource) return fmt.Errorf("invalid event source '%s', must be in format <kind>/<name>", resource)
@ -101,35 +103,35 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !export { if !createArgs.export {
logger.Generatef("generating Receiver") logger.Generatef("generating Receiver")
} }
receiver := notificationv1.Receiver{ receiver := notificationv1.Receiver{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: notificationv1.ReceiverSpec{ Spec: notificationv1.ReceiverSpec{
Type: rcvType, Type: receiverArgs.receiverType,
Events: rcvEvents, Events: receiverArgs.events,
Resources: resources, Resources: resources,
SecretRef: corev1.LocalObjectReference{ SecretRef: corev1.LocalObjectReference{
Name: rcvSecretRef, Name: receiverArgs.secretRef,
}, },
Suspend: false, Suspend: false,
}, },
} }
if export { if createArgs.export {
return exportReceiver(receiver) return exportReceiver(receiver)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@ -141,7 +143,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for Receiver reconciliation") logger.Waitingf("waiting for Receiver reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isReceiverReady(ctx, kubeClient, namespacedName, &receiver)); err != nil { isReceiverReady(ctx, kubeClient, namespacedName, &receiver)); err != nil {
return err return err
} }

@ -71,37 +71,47 @@ For Git over HTTP/S, the provided basic authentication credentials are stored in
RunE: createSecretGitCmdRun, RunE: createSecretGitCmdRun,
} }
var ( type secretGitFlags struct {
secretGitURL string url string
secretGitUsername string username string
secretGitPassword string password string
secretGitKeyAlgorithm flags.PublicKeyAlgorithm = "rsa" keyAlgorithm flags.PublicKeyAlgorithm
secretGitRSABits flags.RSAKeyBits = 2048 rsaBits flags.RSAKeyBits
secretGitECDSACurve = flags.ECDSACurve{Curve: elliptic.P384()} ecdsaCurve flags.ECDSACurve
) }
var secretGitArgs = NewSecretGitFlags()
func init() { func init() {
createSecretGitCmd.Flags().StringVar(&secretGitURL, "url", "", "git address, e.g. ssh://git@host/org/repository") createSecretGitCmd.Flags().StringVar(&secretGitArgs.url, "url", "", "git address, e.g. ssh://git@host/org/repository")
createSecretGitCmd.Flags().StringVarP(&secretGitUsername, "username", "u", "", "basic authentication username") createSecretGitCmd.Flags().StringVarP(&secretGitArgs.username, "username", "u", "", "basic authentication username")
createSecretGitCmd.Flags().StringVarP(&secretGitPassword, "password", "p", "", "basic authentication password") createSecretGitCmd.Flags().StringVarP(&secretGitArgs.password, "password", "p", "", "basic authentication password")
createSecretGitCmd.Flags().Var(&secretGitKeyAlgorithm, "ssh-key-algorithm", secretGitKeyAlgorithm.Description()) createSecretGitCmd.Flags().Var(&secretGitArgs.keyAlgorithm, "ssh-key-algorithm", secretGitArgs.keyAlgorithm.Description())
createSecretGitCmd.Flags().Var(&secretGitRSABits, "ssh-rsa-bits", secretGitRSABits.Description()) createSecretGitCmd.Flags().Var(&secretGitArgs.rsaBits, "ssh-rsa-bits", secretGitArgs.rsaBits.Description())
createSecretGitCmd.Flags().Var(&secretGitECDSACurve, "ssh-ecdsa-curve", secretGitECDSACurve.Description()) createSecretGitCmd.Flags().Var(&secretGitArgs.ecdsaCurve, "ssh-ecdsa-curve", secretGitArgs.ecdsaCurve.Description())
createSecretCmd.AddCommand(createSecretGitCmd) createSecretCmd.AddCommand(createSecretGitCmd)
} }
func NewSecretGitFlags() secretGitFlags {
return secretGitFlags{
keyAlgorithm: "rsa",
rsaBits: 2048,
ecdsaCurve: flags.ECDSACurve{Curve: elliptic.P384()},
}
}
func createSecretGitCmdRun(cmd *cobra.Command, args []string) error { func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 { if len(args) < 1 {
return fmt.Errorf("secret name is required") return fmt.Errorf("secret name is required")
} }
name := args[0] name := args[0]
if secretGitURL == "" { if secretGitArgs.url == "" {
return fmt.Errorf("url is required") return fmt.Errorf("url is required")
} }
u, err := url.Parse(secretGitURL) u, err := url.Parse(secretGitArgs.url)
if err != nil { if err != nil {
return fmt.Errorf("git URL parse failed: %w", err) return fmt.Errorf("git URL parse failed: %w", err)
} }
@ -111,20 +121,20 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: secretLabels, Labels: secretLabels,
}, },
} }
switch u.Scheme { switch u.Scheme {
case "ssh": case "ssh":
pair, err := generateKeyPair(ctx, secretGitKeyAlgorithm, secretGitRSABits, secretGitECDSACurve) pair, err := generateKeyPair(ctx, secretGitArgs.keyAlgorithm, secretGitArgs.rsaBits, secretGitArgs.ecdsaCurve)
if err != nil { if err != nil {
return err return err
} }
@ -140,28 +150,28 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
"known_hosts": hostKey, "known_hosts": hostKey,
} }
if !export { if !createArgs.export {
logger.Generatef("deploy key: %s", string(pair.PublicKey)) logger.Generatef("deploy key: %s", string(pair.PublicKey))
} }
case "http", "https": case "http", "https":
if secretGitUsername == "" || secretGitPassword == "" { if secretGitArgs.username == "" || secretGitArgs.password == "" {
return fmt.Errorf("for Git over HTTP/S the username and password are required") return fmt.Errorf("for Git over HTTP/S the username and password are required")
} }
// TODO: add cert data when it's implemented in source-controller // TODO: add cert data when it's implemented in source-controller
secret.Data = map[string][]byte{ secret.Data = map[string][]byte{
"username": []byte(secretGitUsername), "username": []byte(secretGitArgs.username),
"password": []byte(secretGitPassword), "password": []byte(secretGitArgs.password),
} }
default: default:
return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme) return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme)
} }
if export { if createArgs.export {
return exportSecret(secret) return exportSecret(secret)
} }
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@ -169,7 +179,7 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
if err := upsertSecret(ctx, kubeClient, secret); err != nil { if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err return err
} }
logger.Actionf("secret '%s' created in '%s' namespace", name, namespace) logger.Actionf("secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil return nil
} }

@ -55,20 +55,22 @@ The create secret helm command generates a Kubernetes secret with basic authenti
RunE: createSecretHelmCmdRun, RunE: createSecretHelmCmdRun,
} }
var ( type secretHelmFlags struct {
secretHelmUsername string username string
secretHelmPassword string password string
secretHelmCertFile string certFile string
secretHelmKeyFile string keyFile string
secretHelmCAFile string caFile string
) }
var secretHelmArgs secretHelmFlags
func init() { func init() {
createSecretHelmCmd.Flags().StringVarP(&secretHelmUsername, "username", "u", "", "basic authentication username") createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.username, "username", "u", "", "basic authentication username")
createSecretHelmCmd.Flags().StringVarP(&secretHelmPassword, "password", "p", "", "basic authentication password") createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.password, "password", "p", "", "basic authentication password")
createSecretHelmCmd.Flags().StringVar(&secretHelmCertFile, "cert-file", "", "TLS authentication cert file path") createSecretHelmCmd.Flags().StringVar(&secretHelmArgs.certFile, "cert-file", "", "TLS authentication cert file path")
createSecretHelmCmd.Flags().StringVar(&secretHelmKeyFile, "key-file", "", "TLS authentication key file path") createSecretHelmCmd.Flags().StringVar(&secretHelmArgs.keyFile, "key-file", "", "TLS authentication key file path")
createSecretHelmCmd.Flags().StringVar(&secretHelmCAFile, "ca-file", "", "TLS authentication CA file path") createSecretHelmCmd.Flags().StringVar(&secretHelmArgs.caFile, "ca-file", "", "TLS authentication CA file path")
createSecretCmd.AddCommand(createSecretHelmCmd) createSecretCmd.AddCommand(createSecretHelmCmd)
} }
@ -87,47 +89,47 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: secretLabels, Labels: secretLabels,
}, },
StringData: map[string]string{}, StringData: map[string]string{},
} }
if secretHelmUsername != "" && secretHelmPassword != "" { if secretHelmArgs.username != "" && secretHelmArgs.password != "" {
secret.StringData["username"] = secretHelmUsername secret.StringData["username"] = secretHelmArgs.username
secret.StringData["password"] = secretHelmPassword secret.StringData["password"] = secretHelmArgs.password
} }
if secretHelmCertFile != "" && secretHelmKeyFile != "" { if secretHelmArgs.certFile != "" && secretHelmArgs.keyFile != "" {
cert, err := ioutil.ReadFile(secretHelmCertFile) cert, err := ioutil.ReadFile(secretHelmArgs.certFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to read repository cert file '%s': %w", secretHelmCertFile, err) return fmt.Errorf("failed to read repository cert file '%s': %w", secretHelmArgs.certFile, err)
} }
secret.StringData["certFile"] = string(cert) secret.StringData["certFile"] = string(cert)
key, err := ioutil.ReadFile(secretHelmKeyFile) key, err := ioutil.ReadFile(secretHelmArgs.keyFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to read repository key file '%s': %w", secretHelmKeyFile, err) return fmt.Errorf("failed to read repository key file '%s': %w", secretHelmArgs.keyFile, err)
} }
secret.StringData["keyFile"] = string(key) secret.StringData["keyFile"] = string(key)
} }
if secretHelmCAFile != "" { if secretHelmArgs.caFile != "" {
ca, err := ioutil.ReadFile(secretHelmCAFile) ca, err := ioutil.ReadFile(secretHelmArgs.caFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to read repository CA file '%s': %w", secretHelmCAFile, err) return fmt.Errorf("failed to read repository CA file '%s': %w", secretHelmArgs.caFile, err)
} }
secret.StringData["caFile"] = string(ca) secret.StringData["caFile"] = string(ca)
} }
if export { if createArgs.export {
return exportSecret(secret) return exportSecret(secret)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
@ -135,7 +137,7 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
if err := upsertSecret(ctx, kubeClient, secret); err != nil { if err := upsertSecret(ctx, kubeClient, secret); err != nil {
return err return err
} }
logger.Actionf("secret '%s' created in '%s' namespace", name, namespace) logger.Actionf("secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil return nil
} }

@ -61,41 +61,49 @@ For Buckets with static authentication, the credentials are stored in a Kubernet
RunE: createSourceBucketCmdRun, RunE: createSourceBucketCmdRun,
} }
var ( type sourceBucketFlags struct {
sourceBucketName string name string
sourceBucketProvider = flags.SourceBucketProvider(sourcev1.GenericBucketProvider) provider flags.SourceBucketProvider
sourceBucketEndpoint string endpoint string
sourceBucketAccessKey string accessKey string
sourceBucketSecretKey string secretKey string
sourceBucketRegion string region string
sourceBucketInsecure bool insecure bool
sourceBucketSecretRef string secretRef string
) }
var sourceBucketArgs = NewSourceBucketFlags()
func init() { func init() {
createSourceBucketCmd.Flags().Var(&sourceBucketProvider, "provider", sourceBucketProvider.Description()) createSourceBucketCmd.Flags().Var(&sourceBucketArgs.provider, "provider", sourceBucketArgs.provider.Description())
createSourceBucketCmd.Flags().StringVar(&sourceBucketName, "bucket-name", "", "the bucket name") createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.name, "bucket-name", "", "the bucket name")
createSourceBucketCmd.Flags().StringVar(&sourceBucketEndpoint, "endpoint", "", "the bucket endpoint address") createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.endpoint, "endpoint", "", "the bucket endpoint address")
createSourceBucketCmd.Flags().StringVar(&sourceBucketAccessKey, "access-key", "", "the bucket access key") createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.accessKey, "access-key", "", "the bucket access key")
createSourceBucketCmd.Flags().StringVar(&sourceBucketSecretKey, "secret-key", "", "the bucket secret key") createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.secretKey, "secret-key", "", "the bucket secret key")
createSourceBucketCmd.Flags().StringVar(&sourceBucketRegion, "region", "", "the bucket region") createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.region, "region", "", "the bucket region")
createSourceBucketCmd.Flags().BoolVar(&sourceBucketInsecure, "insecure", false, "for when connecting to a non-TLS S3 HTTP endpoint") createSourceBucketCmd.Flags().BoolVar(&sourceBucketArgs.insecure, "insecure", false, "for when connecting to a non-TLS S3 HTTP endpoint")
createSourceBucketCmd.Flags().StringVar(&sourceBucketSecretRef, "secret-ref", "", "the name of an existing secret containing credentials") createSourceBucketCmd.Flags().StringVar(&sourceBucketArgs.secretRef, "secret-ref", "", "the name of an existing secret containing credentials")
createSourceCmd.AddCommand(createSourceBucketCmd) createSourceCmd.AddCommand(createSourceBucketCmd)
} }
func NewSourceBucketFlags() sourceBucketFlags {
return sourceBucketFlags{
provider: flags.SourceBucketProvider(sourcev1.GenericBucketProvider),
}
}
func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error { func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 { if len(args) < 1 {
return fmt.Errorf("Bucket source name is required") return fmt.Errorf("Bucket source name is required")
} }
name := args[0] name := args[0]
if sourceBucketName == "" { if sourceBucketArgs.name == "" {
return fmt.Errorf("bucket-name is required") return fmt.Errorf("bucket-name is required")
} }
if sourceBucketEndpoint == "" { if sourceBucketArgs.endpoint == "" {
return fmt.Errorf("endpoint is required") return fmt.Errorf("endpoint is required")
} }
@ -113,55 +121,55 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
bucket := &sourcev1.Bucket{ bucket := &sourcev1.Bucket{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1.BucketSpec{ Spec: sourcev1.BucketSpec{
BucketName: sourceBucketName, BucketName: sourceBucketArgs.name,
Provider: sourceBucketProvider.String(), Provider: sourceBucketArgs.provider.String(),
Insecure: sourceBucketInsecure, Insecure: sourceBucketArgs.insecure,
Endpoint: sourceBucketEndpoint, Endpoint: sourceBucketArgs.endpoint,
Region: sourceBucketRegion, Region: sourceBucketArgs.region,
Interval: metav1.Duration{ Interval: metav1.Duration{
Duration: interval, Duration: createArgs.interval,
}, },
}, },
} }
if sourceHelmSecretRef != "" { if sourceHelmArgs.secretRef != "" {
bucket.Spec.SecretRef = &corev1.LocalObjectReference{ bucket.Spec.SecretRef = &corev1.LocalObjectReference{
Name: sourceBucketSecretRef, Name: sourceBucketArgs.secretRef,
} }
} }
if export { if createArgs.export {
return exportBucket(*bucket) return exportBucket(*bucket)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
logger.Generatef("generating Bucket source") logger.Generatef("generating Bucket source")
if sourceBucketSecretRef == "" { if sourceBucketArgs.secretRef == "" {
secretName := fmt.Sprintf("bucket-%s", name) secretName := fmt.Sprintf("bucket-%s", name)
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: secretName, Name: secretName,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
StringData: map[string]string{}, StringData: map[string]string{},
} }
if sourceBucketAccessKey != "" && sourceBucketSecretKey != "" { if sourceBucketArgs.accessKey != "" && sourceBucketArgs.secretKey != "" {
secret.StringData["accesskey"] = sourceBucketAccessKey secret.StringData["accesskey"] = sourceBucketArgs.accessKey
secret.StringData["secretkey"] = sourceBucketSecretKey secret.StringData["secretkey"] = sourceBucketArgs.secretKey
} }
if len(secret.StringData) > 0 { if len(secret.StringData) > 0 {
@ -183,7 +191,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for Bucket source reconciliation") logger.Waitingf("waiting for Bucket source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isBucketReady(ctx, kubeClient, namespacedName, bucket)); err != nil { isBucketReady(ctx, kubeClient, namespacedName, bucket)); err != nil {
return err return err
} }

@ -40,6 +40,21 @@ import (
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
) )
type SourceGitFlags struct {
GitURL string
GitBranch string
GitTag string
GitSemver string
GitUsername string
GitPassword string
GitKeyAlgorithm flags.PublicKeyAlgorithm
GitRSABits flags.RSAKeyBits
GitECDSACurve flags.ECDSACurve
GitSecretRef string
GitImplementation flags.GitImplementation
}
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",
@ -84,44 +99,39 @@ For private Git repositories, the basic authentication credentials are stored in
RunE: createSourceGitCmdRun, RunE: createSourceGitCmdRun,
} }
var ( var sourceArgs = NewSourceGitFlags()
sourceGitURL string
sourceGitBranch string
sourceGitTag string
sourceGitSemver string
sourceGitUsername string
sourceGitPassword string
sourceGitKeyAlgorithm flags.PublicKeyAlgorithm = "rsa"
sourceGitRSABits flags.RSAKeyBits = 2048
sourceGitECDSACurve = flags.ECDSACurve{Curve: elliptic.P384()}
sourceGitSecretRef string
sourceGitImplementation flags.GitImplementation
)
func init() { func init() {
createSourceGitCmd.Flags().StringVar(&sourceGitURL, "url", "", "git address, e.g. ssh://git@host/org/repository") createSourceGitCmd.Flags().StringVar(&sourceArgs.GitURL, "url", "", "git address, e.g. ssh://git@host/org/repository")
createSourceGitCmd.Flags().StringVar(&sourceGitBranch, "branch", "master", "git branch") createSourceGitCmd.Flags().StringVar(&sourceArgs.GitBranch, "branch", "master", "git branch")
createSourceGitCmd.Flags().StringVar(&sourceGitTag, "tag", "", "git tag") createSourceGitCmd.Flags().StringVar(&sourceArgs.GitTag, "tag", "", "git tag")
createSourceGitCmd.Flags().StringVar(&sourceGitSemver, "tag-semver", "", "git tag semver range") createSourceGitCmd.Flags().StringVar(&sourceArgs.GitSemver, "tag-semver", "", "git tag semver range")
createSourceGitCmd.Flags().StringVarP(&sourceGitUsername, "username", "u", "", "basic authentication username") createSourceGitCmd.Flags().StringVarP(&sourceArgs.GitUsername, "username", "u", "", "basic authentication username")
createSourceGitCmd.Flags().StringVarP(&sourceGitPassword, "password", "p", "", "basic authentication password") createSourceGitCmd.Flags().StringVarP(&sourceArgs.GitPassword, "password", "p", "", "basic authentication password")
createSourceGitCmd.Flags().Var(&sourceGitKeyAlgorithm, "ssh-key-algorithm", sourceGitKeyAlgorithm.Description()) createSourceGitCmd.Flags().Var(&sourceArgs.GitKeyAlgorithm, "ssh-key-algorithm", sourceArgs.GitKeyAlgorithm.Description())
createSourceGitCmd.Flags().Var(&sourceGitRSABits, "ssh-rsa-bits", sourceGitRSABits.Description()) createSourceGitCmd.Flags().Var(&sourceArgs.GitRSABits, "ssh-rsa-bits", sourceArgs.GitRSABits.Description())
createSourceGitCmd.Flags().Var(&sourceGitECDSACurve, "ssh-ecdsa-curve", sourceGitECDSACurve.Description()) createSourceGitCmd.Flags().Var(&sourceArgs.GitECDSACurve, "ssh-ecdsa-curve", sourceArgs.GitECDSACurve.Description())
createSourceGitCmd.Flags().StringVarP(&sourceGitSecretRef, "secret-ref", "", "", "the name of an existing secret containing SSH or basic credentials") createSourceGitCmd.Flags().StringVarP(&sourceArgs.GitSecretRef, "secret-ref", "", "", "the name of an existing secret containing SSH or basic credentials")
createSourceGitCmd.Flags().Var(&sourceGitImplementation, "git-implementation", sourceGitImplementation.Description()) createSourceGitCmd.Flags().Var(&sourceArgs.GitImplementation, "git-implementation", sourceArgs.GitImplementation.Description())
createSourceCmd.AddCommand(createSourceGitCmd) createSourceCmd.AddCommand(createSourceGitCmd)
} }
func NewSourceGitFlags() SourceGitFlags {
return SourceGitFlags{
GitKeyAlgorithm: "rsa",
GitRSABits: 2048,
GitECDSACurve: flags.ECDSACurve{Curve: elliptic.P384()},
}
}
func createSourceGitCmdRun(cmd *cobra.Command, args []string) error { func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 { if len(args) < 1 {
return fmt.Errorf("GitRepository source name is required") return fmt.Errorf("GitRepository source name is required")
} }
name := args[0] name := args[0]
if sourceGitURL == "" { if sourceArgs.GitURL == "" {
return fmt.Errorf("url is required") return fmt.Errorf("url is required")
} }
@ -131,7 +141,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
u, err := url.Parse(sourceGitURL) u, err := url.Parse(sourceArgs.GitURL)
if err != nil { if err != nil {
return fmt.Errorf("git URL parse failed: %w", err) return fmt.Errorf("git URL parse failed: %w", err)
} }
@ -144,54 +154,54 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
gitRepository := sourcev1.GitRepository{ gitRepository := sourcev1.GitRepository{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1.GitRepositorySpec{ Spec: sourcev1.GitRepositorySpec{
URL: sourceGitURL, URL: sourceArgs.GitURL,
Interval: metav1.Duration{ Interval: metav1.Duration{
Duration: interval, Duration: createArgs.interval,
}, },
Reference: &sourcev1.GitRepositoryRef{}, Reference: &sourcev1.GitRepositoryRef{},
}, },
} }
if sourceGitImplementation != "" { if sourceArgs.GitImplementation != "" {
gitRepository.Spec.GitImplementation = sourceGitImplementation.String() gitRepository.Spec.GitImplementation = sourceArgs.GitImplementation.String()
} }
if sourceGitSemver != "" { if sourceArgs.GitSemver != "" {
gitRepository.Spec.Reference.SemVer = sourceGitSemver gitRepository.Spec.Reference.SemVer = sourceArgs.GitSemver
} else if sourceGitTag != "" { } else if sourceArgs.GitTag != "" {
gitRepository.Spec.Reference.Tag = sourceGitTag gitRepository.Spec.Reference.Tag = sourceArgs.GitTag
} else { } else {
gitRepository.Spec.Reference.Branch = sourceGitBranch gitRepository.Spec.Reference.Branch = sourceArgs.GitBranch
} }
if export { if createArgs.export {
if sourceGitSecretRef != "" { if sourceArgs.GitSecretRef != "" {
gitRepository.Spec.SecretRef = &corev1.LocalObjectReference{ gitRepository.Spec.SecretRef = &corev1.LocalObjectReference{
Name: sourceGitSecretRef, Name: sourceArgs.GitSecretRef,
} }
} }
return exportGit(gitRepository) return exportGit(gitRepository)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
withAuth := false withAuth := false
// TODO(hidde): move all auth prep to separate func? // TODO(hidde): move all auth prep to separate func?
if sourceGitSecretRef != "" { if sourceArgs.GitSecretRef != "" {
withAuth = true withAuth = true
} else if u.Scheme == "ssh" { } else if u.Scheme == "ssh" {
logger.Generatef("generating deploy key pair") logger.Generatef("generating deploy key pair")
pair, err := generateKeyPair(ctx, sourceGitKeyAlgorithm, sourceGitRSABits, sourceGitECDSACurve) pair, err := generateKeyPair(ctx, sourceArgs.GitKeyAlgorithm, sourceArgs.GitRSABits, sourceArgs.GitECDSACurve)
if err != nil { if err != nil {
return err return err
} }
@ -216,7 +226,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
StringData: map[string]string{ StringData: map[string]string{
@ -229,17 +239,17 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
withAuth = true withAuth = true
} else if sourceGitUsername != "" && sourceGitPassword != "" { } else if sourceArgs.GitUsername != "" && sourceArgs.GitPassword != "" {
logger.Actionf("applying secret with basic auth credentials") logger.Actionf("applying secret with basic auth credentials")
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
StringData: map[string]string{ StringData: map[string]string{
"username": sourceGitUsername, "username": sourceArgs.GitUsername,
"password": sourceGitPassword, "password": sourceArgs.GitPassword,
}, },
} }
if err := upsertSecret(ctx, kubeClient, secret); err != nil { if err := upsertSecret(ctx, kubeClient, secret); err != nil {
@ -256,8 +266,8 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if withAuth { if withAuth {
secretName := name secretName := name
if sourceGitSecretRef != "" { if sourceArgs.GitSecretRef != "" {
secretName = sourceGitSecretRef secretName = sourceArgs.GitSecretRef
} }
gitRepository.Spec.SecretRef = &corev1.LocalObjectReference{ gitRepository.Spec.SecretRef = &corev1.LocalObjectReference{
Name: secretName, Name: secretName,
@ -271,7 +281,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for GitRepository source reconciliation") logger.Waitingf("waiting for GitRepository source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isGitRepositoryReady(ctx, kubeClient, namespacedName, &gitRepository)); err != nil { isGitRepositoryReady(ctx, kubeClient, namespacedName, &gitRepository)); err != nil {
return err return err
} }

@ -64,24 +64,26 @@ For private Helm repositories, the basic authentication credentials are stored i
RunE: createSourceHelmCmdRun, RunE: createSourceHelmCmdRun,
} }
var ( type sourceHelmFlags struct {
sourceHelmURL string url string
sourceHelmUsername string username string
sourceHelmPassword string password string
sourceHelmCertFile string certFile string
sourceHelmKeyFile string keyFile string
sourceHelmCAFile string caFile string
sourceHelmSecretRef string secretRef string
) }
var sourceHelmArgs sourceHelmFlags
func init() { func init() {
createSourceHelmCmd.Flags().StringVar(&sourceHelmURL, "url", "", "Helm repository address") createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.url, "url", "", "Helm repository address")
createSourceHelmCmd.Flags().StringVarP(&sourceHelmUsername, "username", "u", "", "basic authentication username") createSourceHelmCmd.Flags().StringVarP(&sourceHelmArgs.username, "username", "u", "", "basic authentication username")
createSourceHelmCmd.Flags().StringVarP(&sourceHelmPassword, "password", "p", "", "basic authentication password") createSourceHelmCmd.Flags().StringVarP(&sourceHelmArgs.password, "password", "p", "", "basic authentication password")
createSourceHelmCmd.Flags().StringVar(&sourceHelmCertFile, "cert-file", "", "TLS authentication cert file path") createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.certFile, "cert-file", "", "TLS authentication cert file path")
createSourceHelmCmd.Flags().StringVar(&sourceHelmKeyFile, "key-file", "", "TLS authentication key file path") createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.keyFile, "key-file", "", "TLS authentication key file path")
createSourceHelmCmd.Flags().StringVar(&sourceHelmCAFile, "ca-file", "", "TLS authentication CA file path") createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.caFile, "ca-file", "", "TLS authentication CA file path")
createSourceHelmCmd.Flags().StringVarP(&sourceHelmSecretRef, "secret-ref", "", "", "the name of an existing secret containing TLS or basic auth credentials") createSourceHelmCmd.Flags().StringVarP(&sourceHelmArgs.secretRef, "secret-ref", "", "", "the name of an existing secret containing TLS or basic auth credentials")
createSourceCmd.AddCommand(createSourceHelmCmd) createSourceCmd.AddCommand(createSourceHelmCmd)
} }
@ -92,7 +94,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
if sourceHelmURL == "" { if sourceHelmArgs.url == "" {
return fmt.Errorf("url is required") return fmt.Errorf("url is required")
} }
@ -107,78 +109,78 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
if _, err := url.Parse(sourceHelmURL); err != nil { if _, err := url.Parse(sourceHelmArgs.url); err != nil {
return fmt.Errorf("url parse failed: %w", err) return fmt.Errorf("url parse failed: %w", err)
} }
helmRepository := &sourcev1.HelmRepository{ helmRepository := &sourcev1.HelmRepository{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1.HelmRepositorySpec{ Spec: sourcev1.HelmRepositorySpec{
URL: sourceHelmURL, URL: sourceHelmArgs.url,
Interval: metav1.Duration{ Interval: metav1.Duration{
Duration: interval, Duration: createArgs.interval,
}, },
}, },
} }
if sourceHelmSecretRef != "" { if sourceHelmArgs.secretRef != "" {
helmRepository.Spec.SecretRef = &corev1.LocalObjectReference{ helmRepository.Spec.SecretRef = &corev1.LocalObjectReference{
Name: sourceHelmSecretRef, Name: sourceHelmArgs.secretRef,
} }
} }
if export { if createArgs.export {
return exportHelmRepository(*helmRepository) return exportHelmRepository(*helmRepository)
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
logger.Generatef("generating HelmRepository source") logger.Generatef("generating HelmRepository source")
if sourceHelmSecretRef == "" { if sourceHelmArgs.secretRef == "" {
secretName := fmt.Sprintf("helm-%s", name) secretName := fmt.Sprintf("helm-%s", name)
secret := corev1.Secret{ secret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: secretName, Name: secretName,
Namespace: namespace, Namespace: rootArgs.namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
StringData: map[string]string{}, StringData: map[string]string{},
} }
if sourceHelmUsername != "" && sourceHelmPassword != "" { if sourceHelmArgs.username != "" && sourceHelmArgs.password != "" {
secret.StringData["username"] = sourceHelmUsername secret.StringData["username"] = sourceHelmArgs.username
secret.StringData["password"] = sourceHelmPassword secret.StringData["password"] = sourceHelmArgs.password
} }
if sourceHelmCertFile != "" && sourceHelmKeyFile != "" { if sourceHelmArgs.certFile != "" && sourceHelmArgs.keyFile != "" {
cert, err := ioutil.ReadFile(sourceHelmCertFile) cert, err := ioutil.ReadFile(sourceHelmArgs.certFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to read repository cert file '%s': %w", sourceHelmCertFile, err) return fmt.Errorf("failed to read repository cert file '%s': %w", sourceHelmArgs.certFile, err)
} }
secret.StringData["certFile"] = string(cert) secret.StringData["certFile"] = string(cert)
key, err := ioutil.ReadFile(sourceHelmKeyFile) key, err := ioutil.ReadFile(sourceHelmArgs.keyFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to read repository key file '%s': %w", sourceHelmKeyFile, err) return fmt.Errorf("failed to read repository key file '%s': %w", sourceHelmArgs.keyFile, err)
} }
secret.StringData["keyFile"] = string(key) secret.StringData["keyFile"] = string(key)
} }
if sourceHelmCAFile != "" { if sourceHelmArgs.caFile != "" {
ca, err := ioutil.ReadFile(sourceHelmCAFile) ca, err := ioutil.ReadFile(sourceHelmArgs.caFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to read repository CA file '%s': %w", sourceHelmCAFile, err) return fmt.Errorf("failed to read repository CA file '%s': %w", sourceHelmArgs.caFile, err)
} }
secret.StringData["caFile"] = string(ca) secret.StringData["caFile"] = string(ca)
} }
@ -202,7 +204,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Waitingf("waiting for HelmRepository source reconciliation") logger.Waitingf("waiting for HelmRepository source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isHelmRepositoryReady(ctx, kubeClient, namespacedName, helmRepository)); err != nil { isHelmRepositoryReady(ctx, kubeClient, namespacedName, helmRepository)); err != nil {
return err return err
} }

@ -58,14 +58,16 @@ const (
tenantLabel = "toolkit.fluxcd.io/tenant" tenantLabel = "toolkit.fluxcd.io/tenant"
) )
var ( type tenantFlags struct {
tenantNamespaces []string namespaces []string
tenantClusterRole string clusterRole string
) }
var tenantArgs tenantFlags
func init() { func init() {
createTenantCmd.Flags().StringSliceVar(&tenantNamespaces, "with-namespace", nil, "namespace belonging to this tenant") createTenantCmd.Flags().StringSliceVar(&tenantArgs.namespaces, "with-namespace", nil, "namespace belonging to this tenant")
createTenantCmd.Flags().StringVar(&tenantClusterRole, "cluster-role", "cluster-admin", "cluster role of the tenant role binding") createTenantCmd.Flags().StringVar(&tenantArgs.clusterRole, "cluster-role", "cluster-admin", "cluster role of the tenant role binding")
createCmd.AddCommand(createTenantCmd) createCmd.AddCommand(createTenantCmd)
} }
@ -78,11 +80,11 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("invalid tenant name '%s': %v", tenant, err) return fmt.Errorf("invalid tenant name '%s': %v", tenant, err)
} }
if tenantClusterRole == "" { if tenantArgs.clusterRole == "" {
return fmt.Errorf("cluster-role is required") return fmt.Errorf("cluster-role is required")
} }
if tenantNamespaces == nil { if tenantArgs.namespaces == nil {
return fmt.Errorf("with-namespace is required") return fmt.Errorf("with-namespace is required")
} }
@ -90,7 +92,7 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
var accounts []corev1.ServiceAccount var accounts []corev1.ServiceAccount
var roleBindings []rbacv1.RoleBinding var roleBindings []rbacv1.RoleBinding
for _, ns := range tenantNamespaces { for _, ns := range tenantArgs.namespaces {
if err := validation.IsQualifiedName(ns); len(err) > 0 { if err := validation.IsQualifiedName(ns); len(err) > 0 {
return fmt.Errorf("invalid namespace '%s': %v", ns, err) return fmt.Errorf("invalid namespace '%s': %v", ns, err)
} }
@ -141,14 +143,14 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
RoleRef: rbacv1.RoleRef{ RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io", APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole", Kind: "ClusterRole",
Name: tenantClusterRole, Name: tenantArgs.clusterRole,
}, },
} }
roleBindings = append(roleBindings, roleBinding) roleBindings = append(roleBindings, roleBinding)
} }
if export { if createArgs.export {
for i, _ := range tenantNamespaces { for i, _ := range tenantArgs.namespaces {
if err := exportTenant(namespaces[i], accounts[i], roleBindings[i]); err != nil { if err := exportTenant(namespaces[i], accounts[i], roleBindings[i]); err != nil {
return err return err
} }
@ -156,15 +158,15 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
return nil return nil
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
for i, _ := range tenantNamespaces { for i, _ := range tenantArgs.namespaces {
logger.Actionf("applying namespace %s", namespaces[i].Name) logger.Actionf("applying namespace %s", namespaces[i].Name)
if err := upsertNamespace(ctx, kubeClient, namespaces[i]); err != nil { if err := upsertNamespace(ctx, kubeClient, namespaces[i]); err != nil {
return err return err

@ -33,12 +33,14 @@ var deleteCmd = &cobra.Command{
Long: "The delete sub-commands delete sources and resources.", Long: "The delete sub-commands delete sources and resources.",
} }
var ( type deleteFlags struct {
deleteSilent bool silent bool
) }
var deleteArgs deleteFlags
func init() { func init() {
deleteCmd.PersistentFlags().BoolVarP(&deleteSilent, "silent", "s", false, deleteCmd.PersistentFlags().BoolVarP(&deleteArgs.silent, "silent", "s", false,
"delete resource without asking for confirmation") "delete resource without asking for confirmation")
rootCmd.AddCommand(deleteCmd) rootCmd.AddCommand(deleteCmd)
@ -55,16 +57,16 @@ func (del deleteCommand) run(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -73,7 +75,7 @@ func (del deleteCommand) run(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Are you sure you want to delete this " + del.humanKind, Label: "Are you sure you want to delete this " + del.humanKind,
IsConfirm: true, IsConfirm: true,
@ -83,7 +85,7 @@ func (del deleteCommand) run(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting %s %s in %s namespace", del.humanKind, name, namespace) logger.Actionf("deleting %s %s in %s namespace", del.humanKind, name, rootArgs.namespace)
err = kubeClient.Delete(ctx, del.object.asClientObject()) err = kubeClient.Delete(ctx, del.object.asClientObject())
if err != nil { if err != nil {
return err return err

@ -48,16 +48,16 @@ func deleteAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -67,7 +67,7 @@ func deleteAlertCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Alert", Label: "Are you sure you want to delete this Alert",
IsConfirm: true, IsConfirm: true,
@ -77,7 +77,7 @@ func deleteAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting alert %s in %s namespace", name, namespace) logger.Actionf("deleting alert %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &alert) err = kubeClient.Delete(ctx, &alert)
if err != nil { if err != nil {
return err return err

@ -48,16 +48,16 @@ func deleteAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -67,7 +67,7 @@ func deleteAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Provider", Label: "Are you sure you want to delete this Provider",
IsConfirm: true, IsConfirm: true,
@ -77,7 +77,7 @@ func deleteAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting provider %s in %s namespace", name, namespace) logger.Actionf("deleting provider %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &alertProvider) err = kubeClient.Delete(ctx, &alertProvider)
if err != nil { if err != nil {
return err return err

@ -49,16 +49,16 @@ func deleteHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -68,7 +68,7 @@ func deleteHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
if !helmRelease.Spec.Suspend { if !helmRelease.Spec.Suspend {
logger.Waitingf("This action will remove the Kubernetes objects previously applied by the %s Helm release!", name) logger.Waitingf("This action will remove the Kubernetes objects previously applied by the %s Helm release!", name)
} }
@ -81,7 +81,7 @@ func deleteHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting release %s in %s namespace", name, namespace) logger.Actionf("deleting release %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &helmRelease) err = kubeClient.Delete(ctx, &helmRelease)
if err != nil { if err != nil {
return err return err

@ -48,16 +48,16 @@ func deleteKsCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -67,7 +67,7 @@ func deleteKsCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
if !kustomization.Spec.Suspend { if !kustomization.Spec.Suspend {
logger.Waitingf("This action will remove the Kubernetes objects previously applied by the %s kustomization!", name) logger.Waitingf("This action will remove the Kubernetes objects previously applied by the %s kustomization!", name)
} }
@ -80,7 +80,7 @@ func deleteKsCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting kustomization %s in %s namespace", name, namespace) logger.Actionf("deleting kustomization %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &kustomization) err = kubeClient.Delete(ctx, &kustomization)
if err != nil { if err != nil {
return err return err

@ -48,16 +48,16 @@ func deleteReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -67,7 +67,7 @@ func deleteReceiverCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Receiver", Label: "Are you sure you want to delete this Receiver",
IsConfirm: true, IsConfirm: true,
@ -77,7 +77,7 @@ func deleteReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting receiver %s in %s namespace", name, namespace) logger.Actionf("deleting receiver %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &receiver) err = kubeClient.Delete(ctx, &receiver)
if err != nil { if err != nil {
return err return err

@ -47,16 +47,16 @@ func deleteSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -66,7 +66,7 @@ func deleteSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Are you sure you want to delete this source", Label: "Are you sure you want to delete this source",
IsConfirm: true, IsConfirm: true,
@ -76,7 +76,7 @@ func deleteSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting source %s in %s namespace", name, namespace) logger.Actionf("deleting source %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &bucket) err = kubeClient.Delete(ctx, &bucket)
if err != nil { if err != nil {
return err return err

@ -47,16 +47,16 @@ func deleteSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -66,7 +66,7 @@ func deleteSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Are you sure you want to delete this source", Label: "Are you sure you want to delete this source",
IsConfirm: true, IsConfirm: true,
@ -76,7 +76,7 @@ func deleteSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting source %s in %s namespace", name, namespace) logger.Actionf("deleting source %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &git) err = kubeClient.Delete(ctx, &git)
if err != nil { if err != nil {
return err return err

@ -47,16 +47,16 @@ func deleteSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -66,7 +66,7 @@ func deleteSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if !deleteSilent { if !deleteArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: "Are you sure you want to delete this source", Label: "Are you sure you want to delete this source",
IsConfirm: true, IsConfirm: true,
@ -76,7 +76,7 @@ func deleteSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
logger.Actionf("deleting source %s in %s namespace", name, namespace) logger.Actionf("deleting source %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &helmRepository) err = kubeClient.Delete(ctx, &helmRepository)
if err != nil { if err != nil {
return err return err

@ -35,12 +35,14 @@ var exportCmd = &cobra.Command{
Long: "The export sub-commands export resources in YAML format.", Long: "The export sub-commands export resources in YAML format.",
} }
var ( type exportFlags struct {
exportAll bool all bool
) }
var exportArgs exportFlags
func init() { func init() {
exportCmd.PersistentFlags().BoolVar(&exportAll, "all", false, "select all resources") exportCmd.PersistentFlags().BoolVar(&exportArgs.all, "all", false, "select all resources")
rootCmd.AddCommand(exportCmd) rootCmd.AddCommand(exportCmd)
} }
@ -65,26 +67,26 @@ type exportCommand struct {
} }
func (export exportCommand) run(cmd *cobra.Command, args []string) error { func (export exportCommand) run(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(namespace)) err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if export.list.len() == 0 { if export.list.len() == 0 {
logger.Failuref("no objects found in %s namespace", namespace) logger.Failuref("no objects found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -96,7 +98,7 @@ func (export exportCommand) run(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject()) err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject())

@ -48,27 +48,27 @@ func init() {
} }
func exportAlertCmdRun(cmd *cobra.Command, args []string) error { func exportAlertCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list notificationv1.AlertList var list notificationv1.AlertList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no alerts found in %s namespace", namespace) logger.Failuref("no alerts found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -80,7 +80,7 @@ func exportAlertCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var alert notificationv1.Alert var alert notificationv1.Alert

@ -48,27 +48,27 @@ func init() {
} }
func exportAlertProviderCmdRun(cmd *cobra.Command, args []string) error { func exportAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list notificationv1.ProviderList var list notificationv1.ProviderList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no alertproviders found in %s namespace", namespace) logger.Failuref("no alertproviders found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -80,7 +80,7 @@ func exportAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var alertProvider notificationv1.Provider var alertProvider notificationv1.Provider

@ -49,27 +49,27 @@ func init() {
} }
func exportHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { func exportHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list helmv2.HelmReleaseList var list helmv2.HelmReleaseList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no helmrelease found in %s namespace", namespace) logger.Failuref("no helmrelease found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -81,7 +81,7 @@ func exportHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var helmRelease helmv2.HelmRelease var helmRelease helmv2.HelmRelease

@ -49,27 +49,27 @@ func init() {
} }
func exportKsCmdRun(cmd *cobra.Command, args []string) error { func exportKsCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("kustomization name is required") return fmt.Errorf("kustomization name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list kustomizev1.KustomizationList var list kustomizev1.KustomizationList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no kustomizations found in %s namespace", namespace) logger.Failuref("no kustomizations found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -81,7 +81,7 @@ func exportKsCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var kustomization kustomizev1.Kustomization var kustomization kustomizev1.Kustomization

@ -48,27 +48,27 @@ func init() {
} }
func exportReceiverCmdRun(cmd *cobra.Command, args []string) error { func exportReceiverCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list notificationv1.ReceiverList var list notificationv1.ReceiverList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no receivers found in %s namespace", namespace) logger.Failuref("no receivers found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -80,7 +80,7 @@ func exportReceiverCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var receiver notificationv1.Receiver var receiver notificationv1.Receiver

@ -49,27 +49,27 @@ func init() {
} }
func exportSourceBucketCmdRun(cmd *cobra.Command, args []string) error { func exportSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list sourcev1.BucketList var list sourcev1.BucketList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", namespace) logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -86,7 +86,7 @@ func exportSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var bucket sourcev1.Bucket var bucket sourcev1.Bucket

@ -49,27 +49,27 @@ func init() {
} }
func exportSourceGitCmdRun(cmd *cobra.Command, args []string) error { func exportSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list sourcev1.GitRepositoryList var list sourcev1.GitRepositoryList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", namespace) logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -86,7 +86,7 @@ func exportSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.GitRepository var repository sourcev1.GitRepository

@ -49,27 +49,27 @@ func init() {
} }
func exportSourceHelmCmdRun(cmd *cobra.Command, args []string) error { func exportSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
if !exportAll && len(args) < 1 { if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required") return fmt.Errorf("name is required")
} }
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if exportAll { if exportArgs.all {
var list sourcev1.HelmRepositoryList var list sourcev1.HelmRepositoryList
err = kubeClient.List(ctx, &list, client.InNamespace(namespace)) err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil { if err != nil {
return err return err
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", namespace) logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil return nil
} }
@ -86,7 +86,7 @@ func exportSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} else { } else {
name := args[0] name := args[0]
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.HelmRepository var repository sourcev1.HelmRepository

@ -36,10 +36,14 @@ var getCmd = &cobra.Command{
Long: "The get sub-commands print the statuses of sources and resources.", Long: "The get sub-commands print the statuses of sources and resources.",
} }
var allNamespaces bool type GetFlags struct {
allNamespaces bool
}
var getArgs GetFlags
func init() { func init() {
getCmd.PersistentFlags().BoolVarP(&allNamespaces, "all-namespaces", "A", false, getCmd.PersistentFlags().BoolVarP(&getArgs.allNamespaces, "all-namespaces", "A", false,
"list the requested object(s) across all namespaces") "list the requested object(s) across all namespaces")
rootCmd.AddCommand(getCmd) rootCmd.AddCommand(getCmd)
} }
@ -74,17 +78,17 @@ type getCommand struct {
} }
func (get getCommand) run(cmd *cobra.Command, args []string) error { func (get getCommand) run(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
err = kubeClient.List(ctx, get.list.asClientList(), listOpts...) err = kubeClient.List(ctx, get.list.asClientList(), listOpts...)
if err != nil { if err != nil {
@ -92,14 +96,14 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
} }
if get.list.len() == 0 { if get.list.len() == 0 {
logger.Failuref("no %s objects found in %s namespace", get.kind, namespace) logger.Failuref("no %s objects found in %s namespace", get.kind, rootArgs.namespace)
return nil return nil
} }
header := get.list.headers(allNamespaces) header := get.list.headers(getArgs.allNamespaces)
var rows [][]string var rows [][]string
for i := 0; i < get.list.len(); i++ { for i := 0; i < get.list.len(); i++ {
row := get.list.summariseItem(i, allNamespaces) row := get.list.summariseItem(i, getArgs.allNamespaces)
rows = append(rows, row) rows = append(rows, row)
} }
utils.PrintTable(os.Stdout, header, rows) utils.PrintTable(os.Stdout, header, rows)

@ -47,17 +47,17 @@ func init() {
} }
func getAlertCmdRun(cmd *cobra.Command, args []string) error { func getAlertCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list notificationv1.AlertList var list notificationv1.AlertList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -66,12 +66,12 @@ func getAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no alerts found in %s namespace", namespace) logger.Failuref("no alerts found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Suspended"} header := []string{"Name", "Ready", "Message", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -92,7 +92,7 @@ func getAlertCmdRun(cmd *cobra.Command, args []string) error {
strings.Title(strconv.FormatBool(alert.Spec.Suspend)), strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{alert.Namespace}, row...) row = append([]string{alert.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -45,17 +45,17 @@ func init() {
} }
func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error { func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list notificationv1.ProviderList var list notificationv1.ProviderList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -64,12 +64,12 @@ func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no providers found in %s namespace", namespace) logger.Failuref("no providers found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message"} header := []string{"Name", "Ready", "Message"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -88,7 +88,7 @@ func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
"waiting to be reconciled", "waiting to be reconciled",
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{provider.Namespace}, row...) row = append([]string{provider.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -49,17 +49,17 @@ func init() {
} }
func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list helmv2.HelmReleaseList var list helmv2.HelmReleaseList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -68,12 +68,12 @@ func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no releases found in %s namespace", namespace) logger.Failuref("no releases found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"} header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -96,7 +96,7 @@ func getHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
strings.Title(strconv.FormatBool(helmRelease.Spec.Suspend)), strings.Title(strconv.FormatBool(helmRelease.Spec.Suspend)),
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{helmRelease.Namespace}, row...) row = append([]string{helmRelease.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -48,17 +48,17 @@ func init() {
} }
func getKsCmdRun(cmd *cobra.Command, args []string) error { func getKsCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list kustomizev1.KustomizationList var list kustomizev1.KustomizationList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -67,12 +67,12 @@ func getKsCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no kustomizations found in %s namespace", namespace) logger.Failuref("no kustomizations found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"} header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -95,7 +95,7 @@ func getKsCmdRun(cmd *cobra.Command, args []string) error {
strings.Title(strconv.FormatBool(kustomization.Spec.Suspend)), strings.Title(strconv.FormatBool(kustomization.Spec.Suspend)),
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{kustomization.Namespace}, row...) row = append([]string{kustomization.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -47,17 +47,17 @@ func init() {
} }
func getReceiverCmdRun(cmd *cobra.Command, args []string) error { func getReceiverCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list notificationv1.ReceiverList var list notificationv1.ReceiverList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -66,12 +66,12 @@ func getReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no receivers found in %s namespace", namespace) logger.Failuref("no receivers found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Suspended"} header := []string{"Name", "Ready", "Message", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string

@ -50,17 +50,17 @@ func init() {
} }
func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error { func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list sourcev1.BucketList var list sourcev1.BucketList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -69,12 +69,12 @@ func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no bucket sources found in %s namespace", namespace) logger.Failuref("no bucket sources found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"} header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -101,7 +101,7 @@ func getSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
strings.Title(strconv.FormatBool(source.Spec.Suspend)), strings.Title(strconv.FormatBool(source.Spec.Suspend)),
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{source.Namespace}, row...) row = append([]string{source.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -50,17 +50,17 @@ func init() {
} }
func getSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error { func getSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list sourcev1.HelmChartList var list sourcev1.HelmChartList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -69,12 +69,12 @@ func getSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no chart sources found in %s namespace", namespace) logger.Failuref("no chart sources found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"} header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -101,7 +101,7 @@ func getSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
strings.Title(strconv.FormatBool(source.Spec.Suspend)), strings.Title(strconv.FormatBool(source.Spec.Suspend)),
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{source.Namespace}, row...) row = append([]string{source.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -50,17 +50,17 @@ func init() {
} }
func getSourceGitCmdRun(cmd *cobra.Command, args []string) error { func getSourceGitCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list sourcev1.GitRepositoryList var list sourcev1.GitRepositoryList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -69,12 +69,12 @@ func getSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no git sources found in %s namespace", namespace) logger.Failuref("no git sources found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"} header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -101,7 +101,7 @@ func getSourceGitCmdRun(cmd *cobra.Command, args []string) error {
strings.Title(strconv.FormatBool(source.Spec.Suspend)), strings.Title(strconv.FormatBool(source.Spec.Suspend)),
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{source.Namespace}, row...) row = append([]string{source.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -50,17 +50,17 @@ func init() {
} }
func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error { func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
var listOpts []client.ListOption var listOpts []client.ListOption
if !allNamespaces { if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
} }
var list sourcev1.HelmRepositoryList var list sourcev1.HelmRepositoryList
err = kubeClient.List(ctx, &list, listOpts...) err = kubeClient.List(ctx, &list, listOpts...)
@ -69,12 +69,12 @@ func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
if len(list.Items) == 0 { if len(list.Items) == 0 {
logger.Failuref("no helm sources found in %s namespace", namespace) logger.Failuref("no helm sources found in %s namespace", rootArgs.namespace)
return nil return nil
} }
header := []string{"Name", "Ready", "Message", "Revision", "Suspended"} header := []string{"Name", "Ready", "Message", "Revision", "Suspended"}
if allNamespaces { if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...) header = append([]string{"Namespace"}, header...)
} }
var rows [][]string var rows [][]string
@ -101,7 +101,7 @@ func getSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
strings.Title(strconv.FormatBool(source.Spec.Suspend)), strings.Title(strconv.FormatBool(source.Spec.Suspend)),
} }
} }
if allNamespaces { if getArgs.allNamespaces {
row = append([]string{source.Namespace}, row...) row = append([]string{source.Namespace}, row...)
} }
rows = append(rows, row) rows = append(rows, row)

@ -63,7 +63,7 @@ var (
installWatchAllNamespaces bool installWatchAllNamespaces bool
installNetworkPolicy bool installNetworkPolicy bool
installArch flags.Arch installArch flags.Arch
installLogLevel = flags.LogLevel(defaults.LogLevel) installLogLevel = flags.LogLevel(rootArgs.defaults.LogLevel)
installClusterDomain string installClusterDomain string
) )
@ -72,34 +72,34 @@ func init() {
"write the install manifests to stdout and exit") "write the install manifests to stdout and exit")
installCmd.Flags().BoolVarP(&installDryRun, "dry-run", "", false, installCmd.Flags().BoolVarP(&installDryRun, "dry-run", "", false,
"only print the object that would be applied") "only print the object that would be applied")
installCmd.Flags().StringVarP(&installVersion, "version", "v", defaults.Version, installCmd.Flags().StringVarP(&installVersion, "version", "v", rootArgs.defaults.Version,
"toolkit version") "toolkit version")
installCmd.Flags().StringSliceVar(&installDefaultComponents, "components", defaults.Components, installCmd.Flags().StringSliceVar(&installDefaultComponents, "components", rootArgs.defaults.Components,
"list of components, accepts comma-separated values") "list of components, accepts comma-separated values")
installCmd.Flags().StringSliceVar(&installExtraComponents, "components-extra", nil, installCmd.Flags().StringSliceVar(&installExtraComponents, "components-extra", nil,
"list of components in addition to those supplied or defaulted, accepts comma-separated values") "list of components in addition to those supplied or defaulted, accepts comma-separated values")
installCmd.Flags().StringVar(&installManifestsPath, "manifests", "", "path to the manifest directory") installCmd.Flags().StringVar(&installManifestsPath, "manifests", "", "path to the manifest directory")
installCmd.Flags().StringVar(&installRegistry, "registry", defaults.Registry, installCmd.Flags().StringVar(&installRegistry, "registry", rootArgs.defaults.Registry,
"container registry where the toolkit images are published") "container registry where the toolkit images are published")
installCmd.Flags().StringVar(&installImagePullSecret, "image-pull-secret", "", installCmd.Flags().StringVar(&installImagePullSecret, "image-pull-secret", "",
"Kubernetes secret name used for pulling the toolkit images from a private registry") "Kubernetes secret name used for pulling the toolkit images from a private registry")
installCmd.Flags().Var(&installArch, "arch", installArch.Description()) installCmd.Flags().Var(&installArch, "arch", installArch.Description())
installCmd.Flags().BoolVar(&installWatchAllNamespaces, "watch-all-namespaces", defaults.WatchAllNamespaces, installCmd.Flags().BoolVar(&installWatchAllNamespaces, "watch-all-namespaces", rootArgs.defaults.WatchAllNamespaces,
"watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed") "watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed")
installCmd.Flags().Var(&installLogLevel, "log-level", installLogLevel.Description()) installCmd.Flags().Var(&installLogLevel, "log-level", installLogLevel.Description())
installCmd.Flags().BoolVar(&installNetworkPolicy, "network-policy", defaults.NetworkPolicy, installCmd.Flags().BoolVar(&installNetworkPolicy, "network-policy", rootArgs.defaults.NetworkPolicy,
"deny ingress access to the toolkit controllers from other namespaces using network policies") "deny ingress access to the toolkit controllers from other namespaces using network policies")
installCmd.Flags().StringVar(&installClusterDomain, "cluster-domain", defaults.ClusterDomain, "internal cluster domain") installCmd.Flags().StringVar(&installClusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain")
installCmd.Flags().MarkHidden("manifests") installCmd.Flags().MarkHidden("manifests")
installCmd.Flags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64") installCmd.Flags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64")
rootCmd.AddCommand(installCmd) rootCmd.AddCommand(installCmd)
} }
func installCmdRun(cmd *cobra.Command, args []string) error { func installCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
tmpDir, err := ioutil.TempDir("", namespace) tmpDir, err := ioutil.TempDir("", rootArgs.namespace)
if err != nil { if err != nil {
return err return err
} }
@ -118,16 +118,16 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
opts := install.Options{ opts := install.Options{
BaseURL: installManifestsPath, BaseURL: installManifestsPath,
Version: installVersion, Version: installVersion,
Namespace: namespace, Namespace: rootArgs.namespace,
Components: components, Components: components,
Registry: installRegistry, Registry: installRegistry,
ImagePullSecret: installImagePullSecret, ImagePullSecret: installImagePullSecret,
WatchAllNamespaces: installWatchAllNamespaces, WatchAllNamespaces: installWatchAllNamespaces,
NetworkPolicy: installNetworkPolicy, NetworkPolicy: installNetworkPolicy,
LogLevel: installLogLevel.String(), LogLevel: installLogLevel.String(),
NotificationController: defaults.NotificationController, NotificationController: rootArgs.defaults.NotificationController,
ManifestFile: fmt.Sprintf("%s.yaml", namespace), ManifestFile: fmt.Sprintf("%s.yaml", rootArgs.namespace),
Timeout: timeout, Timeout: rootArgs.timeout,
ClusterDomain: installClusterDomain, ClusterDomain: installClusterDomain,
} }
@ -144,7 +144,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("install failed: %w", err) return fmt.Errorf("install failed: %w", err)
} }
if verbose { if rootArgs.verbose {
fmt.Print(manifest.Content) fmt.Print(manifest.Content)
} else if installExport { } else if installExport {
fmt.Println("---") fmt.Println("---")
@ -156,9 +156,9 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Successf("manifests build completed") logger.Successf("manifests build completed")
logger.Actionf("installing components in %s namespace", namespace) logger.Actionf("installing components in %s namespace", rootArgs.namespace)
applyOutput := utils.ModeStderrOS applyOutput := utils.ModeStderrOS
if verbose { if rootArgs.verbose {
applyOutput = utils.ModeOS applyOutput = utils.ModeOS
} }
@ -167,7 +167,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
kubectlArgs = append(kubectlArgs, "--dry-run=client") kubectlArgs = append(kubectlArgs, "--dry-run=client")
applyOutput = utils.ModeOS applyOutput = utils.ModeOS
} }
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, kubeconfig, kubecontext, kubectlArgs...); err != nil { if _, err := utils.ExecKubectlCommand(ctx, applyOutput, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
@ -180,8 +180,8 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
logger.Waitingf("verifying installation") logger.Waitingf("verifying installation")
for _, deployment := range components { for _, deployment := range components {
kubectlArgs = []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()} kubectlArgs = []string{"-n", rootArgs.namespace, "rollout", "status", "deployment", deployment, "--timeout", rootArgs.timeout.String()}
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, kubeconfig, kubecontext, kubectlArgs...); err != nil { if _, err := utils.ExecKubectlCommand(ctx, applyOutput, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} else { } else {
logger.Successf("%s ready", deployment) logger.Successf("%s ready", deployment)

@ -26,7 +26,6 @@ import (
"github.com/spf13/cobra/doc" "github.com/spf13/cobra/doc"
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
fluxlog "github.com/fluxcd/flux2/pkg/log"
"github.com/fluxcd/flux2/pkg/manifestgen/install" "github.com/fluxcd/flux2/pkg/manifestgen/install"
) )
@ -94,22 +93,32 @@ var rootCmd = &cobra.Command{
`, `,
} }
var ( var logger = stderrLogger{stderr: os.Stderr}
type rootFlags struct {
kubeconfig string kubeconfig string
kubecontext string kubecontext string
namespace string namespace string
timeout time.Duration timeout time.Duration
verbose bool verbose bool
pollInterval = 2 * time.Second pollInterval time.Duration
logger fluxlog.Logger = stderrLogger{stderr: os.Stderr} defaults install.Options
defaults = install.MakeDefaultOptions() }
)
var rootArgs = NewRootFlags()
func init() { func init() {
rootCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", 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(&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(&verbose, "verbose", false, "print generated objects") rootCmd.PersistentFlags().BoolVar(&rootArgs.verbose, "verbose", false, "print generated objects")
rootCmd.PersistentFlags().StringVarP(&kubecontext, "context", "", "", "kubernetes context to use") rootCmd.PersistentFlags().StringVarP(&rootArgs.kubecontext, "context", "", "", "kubernetes context to use")
}
func NewRootFlags() rootFlags {
return rootFlags{
pollInterval: 2 * time.Second,
defaults: install.MakeDefaultOptions(),
}
} }
func main() { func main() {
@ -124,22 +133,22 @@ func main() {
func kubeconfigFlag() { func kubeconfigFlag() {
if home := homeDir(); home != "" { if home := homeDir(); home != "" {
rootCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", filepath.Join(home, ".kube", "config"), rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", filepath.Join(home, ".kube", "config"),
"path to the kubeconfig file") "path to the kubeconfig file")
} else { } else {
rootCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", "", rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", "",
"absolute path to the kubeconfig file") "absolute path to the kubeconfig file")
} }
if len(os.Getenv("KUBECONFIG")) > 0 { if len(os.Getenv("KUBECONFIG")) > 0 {
kubeconfig = os.Getenv("KUBECONFIG") rootArgs.kubeconfig = os.Getenv("KUBECONFIG")
} }
} }
func generateDocs() { func generateDocs() {
args := os.Args[1:] args := os.Args[1:]
if len(args) > 0 && args[0] == "docgen" { if len(args) > 0 && args[0] == "docgen" {
rootCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", "~/.kube/config", rootCmd.PersistentFlags().StringVarP(&rootArgs.kubeconfig, "kubeconfig", "", "~/.kube/config",
"path to the kubeconfig file") "path to the kubeconfig file")
rootCmd.DisableAutoGenTag = true rootCmd.DisableAutoGenTag = true
err := doc.GenMarkdownTree(rootCmd, "./docs/cmd") err := doc.GenMarkdownTree(rootCmd, "./docs/cmd")

@ -69,16 +69,16 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -91,7 +91,7 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
logger.Actionf("annotating %s %s in %s namespace", reconcile.kind, name, namespace) logger.Actionf("annotating %s %s in %s namespace", reconcile.kind, name, rootArgs.namespace)
if err := requestReconciliation(ctx, kubeClient, namespacedName, reconcile.object); err != nil { if err := requestReconciliation(ctx, kubeClient, namespacedName, reconcile.object); err != nil {
return err return err
} }
@ -99,7 +99,7 @@ func (reconcile reconcileCommand) run(cmd *cobra.Command, args []string) error {
lastHandledReconcileAt := reconcile.object.lastHandledReconcileRequest() lastHandledReconcileAt := reconcile.object.lastHandledReconcileRequest()
logger.Waitingf("waiting for %s reconciliation", reconcile.kind) logger.Waitingf("waiting for %s reconciliation", reconcile.kind)
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
reconciliationHandled(ctx, kubeClient, namespacedName, reconcile.object, lastHandledReconcileAt)); err != nil { reconciliationHandled(ctx, kubeClient, namespacedName, reconcile.object, lastHandledReconcileAt)); err != nil {
return err return err
} }

@ -51,16 +51,16 @@ func reconcileAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -74,7 +74,7 @@ func reconcileAlertCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
logger.Actionf("annotating Alert %s in %s namespace", name, namespace) logger.Actionf("annotating Alert %s in %s namespace", name, rootArgs.namespace)
if alert.Annotations == nil { if alert.Annotations == nil {
alert.Annotations = map[string]string{ alert.Annotations = map[string]string{
meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano), meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano),
@ -89,7 +89,7 @@ func reconcileAlertCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("Alert annotated") logger.Successf("Alert annotated")
logger.Waitingf("waiting for reconciliation") logger.Waitingf("waiting for reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isAlertReady(ctx, kubeClient, namespacedName, &alert)); err != nil { isAlertReady(ctx, kubeClient, namespacedName, &alert)); err != nil {
return err return err
} }

@ -51,20 +51,20 @@ func reconcileAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
logger.Actionf("annotating Provider %s in %s namespace", name, namespace) logger.Actionf("annotating Provider %s in %s namespace", name, rootArgs.namespace)
var alertProvider notificationv1.Provider var alertProvider notificationv1.Provider
err = kubeClient.Get(ctx, namespacedName, &alertProvider) err = kubeClient.Get(ctx, namespacedName, &alertProvider)
if err != nil { if err != nil {
@ -84,7 +84,7 @@ func reconcileAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("Provider annotated") logger.Successf("Provider annotated")
logger.Waitingf("waiting for reconciliation") logger.Waitingf("waiting for reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isAlertProviderReady(ctx, kubeClient, namespacedName, &alertProvider)); err != nil { isAlertProviderReady(ctx, kubeClient, namespacedName, &alertProvider)); err != nil {
return err return err
} }

@ -51,12 +51,14 @@ The reconcile kustomization command triggers a reconciliation of a HelmRelease r
RunE: reconcileHrCmdRun, RunE: reconcileHrCmdRun,
} }
var ( type reconcileHelmReleaseFlags struct {
syncHrWithSource bool syncHrWithSource bool
) }
var rhrArgs reconcileHelmReleaseFlags
func init() { func init() {
reconcileHrCmd.Flags().BoolVar(&syncHrWithSource, "with-source", false, "reconcile HelmRelease source") reconcileHrCmd.Flags().BoolVar(&rhrArgs.syncHrWithSource, "with-source", false, "reconcile HelmRelease source")
reconcileCmd.AddCommand(reconcileHrCmd) reconcileCmd.AddCommand(reconcileHrCmd)
} }
@ -67,16 +69,16 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -90,7 +92,7 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
if syncHrWithSource { if rhrArgs.syncHrWithSource {
switch helmRelease.Spec.Chart.Spec.SourceRef.Kind { switch helmRelease.Spec.Chart.Spec.SourceRef.Kind {
case sourcev1.HelmRepositoryKind: case sourcev1.HelmRepositoryKind:
err = reconcileSourceHelmCmdRun(nil, []string{helmRelease.Spec.Chart.Spec.SourceRef.Name}) err = reconcileSourceHelmCmdRun(nil, []string{helmRelease.Spec.Chart.Spec.SourceRef.Name})
@ -105,14 +107,14 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error {
} }
lastHandledReconcileAt := helmRelease.Status.LastHandledReconcileAt lastHandledReconcileAt := helmRelease.Status.LastHandledReconcileAt
logger.Actionf("annotating HelmRelease %s in %s namespace", name, namespace) logger.Actionf("annotating HelmRelease %s in %s namespace", name, rootArgs.namespace)
if err := requestHelmReleaseReconciliation(ctx, kubeClient, namespacedName, &helmRelease); err != nil { if err := requestHelmReleaseReconciliation(ctx, kubeClient, namespacedName, &helmRelease); err != nil {
return err return err
} }
logger.Successf("HelmRelease annotated") logger.Successf("HelmRelease annotated")
logger.Waitingf("waiting for HelmRelease reconciliation") logger.Waitingf("waiting for HelmRelease reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
helmReleaseReconciliationHandled(ctx, kubeClient, namespacedName, &helmRelease, lastHandledReconcileAt), helmReleaseReconciliationHandled(ctx, kubeClient, namespacedName, &helmRelease, lastHandledReconcileAt),
); err != nil { ); err != nil {
return err return err

@ -50,12 +50,14 @@ The reconcile kustomization command triggers a reconciliation of a Kustomization
RunE: reconcileKsCmdRun, RunE: reconcileKsCmdRun,
} }
var ( type reconcileKsFlags struct {
syncKsWithSource bool syncKsWithSource bool
) }
var rksArgs reconcileKsFlags
func init() { func init() {
reconcileKsCmd.Flags().BoolVar(&syncKsWithSource, "with-source", false, "reconcile Kustomization source") reconcileKsCmd.Flags().BoolVar(&rksArgs.syncKsWithSource, "with-source", false, "reconcile Kustomization source")
reconcileCmd.AddCommand(reconcileKsCmd) reconcileCmd.AddCommand(reconcileKsCmd)
} }
@ -66,16 +68,16 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var kustomization kustomizev1.Kustomization var kustomization kustomizev1.Kustomization
@ -88,7 +90,7 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
if syncKsWithSource { if rksArgs.syncKsWithSource {
switch kustomization.Spec.SourceRef.Kind { switch kustomization.Spec.SourceRef.Kind {
case sourcev1.GitRepositoryKind: case sourcev1.GitRepositoryKind:
err = reconcileSourceGitCmdRun(nil, []string{kustomization.Spec.SourceRef.Name}) err = reconcileSourceGitCmdRun(nil, []string{kustomization.Spec.SourceRef.Name})
@ -101,7 +103,7 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error {
} }
lastHandledReconcileAt := kustomization.Status.LastHandledReconcileAt lastHandledReconcileAt := kustomization.Status.LastHandledReconcileAt
logger.Actionf("annotating Kustomization %s in %s namespace", name, namespace) logger.Actionf("annotating Kustomization %s in %s namespace", name, rootArgs.namespace)
if err := requestKustomizeReconciliation(ctx, kubeClient, namespacedName, &kustomization); err != nil { if err := requestKustomizeReconciliation(ctx, kubeClient, namespacedName, &kustomization); err != nil {
return err return err
} }
@ -109,7 +111,7 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error {
logger.Waitingf("waiting for Kustomization reconciliation") logger.Waitingf("waiting for Kustomization reconciliation")
if err := wait.PollImmediate( if err := wait.PollImmediate(
pollInterval, timeout, rootArgs.pollInterval, rootArgs.timeout,
kustomizeReconciliationHandled(ctx, kubeClient, namespacedName, &kustomization, lastHandledReconcileAt), kustomizeReconciliationHandled(ctx, kubeClient, namespacedName, &kustomization, lastHandledReconcileAt),
); err != nil { ); err != nil {
return err return err

@ -51,16 +51,16 @@ func reconcileReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -74,7 +74,7 @@ func reconcileReceiverCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
logger.Actionf("annotating Receiver %s in %s namespace", name, namespace) logger.Actionf("annotating Receiver %s in %s namespace", name, rootArgs.namespace)
if receiver.Annotations == nil { if receiver.Annotations == nil {
receiver.Annotations = map[string]string{ receiver.Annotations = map[string]string{
meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano), meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano),
@ -88,7 +88,7 @@ func reconcileReceiverCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("Receiver annotated") logger.Successf("Receiver annotated")
logger.Waitingf("waiting for Receiver reconciliation") logger.Waitingf("waiting for Receiver reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isReceiverReady(ctx, kubeClient, namespacedName, &receiver)); err != nil { isReceiverReady(ctx, kubeClient, namespacedName, &receiver)); err != nil {
return err return err
} }

@ -56,16 +56,16 @@ func reconcileSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var bucket sourcev1.Bucket var bucket sourcev1.Bucket
@ -79,7 +79,7 @@ func reconcileSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
lastHandledReconcileAt := bucket.Status.LastHandledReconcileAt lastHandledReconcileAt := bucket.Status.LastHandledReconcileAt
logger.Actionf("annotating Bucket source %s in %s namespace", name, namespace) logger.Actionf("annotating Bucket source %s in %s namespace", name, rootArgs.namespace)
if err := requestBucketReconciliation(ctx, kubeClient, namespacedName, &bucket); err != nil { if err := requestBucketReconciliation(ctx, kubeClient, namespacedName, &bucket); err != nil {
return err return err
} }
@ -87,7 +87,7 @@ func reconcileSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
logger.Waitingf("waiting for Bucket source reconciliation") logger.Waitingf("waiting for Bucket source reconciliation")
if err := wait.PollImmediate( if err := wait.PollImmediate(
pollInterval, timeout, rootArgs.pollInterval, rootArgs.timeout,
bucketReconciliationHandled(ctx, kubeClient, namespacedName, &bucket, lastHandledReconcileAt), bucketReconciliationHandled(ctx, kubeClient, namespacedName, &bucket, lastHandledReconcileAt),
); err != nil { ); err != nil {
return err return err

@ -54,16 +54,16 @@ func reconcileSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.GitRepository var repository sourcev1.GitRepository
@ -76,7 +76,7 @@ func reconcileSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
logger.Actionf("annotating GitRepository source %s in %s namespace", name, namespace) logger.Actionf("annotating GitRepository source %s in %s namespace", name, rootArgs.namespace)
if err := requestGitRepositoryReconciliation(ctx, kubeClient, namespacedName, &repository); err != nil { if err := requestGitRepositoryReconciliation(ctx, kubeClient, namespacedName, &repository); err != nil {
return err return err
} }
@ -84,7 +84,7 @@ func reconcileSourceGitCmdRun(cmd *cobra.Command, args []string) error {
lastHandledReconcileAt := repository.Status.LastHandledReconcileAt lastHandledReconcileAt := repository.Status.LastHandledReconcileAt
logger.Waitingf("waiting for GitRepository source reconciliation") logger.Waitingf("waiting for GitRepository source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
gitRepositoryReconciliationHandled(ctx, kubeClient, namespacedName, &repository, lastHandledReconcileAt)); err != nil { gitRepositoryReconciliationHandled(ctx, kubeClient, namespacedName, &repository, lastHandledReconcileAt)); err != nil {
return err return err
} }

@ -55,16 +55,16 @@ func reconcileSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.HelmRepository var repository sourcev1.HelmRepository
@ -77,7 +77,7 @@ func reconcileSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("resource is suspended") return fmt.Errorf("resource is suspended")
} }
logger.Actionf("annotating HelmRepository source %s in %s namespace", name, namespace) logger.Actionf("annotating HelmRepository source %s in %s namespace", name, rootArgs.namespace)
if err := requestHelmRepositoryReconciliation(ctx, kubeClient, namespacedName, &repository); err != nil { if err := requestHelmRepositoryReconciliation(ctx, kubeClient, namespacedName, &repository); err != nil {
return err return err
} }
@ -85,7 +85,7 @@ func reconcileSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
lastHandledReconcileAt := repository.Status.LastHandledReconcileAt lastHandledReconcileAt := repository.Status.LastHandledReconcileAt
logger.Waitingf("waiting for HelmRepository source reconciliation") logger.Waitingf("waiting for HelmRepository source reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
helmRepositoryReconciliationHandled(ctx, kubeClient, namespacedName, &repository, lastHandledReconcileAt)); err != nil { helmRepositoryReconciliationHandled(ctx, kubeClient, namespacedName, &repository, lastHandledReconcileAt)); err != nil {
return err return err
} }

@ -55,16 +55,16 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
@ -73,7 +73,7 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, name, namespace) logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, name, rootArgs.namespace)
resume.object.setUnsuspended() resume.object.setUnsuspended()
if err := kubeClient.Update(ctx, resume.object.asClientObject()); err != nil { if err := kubeClient.Update(ctx, resume.object.asClientObject()); err != nil {
return err return err
@ -81,7 +81,7 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
logger.Successf("%s resumed", resume.humanKind) logger.Successf("%s resumed", resume.humanKind)
logger.Waitingf("waiting for %s reconciliation", resume.kind) logger.Waitingf("waiting for %s reconciliation", resume.kind)
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isReady(ctx, kubeClient, namespacedName, resume.object)); err != nil { isReady(ctx, kubeClient, namespacedName, resume.object)); err != nil {
return err return err
} }

@ -54,16 +54,16 @@ func resumeAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var alert notificationv1.Alert var alert notificationv1.Alert
@ -72,7 +72,7 @@ func resumeAlertCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming Alert %s in %s namespace", name, namespace) logger.Actionf("resuming Alert %s in %s namespace", name, rootArgs.namespace)
alert.Spec.Suspend = false alert.Spec.Suspend = false
if err := kubeClient.Update(ctx, &alert); err != nil { if err := kubeClient.Update(ctx, &alert); err != nil {
return err return err
@ -80,7 +80,7 @@ func resumeAlertCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("Alert resumed") logger.Successf("Alert resumed")
logger.Waitingf("waiting for Alert reconciliation") logger.Waitingf("waiting for Alert reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isAlertResumed(ctx, kubeClient, namespacedName, &alert)); err != nil { isAlertResumed(ctx, kubeClient, namespacedName, &alert)); err != nil {
return err return err
} }

@ -55,16 +55,16 @@ func resumeHrCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var helmRelease helmv2.HelmRelease var helmRelease helmv2.HelmRelease
@ -73,7 +73,7 @@ func resumeHrCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming HelmRelease %s in %s namespace", name, namespace) logger.Actionf("resuming HelmRelease %s in %s namespace", name, rootArgs.namespace)
helmRelease.Spec.Suspend = false helmRelease.Spec.Suspend = false
if err := kubeClient.Update(ctx, &helmRelease); err != nil { if err := kubeClient.Update(ctx, &helmRelease); err != nil {
return err return err
@ -81,7 +81,7 @@ func resumeHrCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("HelmRelease resumed") logger.Successf("HelmRelease resumed")
logger.Waitingf("waiting for HelmRelease reconciliation") logger.Waitingf("waiting for HelmRelease reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isHelmReleaseResumed(ctx, kubeClient, namespacedName, &helmRelease)); err != nil { isHelmReleaseResumed(ctx, kubeClient, namespacedName, &helmRelease)); err != nil {
return err return err
} }

@ -54,16 +54,16 @@ func resumeKsCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var kustomization kustomizev1.Kustomization var kustomization kustomizev1.Kustomization
@ -72,7 +72,7 @@ func resumeKsCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming Kustomization %s in %s namespace", name, namespace) logger.Actionf("resuming Kustomization %s in %s namespace", name, rootArgs.namespace)
kustomization.Spec.Suspend = false kustomization.Spec.Suspend = false
if err := kubeClient.Update(ctx, &kustomization); err != nil { if err := kubeClient.Update(ctx, &kustomization); err != nil {
return err return err
@ -80,7 +80,7 @@ func resumeKsCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("Kustomization resumed") logger.Successf("Kustomization resumed")
logger.Waitingf("waiting for Kustomization reconciliation") logger.Waitingf("waiting for Kustomization reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isKustomizationResumed(ctx, kubeClient, namespacedName, &kustomization)); err != nil { isKustomizationResumed(ctx, kubeClient, namespacedName, &kustomization)); err != nil {
return err return err
} }

@ -54,16 +54,16 @@ func resumeReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var receiver notificationv1.Receiver var receiver notificationv1.Receiver
@ -72,7 +72,7 @@ func resumeReceiverCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming Receiver %s in %s namespace", name, namespace) logger.Actionf("resuming Receiver %s in %s namespace", name, rootArgs.namespace)
receiver.Spec.Suspend = false receiver.Spec.Suspend = false
if err := kubeClient.Update(ctx, &receiver); err != nil { if err := kubeClient.Update(ctx, &receiver); err != nil {
return err return err
@ -80,7 +80,7 @@ func resumeReceiverCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("Receiver resumed") logger.Successf("Receiver resumed")
logger.Waitingf("waiting for Receiver reconciliation") logger.Waitingf("waiting for Receiver reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isReceiverResumed(ctx, kubeClient, namespacedName, &receiver)); err != nil { isReceiverResumed(ctx, kubeClient, namespacedName, &receiver)); err != nil {
return err return err
} }

@ -53,16 +53,16 @@ func resumeSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var bucket sourcev1.Bucket var bucket sourcev1.Bucket
@ -71,7 +71,7 @@ func resumeSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming source %s in %s namespace", name, namespace) logger.Actionf("resuming source %s in %s namespace", name, rootArgs.namespace)
bucket.Spec.Suspend = false bucket.Spec.Suspend = false
if err := kubeClient.Update(ctx, &bucket); err != nil { if err := kubeClient.Update(ctx, &bucket); err != nil {
return err return err
@ -79,7 +79,7 @@ func resumeSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("source resumed") logger.Successf("source resumed")
logger.Waitingf("waiting for Bucket reconciliation") logger.Waitingf("waiting for Bucket reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isBucketResumed(ctx, kubeClient, namespacedName, &bucket)); err != nil { isBucketResumed(ctx, kubeClient, namespacedName, &bucket)); err != nil {
return err return err
} }

@ -53,16 +53,16 @@ func resumeSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.HelmChart var repository sourcev1.HelmChart
@ -71,7 +71,7 @@ func resumeSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming source %s in %s namespace", name, namespace) logger.Actionf("resuming source %s in %s namespace", name, rootArgs.namespace)
repository.Spec.Suspend = false repository.Spec.Suspend = false
if err := kubeClient.Update(ctx, &repository); err != nil { if err := kubeClient.Update(ctx, &repository); err != nil {
return err return err
@ -79,7 +79,7 @@ func resumeSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("source resumed") logger.Successf("source resumed")
logger.Waitingf("waiting for HelmChart reconciliation") logger.Waitingf("waiting for HelmChart reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isHelmChartResumed(ctx, kubeClient, namespacedName, &repository)); err != nil { isHelmChartResumed(ctx, kubeClient, namespacedName, &repository)); err != nil {
return err return err
} }

@ -53,16 +53,16 @@ func resumeSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.GitRepository var repository sourcev1.GitRepository
@ -71,7 +71,7 @@ func resumeSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming source %s in %s namespace", name, namespace) logger.Actionf("resuming source %s in %s namespace", name, rootArgs.namespace)
repository.Spec.Suspend = false repository.Spec.Suspend = false
if err := kubeClient.Update(ctx, &repository); err != nil { if err := kubeClient.Update(ctx, &repository); err != nil {
return err return err
@ -79,7 +79,7 @@ func resumeSourceGitCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("source resumed") logger.Successf("source resumed")
logger.Waitingf("waiting for GitRepository reconciliation") logger.Waitingf("waiting for GitRepository reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isGitRepositoryResumed(ctx, kubeClient, namespacedName, &repository)); err != nil { isGitRepositoryResumed(ctx, kubeClient, namespacedName, &repository)); err != nil {
return err return err
} }

@ -53,16 +53,16 @@ func resumeSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.HelmRepository var repository sourcev1.HelmRepository
@ -71,7 +71,7 @@ func resumeSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("resuming source %s in %s namespace", name, namespace) logger.Actionf("resuming source %s in %s namespace", name, rootArgs.namespace)
repository.Spec.Suspend = false repository.Spec.Suspend = false
if err := kubeClient.Update(ctx, &repository); err != nil { if err := kubeClient.Update(ctx, &repository); err != nil {
return err return err
@ -79,7 +79,7 @@ func resumeSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
logger.Successf("source resumed") logger.Successf("source resumed")
logger.Waitingf("waiting for HelmRepository reconciliation") logger.Waitingf("waiting for HelmRepository reconciliation")
if err := wait.PollImmediate(pollInterval, timeout, if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
isHelmRepositoryResumed(ctx, kubeClient, namespacedName, &repository)); err != nil { isHelmRepositoryResumed(ctx, kubeClient, namespacedName, &repository)); err != nil {
return err return err
} }

@ -53,16 +53,16 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
err = kubeClient.Get(ctx, namespacedName, suspend.object.asClientObject()) err = kubeClient.Get(ctx, namespacedName, suspend.object.asClientObject())
@ -70,7 +70,7 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending %s %s in %s namespace", suspend.humanKind, name, namespace) logger.Actionf("suspending %s %s in %s namespace", suspend.humanKind, name, rootArgs.namespace)
suspend.object.setSuspended() suspend.object.setSuspended()
if err := kubeClient.Update(ctx, suspend.object.asClientObject()); err != nil { if err := kubeClient.Update(ctx, suspend.object.asClientObject()); err != nil {
return err return err

@ -47,16 +47,16 @@ func suspendAlertCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var alert notificationv1.Alert var alert notificationv1.Alert
@ -65,7 +65,7 @@ func suspendAlertCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending Alert %s in %s namespace", name, namespace) logger.Actionf("suspending Alert %s in %s namespace", name, rootArgs.namespace)
alert.Spec.Suspend = true alert.Spec.Suspend = true
if err := kubeClient.Update(ctx, &alert); err != nil { if err := kubeClient.Update(ctx, &alert); err != nil {
return err return err

@ -48,16 +48,16 @@ func suspendHrCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var helmRelease helmv2.HelmRelease var helmRelease helmv2.HelmRelease
@ -66,7 +66,7 @@ func suspendHrCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending HelmRelease %s in %s namespace", name, namespace) logger.Actionf("suspending HelmRelease %s in %s namespace", name, rootArgs.namespace)
helmRelease.Spec.Suspend = true helmRelease.Spec.Suspend = true
if err := kubeClient.Update(ctx, &helmRelease); err != nil { if err := kubeClient.Update(ctx, &helmRelease); err != nil {
return err return err

@ -47,16 +47,16 @@ func suspendKsCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var kustomization kustomizev1.Kustomization var kustomization kustomizev1.Kustomization
@ -65,7 +65,7 @@ func suspendKsCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending kustomization %s in %s namespace", name, namespace) logger.Actionf("suspending kustomization %s in %s namespace", name, rootArgs.namespace)
kustomization.Spec.Suspend = true kustomization.Spec.Suspend = true
if err := kubeClient.Update(ctx, &kustomization); err != nil { if err := kubeClient.Update(ctx, &kustomization); err != nil {
return err return err

@ -47,16 +47,16 @@ func suspendReceiverCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var receiver notificationv1.Receiver var receiver notificationv1.Receiver
@ -65,7 +65,7 @@ func suspendReceiverCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending Receiver %s in %s namespace", name, namespace) logger.Actionf("suspending Receiver %s in %s namespace", name, rootArgs.namespace)
receiver.Spec.Suspend = true receiver.Spec.Suspend = true
if err := kubeClient.Update(ctx, &receiver); err != nil { if err := kubeClient.Update(ctx, &receiver); err != nil {
return err return err

@ -46,16 +46,16 @@ func suspendSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var bucket sourcev1.Bucket var bucket sourcev1.Bucket
@ -64,7 +64,7 @@ func suspendSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending source %s in %s namespace", name, namespace) logger.Actionf("suspending source %s in %s namespace", name, rootArgs.namespace)
bucket.Spec.Suspend = true bucket.Spec.Suspend = true
if err := kubeClient.Update(ctx, &bucket); err != nil { if err := kubeClient.Update(ctx, &bucket); err != nil {
return err return err

@ -46,16 +46,16 @@ func suspendSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var chart sourcev1.HelmChart var chart sourcev1.HelmChart
@ -64,7 +64,7 @@ func suspendSourceHelmChartCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending source %s in %s namespace", name, namespace) logger.Actionf("suspending source %s in %s namespace", name, rootArgs.namespace)
chart.Spec.Suspend = true chart.Spec.Suspend = true
if err := kubeClient.Update(ctx, &chart); err != nil { if err := kubeClient.Update(ctx, &chart); err != nil {
return err return err

@ -46,16 +46,16 @@ func suspendSourceGitCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.GitRepository var repository sourcev1.GitRepository
@ -64,7 +64,7 @@ func suspendSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending source %s in %s namespace", name, namespace) logger.Actionf("suspending source %s in %s namespace", name, rootArgs.namespace)
repository.Spec.Suspend = true repository.Spec.Suspend = true
if err := kubeClient.Update(ctx, &repository); err != nil { if err := kubeClient.Update(ctx, &repository); err != nil {
return err return err

@ -46,16 +46,16 @@ func suspendSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
name := args[0] name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: name, Name: name,
} }
var repository sourcev1.HelmRepository var repository sourcev1.HelmRepository
@ -64,7 +64,7 @@ func suspendSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
logger.Actionf("suspending source %s in %s namespace", name, namespace) logger.Actionf("suspending source %s in %s namespace", name, rootArgs.namespace)
repository.Spec.Suspend = true repository.Spec.Suspend = true
if err := kubeClient.Update(ctx, &repository); err != nil { if err := kubeClient.Update(ctx, &repository); err != nil {
return err return err

@ -45,38 +45,40 @@ var uninstallCmd = &cobra.Command{
RunE: uninstallCmdRun, RunE: uninstallCmdRun,
} }
var ( type uninstallFlags struct {
uninstallCRDs bool crds bool
uninstallResources bool resources bool
uninstallDryRun bool dryRun bool
uninstallSilent bool silent bool
) }
var uninstallArgs uninstallFlags
func init() { func init() {
uninstallCmd.Flags().BoolVar(&uninstallResources, "resources", true, uninstallCmd.Flags().BoolVar(&uninstallArgs.resources, "resources", true,
"removes custom resources such as Kustomizations, GitRepositories and HelmRepositories") "removes custom resources such as Kustomizations, GitRepositories and HelmRepositories")
uninstallCmd.Flags().BoolVar(&uninstallCRDs, "crds", false, uninstallCmd.Flags().BoolVar(&uninstallArgs.crds, "crds", false,
"removes all CRDs previously installed") "removes all CRDs previously installed")
uninstallCmd.Flags().BoolVar(&uninstallDryRun, "dry-run", false, uninstallCmd.Flags().BoolVar(&uninstallArgs.dryRun, "dry-run", false,
"only print the object that would be deleted") "only print the object that would be deleted")
uninstallCmd.Flags().BoolVarP(&uninstallSilent, "silent", "s", false, uninstallCmd.Flags().BoolVarP(&uninstallArgs.silent, "silent", "s", false,
"delete components without asking for confirmation") "delete components without asking for confirmation")
rootCmd.AddCommand(uninstallCmd) rootCmd.AddCommand(uninstallCmd)
} }
func uninstallCmdRun(cmd *cobra.Command, args []string) error { func uninstallCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext) kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil { if err != nil {
return err return err
} }
if !uninstallDryRun && !uninstallSilent { if !uninstallArgs.dryRun && !uninstallArgs.silent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: fmt.Sprintf("Are you sure you want to delete the %s namespace", namespace), Label: fmt.Sprintf("Are you sure you want to delete the %s namespace", rootArgs.namespace),
IsConfirm: true, IsConfirm: true,
} }
if _, err := prompt.Run(); err != nil { if _, err := prompt.Run(); err != nil {
@ -85,7 +87,7 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
} }
dryRun := "--dry-run=server" dryRun := "--dry-run=server"
deleteResources := uninstallResources || uninstallCRDs deleteResources := uninstallArgs.resources || uninstallArgs.crds
// known kinds with finalizers // known kinds with finalizers
namespacedKinds := []string{ namespacedKinds := []string{
@ -96,8 +98,8 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
// suspend bootstrap kustomization to avoid finalizers deadlock // suspend bootstrap kustomization to avoid finalizers deadlock
kustomizationName := types.NamespacedName{ kustomizationName := types.NamespacedName{
Namespace: namespace, Namespace: rootArgs.namespace,
Name: namespace, Name: rootArgs.namespace,
} }
var kustomization kustomizev1.Kustomization var kustomization kustomizev1.Kustomization
err = kubeClient.Get(ctx, kustomizationName, &kustomization) err = kubeClient.Get(ctx, kustomizationName, &kustomization)
@ -113,21 +115,21 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
// add HelmRelease kind to deletion list if exists // add HelmRelease kind to deletion list if exists
var list helmv2.HelmReleaseList var list helmv2.HelmReleaseList
if err := kubeClient.List(ctx, &list, client.InNamespace(namespace)); err == nil { if err := kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace)); err == nil {
namespacedKinds = append(namespacedKinds, helmv2.HelmReleaseKind) namespacedKinds = append(namespacedKinds, helmv2.HelmReleaseKind)
} }
if deleteResources { if deleteResources {
logger.Actionf("uninstalling custom resources") logger.Actionf("uninstalling custom resources")
for _, kind := range namespacedKinds { for _, kind := range namespacedKinds {
if err := deleteAll(ctx, kind, uninstallDryRun); err != nil { if err := deleteAll(ctx, kind, uninstallArgs.dryRun); err != nil {
logger.Failuref("kubectl: %s", err.Error()) logger.Failuref("kubectl: %s", err.Error())
} }
} }
} }
var kinds []string var kinds []string
if uninstallCRDs { if uninstallArgs.crds {
kinds = append(kinds, "crds") kinds = append(kinds, "crds")
} }
@ -138,13 +140,13 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
for _, kind := range kinds { for _, kind := range kinds {
kubectlArgs := []string{ kubectlArgs := []string{
"delete", kind, "delete", kind,
"-l", fmt.Sprintf("app.kubernetes.io/instance=%s", namespace), "-l", fmt.Sprintf("app.kubernetes.io/instance=%s", rootArgs.namespace),
"--ignore-not-found", "--timeout", timeout.String(), "--ignore-not-found", "--timeout", rootArgs.timeout.String(),
} }
if uninstallDryRun { if uninstallArgs.dryRun {
kubectlArgs = append(kubectlArgs, dryRun) kubectlArgs = append(kubectlArgs, dryRun)
} }
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...); err != nil { if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("uninstall failed: %w", err) return fmt.Errorf("uninstall failed: %w", err)
} }
} }
@ -157,13 +159,13 @@ func deleteAll(ctx context.Context, kind string, dryRun bool) error {
kubectlArgs := []string{ kubectlArgs := []string{
"delete", kind, "--ignore-not-found", "delete", kind, "--ignore-not-found",
"--all", "--all-namespaces", "--all", "--all-namespaces",
"--timeout", timeout.String(), "--timeout", rootArgs.timeout.String(),
} }
if dryRun { if dryRun {
kubectlArgs = append(kubectlArgs, "--dry-run=server") kubectlArgs = append(kubectlArgs, "--dry-run=server")
} }
_, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, kubeconfig, kubecontext, kubectlArgs...) _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
return err return err
} }

Loading…
Cancel
Save