Skip to content

Commit a218395

Browse files
authored
Add suspend/resume engine to the api (#150)
* Add suspend/resume engine to the api * Fix docs * Feedback changes
1 parent d7edf5d commit a218395

File tree

5 files changed

+120
-1
lines changed

5 files changed

+120
-1
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## v0.6.20
4+
5+
* Add suspend/resume engine to the api
6+
* Add examples for suspend/resume
7+
38
## v0.6.19
49

510
* Fix setting of created_on attribute on AccessToken

examples/resume_engine.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2021 RelationalAI, 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+
"""Resume an engine."""
16+
17+
from argparse import ArgumentParser
18+
import json
19+
import time
20+
from urllib.request import HTTPError
21+
from railib import api, config, show
22+
23+
24+
def run(engine: str, profile: str):
25+
cfg = config.read(profile=profile)
26+
ctx = api.Context(**cfg)
27+
api.resume_engine_wait(ctx, engine)
28+
print(json.dumps(api.get_engine(ctx, engine), indent=2))
29+
30+
31+
if __name__ == "__main__":
32+
p = ArgumentParser()
33+
p.add_argument("engine", type=str, help="engine name")
34+
p.add_argument("-p", "--profile", type=str, help="profile name", default="default")
35+
args = p.parse_args()
36+
try:
37+
run(args.engine, args.profile)
38+
except HTTPError as e:
39+
show.http_error(e)

examples/suspend_engine.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2021 RelationalAI, 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+
"""Suspend an engine."""
16+
17+
from argparse import ArgumentParser
18+
import json
19+
import time
20+
from urllib.request import HTTPError
21+
from railib import api, config, show
22+
23+
24+
# Answers if the given state is a terminal state.
25+
def is_term_state(state: str) -> bool:
26+
return state == "SUSPENDED" or ("FAILED" in state)
27+
28+
29+
def run(engine: str, profile: str):
30+
cfg = config.read(profile=profile)
31+
ctx = api.Context(**cfg)
32+
rsp = api.suspend_engine(ctx, engine)
33+
while True: # wait for request to reach terminal state
34+
time.sleep(3)
35+
rsp = api.get_engine(ctx, engine)
36+
if not rsp or is_term_state(rsp["state"]):
37+
break
38+
print(json.dumps(rsp, indent=2))
39+
40+
41+
if __name__ == "__main__":
42+
p = ArgumentParser()
43+
p.add_argument("engine", type=str, help="engine name")
44+
p.add_argument("-p", "--profile", type=str, help="profile name", default="default")
45+
args = p.parse_args()
46+
try:
47+
run(args.engine, args.profile)
48+
except HTTPError as e:
49+
show.http_error(e)

railib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
__version_info__ = (0, 7, 3)
15+
__version_info__ = (0, 7, 4)
1616
__version__ = ".".join(map(str, __version_info__))

railib/api.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ class Permission(str, Enum):
135135
"list_oauth_clients",
136136
"load_csv",
137137
"update_user",
138+
"suspend_engine",
139+
"resume_engine",
138140
]
139141

140142

@@ -373,6 +375,30 @@ def create_engine_wait(ctx: Context, engine: str, size: str = "XS", **kwargs):
373375
return get_engine(ctx, engine)
374376

375377

378+
def suspend_engine(ctx: Context, engine: str, **kwargs):
379+
data = {"suspend": True}
380+
url = _mkurl(ctx, f"{PATH_ENGINE}/{engine}")
381+
rsp = rest.patch(ctx, url, data, **kwargs)
382+
return json.loads(rsp.read())
383+
384+
385+
def resume_engine(ctx: Context, engine: str, **kwargs):
386+
data = {"suspend": False}
387+
url = _mkurl(ctx, f"{PATH_ENGINE}/{engine}")
388+
rsp = rest.patch(ctx, url, data, **kwargs)
389+
return json.loads(rsp.read())
390+
391+
392+
def resume_engine_wait(ctx: Context, engine: str, **kwargs):
393+
resume_engine(ctx, engine, **kwargs)
394+
poll_with_specified_overhead(
395+
lambda: is_engine_term_state(get_engine(ctx, engine)["state"]),
396+
overhead_rate=0.2,
397+
timeout=30 * 60,
398+
)
399+
return get_engine(ctx, engine)
400+
401+
376402
def create_user(ctx: Context, email: str, roles: List[Role] = None, **kwargs):
377403
rs = roles or []
378404
data = {"email": email, "roles": [r.value for r in rs]}

0 commit comments

Comments
 (0)