Skip to content

Commit e13ab33

Browse files
committed
check readiness using kstatus
This change replaces all the many functions and ways of calculating readiness of objects into one unified way that uses kstatus.Compute() to check if the object is in progress or current. Only the objects that are current are considered to be ready. This takes advantage of the kstatus compatibility of Flux's APIs and also makes sure that they remain kstatus compatible. The new isObjectReady() function is also aware of static/statusless objects and knows how to check their readiness using kstatus. This prepares the CLI for the upcoming static API objects. All the is*Ready() functions for specific objects have been removed. This change doesn't affect any of the existing tests results. Introduce suspend and resume subcommands for alert-provider. Signed-off-by: Sunny <darkowlzz@protonmail.com>
1 parent ae0c3c8 commit e13ab33

26 files changed

+467
-422
lines changed

cmd/flux/create.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func (names apiType) upsertAndWait(object upsertWaitable, mutate func() error) e
132132

133133
logger.Waitingf("waiting for %s reconciliation", names.kind)
134134
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
135-
isReady(ctx, kubeClient, namespacedName, object)); err != nil {
135+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, object.asClientObject())); err != nil {
136136
return err
137137
}
138138
logger.Successf("%s reconciliation completed", names.kind)

cmd/flux/create_alert.go

+1-22
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222

2323
"github.com/spf13/cobra"
2424
"k8s.io/apimachinery/pkg/api/errors"
25-
apimeta "k8s.io/apimachinery/pkg/api/meta"
2625
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2726
"k8s.io/apimachinery/pkg/types"
2827
"k8s.io/apimachinery/pkg/util/wait"
@@ -133,7 +132,7 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
133132

134133
logger.Waitingf("waiting for Alert reconciliation")
135134
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
136-
isAlertReady(ctx, kubeClient, namespacedName, &alert)); err != nil {
135+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, &alert)); err != nil {
137136
return err
138137
}
139138
logger.Successf("Alert %s is ready", name)
@@ -170,23 +169,3 @@ func upsertAlert(ctx context.Context, kubeClient client.Client,
170169
logger.Successf("Alert updated")
171170
return namespacedName, nil
172171
}
173-
174-
func isAlertReady(ctx context.Context, kubeClient client.Client,
175-
namespacedName types.NamespacedName, alert *notificationv1b2.Alert) wait.ConditionFunc {
176-
return func() (bool, error) {
177-
err := kubeClient.Get(ctx, namespacedName, alert)
178-
if err != nil {
179-
return false, err
180-
}
181-
182-
if c := apimeta.FindStatusCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
183-
switch c.Status {
184-
case metav1.ConditionTrue:
185-
return true, nil
186-
case metav1.ConditionFalse:
187-
return false, fmt.Errorf(c.Message)
188-
}
189-
}
190-
return false, nil
191-
}
192-
}

cmd/flux/create_alertprovider.go

+1-22
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222

2323
"github.com/spf13/cobra"
2424
"k8s.io/apimachinery/pkg/api/errors"
25-
apimeta "k8s.io/apimachinery/pkg/api/meta"
2625
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2726
"k8s.io/apimachinery/pkg/types"
2827
"k8s.io/apimachinery/pkg/util/wait"
@@ -128,7 +127,7 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
128127

129128
logger.Waitingf("waiting for Provider reconciliation")
130129
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
131-
isAlertProviderReady(ctx, kubeClient, namespacedName, &provider)); err != nil {
130+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, &provider)); err != nil {
132131
return err
133132
}
134133

@@ -167,23 +166,3 @@ func upsertAlertProvider(ctx context.Context, kubeClient client.Client,
167166
logger.Successf("Provider updated")
168167
return namespacedName, nil
169168
}
170-
171-
func isAlertProviderReady(ctx context.Context, kubeClient client.Client,
172-
namespacedName types.NamespacedName, provider *notificationv1.Provider) wait.ConditionFunc {
173-
return func() (bool, error) {
174-
err := kubeClient.Get(ctx, namespacedName, provider)
175-
if err != nil {
176-
return false, err
177-
}
178-
179-
if c := apimeta.FindStatusCondition(provider.Status.Conditions, meta.ReadyCondition); c != nil {
180-
switch c.Status {
181-
case metav1.ConditionTrue:
182-
return true, nil
183-
case metav1.ConditionFalse:
184-
return false, fmt.Errorf(c.Message)
185-
}
186-
}
187-
return false, nil
188-
}
189-
}

cmd/flux/create_helmrelease.go

+1-19
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import (
3232
"github.com/spf13/cobra"
3333
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
3434
"k8s.io/apimachinery/pkg/api/errors"
35-
apimeta "k8s.io/apimachinery/pkg/api/meta"
3635
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3736
"k8s.io/apimachinery/pkg/types"
3837
"k8s.io/apimachinery/pkg/util/wait"
@@ -304,7 +303,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
304303

305304
logger.Waitingf("waiting for HelmRelease reconciliation")
306305
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
307-
isHelmReleaseReady(ctx, kubeClient, namespacedName, &helmRelease)); err != nil {
306+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, &helmRelease)); err != nil {
308307
return err
309308
}
310309
logger.Successf("HelmRelease %s is ready", name)
@@ -344,23 +343,6 @@ func upsertHelmRelease(ctx context.Context, kubeClient client.Client,
344343
return namespacedName, nil
345344
}
346345

