Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logic to reconcile multiple RolloutMangers #65

Merged
merged 2 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion controllers/argorollouts_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ import (
"k8s.io/client-go/discovery"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
logr "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

Expand Down Expand Up @@ -143,9 +147,15 @@ func (r *RolloutManagerReconciler) Reconcile(ctx context.Context, req ctrl.Reque
// SetupWithManager sets up the controller with the Manager.
func (r *RolloutManagerReconciler) SetupWithManager(mgr ctrl.Manager) error {
bld := ctrl.NewControllerManagedBy(mgr)
// Watch for changes to primary resource RolloutManager.

bld.For(&rolloutsmanagerv1alpha1.RolloutManager{})

// If the .spec of any RolloutManager changes (or a RM is created/deleted), inform the other RolloutManagers on the cluster
bld.Watches(
&rolloutsmanagerv1alpha1.RolloutManager{},
handler.EnqueueRequestsFromMapFunc(r.queueOtherRolloutManagers),
builder.WithPredicates(predicate.Or(predicate.GenerationChangedPredicate{}, createdOrDeletedPredicate())))

// Watch for changes to ConfigMap sub-resources owned by RolloutManager.
bld.Owns(&corev1.ConfigMap{})

Expand Down Expand Up @@ -180,6 +190,51 @@ func (r *RolloutManagerReconciler) SetupWithManager(mgr ctrl.Manager) error {
return bld.Complete(r)
}

// createdOrDeletedPredicate returns a predicate which filters out
// only SpaceRequests whose Ready Status are set to true
func createdOrDeletedPredicate() predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(createEvent event.CreateEvent) bool {
return true
},
DeleteFunc: func(deleteEvent event.DeleteEvent) bool {
return true
},
GenericFunc: func(genericEvent event.GenericEvent) bool {
return false
},
UpdateFunc: func(e event.UpdateEvent) bool {
return false
},
}
}

func (r *RolloutManagerReconciler) queueOtherRolloutManagers(context context.Context, obj client.Object) []reconcile.Request {

// List all other RolloutMangers on the cluster
rmList := rolloutsmanagerv1alpha1.RolloutManagerList{}
if err := r.List(context, &rmList); err != nil {
return []reconcile.Request{}
}

requests := []reconcile.Request{}

for idx := range rmList.Items {
rm := rmList.Items[idx]

if rm.Name == obj.GetName() && rm.Namespace == obj.GetNamespace() {
// Don't queue the object itself, we are already handling that elsewhere
continue
}

requests = append(requests, reconcile.Request{
NamespacedName: client.ObjectKeyFromObject(&rm),
})
}

return requests
}

// doesCRDExist checks if a CRD is present in the cluster, by using the discovery client.
//
// NOTE: this function should only be called from SetupWithManager. There are more efficient methods to determine this, elsewhere.
Expand Down
16 changes: 16 additions & 0 deletions controllers/argorollouts_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,22 @@ var _ = Describe("RolloutManagerReconciler tests", func() {
rm.Status.Conditions[0].Reason == rolloutsmanagerv1alpha1.RolloutManagerReasonMultipleClusterScopedRolloutManager &&
rm.Status.Conditions[0].Message == UnsupportedRolloutManagerConfiguration &&
rm.Status.Conditions[0].Status == metav1.ConditionFalse).To(BeTrue())

By("1st RM: Delete 1st RolloutManager")
Expect(r.Client.Delete(ctx, rm)).To(Succeed())
Expect(r.Client.Get(ctx, types.NamespacedName{Name: rm.Name, Namespace: rm.Namespace}, rm)).ToNot(Succeed())

By("2nd RM: Reconcile 2nd RolloutManager's once again and check whether it has removed failed condition.")
res2, err = r.Reconcile(ctx, req2)
Expect(err).ToNot(HaveOccurred())
Expect(res2.Requeue).Should(BeFalse(), "reconcile should not requeue request")

By("2nd RM: Check if RolloutManager's Status.Conditions are set.")
Expect(r.Client.Get(ctx, types.NamespacedName{Name: rm2.Name, Namespace: rm2.Namespace}, rm2)).To(Succeed())
Expect(rm2.Status.Conditions[0].Type == rolloutsmanagerv1alpha1.RolloutManagerConditionType &&
rm2.Status.Conditions[0].Reason == rolloutsmanagerv1alpha1.RolloutManagerReasonSuccess &&
rm2.Status.Conditions[0].Message == "" &&
rm2.Status.Conditions[0].Status == metav1.ConditionTrue).To(BeTrue())
})
})

Expand Down
43 changes: 43 additions & 0 deletions tests/e2e/cluster-scoped/cluster_scoped_rollouts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,5 +266,48 @@ var _ = Describe("Cluster-scoped RolloutManager tests", func() {
By("1st RM: Create and validate Rollout in 3rd namespace.")
utils.ValidateArgoRolloutsResources(ctx, k8sClient, nsName2, 31002, 32002)
})

It("After creating 2 cluster-scoped RolloutManager in a namespace, delete 1st RolloutManager and verify it removes the Failed status of 2nd RolloutManager", func() {
By("1st RM: Create cluster-scoped RolloutManager in a namespace.")
rolloutsManagerCl, err := utils.CreateRolloutManager(ctx, k8sClient, "test-rollouts-manager-1", fixture.TestE2ENamespace, false)
Expect(err).ToNot(HaveOccurred())

By("1st RM: Verify that RolloutManager is successfully created.")
Eventually(rolloutsManagerCl, "1m", "1s").Should(rmFixture.HavePhase(rmv1alpha1.PhaseAvailable))

By("1st RM: Verify that Status.Condition is having success condition.")
Eventually(rolloutsManagerCl, "1m", "1s").Should(rmFixture.HaveSuccessCondition())

By("2nd RM: Create cluster-scoped RolloutManager in a namespace.")
rolloutsManagerCl2, err := utils.CreateRolloutManager(ctx, k8sClient, "test-rollouts-manager-2", fixture.TestE2ENamespace, false)
Expect(err).ToNot(HaveOccurred())

By("2nd RM: Verify that RolloutManager is not working.")
Eventually(rolloutsManagerCl2, "1m", "1s").Should(rmFixture.HavePhase(rmv1alpha1.PhaseFailure))

By("1st RM: Verify that Status.Condition is now having error message.")
Eventually(rolloutsManagerCl, "3m", "1s").Should(rmFixture.HaveCondition(
metav1.Condition{
Type: rmv1alpha1.RolloutManagerConditionType,
Status: metav1.ConditionFalse,
Reason: rmv1alpha1.RolloutManagerReasonMultipleClusterScopedRolloutManager,
Message: controllers.UnsupportedRolloutManagerConfiguration,
}))

By("2nd RM: Verify that Status.Condition is now having error message.")
Eventually(rolloutsManagerCl2, "3m", "1s").Should(rmFixture.HaveCondition(
metav1.Condition{
Type: rmv1alpha1.RolloutManagerConditionType,
Status: metav1.ConditionFalse,
Reason: rmv1alpha1.RolloutManagerReasonMultipleClusterScopedRolloutManager,
Message: controllers.UnsupportedRolloutManagerConfiguration,
}))

By("1st RM: Delete first RolloutManager.")
Expect(k8sClient.Delete(ctx, &rolloutsManagerCl)).To(Succeed())

By("2nd RM: Verify that Status.Condition is having success condition.")
Eventually(rolloutsManagerCl2, "1m", "1s").Should(rmFixture.HaveSuccessCondition())
})
})
})
Loading