-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #867 from weaveworks/825-observed-generation
Defaults ObservedGeneration to -1 and sets LastHandledReconcileAt
- Loading branch information
Showing
11 changed files
with
220 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package controllers | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
. "github.com/onsi/gomega" | ||
|
||
infrav1 "github.com/weaveworks/tf-controller/api/v1alpha2" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/util/rand" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
func Test_000016_default_observed_generation(t *testing.T) { | ||
Spec("This spec describes default value of a Terraform resource") | ||
It("should set the observedGeneration to -1 when the resource is created") | ||
|
||
var ( | ||
terraformName = "tf-" + rand.String(6) | ||
) | ||
g := NewWithT(t) | ||
ctx := context.Background() | ||
|
||
Given("a Terraform resource") | ||
By("creating a new TF resource.") | ||
helloWorldTF := infrav1.Terraform{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: terraformName, | ||
Namespace: "default", | ||
}, | ||
Spec: infrav1.TerraformSpec{ | ||
Path: "./terraform-hello-world-example", | ||
SourceRef: infrav1.CrossNamespaceSourceReference{ | ||
Kind: "GitRepository", | ||
Name: "foo", | ||
Namespace: "flux-system", | ||
}, | ||
Interval: metav1.Duration{Duration: time.Second * 10}, | ||
}, | ||
} | ||
It("should be created and attached successfully.") | ||
g.Expect(k8sClient.Create(ctx, &helloWorldTF)).Should(Succeed()) | ||
t.Cleanup(func() { g.Expect(k8sClient.Delete(ctx, &helloWorldTF)).Should(Succeed()) }) | ||
|
||
It("should have observedGeneration set to -1") | ||
helloWorldTFKey := client.ObjectKeyFromObject(&helloWorldTF) | ||
var createdHelloWorldTF infrav1.Terraform | ||
g.Expect(k8sClient.Get(ctx, helloWorldTFKey, &createdHelloWorldTF)).To(Succeed()) | ||
|
||
g.Expect(createdHelloWorldTF.Status.ObservedGeneration).Should(Equal(int64(-1))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package controllers | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
"github.com/fluxcd/pkg/apis/meta" | ||
sourcev1 "github.com/fluxcd/source-controller/api/v1" | ||
. "github.com/onsi/gomega" | ||
|
||
infrav1 "github.com/weaveworks/tf-controller/api/v1alpha2" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/util/rand" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
func Test_000016_finalize_status(t *testing.T) { | ||
Spec("This spec describes the behaviour of the Terraform controller when finalizing the status of a Terraform resource") | ||
It("should set the observedGeneration and LastHandledReconcileAt after reconcile") | ||
|
||
var ( | ||
sourceName = "test-finalize-status" | ||
terraformName = "tf-" + rand.String(6) | ||
) | ||
g := NewWithT(t) | ||
ctx := context.Background() | ||
|
||
Given("a GitRepository") | ||
By("defining a new GitRepository resource.") | ||
updatedTime := time.Now() | ||
testRepo := sourcev1.GitRepository{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: sourceName, | ||
Namespace: "flux-system", | ||
}, | ||
Spec: sourcev1.GitRepositorySpec{ | ||
URL: "https://github.com/openshift-fluxv2-poc/podinfo", | ||
Reference: &sourcev1.GitRepositoryRef{ | ||
Branch: "main", | ||
}, | ||
Interval: metav1.Duration{Duration: time.Second * 30}, | ||
}, | ||
} | ||
|
||
By("creating the GitRepository resource in the cluster.") | ||
It("should be created successfully.") | ||
g.Expect(k8sClient.Create(ctx, &testRepo)).Should(Succeed()) | ||
defer func() { g.Expect(k8sClient.Delete(ctx, &testRepo)).Should(Succeed()) }() | ||
|
||
Given("the GitRepository's reconciled status") | ||
By("setting the GitRepository's status, with the downloadable BLOB's URL, and the correct checksum.") | ||
testRepo.Status = sourcev1.GitRepositoryStatus{ | ||
ObservedGeneration: int64(1), | ||
Conditions: []metav1.Condition{ | ||
{ | ||
Type: "Ready", | ||
Status: metav1.ConditionTrue, | ||
LastTransitionTime: metav1.Time{Time: updatedTime}, | ||
Reason: "GitOperationSucceed", | ||
Message: "Fetched revision: main/b8e362c206e3d0cbb7ed22ced771a0056455a2fb", | ||
}, | ||
}, | ||
Artifact: &sourcev1.Artifact{ | ||
Path: "gitrepository/flux-system/test-tf-controller/b8e362c206e3d0cbb7ed22ced771a0056455a2fb.tar.gz", | ||
URL: server.URL() + "/file.tar.gz", | ||
Revision: "main/b8e362c206e3d0cbb7ed22ced771a0056455a2fb", | ||
Digest: "sha256:80ddfd18eb96f7d31cadc1a8a5171c6e2d95df3f6c23b0ed9cd8dddf6dba1406", | ||
LastUpdateTime: metav1.Time{Time: updatedTime}, | ||
}, | ||
} | ||
|
||
It("should be updated successfully.") | ||
g.Expect(k8sClient.Status().Update(ctx, &testRepo)).Should(Succeed()) | ||
|
||
Given("a Terraform resource") | ||
By("creating a new TF resource.") | ||
helloWorldTF := infrav1.Terraform{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: terraformName, | ||
Namespace: "default", | ||
Annotations: map[string]string{ | ||
meta.ReconcileRequestAnnotation: updatedTime.String(), | ||
}, | ||
}, | ||
Spec: infrav1.TerraformSpec{ | ||
Path: "./terraform-hello-world-example", | ||
SourceRef: infrav1.CrossNamespaceSourceReference{ | ||
Kind: "GitRepository", | ||
Name: sourceName, | ||
Namespace: "flux-system", | ||
}, | ||
Interval: metav1.Duration{Duration: time.Second * 10}, | ||
}, | ||
} | ||
It("should be created and attached successfully.") | ||
g.Expect(k8sClient.Create(ctx, &helloWorldTF)).Should(Succeed()) | ||
t.Cleanup(func() { g.Expect(k8sClient.Delete(ctx, &helloWorldTF)).Should(Succeed()) }) | ||
|
||
It("should have observedGeneration and LastHandledReconcileAt set") | ||
helloWorldTFKey := client.ObjectKeyFromObject(&helloWorldTF) | ||
g.Eventually(func() int64 { | ||
var createdHelloWorldTF infrav1.Terraform | ||
g.Expect(k8sClient.Get(ctx, helloWorldTFKey, &createdHelloWorldTF)).To(Succeed()) | ||
return createdHelloWorldTF.Status.ObservedGeneration | ||
}, timeout, interval).Should(Equal(int64(1))) | ||
|
||
g.Eventually(func() string { | ||
var createdHelloWorldTF infrav1.Terraform | ||
g.Expect(k8sClient.Get(ctx, helloWorldTFKey, &createdHelloWorldTF)).To(Succeed()) | ||
return createdHelloWorldTF.Status.LastHandledReconcileAt | ||
}, timeout, interval).Should(Equal(updatedTime.String())) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
//go:build flaky | ||
|
||
package controllers | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
//go:build flaky | ||
|
||
package controllers | ||
|
||
import ( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,9 +30,11 @@ import ( | |
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1" | ||
"github.com/fluxcd/pkg/apis/meta" | ||
"github.com/fluxcd/pkg/runtime/acl" | ||
"github.com/fluxcd/pkg/runtime/conditions" | ||
runtimeCtrl "github.com/fluxcd/pkg/runtime/controller" | ||
"github.com/fluxcd/pkg/runtime/dependency" | ||
"github.com/fluxcd/pkg/runtime/logger" | ||
"github.com/fluxcd/pkg/runtime/patch" | ||
"github.com/fluxcd/pkg/runtime/predicates" | ||
sourcev1 "github.com/fluxcd/source-controller/api/v1" | ||
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2" | ||
|
@@ -46,6 +48,7 @@ import ( | |
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/types" | ||
kerrors "k8s.io/apimachinery/pkg/util/errors" | ||
"k8s.io/apimachinery/pkg/util/wait" | ||
kuberecorder "k8s.io/client-go/tools/record" | ||
"sigs.k8s.io/cli-utils/pkg/kstatus/polling" | ||
|
@@ -97,7 +100,7 @@ type TerraformReconciler struct { | |
// | ||
// For more details, check Reconcile and its Result here: | ||
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile | ||
func (r *TerraformReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { | ||
func (r *TerraformReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) { | ||
reconcileStart := time.Now() | ||
reconciliationLoopID := uuid.New().String() | ||
log := ctrl.LoggerFrom(ctx, "reconciliation-loop-id", reconciliationLoopID, "start-time", reconcileStart) | ||
|
@@ -126,7 +129,14 @@ func (r *TerraformReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( | |
} | ||
log.Info(fmt.Sprintf(">> Started Generation: %d", terraform.GetGeneration())) | ||
|
||
// Initialize the runtime patcher with the current version of the object. | ||
patcher := patch.NewSerialPatcher(&terraform, r.Client) | ||
|
||
defer func() { | ||
if err := r.finalizeStatus(ctx, &terraform, patcher); err != nil { | ||
retErr = kerrors.NewAggregate([]error{retErr, err}) | ||
} | ||
|
||
// Record Prometheus metrics. | ||
r.Metrics.RecordReadiness(ctx, &terraform) | ||
r.Metrics.RecordSuspend(ctx, &terraform, terraform.Spec.Suspend) | ||
|
@@ -807,3 +817,23 @@ func (r *TerraformReconciler) event(ctx context.Context, terraform infrav1.Terra | |
traceLog.Info("Add new annotated event") | ||
r.EventRecorder.AnnotatedEventf(&terraform, metadata, eventType, reason, msg) | ||
} | ||
|
||
func (r *TerraformReconciler) finalizeStatus(ctx context.Context, obj *infrav1.Terraform, patcher *patch.SerialPatcher) error { | ||
if v, ok := meta.ReconcileAnnotationValue(obj.GetAnnotations()); ok { | ||
obj.Status.LastHandledReconcileAt = v | ||
} | ||
|
||
if conditions.IsTrue(obj, meta.ReadyCondition) { | ||
obj.Status.ObservedGeneration = obj.Generation | ||
} | ||
|
||
if err := patcher.Patch(ctx, obj); err != nil { | ||
if !obj.GetDeletionTimestamp().IsZero() { | ||
err = kerrors.FilterOut(err, func(e error) bool { return apierrors.IsNotFound(e) }) | ||
} | ||
|
||
return err | ||
} | ||
|
||
return nil | ||
} |