|
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, DbtNodeInfo |
67 | 67 | from sqlmesh.core.signal import signal |
@@ -11831,90 +11831,235 @@ def my_macro(evaluator): |
11831 | 11831 | assert model.render_query_or_raise().sql() == 'SELECT 3 AS "c"' |
11832 | 11832 |
|
11833 | 11833 |
|
11834 | | -def test_grants_validation_symbolic_model_error(): |
11835 | | - with pytest.raises(ValidationError, match=r".*grants cannot be set for EXTERNAL.*"): |
11836 | | - create_sql_model( |
11837 | | - "db.table", |
11838 | | - parse_one("SELECT 1 AS id"), |
11839 | | - kind="EXTERNAL", |
11840 | | - grants={"select": ["user1", "user2"], "insert": ["admin_user"]}, |
11841 | | - ) |
| 11834 | +@pytest.mark.parametrize( |
| 11835 | + "kind", |
| 11836 | + [ |
| 11837 | + "FULL", |
| 11838 | + "VIEW", |
| 11839 | + SeedKind(path="test.csv"), |
| 11840 | + IncrementalByTimeRangeKind(time_column="ds"), |
| 11841 | + IncrementalByUniqueKeyKind(unique_key="id"), |
| 11842 | + ], |
| 11843 | +) |
| 11844 | +def test_grants_valid_model_kinds(kind: t.Union[str, _ModelKind]): |
| 11845 | + model = create_sql_model( |
| 11846 | + "db.table", |
| 11847 | + parse_one("SELECT 1 AS id"), |
| 11848 | + kind=kind, |
| 11849 | + grants={"select": ["user1", "user2"], "insert": ["admin_user"]}, |
| 11850 | + ) |
| 11851 | + assert model.grants == {"select": ["user1", "user2"], "insert": ["admin_user"]} |
11842 | 11852 |
|
11843 | 11853 |
|
11844 | | -def test_grants_validation_embedded_model_error(): |
11845 | | - with pytest.raises(ValidationError, match=r".*grants cannot be set for EMBEDDED.*"): |
| 11854 | +@pytest.mark.parametrize( |
| 11855 | + "kind", |
| 11856 | + [ |
| 11857 | + "EXTERNAL", |
| 11858 | + "EMBEDDED", |
| 11859 | + ], |
| 11860 | +) |
| 11861 | +def test_grants_invalid_model_kind_errors(kind: str): |
| 11862 | + with pytest.raises(ValidationError, match=rf".*grants cannot be set for {kind}.*"): |
11846 | 11863 | create_sql_model( |
11847 | 11864 | "db.table", |
11848 | 11865 | parse_one("SELECT 1 AS id"), |
11849 | | - kind="EMBEDDED", |
| 11866 | + kind=kind, |
11850 | 11867 | grants={"select": ["user1"], "insert": ["admin_user"]}, |
11851 | 11868 | ) |
11852 | 11869 |
|
11853 | 11870 |
|
11854 | | -def test_grants_validation_valid_seed_model(): |
| 11871 | +def test_grants_validation_no_grants(): |
| 11872 | + model = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL") |
| 11873 | + assert model.grants is None |
| 11874 | + |
| 11875 | + |
| 11876 | +def test_grants_validation_empty_grantees(): |
11855 | 11877 | model = create_sql_model( |
11856 | | - "db.table", |
11857 | | - parse_one("SELECT 1 AS id"), |
11858 | | - kind=SeedKind(path="test.csv"), |
11859 | | - grants={"select": ["user1"], "insert": ["admin_user"]}, |
| 11878 | + "db.table", parse_one("SELECT 1 AS id"), kind="FULL", grants={"select": []} |
11860 | 11879 | ) |
11861 | | - assert model.grants == {"select": ["user1"], "insert": ["admin_user"]} |
| 11880 | + assert model.grants == {"select": []} |
11862 | 11881 |
|
11863 | 11882 |
|
11864 | | -def test_grants_validation_valid_materialized_model(): |
| 11883 | +def test_grants_single_value_conversions(): |
| 11884 | + expressions = d.parse(f""" |
| 11885 | + MODEL ( |
| 11886 | + name test.nested_arrays, |
| 11887 | + kind FULL, |
| 11888 | + grants ( |
| 11889 | + 'select' = "user1", update = user2 |
| 11890 | + ) |
| 11891 | + ); |
| 11892 | + SELECT 1 as id |
| 11893 | + """) |
| 11894 | + model = load_sql_based_model(expressions) |
| 11895 | + assert model.grants == {"select": ["user1"], "update": ["user2"]} |
| 11896 | + |
11865 | 11897 | model = create_sql_model( |
11866 | 11898 | "db.table", |
11867 | 11899 | parse_one("SELECT 1 AS id"), |
11868 | 11900 | kind="FULL", |
11869 | | - grants={"select": ["user1", "user2"], "insert": ["admin_user"]}, |
| 11901 | + grants={"select": "user1", "insert": 123}, |
11870 | 11902 | ) |
11871 | | - assert model.grants == {"select": ["user1", "user2"], "insert": ["admin_user"]} |
| 11903 | + assert model.grants == {"select": ["user1"], "insert": ["123"]} |
11872 | 11904 |
|
11873 | 11905 |
|
11874 | | -def test_grants_validation_valid_view_model(): |
11875 | | - model = create_sql_model( |
11876 | | - "db.table", parse_one("SELECT 1 AS id"), kind="VIEW", grants={"select": ["user1", "user2"]} |
| 11906 | +@pytest.mark.parametrize( |
| 11907 | + "grantees", |
| 11908 | + [ |
| 11909 | + "('user1', ('user2', 'user3'), 'user4')", |
| 11910 | + "('user1', ['user2', 'user3'], user4)", |
| 11911 | + "['user1', ['user2', user3], 'user4']", |
| 11912 | + "[user1, ('user2', \"user3\"), 'user4']", |
| 11913 | + ], |
| 11914 | +) |
| 11915 | +def test_grants_array_flattening(grantees: str): |
| 11916 | + expressions = d.parse(f""" |
| 11917 | + MODEL ( |
| 11918 | + name test.nested_arrays, |
| 11919 | + kind FULL, |
| 11920 | + grants ( |
| 11921 | + 'select' = {grantees} |
| 11922 | + ) |
| 11923 | + ); |
| 11924 | + SELECT 1 as id |
| 11925 | + """) |
| 11926 | + model = load_sql_based_model(expressions) |
| 11927 | + assert model.grants == {"select": ["user1", "user2", "user3", "user4"]} |
| 11928 | + |
| 11929 | + |
| 11930 | +def test_grants_macro_var_resolved(): |
| 11931 | + expressions = d.parse(""" |
| 11932 | + MODEL ( |
| 11933 | + name test.macro_grants, |
| 11934 | + kind FULL, |
| 11935 | + grants ( |
| 11936 | + 'select' = @VAR('readers'), |
| 11937 | + 'insert' = @VAR('writers') |
| 11938 | + ) |
| 11939 | + ); |
| 11940 | + SELECT 1 as id |
| 11941 | + """) |
| 11942 | + model = load_sql_based_model( |
| 11943 | + expressions, variables={"readers": ["user1", "user2"], "writers": "admin"} |
11877 | 11944 | ) |
11878 | | - assert model.grants == {"select": ["user1", "user2"]} |
| 11945 | + assert model.grants == { |
| 11946 | + "select": ["user1", "user2"], |
| 11947 | + "insert": ["admin"], |
| 11948 | + } |
11879 | 11949 |
|
11880 | 11950 |
|
11881 | | -def test_grants_validation_valid_incremental_model(): |
11882 | | - model = create_sql_model( |
11883 | | - "db.table", |
11884 | | - parse_one("SELECT 1 AS id, CURRENT_TIMESTAMP AS ts"), |
11885 | | - kind=IncrementalByTimeRangeKind(time_column="ts"), |
11886 | | - grants={"select": ["user1"], "update": ["admin_user"]}, |
| 11951 | +def test_grants_macro_var_in_array_flattening(): |
| 11952 | + expressions = d.parse(""" |
| 11953 | + MODEL ( |
| 11954 | + name test.macro_in_array, |
| 11955 | + kind FULL, |
| 11956 | + grants ( |
| 11957 | + 'select' = ['user1', @VAR('admins'), 'user3'] |
| 11958 | + ) |
| 11959 | + ); |
| 11960 | + SELECT 1 as id |
| 11961 | + """) |
| 11962 | + |
| 11963 | + model = load_sql_based_model(expressions, variables={"admins": ["admin1", "admin2"]}) |
| 11964 | + assert model.grants == {"select": ["user1", "admin1", "admin2", "user3"]} |
| 11965 | + |
| 11966 | + model2 = load_sql_based_model(expressions, variables={"admins": "super_admin"}) |
| 11967 | + assert model2.grants == {"select": ["user1", "super_admin", "user3"]} |
| 11968 | + |
| 11969 | + |
| 11970 | +def test_grants_dynamic_permission_names(): |
| 11971 | + expressions = d.parse(""" |
| 11972 | + MODEL ( |
| 11973 | + name test.dynamic_keys, |
| 11974 | + kind FULL, |
| 11975 | + grants ( |
| 11976 | + @VAR('read_perm') = ['user1', 'user2'], |
| 11977 | + @VAR('write_perm') = ['admin'] |
| 11978 | + ) |
| 11979 | + ); |
| 11980 | + SELECT 1 as id |
| 11981 | + """) |
| 11982 | + model = load_sql_based_model( |
| 11983 | + expressions, variables={"read_perm": "select", "write_perm": "insert"} |
11887 | 11984 | ) |
11888 | | - assert model.grants == {"select": ["user1"], "update": ["admin_user"]} |
| 11985 | + assert model.grants == {"select": ["user1", "user2"], "insert": ["admin"]} |
11889 | 11986 |
|
11890 | 11987 |
|
11891 | | -def test_grants_validation_no_grants(): |
11892 | | - model = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL") |
11893 | | - assert model.grants is None |
| 11988 | +def test_grants_unresolved_macro_errors(): |
| 11989 | + expressions1 = d.parse(""" |
| 11990 | + MODEL (name test.bad1, kind FULL, grants ('select' = @VAR('undefined'))); |
| 11991 | + SELECT 1 as id |
| 11992 | + """) |
| 11993 | + with pytest.raises(ConfigError, match=r"Invalid grants configuration for 'select': NULL value"): |
| 11994 | + load_sql_based_model(expressions1) |
11894 | 11995 |
|
| 11996 | + expressions2 = d.parse(""" |
| 11997 | + MODEL (name test.bad2, kind FULL, grants (@VAR('undefined') = ['user'])); |
| 11998 | + SELECT 1 as id |
| 11999 | + """) |
| 12000 | + with pytest.raises(ConfigError, match=r"Invalid grants configuration.*NULL value"): |
| 12001 | + load_sql_based_model(expressions2) |
11895 | 12002 |
|
11896 | | -def test_grants_validation_empty_grantees(): |
11897 | | - model = create_sql_model( |
| 12003 | + expressions3 = d.parse(""" |
| 12004 | + MODEL (name test.bad3, kind FULL, grants ('select' = ['user', @VAR('undefined')])); |
| 12005 | + SELECT 1 as id |
| 12006 | + """) |
| 12007 | + with pytest.raises(ConfigError, match=r"Invalid grants configuration for 'select': NULL value"): |
| 12008 | + load_sql_based_model(expressions3) |
| 12009 | + |
| 12010 | + |
| 12011 | +def test_grants_mixed_types_conversion(): |
| 12012 | + expressions = d.parse(""" |
| 12013 | + MODEL ( |
| 12014 | + name test.mixed_types, |
| 12015 | + kind FULL, |
| 12016 | + grants ( |
| 12017 | + 'select' = ['user1', 123, admin_role, 'user2'] |
| 12018 | + ) |
| 12019 | + ); |
| 12020 | + SELECT 1 as id |
| 12021 | + """) |
| 12022 | + model = load_sql_based_model(expressions) |
| 12023 | + assert model.grants == {"select": ["user1", "123", "admin_role", "user2"]} |
| 12024 | + |
| 12025 | + |
| 12026 | +def test_grants_empty_values(): |
| 12027 | + model1 = create_sql_model( |
11898 | 12028 | "db.table", parse_one("SELECT 1 AS id"), kind="FULL", grants={"select": []} |
11899 | 12029 | ) |
11900 | | - assert model.grants == {"select": []} |
| 12030 | + assert model1.grants == {"select": []} |
11901 | 12031 |
|
| 12032 | + model2 = create_sql_model("db.table", parse_one("SELECT 1 AS id"), kind="FULL") |
| 12033 | + assert model2.grants is None |
11902 | 12034 |
|
11903 | | -def test_grants_table_type_view(): |
11904 | | - model = create_sql_model("test_view", parse_one("SELECT 1 as id"), kind="VIEW") |
11905 | | - assert model.grants_table_type == DataObjectType.VIEW |
11906 | 12035 |
|
| 12036 | +def test_grants_backward_compatibility(): |
11907 | 12037 | model = create_sql_model( |
11908 | | - "test_mv", parse_one("SELECT 1 as id"), kind=ViewKind(materialized=True) |
| 12038 | + "db.table", |
| 12039 | + parse_one("SELECT 1 AS id"), |
| 12040 | + kind="FULL", |
| 12041 | + grants={ |
| 12042 | + "select": ["user1", "user2"], |
| 12043 | + "insert": ["admin"], |
| 12044 | + "roles/bigquery.dataViewer": ["user:data_eng@company.com"], |
| 12045 | + }, |
11909 | 12046 | ) |
11910 | | - assert model.grants_table_type == DataObjectType.MATERIALIZED_VIEW |
11911 | | - |
11912 | | - |
11913 | | -def test_grants_table_type_table(): |
11914 | | - model = create_sql_model("test_table", parse_one("SELECT 1 as id"), kind="FULL") |
11915 | | - assert model.grants_table_type == DataObjectType.TABLE |
| 12047 | + assert model.grants == { |
| 12048 | + "select": ["user1", "user2"], |
| 12049 | + "insert": ["admin"], |
| 12050 | + "roles/bigquery.dataViewer": ["user:data_eng@company.com"], |
| 12051 | + } |
11916 | 12052 |
|
11917 | 12053 |
|
11918 | | -def test_grants_table_type_managed(): |
11919 | | - model = create_sql_model("test_managed", parse_one("SELECT 1 as id"), kind="MANAGED") |
11920 | | - assert model.grants_table_type == DataObjectType.MANAGED_TABLE |
| 12054 | +@pytest.mark.parametrize( |
| 12055 | + "kind, expected", |
| 12056 | + [ |
| 12057 | + ("VIEW", DataObjectType.VIEW), |
| 12058 | + ("FULL", DataObjectType.TABLE), |
| 12059 | + ("MANAGED", DataObjectType.MANAGED_TABLE), |
| 12060 | + (ViewKind(materialized=True), DataObjectType.MATERIALIZED_VIEW), |
| 12061 | + ], |
| 12062 | +) |
| 12063 | +def test_grants_table_type(kind: t.Union[str, _ModelKind], expected: DataObjectType): |
| 12064 | + model = create_sql_model("test_table", parse_one("SELECT 1 as id"), kind=kind) |
| 12065 | + assert model.grants_table_type == expected |
0 commit comments