347-
func isHelmReleaseReady(ctx context.Context, kubeClient client.Client,
348-
namespacedName types.NamespacedName, helmRelease *helmv2.HelmRelease) wait.ConditionFunc {
349-
return func() (bool, error) {
350-
err := kubeClient.Get(ctx, namespacedName, helmRelease)
351-
if err != nil {
352-
return false, err
353-
}
354-
355-
// Confirm the state we are observing is for the current generation
356-
if helmRelease.Generation != helmRelease.Status.ObservedGeneration {
357-
return false, nil
358-
}
359-
360-
return apimeta.IsStatusConditionTrue(helmRelease.Status.Conditions, meta.ReadyCondition), nil
361-
}
362-
}
363-
364346
func validateStrategy(input string) bool {
365347
allowedStrategy := []string{"Revision", "ChartVersion"}
366348

cmd/flux/create_kustomization.go

+1-27
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424

2525
"github.com/spf13/cobra"
2626
"k8s.io/apimachinery/pkg/api/errors"
27-
apimeta "k8s.io/apimachinery/pkg/api/meta"
2827
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2928
"k8s.io/apimachinery/pkg/types"
3029
"k8s.io/apimachinery/pkg/util/wait"
@@ -264,7 +263,7 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
264263

265264
logger.Waitingf("waiting for Kustomization reconciliation")
266265
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
267-
isKustomizationReady(ctx, kubeClient, namespacedName, &kustomization)); err != nil {
266+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, &kustomization)); err != nil {
268267
return err
269268
}
270269
logger.Successf("Kustomization %s is ready", name)
@@ -303,28 +302,3 @@ func upsertKustomization(ctx context.Context, kubeClient client.Client,
303302
logger.Successf("Kustomization updated")
304303
return namespacedName, nil
305304
}
306-
307-
func isKustomizationReady(ctx context.Context, kubeClient client.Client,
308-
namespacedName types.NamespacedName, kustomization *kustomizev1.Kustomization) wait.ConditionFunc {
309-
return func() (bool, error) {
310-
err := kubeClient.Get(ctx, namespacedName, kustomization)
311-
if err != nil {
312-
return false, err
313-
}
314-
315-
// Confirm the state we are observing is for the current generation
316-
if kustomization.Generation != kustomization.Status.ObservedGeneration {
317-
return false, nil
318-
}
319-
320-
if c := apimeta.FindStatusCondition(kustomization.Status.Conditions, meta.ReadyCondition); c != nil {
321-
switch c.Status {
322-
case metav1.ConditionTrue:
323-
return true, nil
324-
case metav1.ConditionFalse:
325-
return false, fmt.Errorf(c.Message)
326-
}
327-
}
328-
return false, nil
329-
}
330-
}

cmd/flux/create_receiver.go

+1-22
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222

2323
"github.com/spf13/cobra"
2424
"k8s.io/apimachinery/pkg/api/errors"
25-
apimeta "k8s.io/apimachinery/pkg/api/meta"
2625
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2726
"k8s.io/apimachinery/pkg/types"
2827
"k8s.io/apimachinery/pkg/util/wait"
@@ -140,7 +139,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
140139

141140
logger.Waitingf("waiting for Receiver reconciliation")
142141
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
143-
isReceiverReady(ctx, kubeClient, namespacedName, &receiver)); err != nil {
142+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, &receiver)); err != nil {
144143
return err
145144
}
146145
logger.Successf("Receiver %s is ready", name)
@@ -179,23 +178,3 @@ func upsertReceiver(ctx context.Context, kubeClient client.Client,
179178
logger.Successf("Receiver updated")
180179
return namespacedName, nil
181180
}
182-
183-
func isReceiverReady(ctx context.Context, kubeClient client.Client,
184-
namespacedName types.NamespacedName, receiver *notificationv1.Receiver) wait.ConditionFunc {
185-
return func() (bool, error) {
186-
err := kubeClient.Get(ctx, namespacedName, receiver)
187-
if err != nil {
188-
return false, err
189-
}
190-
191-
if c := apimeta.FindStatusCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
192-
switch c.Status {
193-
case metav1.ConditionTrue:
194-
return true, nil
195-
case metav1.ConditionFalse:
196-
return false, fmt.Errorf(c.Message)
197-
}
198-
}
199-
return false, nil
200-
}
201-
}

cmd/flux/create_source_bucket.go

+1-29
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"sigs.k8s.io/controller-runtime/pkg/client"
3232

3333
"github.com/fluxcd/pkg/apis/meta"
34-
"github.com/fluxcd/pkg/runtime/conditions"
3534

3635
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
3736

@@ -205,7 +204,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
205204

