feat: add nodejs20 runtime
- runtimes/nodejs20/server.js: HTTP wrapper, exports.handle(event)
- runtimes/nodejs20/Dockerfile: node:20-alpine base image
- naeel/sless-runtime-nodejs20:v0.1.0 pushed to DockerHub
- upload.go: nodejs20 in runtimeBaseImage(), package.json → npm install
- upload.go: python3.11 now uses v0.1.0 tag (no more latest)
- operator v0.1.2 deployed in cluster
- E2E: hello-node-default.fn.kube5s.ru → {"message":"Hello, Naeel! (nodejs20)"}
This commit is contained in:
@@ -26,31 +26,39 @@ import (
|
||||
)
|
||||
|
||||
// runtimeBaseImage возвращает Docker образ базового runtime для данного runtime-идентификатора.
|
||||
// Соглашение: образы лежат на DockerHub под аккаунтом naeel.
|
||||
// Соглашение: образы лежат на DockerHub под аккаунтом naeel, тег = версия образа.
|
||||
// Возвращает ошибку если runtime не поддерживается — это граница валидации.
|
||||
func runtimeBaseImage(runtime string) (string, error) {
|
||||
switch runtime {
|
||||
case "python3.11":
|
||||
return "naeel/sless-runtime-python3.11:latest", nil
|
||||
return "naeel/sless-runtime-python3.11:v0.1.0", nil
|
||||
case "nodejs20":
|
||||
return "naeel/sless-runtime-nodejs20:v0.1.0", nil
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported runtime: %q (supported: python3.11)", runtime)
|
||||
return "", fmt.Errorf("unsupported runtime: %q (supported: python3.11, nodejs20)", runtime)
|
||||
}
|
||||
}
|
||||
|
||||
// generateDockerfile генерирует Dockerfile для kaniko.
|
||||
// Базовый образ содержит HTTP-обёртку (server.py).
|
||||
// Базовый образ содержит HTTP-обёртку (server.py / server.js).
|
||||
// Пользовательский код копируется в /app/function/ поверх базового образа.
|
||||
// Если в zip есть requirements.txt — добавляем pip install (для python runtime).
|
||||
func generateDockerfile(runtime string, hasRequirements bool) ([]byte, error) {
|
||||
// Зависимости устанавливаются ПОСЛЕ COPY — чтобы кеш слоёв работал при повторных сборках.
|
||||
func generateDockerfile(runtime string, hasRequirements bool, hasPackageJSON bool) ([]byte, error) {
|
||||
baseImage, err := runtimeBaseImage(runtime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
content := fmt.Sprintf("FROM %s\nCOPY . /app/function/\n", baseImage)
|
||||
// pip install только для python runtime и только если requirements.txt есть в zip.
|
||||
// Делаем это ПОСЛЕ COPY чтобы воспользоваться кешем слоёв Docker при повторных сборках.
|
||||
if hasRequirements && runtime == "python3.11" {
|
||||
content += "RUN pip install --no-cache-dir -r /app/function/requirements.txt\n"
|
||||
switch runtime {
|
||||
case "python3.11":
|
||||
if hasRequirements {
|
||||
content += "RUN pip install --no-cache-dir -r /app/function/requirements.txt\n"
|
||||
}
|
||||
case "nodejs20":
|
||||
if hasPackageJSON {
|
||||
// cd нужен т.к. npm install читает package.json из текущей директории
|
||||
content += "RUN cd /app/function && npm install --omit=dev\n"
|
||||
}
|
||||
}
|
||||
return []byte(content), nil
|
||||
}
|
||||
@@ -151,19 +159,22 @@ func (h *Handler) UploadCode(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Проверяем есть ли requirements.txt в zip (для python runtime — pip install)
|
||||
hasRequirements := false
|
||||
// Сканируем zip на наличие файлов зависимостей для разных runtime
|
||||
hasRequirements := false // requirements.txt — python3.11
|
||||
hasPackageJSON := false // package.json — nodejs20
|
||||
if zr, err := zip.NewReader(bytes.NewReader(zipData), int64(len(zipData))); err == nil {
|
||||
for _, f := range zr.File {
|
||||
if f.Name == "requirements.txt" {
|
||||
switch f.Name {
|
||||
case "requirements.txt":
|
||||
hasRequirements = true
|
||||
break
|
||||
case "package.json":
|
||||
hasPackageJSON = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Генерируем Dockerfile под runtime функции
|
||||
dockerfileContent, err := generateDockerfile(fn.Spec.Runtime, hasRequirements)
|
||||
dockerfileContent, err := generateDockerfile(fn.Spec.Runtime, hasRequirements, hasPackageJSON)
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusBadRequest, errResp(err.Error()))
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user