Skip to content

Commit

Permalink
refactor post deploy hooks to use sql facade and clean up tests with …
Browse files Browse the repository at this point in the history
…factories (#1804)

* refactor post deploy hooks to use sql facade and clean up tests with factories

* Create shortcut properties for entity model fields (#1805)

Adds properties to the native app entities to make usage of model fields a bit simpler and safer (especially the derived ones like paths).

For example, to get the package name, we can call `self.name` instead of `self._entity_model.fqn.name`.

* mock sqlfacade instead of executor

---------

Co-authored-by: Francois Campbell <francois.campbell@snowflake.com>
  • Loading branch information
sfc-gh-mchok and sfc-gh-fcampbell authored Oct 29, 2024
1 parent d02c05d commit 35abf56
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 439 deletions.
24 changes: 8 additions & 16 deletions src/snowflake/cli/_plugins/nativeapp/entities/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
from snowflake.cli._plugins.nativeapp.sf_facade import get_snowflake_facade
from snowflake.cli._plugins.nativeapp.utils import needs_confirmation
from snowflake.cli._plugins.workspace.context import ActionContext
from snowflake.cli.api.cli_global_context import get_cli_context
from snowflake.cli.api.entities.common import EntityBase, get_sql_executor
from snowflake.cli.api.entities.utils import (
drop_generic_object,
Expand All @@ -60,7 +59,6 @@
NOT_SUPPORTED_ON_DEV_MODE_APPLICATIONS,
ONLY_SUPPORTED_ON_DEV_MODE_APPLICATIONS,
)
from snowflake.cli.api.metrics import CLICounterField
from snowflake.cli.api.project.schemas.entities.common import (
EntityModelBase,
Identifier,
Expand Down Expand Up @@ -538,22 +536,16 @@ def create_or_upgrade_app(
generic_sql_error_handler(err)

def execute_post_deploy_hooks(self):
console = self._workspace_ctx.console

get_cli_context().metrics.set_counter_default(
CLICounterField.POST_DEPLOY_SCRIPTS, 0
execute_post_deploy_hooks(
console=self._workspace_ctx.console,
project_root=self.project_root,
post_deploy_hooks=self.post_deploy_hooks,
deployed_object_type="application",
role_name=self.role,
warehouse_name=self.warehouse,
database_name=self.name,
)

if self.post_deploy_hooks:
with self.use_application_warehouse():
execute_post_deploy_hooks(
console=console,
project_root=self.project_root,
post_deploy_hooks=self.post_deploy_hooks,
deployed_object_type="application",
database_name=self.name,
)

@contextmanager
def use_application_warehouse(self):
if self.warehouse:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

import json
from contextlib import contextmanager
from pathlib import Path
from textwrap import dedent
from typing import List, Literal, Optional, Union
Expand Down Expand Up @@ -44,7 +43,6 @@
from snowflake.cli._plugins.stage.diff import DiffResult
from snowflake.cli._plugins.stage.manager import StageManager
from snowflake.cli._plugins.workspace.context import ActionContext
from snowflake.cli.api.cli_global_context import get_cli_context
from snowflake.cli.api.entities.common import EntityBase, get_sql_executor
from snowflake.cli.api.entities.utils import (
drop_generic_object,
Expand All @@ -55,7 +53,6 @@
)
from snowflake.cli.api.errno import DOES_NOT_EXIST_OR_NOT_AUTHORIZED
from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
from snowflake.cli.api.metrics import CLICounterField
from snowflake.cli.api.project.schemas.entities.common import (
EntityModelBase,
Identifier,
Expand Down Expand Up @@ -604,8 +601,8 @@ def _deploy(
print_diff=print_diff,
)

if run_post_deploy_hooks:
self.execute_post_deploy_hooks()
if run_post_deploy_hooks:
self.execute_post_deploy_hooks()

if validate:
self.validate_setup_script(
Expand Down Expand Up @@ -836,21 +833,6 @@ def verify_project_distribution(
return False
return True

@contextmanager
def use_package_warehouse(self):
if self.warehouse:
with get_sql_executor().use_warehouse(self.warehouse):
yield
else:
raise ClickException(
dedent(
f"""\
Application package warehouse cannot be empty.
Please provide a value for it in your connection information or your project definition file.
"""
)
)

def create_app_package(self) -> None:
"""
Creates the application package with our up-to-date stage if none exists.
Expand Down Expand Up @@ -895,22 +877,16 @@ def create_app_package(self) -> None:
)

def execute_post_deploy_hooks(self):
console = self._workspace_ctx.console

get_cli_context().metrics.set_counter_default(
CLICounterField.POST_DEPLOY_SCRIPTS, 0
execute_post_deploy_hooks(
console=self._workspace_ctx.console,
project_root=self.project_root,
post_deploy_hooks=self.post_deploy_hooks,
deployed_object_type="application package",
role_name=self.role,
warehouse_name=self.warehouse,
database_name=self.name,
)

if self.post_deploy_hooks:
with self.use_package_warehouse():
execute_post_deploy_hooks(
console=console,
project_root=self.project_root,
post_deploy_hooks=self.post_deploy_hooks,
deployed_object_type="application package",
database_name=self.name,
)

def validate_setup_script(
self, use_scratch_stage: bool, interactive: bool, force: bool
):
Expand Down
36 changes: 15 additions & 21 deletions src/snowflake/cli/api/entities/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
InvalidTemplateInFileError,
MissingScriptError,
)
from snowflake.cli._plugins.nativeapp.sf_facade import get_snowflake_facade
from snowflake.cli._plugins.nativeapp.utils import verify_exists, verify_no_directories
from snowflake.cli._plugins.stage.diff import (
DiffResult,
Expand Down Expand Up @@ -195,36 +196,24 @@ def sync_deploy_root_with_stage(
return diff


def _execute_sql_script(
script_content: str,
database_name: Optional[str] = None,
) -> None:
"""
Executing the provided SQL script content.
This assumes that a relevant warehouse is already active.
If database_name is passed in, it will be used first.
"""
try:
sql_executor = get_sql_executor()
if database_name is not None:
sql_executor.execute_query(f"use database {database_name}")
sql_executor.execute_queries(script_content)
except ProgrammingError as err:
generic_sql_error_handler(err)


def execute_post_deploy_hooks(
console: AbstractConsole,
project_root: Path,
post_deploy_hooks: Optional[List[PostDeployHook]],
deployed_object_type: str,
role_name: str,
database_name: str,
warehouse_name: str,
) -> None:
"""
Executes post-deploy hooks for the given object type.
While executing SQL post deploy hooks, it first switches to the database provided in the input.
All post deploy scripts templates will first be expanded using the global template context.
"""
get_cli_context().metrics.set_counter_default(
CLICounterField.POST_DEPLOY_SCRIPTS, 0
)

if not post_deploy_hooks:
return

Expand All @@ -248,11 +237,16 @@ def execute_post_deploy_hooks(
sql_scripts_paths,
)

sql_facade = get_snowflake_facade()

for index, sql_script_path in enumerate(display_paths):
console.step(f"Executing SQL script: {sql_script_path}")
_execute_sql_script(
script_content=scripts_content_list[index],
database_name=database_name,
sql_facade.execute_user_script(
queries=scripts_content_list[index],
script_name=sql_script_path,
role=role_name,
warehouse=warehouse_name,
database=database_name,
)


Expand Down
Loading

0 comments on commit 35abf56

Please sign in to comment.