206205
logger.Waitingf("waiting for Bucket source reconciliation")
207206
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
208-
isBucketReady(ctx, kubeClient, namespacedName, bucket)); err != nil {
207+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, bucket)); err != nil {
209208
return err
210209
}
211210
logger.Successf("Bucket source reconciliation completed")
@@ -247,30 +246,3 @@ func upsertBucket(ctx context.Context, kubeClient client.Client,
247246
logger.Successf("Bucket source updated")
248247
return namespacedName, nil
249248
}
250-
251-
func isBucketReady(ctx context.Context, kubeClient client.Client,
252-
namespacedName types.NamespacedName, bucket *sourcev1.Bucket) wait.ConditionFunc {
253-
return func() (bool, error) {
254-
err := kubeClient.Get(ctx, namespacedName, bucket)
255-
if err != nil {
256-
return false, err
257-
}
258-
259-
if c := conditions.Get(bucket, meta.ReadyCondition); c != nil {
260-
// Confirm the Ready condition we are observing is for the
261-
// current generation
262-
if c.ObservedGeneration != bucket.GetGeneration() {
263-
return false, nil
264-
}
265-
266-
// Further check the Status
267-
switch c.Status {
268-
case metav1.ConditionTrue:
269-
return true, nil
270-
case metav1.ConditionFalse:
271-
return false, fmt.Errorf(c.Message)
272-
}
273-
}
274-
return false, nil
275-
}
276-
}

cmd/flux/create_source_git.go

+1-29
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import (
3535
"sigs.k8s.io/yaml"
3636

3737
"github.com/fluxcd/pkg/apis/meta"
38-
"github.com/fluxcd/pkg/runtime/conditions"
3938

4039
sourcev1 "github.com/fluxcd/source-controller/api/v1"
4140

@@ -326,7 +325,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
326325

327326
logger.Waitingf("waiting for GitRepository source reconciliation")
328327
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
329-
isGitRepositoryReady(ctx, kubeClient, namespacedName, &gitRepository)); err != nil {
328+
isObjectReadyConditionFunc(ctx, kubeClient, namespacedName, &gitRepository)); err != nil {
330329
return err
331330
}
332331
logger.Successf("GitRepository source reconciliation completed")
@@ -368,30 +367,3 @@ func upsertGitRepository(ctx context.Context, kubeClient client.Client,
368367
logger.Successf("GitRepository source updated")
369368
return namespacedName, nil
370369
}
371-
372-
func isGitRepositoryReady(ctx context.Context, kubeClient client.Client,
373-
namespacedName types.NamespacedName, gitRepository *sourcev1.GitRepository) wait.ConditionFunc {
374-
return func() (bool, error) {
375-
err := kubeClient.Get(ctx, namespacedName, gitRepository)
376-
if err != nil {
377-
return false, err
378-
}
379-
380-
if c := conditions.Get(gitRepository, meta.ReadyCondition); c != nil {
381-
// Confirm the Ready condition we are observing is for the
382-
// current generation
383-
if c.ObservedGeneration != gitRepository.GetGeneration() {
384-
return false, nil
385-
}
386-
387-
// Further check the Status
388-
switch c.Status {
389-
case metav1.ConditionTrue:
390-
return true, nil
391-
case metav1.ConditionFalse:
392-
return false, fmt.Errorf(c.Message)
393-
}
394-
}
395-
return false, nil
396-
}
397-
}

cmd/flux/create_source_git_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,21 @@ func TestCreateSourceGit(t *testing.T) {
181181
Time: time.Now(),
182182
},
183183
}
184+
repo.Status.ObservedGeneration = repo.GetGeneration()
184185
},
185186
}, {
186187
"Failed",
187188
command,
188189
assertError("failed message"),
189190
func(repo *sourcev1.GitRepository) {
191+
stalledCondition := metav1.Condition{
192+
Type: meta.StalledCondition,
193+
Status: metav1.ConditionTrue,
194+
Reason: sourcev1.URLInvalidReason,
195+
Message: "failed message",
196+
ObservedGeneration: repo.GetGeneration(),
197+
}
198+
apimeta.SetStatusCondition(&repo.Status.Conditions, stalledCondition)
190199
newCondition := metav1.Condition{
191200
Type: meta.ReadyCondition,
192201
Status: metav1.ConditionFalse,
@@ -195,6 +204,7 @@ func TestCreateSourceGit(t *testing.T) {
195204
ObservedGeneration: repo.GetGeneration(),
196205
}
197206
apimeta.SetStatusCondition(&repo.Status.Conditions, newCondition)
207+
repo.Status.ObservedGeneration = repo.GetGeneration()
198208
},
199209
}, {
200210
"NoArtifact",
@@ -210,6 +220,7 @@ func TestCreateSourceGit(t *testing.T) {
210220
ObservedGeneration: repo.GetGeneration(),
211221
}
212222
apimeta.SetStatusCondition(&repo.Status.Conditions, newCondition)
223+
repo.Status.ObservedGeneration = repo.GetGeneration()
213224
},
214225
},
215226
}

0 commit comments

Comments
 (0)