Skip to content

Commit 86a012a

Browse files
authored
Add user limits. (#962)
* Add user limits. * Clean up after tests. * Delete existing limits if they are removed from a user. * Only create user limits when limits exist to create.
1 parent e3e676f commit 86a012a

30 files changed

+791
-2
lines changed

api/v1beta1/user_types.go

+16
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ type UserSpec struct {
3737
//
3838
// Note that this import only occurs at creation time, and is ignored once a password has been set on a User.
3939
ImportCredentialsSecret *corev1.LocalObjectReference `json:"importCredentialsSecret,omitempty"`
40+
// Limits to apply to a user to restrict the number of connections and channels
41+
// the user can create. These limits can be used as guard rails in environments
42+
// where applications cannot be trusted and monitored in detail, for example,
43+
// when RabbitMQ clusters are offered as a service. See https://www.rabbitmq.com/docs/user-limits.
44+
UserLimits *UserLimits `json:"limits,omitempty"`
4045
}
4146

4247
// UserStatus defines the observed state of User.
@@ -56,6 +61,17 @@ type UserStatus struct {
5661
// +kubebuilder:validation:Enum=management;policymaker;monitoring;administrator
5762
type UserTag string
5863

64+
// Limits to apply to a user to restrict the number of connections and channels
65+
// the user can create. These limits can be used as guard rails in environments
66+
// where applications cannot be trusted and monitored in detail, for example,
67+
// when RabbitMQ clusters are offered as a service. See https://www.rabbitmq.com/docs/user-limits.
68+
type UserLimits struct {
69+
// Limits how many connections the user can open.
70+
Connections *int32 `json:"connections,omitempty"`
71+
// Limits how many AMQP 0.9.1 channels the user can open.
72+
Channels *int32 `json:"channels,omitempty"`
73+
}
74+
5975
// +genclient
6076
// +kubebuilder:object:root=true
6177
// +kubebuilder:resource:categories=rabbitmq

api/v1beta1/user_types_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,51 @@ var _ = Describe("user spec", func() {
9292
})
9393
})
9494

95+
When("creating a user with limits", func() {
96+
var user User
97+
var username string
98+
var userLimits UserLimits
99+
var connections, channels int32
100+
101+
JustBeforeEach(func() {
102+
user = User{
103+
ObjectMeta: metav1.ObjectMeta{
104+
Name: username,
105+
Namespace: namespace,
106+
},
107+
Spec: UserSpec{
108+
RabbitmqClusterReference: RabbitmqClusterReference{
109+
Name: "some-cluster",
110+
},
111+
UserLimits: &userLimits,
112+
},
113+
}
114+
})
115+
116+
When("creating a user with valid limits", func() {
117+
BeforeEach(func() {
118+
username = "limits-user"
119+
connections = 5
120+
channels = 10
121+
userLimits = UserLimits{
122+
Connections: &connections,
123+
Channels: &channels,
124+
}
125+
})
126+
It("successfully creates the user", func() {
127+
Expect(k8sClient.Create(ctx, &user)).To(Succeed())
128+
fetchedUser := &User{}
129+
Expect(k8sClient.Get(ctx, types.NamespacedName{
130+
Name: user.Name,
131+
Namespace: user.Namespace,
132+
}, fetchedUser)).To(Succeed())
133+
Expect(fetchedUser.Spec.RabbitmqClusterReference).To(Equal(RabbitmqClusterReference{
134+
Name: "some-cluster",
135+
}))
136+
Expect(fetchedUser.Spec.UserLimits).NotTo(BeNil())
137+
Expect(*fetchedUser.Spec.UserLimits.Connections).To(Equal(connections))
138+
Expect(*fetchedUser.Spec.UserLimits.Channels).To(Equal(channels))
139+
})
140+
})
141+
})
95142
})

api/v1beta1/zz_generated.deepcopy.go

+30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/rabbitmq.com_users.yaml

+17
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,23 @@ spec:
6464
type: string
6565
type: object
6666
x-kubernetes-map-type: atomic
67+
limits:
68+
description: |-
69+
Limits to apply to a user to restrict the number of connections and channels
70+
the user can create. These limits can be used as guard rails in environments
71+
where applications cannot be trusted and monitored in detail, for example,
72+
when RabbitMQ clusters are offered as a service. See https://www.rabbitmq.com/docs/user-limits.
73+
properties:
74+
channels:
75+
description: Limits how many AMQP 0.9.1 channels the user can
76+
open.
77+
format: int32
78+
type: integer
79+
connections:
80+
description: Limits how many connections the user can open.
81+
format: int32
82+
type: integer
83+
type: object
6784
rabbitmqClusterReference:
6885
description: |-
6986
Reference to the RabbitmqCluster that the user will be created for. This cluster must

