From 4b82d8195e4f8fd87d3bc3e938c6b6a9f4958ddb Mon Sep 17 00:00:00 2001 From: Jan Sikorski Date: Tue, 11 Jun 2024 15:28:35 +0200 Subject: [PATCH 1/2] Add copy grants --- src/snowflake/cli/plugins/snowpark/common.py | 1 + tests/snowpark/test_function.py | 4 ++ tests/snowpark/test_procedure.py | 3 ++ tests_integration/test_snowpark.py | 46 +++++++++++++++++++ .../testing_utils/snowpark_utils.py | 27 +++++++++++ 5 files changed, 81 insertions(+) diff --git a/src/snowflake/cli/plugins/snowpark/common.py b/src/snowflake/cli/plugins/snowpark/common.py index 8fdb0d8f5..2d16eaf4b 100644 --- a/src/snowflake/cli/plugins/snowpark/common.py +++ b/src/snowflake/cli/plugins/snowpark/common.py @@ -153,6 +153,7 @@ def create_query( query = [ f"create or replace {self._object_type.value.sf_name} {identifier}", + f"copy grants", f"returns {return_type}", "language python", f"runtime_version={runtime or DEFAULT_RUNTIME}", diff --git a/tests/snowpark/test_function.py b/tests/snowpark/test_function.py index c98fcbed7..c4e7c770c 100644 --- a/tests/snowpark/test_function.py +++ b/tests/snowpark/test_function.py @@ -38,6 +38,7 @@ def test_deploy_function( dedent( """\ create or replace function MockDatabase.MockSchema.func1(a string default 'default value', b variant) + copy grants returns string language python runtime_version=3.10 @@ -85,6 +86,7 @@ def test_deploy_function_with_external_access( dedent( """\ create or replace function MockDatabase.MockSchema.func1(a string, b variant) + copy grants returns string language python runtime_version=3.8 @@ -204,6 +206,7 @@ def test_deploy_function_needs_update_because_packages_changes( dedent( """\ create or replace function MockDatabase.MockSchema.func1(a string default 'default value', b variant) + copy grants returns string language python runtime_version=3.10 @@ -254,6 +257,7 @@ def test_deploy_function_needs_update_because_handler_changes( dedent( """\ create or replace function MockDatabase.MockSchema.func1(a string default 'default value', b variant) + copy grants returns string language python runtime_version=3.10 diff --git a/tests/snowpark/test_procedure.py b/tests/snowpark/test_procedure.py index 9d962d4fe..278abc49a 100644 --- a/tests/snowpark/test_procedure.py +++ b/tests/snowpark/test_procedure.py @@ -58,6 +58,7 @@ def test_deploy_procedure( dedent( """\ create or replace procedure MockDatabase.MockSchema.procedureName(name string) + copy grants returns string language python runtime_version=3.8 @@ -69,6 +70,7 @@ def test_deploy_procedure( dedent( """\ create or replace procedure MockDatabase.MockSchema.test() + copy grants returns string language python runtime_version=3.10 @@ -124,6 +126,7 @@ def test_deploy_procedure_with_external_access( dedent( """\ create or replace procedure MockDatabase.MockSchema.procedureName(name string) + copy grants returns string language python runtime_version=3.8 diff --git a/tests_integration/test_snowpark.py b/tests_integration/test_snowpark.py index 966bb597e..59f1feb7b 100644 --- a/tests_integration/test_snowpark.py +++ b/tests_integration/test_snowpark.py @@ -86,6 +86,36 @@ def test_snowpark_flow( returns="VARCHAR(16777216)", ) + # Grants are given correctly + + _test_steps.set_grants_on_selected_object( + object_type="procedure", + object_name="hello_procedure(VARCHAR)", + privillege="USAGE", + role="test_role", + ) + + _test_steps.set_grants_on_selected_object( + object_type="function", + object_name="hello_function(VARCHAR)", + privillege="USAGE", + role="test_role", + ) + + _test_steps.assert_that_object_has_expected_grant( + object_type="procedure", + object_name="hello_procedure(VARCHAR)", + expected_privillege="USAGE", + expected_role="test_role", + ) + + _test_steps.assert_that_object_has_expected_grant( + object_type="function", + object_name="hello_function(VARCHAR)", + expected_privillege="USAGE", + expected_role="test_role", + ) + # Created objects can be executed _test_steps.snowpark_execute_should_return_expected_value( object_type="procedure", @@ -215,6 +245,22 @@ def test_snowpark_flow( *expected_files, stage_name=STAGE_NAME ) + # Grants are preserved after updates + + _test_steps.assert_that_object_has_expected_grant( + object_type="procedure", + object_name="hello_procedure(VARCHAR)", + expected_privillege="USAGE", + expected_role="test_role", + ) + + _test_steps.assert_that_object_has_expected_grant( + object_type="function", + object_name="hello_function(VARCHAR)", + expected_privillege="USAGE", + expected_role="test_role", + ) + # Check if objects can be dropped _test_steps.object_drop_should_finish_successfully( object_type="procedure", identifier="hello_procedure(varchar)" diff --git a/tests_integration/testing_utils/snowpark_utils.py b/tests_integration/testing_utils/snowpark_utils.py index f8a739be8..735072062 100644 --- a/tests_integration/testing_utils/snowpark_utils.py +++ b/tests_integration/testing_utils/snowpark_utils.py @@ -351,3 +351,30 @@ def get_actual_files_staged_in_db(self, stage_name: str): stage_name=stage_name ) ] + + def set_grants_on_selected_object( + self, object_type: str, object_name: str, privillege: str, role: str + ): + self._setup.sql_test_helper.execute_single_sql( + f"GRANT {privillege} ON {object_type} {object_name} TO ROLE {role};" + ) + + def assert_that_object_has_expected_grant( + self, + object_type: str, + object_name: str, + expected_privillege: str, + expected_role: str, + ): + result = self._setup.sql_test_helper.execute_single_sql( + f"SHOW GRANTS ON {object_type} {object_name};" + ) + assert any( + [ + ( + grant.get("privilege") == expected_privillege.upper() + and grant.get("grantee_name") == expected_role.upper() + ) + for grant in result + ] + ) From 5c9bf990ca93d792a4a998e944fb10232702c491 Mon Sep 17 00:00:00 2001 From: Jan Sikorski Date: Tue, 11 Jun 2024 15:31:31 +0200 Subject: [PATCH 2/2] Added notes --- RELEASE-NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 4f0157f59..f1cd9ab9a 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -15,6 +15,7 @@ ## Fixes and improvements * Fixed error handling for malformatted `config.toml` * Fixed ZIP packaging of Snowpark project dependencies containing implicit namespace packages like `snowflake`. +* Deploying function/procedure with `--replace` flag now copies all grants # v2.4.0 ## Backward incompatibility