Skip to content

Commit 9eb3e70

Browse files
committed
Add vhost limits.
1 parent baa57a2 commit 9eb3e70

File tree

12 files changed

+557
-2
lines changed

12 files changed

+557
-2
lines changed

api/v1beta1/vhost_types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ type VhostSpec struct {
3434
// +kubebuilder:validation:Enum=delete;retain
3535
// +kubebuilder:default:=delete
3636
DeletionPolicy string `json:"deletionPolicy,omitempty"`
37+
// Limits defines limits to be applied to the vhost.
38+
// Supported limits include max-connections and max-queues.
39+
// See https://www.rabbitmq.com/docs/vhosts#limits
40+
VhostLimits *VhostLimits `json:"limits,omitempty"`
3741
}
3842

3943
// VhostStatus defines the observed state of Vhost
@@ -67,6 +71,12 @@ type VhostList struct {
6771
Items []Vhost `json:"items"`
6872
}
6973

74+
// VhostLimits defines limits to be applied to the vhost.
75+
type VhostLimits struct {
76+
Connections *int32 `json:"connections,omitempty"`
77+
Queues *int32 `json:"queues,omitempty"`
78+
}
79+
7080
func (v *Vhost) GroupResource() schema.GroupResource {
7181
return schema.GroupResource{
7282
Group: v.GroupVersionKind().Group,

api/v1beta1/vhost_types_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,109 @@ var _ = Describe("Vhost", func() {
101101
}))
102102
})
103103