controllers/binding_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ var _ = Describe("bindingController", func() {
9595
})
9696

9797
When("creating a binding", func() {
98+
AfterEach(func() {
99+
Expect(k8sClient.Delete(ctx, &binding)).To(Succeed())
100+
})
101+
98102
When("the RabbitMQ Client returns a HTTP error response", func() {
99103
BeforeEach(func() {
100104
bindingName = "test-binding-http-error"

controllers/exchange_controller_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ var _ = Describe("exchange-controller", func() {
9797
})
9898

9999
Context("creation", func() {
100+
AfterEach(func() {
101+
Expect(k8sClient.Delete(ctx, &exchange)).To(Succeed())
102+
})
103+
100104
When("the RabbitMQ Client returns a HTTP error response", func() {
101105
BeforeEach(func() {
102106
exchangeName = "test-http-error"
@@ -150,6 +154,7 @@ var _ = Describe("exchange-controller", func() {
150154
})
151155
})
152156
})
157+
153158
Context("LastTransitionTime", func() {
154159
BeforeEach(func() {
155160
exchangeName = "test-last-transition-time"
@@ -158,6 +163,11 @@ var _ = Describe("exchange-controller", func() {
158163
StatusCode: http.StatusCreated,
159164
}, nil)
160165
})
166+
167+
AfterEach(func() {
168+
Expect(k8sClient.Delete(ctx, &exchange)).To(Succeed())
169+
})
170+
161171
It("changes only if status changes", func() {
162172
By("setting LastTransitionTime when transitioning to status Ready=true")
163173
Expect(k8sClient.Create(ctx, &exchange)).To(Succeed())

controllers/federation_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ var _ = Describe("federation-controller", func() {
9898
})
9999

100100
When("creation", func() {
101+
AfterEach(func() {
102+
Expect(k8sClient.Delete(ctx, &federation)).To(Succeed())
103+
})
104+
101105
When("the RabbitMQ Client returns a HTTP error response", func() {
102106
BeforeEach(func() {
103107
federationName = "test-federation-http-error"

controllers/operatorpolicy_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ var _ = Describe("operatorpolicy-controller", func() {
101101
})
102102

103103
Context("creation", func() {
104+
AfterEach(func() {
105+
Expect(k8sClient.Delete(ctx, &policy)).To(Succeed())
106+
})
107+
104108
When("the RabbitMQ Client returns a HTTP error response", func() {
105109
BeforeEach(func() {
106110
policyName = "test-http-error"

controllers/permission_controller_test.go

+21-1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ var _ = Describe("permission-controller", func() {
101101
})
102102

103103
Context("creation", func() {
104+
AfterEach(func() {
105+
Expect(k8sClient.Delete(ctx, &permission)).To(Succeed())
106+
})
107+
104108
When("the RabbitMQ Client returns a HTTP error response", func() {
105109
BeforeEach(func() {
106110
permissionName = "test-with-username-http-error"
@@ -261,9 +265,21 @@ var _ = Describe("permission-controller", func() {
261265
Status: "204 No Content",
262266
StatusCode: http.StatusNoContent,
263267
}, nil)
268+
fakeRabbitMQClient.PutUserLimitsReturns(&http.Response{
269+
Status: "201 Created",
270+
StatusCode: http.StatusCreated,
271+
}, nil)
272+
fakeRabbitMQClient.DeleteUserLimitsReturns(&http.Response{
273+
Status: "204 No Content",
274+
StatusCode: http.StatusNoContent,
275+
}, nil)
264276
})
265277

266278
Context("creation", func() {
279+
AfterEach(func() {
280+
Expect(k8sClient.Delete(ctx, &permission)).To(Succeed())
281+
})
282+
267283
When("user not exist", func() {
268284
BeforeEach(func() {
269285
permissionName = "test-with-userref-create-not-exist"
@@ -407,12 +423,16 @@ var _ = Describe("permission-controller", func() {
407423
})
408424
})
409425

410-
Context("ownerref", func() {
426+
When("the user already exists", func() {
411427
BeforeEach(func() {
412428
permissionName = "ownerref-with-userref-test"
413429
userName = "example-ownerref"
414430
})
415431

432+
AfterEach(func() {
433+
Expect(k8sClient.Delete(ctx, &user)).To(Succeed())
434+
})
435+
416436
It("sets the correct deletion ownerref to the object", func() {
417437
Expect(k8sClient.Create(ctx, &user)).To(Succeed())
418438
user.Status.Username = userName

controllers/policy_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ var _ = Describe("policy-controller", func() {
100100
})
101101

102102
Context("creation", func() {
103+
AfterEach(func() {
104+
Expect(k8sClient.Delete(ctx, &policy)).To(Succeed())
105+
})
106+
103107
When("the RabbitMQ Client returns a HTTP error response", func() {
104108
BeforeEach(func() {
105109
policyName = "test-http-error"

controllers/queue_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ var _ = Describe("queue-controller", func() {
9696
})
9797

9898
Context("creation", func() {
99+
AfterEach(func() {
100+
Expect(k8sClient.Delete(ctx, &queue)).To(Succeed())
101+
})
102+
99103
When("the RabbitMQ Client returns a HTTP error response", func() {
100104
BeforeEach(func() {
101105
queueName = "test-http-error"

controllers/schemareplication_controller_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ var _ = Describe("schema-replication-controller", func() {
103103
})
104104

105105
When("creation", func() {
106+
AfterEach(func() {
107+
Expect(k8sClient.Delete(ctx, &replication)).To(Succeed())
108+
})
109+
106110
When("the RabbitMQ Client returns a HTTP error response", func() {
107111
BeforeEach(func() {
108112
replicationName = "test-replication-http-error"
@@ -257,6 +261,7 @@ var _ = Describe("schema-replication-controller", func() {
257261
})
258262

259263
AfterEach(func() {
264+
Expect(k8sClient.Delete(ctx, &replication)).To(Succeed())
260265
rabbitmqclient.SecretStoreClientProvider = rabbitmqclient.GetSecretStoreClient
261266
})
262267

controllers/shovel_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ var _ = Describe("shovel-controller", func() {
100100
})
101101

102102
When("creation", func() {
103+
AfterEach(func() {
104+
Expect(k8sClient.Delete(ctx, &shovel)).To(Succeed())
105+
})
106+
103107
When("the RabbitMQ Client returns a HTTP error response", func() {
104108
BeforeEach(func() {
105109
shovelName = "test-shovel-http-error"

controllers/super_stream_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ var _ = Describe("super-stream-controller", func() {
124124
})
125125

126126
Context("creation", func() {
127+
AfterEach(func() {
128+
Expect(k8sClient.Delete(ctx, &superStream)).To(Succeed())
129+
})
130+
127131
When("an underlying resource is deleted", func() {
128132
JustBeforeEach(func() {
129133
Expect(k8sClient.Create(ctx, &superStream)).To(Succeed())

controllers/topicpermission_controller_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ var _ = Describe("topicpermission-controller", func() {
103103
})
104104

105105
Context("creation", func() {
106+
AfterEach(func() {
107+
Expect(k8sClient.Delete(ctx, &topicperm)).To(Succeed())
108+
})
109+
106110
When("the RabbitMQ Client returns a HTTP error response", func() {
107111
BeforeEach(func() {
108112
name = "test-with-username-http-error"
@@ -284,6 +288,10 @@ var _ = Describe("topicpermission-controller", func() {
284288
})
285289

286290
Context("creation", func() {
291+
AfterEach(func() {
292+
Expect(k8sClient.Delete(ctx, &topicperm)).To(Succeed())
293+
})
294+
287295
When("user not exist", func() {
288296
BeforeEach(func() {
289297
name = "test-with-userref-create-not-exist"
@@ -457,6 +465,11 @@ var _ = Describe("topicpermission-controller", func() {
457465
userName = "topic-perm-topic-perm-user"
458466
})
459467

468+
AfterEach(func() {
469+
Expect(k8sClient.Delete(ctx, &user)).To(Succeed())
470+
Expect(k8sClient.Delete(ctx, &topicperm)).To(Succeed())
471+
})
472+
460473
It("sets the correct deletion ownerref to the object", func() {
461474
Expect(k8sClient.Create(ctx, &user)).To(Succeed())
462475
user.Status.Username = userName

0 commit comments

Comments
 (0)