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-1706990 Extract non action-related fields in ActionContext to new WorkspaceContext #1652

Merged
merged 1 commit into from
Oct 3, 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
32 changes: 18 additions & 14 deletions src/snowflake/cli/_plugins/nativeapp/entities/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
SameAccountInstallMethod,
)
from snowflake.cli._plugins.nativeapp.utils import needs_confirmation
from snowflake.cli._plugins.workspace.action_context import ActionContext
from snowflake.cli._plugins.workspace.context import ActionContext
from snowflake.cli.api.cli_global_context import get_cli_context
from snowflake.cli.api.console.abc import AbstractConsole
from snowflake.cli.api.entities.common import EntityBase, get_sql_executor
Expand Down Expand Up @@ -118,7 +118,7 @@ class ApplicationEntity(EntityBase[ApplicationEntityModel]):

def action_deploy(
self,
ctx: ActionContext,
action_ctx: ActionContext,
from_release_directive: bool,
prune: bool,
recursive: bool,
Expand All @@ -133,26 +133,29 @@ def action_deploy(
**kwargs,
):
model = self._entity_model
workspace_ctx = self._workspace_ctx
app_name = model.fqn.identifier
debug_mode = model.debug
if model.meta:
app_role = model.meta.role or ctx.default_role
app_warehouse = model.meta.warehouse or ctx.default_warehouse
app_role = model.meta.role or workspace_ctx.default_role
app_warehouse = model.meta.warehouse or workspace_ctx.default_warehouse
post_deploy_hooks = model.meta.post_deploy
else:
app_role = ctx.default_role
app_warehouse = ctx.default_warehouse
app_role = workspace_ctx.default_role
app_warehouse = workspace_ctx.default_warehouse
post_deploy_hooks = None

package_entity: ApplicationPackageEntity = ctx.get_entity(model.from_.target)
package_entity: ApplicationPackageEntity = action_ctx.get_entity(
model.from_.target
)
package_model: ApplicationPackageEntityModel = (
package_entity._entity_model # noqa: SLF001
)
package_name = package_model.fqn.identifier
if package_model.meta and package_model.meta.role:
package_role = package_model.meta.role
else:
package_role = ctx.default_role
package_role = workspace_ctx.default_role

if not stage_fqn:
stage_fqn = f"{package_name}.{package_model.stage}"
Expand All @@ -169,7 +172,7 @@ def action_deploy(

def deploy_package():
package_entity.action_deploy(
ctx=ctx,
action_ctx=action_ctx,
prune=True,
recursive=True,
paths=[],
Expand All @@ -180,8 +183,8 @@ def deploy_package():
)

self.deploy(
console=ctx.console,
project_root=ctx.project_root,
console=workspace_ctx.console,
project_root=workspace_ctx.project_root,
app_name=app_name,
app_role=app_role,
app_warehouse=app_warehouse,
Expand All @@ -202,21 +205,22 @@ def deploy_package():

def action_drop(
self,
ctx: ActionContext,
action_ctx: ActionContext,
interactive: bool,
force_drop: bool = False,
cascade: Optional[bool] = None,
*args,
**kwargs,
):
model = self._entity_model
workspace_ctx = self._workspace_ctx
app_name = model.fqn.identifier
if model.meta and model.meta.role:
app_role = model.meta.role
else:
app_role = ctx.default_role
app_role = workspace_ctx.default_role
self.drop(
console=ctx.console,
console=workspace_ctx.console,
app_name=app_name,
app_role=app_role,
auto_yes=force_drop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,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._plugins.workspace.context import ActionContext
from snowflake.cli.api.cli_global_context import get_cli_context
from snowflake.cli.api.console.abc import AbstractConsole
from snowflake.cli.api.entities.common import EntityBase, get_sql_executor
Expand Down Expand Up @@ -150,10 +150,11 @@ class ApplicationPackageEntity(EntityBase[ApplicationPackageEntityModel]):
A Native App application package.
"""

def action_bundle(self, ctx: ActionContext, *args, **kwargs):
def action_bundle(self, action_ctx: ActionContext, *args, **kwargs):
model = self._entity_model
workspace_ctx = self._workspace_ctx
return self.bundle(
project_root=ctx.project_root,
project_root=workspace_ctx.project_root,
deploy_root=Path(model.deploy_root),
bundle_root=Path(model.bundle_root),
generated_root=Path(model.generated_root),
Expand All @@ -163,7 +164,7 @@ def action_bundle(self, ctx: ActionContext, *args, **kwargs):

def action_deploy(
self,
ctx: ActionContext,
action_ctx: ActionContext,
prune: bool,
recursive: bool,
paths: List[Path],
Expand All @@ -175,6 +176,7 @@ def action_deploy(
**kwargs,
):
model = self._entity_model
workspace_ctx = self._workspace_ctx
package_name = model.fqn.identifier

if force:
Expand All @@ -185,15 +187,15 @@ def action_deploy(
policy = DenyAlwaysPolicy()

return self.deploy(
console=ctx.console,
project_root=ctx.project_root,
console=workspace_ctx.console,
project_root=workspace_ctx.project_root,
deploy_root=Path(model.deploy_root),
bundle_root=Path(model.bundle_root),
generated_root=Path(model.generated_root),
artifacts=model.artifacts,
bundle_map=None,
package_name=package_name,
package_role=(model.meta and model.meta.role) or ctx.default_role,
package_role=(model.meta and model.meta.role) or workspace_ctx.default_role,
package_distribution=model.distribution,
prune=prune,
recursive=recursive,
Expand All @@ -202,32 +204,34 @@ def action_deploy(
validate=validate,
stage_fqn=stage_fqn or f"{package_name}.{model.stage}",
package_warehouse=(
(model.meta and model.meta.warehouse) or ctx.default_warehouse
(model.meta and model.meta.warehouse) or workspace_ctx.default_warehouse
),
post_deploy_hooks=model.meta and model.meta.post_deploy,
package_scripts=[], # Package scripts are not supported in PDFv2
policy=policy,
)

def action_drop(self, ctx: ActionContext, force_drop: bool, *args, **kwargs):
def action_drop(self, action_ctx: ActionContext, force_drop: bool, *args, **kwargs):
model = self._entity_model
workspace_ctx = self._workspace_ctx
package_name = model.fqn.identifier
if model.meta and model.meta.role:
package_role = model.meta.role
else:
package_role = ctx.default_role
package_role = workspace_ctx.default_role

self.drop(
console=ctx.console,
console=workspace_ctx.console,
package_name=package_name,
package_role=package_role,
force_drop=force_drop,
)

def action_validate(
self, ctx: ActionContext, interactive: bool, force: bool, *args, **kwargs
self, action_ctx: ActionContext, interactive: bool, force: bool, *args, **kwargs
):
model = self._entity_model
workspace_ctx = self._workspace_ctx
package_name = model.fqn.identifier
if force:
policy = AllowAlwaysPolicy()
Expand All @@ -237,42 +241,43 @@ def action_validate(
policy = DenyAlwaysPolicy()

self.validate_setup_script(
console=ctx.console,
project_root=ctx.project_root,
console=workspace_ctx.console,
project_root=workspace_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=(model.meta and model.meta.role) or ctx.default_role,
package_role=(model.meta and model.meta.role) or workspace_ctx.default_role,
package_distribution=model.distribution,
prune=True,
recursive=True,
paths=[],
stage_fqn=f"{package_name}.{model.stage}",
package_warehouse=(
(model.meta and model.meta.warehouse) or ctx.default_warehouse
(model.meta and model.meta.warehouse) or workspace_ctx.default_warehouse
),
post_deploy_hooks=model.meta and model.meta.post_deploy,
package_scripts=[], # Package scripts are not supported in PDFv2
policy=policy,
use_scratch_stage=True,
scratch_stage_fqn=f"{package_name}.{model.scratch_stage}",
)
ctx.console.message("Setup script is valid")
workspace_ctx.console.message("Setup script is valid")

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

def action_version_create(
self,
ctx: ActionContext,
action_ctx: ActionContext,
version: Optional[str],
patch: Optional[int],
skip_git_check: bool,
Expand All @@ -282,16 +287,17 @@ def action_version_create(
**kwargs,
):
model = self._entity_model
workspace_ctx = self._workspace_ctx
package_name = model.fqn.identifier
return self.version_create(
console=ctx.console,
project_root=ctx.project_root,
console=workspace_ctx.console,
project_root=workspace_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=(model.meta and model.meta.role) or ctx.default_role,
package_role=(model.meta and model.meta.role) or workspace_ctx.default_role,
package_distribution=model.distribution,
prune=True,
recursive=True,
Expand All @@ -300,7 +306,7 @@ def action_version_create(
validate=True,
stage_fqn=f"{package_name}.{model.stage}",
package_warehouse=(
(model.meta and model.meta.warehouse) or ctx.default_warehouse
(model.meta and model.meta.warehouse) or workspace_ctx.default_warehouse
),
post_deploy_hooks=model.meta and model.meta.post_deploy,
package_scripts=[], # Package scripts are not supported in PDFv2
Expand All @@ -313,24 +319,25 @@ def action_version_create(

def action_version_drop(
self,
ctx: ActionContext,
action_ctx: ActionContext,
version: Optional[str],
interactive: bool,
force: bool,
*args,
**kwargs,
):
model = self._entity_model
workspace_ctx = self._workspace_ctx
package_name = model.fqn.identifier
return self.version_drop(
console=ctx.console,
project_root=ctx.project_root,
console=workspace_ctx.console,
project_root=workspace_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=(model.meta and model.meta.role) or ctx.default_role,
package_role=(model.meta and model.meta.role) or workspace_ctx.default_role,
package_distribution=model.distribution,
version=version,
force=force,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@


@dataclass
class ActionContext:
class WorkspaceContext:
"""
An object that is passed to each action when called by WorkspaceManager
An object that is passed to each entity when instantiated by WorkspaceManager
to allow access to the CLI context without requiring the entities to use
get_cli_context().
"""

console: AbstractConsole
project_root: Path
get_default_role: Callable[[], str]
get_default_warehouse: Callable[[], str | None]
get_entity: Callable

@cached_property
def default_role(self) -> str:
Expand All @@ -25,3 +26,13 @@ def default_role(self) -> str:
@cached_property
def default_warehouse(self) -> str | None:
return self.get_default_warehouse()


@dataclass
class ActionContext:
"""
An object that is passed to each action when called by WorkspaceManager
to provide access to metadata about the entity and project being acted upon.
"""

get_entity: Callable
15 changes: 9 additions & 6 deletions src/snowflake/cli/_plugins/workspace/manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pathlib import Path
from typing import Dict

from snowflake.cli._plugins.workspace.action_context import ActionContext
from snowflake.cli._plugins.workspace.context import ActionContext, WorkspaceContext
from snowflake.cli.api.cli_global_context import get_cli_context
from snowflake.cli.api.console import cli_console as cc
from snowflake.cli.api.entities.common import EntityActions, get_sql_executor
Expand Down Expand Up @@ -43,7 +43,13 @@ def get_entity(self, entity_id: str):
raise ValueError(f"No such entity ID: {entity_id}")
entity_model_cls = entity_model.__class__
entity_cls = v2_entity_model_to_entity_map[entity_model_cls]
self._entities_cache[entity_id] = entity_cls(entity_model)
workspace_ctx = WorkspaceContext(
console=cc,
project_root=self.project_root,
get_default_role=_get_default_role,
get_default_warehouse=_get_default_warehouse,
)
self._entities_cache[entity_id] = entity_cls(entity_model, workspace_ctx)
return self._entities_cache[entity_id]

def perform_action(self, entity_id: str, action: EntityActions, *args, **kwargs):
Expand All @@ -53,16 +59,13 @@ def perform_action(self, entity_id: str, action: EntityActions, *args, **kwargs)
entity = self.get_entity(entity_id)
if entity.supports(action):
action_ctx = ActionContext(
console=cc,
project_root=self.project_root(),
get_default_role=_get_default_role,
get_default_warehouse=_get_default_warehouse,
get_entity=self.get_entity,
)
return entity.perform(action, action_ctx, *args, **kwargs)
else:
raise ValueError(f'This entity type does not support "{action.value}"')

@property
Copy link
Contributor Author

@sfc-gh-fcampbell sfc-gh-fcampbell Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drive-by improvement, we never take a reference to this method so it can be a property instead, like it is in other classes

def project_root(self) -> Path:
return self._project_root

Expand Down
Loading
Loading