Prevent creating managed servicesat runtime

This commit is contained in:
Duc Trung LE
2023-05-16 12:02:55 +02:00
parent 9ef5978515
commit 2823c12552
3 changed files with 34 additions and 9 deletions

View File

@@ -176,7 +176,7 @@ In this case, the `url` field will be passed along to the Service as
## Adding or removing services at runtime
Both Hub-Managed services and Externally-Managed services can be added at runtime by using JupyterHubs REST API.
Only externally-managed services can be added at runtime by using JupyterHubs REST API.
### Add a new service
@@ -188,7 +188,7 @@ POST /hub/api/services/:servicename
**Required scope: `admin:services`**
**Payload**: The payload should contain the definition of the service to be created. The endpoint supports the same properties as services defined in the config file.
**Payload**: The payload should contain the definition of the service to be created. The endpoint supports the same properties as externally-managed services defined in the config file.
**Possible responses**

View File

@@ -49,6 +49,11 @@ class ServiceAPIHandler(APIHandler):
self._check_service_model(spec)
service_name = spec["name"]
managed = bool(spec.get('command'))
if managed:
msg = f"Can not create managed service {service_name} at runtime"
self.log.error(msg, exc_info=True)
raise web.HTTPError(400, msg)
try:
new_service = self.service_from_spec(spec)
except Exception:
@@ -64,12 +69,9 @@ class ServiceAPIHandler(APIHandler):
await self.app._add_tokens(
{new_service.api_token: new_service.name}, kind='service'
)
elif new_service.managed:
new_service.api_token = new_service.orm.new_api_token(
note='generated at runtime'
)
if new_service.managed or new_service.url:
service_status = self.app.start_service(service_name, new_service)
if new_service.url:
# Start polling for external service
service_status = await self.app.start_service(service_name, new_service)
if not service_status:
self.log.error(
'Failed to start service %s',
@@ -116,6 +118,8 @@ class ServiceAPIHandler(APIHandler):
try:
await self.remove_service(service, orm_service)
self.services.pop(service_name)
if service.url:
self.app.toggle_service_health_check()
except Exception:
msg = f"Failed to remove service {service_name}"
self.log.error(msg, exc_info=True)
@@ -178,7 +182,7 @@ class ServiceAPIHandler(APIHandler):
service = self.services.get(name)
return service, orm_service
return None, None
return (None, None)
default_handlers = [

View File

@@ -4,6 +4,7 @@ import json
import re
import sys
import uuid
from copy import deepcopy
from datetime import datetime, timedelta
from unittest import mock
from urllib.parse import quote, urlparse
@@ -2177,6 +2178,26 @@ async def test_create_service_duplication(app, service_admin_user, service_data)
assert r.status_code == 409
@mark.services
async def test_create_managed_service(app, service_admin_user, service_data):
db = app.db
service_name = 'managed-service-from-api'
managed_service_data = deepcopy(service_data)
managed_service_data['command'] = ['foo']
r = await api_request(
app,
f'services/{service_name}',
headers=auth_header(db, service_admin_user.name),
data=json.dumps(managed_service_data),
method='post',
)
assert r.status_code == 400
assert 'Can not create managed service' in r.json()['message']
orm_service = orm.Service.find(db, service_name)
assert orm_service is None
@mark.services
async def test_remove_service(app, service_admin_user, service_data):
db = app.db