Skip to content

Commit

Permalink
feat: available condition
Browse files Browse the repository at this point in the history
  • Loading branch information
KevFan committed Mar 6, 2024
1 parent e0517a2 commit 7a9dab7
Show file tree
Hide file tree
Showing 15 changed files with 195 additions and 36 deletions.
12 changes: 11 additions & 1 deletion api/v1alpha1/limitador_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
Expand All @@ -34,7 +35,8 @@ const (
DefaultServiceGRPCPort int32 = 8081

// Status conditions
StatusConditionReady string = "Ready"
StatusConditionReady string = "Ready"
StatusConditionAvailable string = "Available"
)

var (
Expand Down Expand Up @@ -147,6 +149,14 @@ func (l *Limitador) GetResourceRequirements() *corev1.ResourceRequirements {
return l.Spec.ResourceRequirements
}

func (l *Limitador) IsReady() bool {
return meta.IsStatusConditionTrue(l.Status.Conditions, StatusConditionReady)
}

func (l *Limitador) IsAvailable() bool {
return meta.IsStatusConditionTrue(l.Status.Conditions, StatusConditionAvailable)
}

//+kubebuilder:object:root=true

// LimitadorList contains a list of Limitador
Expand Down
4 changes: 3 additions & 1 deletion controllers/limitador_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,21 @@ import (
v1 "k8s.io/api/core/v1"
policyv1 "k8s.io/api/policy/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"

limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1"
"github.com/kuadrant/limitador-operator/pkg/limitador"
"github.com/kuadrant/limitador-operator/pkg/reconcilers"
upgrades "github.com/kuadrant/limitador-operator/pkg/upgrades"
"github.com/kuadrant/limitador-operator/pkg/upgrades"
)

// LimitadorReconciler reconciles a Limitador object
type LimitadorReconciler struct {
*reconcilers.BaseReconciler
RestConfig *rest.Config
}

//+kubebuilder:rbac:groups=limitador.kuadrant.io,resources=limitadors,verbs=get;list;watch;create;update;patch;delete
Expand Down
4 changes: 2 additions & 2 deletions controllers/limitador_controller_affinity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var _ = Describe("Limitador controller manages affinity", func() {
limitadorObj = basicLimitador(testNamespace)
limitadorObj.Spec.Affinity = affinity
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create a new deployment with the custom affinity", func() {
Expand Down Expand Up @@ -96,7 +96,7 @@ var _ = Describe("Limitador controller manages affinity", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify the deployment with the affinity custom settings", func() {
Expand Down
10 changes: 8 additions & 2 deletions controllers/limitador_controller_limits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var _ = Describe("Limitador controller manages limits", func() {
limitadorObj = basicLimitador(testNamespace)
limitadorObj.Spec.Limits = limits
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create configmap with the custom limits", func() {
Expand Down Expand Up @@ -96,7 +96,7 @@ var _ = Describe("Limitador controller manages limits", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify configmap with the new limits", func() {
Expand Down Expand Up @@ -152,6 +152,12 @@ var _ = Describe("Limitador controller manages limits", func() {

return reflect.DeepEqual(cmLimits, limits)
}, timeout, interval).Should(BeTrue())

// Updating limits should transition available condition to first false due to config map loaded in pod is out of sync
Eventually(testLimitadorIsAvailable(limitadorObj), timeout, interval).Should(BeFalse())

// Status should be ready and available once config map limits are in sync
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), 3*time.Minute, interval).Should(BeTrue())
})
})
})
4 changes: 2 additions & 2 deletions controllers/limitador_controller_pdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var _ = Describe("Limitador controller manages PodDisruptionBudget", func() {
limitadorObj = basicLimitador(testNamespace)
limitadorObj.Spec.PodDisruptionBudget = pdbType
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create PodDisruptionBudget", func() {
Expand Down Expand Up @@ -64,7 +64,7 @@ var _ = Describe("Limitador controller manages PodDisruptionBudget", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify pdb object with the new limits", func() {
Expand Down
4 changes: 2 additions & 2 deletions controllers/limitador_controller_ports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ var _ = Describe("Limitador controller manages ports", func() {
HTTP: httpPort, GRPC: grpcPort,
}
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should configure k8s resources with the custom ports", func() {
Expand Down Expand Up @@ -140,7 +140,7 @@ var _ = Describe("Limitador controller manages ports", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify the k8s resources with the custom ports", func() {
Expand Down
4 changes: 2 additions & 2 deletions controllers/limitador_controller_replicas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var _ = Describe("Limitador controller manages replicas", func() {
limitadorObj = basicLimitador(testNamespace)
limitadorObj.Spec.Replicas = &[]int{int(replicas)}[0]
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create a new deployment with the custom replicas", func() {
Expand All @@ -60,7 +60,7 @@ var _ = Describe("Limitador controller manages replicas", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify deployment replicas", func() {
Expand Down
4 changes: 2 additions & 2 deletions controllers/limitador_controller_resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var _ = Describe("Limitador controller manages resource requirements", func() {
limitadorObj = basicLimitador(testNamespace)
limitadorObj.Spec.ResourceRequirements = &resourceRequirements
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create a new deployment with the custom resource requirements", func() {
Expand Down Expand Up @@ -68,7 +68,7 @@ var _ = Describe("Limitador controller manages resource requirements", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify deployment resource requirements", func() {
Expand Down
35 changes: 21 additions & 14 deletions controllers/limitador_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
v1 "k8s.io/api/core/v1"
policyv1 "k8s.io/api/policy/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -51,7 +50,7 @@ var _ = Describe("Limitador controller", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create a Limitador service with default ports", func() {
Expand Down Expand Up @@ -190,7 +189,7 @@ var _ = Describe("Limitador controller", func() {
limitadorObj.Spec.RateLimitHeaders = &[]limitadorv1alpha1.RateLimitHeadersType{"DRAFT_VERSION_03"}[0]

Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create a new deployment with rate limit headers command line arg", func() {
Expand Down Expand Up @@ -230,7 +229,7 @@ var _ = Describe("Limitador controller", func() {
limitadorObj = basicLimitador(testNamespace)

Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify the limitador deployment command line args", func() {
Expand Down Expand Up @@ -291,7 +290,7 @@ var _ = Describe("Limitador controller", func() {
limitadorObj = basicLimitador(testNamespace)

Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify the limitador deployment command line args", func() {
Expand Down Expand Up @@ -353,7 +352,7 @@ var _ = Describe("Limitador controller", func() {
limitadorObj.Spec.Verbosity = &[]limitadorv1alpha1.VerbosityLevel{3}[0]

Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should create a new deployment with verbosity level command line arg", func() {
Expand Down Expand Up @@ -400,7 +399,7 @@ var _ = Describe("Limitador controller", func() {
limitadorObj = basicLimitador(testNamespace)

Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify the limitador deployment command line args", func() {
Expand Down Expand Up @@ -477,7 +476,7 @@ var _ = Describe("Limitador controller", func() {
BeforeEach(func() {
limitadorObj = basicLimitador(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("User tries adding side-cars to deployment CR", func() {
Expand Down Expand Up @@ -566,7 +565,7 @@ var _ = Describe("Limitador controller", func() {
It("command line is correct", func() {
limitadorObj := limitadorWithRedisStorage(client.ObjectKeyFromObject(redisSecret), testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())

deploymentObj := appsv1.Deployment{}
Eventually(func() bool {
Expand Down Expand Up @@ -635,7 +634,7 @@ var _ = Describe("Limitador controller", func() {
It("command line is correct", func() {
limitadorObj := limitadorWithRedisCachedStorage(client.ObjectKeyFromObject(redisSecret), testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())

deploymentObj := appsv1.Deployment{}
Eventually(func() bool {
Expand Down Expand Up @@ -674,7 +673,7 @@ var _ = Describe("Limitador controller", func() {
It("deployment is correct", func() {
limitadorObj := limitadorWithDiskStorage(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())

deploymentObj := appsv1.Deployment{}
Eventually(func() bool {
Expand Down Expand Up @@ -731,7 +730,7 @@ var _ = Describe("Limitador controller", func() {
It("pvc is correct", func() {
limitadorObj := limitadorWithDiskStorage(testNamespace)
Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())

pvc := &v1.PersistentVolumeClaim{}
Eventually(func() bool {
Expand Down Expand Up @@ -891,11 +890,19 @@ func redisService(ns string) *v1.Service {
}
}

func testLimitadorIsReady(l *limitadorv1alpha1.Limitador) func() bool {
func testLimitadorIsReadyAndAvailable(l *limitadorv1alpha1.Limitador) func() bool {
return func() bool {
existing := &limitadorv1alpha1.Limitador{}
err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(l), existing)
return err == nil && meta.IsStatusConditionTrue(existing.Status.Conditions, "Ready")
return err == nil && existing.IsReady() && existing.IsAvailable()
}
}

func testLimitadorIsAvailable(l *limitadorv1alpha1.Limitador) func() bool {
return func() bool {
existing := &limitadorv1alpha1.Limitador{}
err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(l), existing)
return err == nil && existing.IsAvailable()
}
}

Expand Down
2 changes: 1 addition & 1 deletion controllers/limitador_controller_version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var _ = Describe("Limitador controller manages image version", func() {
limitadorObj = basicLimitador(testNamespace)

Expect(k8sClient.Create(context.TODO(), limitadorObj)).Should(Succeed())
Eventually(testLimitadorIsReady(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
Eventually(testLimitadorIsReadyAndAvailable(limitadorObj), time.Minute, 5*time.Second).Should(BeTrue())
})

It("Should modify the deployment with the custom image", func() {
Expand Down
Loading

0 comments on commit 7a9dab7

Please sign in to comment.