Skip to content

Commit

Permalink
v0.1.2 (#13)
Browse files Browse the repository at this point in the history
* Add PACKAGES POLICY resource

* Cleanup

* debug

* debug

* build

* weird priv issues

* dont permit role switching in spi install

* no roles

* Resolvers, sproc fixes

---------

Co-authored-by: TJ Murphy <[email protected]>
  • Loading branch information
teej and teej authored Jan 30, 2024
1 parent 459d5c4 commit 5ed41c5
Show file tree
Hide file tree
Showing 30 changed files with 704 additions and 170 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,5 @@ cython_debug/
.python-version
.DS_Store
.vscode/
.packages/
.packages/
.build/
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ style:
check: style test

clean:
rm -rf build dist *.egg-info
find . -name "__pycache__" -type d -exec rm -rf {} +
85 changes: 85 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,91 @@ Titan Core simplifies this process with a declarative Python approach. It allows



# Resource support

| Name | Supported | SPI |
|-------------------------------|-----------|-----|
| **Account Resources** | | |
| API Integration |||
| Catalog Integration |||
| Compute Pool |||
| Connection |||
| Database |||
| External Access Integration |||
| External Volume |||
| Network Policy |||
| Notification Integration | WIP ||
| ↪ Email |||
| ↪ AWS |||
| ↪ Azure |||
| ↪ GCP |||
| Resource Monitor |||
| Role |||
| Security Integration |||
| Share |||
| Storage Integration | WIP ||
| ↪ AWS |||
| ↪ Azure |||
| ↪ GCP |||
| User |||
| Warehouse |||
| | | |
| **Database Resources** | | |
| Database Role |||
| Schema |||
| | | |
| **Schema Resources** | | |
| Alert |||
| Dynamic Table |||
| External Function |||
| External Stage |||
| External Table |||
| Failover Group |||
| File Format |||
| ↪ CSV |||
| ↪ JSON |||
| ↪ AVRO |||
| ↪ ORC |||
| ↪ Parquet |||
| Grant | WIP ||
| ↪ Privilege Grant |||
| ↪ Future Grant |||
| Iceberg Table |||
| Image Repository |||
| Internal Stage |||
| Masking Policy |||
| Materialized View |||
| Model |||
| Network Rule |||
| Packages Policy |||
| Password Policy |||
| Pipe |||
| Role Grant |||
| Row Access Policy |||
| Secret |||
| Sequence |||
| Service |||
| Session Policy |||
| Stage |||
| Stored Procedure | WIP ||
| ↪ Java |||
| ↪ Javascript |||
| ↪ Python |||
| ↪ Scala |||
| ↪ SQL |||
| Stream |||
| Streamlit |||
| Table |||
| Tag |||
| Task |||
| User-Defined Function | WIP ||
| ↪ Java |||
| ↪ Javascript |||
| ↪ Python |||
| ↪ Scala |||
| ↪ SQL |||
| View |||



## Examples
Expand Down
1 change: 1 addition & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def cursor(suffix, test_db, marked_for_cleanup):
cur.execute("USE WAREHOUSE CI")
cur.execute(f"USE ROLE {TEST_ROLE}")
yield cur
cur.execute(f"USE ROLE {TEST_ROLE}")
cur.execute(f"USE DATABASE {test_db}")
for res in marked_for_cleanup:
cur.execute(res.drop_sql(if_exists=True))
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ line-length = 120
# addopts = "-n 4"
markers = [
"requires_snowflake: Mark a test as requiring a Snowflake connection.",
"enterprise: Mark a test as an enterprise test."
"enterprise: Mark a test that only works on Enterprise Edition Snowflake.",
"standard: Mark a test that works on Standard Edition Snowflake.",
]
filterwarnings = [
"ignore:.*urllib3.contrib.pyopenssl.*:DeprecationWarning"
Expand Down
2 changes: 1 addition & 1 deletion scripts/install
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ RETURNS OBJECT NOT NULL
LANGUAGE PYTHON
RUNTIME_VERSION = '3.9'
PACKAGES = ('snowflake-snowpark-python', 'inflection', 'pyparsing')
IMPORTS = ('@titan_aws/releases/titan-0.1.1.zip')
IMPORTS = ('@titan_aws/releases/titan-0.1.2.zip')
HANDLER = 'titan.spi.install'
EXECUTE AS CALLER
CALL install()
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name="titan",
version="0.1.1",
version="0.1.2",
description="Snowflake infrastructure as code",
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
Expand Down
18 changes: 18 additions & 0 deletions tests/fixtures/json/packages_policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "EXAMPLE_POLICY",
"language": "PYTHON",
"allowlist": [
"numpy",
"pandas"
],
"blocklist": [
"os",
"sys"
],
"additional_creation_blocklist": [
"exec",
"eval"
],
"comment": "This is an example packages policy.",
"owner": "SYSADMIN"
}
6 changes: 6 additions & 0 deletions tests/fixtures/sql/packages_policy.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE OR REPLACE PACKAGES POLICY example_policy
LANGUAGE PYTHON
ALLOWLIST = ('numpy', 'pandas')
BLOCKLIST = ('os', 'sys')
ADDITIONAL_CREATION_BLOCKLIST = ('exec', 'eval')
COMMENT = 'This is an example packages policy.'
12 changes: 12 additions & 0 deletions tests/integration/data_provider/test_fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,18 @@
"managed_access": False,
},
},
{
"resource_type": ResourceType.SEQUENCE,
"setup_sql": "CREATE SEQUENCE someseq START 1 INCREMENT 2 COMMENT = '+3'",
"teardown_sql": "DROP SEQUENCE IF EXISTS someseq",
"data": {
"name": "SOMESEQ",
"owner": TEST_ROLE,
"start": 1,
"increment": 2,
"comment": "+3",
},
},
{
"resource_type": ResourceType.TABLE,
"setup_sql": "CREATE TABLE sometbl (id INT)",
Expand Down
70 changes: 70 additions & 0 deletions tests/integration/test_blueprint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import pytest

from titan import Blueprint, User, Role, RoleGrant, data_provider
from titan.blueprint import MissingPrivilegeException
from tests.helpers import get_json_fixtures

JSON_FIXTURES = list(get_json_fixtures())


@pytest.fixture(
params=JSON_FIXTURES,
ids=[resource_cls.__name__ for resource_cls, _ in JSON_FIXTURES],
scope="function",
)
def resource(request):
resource_cls, data = request.param
yield resource_cls, data


@pytest.fixture(scope="session")
def user(suffix, cursor, marked_for_cleanup):
user = User(name=f"TEST_USER_{suffix}".upper(), owner="ACCOUNTADMIN")
cursor.execute(user.create_sql())
marked_for_cleanup.append(user)
return user


@pytest.fixture(scope="session")
def role(suffix, cursor, marked_for_cleanup):
role = Role(name=f"TEST_ROLE_{suffix}".upper(), owner="ACCOUNTADMIN")
cursor.execute(role.create_sql())
marked_for_cleanup.append(role)
return role


@pytest.fixture(scope="session")
def noprivs_role(cursor, test_db, marked_for_cleanup):
role = Role(name="NOPRIVS")
cursor.execute(role.create_sql(if_not_exists=True))
cursor.execute(f"GRANT ROLE NOPRIVS TO USER {cursor.connection.user}")
cursor.execute(f"GRANT USAGE ON DATABASE {test_db} TO ROLE NOPRIVS")
cursor.execute(f"GRANT USAGE ON SCHEMA {test_db}.PUBLIC TO ROLE NOPRIVS")
marked_for_cleanup.append(role)
return role.name


@pytest.mark.requires_snowflake
def test_plan(cursor, user, role):
session = cursor.connection
bp = Blueprint(name="test")
role_grant = RoleGrant(role=role, to_user=user)
bp.add(role_grant)
changes = bp.plan(session)
assert len(changes) == 1
bp.apply(session, changes)
role_grant_remote = data_provider.fetch_role_grant(session, role_grant.fqn)
assert role_grant_remote


# noprivs_role is causing issues and breaking other integration tests
# @pytest.mark.requires_snowflake
# def test_privilege_scanning(resource, noprivs_role, cursor, marked_for_cleanup):
# resource_cls, data = resource
# cursor.execute(f"USE ROLE {noprivs_role}")
# bp = Blueprint(name="test", allow_role_switching=False)
# res = resource_cls(**data)
# bp.add(res)
# marked_for_cleanup.append(res)
# with pytest.raises(MissingPrivilegeException):
# bp.apply(cursor.connection)
32 changes: 0 additions & 32 deletions tests/integration/test_plan.py

This file was deleted.

13 changes: 13 additions & 0 deletions tests/integration/test_spi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest

from titan import __version__


@pytest.mark.requires_snowflake
def test_install(suffix, cursor):
install = open("scripts/install", "r").read()
install = install.replace(__version__, f"{__version__}-dev")
cursor.execute("USE ROLE SYSADMIN")
cursor.execute(f"CREATE DATABASE TITAN_SPI_TEST_{suffix}")
cursor.execute(f"CREATE STAGE TITAN_SPI_TEST_{suffix}.PUBLIC.TITAN_AWS URL = 's3://titan-snowflake/';")
cursor.execute(install)
47 changes: 47 additions & 0 deletions tests/test_logical_grant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from titan.logical_grant import And, LogicalGrant, Or


def test_logical_grant_init():
lg = LogicalGrant("urn", "priv")
assert lg.urn == "urn"
assert lg.priv == "priv"


def test_logical_grant_repr():
lg = LogicalGrant("urn", "priv")
assert repr(lg) == "LogicalGrant(urn, priv)"


def test_logical_grant_eq():
lg1 = LogicalGrant("urn", "priv")
lg2 = LogicalGrant("urn", "priv")
assert lg1 == lg2


def test_logical_grant_hash():
lg = LogicalGrant("urn", "priv")
assert hash(lg) == hash(("urn", "priv"))


def test_logical_grant_or():
lg1 = LogicalGrant("urn1", "priv1")
lg2 = LogicalGrant("urn2", "priv2")
lg3 = LogicalGrant("urn3", "priv3")
result = lg1 | lg2
assert isinstance(result, Or)
assert result.args == (lg1, lg2)
result = result | lg3
assert isinstance(result, Or)
assert result.args == (lg1, lg2, lg3)


def test_logical_grant_and():
lg1 = LogicalGrant("urn1", "priv1")
lg2 = LogicalGrant("urn2", "priv2")
lg3 = LogicalGrant("urn3", "priv3")
result = lg1 & lg2
assert isinstance(result, And)
assert result.args == (lg1, lg2)
result = result & lg3
assert isinstance(result, And)
assert result.args == (lg1, lg2, lg3)
2 changes: 1 addition & 1 deletion titan/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"Warehouse",
]

__version__ = "0.1.1"
__version__ = "0.1.2"

LOGO = r"""
__ _ __
Expand Down
Loading

0 comments on commit 5ed41c5

Please sign in to comment.