Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-1643309 Add snow ws version list command #1574

Merged
merged 5 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 6 additions & 13 deletions src/snowflake/cli/_plugins/nativeapp/run_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@
from snowflake.cli.api.entities.application_entity import (
ApplicationEntity,
)
from snowflake.cli.api.entities.application_package_entity import (
ApplicationPackageEntity,
)
from snowflake.cli.api.entities.utils import (
generic_sql_error_handler,
)
from snowflake.cli.api.errno import (
APPLICATION_NO_LONGER_AVAILABLE,
APPLICATION_OWNS_EXTERNAL_OBJECTS,
)
from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
from snowflake.cli.api.project.schemas.native_app.native_app import NativeApp
from snowflake.connector import ProgrammingError
from snowflake.connector.cursor import SnowflakeCursor
Expand All @@ -49,18 +51,9 @@ def __init__(self, project_definition: NativeApp, project_root: Path):
super().__init__(project_definition, project_root)

def get_all_existing_versions(self) -> SnowflakeCursor:
"""
Get all existing versions, if defined, for an application package.
It executes a 'show versions in application package' query and returns all the results.
"""
with self.use_role(self.package_role):
show_obj_query = f"show versions in application package {self.package_name}"
show_obj_cursor = self._execute_query(show_obj_query)

if show_obj_cursor.rowcount is None:
raise SnowflakeSQLExecutionError(show_obj_query)

return show_obj_cursor
return ApplicationPackageEntity.version_list(
self.package_name, self.package_role
)

def get_existing_version_info(self, version: str) -> Optional[dict]:
return ApplicationEntity.get_existing_version_info(
Expand Down
34 changes: 31 additions & 3 deletions src/snowflake/cli/_plugins/workspace/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@
from snowflake.cli._plugins.workspace.manager import WorkspaceManager
from snowflake.cli.api.cli_global_context import get_cli_context
from snowflake.cli.api.commands.decorators import with_project_definition
from snowflake.cli.api.commands.snow_typer import SnowTyper
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
from snowflake.cli.api.entities.common import EntityActions
from snowflake.cli.api.exceptions import IncompatibleParametersError
from snowflake.cli.api.output.types import MessageResult
from snowflake.cli.api.output.types import MessageResult, QueryResult
from snowflake.cli.api.project.definition_conversion import (
convert_project_definition_to_v2,
)
from snowflake.cli.api.project.definition_manager import DefinitionManager
from snowflake.cli.api.secure_path import SecurePath

ws = SnowTyper(
ws = SnowTyperFactory(
name="ws",
help="Deploy and interact with snowflake.yml-based entities.",
)
Expand Down Expand Up @@ -224,3 +224,31 @@ def validate(
entity_id,
EntityActions.VALIDATE,
)


version = SnowTyperFactory(
name="version",
help="Manages versions for project entities.",
sfc-gh-gbloom marked this conversation as resolved.
Show resolved Hide resolved
)
ws.add_typer(version)


@version.command(name="list", requires_connection=True, hidden=True)
@with_project_definition()
def version_list(
entity_id: str = typer.Option(
help="The ID of the entity you want to list versions for.",
),
**options,
):
"""Lists the versions of the specified entity."""
cli_context = get_cli_context()
ws = WorkspaceManager(
project_definition=cli_context.project_definition,
project_root=cli_context.project_root,
)
cursor = ws.perform_action(
entity_id,
EntityActions.VERSION_LIST,
)
return QueryResult(cursor)
2 changes: 1 addition & 1 deletion src/snowflake/cli/_plugins/workspace/plugin_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ def command_spec():
return CommandSpec(
parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
command_type=CommandType.COMMAND_GROUP,
typer_instance=commands.ws,
typer_instance=commands.ws.create_instance(),
)
27 changes: 26 additions & 1 deletion src/snowflake/cli/api/entities/application_package_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
get_basic_jinja_env,
)
from snowflake.connector import ProgrammingError
from snowflake.connector.cursor import DictCursor
from snowflake.connector.cursor import DictCursor, SnowflakeCursor


class ApplicationPackageEntity(EntityBase[ApplicationPackageEntityModel]):
Expand Down Expand Up @@ -155,6 +155,15 @@ def deploy_to_scratch_stage_fn():
)
ctx.console.message("Setup script is valid")

def action_version_list(
self, ctx: ActionContext, *args, **kwargs
) -> SnowflakeCursor:
model = self._entity_model
return self.version_list(
package_name=model.fqn.identifier,
package_role=(model.meta and model.meta.role) or ctx.default_role,
)

