Skip to content

Commit 9e16d9f

Browse files
committed
Add vhost limits.
1 parent 6e86002 commit 9e16d9f

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

docs/api/rabbitmq.com.ref.asciidoc

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

15521552

1553+
[id="{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostlimits"]
1554+
==== VhostLimits
1555+
1556+
VhostLimits defines limits to be applied to the vhost.
1557+
1558+
.Appears In:
1559+
****
1560+
- xref:{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostspec[$$VhostSpec$$]
1561+
****
1562+
1563+
[cols="25a,75a", options="header"]
1564+
|===
1565+
| Field | Description
1566+
| *`connections`* __integer__ |
1567+
| *`queues`* __integer__ |
1568+
|===
1569+
1570+
15531571
[id="{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostlist"]
15541572
==== VhostList
15551573

@@ -1619,6 +1637,9 @@ Supported in RabbitMQ 3.11.12 or above.
16191637
Required property.
16201638
| *`deletionPolicy`* __string__ | DeletionPolicy defines the behavior of vhost in the RabbitMQ cluster when the corresponding custom resource is deleted.
16211639
Can be set to 'delete' or 'retain'. Default is 'delete'.
1640+
| *`limits`* __xref:{anchor_prefix}-github-com-rabbitmq-messaging-topology-operator-api-v1beta1-vhostlimits[$$VhostLimits$$]__ | Limits defines limits to be applied to the vhost.
1641+
Supported limits include max-connections and max-queues.
1642+
See https://www.rabbitmq.com/docs/vhosts#limits
16221643
|===
16231644

16241645

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)