Merge pull request #3755 from rishinair11/add_multiple_args
Allow multiple arguments for "flux suspend/resume"
This commit is contained in:
@@ -61,11 +61,26 @@ func TestKustomizationFromGit(t *testing.T) {
|
||||
"testdata/kustomization/suspend_kustomization_from_git.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"suspend kustomization tkfg foo tkfg bar",
|
||||
"testdata/kustomization/suspend_kustomization_from_git_multiple_args.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"resume kustomization tkfg foo --wait",
|
||||
"testdata/kustomization/resume_kustomization_from_git_multiple_args_wait.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"resume kustomization tkfg",
|
||||
"testdata/kustomization/resume_kustomization_from_git.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"resume kustomization tkfg tkfg",
|
||||
"testdata/kustomization/resume_kustomization_from_git_multiple_args.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"delete kustomization tkfg --silent",
|
||||
"testdata/kustomization/delete_kustomization_from_git.golden",
|
||||
|
||||
@@ -365,6 +365,12 @@ func executeTemplate(content string, templateValues map[string]string) (string,
|
||||
// Run the command and return the captured output.
|
||||
func executeCommand(cmd string) (string, error) {
|
||||
defer resetCmdArgs()
|
||||
defer func() {
|
||||
// need to set this explicitly because apparently its value isn't changed
|
||||
// in subsequent executions which causes tests to fail that rely on the value
|
||||
// of "Changed".
|
||||
resumeCmd.PersistentFlags().Lookup("wait").Changed = false
|
||||
}()
|
||||
args, err := shellwords.Parse(cmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -47,7 +47,7 @@ type copyable interface {
|
||||
deepCopyClientObject() client.Object
|
||||
}
|
||||
|
||||
// listAdapater is the analogue to adapter, but for lists; the
|
||||
// listAdapter is the analogue to adapter, but for lists; the
|
||||
// controller runtime distinguishes between methods dealing with
|
||||
// objects and lists.
|
||||
type listAdapter interface {
|
||||
|
||||
@@ -19,6 +19,8 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
@@ -59,8 +61,10 @@ type resumable interface {
|
||||
|
||||
type resumeCommand struct {
|
||||
apiType
|
||||
object resumable
|
||||
client client.WithWatch
|
||||
list listResumable
|
||||
namespace string
|
||||
shouldReconcile bool
|
||||
}
|
||||
|
||||
type listResumable interface {
|
||||
@@ -68,6 +72,11 @@ type listResumable interface {
|
||||
resumeItem(i int) resumable
|
||||
}
|
||||
|
||||
type reconcileResponse struct {
|
||||
resumable
|
||||
err error
|
||||
}
|
||||
|
||||
func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 && !resumeArgs.all {
|
||||
return fmt.Errorf("%s name is required", resume.humanKind)
|
||||
@@ -80,52 +89,162 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resume.client = kubeClient
|
||||
resume.namespace = *kubeconfigArgs.Namespace
|
||||
|
||||
var listOpts []client.ListOption
|
||||
listOpts = append(listOpts, client.InNamespace(*kubeconfigArgs.Namespace))
|
||||
if len(args) > 0 {
|
||||
listOpts = append(listOpts, client.MatchingFields{
|
||||
"metadata.name": args[0],
|
||||
})
|
||||
}
|
||||
// require waiting for the object(s) if the user has not provided the --wait flag and gave exactly
|
||||
// one object to resume. This is necessary to maintain backwards compatibility with prior versions
|
||||
// of this command. Otherwise just follow the value of the --wait flag (including its default).
|
||||
resume.shouldReconcile = !resumeCmd.PersistentFlags().Changed("wait") && len(args) == 1 || resumeArgs.wait
|
||||
|
||||
err = kubeClient.List(ctx, resume.list.asClientList(), listOpts...)
|
||||
resumables, err := resume.getPatchedResumables(ctx, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resume.list.len() == 0 {
|
||||
logger.Failuref("no %s objects found in %s namespace", resume.kind, *kubeconfigArgs.Namespace)
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(resumables))
|
||||
|
||||
resultChan := make(chan reconcileResponse, len(resumables))
|
||||
for _, r := range resumables {
|
||||
go func(res resumable) {
|
||||
defer wg.Done()
|
||||
resultChan <- resume.reconcile(ctx, res)
|
||||
}(r)
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(resultChan)
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
reconcileResps := make([]reconcileResponse, 0, len(resumables))
|
||||
for c := range resultChan {
|
||||
reconcileResps = append(reconcileResps, c)
|
||||
}
|
||||
|
||||
resume.printMessage(reconcileResps)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < resume.list.len(); i++ {
|
||||
logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, resume.list.resumeItem(i).asClientObject().GetName(), *kubeconfigArgs.Namespace)
|
||||
obj := resume.list.resumeItem(i)
|
||||
patch := client.MergeFrom(obj.deepCopyClientObject())
|
||||
obj.setUnsuspended()
|
||||
if err := kubeClient.Patch(ctx, obj.asClientObject(), patch); err != nil {
|
||||
return err
|
||||
// getPatchedResumables returns a list of the given resumable objects that have been patched to be resumed.
|
||||
// If the args slice is empty, it patches all resumable objects in the given namespace.
|
||||
func (resume *resumeCommand) getPatchedResumables(ctx context.Context, args []string) ([]resumable, error) {
|
||||
if len(args) < 1 {
|
||||
objs, err := resume.patch(ctx, []client.ListOption{
|
||||
client.InNamespace(resume.namespace),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed patching objects: %w", err)
|
||||
}
|
||||
|
||||
logger.Successf("%s resumed", resume.humanKind)
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
var resumables []resumable
|
||||
processed := make(map[string]struct{}, len(args))
|
||||
for _, arg := range args {
|
||||
if _, has := processed[arg]; has {
|
||||
continue // skip object that user might have provided more than once
|
||||
}
|
||||
processed[arg] = struct{}{}
|
||||
|
||||
objs, err := resume.patch(ctx, []client.ListOption{
|
||||
client.InNamespace(resume.namespace),
|
||||
client.MatchingFields{
|
||||
"metadata.name": arg,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resumables = append(resumables, objs...)
|
||||
}
|
||||
|
||||
return resumables, nil
|
||||
}
|
||||
|
||||
// Patches resumable objects by setting their status to unsuspended.
|
||||
// Returns a slice of resumables that have been patched and any error encountered during patching.
|
||||
func (resume resumeCommand) patch(ctx context.Context, listOpts []client.ListOption) ([]resumable, error) {
|
||||
if err := resume.client.List(ctx, resume.list.asClientList(), listOpts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resume.list.len() == 0 {
|
||||
logger.Failuref("no %s objects found in %s namespace", resume.kind, resume.namespace)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var resumables []resumable
|
||||
|
||||
for i := 0; i < resume.list.len(); i++ {
|
||||
obj := resume.list.resumeItem(i)
|
||||
logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, obj.asClientObject().GetName(), resume.namespace)
|
||||
|
||||
patch := client.MergeFrom(obj.deepCopyClientObject())
|
||||
obj.setUnsuspended()
|
||||
if err := resume.client.Patch(ctx, obj.asClientObject(), patch); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resumables = append(resumables, obj)
|
||||
|
||||
logger.Successf("%s resumed", resume.humanKind)
|
||||
}
|
||||
|
||||
return resumables, nil
|
||||
}
|
||||
|
||||
// Waits for resumable object to be reconciled and returns the object and any error encountered while waiting.
|
||||
// Returns an empty reconcileResponse, if shouldReconcile is false.
|
||||
func (resume resumeCommand) reconcile(ctx context.Context, res resumable) reconcileResponse {
|
||||
if !resume.shouldReconcile {
|
||||
return reconcileResponse{}
|
||||
}
|
||||
|
||||
if resumeArgs.wait || !resumeArgs.all {
|
||||
namespacedName := types.NamespacedName{
|
||||
Name: resume.list.resumeItem(i).asClientObject().GetName(),
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Name: res.asClientObject().GetName(),
|
||||
Namespace: resume.namespace,
|
||||
}
|
||||
|
||||
logger.Waitingf("waiting for %s reconciliation", resume.kind)
|
||||
|
||||
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
|
||||
isReady(ctx, kubeClient, namespacedName, resume.list.resumeItem(i))); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
continue
|
||||
}
|
||||
logger.Successf("%s reconciliation completed", resume.kind)
|
||||
logger.Successf(resume.list.resumeItem(i).successMessage())
|
||||
isReady(ctx, resume.client, namespacedName, res)); err != nil {
|
||||
return reconcileResponse{
|
||||
resumable: res,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return reconcileResponse{
|
||||
resumable: res,
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// Sorts the given reconcileResponses by resumable name and prints the success/error message for each response.
|
||||
func (resume resumeCommand) printMessage(responses []reconcileResponse) {
|
||||
sort.Slice(responses, func(i, j int) bool {
|
||||
r1, r2 := responses[i], responses[j]
|
||||
if r1.resumable == nil || r2.resumable == nil {
|
||||
return false
|
||||
}
|
||||
return r1.asClientObject().GetName() <= r2.asClientObject().GetName()
|
||||
})
|
||||
|
||||
// Print success/error message.
|
||||
for _, r := range responses {
|
||||
if r.resumable == nil {
|
||||
continue
|
||||
}
|
||||
if r.err != nil {
|
||||
logger.Failuref(r.err.Error())
|
||||
}
|
||||
logger.Successf("%s %s reconciliation completed", resume.kind, r.asClientObject().GetName())
|
||||
logger.Successf(r.successMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,13 @@ var resumeAlertCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended Alert resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Alert
|
||||
flux resume alert main`,
|
||||
flux resume alert main
|
||||
|
||||
# Resume reconciliation for multiple Alerts
|
||||
flux resume alert main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.AlertKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: alertType,
|
||||
object: alertAdapter{¬ificationv1.Alert{}},
|
||||
list: &alertListAdapter{¬ificationv1.AlertList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -31,11 +31,13 @@ var resumeHrCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended HelmRelease resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Helm release
|
||||
flux resume hr podinfo`,
|
||||
flux resume hr podinfo
|
||||
|
||||
# Resume reconciliation for multiple Helm releases
|
||||
flux resume hr podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: helmReleaseType,
|
||||
object: helmReleaseAdapter{&helmv2.HelmRelease{}},
|
||||
list: helmReleaseListAdapter{&helmv2.HelmReleaseList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeImageRepositoryCmd = &cobra.Command{
|
||||
Short: "Resume a suspended ImageRepository",
|
||||
Long: `The resume command marks a previously suspended ImageRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing ImageRepository
|
||||
flux resume image repository alpine`,
|
||||
flux resume image repository alpine
|
||||
|
||||
# Resume reconciliation for multiple ImageRepositories
|
||||
flux resume image repository alpine-1 alpine-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: imageRepositoryType,
|
||||
object: imageRepositoryAdapter{&imagev1.ImageRepository{}},
|
||||
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeImageUpdateCmd = &cobra.Command{
|
||||
Short: "Resume a suspended ImageUpdateAutomation",
|
||||
Long: `The resume command marks a previously suspended ImageUpdateAutomation resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing ImageUpdateAutomation
|
||||
flux resume image update latest-images`,
|
||||
flux resume image update latest-images
|
||||
|
||||
# Resume reconciliation for multiple ImageUpdateAutomations
|
||||
flux resume image update latest-images-1 latest-images-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: imageUpdateAutomationType,
|
||||
object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}},
|
||||
list: imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -31,11 +31,13 @@ var resumeKsCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended Kustomization resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Kustomization
|
||||
flux resume ks podinfo`,
|
||||
flux resume ks podinfo
|
||||
|
||||
# Resume reconciliation for multiple Kustomizations
|
||||
flux resume ks podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: kustomizationType,
|
||||
object: kustomizationAdapter{&kustomizev1.Kustomization{}},
|
||||
list: kustomizationListAdapter{&kustomizev1.KustomizationList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -28,11 +28,13 @@ var resumeReceiverCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended Receiver resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Receiver
|
||||
flux resume receiver main`,
|
||||
flux resume receiver main
|
||||
|
||||
# Resume reconciliation for multiple Receivers
|
||||
flux resume receiver main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.ReceiverKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: receiverType,
|
||||
object: receiverAdapter{¬ificationv1.Receiver{}},
|
||||
list: receiverListAdapter{¬ificationv1.ReceiverList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceBucketCmd = &cobra.Command{
|
||||
Short: "Resume a suspended Bucket",
|
||||
Long: `The resume command marks a previously suspended Bucket resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing Bucket
|
||||
flux resume source bucket podinfo`,
|
||||
flux resume source bucket podinfo
|
||||
|
||||
# Resume reconciliation for multiple Buckets
|
||||
flux resume source bucket podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: bucketType,
|
||||
object: bucketAdapter{&sourcev1.Bucket{}},
|
||||
list: bucketListAdapter{&sourcev1.BucketList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -29,11 +29,13 @@ var resumeSourceHelmChartCmd = &cobra.Command{
|
||||
Short: "Resume a suspended HelmChart",
|
||||
Long: `The resume command marks a previously suspended HelmChart resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing HelmChart
|
||||
flux resume source chart podinfo`,
|
||||
flux resume source chart podinfo
|
||||
|
||||
# Resume reconciliation for multiple HelmCharts
|
||||
flux resume source chart podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: helmChartType,
|
||||
object: &helmChartAdapter{&sourcev1.HelmChart{}},
|
||||
list: &helmChartListAdapter{&sourcev1.HelmChartList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceGitCmd = &cobra.Command{
|
||||
Short: "Resume a suspended GitRepository",
|
||||
Long: `The resume command marks a previously suspended GitRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing GitRepository
|
||||
flux resume source git podinfo`,
|
||||
flux resume source git podinfo
|
||||
|
||||
# Resume reconciliation for multiple GitRepositories
|
||||
flux resume source git podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: gitRepositoryType,
|
||||
object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
|
||||
list: gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceHelmCmd = &cobra.Command{
|
||||
Short: "Resume a suspended HelmRepository",
|
||||
Long: `The resume command marks a previously suspended HelmRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing HelmRepository
|
||||
flux resume source helm bitnami`,
|
||||
flux resume source helm bitnami
|
||||
|
||||
# Resume reconciliation for multiple HelmRepositories
|
||||
flux resume source helm bitnami-1 bitnami-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: helmRepositoryType,
|
||||
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}},
|
||||
list: helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceOCIRepositoryCmd = &cobra.Command{
|
||||
Short: "Resume a suspended OCIRepository",
|
||||
Long: `The resume command marks a previously suspended OCIRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing OCIRepository
|
||||
flux resume source oci podinfo`,
|
||||
flux resume source oci podinfo
|
||||
|
||||
# Resume reconciliation for multiple OCIRepositories
|
||||
flux resume source oci podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: ociRepositoryType,
|
||||
object: ociRepositoryAdapter{&sourcev1.OCIRepository{}},
|
||||
list: ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -75,22 +76,53 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var listOpts []client.ListOption
|
||||
listOpts = append(listOpts, client.InNamespace(*kubeconfigArgs.Namespace))
|
||||
if len(args) > 0 {
|
||||
listOpts = append(listOpts, client.MatchingFields{
|
||||
"metadata.name": args[0],
|
||||
})
|
||||
if len(args) < 1 && suspendArgs.all {
|
||||
listOpts := []client.ListOption{
|
||||
client.InNamespace(*kubeconfigArgs.Namespace),
|
||||
}
|
||||
|
||||
err = kubeClient.List(ctx, suspend.list.asClientList(), listOpts...)
|
||||
if err != nil {
|
||||
if err := suspend.patch(ctx, kubeClient, listOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
processed := make(map[string]struct{}, len(args))
|
||||
for _, arg := range args {
|
||||
if _, has := processed[arg]; has {
|
||||
continue // skip object that user might have provided more than once
|
||||
}
|
||||
processed[arg] = struct{}{}
|
||||
|
||||
listOpts := []client.ListOption{
|
||||
client.InNamespace(*kubeconfigArgs.Namespace),
|
||||
client.MatchingFields{
|
||||
"metadata.name": arg,
|
||||
},
|
||||
}
|
||||
|
||||
if err := suspend.patch(ctx, kubeClient, listOpts); err != nil {
|
||||
if err == ErrNoObjectsFound {
|
||||
logger.Failuref("%s %s not found in %s namespace", suspend.kind, arg, *kubeconfigArgs.Namespace)
|
||||
} else {
|
||||
logger.Failuref("failed suspending %s %s in %s namespace: %s", suspend.kind, arg, *kubeconfigArgs.Namespace, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var ErrNoObjectsFound = errors.New("no objects found")
|
||||
|
||||
func (suspend suspendCommand) patch(ctx context.Context, kubeClient client.WithWatch, listOpts []client.ListOption) error {
|
||||
if err := kubeClient.List(ctx, suspend.list.asClientList(), listOpts...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if suspend.list.len() == 0 {
|
||||
logger.Failuref("no %s objects found in %s namespace", suspend.kind, *kubeconfigArgs.Namespace)
|
||||
return nil
|
||||
return ErrNoObjectsFound
|
||||
}
|
||||
|
||||
for i := 0; i < suspend.list.len(); i++ {
|
||||
@@ -102,8 +134,8 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if err := kubeClient.Patch(ctx, obj.asClientObject(), patch); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Successf("%s suspended", suspend.humanKind)
|
||||
|
||||
logger.Successf("%s suspended", suspend.humanKind)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendAlertCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of Alert",
|
||||
Long: `The suspend command disables the reconciliation of a Alert resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Alert
|
||||
flux suspend alert main`,
|
||||
flux suspend alert main
|
||||
|
||||
# Suspend reconciliation for multiple Alerts
|
||||
flux suspend alert main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.AlertKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: alertType,
|
||||
|
||||
@@ -28,7 +28,10 @@ var suspendHrCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of HelmRelease",
|
||||
Long: `The suspend command disables the reconciliation of a HelmRelease resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Helm release
|
||||
flux suspend hr podinfo`,
|
||||
flux suspend hr podinfo
|
||||
|
||||
# Suspend reconciliation for multiple Helm releases
|
||||
flux suspend hr podinfo-1 podinfo-2 `,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: helmReleaseType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendImageRepositoryCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of an ImageRepository",
|
||||
Long: `The suspend image repository command disables the reconciliation of a ImageRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing ImageRepository
|
||||
flux suspend image repository alpine`,
|
||||
flux suspend image repository alpine
|
||||
|
||||
# Suspend reconciliation for multiple ImageRepositories
|
||||
flux suspend image repository alpine-1 alpine-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: imageRepositoryType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendImageUpdateCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of an ImageUpdateAutomation",
|
||||
Long: `The suspend image update command disables the reconciliation of a ImageUpdateAutomation resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing ImageUpdateAutomation
|
||||
flux suspend image update latest-images`,
|
||||
flux suspend image update latest-images
|
||||
|
||||
# Suspend reconciliation for multiple ImageUpdateAutomations
|
||||
flux suspend image update latest-images-1 latest-images-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: imageUpdateAutomationType,
|
||||
|
||||
@@ -28,7 +28,10 @@ var suspendKsCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of Kustomization",
|
||||
Long: `The suspend command disables the reconciliation of a Kustomization resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Kustomization
|
||||
flux suspend ks podinfo`,
|
||||
flux suspend ks podinfo
|
||||
|
||||
# Suspend reconciliation for multiple Kustomizations
|
||||
flux suspend ks podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: kustomizationType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendReceiverCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of Receiver",
|
||||
Long: `The suspend command disables the reconciliation of a Receiver resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Receiver
|
||||
flux suspend receiver main`,
|
||||
flux suspend receiver main
|
||||
|
||||
# Suspend reconciliation for multiple Receivers
|
||||
flux suspend receiver main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.ReceiverKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: receiverType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceBucketCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a Bucket",
|
||||
Long: `The suspend command disables the reconciliation of a Bucket resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Bucket
|
||||
flux suspend source bucket podinfo`,
|
||||
flux suspend source bucket podinfo
|
||||
|
||||
# Suspend reconciliation for multiple Buckets
|
||||
flux suspend source bucket podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: bucketType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceHelmChartCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a HelmChart",
|
||||
Long: `The suspend command disables the reconciliation of a HelmChart resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing HelmChart
|
||||
flux suspend source chart podinfo`,
|
||||
flux suspend source chart podinfo
|
||||
|
||||
# Suspend reconciliation for multiple HelmCharts
|
||||
flux suspend source chart podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: helmChartType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceGitCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a GitRepository",
|
||||
Long: `The suspend command disables the reconciliation of a GitRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing GitRepository
|
||||
flux suspend source git podinfo`,
|
||||
flux suspend source git podinfo
|
||||
|
||||
# Suspend reconciliation for multiple GitRepositories
|
||||
flux suspend source git podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: gitRepositoryType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceHelmCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a HelmRepository",
|
||||
Long: `The suspend command disables the reconciliation of a HelmRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing HelmRepository
|
||||
flux suspend source helm bitnami`,
|
||||
flux suspend source helm bitnami
|
||||
|
||||
# Suspend reconciliation for multiple HelmRepositories
|
||||
flux suspend source helm bitnami-1 bitnami-2 `,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: helmRepositoryType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceOCIRepositoryCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of an OCIRepository",
|
||||
Long: `The suspend command disables the reconciliation of an OCIRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing OCIRepository
|
||||
flux suspend source oci podinfo`,
|
||||
flux suspend source oci podinfo
|
||||
|
||||
# Suspend reconciliation for multiple OCIRepositories
|
||||
flux suspend source oci podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: ociRepositoryType,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
► resuming helmrelease thrfg in {{ .ns }} namespace
|
||||
✔ helmrelease resumed
|
||||
◎ waiting for HelmRelease reconciliation
|
||||
✔ HelmRelease reconciliation completed
|
||||
✔ HelmRelease thrfg reconciliation completed
|
||||
✔ applied revision 6.3.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
► resuming kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization resumed
|
||||
◎ waiting for Kustomization reconciliation
|
||||
✔ Kustomization reconciliation completed
|
||||
✔ Kustomization tkfg reconciliation completed
|
||||
✔ applied revision 6.3.5@sha1:67e2c98a60dc92283531412a9e604dd4bae005a9
|
||||
|
||||
2
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args.golden
vendored
Normal file
2
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args.golden
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
► resuming kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization resumed
|
||||
6
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args_wait.golden
vendored
Normal file
6
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args_wait.golden
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
► resuming kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization resumed
|
||||
✗ no Kustomization objects found in {{ .ns }} namespace
|
||||
◎ waiting for Kustomization reconciliation
|
||||
✔ Kustomization tkfg reconciliation completed
|
||||
✔ applied revision 6.3.5@sha1:67e2c98a60dc92283531412a9e604dd4bae005a9
|
||||
4
cmd/flux/testdata/kustomization/suspend_kustomization_from_git_multiple_args.golden
vendored
Normal file
4
cmd/flux/testdata/kustomization/suspend_kustomization_from_git_multiple_args.golden
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
► suspending kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization suspended
|
||||
✗ Kustomization foo not found in {{ .ns }} namespace
|
||||
✗ Kustomization bar not found in {{ .ns }} namespace
|
||||
2
cmd/flux/testdata/oci/resume_oci.golden
vendored
2
cmd/flux/testdata/oci/resume_oci.golden
vendored
@@ -1,5 +1,5 @@
|
||||
► resuming source oci thrfg in {{ .ns }} namespace
|
||||
✔ source oci resumed
|
||||
◎ waiting for OCIRepository reconciliation
|
||||
✔ OCIRepository reconciliation completed
|
||||
✔ OCIRepository thrfg reconciliation completed
|
||||
✔ fetched revision 6.3.5@sha256:6c959c51ccbb952e5fe4737563338a0aaf975675dcf812912cf09e5463181871
|
||||
|
||||
Reference in New Issue
Block a user