Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions e2e/serving/serving-deploy-lifecycle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ async function uploadFixturesToVFolder(
);

const serviceDefContent = [
'[custom.environment]',
`image = "${pythonImage}"`,
'architecture = "x86_64"',
'',
'[custom.resource_slots]',
'cpu = 1',
'mem = "512m"',
'custom:',
' environment:',
` image: "${pythonImage}"`,
' architecture: "x86_64"',
' resource_slots:',
' cpu: 1',
' mem: "512m"',
].join('\n');

await fileChooser.setFiles([
Expand All @@ -122,15 +122,15 @@ async function uploadFixturesToVFolder(
buffer: Buffer.from(modelDefContent),
},
{
name: 'service-definition.toml',
mimeType: 'application/toml',
name: 'deployment-config.yaml',
mimeType: 'application/x-yaml',
buffer: Buffer.from(serviceDefContent),
},
]);

await modal.verifyFileVisible('mock_openai_server.py');
await modal.verifyFileVisible('model-definition.yaml');
await modal.verifyFileVisible('service-definition.toml');
await modal.verifyFileVisible('deployment-config.yaml');

await modal.close();
}
Expand Down Expand Up @@ -379,7 +379,7 @@ test.describe(
await modal.waitForOpen();
await modal.verifyFileVisible('mock_openai_server.py');
await modal.verifyFileVisible('model-definition.yaml');
await modal.verifyFileVisible('service-definition.toml');
await modal.verifyFileVisible('deployment-config.yaml');
await modal.close();
});

Expand Down
14 changes: 7 additions & 7 deletions react/src/components/LegacyModelTryContentButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const MAX_RETRIES = 12; // 12 retries * 5 seconds = 1 minute max
const RETRY_INTERVAL_MS = 5000;

