Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 沙箱回收 command #1710

Merged
4 changes: 3 additions & 1 deletion apiserver/paasng/paas_wl/bk_app/dev_sandbox/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,15 @@ class DevSandboxWithCodeEditorUrls:
app_url: str
devserver_url: str
code_editor_url: str
code_editor_health_url: str

def __init__(self, base_url: str, dev_sandbox_code: str):
self.app_url = f"{base_url}/dev_sandbox/{dev_sandbox_code}/app/"
self.devserver_url = f"{base_url}/dev_sandbox/{dev_sandbox_code}/devserver/"
self.code_editor_url = (
f"{base_url}/dev_sandbox/{dev_sandbox_code}/code-editor/?folder={settings.CODE_EDITOR_START_DIR}"
)
self.code_editor_health_url = f"{base_url}/dev_sandbox/{dev_sandbox_code}/code-editor/healthz"


@dataclass
Expand All @@ -138,7 +140,7 @@ class DevSandboxWithCodeEditorDetail:
code_editor_env_vars: Dict[str, str]
dev_sandbox_status: str
code_editor_status: str
urls: Optional[DevSandboxWithCodeEditorUrls] = None
urls: DevSandboxWithCodeEditorUrls


@dataclass
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
# Licensed under the MIT License (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
#
# http://opensource.org/licenses/MIT
#
# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific language governing permissions and
# limitations under the License.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
# Licensed under the MIT License (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
#
# http://opensource.org/licenses/MIT
#
# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific language governing permissions and
# limitations under the License.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
# Licensed under the MIT License (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
#
# http://opensource.org/licenses/MIT
#
# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific language governing permissions and
# limitations under the License.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.

"""Recycle dev sandbox.

By default, only expired sandboxes are recycled. Use the --all flag to recycle all sandboxes.

Examples:

# 仅回收过期沙箱
python manage.py recycle_dev_sandbox
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved

# 全量回收沙箱
python manage.py recycle_dev_sandbox --all
"""

from django.core.management.base import BaseCommand

from paas_wl.bk_app.dev_sandbox.controller import DevSandboxWithCodeEditorController
from paasng.accessories.dev_sandbox.models import DevSandbox


class Command(BaseCommand):
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved
help = "回收沙箱"

def add_arguments(self, parser):
parser.add_argument(
"--all",
dest="all",
action="store_true",
help="recycle all dev sandboxes",
)

def handle(self, all, *args, **options):
for dev_sandbox in DevSandbox.objects.all():
controller = DevSandboxWithCodeEditorController(
app=dev_sandbox.module.application,
module_name=dev_sandbox.module.name,
dev_sandbox_code=dev_sandbox.code,
owner=dev_sandbox.owner,
)
if all or dev_sandbox.is_expired():
controller.delete()
dev_sandbox.delete()
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
# TencentBlueKing is pleased to support the open source community by making
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
# Licensed under the MIT License (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
#
# http://opensource.org/licenses/MIT
#
# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific language governing permissions and
# limitations under the License.
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.

import logging

import requests
from django.core.management.base import BaseCommand

from paas_wl.bk_app.dev_sandbox.controller import DevSandboxWithCodeEditorController
from paasng.accessories.dev_sandbox.models import DevSandbox

logger = logging.getLogger(__name__)


class Command(BaseCommand):
help = "更新沙箱状态"

def handle(self, *args, **options):
for dev_sandbox in DevSandbox.objects.all():
controller = DevSandboxWithCodeEditorController(
app=dev_sandbox.module.application,
module_name=dev_sandbox.module.name,
dev_sandbox_code=dev_sandbox.code,
owner=dev_sandbox.owner,
)
try:
detail = controller.get_detail()
except Exception as e:
# 防止沙箱资源被管理员删除等导致的报错
logger.warning("Failed to get detail of dev sandbox: %s. Error: %s", dev_sandbox.code, e)
continue

url = detail.urls.code_editor_health_url
# 沙箱相关域名无法确定协议,因此全部遍历 http 和 https
if check_alive(f"http://{url}") or check_alive(f"https://{url}"):
dev_sandbox.renew_expire_at()


# 通过 code_editor_health_url 检查沙箱是否存活
def check_alive(url: str) -> bool:
try:
resp = requests.get(url)
return resp.status_code == 200 and resp.json().get("status") == "alive"
except Exception as e:
logger.warning("Dev sandbox status check failed for URL: %s. Error: %s", url, e)
return False
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.16 on 2024-11-11 07:49

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('dev_sandbox', '0001_initial'),
]

operations = [
migrations.RenameField(
model_name='devsandbox',
old_name='expire_at',
new_name='expired_at',
),
]
16 changes: 6 additions & 10 deletions apiserver/paasng/paasng/accessories/dev_sandbox/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
#
# We undertake not to change the open source license (MIT license) applicable
# to the current version of the project delivered to anyone in the future.
import datetime
import string

from blue_krill.models.fields import EncryptField
from django.db import models
from django.utils import timezone
from django.utils.crypto import get_random_string

from paas_wl.bk_app.dev_sandbox.constants import DevSandboxStatus
Expand All @@ -45,21 +45,17 @@ class DevSandbox(OwnerTimestampedModel):
code = models.CharField(max_length=8, help_text="沙箱标识", unique=True)
module = models.ForeignKey(Module, on_delete=models.CASCADE, db_constraint=False)
status = models.CharField(max_length=32, verbose_name="沙箱状态", choices=DevSandboxStatus.get_choices())
expire_at = models.DateTimeField(null=True, help_text="到期时间")
expired_at = models.DateTimeField(null=True, help_text="到期时间")
version_info = VersionInfoField(help_text="代码版本信息", default=None, null=True)

def renew_expire_at(self):
# 如果状态不是ALIVE, 则设置两小时后过期
if self.status != DevSandboxStatus.ACTIVE.value:
self.expire_at = datetime.datetime.now() + datetime.timedelta(hours=2)
else:
self.expire_at = None
def renew_expired_at(self):
self.expired_at = timezone.now() + timezone.timedelta(hours=2)
self.save(update_fields=["expire_at"])

def should_recycle(self) -> bool:
"""检查是否应该被回收"""
if self.expire_at:
return self.expire_at <= datetime.datetime.now()
if self.expired_at:
return self.expired_at <= timezone.now()
return False

class Meta:
Expand Down
2 changes: 2 additions & 0 deletions apiserver/paasng/paasng/accessories/dev_sandbox/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ def deploy(self, request, code, module_name):
version_info=version_info,
code=dev_sandbox_code,
)
# 更新过期时间
dev_sandbox.renew_expire_at()
SheepSheepChen marked this conversation as resolved.
Show resolved Hide resolved

# 生成代码编辑器密码
password = generate_password()
Expand Down