@staticmethod
def bundle(
project_root: Path,
Expand Down Expand Up @@ -266,6 +275,22 @@ def deploy(

return diff

@staticmethod
def version_list(package_name: str, package_role: str) -> SnowflakeCursor:
"""
Get all existing versions, if defined, for an application package.
It executes a 'show versions in application package' query and returns all the results.
"""
sql_executor = get_sql_executor()
with sql_executor.use_role(package_role):
show_obj_query = f"show versions in application package {package_name}"
show_obj_cursor = sql_executor.execute_query(show_obj_query)

if show_obj_cursor.rowcount is None:
raise SnowflakeSQLExecutionError(show_obj_query)

return show_obj_cursor

@staticmethod
def get_existing_app_pkg_info(
package_name: str,
Expand Down
2 changes: 2 additions & 0 deletions src/snowflake/cli/api/entities/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class EntityActions(str, Enum):
DROP = "action_drop"
VALIDATE = "action_validate"

VERSION_LIST = "action_version_list"


T = TypeVar("T")

Expand Down
23 changes: 23 additions & 0 deletions tests/workspace/test_application_package_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,26 @@ def test_deploy(
package_warehouse="wh",
)
assert mock_execute.mock_calls == expected


@mock.patch(SQL_EXECUTOR_EXECUTE)
def test_version_list(mock_execute, mock_cursor):
package_role = "package_role"
package_name = "test_pkg"
side_effects, expected = mock_execute_helper(
[
(
mock_cursor([{"CURRENT_ROLE()": "old_role"}], []),
mock.call("select current_role()", cursor_class=DictCursor),
),
(None, mock.call(f"use role {package_role}")),
(
mock_cursor([], []),
mock.call(f"show versions in application package {package_name}"),
),
(None, mock.call("use role old_role")),
]
)
mock_execute.side_effect = side_effects
ApplicationPackageEntity.version_list(package_name, package_role)
assert mock_execute.mock_calls == expected
62 changes: 44 additions & 18 deletions tests_integration/nativeapp/__snapshots__/test_version.ambr
Original file line number Diff line number Diff line change
@@ -1,52 +1,78 @@
# serializer version: 1
# name: test_nativeapp_version_create_package_no_magic_comment[integration]
# name: test_nativeapp_version_create_package_no_magic_comment[app version list-napp_init_v1]
list([
dict({
'comment': 'Default version used for development. Override for actual deployment.',
'comment': None,
'dropped_on': None,
'label': 'Dev Version',
'log_level': 'INFO',
'label': None,
'log_level': 'OFF',
'patch': 0,
'review_status': 'NOT_REVIEWED',
'state': 'READY',
'trace_level': 'ALWAYS',
'trace_level': 'OFF',
'version': 'V1',
}),
dict({
'comment': 'Default version used for development. Override for actual deployment.',
'comment': None,
'dropped_on': None,
'label': 'Dev Version',
'log_level': 'INFO',
'label': None,
'log_level': 'OFF',
'patch': 1,
'review_status': 'NOT_REVIEWED',
'state': 'READY',
'trace_level': 'ALWAYS',
'trace_level': 'OFF',
'version': 'V1',
}),
])
# ---
# name: test_nativeapp_version_create_package_no_magic_comment[integration_v2]
# name: test_nativeapp_version_create_package_no_magic_comment[app version list-napp_init_v2]
list([
dict({
'comment': 'Default version used for development. Override for actual deployment.',
'comment': None,
'dropped_on': None,
'label': 'Dev Version',
'log_level': 'INFO',
'label': None,
'log_level': 'OFF',
'patch': 0,
'review_status': 'NOT_REVIEWED',
'state': 'READY',
'trace_level': 'ALWAYS',
'trace_level': 'OFF',
'version': 'V1',
}),
dict({
'comment': 'Default version used for development. Override for actual deployment.',
'comment': None,
'dropped_on': None,
'label': 'Dev Version',
'log_level': 'INFO',
'label': None,
'log_level': 'OFF',
'patch': 1,
'review_status': 'NOT_REVIEWED',
'state': 'READY',
'trace_level': 'ALWAYS',
'trace_level': 'OFF',
'version': 'V1',
}),
])
# ---
# name: test_nativeapp_version_create_package_no_magic_comment[ws version list --entity-id=pkg-napp_init_v2]
list([
dict({
'comment': None,
'dropped_on': None,
'label': None,
'log_level': 'OFF',
'patch': 0,
'review_status': 'NOT_REVIEWED',
'state': 'READY',
'trace_level': 'OFF',
'version': 'V1',
}),
dict({
'comment': None,
'dropped_on': None,
'label': None,
'log_level': 'OFF',
'patch': 1,
'review_status': 'NOT_REVIEWED',
'state': 'READY',
'trace_level': 'OFF',
'version': 'V1',
}),
])
Expand Down
Loading
Loading