Skip to content

Commit

Permalink
move create/alter app upgrade calls to sql facade to reclassify error…
Browse files Browse the repository at this point in the history
…s cause by setup script execution (#1870)
  • Loading branch information
sfc-gh-mchok authored Dec 3, 2024
1 parent 65d2046 commit 6475e23
Show file tree
Hide file tree
Showing 14 changed files with 2,568 additions and 1,533 deletions.
3 changes: 2 additions & 1 deletion src/snowflake/cli/_plugins/nativeapp/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from snowflake.cli._plugins.nativeapp.entities.application_package import (
ApplicationPackageEntityModel,
)
from snowflake.cli._plugins.nativeapp.sf_facade import get_snowflake_facade
from snowflake.cli._plugins.nativeapp.v2_conversions.compat import (
find_entity,
force_project_definition_v2,
Expand Down Expand Up @@ -198,7 +199,7 @@ def app_open(
)
app_id = options["app_entity_id"]
app = ws.get_entity(app_id)
if app.get_existing_app_info():
if get_snowflake_facade().get_existing_app_info(app.name, app.role):
typer.launch(app.get_snowsight_url())
return MessageResult(f"Snowflake Native App opened in browser.")
else:
Expand Down
465 changes: 190 additions & 275 deletions src/snowflake/cli/_plugins/nativeapp/entities/application.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from dataclasses import dataclass
from typing import Optional

from snowflake.cli._plugins.nativeapp.constants import (
Expand All @@ -8,25 +9,15 @@
ApplicationCreatedExternallyError,
)
from snowflake.cli._plugins.stage.manager import StageManager
from snowflake.cli.api.project.util import to_identifier


@dataclass
class SameAccountInstallMethod:
_requires_created_by_cli: bool
_from_release_directive: bool
version: Optional[str]
patch: Optional[int]

def __init__(
self,
requires_created_by_cli: bool,
version: Optional[str] = None,
patch: Optional[int] = None,
from_release_directive: bool = False,
):
self._requires_created_by_cli = requires_created_by_cli
self.version = version
self.patch = patch
self._from_release_directive = from_release_directive
version: Optional[str] = None
patch: Optional[int] = None
_from_release_directive: bool = False

@classmethod
def unversioned_dev(cls):
Expand All @@ -39,7 +30,7 @@ def versioned_dev(cls, version: str, patch: Optional[int] = None):

@classmethod
def release_directive(cls):
return cls(False, from_release_directive=True)
return cls(False, _from_release_directive=True)

@property
def is_dev_mode(self) -> bool:
Expand All @@ -53,8 +44,9 @@ def using_clause(
return ""

if self.version:
version_clause = f"version {to_identifier(self.version)}"
patch_clause = f"patch {self.patch}" if self.patch else ""
return f"using version {self.version} {patch_clause}"
return f"using {version_clause} {patch_clause}"

stage_name = StageManager.quote_stage_name(stage_fqn)
return f"using {stage_name}"
Expand Down
80 changes: 80 additions & 0 deletions src/snowflake/cli/_plugins/nativeapp/sf_facade_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,83 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations

from typing import NoReturn

from click import ClickException
from snowflake.cli._plugins.nativeapp.sf_facade_constants import UseObjectType
from snowflake.cli.api.errno import (
APPLICATION_FILE_NOT_FOUND_ON_STAGE,
APPLICATION_INSTANCE_EMPTY_SETUP_SCRIPT,
APPLICATION_INSTANCE_FAILED_TO_RUN_SETUP_SCRIPT,
APPLICATION_INSTANCE_NO_ACTIVE_WAREHOUSE_FOR_CREATE_OR_UPGRADE,
APPLICATION_NO_LONGER_AVAILABLE,
APPLICATION_PACKAGE_CANNOT_SET_EXTERNAL_DISTRIBUTION_WITH_SPCS,
APPLICATION_PACKAGE_MANIFEST_CONTAINER_IMAGE_URL_BAD_VALUE,
APPLICATION_PACKAGE_MANIFEST_SPECIFIED_FILE_NOT_FOUND,
APPLICATION_PACKAGE_PATCH_DOES_NOT_EXIST,
CANNOT_GRANT_NON_MANIFEST_PRIVILEGE,
CANNOT_GRANT_OBJECT_NOT_IN_APP_PACKAGE,
CANNOT_GRANT_RESTRICTED_PRIVILEGE_TO_APP_PACKAGE_SHARE,
CANNOT_UPGRADE_FROM_LOOSE_FILES_TO_VERSION,
CANNOT_UPGRADE_FROM_VERSION_TO_LOOSE_FILES,
NATIVE_APPLICATION_MANIFEST_GENERIC_JSON_ERROR,
NATIVE_APPLICATION_MANIFEST_INVALID_SYNTAX,
NATIVE_APPLICATION_MANIFEST_UNEXPECTED_VALUE_FOR_PROPERTY,
NATIVE_APPLICATION_MANIFEST_UNRECOGNIZED_FIELD,
NO_REFERENCE_SET_FOR_DEFINITION,
NO_VERSIONS_AVAILABLE_FOR_ACCOUNT,
NOT_SUPPORTED_ON_DEV_MODE_APPLICATIONS,
ONLY_SUPPORTED_ON_DEV_MODE_APPLICATIONS,
ROLE_NOT_ASSIGNED,
SNOWSERVICES_IMAGE_MANIFEST_NOT_FOUND,
SNOWSERVICES_IMAGE_REPOSITORY_FAILS_TO_RETRIEVE_IMAGE_HASH_NEW,
SNOWSERVICES_IMAGE_REPOSITORY_IMAGE_IMPORT_TO_NATIVE_APP_FAIL,
VIEW_EXPANSION_FAILED,
)
from snowflake.connector import DatabaseError, Error, ProgrammingError

# Reasons why an `alter application ... upgrade` might fail
UPGRADE_RESTRICTION_CODES = {
CANNOT_UPGRADE_FROM_LOOSE_FILES_TO_VERSION,
CANNOT_UPGRADE_FROM_VERSION_TO_LOOSE_FILES,
ONLY_SUPPORTED_ON_DEV_MODE_APPLICATIONS,
NOT_SUPPORTED_ON_DEV_MODE_APPLICATIONS,
APPLICATION_NO_LONGER_AVAILABLE,
}

CREATE_OR_UPGRADE_APPLICATION_EXPECTED_USER_ERROR_CODES = {
APPLICATION_INSTANCE_FAILED_TO_RUN_SETUP_SCRIPT,
NATIVE_APPLICATION_MANIFEST_GENERIC_JSON_ERROR,
APPLICATION_INSTANCE_NO_ACTIVE_WAREHOUSE_FOR_CREATE_OR_UPGRADE,
# when setup script/manifest/readme isn't on the stage
APPLICATION_FILE_NOT_FOUND_ON_STAGE,
NATIVE_APPLICATION_MANIFEST_UNRECOGNIZED_FIELD,
SNOWSERVICES_IMAGE_MANIFEST_NOT_FOUND,
# user tried to clone tables and it failed
VIEW_EXPANSION_FAILED,
# user tried to do something with a role that wasn't assigned to them
ROLE_NOT_ASSIGNED,
APPLICATION_PACKAGE_MANIFEST_SPECIFIED_FILE_NOT_FOUND,
SNOWSERVICES_IMAGE_REPOSITORY_IMAGE_IMPORT_TO_NATIVE_APP_FAIL,
APPLICATION_PACKAGE_PATCH_DOES_NOT_EXIST,
APPLICATION_PACKAGE_MANIFEST_CONTAINER_IMAGE_URL_BAD_VALUE,
SNOWSERVICES_IMAGE_REPOSITORY_FAILS_TO_RETRIEVE_IMAGE_HASH_NEW,
NATIVE_APPLICATION_MANIFEST_UNEXPECTED_VALUE_FOR_PROPERTY,
CANNOT_GRANT_NON_MANIFEST_PRIVILEGE,
NO_REFERENCE_SET_FOR_DEFINITION,
NATIVE_APPLICATION_MANIFEST_INVALID_SYNTAX,
CANNOT_GRANT_OBJECT_NOT_IN_APP_PACKAGE,
APPLICATION_PACKAGE_MANIFEST_SPECIFIED_FILE_NOT_FOUND,
# user tried installing from release directive and there are none available
NO_VERSIONS_AVAILABLE_FOR_ACCOUNT,
APPLICATION_PACKAGE_MANIFEST_CONTAINER_IMAGE_URL_BAD_VALUE,
APPLICATION_INSTANCE_EMPTY_SETUP_SCRIPT,
APPLICATION_PACKAGE_CANNOT_SET_EXTERNAL_DISTRIBUTION_WITH_SPCS,
CANNOT_GRANT_RESTRICTED_PRIVILEGE_TO_APP_PACKAGE_SHARE,
}


def handle_unclassified_error(err: Error | Exception, context: str) -> NoReturn:
"""
Expand Down Expand Up @@ -115,3 +186,12 @@ def __init__(
if role:
message += f" using role: {role}"
super().__init__(message)


class UpgradeApplicationRestrictionError(UserInputError):
"""
Raised when an alter application ... upgrade fails due to user error.
Must be caught and handled by the caller of an upgrade_application
"""

pass
Loading

0 comments on commit 6475e23

Please sign in to comment.