Skip to content

Commit 7671ca7

Browse files
committed
chore: add tenants context tests
1 parent e0d9411 commit 7671ca7

File tree

4 files changed

+254
-77
lines changed

4 files changed

+254
-77
lines changed

lib/supavisor/tenants.ex

Lines changed: 70 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -84,60 +84,6 @@ defmodule Supavisor.Tenants do
8484

8585
def get_tenant(_, _), do: nil
8686

87-
@spec get_user_cache(:single | :cluster, String.t(), String.t() | nil, String.t() | nil) ::
88-
{:ok, map()} | {:error, any()}
89-
def get_user_cache(type, user, external_id, sni_hostname) do
90-
cache_key = {:user_cache, type, user, external_id, sni_hostname}
91-
92-
case Cachex.fetch(Supavisor.Cache, cache_key, fn _key ->
93-
{:commit, {:cached, get_user(type, user, external_id, sni_hostname)},
94-
ttl: :timer.hours(24)}
95-
end) do
96-
{_, {:cached, value}} -> value
97-
{_, {:cached, value}, _} -> value
98-
end
99-
end
100-
101-
@spec get_user(atom(), String.t(), String.t() | nil, String.t() | nil) ::
102-
{:ok, map()} | {:error, any()}
103-
def get_user(_, _, nil, nil) do
104-
{:error, "Either external_id or sni_hostname must be provided"}
105-
end
106-
107-
def get_user(:cluster, user, external_id, sni_hostname) do
108-
query =
109-
from(ct in ClusterTenants,
110-
where: ct.cluster_alias == ^external_id and ct.active == true,
111-
limit: 1
112-
)
113-
114-
case Repo.all(query) do
115-
[%ClusterTenants{} = ct] ->
116-
get_user(:single, user, ct.tenant_external_id, sni_hostname)
117-
118-
[_ | _] ->
119-
{:error, :multiple_results}
120-
121-
_ ->
122-
{:error, :not_found}
123-
end
124-
end
125-
126-
def get_user(:single, user, external_id, sni_hostname) do
127-
query = build_user_query(user, external_id, sni_hostname)
128-
129-
case Repo.all(query) do
130-
[{%User{}, %Tenant{}} = {user, tenant}] ->
131-
{:ok, %{user: user, tenant: tenant}}
132-
133-
[_ | _] ->
134-
{:error, :multiple_results}
135-
136-
_ ->
137-
{:error, :not_found}
138-
end
139-
end
140-
14187
def get_pool_config(external_id, user) do
14288
query =
14389
from(a in User,
@@ -306,6 +252,76 @@ defmodule Supavisor.Tenants do
306252
Repo.all(User)
307253
end
308254

255+
@doc """
256+
Gets a single user.
257+
258+
Raises `Ecto.NoResultsError` if the User does not exist.
259+
260+
## Examples
261+
262+
iex> get_user!(123)
263+
%User{}
264+
265+
iex> get_user!(456)
266+
** (Ecto.NoResultsError)
267+
268+
"""
269+
def get_user!(id), do: Repo.get!(User, id)
270+
271+
@spec get_user_cache(:single | :cluster, String.t(), String.t() | nil, String.t() | nil) ::
272+
{:ok, map()} | {:error, any()}
273+
def get_user_cache(type, user, external_id, sni_hostname) do
274+
cache_key = {:user_cache, type, user, external_id, sni_hostname}
275+
276+
case Cachex.fetch(Supavisor.Cache, cache_key, fn _key ->
277+
{:commit, {:cached, get_user(type, user, external_id, sni_hostname)},
278+
ttl: :timer.hours(24)}
279+
end) do
280+
{_, {:cached, value}} -> value
281+
{_, {:cached, value}, _} -> value
282+
end
283+
end
284+
285+
@spec get_user(atom(), String.t(), String.t() | nil, String.t() | nil) ::
286+
{:ok, map()} | {:error, any()}
287+
def get_user(_, _, nil, nil) do
288+
{:error, "Either external_id or sni_hostname must be provided"}
289+
end
290+
291+
def get_user(:cluster, user, external_id, sni_hostname) do
292+
query =
293+
from(ct in ClusterTenants,
294+
where: ct.cluster_alias == ^external_id and ct.active == true,
295+
limit: 1
296+
)
297+
298+
case Repo.all(query) do
299+
[%ClusterTenants{} = ct] ->
300+
get_user(:single, user, ct.tenant_external_id, sni_hostname)
301+
302+
[_ | _] ->
303+
{:error, :multiple_results}
304+
305+
_ ->
306+
{:error, :not_found}
307+
end
308+
end
309+
310+
def get_user(:single, user, external_id, sni_hostname) do
311+
query = build_user_query(user, external_id, sni_hostname)
312+
313+
case Repo.all(query) do
314+
[{%User{}, %Tenant{}} = {user, tenant}] ->
315+
{:ok, %{user: user, tenant: tenant}}
316+
317+
[_ | _] ->
318+
{:error, :multiple_results}
319+
320+
_ ->
321+
{:error, :not_found}
322+
end
323+
end
324+
309325
@doc """
310326
Creates a user.
311327
@@ -424,17 +440,6 @@ defmodule Supavisor.Tenants do
424440
"""
425441
def get_cluster!(id), do: Repo.get!(Cluster, id)
426442

427-
@spec get_cluster_with_rel(String.t()) :: {:ok, Cluster.t()} | {:error, any()}
428-
def get_cluster_with_rel(id) do
429-
case Repo.get(Cluster, id) do
430-
nil ->
431-
{:error, :not_found}
432-
433-
cluster ->
434-
{:ok, Repo.preload(cluster, :cluster_tenants)}
435-
end
436-
end
437-
438443
@doc """
439444
Creates a cluster.
440445

lib/supavisor/tenants/user.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ defmodule Supavisor.Tenants.User do
2424
@doc false
2525
def changeset(user, attrs) do
2626
attrs =
27-
if attrs["db_user_alias"] do
28-
attrs
29-
else
30-
Map.put(attrs, "db_user_alias", attrs["db_user"])
27+
case attrs do
28+
%{"db_user_alias" => _} -> attrs
29+
%{"db_user" => db_user} -> Map.put(attrs, "db_user_alias", db_user)
30+
_ -> attrs
3131
end
3232

3333
user

test/supavisor/tenants_test.exs

Lines changed: 143 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,6 @@ defmodule Supavisor.TenantsTest do
139139
assert %Ecto.Changeset{} = Tenants.change_tenant(tenant)
140140
end
141141

142-
test "get_user/4" do
143-
_tenant = tenant_fixture()
144-
assert {:error, :not_found} = Tenants.get_user(:single, "no_user", "no_tenant", "")
145-
146-
assert {:ok, %{tenant: _, user: _}} =
147-
Tenants.get_user(:single, "postgres", "dev_tenant", "")
148-
end
149-
150142
test "update_tenant_ps/2 updates the tenant's default_parameter_status" do
151143
_tenant = tenant_fixture()
152144
default_parameter_status = %{"server_version" => "17.0"}
@@ -174,6 +166,77 @@ defmodule Supavisor.TenantsTest do
174166
end
175167
end
176168

169+
describe "users" do
170+
alias Supavisor.Tenants.User
171+
172+
import Supavisor.TenantsFixtures
173+
174+
@invalid_attrs %{
175+
"db_user" => nil,
176+
"db_password" => nil,
177+
"pool_size" => nil,
178+
"mode_type" => nil
179+
}
180+
181+
test "list_users/0 returns all users" do
182+
user = user_fixture()
183+
assert user in Tenants.list_users()
184+
end
185+
186+
test "get_user!/1 returns the user with given id" do
187+
user = user_fixture()
188+
assert Tenants.get_user!(user.id) == user
189+
end
190+
191+
test "get_user/4" do
192+
_tenant = tenant_fixture()
193+
assert {:error, :not_found} = Tenants.get_user(:single, "no_user", "no_tenant", "")
194+
195+
assert {:ok, %{tenant: _, user: _}} =
196+
Tenants.get_user(:single, "postgres", "dev_tenant", "")
197+
end
198+
199+
test "create_user/1 with valid data creates a user" do
200+
valid_attrs = %{
201+
"db_user" => "some_user",
202+
"db_password" => "some_password",
203+
"pool_size" => 3,
204+
"mode_type" => "transaction"
205+
}
206+
207+
assert {:ok, %User{} = user} = Tenants.create_user(valid_attrs)
208+
assert user.db_user_alias == "some_user"
209+
assert user.db_user == "some_user"
210+
assert user.db_password == "some_password"
211+
assert user.pool_size == 3
212+
assert user.mode_type == :transaction
213+
end
214+
215+
test "create_user/1 with invalid data returns error changeset" do
216+
assert {:error, %Ecto.Changeset{}} = Tenants.create_user(@invalid_attrs)
217+
end
218+
219+
test "update_user/2 with valid data updates the user" do
220+
user = user_fixture()
221+
update_attrs = %{"db_password" => "some_updated_password", "pool_size" => 4}
222+
223+
assert {:ok, %User{} = user} = Tenants.update_user(user, update_attrs)
224+
assert user.db_password == "some_updated_password"
225+
assert user.pool_size == 4
226+
end
227+
228+
test "delete_user/1 deletes the user" do
229+
user = user_fixture()
230+
assert {:ok, %User{}} = Tenants.delete_user(user)
231+
assert_raise Ecto.NoResultsError, fn -> Tenants.get_user!(user.id) end
232+
end
233+
234+
test "change_user/1 returns a user changeset" do
235+
user = user_fixture()
236+
assert %Ecto.Changeset{} = Tenants.change_user(user)
237+
end
238+
end
239+
177240
describe "clusters" do
178241
alias Supavisor.Tenants.Cluster
179242

@@ -225,4 +288,76 @@ defmodule Supavisor.TenantsTest do
225288
assert %Ecto.Changeset{} = Tenants.change_cluster(cluster)
226289
end
227290
end
291+
292+
describe "cluster_tenants" do
293+
alias Supavisor.Tenants.ClusterTenants
294+
295+
import Supavisor.TenantsFixtures
296+
297+
@invalid_attrs %{type: nil, cluster_alias: nil, tenant_external_id: nil, active: nil}
298+
299+
test "list_cluster_tenants/0 returns all cluster_tenants" do
300+
cluster_tenants = cluster_tenants_fixture()
301+
assert cluster_tenants in Tenants.list_cluster_tenants()
302+
end
303+
304+
test "get_cluster_tenants!/1 returns the cluster_tenants with given id" do
305+
cluster_tenants = cluster_tenants_fixture()
306+
assert Tenants.get_cluster_tenants!(cluster_tenants.id) == cluster_tenants
307+
end
308+
309+
test "create_cluster_tenants/1 with valid data creates a cluster_tenants" do
310+
tenant = tenant_fixture()
311+
cluster = cluster_fixture()
312+
313+
valid_attrs = %{
314+
type: "write",
315+
cluster_alias: cluster.alias,
316+
tenant_external_id: tenant.external_id,
317+
active: true
318+
}
319+
320+
assert {:ok, %ClusterTenants{} = cluster_tenants} =
321+
Tenants.create_cluster_tenants(valid_attrs)
322+
323+
assert cluster_tenants.type == :write
324+
assert cluster_tenants.cluster_alias == cluster.alias
325+
assert cluster_tenants.tenant_external_id == tenant.external_id
326+
assert cluster_tenants.active == true
327+
end
328+
329+
test "create_cluster_tenants/1 with invalid data returns error changeset" do
330+
assert {:error, %Ecto.Changeset{}} = Tenants.create_cluster_tenants(@invalid_attrs)
331+
end
332+
333+
test "update_cluster_tenants/2 with valid data updates the cluster_tenants" do
334+
valid_attrs = %{type: "read"}
335+
cluster_tenants = cluster_tenants_fixture()
336+
337+
assert {:ok, %ClusterTenants{} = cluster_tenants} =
338+
Tenants.update_cluster_tenants(cluster_tenants, valid_attrs)
339+
340+
assert cluster_tenants.active == true
341+
end
342+
343+
test "update_cluster_tenants/2 with invalid data returns error changeset" do
344+
cluster_tenants = cluster_tenants_fixture()
345+
346+
assert {:error, %Ecto.Changeset{}} =
347+
Tenants.update_cluster_tenants(cluster_tenants, @invalid_attrs)
348+
349+
assert cluster_tenants == Tenants.get_cluster_tenants!(cluster_tenants.id)
350+
end
351+
352+
test "delete_cluster_tenants/1 deletes the cluster_tenants" do
353+
cluster_tenants = cluster_tenants_fixture()
354+
assert {:ok, %ClusterTenants{}} = Tenants.delete_cluster_tenants(cluster_tenants)
355+
assert_raise Ecto.NoResultsError, fn -> Tenants.get_cluster_tenants!(cluster_tenants.id) end
356+
end
357+
358+
test "change_cluster_tenants/1 returns a cluster_tenants changeset" do
359+
cluster_tenants = cluster_tenants_fixture()
360+
assert %Ecto.Changeset{} = Tenants.change_cluster_tenants(cluster_tenants)
361+
end
362+
end
228363
end

test/support/fixtures/tenants_fixtures.ex

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ defmodule Supavisor.TenantsFixtures do
3131
tenant
3232
end
3333

34+
@doc """
35+
Generate a user.
36+
"""
37+
def user_fixture(attrs \\ %{}) do
38+
{:ok, user} =
39+
attrs
40+
|> Enum.into(%{
41+
"db_user" => "postgres",
42+
"db_password" => "postgres",
43+
"pool_size" => 3,
44+
"mode_type" => "transaction"
45+
})
46+
|> Supavisor.Tenants.create_user()
47+
48+
user
49+
end
50+
3451
# @doc """
3552
# Generate a unique cluster tenant_external_id.
3653
# """
@@ -64,4 +81,24 @@ defmodule Supavisor.TenantsFixtures do
6481

6582
cluster
6683
end
84+
85+
@doc """
86+
Generate a cluster tenants.
87+
"""
88+
def cluster_tenants_fixture(attrs \\ %{}) do
89+
tenant = tenant_fixture()
90+
cluster = cluster_fixture(%{cluster_tenants: []})
91+
92+
{:ok, cluster_tenants} =
93+
attrs
94+
|> Enum.into(%{
95+
type: "write",
96+
cluster_alias: cluster.alias,
97+
tenant_external_id: tenant.external_id,
98+
active: true
99+
})
100+
|> Supavisor.Tenants.create_cluster_tenants()
101+
102+
cluster_tenants
103+
end
67104
end

0 commit comments

Comments
 (0)