snowflake-cli 3.4.1__py3-none-any.whl → 3.6.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 +13 -1
- snowflake/cli/_app/cli_app.py +1 -10
- snowflake/cli/_app/commands_registration/builtin_plugins.py +7 -1
- snowflake/cli/_app/commands_registration/command_plugins_loader.py +3 -1
- snowflake/cli/_app/commands_registration/commands_registration_with_callbacks.py +3 -3
- snowflake/cli/_app/printing.py +2 -2
- snowflake/cli/_app/snow_connector.py +5 -4
- snowflake/cli/_app/telemetry.py +3 -15
- snowflake/cli/_app/version_check.py +4 -4
- snowflake/cli/_plugins/auth/__init__.py +11 -0
- snowflake/cli/_plugins/auth/keypair/__init__.py +0 -0
- snowflake/cli/_plugins/auth/keypair/commands.py +151 -0
- snowflake/cli/_plugins/auth/keypair/manager.py +331 -0
- snowflake/cli/_plugins/auth/keypair/plugin_spec.py +30 -0
- snowflake/cli/_plugins/connection/commands.py +79 -5
- snowflake/cli/_plugins/helpers/commands.py +3 -4
- snowflake/cli/_plugins/nativeapp/entities/application.py +4 -1
- snowflake/cli/_plugins/nativeapp/sf_sql_facade.py +33 -6
- snowflake/cli/_plugins/notebook/commands.py +3 -4
- snowflake/cli/_plugins/object/command_aliases.py +3 -1
- snowflake/cli/_plugins/object/manager.py +4 -2
- snowflake/cli/_plugins/plugin/commands.py +79 -0
- snowflake/cli/_plugins/plugin/manager.py +74 -0
- snowflake/cli/_plugins/plugin/plugin_spec.py +30 -0
- snowflake/cli/_plugins/project/__init__.py +0 -0
- snowflake/cli/_plugins/project/commands.py +173 -0
- snowflake/cli/{_app/api_impl/plugin/__init__.py → _plugins/project/feature_flags.py} +9 -0
- snowflake/cli/_plugins/project/manager.py +76 -0
- snowflake/cli/_plugins/project/plugin_spec.py +30 -0
- snowflake/cli/_plugins/project/project_entity_model.py +40 -0
- snowflake/cli/_plugins/snowpark/commands.py +2 -1
- snowflake/cli/_plugins/spcs/compute_pool/commands.py +70 -10
- snowflake/cli/_plugins/spcs/compute_pool/compute_pool_entity.py +8 -0
- snowflake/cli/_plugins/spcs/compute_pool/compute_pool_entity_model.py +37 -0
- snowflake/cli/_plugins/spcs/compute_pool/manager.py +45 -0
- snowflake/cli/_plugins/spcs/image_repository/commands.py +29 -0
- snowflake/cli/_plugins/spcs/image_repository/image_repository_entity.py +8 -0
- snowflake/cli/_plugins/spcs/image_repository/image_repository_entity_model.py +8 -0
- snowflake/cli/_plugins/spcs/image_repository/manager.py +1 -1
- snowflake/cli/_plugins/spcs/services/commands.py +53 -0
- snowflake/cli/_plugins/spcs/services/manager.py +114 -0
- snowflake/cli/_plugins/spcs/services/service_entity.py +6 -0
- snowflake/cli/_plugins/spcs/services/service_entity_model.py +45 -0
- snowflake/cli/_plugins/spcs/services/service_project_paths.py +15 -0
- snowflake/cli/_plugins/sql/manager.py +42 -51
- snowflake/cli/_plugins/sql/source_reader.py +230 -0
- snowflake/cli/_plugins/stage/manager.py +10 -4
- snowflake/cli/_plugins/streamlit/commands.py +9 -24
- snowflake/cli/_plugins/streamlit/manager.py +5 -36
- snowflake/cli/api/artifacts/upload.py +51 -0
- snowflake/cli/api/commands/flags.py +35 -10
- snowflake/cli/api/commands/snow_typer.py +12 -0
- snowflake/cli/api/commands/utils.py +2 -0
- snowflake/cli/api/config.py +15 -10
- snowflake/cli/api/constants.py +2 -0
- snowflake/cli/api/errno.py +1 -0
- snowflake/cli/api/exceptions.py +15 -1
- snowflake/cli/api/feature_flags.py +2 -0
- snowflake/cli/api/plugins/plugin_config.py +43 -4
- snowflake/cli/api/project/definition_helper.py +31 -0
- snowflake/cli/api/project/schemas/entities/entities.py +26 -0
- snowflake/cli/api/rest_api.py +2 -3
- snowflake/cli/{_app → api}/secret.py +4 -1
- snowflake/cli/api/secure_path.py +16 -4
- snowflake/cli/api/sql_execution.py +7 -3
- {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/METADATA +12 -12
- {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/RECORD +71 -50
- snowflake/cli/_app/api_impl/plugin/plugin_config_provider_impl.py +0 -66
- snowflake/cli/api/__init__.py +0 -48
- /snowflake/cli/{_app/api_impl → _plugins/plugin}/__init__.py +0 -0
- {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/WHEEL +0 -0
- {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/entry_points.txt +0 -0
- {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
import logging
|
|
18
|
+
from typing import Dict, List
|
|
19
|
+
|
|
20
|
+
import typer
|
|
21
|
+
from snowflake.cli._plugins.plugin.manager import PluginManager
|
|
22
|
+
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
23
|
+
from snowflake.cli.api.output.types import (
|
|
24
|
+
CollectionResult,
|
|
25
|
+
CommandResult,
|
|
26
|
+
MessageResult,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
log = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
app = SnowTyperFactory(
|
|
32
|
+
name="plugin",
|
|
33
|
+
help="Plugin management commands.",
|
|
34
|
+
is_hidden=lambda: True,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@app.command(name="enable", requires_connection=False)
|
|
39
|
+
def enable(
|
|
40
|
+
plugin_name: str = typer.Argument(None, help="Plugin name"),
|
|
41
|
+
**options,
|
|
42
|
+
) -> CommandResult:
|
|
43
|
+
"""Enables a plugin with a given name."""
|
|
44
|
+
plugin_manager = PluginManager()
|
|
45
|
+
plugin_manager.assert_plugin_is_installed(plugin_name)
|
|
46
|
+
plugin_manager.enable_plugin(plugin_name)
|
|
47
|
+
|
|
48
|
+
return MessageResult(f"Plugin {plugin_name} successfully enabled.")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@app.command(name="disable", requires_connection=False)
|
|
52
|
+
def disable(
|
|
53
|
+
plugin_name: str = typer.Argument(None, help="Plugin name"),
|
|
54
|
+
**options,
|
|
55
|
+
) -> CommandResult:
|
|
56
|
+
"""Disables a plugin with a given name."""
|
|
57
|
+
plugin_manager = PluginManager()
|
|
58
|
+
plugin_manager.assert_plugin_is_installed(plugin_name)
|
|
59
|
+
plugin_manager.disable_plugin(plugin_name)
|
|
60
|
+
|
|
61
|
+
return MessageResult(f"Plugin {plugin_name} successfully disabled.")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@app.command(name="list", requires_connection=False)
|
|
65
|
+
def list_(
|
|
66
|
+
**options,
|
|
67
|
+
) -> CommandResult:
|
|
68
|
+
"""Lists all installed plugins."""
|
|
69
|
+
plugin_manager = PluginManager()
|
|
70
|
+
result: List[Dict[str, str]] = []
|
|
71
|
+
for plugin_name in sorted(plugin_manager.get_installed_plugin_names()):
|
|
72
|
+
result.append(
|
|
73
|
+
{
|
|
74
|
+
"plugin name": plugin_name,
|
|
75
|
+
"enabled": plugin_manager.is_plugin_enabled(plugin_name),
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return CollectionResult(result)
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
import importlib
|
|
15
|
+
from typing import List
|
|
16
|
+
|
|
17
|
+
from snowflake.cli.api.config import (
|
|
18
|
+
PLUGIN_ENABLED_KEY,
|
|
19
|
+
PLUGINS_SECTION_PATH,
|
|
20
|
+
config_section_exists,
|
|
21
|
+
get_config_section,
|
|
22
|
+
set_config_value,
|
|
23
|
+
)
|
|
24
|
+
from snowflake.cli.api.exceptions import PluginNotInstalledError
|
|
25
|
+
from snowflake.cli.api.plugins.command import SNOWCLI_COMMAND_PLUGIN_NAMESPACE
|
|
26
|
+
from snowflake.cli.api.plugins.plugin_config import PluginConfigProvider
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PluginManager:
|
|
30
|
+
"""
|
|
31
|
+
Manage installation of plugins.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def enable_plugin(self, plugin_name: str):
|
|
35
|
+
self._change_plugin_enabled(plugin_name, enable=True)
|
|
36
|
+
|
|
37
|
+
def disable_plugin(self, plugin_name: str):
|
|
38
|
+
self._change_plugin_enabled(plugin_name, enable=False)
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def _change_plugin_enabled(plugin_name: str, enable: bool):
|
|
42
|
+
plugin_config_path = PLUGINS_SECTION_PATH + [plugin_name]
|
|
43
|
+
|
|
44
|
+
if config_section_exists(*plugin_config_path):
|
|
45
|
+
plugin_config = get_config_section(*plugin_config_path)
|
|
46
|
+
elif enable:
|
|
47
|
+
plugin_config = {}
|
|
48
|
+
else:
|
|
49
|
+
# do not add a new plugin config if user wants to disable a plugin which is not configured
|
|
50
|
+
# (plugins are disabled by default)
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
plugin_config[PLUGIN_ENABLED_KEY] = enable
|
|
54
|
+
set_config_value(path=plugin_config_path, value=plugin_config)
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def is_plugin_enabled(plugin_name: str) -> bool:
|
|
58
|
+
return PluginConfigProvider.get_config(plugin_name).is_plugin_enabled
|
|
59
|
+
|
|
60
|
+
def assert_plugin_is_installed(self, plugin_name: str):
|
|
61
|
+
installed_plugins = self.get_installed_plugin_names()
|
|
62
|
+
if plugin_name not in installed_plugins:
|
|
63
|
+
raise PluginNotInstalledError(
|
|
64
|
+
plugin_name, installed_plugins=sorted(installed_plugins)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def get_installed_plugin_names() -> List[str]:
|
|
69
|
+
return [
|
|
70
|
+
entry_point.name
|
|
71
|
+
for entry_point in importlib.metadata.entry_points(
|
|
72
|
+
group=SNOWCLI_COMMAND_PLUGIN_NAMESPACE
|
|
73
|
+
)
|
|
74
|
+
]
|
|
@@ -0,0 +1,30 @@
|
|
|
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 snowflake.cli._plugins.plugin import commands
|
|
16
|
+
from snowflake.cli.api.plugins.command import (
|
|
17
|
+
SNOWCLI_ROOT_COMMAND_PATH,
|
|
18
|
+
CommandSpec,
|
|
19
|
+
CommandType,
|
|
20
|
+
plugin_hook_impl,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@plugin_hook_impl
|
|
25
|
+
def command_spec():
|
|
26
|
+
return CommandSpec(
|
|
27
|
+
parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
|
|
28
|
+
command_type=CommandType.COMMAND_GROUP,
|
|
29
|
+
typer_instance=commands.app.create_instance(),
|
|
30
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,173 @@
|
|
|
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 typing import List, Optional
|
|
16
|
+
|
|
17
|
+
import typer
|
|
18
|
+
from snowflake.cli._plugins.object.command_aliases import add_object_command_aliases
|
|
19
|
+
from snowflake.cli._plugins.object.commands import scope_option
|
|
20
|
+
from snowflake.cli._plugins.project.feature_flags import FeatureFlag
|
|
21
|
+
from snowflake.cli._plugins.project.manager import ProjectManager
|
|
22
|
+
from snowflake.cli._plugins.project.project_entity_model import (
|
|
23
|
+
ProjectEntityModel,
|
|
24
|
+
)
|
|
25
|
+
from snowflake.cli._plugins.stage.manager import StageManager
|
|
26
|
+
from snowflake.cli.api.artifacts.upload import put_files
|
|
27
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
28
|
+
from snowflake.cli.api.commands.decorators import with_project_definition
|
|
29
|
+
from snowflake.cli.api.commands.flags import (
|
|
30
|
+
entity_argument,
|
|
31
|
+
identifier_argument,
|
|
32
|
+
like_option,
|
|
33
|
+
variables_option,
|
|
34
|
+
)
|
|
35
|
+
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
36
|
+
from snowflake.cli.api.commands.utils import get_entity_for_operation
|
|
37
|
+
from snowflake.cli.api.console.console import cli_console
|
|
38
|
+
from snowflake.cli.api.constants import ObjectType
|
|
39
|
+
from snowflake.cli.api.identifiers import FQN
|
|
40
|
+
from snowflake.cli.api.output.types import MessageResult, SingleQueryResult
|
|
41
|
+
from snowflake.cli.api.project.project_paths import ProjectPaths
|
|
42
|
+
|
|
43
|
+
app = SnowTyperFactory(
|
|
44
|
+
name="project",
|
|
45
|
+
help="Manages projects in Snowflake.",
|
|
46
|
+
is_hidden=FeatureFlag.ENABLE_SNOWFLAKE_PROJECTS.is_disabled,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
project_identifier = identifier_argument(sf_object="project", example="MY_PROJECT")
|
|
50
|
+
version_flag = typer.Option(
|
|
51
|
+
..., "--version", help="Version of the project to use.", show_default=False
|
|
52
|
+
)
|
|
53
|
+
variables_flag = variables_option(
|
|
54
|
+
'Variables for the execution context; for example: `-D "<key>=<value>"`.'
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
add_object_command_aliases(
|
|
59
|
+
app=app,
|
|
60
|
+
object_type=ObjectType.PROJECT,
|
|
61
|
+
name_argument=project_identifier,
|
|
62
|
+
like_option=like_option(
|
|
63
|
+
help_example='`list --like "my%"` lists all projects that begin with “my”'
|
|
64
|
+
),
|
|
65
|
+
scope_option=scope_option(help_example="`list --in database my_db`"),
|
|
66
|
+
ommit_commands=["drop", "create", "describe"],
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@app.command(requires_connection=True)
|
|
71
|
+
def execute(
|
|
72
|
+
identifier: FQN = project_identifier,
|
|
73
|
+
version: str = version_flag,
|
|
74
|
+
variables: Optional[List[str]] = variables_flag,
|
|
75
|
+
**options,
|
|
76
|
+
):
|
|
77
|
+
"""
|
|
78
|
+
Executes a project.
|
|
79
|
+
"""
|
|
80
|
+
result = ProjectManager().execute(
|
|
81
|
+
project_name=identifier, version=version, variables=variables
|
|
82
|
+
)
|
|
83
|
+
return SingleQueryResult(result)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@app.command(requires_connection=True)
|
|
87
|
+
def dry_run(
|
|
88
|
+
identifier: FQN = project_identifier,
|
|
89
|
+
version: str = version_flag,
|
|
90
|
+
variables: Optional[List[str]] = variables_flag,
|
|
91
|
+
**options,
|
|
92
|
+
):
|
|
93
|
+
"""
|
|
94
|
+
Validates a project.
|
|
95
|
+
"""
|
|
96
|
+
result = ProjectManager().execute(
|
|
97
|
+
project_name=identifier, version=version, dry_run=True, variables=variables
|
|
98
|
+
)
|
|
99
|
+
return SingleQueryResult(result)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@app.command(requires_connection=True)
|
|
103
|
+
@with_project_definition()
|
|
104
|
+
def create_version(
|
|
105
|
+
entity_id: str = entity_argument("project"),
|
|
106
|
+
**options,
|
|
107
|
+
):
|
|
108
|
+
"""
|
|
109
|
+
Upload local files and create a new version of a project using those files. If the stage does not exist, it will be created.
|
|
110
|
+
"""
|
|
111
|
+
cli_context = get_cli_context()
|
|
112
|
+
project: ProjectEntityModel = get_entity_for_operation(
|
|
113
|
+
cli_context=cli_context,
|
|
114
|
+
entity_id=entity_id,
|
|
115
|
+
project_definition=cli_context.project_definition,
|
|
116
|
+
entity_type="project",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Sync state
|
|
120
|
+
with cli_console.phase("Syncing project state"):
|
|
121
|
+
stage_name = FQN.from_stage(project.stage)
|
|
122
|
+
sm = StageManager()
|
|
123
|
+
|
|
124
|
+
cli_console.step(f"Creating stage {stage_name}")
|
|
125
|
+
sm.create(fqn=stage_name)
|
|
126
|
+
|
|
127
|
+
put_files(
|
|
128
|
+
project_paths=ProjectPaths(project_root=cli_context.project_root),
|
|
129
|
+
stage_root=project.stage,
|
|
130
|
+
artifacts=project.artifacts,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Create project and version
|
|
134
|
+
with cli_console.phase("Creating project and version"):
|
|
135
|
+
pm = ProjectManager()
|
|
136
|
+
cli_console.step(f"Creating project {project.fqn}")
|
|
137
|
+
pm.create(project_name=project.fqn)
|
|
138
|
+
|
|
139
|
+
cli_console.step(f"Creating version from stage {stage_name}")
|
|
140
|
+
pm.create_version(project_name=project.fqn, stage_name=stage_name)
|
|
141
|
+
return MessageResult(f"Project {project.fqn} deployed.")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@app.command(requires_connection=True)
|
|
145
|
+
@with_project_definition()
|
|
146
|
+
def add_version(
|
|
147
|
+
entity_id: str = entity_argument("project"),
|
|
148
|
+
_from: str = typer.Option(
|
|
149
|
+
...,
|
|
150
|
+
"--from",
|
|
151
|
+
help="Source stage to create the version from.",
|
|
152
|
+
show_default=False,
|
|
153
|
+
),
|
|
154
|
+
alias: str
|
|
155
|
+
| None = typer.Option(
|
|
156
|
+
None, "--alias", help="Alias for the version.", show_default=False
|
|
157
|
+
),
|
|
158
|
+
comment: str
|
|
159
|
+
| None = typer.Option(
|
|
160
|
+
None, "--comment", help="Version comment.", show_default=False
|
|
161
|
+
),
|
|
162
|
+
**options,
|
|
163
|
+
):
|
|
164
|
+
"""Adds a new version to a project using existing sources from provided stage path."""
|
|
165
|
+
|
|
166
|
+
pm = ProjectManager()
|
|
167
|
+
pm.add_version(
|
|
168
|
+
project_name=entity_id,
|
|
169
|
+
from_stage=_from,
|
|
170
|
+
alias=alias,
|
|
171
|
+
comment=comment,
|
|
172
|
+
)
|
|
173
|
+
return MessageResult("Version added.")
|
|
@@ -11,3 +11,12 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from enum import unique
|
|
16
|
+
|
|
17
|
+
from snowflake.cli.api.feature_flags import BooleanFlag, FeatureFlagMixin
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@unique
|
|
21
|
+
class FeatureFlag(FeatureFlagMixin):
|
|
22
|
+
ENABLE_SNOWFLAKE_PROJECTS = BooleanFlag("ENABLE_SNOWFLAKE_PROJECTS", False)
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
from textwrap import dedent
|
|
15
|
+
from typing import List
|
|
16
|
+
|
|
17
|
+
from snowflake.cli._plugins.stage.manager import StageManager
|
|
18
|
+
from snowflake.cli.api.commands.utils import parse_key_value_variables
|
|
19
|
+
from snowflake.cli.api.identifiers import FQN
|
|
20
|
+
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
21
|
+
from snowflake.cli.api.stage_path import StagePath
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ProjectManager(SqlExecutionMixin):
|
|
25
|
+
def execute(
|
|
26
|
+
self,
|
|
27
|
+
project_name: FQN,
|
|
28
|
+
version: str | None = None,
|
|
29
|
+
variables: List[str] | None = None,
|
|
30
|
+
dry_run: bool = False,
|
|
31
|
+
):
|
|
32
|
+
query = f"EXECUTE PROJECT {project_name.sql_identifier}"
|
|
33
|
+
if variables:
|
|
34
|
+
query += StageManager.parse_execute_variables(
|
|
35
|
+
parse_key_value_variables(variables)
|
|
36
|
+
)
|
|
37
|
+
if version:
|
|
38
|
+
query += f" WITH VERSION {version}"
|
|
39
|
+
if dry_run:
|
|
40
|
+
query += " DRY_RUN=TRUE"
|
|
41
|
+
return self.execute_query(query=query)
|
|
42
|
+
|
|
43
|
+
def create(
|
|
44
|
+
self,
|
|
45
|
+
project_name: FQN,
|
|
46
|
+
) -> str:
|
|
47
|
+
queries = dedent(f"CREATE PROJECT IF NOT EXISTS {project_name.sql_identifier}")
|
|
48
|
+
return self.execute_query(query=queries)
|
|
49
|
+
|
|
50
|
+
def create_version(self, project_name: FQN, stage_name: FQN):
|
|
51
|
+
return self.add_version(
|
|
52
|
+
project_name=project_name,
|
|
53
|
+
from_stage=StagePath.from_stage_str(stage_name).absolute_path(
|
|
54
|
+
at_prefix=True
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def add_version(
|
|
59
|
+
self,
|
|
60
|
+
project_name: str | FQN,
|
|
61
|
+
from_stage: str,
|
|
62
|
+
alias: str | None = None,
|
|
63
|
+
comment: str | None = None,
|
|
64
|
+
):
|
|
65
|
+
project_name = (
|
|
66
|
+
project_name
|
|
67
|
+
if isinstance(project_name, FQN)
|
|
68
|
+
else FQN.from_string(project_name)
|
|
69
|
+
)
|
|
70
|
+
query = f"ALTER PROJECT {project_name.identifier} ADD VERSION"
|
|
71
|
+
if alias:
|
|
72
|
+
query += f" IF NOT EXIST {alias}"
|
|
73
|
+
query += f" FROM {from_stage}"
|
|
74
|
+
if comment:
|
|
75
|
+
query += f" COMMENT = '{comment}'"
|
|
76
|
+
return self.execute_query(query=query)
|
|
@@ -0,0 +1,30 @@
|
|
|
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 snowflake.cli._plugins.project import commands
|
|
16
|
+
from snowflake.cli.api.plugins.command import (
|
|
17
|
+
SNOWCLI_ROOT_COMMAND_PATH,
|
|
18
|
+
CommandSpec,
|
|
19
|
+
CommandType,
|
|
20
|
+
plugin_hook_impl,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@plugin_hook_impl
|
|
25
|
+
def command_spec():
|
|
26
|
+
return CommandSpec(
|
|
27
|
+
parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
|
|
28
|
+
command_type=CommandType.COMMAND_GROUP,
|
|
29
|
+
typer_instance=commands.app.create_instance(),
|
|
30
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import Literal, Optional, TypeVar
|
|
17
|
+
|
|
18
|
+
from pydantic import Field
|
|
19
|
+
from snowflake.cli.api.entities.common import EntityBase, attach_spans_to_entity_actions
|
|
20
|
+
from snowflake.cli.api.project.schemas.entities.common import (
|
|
21
|
+
EntityModelBaseWithArtifacts,
|
|
22
|
+
)
|
|
23
|
+
from snowflake.cli.api.project.schemas.updatable_model import (
|
|
24
|
+
DiscriminatorField,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
T = TypeVar("T")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ProjectEntityModel(EntityModelBaseWithArtifacts):
|
|
31
|
+
type: Literal["project"] = DiscriminatorField() # noqa: A003
|
|
32
|
+
stage: Optional[str] = Field(
|
|
33
|
+
title="Stage in which the project artifacts will be stored", default=None
|
|
34
|
+
)
|
|
35
|
+
main_file: Optional[str] = Field(title="Path to the main file of the project")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@attach_spans_to_entity_actions(entity_name="project")
|
|
39
|
+
class ProjectEntity(EntityBase[ProjectEntityModel]):
|
|
40
|
+
"""Placeholder for project entity"""
|
|
@@ -129,7 +129,8 @@ LikeOption = like_option(
|
|
|
129
129
|
@with_project_definition()
|
|
130
130
|
def deploy(
|
|
131
131
|
replace: bool = ReplaceOption(
|
|
132
|
-
help="Replaces procedure or function if there were changes in the definition."
|
|
132
|
+
help="Replaces procedure or function if there were changes in the definition. It only uploads new and "
|
|
133
|
+
"overwrites existing files, but does not remove any files already on the stage."
|
|
133
134
|
),
|
|
134
135
|
force_replace: bool = ForceReplaceOption(),
|
|
135
136
|
**options,
|