Skip to content

Commit

Permalink
Revert "SNOW-1544013 Fetch events for app" (#1361)
Browse files Browse the repository at this point in the history
Revert "SNOW-1544013 Fetch events for app (#1352)"

This reverts commit 7be4040.
  • Loading branch information
sfc-gh-fcampbell authored Jul 24, 2024
1 parent 7be4040 commit 76da3e3
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 117 deletions.
21 changes: 1 addition & 20 deletions src/snowflake/cli/plugins/nativeapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
CommandResult,
MessageResult,
ObjectResult,
StreamResult,
)
from snowflake.cli.api.project.project_verification import assert_project_type
from snowflake.cli.api.secure_path import SecurePath
Expand Down Expand Up @@ -378,6 +377,7 @@ def app_validate(**options):
@nativeapp_definition_v2_to_v1
def app_events(**options):
"""Fetches events for this app from the event table configured in Snowflake."""
# WIP: only validates event table setup for now while the command is hidden
assert_project_type("native_app")

manager = NativeAppManager(
Expand All @@ -387,22 +387,3 @@ def app_events(**options):
events = manager.get_events()
if not events:
return MessageResult("No events found.")

def g():
for event in events:
yield EventResult(event)

return StreamResult(g())


class EventResult(ObjectResult, MessageResult):
"""ObjectResult that renders as a custom string when not printed as JSON."""

@property
def message(self):
e = self._element
return f"{e['TIMESTAMP']} {e['VALUE']}"

@property
def result(self):
return self._element
25 changes: 6 additions & 19 deletions src/snowflake/cli/plugins/nativeapp/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from functools import cached_property
from pathlib import Path
from textwrap import dedent
from typing import Any, List, NoReturn, Optional, TypedDict
from typing import Any, List, Optional, TypedDict

import jinja2
from click import ClickException
Expand Down Expand Up @@ -89,7 +89,7 @@

def generic_sql_error_handler(
err: ProgrammingError, role: Optional[str] = None, warehouse: Optional[str] = None
) -> NoReturn:
):
# Potential refactor: If moving away from Python 3.8 and 3.9 to >= 3.10, use match ... case
if err.errno == DOES_NOT_EXIST_OR_CANNOT_BE_PERFORMED:
raise ProgrammingError(
Expand Down Expand Up @@ -315,10 +315,10 @@ def get_app_pkg_distribution_in_snowflake(self) -> str:
)

@cached_property
def account_event_table(self) -> str:
def account_event_table(self) -> str | None:
query = "show parameters like 'event_table' in account"
results = self._execute_query(query, cursor_class=DictCursor)
return next((r["value"] for r in results if r["key"] == "EVENT_TABLE"), "")
return next((r["value"] for r in results if r["key"] == "EVENT_TABLE"), None)

def verify_project_distribution(
self, expected_distribution: Optional[str] = None
Expand Down Expand Up @@ -715,22 +715,9 @@ def get_validation_result(self, use_scratch_stage: bool):
)

def get_events(self) -> list[dict]:
if not self.account_event_table:
if self.account_event_table is None:
raise NoEventTableForAccount()

# resource_attributes:"snow.database.name" uses the unquoted/uppercase app name
app_name = unquote_identifier(self.app_name)
query = dedent(
f"""\
select timestamp, value::varchar value
from {self.account_event_table}
where resource_attributes:"snow.database.name" = '{app_name}'
order by timestamp asc;"""
)
try:
return self._execute_query(query, cursor_class=DictCursor).fetchall()
except ProgrammingError as err:
generic_sql_error_handler(err)
return []


def _validation_item_to_str(item: dict[str, str | int]):
Expand Down
76 changes: 3 additions & 73 deletions tests/nativeapp/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
NATIVEAPP_MODULE,
mock_execute_helper,
mock_snowflake_yml_file,
quoted_override_yml_file,
touch,
)
from tests.testing_utils.files_and_dirs import create_named_file
Expand Down Expand Up @@ -1350,92 +1349,23 @@ def test_account_event_table_not_set_up(mock_execute, temp_dir, mock_cursor):
mock_execute.side_effect = side_effects