104+
Context("Vhost Limits", func() {
105+
var connections, queues int32
106+
107+
When("vhost limits are configured", func() {
108+
It("creates a vhost with limits", func() {
109+
connections = 1000
110+
queues = 500
111+
vhost := Vhost{
112+
ObjectMeta: metav1.ObjectMeta{
113+
Name: "vhost-with-limits",
114+
Namespace: namespace,
115+
},
116+
Spec: VhostSpec{
117+
Name: "vhost-with-limits",
118+
VhostLimits: &VhostLimits{
119+
Connections: &connections,
120+
Queues: &queues,
121+
},
122+
RabbitmqClusterReference: RabbitmqClusterReference{
123+
Name: "random-cluster",
124+
},
125+
},
126+
}
127+
Expect(k8sClient.Create(ctx, &vhost)).To(Succeed())
128+
fetched := &Vhost{}
129+
Expect(k8sClient.Get(ctx, types.NamespacedName{
130+
Name: vhost.Name,
131+
Namespace: vhost.Namespace,
132+
}, fetched)).To(Succeed())
133+
134+
Expect(*fetched.Spec.VhostLimits.Connections).To(Equal(connections))
135+
Expect(*fetched.Spec.VhostLimits.Queues).To(Equal(queues))
136+
Expect(fetched.Spec.Name).To(Equal("vhost-with-limits"))
137+
Expect(fetched.Spec.RabbitmqClusterReference).To(Equal(RabbitmqClusterReference{
138+
Name: "random-cluster",
139+
}))
140+
})
141+
})
142+
143+
When("No vhost limits are provided", func() {
144+
It("Does not set VhostLimits", func() {
145+
vhost := Vhost{
146+
ObjectMeta: metav1.ObjectMeta{
147+
Name: "vhost-with-no-provided-limits",
148+
Namespace: namespace,
149+
},
150+
Spec: VhostSpec{
151+
Name: "vhost-with-no-provided-limits",
152+
RabbitmqClusterReference: RabbitmqClusterReference{
153+
Name: "random-cluster",
154+
},
155+
},
156+
}
157+
Expect(k8sClient.Create(ctx, &vhost)).To(Succeed())
158+
fetched := &Vhost{}
159+
Expect(k8sClient.Get(ctx, types.NamespacedName{
160+
Name: vhost.Name,
161+
Namespace: vhost.Namespace,
162+
}, fetched)).To(Succeed())
163+
164+
Expect(fetched.Spec.VhostLimits).To(BeNil())
165+
Expect(fetched.Spec.Name).To(Equal("vhost-with-no-provided-limits"))
166+
Expect(fetched.Spec.RabbitmqClusterReference).To(Equal(RabbitmqClusterReference{
167+
Name: "random-cluster",
168+
}))
169+
})
170+
})
171+
172+
When("Only some vhost limits are provided", func() {
173+
It("Configures those limits and lifts other limits", func() {
174+
queues = 800
175+
vhost := Vhost{
176+
ObjectMeta: metav1.ObjectMeta{
177+
Name: "vhost-some-limits",
178+
Namespace: namespace,
179+
},
180+
Spec: VhostSpec{
181+
Name: "vhost-some-limits",
182+
VhostLimits: &VhostLimits{
183+
Queues: &queues,
184+
},
185+
RabbitmqClusterReference: RabbitmqClusterReference{
186+
Name: "random-cluster",
187+
},
188+
},
189+
}
190+
Expect(k8sClient.Create(ctx, &vhost)).To(Succeed())
191+
fetched := &Vhost{}
192+
Expect(k8sClient.Get(ctx, types.NamespacedName{
193+
Name: vhost.Name,
194+
Namespace: vhost.Namespace,
195+
}, fetched)).To(Succeed())
196+
197+
Expect(fetched.Spec.VhostLimits.Connections).To(BeNil())
198+
Expect(*fetched.Spec.VhostLimits.Queues).To(Equal(queues))
199+
Expect(fetched.Spec.Name).To(Equal("vhost-some-limits"))
200+
Expect(fetched.Spec.RabbitmqClusterReference).To(Equal(RabbitmqClusterReference{
201+
Name: "random-cluster",
202+
}))
203+
})
204+
})
205+
})
206+
104207
Context("Default queue types", func() {
105208
var qTypeVhost = &Vhost{
106209
ObjectMeta: metav1.ObjectMeta{

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/rabbitmq.com_vhosts.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,19 @@ spec:
5959
- delete
6060
- retain
6161
type: string
62+
limits:
63+
description: |-
64+
Limits defines limits to be applied to the vhost.
65+
Supported limits include max-connections and max-queues.
66+
See https://www.rabbitmq.com/docs/vhosts#limits
67+
properties:
68+
connections:
69+
format: int32
70+
type: integer
71+
queues:
72+
format: int32
73+
type: integer
74+
type: object
6275
name:
6376
description: Name of the vhost; see https://www.rabbitmq.com/vhosts.html.
6477
type: string

controllers/vhost_controller.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,22 @@ type VhostReconciler struct {
2020
client.Client
2121
}
2222

23-
func (r *VhostReconciler) DeclareFunc(_ context.Context, client rabbitmqclient.Client, obj topology.TopologyResource) error {
23+
func (r *VhostReconciler) DeclareFunc(ctx context.Context, client rabbitmqclient.Client, obj topology.TopologyResource) error {
24+
logger := ctrl.LoggerFrom(ctx)
2425
vhost := obj.(*topology.Vhost)
25-
return validateResponse(client.PutVhost(vhost.Spec.Name, *internal.GenerateVhostSettings(vhost)))
26+
settings := internal.GenerateVhostSettings(vhost)
27+
logger.Info("generated vhost settings", "vhost", vhost.Spec.Name, "settings", settings)
28+
err := validateResponse(client.PutVhost(vhost.Spec.Name, *settings))
29+
if err != nil {
30+
return err
31+
}
32+
33+
vhostLimits := internal.GenerateVhostLimits(vhost.Spec.VhostLimits)
34+
logger.Info("generated vhost limits", "vhost", vhost.Spec.Name, "limits", vhostLimits)
35+
if len(vhostLimits) > 0 {
36+
err = validateResponse(client.PutVhostLimits(vhost.Spec.Name, vhostLimits))
37+
}
38+
return err
2639
}
2740

2841
// DeleteFunc deletes vhost from server

controllers/vhost_controller_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var _ = Describe("vhost-controller", func() {
3232
managerCtx context.Context
3333
managerCancel context.CancelFunc
3434
k8sClient runtimeClient.Client
35+
vhostLimits *topology.VhostLimits
3536
)
3637

3738
BeforeEach(func() {
@@ -90,6 +91,7 @@ var _ = Describe("vhost-controller", func() {
9091
RabbitmqClusterReference: topology.RabbitmqClusterReference{
9192
Name: "example-rabbit",
9293
},
94+
VhostLimits: vhostLimits,
9395
},
9496
}
9597
})
@@ -248,4 +250,69 @@ var _ = Describe("vhost-controller", func() {
248250
Expect(fakeRabbitMQClient.DeleteVhostCallCount()).To(Equal(0))
249251
})
250252
})
253+
254+
Context("vhost limits", func() {
255+
When("vhost limits are provided", func() {
256+
var connections, queues int32
257+
258+
BeforeEach(func() {
259+
connections = 708
260+
queues = 509
261+
vhostName = "vhost-with-limits"
262+
vhostLimits = &topology.VhostLimits{
263+
Connections: &connections,
264+
Queues: &queues,
265+
}
266+
fakeRabbitMQClient.PutVhostReturns(&http.Response{
267+
Status: "201 Created",
268+
StatusCode: http.StatusCreated,
269+
}, nil)
270+
fakeRabbitMQClient.PutVhostLimitsReturns(&http.Response{
271+
Status: "200 OK",
272+
StatusCode: http.StatusOK,
273+
}, nil)
274+
})
275+
276+
It("puts the vhost limits", func() {
277+
Expect(k8sClient.Create(ctx, &vhost)).To(Succeed())
278+
Eventually(func() []topology.Condition {
279+
_ = k8sClient.Get(
280+
ctx,
281+
types.NamespacedName{Name: vhost.Name, Namespace: vhost.Namespace},
282+
&vhost,
283+
)
284+
285+
return vhost.Status.Conditions
286+
}).
287+
Within(statusEventsUpdateTimeout).
288+
WithPolling(time.Second).
289+
Should(ContainElement(MatchFields(IgnoreExtras, Fields{
290+
"Type": Equal(topology.ConditionType("Ready")),
291+
"Reason": Equal("SuccessfulCreateOrUpdate"),
292+
"Status": Equal(corev1.ConditionTrue),
293+
})))
294+
295+
Expect(fakeRabbitMQClient.PutVhostLimitsCallCount()).To(BeNumerically(">", 0))
296+
_, vhostLimitsValues := fakeRabbitMQClient.PutVhostLimitsArgsForCall(0)
297+
Expect(len(vhostLimitsValues)).To(Equal(2))
298+
connectionLimit, ok := vhostLimitsValues["max-connections"]
299+
Expect(ok).To(BeTrue())
300+
Expect(connectionLimit).To(Equal(int(connections)))
301+
queueLimit, ok := vhostLimitsValues["max-queues"]
302+
Expect(ok).To(BeTrue())
303+
Expect(queueLimit).To(Equal(int(queues)))
304+
})
305+
})
306+
307+
When("vhost limits are not provided", func() {
308+
BeforeEach(func() {
309+
vhostName = "vhost-without-limits"
310+
})
311+
312+
It("does not set vhost limits", func() {
313+
Expect(k8sClient.Create(ctx, &vhost)).To(Succeed())
314+
Expect(fakeRabbitMQClient.PutVhostLimitsCallCount()).To(Equal(0))
315+
})
316+
})
317+
})
251318
})

docs/api/rabbitmq.com.ref.asciidoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,6 +1516,24 @@ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-
15161516
|===
15171517

15181518

1519+
[id="{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostlimits"]
1520+
==== VhostLimits
1521+
1522+
VhostLimits defines limits to be applied to the vhost.
1523+
1524+
.Appears In:
1525+
****
1526+
- xref:{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostspec[$$VhostSpec$$]
1527+
****
1528+
1529+
[cols="25a,75a", options="header"]
1530+
|===
1531+
| Field | Description
1532+
| *`connections`* __integer__ |
1533+
| *`queues`* __integer__ |
1534+
|===
1535+
1536+
15191537
[id="{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostlist"]
15201538
==== VhostList
15211539

@@ -1585,6 +1603,9 @@ Supported in RabbitMQ 3.11.12 or above.
15851603
Required property.
15861604
| *`deletionPolicy`* __string__ | DeletionPolicy defines the behavior of vhost in the RabbitMQ cluster when the corresponding custom resource is deleted.
15871605
Can be set to 'delete' or 'retain'. Default is 'delete'.
1606+
| *`limits`* __xref:{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostlimits[$$VhostLimits$$]__ | Limits defines limits to be applied to the vhost.
1607+
Supported limits include max-connections and max-queues.
1608+
See https://www.rabbitmq.com/docs/vhosts#limits
15881609
|===
15891610

15901611

internal/vhost_settings.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,16 @@ func GenerateVhostSettings(v *topology.Vhost) *rabbithole.VhostSettings {
2121
DefaultQueueType: v.Spec.DefaultQueueType,
2222
}
2323
}
24+
25+
func GenerateVhostLimits(limits *topology.VhostLimits) rabbithole.VhostLimitsValues {
26+
vhostLimitsValues := rabbithole.VhostLimitsValues{}
27+
if limits != nil {
28+
if limits.Connections != nil {
29+
vhostLimitsValues["max-connections"] = int(*limits.Connections)
30+
}
31+
if limits.Queues != nil {
32+
vhostLimitsValues["max-queues"] = int(*limits.Queues)
33+
}
34+
}
35+
return vhostLimitsValues
36+
}

0 commit comments

Comments
 (0)