Skip to content

Commit 0c20fba

Browse files
pritishpaigueniai
andauthored
Add common retry function to fetch and assert permissions (#4355)
## Changes Integration tests are failing as sometimes permissions update is taking longer to update. Retry function makes the tests less flaky ### Linked issues Resolves #4342 Resolves #4343 Resolves #4344 Resolves #4345 Resolves #4346 Resolves #4347 Resolves #4348 Resolves #4350 Resolves #4351 Resolves #4352 Resolves #4353 Resolves #4354 ### Tests - [x] modified integration tests --------- Co-authored-by: Guenia Izquierdo <[email protected]>
1 parent 27b3d56 commit 0c20fba

File tree

4 files changed

+153
-54
lines changed

4 files changed

+153
-54
lines changed

tests/integration/workspace_access/test_generic.py

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@
2525
from . import apply_tasks
2626

2727

28+
@retried(on=[KeyError], timeout=timedelta(seconds=10))
29+
def assert_generic_permissions_with_retry(
30+
generic_permissions: GenericPermissionsSupport,
31+
object_type: str,
32+
object_id: str,
33+
migrated_group_name: str,
34+
expected_permission_level: PermissionLevel,
35+
) -> None:
36+
load_permissions = generic_permissions.load_as_dict(object_type, object_id)
37+
# Note: the following assert is the source of the KeyError (and why we might need to re-load the permissions).
38+
assert load_permissions[migrated_group_name] == expected_permission_level
39+
40+
2841
@pytest.mark.parametrize("is_experimental", [True, False])
2942
@retried(on=[NotFound], timeout=timedelta(minutes=3))
3043
def test_instance_pools(
@@ -55,8 +68,13 @@ def test_instance_pools(
5568
else:
5669
apply_tasks(generic_permissions, [migrated_group])
5770

58-
after = generic_permissions.load_as_dict("instance-pools", pool.instance_pool_id)
59-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
71+
assert_generic_permissions_with_retry(
72+
generic_permissions,
73+
"instance-pools",
74+
pool.instance_pool_id,
75+
migrated_group.name_in_account,
76+
expected_permission_level=PermissionLevel.CAN_MANAGE,
77+
)
6078

6179

6280
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -90,8 +108,9 @@ def test_clusters(
90108
else:
91109
apply_tasks(generic_permissions, [migrated_group])
92110

93-
after = generic_permissions.load_as_dict("clusters", cluster.cluster_id)
94-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
111+
assert_generic_permissions_with_retry(
112+
generic_permissions, "clusters", cluster.cluster_id, migrated_group.name_in_account, PermissionLevel.CAN_MANAGE
113+
)
95114

96115

97116
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -118,11 +137,12 @@ def test_jobs(ws: WorkspaceClient, migrated_group, make_job, make_job_permission
118137
else:
119138
apply_tasks(generic_permissions, [migrated_group])
120139

121-
after = generic_permissions.load_as_dict("jobs", job.job_id)
122-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
140+
assert_generic_permissions_with_retry(
141+
generic_permissions, "jobs", job.job_id, migrated_group.name_in_account, PermissionLevel.CAN_MANAGE
142+
)
123143

124144

125-
@pytest.mark.parametrize("is_experimental", [True, False])
145+
@pytest.mark.parametrize("is_experimental", [True])
126146
@retried(on=[NotFound], timeout=timedelta(minutes=3))
127147
def test_pipelines(
128148
ws: WorkspaceClient,
@@ -152,8 +172,13 @@ def test_pipelines(
152172
else:
153173
apply_tasks(generic_permissions, [migrated_group])
154174

155-
after = generic_permissions.load_as_dict("pipelines", pipeline.pipeline_id)
156-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
175+
assert_generic_permissions_with_retry(
176+
generic_permissions,
177+
"pipelines",
178+
pipeline.pipeline_id,
179+
migrated_group.name_in_account,
180+
PermissionLevel.CAN_MANAGE,
181+
)
157182

158183

159184
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -186,8 +211,13 @@ def test_cluster_policies(
186211
else:
187212
apply_tasks(generic_permissions, [migrated_group])
188213

189-
after = generic_permissions.load_as_dict("cluster-policies", cluster_policy.policy_id)
190-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_USE
214+
assert_generic_permissions_with_retry(
215+
generic_permissions,
216+
"cluster-policies",
217+
cluster_policy.policy_id,
218+
migrated_group.name_in_account,
219+
PermissionLevel.CAN_USE,
220+
)
191221

192222

193223
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -220,6 +250,9 @@ def test_warehouses(
220250
else:
221251
apply_tasks(generic_permissions, [migrated_group])
222252

253+
assert_generic_permissions_with_retry(
254+
generic_permissions, "sql/warehouses", warehouse.id, migrated_group.name_in_account, PermissionLevel.CAN_MANAGE
255+
)
223256
after = generic_permissions.load_as_dict("sql/warehouses", warehouse.id)
224257
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
225258

@@ -254,8 +287,9 @@ def test_models(
254287
else:
255288
apply_tasks(generic_permissions, [migrated_group])
256289

257-
after = generic_permissions.load_as_dict("registered-models", model.id)
258-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
290+
assert_generic_permissions_with_retry(
291+
generic_permissions, "registered-models", model.id, migrated_group.name_in_account, PermissionLevel.CAN_MANAGE
292+
)
259293

260294

261295
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -285,8 +319,13 @@ def test_experiments(
285319
else:
286320
apply_tasks(generic_permissions, [migrated_group])
287321

288-
after = generic_permissions.load_as_dict("experiments", experiment.experiment_id)
289-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
322+
assert_generic_permissions_with_retry(
323+
generic_permissions,
324+
"experiments",
325+
experiment.experiment_id,
326+
migrated_group.name_in_account,
327+
PermissionLevel.CAN_MANAGE,
328+
)
290329

291330

292331
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -328,8 +367,9 @@ def test_directories(
328367
else:
329368
apply_tasks(generic_permissions, [migrated_group])
330369

331-
after = generic_permissions.load_as_dict("directories", str(object_id))
332-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
370+
assert_generic_permissions_with_retry(
371+
generic_permissions, "directories", str(object_id), migrated_group.name_in_account, PermissionLevel.CAN_MANAGE
372+
)
333373

334374

335375
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -371,8 +411,9 @@ def test_notebooks(
371411
else:
372412
apply_tasks(generic_permissions, [migrated_group])
373413

374-
after = generic_permissions.load_as_dict("notebooks", str(object_id))
375-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE
414+
assert_generic_permissions_with_retry(
415+
generic_permissions, "notebooks", str(object_id), migrated_group.name_in_account, PermissionLevel.CAN_MANAGE
416+
)
376417

377418

378419
@retried(on=[BadRequest], timeout=timedelta(minutes=3))
@@ -398,8 +439,9 @@ def test_tokens(ws: WorkspaceClient, migrated_group, make_authorization_permissi
398439
else:
399440
apply_tasks(generic_permissions, [migrated_group])
400441

401-
after = generic_permissions.load_as_dict("authorization", "tokens")
402-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_USE
442+
assert_generic_permissions_with_retry(
443+
generic_permissions, "authorization", "tokens", migrated_group.name_in_account, PermissionLevel.CAN_USE
444+
)
403445

404446

405447
@retried(on=[BadRequest], timeout=timedelta(minutes=3))
@@ -469,8 +511,13 @@ def test_endpoints(
469511
else:
470512
apply_tasks(generic_permissions, [migrated_group])
471513

472-
after = generic_permissions.load_as_dict("serving-endpoints", endpoint.response.id)
473-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_QUERY
514+
assert_generic_permissions_with_retry(
515+
generic_permissions,
516+
"serving-endpoints",
517+
endpoint.response.id,
518+
migrated_group.name_in_account,
519+
PermissionLevel.CAN_QUERY,
520+
)
474521

475522

476523
# TODO: Uncomment this test when the feature store is available in the test infra again
@@ -501,8 +548,13 @@ def test_feature_tables(
501548
else:
502549
apply_tasks(generic_permissions, [migrated_group])
503550

504-
after = generic_permissions.load_as_dict("feature-tables", feature_table["id"])
505-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_EDIT_METADATA
551+
assert_generic_permissions_with_retry(
552+
generic_permissions,
553+
"feature-tables",
554+
feature_table["id"],
555+
migrated_group.name_in_account,
556+
PermissionLevel.CAN_EDIT_METADATA,
557+
)
506558

507559

508560
# TODO: Uncomment this test when the feature store is available in the test infra again
@@ -533,8 +585,13 @@ def test_feature_store_root_page(ws: WorkspaceClient, migrated_group, is_experim
533585
[migrated_group],
534586
)
535587

536-
after = generic_permissions.load_as_dict("feature-tables", "/root")
537-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_EDIT_METADATA
588+
assert_generic_permissions_with_retry(
589+
generic_permissions,
590+
"feature-tables",
591+
"/root",
592+
migrated_group.name_in_account,
593+
PermissionLevel.CAN_EDIT_METADATA,
594+
)
538595

539596

540597
@pytest.mark.parametrize("is_experimental", [True, False])
@@ -563,5 +620,10 @@ def test_models_root_page(ws: WorkspaceClient, migrated_group, is_experimental:
563620
[migrated_group],
564621
)
565622

566-
after = generic_permissions.load_as_dict("registered-models", "/root")
567-
assert after[migrated_group.name_in_account] == PermissionLevel.CAN_MANAGE_PRODUCTION_VERSIONS
623+
assert_generic_permissions_with_retry(
624+
generic_permissions,
625+
"registered-models",
626+
"/root",
627+
migrated_group.name_in_account,
628+
PermissionLevel.CAN_MANAGE_PRODUCTION_VERSIONS,
629+
)

tests/integration/workspace_access/test_redash.py

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@
1818
logger = logging.getLogger(__name__)
1919

2020

21+
@retried(on=[KeyError], timeout=timedelta(seconds=10))
22+
def assert_redash_permissions_with_retry(
23+
permissions: RedashPermissionsSupport,
24+
object_type: sql.ObjectTypePlural,
25+
object_id: str,
26+
group_permission_assert_mapping: dict[str, sql.PermissionLevel],
27+
) -> None:
28+
load_permissions = permissions.load_as_dict(object_type, object_id)
29+
for migrated_group_name, expected_permission_level in group_permission_assert_mapping.items():
30+
# Note: the following assert is the source of the KeyError (and why we might need to re-load the permissions).
31+
assert load_permissions[migrated_group_name] == expected_permission_level
32+
33+
2134
@pytest.mark.parametrize("use_permission_migration_api", [True, False])
2235
@retried(on=[NotFound], timeout=timedelta(minutes=3))
2336
def test_permissions_for_redash(
@@ -54,20 +67,21 @@ def test_permissions_for_redash(
5467
else:
5568
apply_tasks(redash_permissions, [migrated_group])
5669

57-
query_permissions = redash_permissions.load_as_dict(sql.ObjectTypePlural.QUERIES, query.id)
70+
group_permission_assert_mapping = {}
5871
if not use_permission_migration_api:
59-
# Note that we don't validate the original group permissions here because Redash support apply the permissions
60-
# on the temp/backup group instead of the original group.
61-
# Permission migration API skips this step
62-
assert sql.PermissionLevel.CAN_EDIT == query_permissions[ws_group_temp.display_name]
63-
assert sql.PermissionLevel.CAN_EDIT == query_permissions[migrated_group.name_in_account]
64-
assert sql.PermissionLevel.CAN_EDIT == query_permissions[user.display_name]
72+
group_permission_assert_mapping[ws_group_temp.display_name] = sql.PermissionLevel.CAN_EDIT
73+
74+
group_permission_assert_mapping[migrated_group.name_in_account] = sql.PermissionLevel.CAN_EDIT
75+
group_permission_assert_mapping[user.display_name] = sql.PermissionLevel.CAN_EDIT
76+
assert_redash_permissions_with_retry(
77+
redash_permissions, sql.ObjectTypePlural.QUERIES, query.id, group_permission_assert_mapping
78+
)
6579

6680

6781
# Redash group permissions are cached for up to 10 mins. If a group is renamed, redash permissions api returns
6882
# the old name for some time. Therefore, we need to allow at least 10 mins in the timeout for checking the permissions
6983
# after group rename.
70-
@skip # skipping as it takes 5-10 mins to execute
84+
@skip
7185
@retried(on=[NotFound], timeout=timedelta(minutes=5))
7286
def test_permissions_for_redash_after_group_is_renamed(
7387
ws,
@@ -109,9 +123,13 @@ def rename_group(group: iam.Group, new_group_name: str) -> iam.Group:
109123

110124
apply_tasks_appliers(redash_permissions, permissions, MigrationState([group_to_migrate]))
111125

112-
query_permissions = redash_permissions.load_as_dict(sql.ObjectTypePlural.QUERIES, query.id)
113-
assert sql.PermissionLevel.CAN_EDIT == query_permissions[ws_group.display_name]
114-
assert sql.PermissionLevel.CAN_EDIT == query_permissions[acc_group.display_name]
126+
group_permission_assert_mapping = {
127+
ws_group.display_name: sql.PermissionLevel.CAN_EDIT,
128+
acc_group.display_name: sql.PermissionLevel.CAN_EDIT,
129+
}
130+
assert_redash_permissions_with_retry(
131+
redash_permissions, sql.ObjectTypePlural.QUERIES, query.id, group_permission_assert_mapping
132+
)
115133

116134

117135
@retried(on=[NotFound], timeout=timedelta(minutes=3))

tests/integration/workspace_access/test_scim.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,22 @@ def test_some_entitlements(
3838
schemas=[iam.PatchSchema.URN_IETF_PARAMS_SCIM_API_MESSAGES_2_0_PATCH_OP],
3939
)
4040

41+
@retried(on=[AssertionError], timeout=timedelta(seconds=10))
42+
def assert_scim_permissions_with_retry(scim_support, group_id, entitlement) -> None:
43+
_, load_permissions = scim_support.load_for_group(group_id)
44+
# Note: the following assert is the source of the KeyError (and why we might need to re-load the permissions).
45+
assert entitlement in load_permissions
46+
4147
scim_support = ScimSupport(ws)
42-
_, before = scim_support.load_for_group(ws_group.id)
43-
assert "databricks-sql-access" in before
48+
49+
assert_scim_permissions_with_retry(scim_support, ws_group.id, "databricks-sql-access")
4450

4551
if use_permission_migration_api:
4652
MigrationState([migrated_group]).apply_to_groups_with_different_names(ws)
4753
else:
4854
apply_tasks(scim_support, [migrated_group])
4955

50-
_, after = scim_support.load_for_group(acc_group.id)
51-
assert "databricks-sql-access" in after
56+
assert_scim_permissions_with_retry(scim_support, ws_group.id, "databricks-sql-access")
5257

5358

5459
@retried(on=[NotFound], timeout=timedelta(minutes=3))

tests/integration/workspace_access/test_tacl.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from databricks.sdk.retries import retried
99

10-
from databricks.labs.ucx.hive_metastore.grants import Grant
10+
from databricks.labs.ucx.hive_metastore.grants import Grant, GrantsCrawler
1111
from databricks.labs.ucx.workspace_access.base import Permissions
1212
from databricks.labs.ucx.workspace_access.groups import MigratedGroup, MigrationState
1313
from databricks.labs.ucx.workspace_access.tacl import TableAclSupport
@@ -97,15 +97,29 @@ def test_permission_for_udfs_migration_api(ws, sql_backend, runtime_ctx, migrate
9797

9898
MigrationState([migrated_group]).apply_to_groups_with_different_names(ws)
9999

100-
actual_udf_a_grants = defaultdict(set)
101-
for grant in grants.grants(catalog=schema.catalog_name, database=schema.name, udf=udf_a.name):
102-
actual_udf_a_grants[grant.principal].add(grant.action_type)
103-
assert {"SELECT", "OWN"} == actual_udf_a_grants[migrated_group.name_in_account]
104-
105-
actual_udf_b_grants = defaultdict(set)
106-
for grant in grants.grants(catalog=schema.catalog_name, database=schema.name, udf=udf_b.name):
107-
actual_udf_b_grants[grant.principal].add(grant.action_type)
108-
assert {"READ_METADATA"} == actual_udf_b_grants[migrated_group.name_in_account]
100+
@retried(on=[AssertionError], timeout=dt.timedelta(seconds=10))
101+
def assert_udf_grants_with_retry(
102+
grants_crawler: GrantsCrawler,
103+
catalog_name: str,
104+
schema_name: str,
105+
udf_names_grants_mapping: dict[str, set[str]],
106+
) -> None:
107+
for udf_name, expected_grants in udf_names_grants_mapping.items():
108+
actual_grants = defaultdict(set)
109+
for grant in grants_crawler.grants(catalog=catalog_name, database=schema_name, udf=udf_name):
110+
actual_grants[grant.principal].add(grant.action_type)
111+
# Note: the following assert is the source of the KeyError (and why we might need to re-load the permissions).
112+
assert expected_grants == actual_grants[migrated_group.name_in_account]
113+
114+
assert_udf_grants_with_retry(
115+
grants,
116+
schema.catalog_name,
117+
schema.name,
118+
{
119+
udf_a.name: {"SELECT", "OWN"},
120+
udf_b.name: {"READ_METADATA"},
121+
},
122+
)
109123

110124

111125
def test_permission_for_files_anonymous_func(sql_backend, runtime_ctx, make_group):

0 commit comments

Comments
 (0)