snowflake-cli-labs 2.8.0rc1__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snowflake/cli/__about__.py +1 -1
- snowflake/cli/{app → _app}/__main__.py +1 -1
- snowflake/cli/{app → _app}/cli_app.py +22 -13
- snowflake/cli/{app → _app}/commands_registration/builtin_plugins.py +15 -19
- snowflake/cli/{app → _app}/commands_registration/command_plugins_loader.py +9 -9
- snowflake/cli/{app → _app}/commands_registration/commands_registration_with_callbacks.py +4 -4
- snowflake/cli/{app → _app}/commands_registration/exception_logging.py +2 -2
- snowflake/cli/{app → _app}/commands_registration/typer_registration.py +2 -2
- snowflake/cli/{app → _app}/dev/docs/commands_docs_generator.py +30 -12
- snowflake/cli/{app → _app}/dev/docs/generator.py +3 -3
- snowflake/cli/{app → _app}/dev/docs/project_definition_docs_generator.py +4 -4
- snowflake/cli/{app → _app}/dev/docs/templates/usage.rst.jinja2 +14 -4
- snowflake/cli/{app → _app}/main_typer.py +2 -2
- snowflake/cli/{app → _app}/printing.py +2 -2
- snowflake/cli/_app/secret.py +9 -0
- snowflake/cli/{app → _app}/snow_connector.py +127 -61
- snowflake/cli/{app → _app}/telemetry.py +38 -7
- snowflake/cli/_app/version_check.py +74 -0
- snowflake/cli/{plugins → _plugins}/connection/commands.py +34 -11
- snowflake/cli/_plugins/connection/plugin_spec.py +30 -0
- snowflake/cli/{plugins → _plugins}/connection/util.py +16 -0
- snowflake/cli/{plugins → _plugins}/cortex/commands.py +54 -49
- snowflake/cli/{plugins → _plugins}/cortex/constants.py +1 -1
- snowflake/cli/{plugins → _plugins}/cortex/manager.py +5 -5
- snowflake/cli/{plugins → _plugins}/cortex/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/git/commands.py +79 -26
- snowflake/cli/{plugins → _plugins}/git/manager.py +72 -17
- snowflake/cli/{plugins → _plugins}/git/plugin_spec.py +1 -1
- snowflake/cli/_plugins/helpers/commands.py +90 -0
- snowflake/cli/{plugins/notebook → _plugins/helpers}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/init/commands.py +10 -6
- snowflake/cli/{plugins → _plugins}/init/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/artifacts.py +24 -9
- snowflake/cli/_plugins/nativeapp/bundle_context.py +31 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/artifact_processor.py +4 -4
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/compiler.py +37 -18
- snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +249 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/setup/setup_driver.py.source +5 -2
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/extension_function_utils.py +5 -5
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/models.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/python_processor.py +29 -34
- snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +114 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/commands.py +252 -132
- snowflake/cli/{plugins → _plugins}/nativeapp/common_flags.py +1 -1
- snowflake/cli/_plugins/nativeapp/entities/application.py +878 -0
- snowflake/cli/_plugins/nativeapp/entities/application_package.py +1392 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/exceptions.py +3 -12
- snowflake/cli/_plugins/nativeapp/manager.py +415 -0
- snowflake/cli/{plugins/connection → _plugins/nativeapp}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/policy.py +3 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/project_model.py +36 -20
- snowflake/cli/_plugins/nativeapp/run_processor.py +184 -0
- snowflake/cli/_plugins/nativeapp/same_account_install_method.py +70 -0
- snowflake/cli/_plugins/nativeapp/teardown_processor.py +70 -0
- snowflake/cli/_plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +262 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/version/commands.py +20 -49
- snowflake/cli/_plugins/nativeapp/version/version_processor.py +98 -0
- snowflake/cli/{plugins → _plugins}/notebook/commands.py +8 -6
- snowflake/cli/{plugins → _plugins}/notebook/manager.py +14 -14
- snowflake/cli/{plugins/nativeapp → _plugins/notebook}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/notebook/types.py +0 -1
- snowflake/cli/{plugins → _plugins}/object/command_aliases.py +6 -5
- snowflake/cli/{plugins → _plugins}/object/commands.py +16 -10
- snowflake/cli/{plugins → _plugins}/object/manager.py +43 -21
- snowflake/cli/{plugins → _plugins}/object/plugin_spec.py +1 -1
- snowflake/cli/_plugins/snowpark/commands.py +450 -0
- snowflake/cli/_plugins/snowpark/common.py +268 -0
- snowflake/cli/{plugins → _plugins}/snowpark/models.py +2 -8
- snowflake/cli/{plugins → _plugins}/snowpark/package/anaconda_packages.py +2 -36
- snowflake/cli/{plugins → _plugins}/snowpark/package/commands.py +13 -74
- snowflake/cli/{plugins → _plugins}/snowpark/package/manager.py +4 -3
- snowflake/cli/{plugins → _plugins}/snowpark/package_utils.py +5 -5
- snowflake/cli/_plugins/snowpark/plugin_spec.py +30 -0
- snowflake/cli/_plugins/snowpark/snowpark_entity.py +29 -0
- snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +173 -0
- snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +109 -0
- snowflake/cli/{plugins → _plugins}/snowpark/snowpark_shared.py +0 -36
- snowflake/cli/{plugins → _plugins}/snowpark/zipper.py +16 -8
- snowflake/cli/{plugins → _plugins}/spcs/__init__.py +5 -7
- snowflake/cli/{plugins → _plugins}/spcs/compute_pool/commands.py +29 -28
- snowflake/cli/{plugins → _plugins}/spcs/compute_pool/manager.py +3 -3
- snowflake/cli/{plugins → _plugins}/spcs/image_registry/commands.py +3 -3
- snowflake/cli/{plugins → _plugins}/spcs/image_repository/commands.py +25 -19
- snowflake/cli/{plugins → _plugins}/spcs/image_repository/manager.py +1 -1
- snowflake/cli/{plugins → _plugins}/spcs/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/spcs/services/commands.py +66 -32
- snowflake/cli/{plugins → _plugins}/spcs/services/manager.py +43 -5
- snowflake/cli/{plugins → _plugins}/sql/commands.py +20 -17
- snowflake/cli/{plugins → _plugins}/sql/manager.py +1 -1
- snowflake/cli/{plugins → _plugins}/sql/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/stage/commands.py +20 -17
- snowflake/cli/{plugins → _plugins}/stage/diff.py +1 -47
- snowflake/cli/{plugins → _plugins}/stage/manager.py +62 -24
- snowflake/cli/{plugins → _plugins}/stage/plugin_spec.py +1 -1
- snowflake/cli/_plugins/stage/utils.py +54 -0
- snowflake/cli/{plugins → _plugins}/streamlit/commands.py +71 -62
- snowflake/cli/{plugins → _plugins}/streamlit/manager.py +68 -70
- snowflake/cli/_plugins/streamlit/plugin_spec.py +30 -0
- snowflake/cli/_plugins/streamlit/streamlit_entity.py +12 -0
- snowflake/cli/_plugins/streamlit/streamlit_entity_model.py +66 -0
- snowflake/cli/_plugins/workspace/action_context.py +18 -0
- snowflake/cli/_plugins/workspace/commands.py +306 -0
- snowflake/cli/_plugins/workspace/manager.py +74 -0
- snowflake/cli/_plugins/workspace/plugin_spec.py +30 -0
- snowflake/cli/api/cli_global_context.py +152 -295
- snowflake/cli/api/commands/common.py +25 -0
- snowflake/cli/api/commands/decorators.py +19 -4
- snowflake/cli/api/commands/experimental_behaviour.py +2 -3
- snowflake/cli/api/commands/flags.py +143 -222
- snowflake/cli/api/commands/overrideable_parameter.py +143 -0
- snowflake/cli/api/commands/snow_typer.py +21 -11
- snowflake/cli/api/commands/utils.py +18 -0
- snowflake/cli/api/config.py +44 -12
- snowflake/cli/api/connections.py +216 -0
- snowflake/cli/api/console/abc.py +8 -3
- snowflake/cli/api/constants.py +11 -0
- snowflake/cli/api/entities/common.py +56 -0
- snowflake/cli/api/entities/utils.py +370 -0
- snowflake/cli/api/errno.py +1 -0
- snowflake/cli/api/exceptions.py +31 -5
- snowflake/cli/api/feature_flags.py +0 -1
- snowflake/cli/api/identifiers.py +45 -9
- snowflake/cli/api/metrics.py +92 -0
- snowflake/cli/api/project/definition.py +48 -6
- snowflake/cli/api/project/definition_conversion.py +400 -0
- snowflake/cli/api/project/definition_manager.py +16 -5
- snowflake/cli/api/project/project_verification.py +3 -3
- snowflake/cli/api/project/schemas/entities/common.py +91 -16
- snowflake/cli/api/project/schemas/entities/entities.py +37 -6
- snowflake/cli/api/project/schemas/project_definition.py +180 -49
- snowflake/cli/api/project/schemas/updatable_model.py +11 -3
- snowflake/cli/api/project/schemas/v1/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{identifier_model.py → v1/identifier_model.py} +3 -1
- snowflake/cli/api/project/schemas/v1/native_app/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{native_app → v1/native_app}/application.py +8 -9
- snowflake/cli/api/project/schemas/{native_app → v1/native_app}/native_app.py +4 -4
- snowflake/cli/api/project/schemas/{native_app → v1/native_app}/package.py +7 -1
- snowflake/cli/api/project/schemas/v1/snowpark/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/callable.py +2 -2
- snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/snowpark.py +2 -2
- snowflake/cli/api/project/schemas/v1/streamlit/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{streamlit → v1/streamlit}/streamlit.py +2 -1
- snowflake/cli/api/project/util.py +23 -6
- snowflake/cli/api/rendering/jinja.py +14 -8
- snowflake/cli/api/rendering/project_definition_templates.py +5 -1
- snowflake/cli/api/rendering/sql_templates.py +56 -11
- snowflake/cli/api/rest_api.py +11 -5
- snowflake/cli/api/secure_path.py +16 -18
- snowflake/cli/api/secure_utils.py +90 -1
- snowflake/cli/api/sql_execution.py +47 -27
- snowflake/cli/api/utils/definition_rendering.py +45 -13
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/METADATA +20 -18
- snowflake_cli_labs-3.0.0.dist-info/RECORD +242 -0
- snowflake_cli_labs-3.0.0.dist-info/entry_points.txt +2 -0
- snowflake/cli/api/commands/project_initialisation.py +0 -65
- snowflake/cli/api/commands/typer_pre_execute.py +0 -26
- snowflake/cli/api/project/schemas/entities/application_entity.py +0 -44
- snowflake/cli/api/project/schemas/entities/application_package_entity.py +0 -66
- snowflake/cli/app/build_and_push.sh +0 -8
- snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -172
- snowflake/cli/plugins/nativeapp/init.py +0 -345
- snowflake/cli/plugins/nativeapp/manager.py +0 -823
- snowflake/cli/plugins/nativeapp/run_processor.py +0 -389
- snowflake/cli/plugins/nativeapp/teardown_processor.py +0 -301
- snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -135
- snowflake/cli/plugins/nativeapp/version/version_processor.py +0 -362
- snowflake/cli/plugins/object_stage_deprecated/__init__.py +0 -15
- snowflake/cli/plugins/object_stage_deprecated/commands.py +0 -122
- snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +0 -32
- snowflake/cli/plugins/snowpark/commands.py +0 -548
- snowflake/cli/plugins/snowpark/common.py +0 -307
- snowflake/cli/plugins/snowpark/manager.py +0 -109
- snowflake/cli/plugins/snowpark/plugin_spec.py +0 -30
- snowflake/cli/plugins/snowpark/snowpark_package_paths.py +0 -65
- snowflake/cli/plugins/spcs/jobs/commands.py +0 -78
- snowflake/cli/plugins/spcs/jobs/manager.py +0 -53
- snowflake/cli/plugins/streamlit/__init__.py +0 -13
- snowflake/cli/plugins/streamlit/plugin_spec.py +0 -30
- snowflake/cli/plugins/workspace/__init__.py +0 -13
- snowflake/cli/plugins/workspace/commands.py +0 -35
- snowflake/cli/plugins/workspace/plugin_spec.py +0 -30
- snowflake/cli/templates/default_snowpark/.gitignore +0 -4
- snowflake/cli/templates/default_snowpark/app/common.py +0 -2
- snowflake/cli/templates/default_snowpark/app/functions.py +0 -15
- snowflake/cli/templates/default_snowpark/app/procedures.py +0 -22
- snowflake/cli/templates/default_snowpark/requirements.txt +0 -1
- snowflake/cli/templates/default_snowpark/snowflake.yml +0 -23
- snowflake/cli/templates/default_streamlit/.gitignore +0 -4
- snowflake/cli/templates/default_streamlit/common/hello.py +0 -2
- snowflake/cli/templates/default_streamlit/environment.yml +0 -6
- snowflake/cli/templates/default_streamlit/pages/my_page.py +0 -3
- snowflake/cli/templates/default_streamlit/snowflake.yml +0 -10
- snowflake/cli/templates/default_streamlit/streamlit_app.py +0 -4
- snowflake_cli_labs-2.8.0rc1.dist-info/RECORD +0 -240
- snowflake_cli_labs-2.8.0rc1.dist-info/entry_points.txt +0 -2
- /snowflake/cli/{app → _app}/__init__.py +0 -0
- /snowflake/cli/{api/project/schemas/native_app → _app/api_impl}/__init__.py +0 -0
- /snowflake/cli/{api/project/schemas/snowpark → _app/api_impl/plugin}/__init__.py +0 -0
- /snowflake/cli/{app → _app}/api_impl/plugin/plugin_config_provider_impl.py +0 -0
- /snowflake/cli/{app → _app}/commands_registration/__init__.py +0 -0
- /snowflake/cli/{app → _app}/commands_registration/threadsafe.py +0 -0
- /snowflake/cli/{app → _app}/constants.py +0 -0
- /snowflake/cli/{api/project/schemas/streamlit → _app/dev}/__init__.py +0 -0
- /snowflake/cli/{app → _app}/dev/commands_structure.py +0 -0
- /snowflake/cli/{app/api_impl → _app/dev/docs}/__init__.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/project_definition_generate_json_schema.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/template_utils.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/templates/definition_description.rst.jinja2 +0 -0
- /snowflake/cli/{app → _app}/dev/docs/templates/overview.rst.jinja2 +0 -0
- /snowflake/cli/{app → _app}/dev/pycharm_remote_debug.py +0 -0
- /snowflake/cli/{app → _app}/loggers.py +0 -0
- /snowflake/cli/{app/api_impl/plugin → _plugins}/__init__.py +0 -0
- /snowflake/cli/{app/dev → _plugins/connection}/__init__.py +0 -0
- /snowflake/cli/{app/dev/docs → _plugins/cortex}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/cortex/types.py +0 -0
- /snowflake/cli/{plugins → _plugins/git}/__init__.py +0 -0
- /snowflake/cli/{plugins/connection → _plugins/helpers}/__init__.py +0 -0
- /snowflake/cli/{plugins/cortex → _plugins/init}/__init__.py +0 -0
- /snowflake/cli/{plugins/git → _plugins/nativeapp}/__init__.py +0 -0
- /snowflake/cli/{plugins/init → _plugins/nativeapp/codegen}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/sandbox.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/constants.py +0 -0
- /snowflake/cli/{templates/default_snowpark/app → _plugins/nativeapp/entities}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/feature_flags.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/utils.py +0 -0
- /snowflake/cli/{plugins/nativeapp → _plugins/nativeapp/version}/__init__.py +0 -0
- /snowflake/cli/{plugins/nativeapp/codegen → _plugins/notebook}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/notebook/exceptions.py +0 -0
- /snowflake/cli/{plugins/nativeapp/version → _plugins/object}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/object/common.py +0 -0
- /snowflake/cli/{plugins/notebook → _plugins/snowpark}/__init__.py +0 -0
- /snowflake/cli/{plugins/object → _plugins/snowpark/package}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/snowpark/package/utils.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/common.py +0 -0
- /snowflake/cli/{plugins/snowpark → _plugins/spcs/compute_pool}/__init__.py +0 -0
- /snowflake/cli/{plugins/snowpark/package → _plugins/spcs/image_registry}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_registry/manager.py +0 -0
- /snowflake/cli/{plugins/spcs/compute_pool → _plugins/spcs/image_repository}/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/image_registry → _plugins/spcs/services}/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/image_repository → _plugins/sql}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/sql/snowsql_templating.py +0 -0
- /snowflake/cli/{plugins/spcs/jobs → _plugins/stage}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/stage/md5.py +0 -0
- /snowflake/cli/{plugins/spcs/services → _plugins/streamlit}/__init__.py +0 -0
- /snowflake/cli/{plugins/sql → _plugins/workspace}/__init__.py +0 -0
- /snowflake/cli/{plugins/stage → api/project/schemas/entities}/__init__.py +0 -0
- /snowflake/cli/api/project/schemas/{native_app → v1/native_app}/path_mapping.py +0 -0
- /snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/argument.py +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Copyright (c) 2024 Snowflake Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Optional
|
|
19
|
+
|
|
20
|
+
import jinja2
|
|
21
|
+
from snowflake.cli._plugins.nativeapp.artifacts import BundleMap
|
|
22
|
+
from snowflake.cli._plugins.nativeapp.codegen.artifact_processor import (
|
|
23
|
+
ArtifactProcessor,
|
|
24
|
+
)
|
|
25
|
+
from snowflake.cli._plugins.nativeapp.exceptions import InvalidTemplateInFileError
|
|
26
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
27
|
+
from snowflake.cli.api.console import cli_console as cc
|
|
28
|
+
from snowflake.cli.api.metrics import CLICounterField
|
|
29
|
+
from snowflake.cli.api.project.schemas.v1.native_app.path_mapping import (
|
|
30
|
+
PathMapping,
|
|
31
|
+
ProcessorMapping,
|
|
32
|
+
)
|
|
33
|
+
from snowflake.cli.api.rendering.project_definition_templates import (
|
|
34
|
+
get_client_side_jinja_env,
|
|
35
|
+
has_client_side_templates,
|
|
36
|
+
)
|
|
37
|
+
from snowflake.cli.api.rendering.sql_templates import (
|
|
38
|
+
choose_sql_jinja_env_based_on_template_syntax,
|
|
39
|
+
has_sql_templates,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _is_sql_file(file: Path) -> bool:
|
|
44
|
+
return file.name.lower().endswith(".sql")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class TemplatesProcessor(ArtifactProcessor):
|
|
48
|
+
"""
|
|
49
|
+
Processor class to perform template expansion on all relevant artifacts (specified in the project definition file).
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def expand_templates_in_file(self, src: Path, dest: Path) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Expand templates in the file.
|
|
55
|
+
"""
|
|
56
|
+
if src.is_dir():
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
with self.edit_file(dest) as file:
|
|
60
|
+
if not has_client_side_templates(file.contents) and not (
|
|
61
|
+
_is_sql_file(dest) and has_sql_templates(file.contents)
|
|
62
|
+
):
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
src_file_name = src.relative_to(self._bundle_ctx.project_root)
|
|
66
|
+
cc.step(f"Expanding templates in {src_file_name}")
|
|
67
|
+
with cc.indented():
|
|
68
|
+
try:
|
|
69
|
+
jinja_env = (
|
|
70
|
+
choose_sql_jinja_env_based_on_template_syntax(
|
|
71
|
+
file.contents, reference_name=src_file_name
|
|
72
|
+
)
|
|
73
|
+
if _is_sql_file(dest)
|
|
74
|
+
else get_client_side_jinja_env()
|
|
75
|
+
)
|
|
76
|
+
expanded_template = jinja_env.from_string(file.contents).render(
|
|
77
|
+
get_cli_context().template_context
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# For now, we are printing the source file path in the error message
|
|
81
|
+
# instead of the destination file path to make it easier for the user
|
|
82
|
+
# to identify the file that has the error, and edit the correct file.
|
|
83
|
+
except jinja2.TemplateSyntaxError as e:
|
|
84
|
+
raise InvalidTemplateInFileError(src_file_name, e, e.lineno) from e
|
|
85
|
+
|
|
86
|
+
except jinja2.UndefinedError as e:
|
|
87
|
+
raise InvalidTemplateInFileError(src_file_name, e) from e
|
|
88
|
+
|
|
89
|
+
if expanded_template != file.contents:
|
|
90
|
+
file.edited_contents = expanded_template
|
|
91
|
+
|
|
92
|
+
def process(
|
|
93
|
+
self,
|
|
94
|
+
artifact_to_process: PathMapping,
|
|
95
|
+
processor_mapping: Optional[ProcessorMapping],
|
|
96
|
+
**kwargs,
|
|
97
|
+
) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Process the artifact by executing the template expansion logic on it.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
get_cli_context().metrics.set_counter(CLICounterField.TEMPLATES_PROCESSOR, 1)
|
|
103
|
+
|
|
104
|
+
bundle_map = BundleMap(
|
|
105
|
+
project_root=self._bundle_ctx.project_root,
|
|
106
|
+
deploy_root=self._bundle_ctx.deploy_root,
|
|
107
|
+
)
|
|
108
|
+
bundle_map.add(artifact_to_process)
|
|
109
|
+
|
|
110
|
+
for src, dest in bundle_map.all_mappings(
|
|
111
|
+
absolute=True,
|
|
112
|
+
expand_directories=True,
|
|
113
|
+
):
|
|
114
|
+
self.expand_templates_in_file(src, dest)
|
|
@@ -14,60 +14,62 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
+
import itertools
|
|
17
18
|
import logging
|
|
19
|
+
from enum import Enum
|
|
18
20
|
from pathlib import Path
|
|
19
21
|
from textwrap import dedent
|
|
20
|
-
from typing import List, Optional
|
|
22
|
+
from typing import Generator, Iterable, List, Optional, cast
|
|
21
23
|
|
|
22
24
|
import typer
|
|
23
|
-
from click import ClickException
|
|
24
|
-
from snowflake.cli.
|
|
25
|
-
from snowflake.cli.api.commands.decorators import (
|
|
26
|
-
with_project_definition,
|
|
27
|
-
)
|
|
28
|
-
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
29
|
-
from snowflake.cli.api.output.formats import OutputFormat
|
|
30
|
-
from snowflake.cli.api.output.types import (
|
|
31
|
-
CollectionResult,
|
|
32
|
-
CommandResult,
|
|
33
|
-
MessageResult,
|
|
34
|
-
ObjectResult,
|
|
35
|
-
StreamResult,
|
|
36
|
-
)
|
|
37
|
-
from snowflake.cli.api.project.project_verification import assert_project_type
|
|
38
|
-
from snowflake.cli.api.secure_path import SecurePath
|
|
39
|
-
from snowflake.cli.plugins.nativeapp.common_flags import (
|
|
25
|
+
from click.exceptions import ClickException
|
|
26
|
+
from snowflake.cli._plugins.nativeapp.common_flags import (
|
|
40
27
|
ForceOption,
|
|
41
28
|
InteractiveOption,
|
|
42
29
|
ValidateOption,
|
|
43
30
|
)
|
|
44
|
-
from snowflake.cli.
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
from snowflake.cli._plugins.nativeapp.entities.application import ApplicationEntityModel
|
|
32
|
+
from snowflake.cli._plugins.nativeapp.entities.application_package import (
|
|
33
|
+
ApplicationPackageEntityModel,
|
|
47
34
|
)
|
|
48
|
-
from snowflake.cli.
|
|
49
|
-
from snowflake.cli.
|
|
35
|
+
from snowflake.cli._plugins.nativeapp.manager import NativeAppManager
|
|
36
|
+
from snowflake.cli._plugins.nativeapp.policy import (
|
|
50
37
|
AllowAlwaysPolicy,
|
|
51
38
|
AskAlwaysPolicy,
|
|
52
39
|
DenyAlwaysPolicy,
|
|
53
40
|
)
|
|
54
|
-
from snowflake.cli.
|
|
55
|
-
from snowflake.cli.
|
|
41
|
+
from snowflake.cli._plugins.nativeapp.run_processor import NativeAppRunProcessor
|
|
42
|
+
from snowflake.cli._plugins.nativeapp.teardown_processor import (
|
|
56
43
|
NativeAppTeardownProcessor,
|
|
57
44
|
)
|
|
58
|
-
from snowflake.cli.
|
|
59
|
-
|
|
60
|
-
shallow_git_clone,
|
|
61
|
-
)
|
|
62
|
-
from snowflake.cli.plugins.nativeapp.v2_conversions.v2_to_v1_decorator import (
|
|
45
|
+
from snowflake.cli._plugins.nativeapp.v2_conversions.v2_to_v1_decorator import (
|
|
46
|
+
find_entity,
|
|
63
47
|
nativeapp_definition_v2_to_v1,
|
|
64
48
|
)
|
|
65
|
-
from snowflake.cli.
|
|
66
|
-
from snowflake.cli.
|
|
49
|
+
from snowflake.cli._plugins.nativeapp.version.commands import app as versions_app
|
|
50
|
+
from snowflake.cli._plugins.stage.diff import (
|
|
67
51
|
DiffResult,
|
|
68
52
|
compute_stage_diff,
|
|
69
|
-
print_diff_to_console,
|
|
70
53
|
)
|
|
54
|
+
from snowflake.cli._plugins.stage.utils import print_diff_to_console
|
|
55
|
+
from snowflake.cli._plugins.workspace.manager import WorkspaceManager
|
|
56
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
57
|
+
from snowflake.cli.api.commands.decorators import (
|
|
58
|
+
with_project_definition,
|
|
59
|
+
)
|
|
60
|
+
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
61
|
+
from snowflake.cli.api.entities.common import EntityActions
|
|
62
|
+
from snowflake.cli.api.exceptions import IncompatibleParametersError
|
|
63
|
+
from snowflake.cli.api.output.formats import OutputFormat
|
|
64
|
+
from snowflake.cli.api.output.types import (
|
|
65
|
+
CommandResult,
|
|
66
|
+
MessageResult,
|
|
67
|
+
ObjectResult,
|
|
68
|
+
StreamResult,
|
|
69
|
+
)
|
|
70
|
+
from snowflake.cli.api.project.project_verification import assert_project_type
|
|
71
|
+
from snowflake.cli.api.project.schemas.project_definition import ProjectDefinitionV1
|
|
72
|
+
from typing_extensions import Annotated
|
|
71
73
|
|
|
72
74
|
app = SnowTyperFactory(
|
|
73
75
|
name="app",
|
|
@@ -78,85 +80,20 @@ app.add_typer(versions_app)
|
|
|
78
80
|
log = logging.getLogger(__name__)
|
|
79
81
|
|
|
80
82
|
|
|
81
|
-
@app.command("init")
|
|
82
|
-
def app_init(
|
|
83
|
-
path: str = typer.Argument(
|
|
84
|
-
...,
|
|
85
|
-
help=f"""Directory to be initialized with the Snowflake Native App project. This directory must not already exist.""",
|
|
86
|
-
),
|
|
87
|
-
name: str = typer.Option(
|
|
88
|
-
None,
|
|
89
|
-
help=f"""The name of the Snowflake Native App project to include in snowflake.yml. When not specified, it is
|
|
90
|
-
generated from the name of the directory. Names are assumed to be unquoted identifiers whenever possible, but
|
|
91
|
-
can be forced to be quoted by including the surrounding quote characters in the provided value.""",
|
|
92
|
-
),
|
|
93
|
-
template_repo: str = typer.Option(
|
|
94
|
-
None,
|
|
95
|
-
help=f"""Specifies the git URL to a template repository, which can be a template itself or contain many templates inside it,
|
|
96
|
-
such as https://github.com/snowflakedb/native-apps-templates.git for all official Snowflake Native App with Snowflake CLI templates.
|
|
97
|
-
If using a private Github repo, you might be prompted to enter your Github username and password.
|
|
98
|
-
Please use your personal access token in the password prompt, and refer to
|
|
99
|
-
https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.""",
|
|
100
|
-
),
|
|
101
|
-
template: str = typer.Option(
|
|
102
|
-
None,
|
|
103
|
-
help="A specific template name within the template repo to use as template for the Snowflake Native App project. Example: Default is basic if `--template-repo` is https://github.com/snowflakedb/native-apps-templates.git, and None if any other --template-repo is specified.",
|
|
104
|
-
),
|
|
105
|
-
**options,
|
|
106
|
-
) -> CommandResult:
|
|
107
|
-
"""
|
|
108
|
-
Initializes a Snowflake Native App project.
|
|
83
|
+
@app.command("init", hidden=True)
|
|
84
|
+
def app_init(**options):
|
|
109
85
|
"""
|
|
110
|
-
|
|
111
|
-
path=path, name=name, git_url=template_repo, template=template
|
|
112
|
-
)
|
|
113
|
-
return MessageResult(
|
|
114
|
-
f"Snowflake Native App project {project.name} has been created at: {path}"
|
|
115
|
-
)
|
|
116
|
-
|
|
86
|
+
*** Deprecated. Use snow init instead ***
|
|
117
87
|
|
|
118
|
-
|
|
119
|
-
def app_list_templates(**options) -> CommandResult:
|
|
120
|
-
"""
|
|
121
|
-
Prints information regarding the official templates that can be used with snow app init.
|
|
88
|
+
Initializes a Snowflake Native App project.
|
|
122
89
|
"""
|
|
123
|
-
with SecurePath.temporary_directory() as temp_path:
|
|
124
|
-
from git import rmtree as git_rmtree
|
|
125
|
-
|
|
126
|
-
repo = shallow_git_clone(OFFICIAL_TEMPLATES_GITHUB_URL, temp_path.path)
|
|
127
|
-
|
|
128
|
-
# Mark a directory as a template if a project definition jinja template is inside
|
|
129
|
-
template_directories = [
|
|
130
|
-
entry.name
|
|
131
|
-
for entry in repo.head.commit.tree
|
|
132
|
-
if (temp_path / entry.name / "snowflake.yml.jinja").exists()
|
|
133
|
-
]
|
|
134
|
-
|
|
135
|
-
# get the template descriptions from the README.md in its directory
|
|
136
|
-
template_descriptions = [
|
|
137
|
-
get_first_paragraph_from_markdown_file(
|
|
138
|
-
(temp_path / directory / "README.md").path
|
|
139
|
-
)
|
|
140
|
-
for directory in template_directories
|
|
141
|
-
]
|
|
142
|
-
|
|
143
|
-
result = (
|
|
144
|
-
{"template": directory, "description": description}
|
|
145
|
-
for directory, description in zip(
|
|
146
|
-
template_directories, template_descriptions
|
|
147
|
-
)
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
# proactively clean up here to avoid permission issues on Windows
|
|
151
|
-
repo.close()
|
|
152
|
-
git_rmtree(temp_path.path)
|
|
153
90
|
|
|
154
|
-
|
|
91
|
+
raise ClickException("This command has been removed. Use `snow init` instead.")
|
|
155
92
|
|
|
156
93
|
|
|
157
94
|
@app.command("bundle")
|
|
158
95
|
@with_project_definition()
|
|
159
|
-
@nativeapp_definition_v2_to_v1
|
|
96
|
+
@nativeapp_definition_v2_to_v1()
|
|
160
97
|
def app_bundle(
|
|
161
98
|
**options,
|
|
162
99
|
) -> CommandResult:
|
|
@@ -166,6 +103,7 @@ def app_bundle(
|
|
|
166
103
|
|
|
167
104
|
assert_project_type("native_app")
|
|
168
105
|
|
|
106
|
+
cli_context = get_cli_context()
|
|
169
107
|
manager = NativeAppManager(
|
|
170
108
|
project_definition=cli_context.project_definition.native_app,
|
|
171
109
|
project_root=cli_context.project_root,
|
|
@@ -176,7 +114,7 @@ def app_bundle(
|
|
|
176
114
|
|
|
177
115
|
@app.command("diff", requires_connection=True, hidden=True)
|
|
178
116
|
@with_project_definition()
|
|
179
|
-
@nativeapp_definition_v2_to_v1
|
|
117
|
+
@nativeapp_definition_v2_to_v1()
|
|
180
118
|
def app_diff(
|
|
181
119
|
**options,
|
|
182
120
|
) -> CommandResult:
|
|
@@ -185,6 +123,7 @@ def app_diff(
|
|
|
185
123
|
"""
|
|
186
124
|
assert_project_type("native_app")
|
|
187
125
|
|
|
126
|
+
cli_context = get_cli_context()
|
|
188
127
|
manager = NativeAppManager(
|
|
189
128
|
project_definition=cli_context.project_definition.native_app,
|
|
190
129
|
project_root=cli_context.project_root,
|
|
@@ -202,7 +141,7 @@ def app_diff(
|
|
|
202
141
|
|
|
203
142
|
@app.command("run", requires_connection=True)
|
|
204
143
|
@with_project_definition()
|
|
205
|
-
@nativeapp_definition_v2_to_v1
|
|
144
|
+
@nativeapp_definition_v2_to_v1(app_required=True)
|
|
206
145
|
def app_run(
|
|
207
146
|
version: Optional[str] = typer.Option(
|
|
208
147
|
None,
|
|
@@ -243,6 +182,7 @@ def app_run(
|
|
|
243
182
|
else:
|
|
244
183
|
policy = DenyAlwaysPolicy()
|
|
245
184
|
|
|
185
|
+
cli_context = get_cli_context()
|
|
246
186
|
processor = NativeAppRunProcessor(
|
|
247
187
|
project_definition=cli_context.project_definition.native_app,
|
|
248
188
|
project_root=cli_context.project_root,
|
|
@@ -265,7 +205,7 @@ def app_run(
|
|
|
265
205
|
|
|
266
206
|
@app.command("open", requires_connection=True)
|
|
267
207
|
@with_project_definition()
|
|
268
|
-
@nativeapp_definition_v2_to_v1
|
|
208
|
+
@nativeapp_definition_v2_to_v1(app_required=True)
|
|
269
209
|
def app_open(
|
|
270
210
|
**options,
|
|
271
211
|
) -> CommandResult:
|
|
@@ -276,6 +216,7 @@ def app_open(
|
|
|
276
216
|
|
|
277
217
|
assert_project_type("native_app")
|
|
278
218
|
|
|
219
|
+
cli_context = get_cli_context()
|
|
279
220
|
manager = NativeAppManager(
|
|
280
221
|
project_definition=cli_context.project_definition.native_app,
|
|
281
222
|
project_root=cli_context.project_root,
|
|
@@ -291,7 +232,9 @@ def app_open(
|
|
|
291
232
|
|
|
292
233
|
@app.command("teardown", requires_connection=True)
|
|
293
234
|
@with_project_definition()
|
|
294
|
-
@nativeapp_definition_v2_to_v1
|
|
235
|
+
# This command doesn't use @nativeapp_definition_v2_to_v1 because it needs to
|
|
236
|
+
# be aware of PDFv2 definitions that have multiple apps created from the same package,
|
|
237
|
+
# which all need to be torn down.
|
|
295
238
|
def app_teardown(
|
|
296
239
|
force: Optional[bool] = ForceOption,
|
|
297
240
|
cascade: Optional[bool] = typer.Option(
|
|
@@ -300,25 +243,70 @@ def app_teardown(
|
|
|
300
243
|
show_default=False,
|
|
301
244
|
),
|
|
302
245
|
interactive: bool = InteractiveOption,
|
|
246
|
+
# Same as the param auto-added by @nativeapp_definition_v2_to_v1
|
|
247
|
+
package_entity_id: Optional[str] = typer.Option(
|
|
248
|
+
default="",
|
|
249
|
+
help="The ID of the package entity on which to operate when definition_version is 2 or higher.",
|
|
250
|
+
),
|
|
303
251
|
**options,
|
|
304
252
|
) -> CommandResult:
|
|
305
253
|
"""
|
|
306
254
|
Attempts to drop both the application object and application package as defined in the project definition file.
|
|
307
255
|
"""
|
|
256
|
+
cli_context = get_cli_context()
|
|
257
|
+
project = cli_context.project_definition
|
|
258
|
+
if isinstance(project, ProjectDefinitionV1):
|
|
259
|
+
# Old behaviour, not multi-app aware so we can use the old processor
|
|
260
|
+
processor = NativeAppTeardownProcessor(
|
|
261
|
+
project_definition=cli_context.project_definition.native_app,
|
|
262
|
+
project_root=cli_context.project_root,
|
|
263
|
+
)
|
|
264
|
+
processor.process(interactive, force, cascade)
|
|
265
|
+
else:
|
|
266
|
+
# New behaviour, multi-app aware so teardown all the apps created from the package
|
|
267
|
+
|
|
268
|
+
# Determine the package entity to drop, there must be one
|
|
269
|
+
app_package_entity = find_entity(
|
|
270
|
+
project,
|
|
271
|
+
ApplicationPackageEntityModel,
|
|
272
|
+
package_entity_id,
|
|
273
|
+
disambiguation_option="--package-entity-id",
|
|
274
|
+
required=True,
|
|
275
|
+
)
|
|
276
|
+
assert app_package_entity is not None # satisfy mypy
|
|
308
277
|
|
|
309
|
-
|
|
278
|
+
# Same implementation as `snow ws drop`
|
|
279
|
+
ws = WorkspaceManager(
|
|
280
|
+
project_definition=cli_context.project_definition,
|
|
281
|
+
project_root=cli_context.project_root,
|
|
282
|
+
)
|
|
283
|
+
for app_entity in project.get_entities_by_type(
|
|
284
|
+
ApplicationEntityModel.get_type()
|
|
285
|
+
).values():
|
|
286
|
+
# Drop each app
|
|
287
|
+
if app_entity.from_.target == app_package_entity.entity_id:
|
|
288
|
+
ws.perform_action(
|
|
289
|
+
app_entity.entity_id,
|
|
290
|
+
EntityActions.DROP,
|
|
291
|
+
force_drop=force,
|
|
292
|
+
interactive=interactive,
|
|
293
|
+
cascade=cascade,
|
|
294
|
+
)
|
|
295
|
+
# Then drop the package
|
|
296
|
+
ws.perform_action(
|
|
297
|
+
app_package_entity.entity_id,
|
|
298
|
+
EntityActions.DROP,
|
|
299
|
+
force_drop=force,
|
|
300
|
+
interactive=interactive,
|
|
301
|
+
cascade=cascade,
|
|
302
|
+
)
|
|
310
303
|
|
|
311
|
-
processor = NativeAppTeardownProcessor(
|
|
312
|
-
project_definition=cli_context.project_definition.native_app,
|
|
313
|
-
project_root=cli_context.project_root,
|
|
314
|
-
)
|
|
315
|
-
processor.process(interactive, force, cascade)
|
|
316
304
|
return MessageResult(f"Teardown is now complete.")
|
|
317
305
|
|
|
318
306
|
|
|
319
307
|
@app.command("deploy", requires_connection=True)
|
|
320
308
|
@with_project_definition()
|
|
321
|
-
@nativeapp_definition_v2_to_v1
|
|
309
|
+
@nativeapp_definition_v2_to_v1()
|
|
322
310
|
def app_deploy(
|
|
323
311
|
prune: Optional[bool] = typer.Option(
|
|
324
312
|
default=None,
|
|
@@ -341,6 +329,8 @@ def app_deploy(
|
|
|
341
329
|
unspecified, the command syncs all local changes to the stage."""
|
|
342
330
|
).strip(),
|
|
343
331
|
),
|
|
332
|
+
interactive: bool = InteractiveOption,
|
|
333
|
+
force: Optional[bool] = ForceOption,
|
|
344
334
|
validate: bool = ValidateOption,
|
|
345
335
|
**options,
|
|
346
336
|
) -> CommandResult:
|
|
@@ -351,6 +341,13 @@ def app_deploy(
|
|
|
351
341
|
|
|
352
342
|
assert_project_type("native_app")
|
|
353
343
|
|
|
344
|
+
if force:
|
|
345
|
+
policy = AllowAlwaysPolicy()
|
|
346
|
+
elif interactive:
|
|
347
|
+
policy = AskAlwaysPolicy()
|
|
348
|
+
else:
|
|
349
|
+
policy = DenyAlwaysPolicy()
|
|
350
|
+
|
|
354
351
|
has_paths = paths is not None and len(paths) > 0
|
|
355
352
|
if prune is None and recursive is None and not has_paths:
|
|
356
353
|
prune = True
|
|
@@ -362,8 +359,9 @@ def app_deploy(
|
|
|
362
359
|
recursive = False
|
|
363
360
|
|
|
364
361
|
if has_paths and prune:
|
|
365
|
-
raise
|
|
362
|
+
raise IncompatibleParametersError(["paths", "--prune"])
|
|
366
363
|
|
|
364
|
+
cli_context = get_cli_context()
|
|
367
365
|
manager = NativeAppManager(
|
|
368
366
|
project_definition=cli_context.project_definition.native_app,
|
|
369
367
|
project_root=cli_context.project_root,
|
|
@@ -376,6 +374,7 @@ def app_deploy(
|
|
|
376
374
|
recursive=recursive,
|
|
377
375
|
local_paths_to_sync=paths,
|
|
378
376
|
validate=validate,
|
|
377
|
+
policy=policy,
|
|
379
378
|
)
|
|
380
379
|
|
|
381
380
|
return MessageResult(
|
|
@@ -385,14 +384,17 @@ def app_deploy(
|
|
|
385
384
|
|
|
386
385
|
@app.command("validate", requires_connection=True)
|
|
387
386
|
@with_project_definition()
|
|
388
|
-
@nativeapp_definition_v2_to_v1
|
|
389
|
-
def app_validate(
|
|
387
|
+
@nativeapp_definition_v2_to_v1()
|
|
388
|
+
def app_validate(
|
|
389
|
+
**options,
|
|
390
|
+
):
|
|
390
391
|
"""
|
|
391
392
|
Validates a deployed Snowflake Native App's setup script.
|
|
392
393
|
"""
|
|
393
394
|
|
|
394
395
|
assert_project_type("native_app")
|
|
395
396
|
|
|
397
|
+
cli_context = get_cli_context()
|
|
396
398
|
manager = NativeAppManager(
|
|
397
399
|
project_definition=cli_context.project_definition.native_app,
|
|
398
400
|
project_root=cli_context.project_root,
|
|
@@ -404,26 +406,144 @@ def app_validate(**options):
|
|
|
404
406
|
return MessageResult("Snowflake Native App validation succeeded.")
|
|
405
407
|
|
|
406
408
|
|
|
407
|
-
|
|
409
|
+
class RecordType(Enum):
|
|
410
|
+
LOG = "log"
|
|
411
|
+
SPAN = "span"
|
|
412
|
+
SPAN_EVENT = "span_event"
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
# The default number of lines to print before streaming when running
|
|
416
|
+
# snow app events --follow
|
|
417
|
+
DEFAULT_EVENT_FOLLOW_LAST = 20
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
@app.command("events", requires_connection=True)
|
|
408
421
|
@with_project_definition()
|
|
409
|
-
@nativeapp_definition_v2_to_v1
|
|
410
|
-
def app_events(
|
|
411
|
-
|
|
422
|
+
@nativeapp_definition_v2_to_v1(app_required=True)
|
|
423
|
+
def app_events(
|
|
424
|
+
since: str = typer.Option(
|
|
425
|
+
default="",
|
|
426
|
+
help="Fetch events that are newer than this time ago, in Snowflake interval syntax.",
|
|
427
|
+
),
|
|
428
|
+
until: str = typer.Option(
|
|
429
|
+
default="",
|
|
430
|
+
help="Fetch events that are older than this time ago, in Snowflake interval syntax.",
|
|
431
|
+
),
|
|
432
|
+
record_types: Annotated[
|
|
433
|
+
list[RecordType], typer.Option(case_sensitive=False)
|
|
434
|
+
] = typer.Option(
|
|
435
|
+
[],
|
|
436
|
+
"--type",
|
|
437
|
+
help="Restrict results to specific record type. Can be specified multiple times.",
|
|
438
|
+
),
|
|
439
|
+
scopes: Annotated[list[str], typer.Option()] = typer.Option(
|
|
440
|
+
[],
|
|
441
|
+
"--scope",
|
|
442
|
+
help="Restrict results to a specific scope name. Can be specified multiple times.",
|
|
443
|
+
),
|
|
444
|
+
consumer_org: str = typer.Option(
|
|
445
|
+
default="", help="The name of the consumer organization."
|
|
446
|
+
),
|
|
447
|
+
consumer_account: str = typer.Option(
|
|
448
|
+
default="",
|
|
449
|
+
help="The name of the consumer account in the organization.",
|
|
450
|
+
),
|
|
451
|
+
consumer_app_hash: str = typer.Option(
|
|
452
|
+
default="",
|
|
453
|
+
help="The SHA-1 hash of the consumer application name",
|
|
454
|
+
),
|
|
455
|
+
first: int = typer.Option(
|
|
456
|
+
default=-1,
|
|
457
|
+
show_default=False,
|
|
458
|
+
help="Fetch only the first N events. Cannot be used with --last.",
|
|
459
|
+
),
|
|
460
|
+
last: int = typer.Option(
|
|
461
|
+
default=-1,
|
|
462
|
+
show_default=False,
|
|
463
|
+
help="Fetch only the last N events. Cannot be used with --first.",
|
|
464
|
+
),
|
|
465
|
+
follow: bool = typer.Option(
|
|
466
|
+
False,
|
|
467
|
+
"--follow",
|
|
468
|
+
"-f",
|
|
469
|
+
help=(
|
|
470
|
+
f"Continue polling for events. Implies --last {DEFAULT_EVENT_FOLLOW_LAST} "
|
|
471
|
+
f"unless overridden or the --since flag is used."
|
|
472
|
+
),
|
|
473
|
+
),
|
|
474
|
+
follow_interval: int = typer.Option(
|
|
475
|
+
10,
|
|
476
|
+
help=f"Polling interval in seconds when using the --follow flag.",
|
|
477
|
+
),
|
|
478
|
+
**options,
|
|
479
|
+
):
|
|
480
|
+
"""Fetches events for this app from the event table configured in Snowflake.
|
|
481
|
+
|
|
482
|
+
By default, this command will fetch events generated by an app installed in the
|
|
483
|
+
current connection's account. To fetch events generated by an app installed
|
|
484
|
+
in a consumer account, use the --consumer-org and --consumer-account options.
|
|
485
|
+
This requires event sharing to be set up to route events to the provider account:
|
|
486
|
+
https://docs.snowflake.com/en/developer-guide/native-apps/setting-up-logging-and-events
|
|
487
|
+
"""
|
|
488
|
+
if first >= 0 and last >= 0:
|
|
489
|
+
raise IncompatibleParametersError(["--first", "--last"])
|
|
490
|
+
|
|
491
|
+
if (consumer_org and not consumer_account) or (
|
|
492
|
+
consumer_account and not consumer_org
|
|
493
|
+
):
|
|
494
|
+
raise IncompatibleParametersError(["--consumer-org", "--consumer-account"])
|
|
495
|
+
|
|
496
|
+
if follow:
|
|
497
|
+
if until:
|
|
498
|
+
raise IncompatibleParametersError(["--follow", "--until"])
|
|
499
|
+
if first >= 0:
|
|
500
|
+
raise IncompatibleParametersError(["--follow", "--first"])
|
|
501
|
+
|
|
412
502
|
assert_project_type("native_app")
|
|
413
503
|
|
|
504
|
+
record_type_names = [r.name for r in record_types]
|
|
414
505
|
manager = NativeAppManager(
|
|
415
|
-
project_definition=
|
|
416
|
-
project_root=
|
|
506
|
+
project_definition=get_cli_context().project_definition.native_app,
|
|
507
|
+
project_root=get_cli_context().project_root,
|
|
417
508
|
)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
509
|
+
if follow:
|
|
510
|
+
if last == -1 and not since:
|
|
511
|
+
# If we don't have a value for --last or --since, assume a value
|
|
512
|
+
# for --last so we at least print something before starting the stream
|
|
513
|
+
last = DEFAULT_EVENT_FOLLOW_LAST
|
|
514
|
+
stream: Iterable[CommandResult] = (
|
|
515
|
+
EventResult(event)
|
|
516
|
+
for event in manager.stream_events(
|
|
517
|
+
since=since,
|
|
518
|
+
last=last,
|
|
519
|
+
interval_seconds=follow_interval,
|
|
520
|
+
record_types=record_type_names,
|
|
521
|
+
scopes=scopes,
|
|
522
|
+
consumer_org=consumer_org,
|
|
523
|
+
consumer_account=consumer_account,
|
|
524
|
+
consumer_app_hash=consumer_app_hash,
|
|
525
|
+
)
|
|
526
|
+
)
|
|
527
|
+
# Append a newline at the end to make the CLI output clean when we hit Ctrl-C
|
|
528
|
+
stream = itertools.chain(stream, [MessageResult("")])
|
|
529
|
+
else:
|
|
530
|
+
stream = (
|
|
531
|
+
EventResult(event)
|
|
532
|
+
for event in manager.get_events(
|
|
533
|
+
since=since,
|
|
534
|
+
until=until,
|
|
535
|
+
record_types=record_type_names,
|
|
536
|
+
scopes=scopes,
|
|
537
|
+
first=first,
|
|
538
|
+
last=last,
|
|
539
|
+
consumer_org=consumer_org,
|
|
540
|
+
consumer_account=consumer_account,
|
|
541
|
+
consumer_app_hash=consumer_app_hash,
|
|
542
|
+
)
|
|
543
|
+
)
|
|
425
544
|
|
|
426
|
-
|
|
545
|
+
# Cast the stream to a Generator since that's what StreamResult wants
|
|
546
|
+
return StreamResult(cast(Generator[CommandResult, None, None], stream))
|
|
427
547
|
|
|
428
548
|
|
|
429
549
|
class EventResult(ObjectResult, MessageResult):
|