native_app_manager = _get_na_manager()
assert native_app_manager.account_event_table == ""
assert native_app_manager.account_event_table is None


@mock.patch(
NATIVEAPP_MANAGER_ACCOUNT_EVENT_TABLE,
return_value="db.schema.event_table",
new_callable=mock.PropertyMock,
)
@mock.patch(NATIVEAPP_MANAGER_EXECUTE)
def test_get_events(mock_execute, mock_account_event_table, temp_dir, mock_cursor):
def test_get_events(mock_account_event_table, temp_dir, mock_cursor):
create_named_file(
file_name="snowflake.yml",
dir_name=temp_dir,
contents=[mock_snowflake_yml_file],
)

side_effects, expected = mock_execute_helper(
[
(
mock_cursor([dict(TIMESTAMP="2020-01-01T00:00:00Z", VALUE="test")], []),
mock.call(
dedent(
f"""\
select timestamp, value::varchar value
from db.schema.event_table
where resource_attributes:"snow.database.name" = 'MYAPP'
order by timestamp asc;"""
),
cursor_class=DictCursor,
),
),
]
)
mock_execute.side_effect = side_effects

native_app_manager = _get_na_manager()
assert native_app_manager.get_events() == [
dict(TIMESTAMP="2020-01-01T00:00:00Z", VALUE="test")
]
assert mock_execute.mock_calls == expected


@mock.patch(
NATIVEAPP_MANAGER_ACCOUNT_EVENT_TABLE,
return_value="db.schema.event_table",
new_callable=mock.PropertyMock,
)
@mock.patch(NATIVEAPP_MANAGER_EXECUTE)
def test_get_events_quoted_app_name(
mock_execute, mock_account_event_table, temp_dir, mock_cursor
):
create_named_file(
file_name="snowflake.yml",
dir_name=temp_dir,
contents=[mock_snowflake_yml_file],
)
create_named_file(
file_name="snowflake.local.yml",
dir_name=temp_dir,
contents=[quoted_override_yml_file],
)

side_effects, expected = mock_execute_helper(
[
(
mock_cursor([dict(TIMESTAMP="2020-01-01T00:00:00Z", VALUE="test")], []),
mock.call(
dedent(
f"""\
select timestamp, value::varchar value
from db.schema.event_table
where resource_attributes:"snow.database.name" = 'My Application'
order by timestamp asc;"""
),
cursor_class=DictCursor,
),
),
]
)
mock_execute.side_effect = side_effects

native_app_manager = _get_na_manager()
assert native_app_manager.get_events() == [
dict(TIMESTAMP="2020-01-01T00:00:00Z", VALUE="test")
]
assert mock_execute.mock_calls == expected
assert native_app_manager.get_events() == []


@mock.patch(
Expand Down
9 changes: 4 additions & 5 deletions tests_integration/nativeapp/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@


@pytest.mark.integration
def test_app_events_no_event_table(runner, temporary_working_directory):
def test_app_events(runner, temporary_working_directory):
project_name = "myapp"
result = runner.invoke_json(
["app", "init", project_name],
Expand All @@ -36,11 +36,10 @@ def test_app_events_no_event_table(runner, temporary_working_directory):
assert result.exit_code == 0, result.output

with pushd(Path(os.getcwd(), project_name)):
# The integration test account doesn't have an event table set up
# but this test is still useful to validate the negative case
# validate the account's event table
result = runner.invoke_with_connection(
["app", "events"],
env=TEST_ENV,
)
assert result.exit_code == 1, result.output
assert "No event table was found for this Snowflake account." in result.output
assert result.exit_code == 0, result.output
assert "No events found." in result.output

0 comments on commit 76da3e3

Please sign in to comment.