Skip to content

Commit

Permalink
SNOW-1653357 Use ApplicationPackageEntity.deploy for both PDF versions (
Browse files Browse the repository at this point in the history
#1571)

Extracts `ApplicationPackageEntity.action_deploy()` into a method that can also be called from `NativeAppManager.deploy()`.
  • Loading branch information
sfc-gh-fcampbell authored Sep 13, 2024
1 parent e4a7a13 commit 2db6075
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 137 deletions.
49 changes: 20 additions & 29 deletions src/snowflake/cli/_plugins/nativeapp/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,35 +325,26 @@ def deploy(
validate: bool = True,
print_diff: bool = True,
) -> DiffResult:
"""app deploy process"""

# 1. Create an empty application package, if none exists
self.create_app_package()

with self.use_role(self.package_role):
# 2. now that the application package exists, create shared data
self._apply_package_scripts()

# 3. Upload files from deploy root local folder to the above stage
stage_fqn = stage_fqn or self.stage_fqn
diff = self.sync_deploy_root_with_stage(
bundle_map=bundle_map,
role=self.package_role,
prune=prune,
recursive=recursive,
stage_fqn=stage_fqn,
local_paths_to_sync=local_paths_to_sync,
print_diff=print_diff,
)

# 4. Execute post-deploy hooks
with self.use_package_warehouse():
self.execute_package_post_deploy_hooks()

if validate:
self.validate(use_scratch_stage=False)

return diff
return ApplicationPackageEntity.deploy(
console=cc,
project_root=self.project_root,
deploy_root=self.deploy_root,
bundle_root=self.bundle_root,
generated_root=self.generated_root,
artifacts=self.artifacts,
package_name=self.package_name,
package_role=self.package_role,
package_distribution=self.package_distribution,
prune=prune,
recursive=recursive,
paths=local_paths_to_sync,
print_diff=print_diff,
validate=validate,
stage_fqn=stage_fqn or self.stage_fqn,
package_warehouse=self.package_warehouse,
post_deploy_hooks=self.package_post_deploy_hooks,
package_scripts=self.package_scripts,
)

def deploy_to_scratch_stage_fn(self):
bundle_map = self.build_bundle()
Expand Down
158 changes: 108 additions & 50 deletions src/snowflake/cli/api/entities/application_package_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from snowflake.cli._plugins.nativeapp.utils import (
needs_confirmation,
)
from snowflake.cli._plugins.stage.diff import DiffResult
from snowflake.cli._plugins.stage.manager import StageManager
from snowflake.cli._plugins.workspace.action_context import ActionContext
from snowflake.cli.api.console.abc import AbstractConsole
Expand Down Expand Up @@ -86,61 +87,29 @@ def action_deploy(
):
model = self._entity_model
package_name = model.fqn.identifier
if model.meta and model.meta.role:
package_role = model.meta.role
else:
package_role = ctx.default_role

# 1. Create a bundle
bundle_map = self.action_bundle(ctx)

# 2. Create an empty application package, if none exists
self.create_app_package(
return self.deploy(
console=ctx.console,
project_root=ctx.project_root,
deploy_root=Path(model.deploy_root),
bundle_root=Path(model.bundle_root),
generated_root=Path(model.generated_root),
artifacts=model.artifacts,
package_name=package_name,
package_role=package_role,
package_role=(model.meta and model.meta.role) or ctx.default_role,
package_distribution=model.distribution,
prune=prune,
recursive=recursive,
paths=paths,
print_diff=True,
validate=validate,
stage_fqn=stage_fqn or f"{package_name}.{model.stage}",
package_warehouse=(
(model.meta and model.meta.warehouse) or ctx.default_warehouse
),
post_deploy_hooks=model.meta and model.meta.post_deploy,
package_scripts=[], # Package scripts are not supported in PDFv2
)

with get_sql_executor().use_role(package_role):
# 3. Upload files from deploy root local folder to the above stage
if not stage_fqn:
stage_fqn = f"{package_name}.{model.stage}"
stage_schema = extract_schema(stage_fqn)
sync_deploy_root_with_stage(
console=ctx.console,
deploy_root=Path(model.deploy_root),
package_name=package_name,
stage_schema=stage_schema,
bundle_map=bundle_map,
role=package_role,
prune=prune,
recursive=recursive,
stage_fqn=stage_fqn,
local_paths_to_sync=paths,
print_diff=True,
)

if model.meta and model.meta.post_deploy:
self.execute_post_deploy_hooks(
console=ctx.console,
project_root=ctx.project_root,
post_deploy_hooks=model.meta.post_deploy,
package_name=package_name,
package_warehouse=model.meta.warehouse or ctx.default_warehouse,
)

if validate:
self.validate_setup_script(
console=ctx.console,
package_name=package_name,
package_role=package_role,
stage_fqn=stage_fqn,
use_scratch_stage=False,
scratch_stage_fqn="",
deploy_to_scratch_stage_fn=lambda *args: None,
)

def action_drop(self, ctx: ActionContext, force_drop: bool, *args, **kwargs):
model = self._entity_model
package_name = model.fqn.identifier
Expand Down Expand Up @@ -208,6 +177,95 @@ def bundle(
compiler.compile_artifacts()
return bundle_map

@classmethod
def deploy(
cls,
console: AbstractConsole,
project_root: Path,
deploy_root: Path,
bundle_root: Path,
generated_root: Path,
artifacts: list[PathMapping],
package_name: str,
package_role: str,
package_distribution: str,
package_warehouse: str | None,
prune: bool,
recursive: bool,
paths: List[Path],
print_diff: bool,
validate: bool,
stage_fqn: str,
post_deploy_hooks: list[PostDeployHook] | None,
package_scripts: List[str],
) -> DiffResult:
# 1. Create a bundle
bundle_map = cls.bundle(
project_root=project_root,
deploy_root=deploy_root,
bundle_root=bundle_root,
generated_root=generated_root,
artifacts=artifacts,
package_name=package_name,
)

# 2. Create an empty application package, if none exists
cls.create_app_package(
console=console,
package_name=package_name,
package_role=package_role,
package_distribution=package_distribution,
)

with get_sql_executor().use_role(package_role):
if package_scripts:
cls.apply_package_scripts(
console=console,
package_scripts=package_scripts,
package_warehouse=package_warehouse,
project_root=project_root,
package_role=package_role,
package_name=package_name,
)

# 3. Upload files from deploy root local folder to the above stage
stage_schema = extract_schema(stage_fqn)
diff = sync_deploy_root_with_stage(
console=console,
deploy_root=deploy_root,
package_name=package_name,
stage_schema=stage_schema,
bundle_map=bundle_map,
role=package_role,
prune=prune,
recursive=recursive,
stage_fqn=stage_fqn,
local_paths_to_sync=paths,
print_diff=print_diff,
)

if post_deploy_hooks:
cls.execute_post_deploy_hooks(
console=console,
project_root=project_root,
post_deploy_hooks=post_deploy_hooks,
package_name=package_name,
package_warehouse=package_warehouse,
)

if validate:
cls.validate_setup_script(
console=console,
package_name=package_name,
package_role=package_role,
stage_fqn=stage_fqn,
use_scratch_stage=False,
scratch_stage_fqn="",
deploy_to_scratch_stage_fn=lambda *args: None,
)

return diff

@staticmethod
def get_existing_app_pkg_info(
package_name: str,
Expand Down
58 changes: 0 additions & 58 deletions tests/nativeapp/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1701,61 +1701,3 @@ def test_stream_events(mock_execute, mock_account_event_table, temp_dir, mock_cu
pass
else:
pytest.fail("stream_events didn't end when receiving a KeyboardInterrupt")


@mock.patch.object(NativeAppManager, "validate")
@mock.patch.object(NativeAppManager, "execute_package_post_deploy_hooks")
@mock.patch.object(NativeAppManager, "sync_deploy_root_with_stage")
@mock.patch.object(NativeAppManager, "_apply_package_scripts")
@mock.patch.object(NativeAppManager, "create_app_package")
@mock.patch.object(NativeAppManager, "use_role")
@mock.patch.object(NativeAppManager, "use_package_warehouse")
def test_deploy_with_package_post_deploy_hook(
mock_use_package_warehouse,
mock_use_role,
mock_create_app_package,
mock_apply_package_scripts,
mock_sync_deploy_root_with_stage,
mock_execute_package_post_deploy_hooks,
mock_validate,
temp_dir,
):
# Setup
mock_diff_result = DiffResult(different=[StagePath("setup.sql")])
mock_sync_deploy_root_with_stage.return_value = mock_diff_result

current_working_directory = os.getcwd()
create_named_file(
file_name="snowflake.yml",
dir_name=current_working_directory,
contents=[mock_snowflake_yml_file],
)

# Create NativeAppManager instance
manager = _get_na_manager(temp_dir)

mock_bundle_map = mock.Mock(spec=BundleMap)
# Test with default parameters
result = manager.deploy(
bundle_map=mock_bundle_map,
prune=True,
recursive=True,
)

# Assertions
mock_create_app_package.assert_called_once()
mock_use_package_warehouse.assert_called_once()
mock_use_role.assert_called_once_with(manager.package_role)
mock_apply_package_scripts.assert_called_once()
mock_sync_deploy_root_with_stage.assert_called_once_with(
bundle_map=mock_bundle_map,
role=manager.package_role,
prune=True,
recursive=True,
stage_fqn=manager.stage_fqn,
local_paths_to_sync=None,
print_diff=True,
)
mock_execute_package_post_deploy_hooks.assert_called_once()
mock_validate.assert_called_once_with(use_scratch_stage=False)
assert result == mock_diff_result

0 comments on commit 2db6075

Please sign in to comment.