feat: support JS and Go source files in fission package loader

This commit is contained in:
Naeel
2026-04-14 23:37:32 +03:00
parent d40c5c6e07
commit f9dfb882f0
5 changed files with 83 additions and 5 deletions
+1 -1
View File
@@ -70,7 +70,7 @@ terraform import fission_http_trigger.hello default/tf-hello-route
## Ограничения MVP ## Ограничения MVP
- `fission_package.source_dir` в текущей реализации ожидает файл `main.py` в корне указанной директории. - `fission_package.source_dir` в текущей реализации ожидает один из файлов: `main.py`, `main.js`, `main.go`.
- Реализация ориентирована на Python flow через `spec.deployment.literal`. - Реализация ориентирована на Python flow через `spec.deployment.literal`.
- Дополнительные сценарии сборки (`build_command`, многофайловые архивы и т.д.) будут расширены в следующих этапах. - Дополнительные сценарии сборки (`build_command`, многофайловые архивы и т.д.) будут расширены в следующих этапах.
+11
View File
@@ -153,3 +153,14 @@
### Следующий шаг ### Следующий шаг
- Добавить в acceptance-тест проверку HTTP latency/perf budget и порогов SLO. - Добавить в acceptance-тест проверку HTTP latency/perf budget и порогов SLO.
### Обновление этапа (JS/Go source support)
- В `fission_package` расширена поддержка `source_dir`:
- `main.py`
- `main.js`
- `main.go`
- Добавлены unit-тесты на выбор JS/Go исходников в `package_resource_test.go`.
- Прогон `go test ./...` — успешно.
### Следующий шаг
- Добавить отдельные Terraform примеры для Node.js и Go функций.
+15
View File
@@ -194,3 +194,18 @@
- fast: 100% - fast: 100%
- cpu: 100% - cpu: 100%
- json: 100% - json: 100%
---
Агент: GitHub Copilot
Модель: GPT-5.3-Codex
## План (до действий, этап 11)
1. Убрать Python-only ограничение в `fission_package.source_dir`.
2. Добавить поддержку JS/Go исходников на уровне package loader.
3. Закрыть изменения unit-тестами.
## Результат (после действий, этап 11)
- `fission_package` теперь поддерживает `main.py`, `main.js`, `main.go` в `source_dir`.
- Добавлены unit-тесты для JS/Go веток `loadPackageLiteral`.
- `go test ./...` проходит.
@@ -69,11 +69,11 @@ func (r *PackageResource) Schema(_ context.Context, _ resource.SchemaRequest, re
}, },
"source_dir": schema.StringAttribute{ "source_dir": schema.StringAttribute{
Optional: true, Optional: true,
Description: "Путь к директории с кодом, которая будет упакована в zip.", Description: "Путь к директории с кодом (поддерживаются main.py, main.js, main.go).",
}, },
"code_path": schema.StringAttribute{ "code_path": schema.StringAttribute{
Optional: true, Optional: true,
Description: "Путь к готовому zip-архиву с кодом.", Description: "Путь к готовому файлу исходника для literal deployment.",
}, },
"code_hash": schema.StringAttribute{ "code_hash": schema.StringAttribute{
Optional: true, Optional: true,
@@ -271,10 +271,14 @@ func resolveNamespace(resourceNamespace types.String, providerNamespace string)
// loadPackageLiteral читает bytes для spec.deployment.literal. // loadPackageLiteral читает bytes для spec.deployment.literal.
func loadPackageLiteral(sourceDir, codePath string) ([]byte, error) { func loadPackageLiteral(sourceDir, codePath string) ([]byte, error) {
if sourceDir != "" { if sourceDir != "" {
mainFilePath := filepath.Join(sourceDir, "main.py") mainFilePath, err := resolveMainSourceFile(sourceDir)
if err != nil {
return nil, err
}
mainFileBytes, err := os.ReadFile(mainFilePath) mainFileBytes, err := os.ReadFile(mainFilePath)
if err != nil { if err != nil {
return nil, fmt.Errorf("read source_dir main.py %q: %w", mainFilePath, err) return nil, fmt.Errorf("read source_dir source file %q: %w", mainFilePath, err)
} }
return mainFileBytes, nil return mainFileBytes, nil
@@ -288,6 +292,20 @@ func loadPackageLiteral(sourceDir, codePath string) ([]byte, error) {
return literalBytes, nil return literalBytes, nil
} }
// resolveMainSourceFile выбирает основной файл исходника из source_dir.
func resolveMainSourceFile(sourceDir string) (string, error) {
candidates := []string{"main.py", "main.js", "main.go"}
for _, candidate := range candidates {
candidatePath := filepath.Join(sourceDir, candidate)
fileInfo, err := os.Stat(candidatePath)
if err == nil && !fileInfo.IsDir() {
return candidatePath, nil
}
}
return "", fmt.Errorf("source_dir %q must contain one of: main.py, main.js, main.go", sourceDir)
}
// packageToUnstructured преобразует Terraform model в Kubernetes CRD payload. // packageToUnstructured преобразует Terraform model в Kubernetes CRD payload.
func packageToUnstructured(model packageResourceModel, namespace string, literalBytes []byte) *unstructured.Unstructured { func packageToUnstructured(model packageResourceModel, namespace string, literalBytes []byte) *unstructured.Unstructured {
literalSource := base64.StdEncoding.EncodeToString(literalBytes) literalSource := base64.StdEncoding.EncodeToString(literalBytes)
@@ -49,6 +49,40 @@ func TestLoadPackageLiteralFromSourceDir(t *testing.T) {
} }
} }
func TestLoadPackageLiteralFromSourceDirJS(t *testing.T) {
tempDir := t.TempDir()
mainPath := filepath.Join(tempDir, "main.js")
content := []byte("module.exports = async function() { return 'ok'; }\n")
if err := os.WriteFile(mainPath, content, 0o600); err != nil {
t.Fatalf("write temp main.js: %v", err)
}
loaded, err := loadPackageLiteral(tempDir, "")
if err != nil {
t.Fatalf("loadPackageLiteral returned error: %v", err)
}
if string(loaded) != string(content) {
t.Fatalf("unexpected loaded content")
}
}
func TestLoadPackageLiteralFromSourceDirGo(t *testing.T) {
tempDir := t.TempDir()
mainPath := filepath.Join(tempDir, "main.go")
content := []byte("package main\nfunc main() {}\n")
if err := os.WriteFile(mainPath, content, 0o600); err != nil {
t.Fatalf("write temp main.go: %v", err)
}
loaded, err := loadPackageLiteral(tempDir, "")
if err != nil {
t.Fatalf("loadPackageLiteral returned error: %v", err)
}
if string(loaded) != string(content) {
t.Fatalf("unexpected loaded content")
}
}
func TestPackageToUnstructured(t *testing.T) { func TestPackageToUnstructured(t *testing.T) {
input := packageResourceModel{ input := packageResourceModel{
Name: types.StringValue("pkg-a"), Name: types.StringValue("pkg-a"),