|
61 | 61 | model, |
62 | 62 | ) |
63 | 63 | from sqlmesh.core.model.common import parse_expression |
64 | | -from sqlmesh.core.model.kind import ModelKindName, _model_kind_validator |
| 64 | +from sqlmesh.core.model.kind import _ModelKind, ModelKindName, _model_kind_validator |
65 | 65 | from sqlmesh.core.model.seed import CsvSettings |
66 | 66 | from sqlmesh.core.node import IntervalUnit, _Node |
67 | 67 | from sqlmesh.core.signal import signal |
@@ -11774,90 +11774,235 @@ def my_macro(evaluator): |
11774 | 11774 | assert model.render_query_or_raise().sql() == 'SELECT 3 AS "c"' |
11775 | 11775 |
|
11776 | 11776 |
|
11777 | | -def test_grants_validation_symbolic_model_error(): |
11778 | | - with pytest.raises(ValidationError, match=r".*grants cannot be set for EXTERNAL.*"): |
11779 | | - create_sql_model( |
11780 | | - "db.table", |
11781 | | - parse_one("SELECT 1 AS id"), |
11782 | | - kind="EXTERNAL", |
11783 | | - grants={"select": ["user1", "user2"], "insert": ["admin_user"]}, |
11784 | | - ) |
| 11777 | +@pytest.mark.parametrize( |
| 11778 | + "kind", |
| 11779 | + [ |
| 11780 | + "FULL", |
| 11781 | + "VIEW", |
| 11782 | + SeedKind(path="test.csv"), |
| 11783 | + IncrementalByTimeRangeKind(time_column="ds"), |
| 11784 | + IncrementalByUniqueKeyKind(unique_key="id"), |
| 11785 | + ], |
| 11786 | +) |
| 11787 | +def test_grants_valid_model_kinds(kind: t.Union[str, _ModelKind]): |
| 11788 | + model = create_sql_model( |
| 11789 | + "db.table", |
| 11790 | + parse_one("SELECT 1 AS id"), |
| 11791 | + kind=kind, |
| 11792 | + grants={"select": ["user1", "user2"], "insert": ["admin_user"]}, |
| 11793 | + ) |
| 11794 | + assert model.grants == {"select": ["user1", "user2"], "insert": ["admin_user"]} |
11785 | 11795 |
|
11786 | 11796 |
|
11787 | | -def test_grants_validation_embedded_model_error(): |
11788 | | - with pytest.raises(ValidationError, match=r".*grants cannot be set for EMBEDDED.*"): |
| 11797 | +@pytest.mark.parametrize( |
| 11798 | + "kind", |
| 11799 | + [ |
| 11800 | + "EXTERNAL", |
| 11801 | + "EMBEDDED", |
| 11802 | + ], |
| 11803 | +) |
| 11804 | +def test_grants_invalid_model_kind_errors(kind: str): |
| 11805 | + with pytest.raises(ValidationError, match=rf".*grants cannot be set for {kind}.*"): |
11789 | 11806 | create_sql_model( |
11790 | 11807 | "db.table", |
11791 | 11808 | parse_one("SELECT 1 AS id"), |
11792 | | - kind="EMBEDDED", |
| 11809 | + kind=kind, |
11793 | 11810 | grants={"select": ["user1"], "insert": ["admin_user"]}, |
11794 | 11811 | ) |
11795 | 11812 |
|
11796 | 11813 |
|
11797 | | -def test_grants_validation_valid_seed_model(): |
| 11814 | +def test_grants_validation_no_grants(): |
| 11815 | + model = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL") |
| 11816 | + assert model.grants is None |
| 11817 | + |
| 11818 | + |
| 11819 | +def test_grants_validation_empty_grantees(): |
11798 | 11820 | model = create_sql_model( |
11799 | | - "db.table", |
11800 | | - parse_one("SELECT 1 AS id"), |
11801 | | - kind=SeedKind(path="test.csv"), |
11802 | | - grants={"select": ["user1"], "insert": ["admin_user"]}, |
| 11821 | + "db.table", parse_one("SELECT 1 AS id"), kind="FULL", grants={"select": []} |
11803 | 11822 | ) |
11804 | | - assert model.grants == {"select": ["user1"], "insert": ["admin_user"]} |
| 11823 | + assert model.grants == {"select": []} |
11805 | 11824 |
|
11806 | 11825 |
|
11807 | | -def test_grants_validation_valid_materialized_model(): |
| 11826 | +def test_grants_single_value_conversions(): |
| 11827 | + expressions = d.parse(f""" |
| 11828 | + MODEL ( |
| 11829 | + name test.nested_arrays, |
| 11830 | + kind FULL, |
| 11831 | + grants ( |
| 11832 | + 'select' = "user1", update = user2 |
| 11833 | + ) |
| 11834 | + ); |
| 11835 | + SELECT 1 as id |
| 11836 | + """) |
| 11837 | + model = load_sql_based_model(expressions) |
| 11838 | + assert model.grants == {"select": ["user1"], "update": ["user2"]} |
| 11839 | + |
11808 | 11840 | model = create_sql_model( |
11809 | 11841 | "db.table", |
11810 | 11842 | parse_one("SELECT 1 AS id"), |
11811 | 11843 | kind="FULL", |
11812 | | - grants={"select": ["user1", "user2"], "insert": ["admin_user"]}, |
| 11844 | + grants={"select": "user1", "insert": 123}, |
11813 | 11845 | ) |
11814 | | - assert model.grants == {"select": ["user1", "user2"], "insert": ["admin_user"]} |
| 11846 | + assert model.grants == {"select": ["user1"], "insert": ["123"]} |
11815 | 11847 |
|
11816 | 11848 |
|
11817 | | -def test_grants_validation_valid_view_model(): |
11818 | | - model = create_sql_model( |
11819 | | - "db.table", parse_one("SELECT 1 AS id"), kind="VIEW", grants={"select": ["user1", "user2"]} |
| 11849 | +@pytest.mark.parametrize( |
| 11850 | + "grantees", |
| 11851 | + [ |
| 11852 | + "('user1', ('user2', 'user3'), 'user4')", |
| 11853 | + "('user1', ['user2', 'user3'], user4)", |
| 11854 | + "['user1', ['user2', user3], 'user4']", |
| 11855 | + "[user1, ('user2', \"user3\"), 'user4']", |
| 11856 | + ], |
| 11857 | +) |
| 11858 | +def test_grants_array_flattening(grantees: str): |
| 11859 | + expressions = d.parse(f""" |
| 11860 | + MODEL ( |
| 11861 | + name test.nested_arrays, |
| 11862 | + kind FULL, |
| 11863 | + grants ( |
| 11864 | + 'select' = {grantees} |
| 11865 | + ) |
| 11866 | + ); |
| 11867 | + SELECT 1 as id |
| 11868 | + """) |
| 11869 | + model = load_sql_based_model(expressions) |
| 11870 | + assert model.grants == {"select": ["user1", "user2", "user3", "user4"]} |
| 11871 | + |
| 11872 | + |
| 11873 | +def test_grants_macro_var_resolved(): |
| 11874 | + expressions = d.parse(""" |
| 11875 | + MODEL ( |
| 11876 | + name test.macro_grants, |
| 11877 | + kind FULL, |
| 11878 | + grants ( |
| 11879 | + 'select' = @VAR('readers'), |
| 11880 | + 'insert' = @VAR('writers') |
| 11881 | + ) |
| 11882 | + ); |
| 11883 | + SELECT 1 as id |
| 11884 | + """) |
| 11885 | + model = load_sql_based_model( |
| 11886 | + expressions, variables={"readers": ["user1", "user2"], "writers": "admin"} |
11820 | 11887 | ) |
11821 | | - assert model.grants == {"select": ["user1", "user2"]} |
| 11888 | + assert model.grants == { |
| 11889 | + "select": ["user1", "user2"], |
| 11890 | + "insert": ["admin"], |
| 11891 | + } |
11822 | 11892 |
|
11823 | 11893 |
|
11824 | | -def test_grants_validation_valid_incremental_model(): |
11825 | | - model = create_sql_model( |
11826 | | - "db.table", |
11827 | | - parse_one("SELECT 1 AS id, CURRENT_TIMESTAMP AS ts"), |
11828 | | - kind=IncrementalByTimeRangeKind(time_column="ts"), |
11829 | | - grants={"select": ["user1"], "update": ["admin_user"]}, |
| 11894 | +def test_grants_macro_var_in_array_flattening(): |
| 11895 | + expressions = d.parse(""" |
| 11896 | + MODEL ( |
| 11897 | + name test.macro_in_array, |
| 11898 | + kind FULL, |
| 11899 | + grants ( |
| 11900 | + 'select' = ['user1', @VAR('admins'), 'user3'] |
| 11901 | + ) |
| 11902 | + ); |
| 11903 | + SELECT 1 as id |
| 11904 | + """) |
| 11905 | + |
| 11906 | + model = load_sql_based_model(expressions, variables={"admins": ["admin1", "admin2"]}) |
| 11907 | + assert model.grants == {"select": ["user1", "admin1", "admin2", "user3"]} |
| 11908 | + |
| 11909 | + model2 = load_sql_based_model(expressions, variables={"admins": "super_admin"}) |
| 11910 | + assert model2.grants == {"select": ["user1", "super_admin", "user3"]} |
| 11911 | + |
| 11912 | + |
| 11913 | +def test_grants_dynamic_permission_names(): |
| 11914 | + expressions = d.parse(""" |
| 11915 | + MODEL ( |
| 11916 | + name test.dynamic_keys, |
| 11917 | + kind FULL, |
| 11918 | + grants ( |
| 11919 | + @VAR('read_perm') = ['user1', 'user2'], |
| 11920 | + @VAR('write_perm') = ['admin'] |
| 11921 | + ) |
| 11922 | + ); |
| 11923 | + SELECT 1 as id |
| 11924 | + """) |
| 11925 | + model = load_sql_based_model( |
| 11926 | + expressions, variables={"read_perm": "select", "write_perm": "insert"} |
11830 | 11927 | ) |
11831 | | - assert model.grants == {"select": ["user1"], "update": ["admin_user"]} |
| 11928 | + assert model.grants == {"select": ["user1", "user2"], "insert": ["admin"]} |
11832 | 11929 |
|
11833 | 11930 |
|
11834 | | -def test_grants_validation_no_grants(): |
11835 | | - model = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL") |
11836 | | - assert model.grants is None |
| 11931 | +def test_grants_unresolved_macro_errors(): |
| 11932 | + expressions1 = d.parse(""" |
| 11933 | + MODEL (name test.bad1, kind FULL, grants ('select' = @VAR('undefined'))); |
| 11934 | + SELECT 1 as id |
| 11935 | + """) |
| 11936 | + with pytest.raises(ConfigError, match=r"Invalid grants configuration for 'select': NULL value"): |
| 11937 | + load_sql_based_model(expressions1) |
11837 | 11938 |
|
| 11939 | + expressions2 = d.parse(""" |
| 11940 | + MODEL (name test.bad2, kind FULL, grants (@VAR('undefined') = ['user'])); |
| 11941 | + SELECT 1 as id |
| 11942 | + """) |
| 11943 | + with pytest.raises(ConfigError, match=r"Invalid grants configuration.*NULL value"): |
| 11944 | + load_sql_based_model(expressions2) |
11838 | 11945 |
|
11839 | | -def test_grants_validation_empty_grantees(): |
11840 | | - model = create_sql_model( |
| 11946 | + expressions3 = d.parse(""" |
| 11947 | + MODEL (name test.bad3, kind FULL, grants ('select' = ['user', @VAR('undefined')])); |
| 11948 | + SELECT 1 as id |
| 11949 | + """) |
| 11950 | + with pytest.raises(ConfigError, match=r"Invalid grants configuration for 'select': NULL value"): |
| 11951 | + load_sql_based_model(expressions3) |
| 11952 | + |
| 11953 | + |
| 11954 | +def test_grants_mixed_types_conversion(): |
| 11955 | + expressions = d.parse(""" |
| 11956 | + MODEL ( |
| 11957 | + name test.mixed_types, |
| 11958 | + kind FULL, |
| 11959 | + grants ( |
| 11960 | + 'select' = ['user1', 123, admin_role, 'user2'] |
| 11961 | + ) |
| 11962 | + ); |
| 11963 | + SELECT 1 as id |
| 11964 | + """) |
| 11965 | + model = load_sql_based_model(expressions) |
| 11966 | + assert model.grants == {"select": ["user1", "123", "admin_role", "user2"]} |
| 11967 | + |
| 11968 | + |
| 11969 | +def test_grants_empty_values(): |
| 11970 | + model1 = create_sql_model( |
11841 | 11971 | "db.table", parse_one("SELECT 1 AS id"), kind="FULL", grants={"select": []} |
11842 | 11972 | ) |
11843 | | - assert model.grants == {"select": []} |
| 11973 | + assert model1.grants == {"select": []} |
11844 | 11974 |
|
| 11975 | + model2 = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL") |
| 11976 | + assert model2.grants is None |
11845 | 11977 |
|
11846 | | -def test_grants_table_type_view(): |
11847 | | - model = create_sql_model("test_view", parse_one("SELECT 1 as id"), kind="VIEW") |
11848 | | - assert model.grants_table_type == DataObjectType.VIEW |
11849 | 11978 |
|
| 11979 | +def test_grants_backward_compatibility(): |
11850 | 11980 | model = create_sql_model( |
11851 | | - "test_mv", parse_one("SELECT 1 as id"), kind=ViewKind(materialized=True) |
| 11981 | + "db.table", |
| 11982 | + parse_one("SELECT 1 AS id"), |
| 11983 | + kind="FULL", |
| 11984 | + grants={ |
| 11985 | + "select": ["user1", "user2"], |
| 11986 | + "insert": ["admin"], |
| 11987 | + "roles/bigquery.dataViewer": ["user:data_eng@company.com"], |
| 11988 | + }, |
11852 | 11989 | ) |
11853 | | - assert model.grants_table_type == DataObjectType.MATERIALIZED_VIEW |
11854 | | - |
11855 | | - |
11856 | | -def test_grants_table_type_table(): |
11857 | | - model = create_sql_model("test_table", parse_one("SELECT 1 as id"), kind="FULL") |
11858 | | - assert model.grants_table_type == DataObjectType.TABLE |
| 11990 | + assert model.grants == { |
| 11991 | + "select": ["user1", "user2"], |
| 11992 | + "insert": ["admin"], |
| 11993 | + "roles/bigquery.dataViewer": ["user:data_eng@company.com"], |
| 11994 | + } |
11859 | 11995 |
|
11860 | 11996 |
|
11861 | | -def test_grants_table_type_managed(): |
11862 | | - model = create_sql_model("test_managed", parse_one("SELECT 1 as id"), kind="MANAGED") |
11863 | | - assert model.grants_table_type == DataObjectType.MANAGED_TABLE |
| 11997 | +@pytest.mark.parametrize( |
| 11998 | + "kind, expected", |
| 11999 | + [ |
| 12000 | + ("VIEW", DataObjectType.VIEW), |
| 12001 | + ("FULL", DataObjectType.TABLE), |
| 12002 | + ("MANAGED", DataObjectType.MANAGED_TABLE), |
| 12003 | + (ViewKind(materialized=True), DataObjectType.MATERIALIZED_VIEW), |
| 12004 | + ], |
| 12005 | +) |
| 12006 | +def test_grants_table_type(kind: t.Union[str, _ModelKind], expected: DataObjectType): |
| 12007 | + model = create_sql_model("test_table", parse_one("SELECT 1 as id"), kind=kind) |
| 12008 | + assert model.grants_table_type == expected |
0 commit comments