Skip to content

Commit 70d41ec

Browse files
fix: Fir 35673 python sdk engine update fix renaming (#399)
1 parent 8568f9c commit 70d41ec

File tree

2 files changed

+62
-18
lines changed

2 files changed

+62
-18
lines changed

src/firebolt/model/V2/engine.py

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from __future__ import annotations
22

33
import logging
4+
import re
45
import time
56
from dataclasses import dataclass, field
6-
from typing import TYPE_CHECKING, ClassVar, Optional, Tuple, Union
7+
from typing import TYPE_CHECKING, ClassVar, List, Optional, Tuple, Union
78

89
from firebolt.db import Connection, connect
910
from firebolt.model.V2 import FireboltBaseModel
@@ -26,15 +27,17 @@ class Engine(FireboltBaseModel):
2627

2728
START_SQL: ClassVar[str] = 'START ENGINE "{}"'
2829
STOP_SQL: ClassVar[str] = 'STOP ENGINE "{}"'
29-
ALTER_PREFIX_SQL: ClassVar[str] = 'ALTER ENGINE "{}" SET '
30+
ALTER_PREFIX_SQL: ClassVar[str] = 'ALTER ENGINE "{}" '
3031
ALTER_PARAMETER_NAMES: ClassVar[Tuple] = (
3132
"NODES",
3233
"TYPE",
3334
"AUTO_STOP",
34-
"RENAME_TO",
3535
)
3636
DROP_SQL: ClassVar[str] = 'DROP ENGINE "{}"'
3737

38+
# Engine names can only contain alphanumeric characters and underscores
39+
_engine_name_re = re.compile(r"^[a-zA-Z0-9_]+$")
40+
3841
_service: EngineService = field(repr=False, compare=False)
3942

4043
name: str = field(metadata={"db_name": "engine_name"})
@@ -69,11 +72,11 @@ def database(self) -> Optional[Database]:
6972
pass
7073
return None
7174

72-
def refresh(self) -> None:
75+
def refresh(self, name: Optional[str] = None) -> None:
7376
"""Update attributes of the instance from Firebolt."""
7477
field_name_overrides = self._get_field_overrides()
75-
for name, value in self._service._get_dict(self.name).items():
76-
setattr(self, field_name_overrides.get(name, name), value)
78+
for field_name, value in self._service._get_dict(name or self.name).items():
79+
setattr(self, field_name_overrides.get(field_name, field_name), value)
7780

7881
self.__post_init__()
7982

@@ -194,6 +197,9 @@ def update(
194197
# Nothing to be updated
195198
return self
196199

200+
if name is not None and any(x is not None for x in (scale, spec, auto_stop)):
201+
raise ValueError("Cannot update name and other parameters at the same time")
202+
197203
self.refresh()
198204
self._wait_for_start_stop()
199205
if self.current_status in (EngineStatus.DROPPING, EngineStatus.REPAIRING):
@@ -203,21 +209,31 @@ def update(
203209
)
204210

205211
sql = self.ALTER_PREFIX_SQL.format(self.name)
206-
parameters = []
207-
for param, value in zip(
208-
self.ALTER_PARAMETER_NAMES,
209-
(scale, spec, auto_stop, name),
210-
):
211-
if value is not None:
212-
sql_part, new_params = self._service._format_engine_attribute_sql(
213-
param, value
212+
parameters: List[Union[str, int]] = []
213+
if name is not None:
214+
if not self._engine_name_re.match(name):
215+
raise ValueError(
216+
f"Engine name {name} is invalid, "
217+
"it must only contain alphanumeric characters and underscores."
214218
)
215-
sql += sql_part
216-
parameters.extend(new_params)
219+
sql += f" RENAME TO {name}"
220+
else:
221+
sql += " SET "
222+
parameters = []
223+
for param, value in zip(
224+
self.ALTER_PARAMETER_NAMES,
225+
(scale, spec, auto_stop),
226+
):
227+
if value is not None:
228+
sql_part, new_params = self._service._format_engine_attribute_sql(
229+
param, value
230+
)
231+
sql += sql_part
232+
parameters.extend(new_params)
217233

218234
with self._service._connection.cursor() as c:
219235
c.execute(sql, parameters)
220-
self.refresh()
236+
self.refresh(name)
221237
return self
222238

223239
def delete(self) -> None:

tests/integration/resource_manager/V2/test_engine.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from collections import namedtuple
22

3-
from pytest import mark
3+
from pytest import mark, raises
44

55
from firebolt.client.auth import Auth
66
from firebolt.service.manager import ResourceManager
@@ -139,3 +139,31 @@ def test_engine_update_multiple_parameters(
139139
finally:
140140
engine.stop()
141141
engine.delete()
142+
143+
144+
def test_engine_rename(
145+
auth: Auth,
146+
account_name: str,
147+
api_endpoint: str,
148+
database_name: str,
149+
engine_name: str,
150+
):
151+
rm = ResourceManager(
152+
auth=auth, account_name=account_name, api_endpoint=api_endpoint
153+
)
154+
name = f"{engine_name}_to_rename"
155+
new_name = f"{engine_name}_renamed"
156+
engine = rm.engines.create(name=name)
157+
158+
try:
159+
with raises(ValueError):
160+
engine.update(name="name; drop database users")
161+
162+
engine.update(name=new_name)
163+
assert engine.name == new_name
164+
165+
new_engine = rm.engines.get(new_name)
166+
assert new_engine.name == new_name
167+
finally:
168+
engine.stop()
169+
engine.delete()

0 commit comments

Comments
 (0)