// Helper function to create service input
// This will be overridden by service-definition.toml values where applicable
// This will be overridden by deployment-config.yaml values where applicable
// Set minimal default values
function createServiceInput(
modelName: string,
Expand Down Expand Up @@ -133,7 +133,7 @@ const LegacyModelTryContentButton: React.FC<
if (values.envvars) {
values.envvars.forEach((v) => (environ[v.variable] = v.value));
}
// These fields are replaced with contents from service-definition.toml
// These fields are replaced with contents from deployment-config.yaml
const body: ServiceCreateType = {
name: values.serviceName,
desired_session_count: values.replicas,
Expand Down Expand Up @@ -404,13 +404,13 @@ const LegacyModelTryContentButton: React.FC<
file?.name === 'model-definition.yaml' ||
file?.name === 'model-definition.yml',
);
const hasServiceDefinition = _.some(
const hasDeploymentConfig = _.some(
folderFiles?.items,
(file) => file?.name === 'service-definition.toml',
(file) => file?.name === 'deployment-config.yaml',
);

// Both files are required for the button to be enabled
const definitionFilesExist = hasModelDefinition && hasServiceDefinition;
const definitionFilesExist = hasModelDefinition && hasDeploymentConfig;

/* TODO: Apply if cloning to another host is supported.
const currentProject = useCurrentProjectValue();
Expand Down Expand Up @@ -637,11 +637,11 @@ const LegacyModelTryContentButton: React.FC<
<Tooltip
title={
!definitionFilesExist
? !hasModelDefinition && !hasServiceDefinition
? !hasModelDefinition && !hasDeploymentConfig
? t('modelService.BothDefinitionFilesRequired')
: !hasModelDefinition
? t('modelService.ModelDefinitionRequired')
: t('modelService.ServiceDefinitionRequired')
: t('modelService.DeploymentConfigRequired')
: ''
}
>
Expand Down
6 changes: 3 additions & 3 deletions react/src/components/VFolderTextFileEditorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ const definitionSchemaMap: Record<string, SchemaMapping> = {
schemaUrl: '/resources/model-definition.schema.json',
type: 'yaml',
},
'service-definition.toml': {
schemaUrl: '/resources/service-definition.schema.json',
type: 'toml',
'deployment-config.yaml': {
schemaUrl: '/resources/deployment-config.schema.json',
type: 'yaml',
},
};

Expand Down
32 changes: 18 additions & 14 deletions react/src/hooks/useModelServiceLauncher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { ESMClientErrorResponse, generateRandomString } from 'backend.ai-ui';
import * as _ from 'lodash-es';
import { useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { parse as parseToml } from 'smol-toml';
import { parse as parseYaml } from 'yaml';

// Re-export for consumers who need only these types
export type { ServiceCreateType, ServiceLauncherFormValue };
Expand Down Expand Up @@ -56,7 +56,7 @@ const RETRY_INTERVAL_MS = 5000;

/**
* Creates minimal default service input values.
* Fields will be overridden by service-definition.toml values where applicable.
* Fields will be overridden by deployment-config.yaml values where applicable.
*/
export function createServiceInput(
modelName: string,
Expand Down Expand Up @@ -112,7 +112,7 @@ export function useModelServiceLauncher() {
if (values.envvars) {
values.envvars.forEach((v) => (environ[v.variable] = v.value));
}
// These fields are replaced with contents from service-definition.toml
// These fields are replaced with contents from deployment-config.yaml
const body: ServiceCreateType = {
name: values.serviceName,
desired_session_count: values.replicas,
Expand Down Expand Up @@ -281,7 +281,7 @@ interface DefinitionCheckResult {
* for starting a service directly from an existing model folder (no clone).
*
* Steps:
* 1. "Checking definition files..." — validate model-definition.yaml & service-definition.toml
* 1. "Checking definition files..." — validate model-definition.yaml & deployment-config.yaml
* 2. "Creating service..." — POST /services
* 3. "Waiting for service to be ready..." — poll GET /services/:id
*
Expand Down Expand Up @@ -317,21 +317,21 @@ export function useStartServiceFromFolder(options: {
f.name === 'model-definition.yaml' ||
f.name === 'model-definition.yml',
);
const hasServiceDefinition = files.some(
(f) => f.name === 'service-definition.toml',
const hasDeploymentConfig = files.some(
(f) => f.name === 'deployment-config.yaml',
);

// No service-definition → redirect to service start page
if (!hasServiceDefinition) {
throw new StepWarning(t('modelService.ServiceDefinitionMissing'));
// No deployment-config → redirect to service start page
if (!hasDeploymentConfig) {
throw new StepWarning(t('modelService.DeploymentConfigMissing'));
}

// Download and parse service-definition.toml
// Download and parse deployment-config.yaml
let text: string;
try {
const tokenResponse =
await baiClient.vfolder.request_download_token(
'service-definition.toml',
'deployment-config.yaml',
vfolderId,
false,
);
Expand All @@ -342,14 +342,18 @@ export function useStartServiceFromFolder(options: {
}
text = await response.text();
} catch {
throw new Error(t('modelService.ServiceDefinitionDownloadError'));
throw new Error(t('modelService.DeploymentConfigDownloadError'));
}

let parsed: Record<string, unknown>;
try {
parsed = parseToml(text);
const raw: unknown = parseYaml(text);
if (raw == null || typeof raw !== 'object' || Array.isArray(raw)) {
throw new Error('Invalid YAML structure');
}
parsed = raw as Record<string, unknown>;
} catch {
throw new Error(t('modelService.ServiceDefinitionParseError'));
throw new Error(t('modelService.DeploymentConfigParseError'));
}

// Check runtime_variants field
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://www.backend.ai/schemas/service-definition.schema.json",
"title": "Backend.AI Service Definition",
"description": "Defines a service that can be launched inside a Backend.AI container. Stored as JSON files in /etc/backend.ai/service-defs/.",
"$id": "https://www.backend.ai/schemas/deployment-config.schema.json",
"title": "Backend.AI Deployment Config",
"description": "Defines a service that can be launched inside a Backend.AI container. Stored as deployment-config.yaml in the model VFolder.",
"type": "object",
"required": [
"command"
Expand Down
12 changes: 6 additions & 6 deletions resources/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1447,7 +1447,7 @@
"AdditionalMounts": "Zusätzliche Halterungen",
"AutoScalingRules": "Automatische Skalierungsregeln",
"BasePath": "Basispfad",
"BothDefinitionFilesRequired": "Die modelldefinitions.yaml und die dienste definition.toml-Dateien sind erforderlich.",
"BothDefinitionFilesRequired": "Die Dateien model-definition.yaml und deployment-config.yaml sind erforderlich.",
"Cancel": "Stornieren",
"CannotValidateNow": "Der Dienst kann derzeit nicht validiert werden. \nBitte überprüfen Sie die Ressourcenzuweisung oder andere Konfigurationen.",
"Chatting": "Chatten",
Expand All @@ -1461,6 +1461,11 @@
"Custom": "Anpassen",
"CustomExpirationDate": "Benutzerdefinierte Ablaufdatum",
"CustomExpiredDate": "Benutzerdefinierte Ablaufdatum",
"DeploymentConfigDownloadError": "deployment-config.yaml konnte nicht heruntergeladen werden. Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut.",
"DeploymentConfigMissing": "deployment-config.yaml wurde nicht gefunden. Sie werden zur Service-Startseite weitergeleitet.",
"DeploymentConfigNotFound": "Service -Definitionsdatei nicht gefunden. \nNur Klonen sind verfügbar.",
"DeploymentConfigParseError": "Es gibt ein Problem mit der Datei deployment-config.yaml. Bitte öffnen Sie den Ordner und überprüfen Sie die Datei.",
"DeploymentConfigRequired": "deployment-config.yaml-Datei ist erforderlich.",
"DesiredSessionCount": "Gewünschte Anzahl von Sitzungen",
"Destroyed": "Zerstört",
"EditModelService": "Modelldienst bearbeiten",
Expand Down Expand Up @@ -1572,11 +1577,6 @@
"ServiceAlreadyExists": "Servicename existiert bereits",
"ServiceConfigurationNotValid": "Die Dienstkonfiguration ist ungültig. \nBitte wenden Sie sich an den Administrator.",
"ServiceCreated": "Der Modelldienst {{ name }} wurde erfolgreich erstellt.",
"ServiceDefinitionDownloadError": "service-definition.toml konnte nicht heruntergeladen werden. Bitte überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut.",
"ServiceDefinitionMissing": "service-definition.toml wurde nicht gefunden. Sie werden zur Service-Startseite weitergeleitet.",
"ServiceDefinitionNotFound": "Service -Definitionsdatei nicht gefunden. \nNur Klonen sind verfügbar.",
"ServiceDefinitionParseError": "Es gibt ein Problem mit der Datei service-definition.toml. Bitte öffnen Sie den Ordner und überprüfen Sie die Datei.",
"ServiceDefinitionRequired": "Service-Definition.toml-Datei ist erforderlich.",
"ServiceDelegatedFrom": "Der Modelldienst wird von {{ createdUser }} erstellt, aber das Eigentum an der Sitzung wird an {{ sessionOwner }} delegiert.",
"ServiceEndpoint": "Dienst-Endpunkt",
"ServiceInfo": "Service-Informationen",
Expand Down
12 changes: 6 additions & 6 deletions resources/i18n/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,7 @@
"AdditionalMounts": "Πρόσθετες βάσεις",
"AutoScalingRules": "Κανόνες αυτόματης κλιμάκωσης",
"BasePath": "Διαδρομή βάσης",
"BothDefinitionFilesRequired": "Τα αρχεία μοντέλων-definition.yaml και service-definition.toml απαιτούνται.",
"BothDefinitionFilesRequired": "Τα αρχεία μοντέλων-definition.yaml και deployment-config.yaml απαιτούνται.",
"Cancel": "Ματαίωση",
"CannotValidateNow": "Δεν είναι δυνατή η επικύρωση της υπηρεσίας τώρα. \nΕλέγξτε την κατανομή πόρων ή άλλες διαμορφώσεις.",
"Chatting": "Συζήτηση",
Expand All @@ -1459,6 +1459,11 @@
"Custom": "Προσαρμόζω",
"CustomExpirationDate": "Ημερομηνία λήξης προσαρμοσμένης",
"CustomExpiredDate": "Ημερομηνία λήξης προσαρμοσμένης",
"DeploymentConfigDownloadError": "Αποτυχία λήψης του deployment-config.yaml. Ελέγξτε τη σύνδεση δικτύου σας και δοκιμάστε ξανά.",
"DeploymentConfigMissing": "Το deployment-config.yaml δεν βρέθηκε. Μεταφορά στη σελίδα εκκίνησης υπηρεσίας.",
"DeploymentConfigNotFound": "Το αρχείο ορισμού υπηρεσιών δεν βρέθηκε. \nΔιατίθεται μόνο κλωνοποίηση.",
"DeploymentConfigParseError": "Υπάρχει πρόβλημα με το αρχείο deployment-config.yaml. Ανοίξτε τον φάκελο και ελέγξτε το αρχείο.",
"DeploymentConfigRequired": "Απαιτείται αρχείο deployment-config.yaml.",
"DesiredSessionCount": "Επιθυμητός αριθμός συνόδων",
"Destroyed": "Καταστράφηκε",
"EditModelService": "Επεξεργασία υπηρεσίας μοντέλου",
Expand Down Expand Up @@ -1570,11 +1575,6 @@
"ServiceAlreadyExists": "Το όνομα της υπηρεσίας υπάρχει ήδη",
"ServiceConfigurationNotValid": "Η διαμόρφωση της υπηρεσίας δεν είναι έγκυρη. \nΕπικοινωνήστε με τον διαχειριστή.",
"ServiceCreated": "Η υπηρεσία μοντέλου {{ όνομα }} δημιουργήθηκε με επιτυχία.",
"ServiceDefinitionDownloadError": "Αποτυχία λήψης του service-definition.toml. Ελέγξτε τη σύνδεση δικτύου σας και δοκιμάστε ξανά.",
"ServiceDefinitionMissing": "Το service-definition.toml δεν βρέθηκε. Μεταφορά στη σελίδα εκκίνησης υπηρεσίας.",
"ServiceDefinitionNotFound": "Το αρχείο ορισμού υπηρεσιών δεν βρέθηκε. \nΔιατίθεται μόνο κλωνοποίηση.",
"ServiceDefinitionParseError": "Υπάρχει πρόβλημα με το αρχείο service-definition.toml. Ανοίξτε τον φάκελο και ελέγξτε το αρχείο.",
"ServiceDefinitionRequired": "Απαιτείται αρχείο Service-Definition.toml.",
"ServiceDelegatedFrom": "Το μοντέλο υπηρεσίας δημιουργείται από τον {{ createdUser }}, αλλά η ιδιοκτησία της συνεδρίας θα ανατεθεί στον {{ sessionOwner }}",
"ServiceEndpoint": "Τελικό σημείο υπηρεσίας",
"ServiceInfo": "Πληροφορίες υπηρεσίας",
Expand Down
12 changes: 6 additions & 6 deletions resources/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1446,7 +1446,7 @@
"AdditionalMounts": "Additional Mounts",
"AutoScalingRules": "Auto Scaling Rules",
"BasePath": "Base Path",
"BothDefinitionFilesRequired": "model-definition.yaml and service-definition.toml are missing. Please add them to the model folder.",
"BothDefinitionFilesRequired": "model-definition.yaml and deployment-config.yaml are missing. Please add them to the model folder.",
"Cancel": "Cancel",
"CannotValidateNow": "Cannot validate service now. Please check resource allocation or other configurations.",
"Chatting": "Chatting",
Expand All @@ -1460,6 +1460,11 @@
"Custom": "Custom",
"CustomExpirationDate": "Custom Expiration Date",
"CustomExpiredDate": "Custom Expired Date",
"DeploymentConfigDownloadError": "Failed to download deployment-config.yaml. Please check your network connection and try again.",
"DeploymentConfigMissing": "deployment-config.yaml was not found. Redirecting to the service launcher page.",
"DeploymentConfigNotFound": "Service definition file not found. Only cloning is available.",
"DeploymentConfigParseError": "There is an issue with the deployment-config.yaml file. Please open the folder and check the file.",
"DeploymentConfigRequired": "deployment-config.yaml file is needed.",
"DesiredSessionCount": "Desired Session Count",
"Destroyed": "Destroyed",
"EditModelService": "Edit Model Service",
Expand Down Expand Up @@ -1572,11 +1577,6 @@
"ServiceAlreadyExists": "Service name already exists",
"ServiceConfigurationNotValid": "The service configuration is invalid. Please contact the administrator.",
"ServiceCreated": "Model service {{ name }} has been created successfully.",
"ServiceDefinitionDownloadError": "Failed to download service-definition.toml. Please check your network connection and try again.",
"ServiceDefinitionMissing": "service-definition.toml was not found. Redirecting to the service launcher page.",
"ServiceDefinitionNotFound": "Service definition file not found. Only cloning is available.",
"ServiceDefinitionParseError": "There is an issue with the service-definition.toml file. Please open the folder and check the file.",
"ServiceDefinitionRequired": "service-definition.toml file is needed.",
"ServiceDelegatedFrom": "Model service is created by {{ createdUser }} but the session ownership will be delegated to {{ sessionOwner }}",
"ServiceEndpoint": "Service Endpoint",
"ServiceInfo": "Service Info",
Expand Down
12 changes: 6 additions & 6 deletions resources/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,7 @@
"AdditionalMounts": "Montajes adicionales",
"AutoScalingRules": "Reglas de escala automática",
"BasePath": "Ruta base",
"BothDefinitionFilesRequired": "Se requieren modelos-Definition.yaml y Service-DeFinition.TOML.",
"BothDefinitionFilesRequired": "Se requieren modelos-Definition.yaml y deployment-config.yaml.",
"Cancel": "Cancelar",
"CannotValidateNow": "No se puede validar el servicio ahora. \nVerifique la asignación de recursos u otras configuraciones.",
"Chatting": "Charlando",
Expand All @@ -1459,6 +1459,11 @@
"Custom": "Personalizar",
"CustomExpirationDate": "Fecha de vencimiento personalizada",
"CustomExpiredDate": "Fecha de vencimiento personalizada",
"DeploymentConfigDownloadError": "No se pudo descargar deployment-config.yaml. Verifique su conexión de red e inténtelo de nuevo.",
"DeploymentConfigMissing": "No se encontró deployment-config.yaml. Redirigiendo a la página de inicio del servicio.",
"DeploymentConfigNotFound": "Archivo de definición de servicio no encontrado. \nSolo la clonación está disponible.",
"DeploymentConfigParseError": "Hay un problema con el archivo deployment-config.yaml. Abra la carpeta y revise el archivo.",
"DeploymentConfigRequired": "Se requiere el archivo deployment-config.yaml.",
"DesiredSessionCount": "Recuento de sesiones deseado",
"Destroyed": "Destruido",
"EditModelService": "Editar modelo de servicio",
Expand Down Expand Up @@ -1570,11 +1575,6 @@
"ServiceAlreadyExists": "El nombre del servicio ya existe",
"ServiceConfigurationNotValid": "La configuración del servicio no es válida. \nPóngase en contacto con el administrador.",
"ServiceCreated": "El servicio modelo {{ name }} se ha creado correctamente.",
"ServiceDefinitionDownloadError": "No se pudo descargar service-definition.toml. Verifique su conexión de red e inténtelo de nuevo.",
"ServiceDefinitionMissing": "No se encontró service-definition.toml. Redirigiendo a la página de inicio del servicio.",
"ServiceDefinitionNotFound": "Archivo de definición de servicio no encontrado. \nSolo la clonación está disponible.",
"ServiceDefinitionParseError": "Hay un problema con el archivo service-definition.toml. Abra la carpeta y revise el archivo.",
"ServiceDefinitionRequired": "Service-DeFinition.TOML File es necesario.",
"ServiceDelegatedFrom": "El servicio modelo es creado por {{ createdUser }} pero la propiedad de la sesión será delegada a {{ sessionOwner }}",
"ServiceEndpoint": "Punto final del servicio",
"ServiceInfo": "Información de servicio",
Expand Down
Loading
Loading