Skip to content

Commit

Permalink
Merge pull request #6 from 3scale-labs/first-version-ratelimit-reconc…
Browse files Browse the repository at this point in the history
…iler

First version of the RateLimit reconciler
  • Loading branch information
davidor authored Jan 15, 2021
2 parents 81b9835 + 2da7e7e commit bfa64bd
Show file tree
Hide file tree
Showing 14 changed files with 719 additions and 200 deletions.
7 changes: 5 additions & 2 deletions api/v1alpha1/ratelimit_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ type RateLimitSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Foo is an example field of RateLimit. Edit RateLimit_types.go to remove/update
Foo string `json:"foo,omitempty"`
Conditions []string `json:"conditions"`
MaxValue int `json:"max_value"`
Namespace string `json:"namespace"`
Seconds int `json:"seconds"`
Variables []string `json:"variables"`
}

// RateLimitStatus defines the observed state of RateLimit
Expand Down
12 changes: 11 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 19 additions & 3 deletions config/crd/bases/limitador.3scale.net_ratelimits.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,26 @@ spec:
spec:
description: RateLimitSpec defines the desired state of RateLimit
properties:
foo:
description: Foo is an example field of RateLimit. Edit RateLimit_types.go
to remove/update
conditions:
items:
type: string
type: array
max_value:
type: integer
namespace:
type: string
seconds:
type: integer
variables:
items:
type: string
type: array
required:
- conditions
- max_value
- namespace
- seconds
- variables
type: object
status:
description: RateLimitStatus defines the observed state of RateLimit
Expand Down
9 changes: 7 additions & 2 deletions config/samples/limitador_v1alpha1_ratelimit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@ kind: RateLimit
metadata:
name: ratelimit-sample
spec:
# Add fields here
foo: bar
namespace: test_namespace
max_value: 10
seconds: 60
conditions:
- "req.method == GET"
variables:
- user_id
179 changes: 179 additions & 0 deletions controllers/limitador_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package controllers

import (
"context"
limitadorv1alpha1 "github.com/3scale/limitador-operator/api/v1alpha1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"time"
)

var _ = Describe("Limitador controller", func() {
const (
LimitadorName = "limitador-test"
LimitadorNamespace = "default"
LimitadorReplicas = 2
LimitadorImage = "quay.io/3scale/limitador"
LimitadorVersion = "0.3.0"

timeout = time.Second * 10
interval = time.Millisecond * 250
)

replicas := LimitadorReplicas
version := LimitadorVersion
limitador := limitadorv1alpha1.Limitador{
TypeMeta: metav1.TypeMeta{
Kind: "Limitador",
APIVersion: "limitador.3scale.net/v1alpha1",
},
ObjectMeta: metav1.ObjectMeta{
Name: LimitadorName,
Namespace: LimitadorNamespace,
},
Spec: limitadorv1alpha1.LimitadorSpec{
Replicas: &replicas,
Version: &version,
},
}

Context("Creating a new Limitador object", func() {
BeforeEach(func() {
err := k8sClient.Delete(context.TODO(), limitador.DeepCopy())
Expect(err == nil || errors.IsNotFound(err))

Expect(k8sClient.Create(context.TODO(), limitador.DeepCopy())).Should(Succeed())
})

It("Should create a new deployment with the right number of replicas and version", func() {
createdLimitadorDeployment := appsv1.Deployment{}
Eventually(func() bool {
err := k8sClient.Get(
context.TODO(),
types.NamespacedName{
Namespace: LimitadorNamespace,
Name: LimitadorName,
},
&createdLimitadorDeployment)

return err == nil
}, timeout, interval).Should(BeTrue())

Expect(*createdLimitadorDeployment.Spec.Replicas).Should(
Equal((int32)(LimitadorReplicas)),
)
Expect(createdLimitadorDeployment.Spec.Template.Spec.Containers[0].Image).Should(
Equal(LimitadorImage + ":" + LimitadorVersion),
)
})

It("Should create a Limitador service", func() {
createdLimitadorService := v1.Service{}
Eventually(func() bool {
err := k8sClient.Get(
context.TODO(),
types.NamespacedName{
Namespace: "default", // Hardcoded for now
Name: "limitador", // Hardcoded for now
},
&createdLimitadorService)

return err == nil
}, timeout, interval).Should(BeTrue())
})
})

Context("Deleting a Limitador object", func() {
BeforeEach(func() {
err := k8sClient.Create(context.TODO(), limitador.DeepCopy())
Expect(err == nil || errors.IsAlreadyExists(err))

Expect(k8sClient.Delete(context.TODO(), limitador.DeepCopy())).Should(Succeed())
})

It("Should delete the limitador deployment", func() {
createdLimitadorDeployment := appsv1.Deployment{}
Eventually(func() bool {
err := k8sClient.Get(
context.TODO(),
types.NamespacedName{
Namespace: LimitadorNamespace,
Name: LimitadorName,
},
&createdLimitadorDeployment)

return errors.IsNotFound(err)
}, timeout, interval).Should(BeTrue())
})

It("Should delete the limitador service", func() {
createdLimitadorService := v1.Service{}
Eventually(func() bool {
err := k8sClient.Get(
context.TODO(),
types.NamespacedName{
Namespace: "default", // Hardcoded for now
Name: "limitador", // Hardcoded for now
},
&createdLimitadorService)

return errors.IsNotFound(err)
}, timeout, interval).Should(BeTrue())
})
})

Context("Updating a limitador object", func() {
BeforeEach(func() {
err := k8sClient.Delete(context.TODO(), limitador.DeepCopy())
Expect(err == nil || errors.IsNotFound(err))

Expect(k8sClient.Create(context.TODO(), limitador.DeepCopy())).Should(Succeed())
})

It("Should modify the limitador deployment", func() {
updatedLimitador := limitadorv1alpha1.Limitador{}
Eventually(func() bool {
err := k8sClient.Get(
context.TODO(),
types.NamespacedName{
Namespace: LimitadorNamespace,
Name: LimitadorName,
},
&updatedLimitador)

return err == nil
}, timeout, interval).Should(BeTrue())

replicas = LimitadorReplicas + 1
updatedLimitador.Spec.Replicas = &replicas
version = "latest"
updatedLimitador.Spec.Version = &version

Expect(k8sClient.Update(context.TODO(), &updatedLimitador)).Should(Succeed())
updatedLimitadorDeployment := appsv1.Deployment{}
Eventually(func() bool {
err := k8sClient.Get(
context.TODO(),
types.NamespacedName{
Namespace: LimitadorNamespace,
Name: LimitadorName,
},
&updatedLimitadorDeployment)

if err != nil {
return false
}

correctReplicas := *updatedLimitadorDeployment.Spec.Replicas == LimitadorReplicas+1
correctImage := updatedLimitadorDeployment.Spec.Template.Spec.Containers[0].Image == LimitadorImage+":latest"

return correctReplicas && correctImage
}, timeout, interval).Should(BeTrue())
})
})
})
Loading

0 comments on commit bfa64bd

Please sign in to comment.