Аудит провайдера vs каноничный Fission. Добавлено:
Environment:
- builder_image, builder_command для Go и языков с build step
Package:
- deploy_type (literal/source) для переключения deployment/source archive
- loadPackageSourceArchive() — zip-упаковка source_dir
- Убран пустой source:{} из literal mode
Function:
- executor_type (poolmgr/newdeploy/container)
- function_timeout, idle_timeout
- min_scale, max_scale для ExecutionStrategy
Все 21 тест пройден. Обратная совместимость проверена.
Документация: doc/AUDIT_PROVIDER_VS_FISSION_2026-06-03.md
124 lines
4.2 KiB
Go
124 lines
4.2 KiB
Go
package resources
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
)
|
|
|
|
func TestFunctionToUnstructuredAndBack(t *testing.T) {
|
|
input := functionResourceModel{
|
|
Name: types.StringValue("fn-a"),
|
|
Environment: types.StringValue("env-a"),
|
|
PackageName: types.StringValue("pkg-a"),
|
|
Entrypoint: types.StringValue("main.main"),
|
|
}
|
|
|
|
obj := functionToUnstructured(input, "default")
|
|
state := unstructuredToFunctionModel(obj, input)
|
|
|
|
if state.Name.ValueString() != "fn-a" {
|
|
t.Fatalf("unexpected name: %q", state.Name.ValueString())
|
|
}
|
|
if state.Environment.ValueString() != "env-a" {
|
|
t.Fatalf("unexpected environment: %q", state.Environment.ValueString())
|
|
}
|
|
if state.PackageName.ValueString() != "pkg-a" {
|
|
t.Fatalf("unexpected package_name: %q", state.PackageName.ValueString())
|
|
}
|
|
if state.Entrypoint.ValueString() != "main.main" {
|
|
t.Fatalf("unexpected entrypoint: %q", state.Entrypoint.ValueString())
|
|
}
|
|
if state.ExecutorType.ValueString() != "poolmgr" {
|
|
t.Fatalf("unexpected executor_type: %q", state.ExecutorType.ValueString())
|
|
}
|
|
|
|
invoke, found, err := unstructured.NestedMap(obj.Object, "spec", "InvokeStrategy")
|
|
if err != nil || !found || len(invoke) == 0 {
|
|
t.Fatalf("InvokeStrategy not set correctly")
|
|
}
|
|
}
|
|
|
|
func TestFunctionToUnstructuredWithTimeouts(t *testing.T) {
|
|
input := functionResourceModel{
|
|
Name: types.StringValue("fn-b"),
|
|
Environment: types.StringValue("env-a"),
|
|
PackageName: types.StringValue("pkg-a"),
|
|
Entrypoint: types.StringValue("main.main"),
|
|
ExecutorType: types.StringValue("newdeploy"),
|
|
FunctionTimeout: types.Int64Value(120),
|
|
IdleTimeout: types.Int64Value(60),
|
|
MinScale: types.Int64Value(1),
|
|
MaxScale: types.Int64Value(5),
|
|
}
|
|
|
|
obj := functionToUnstructured(input, "default")
|
|
state := unstructuredToFunctionModel(obj, input)
|
|
|
|
if state.ExecutorType.ValueString() != "newdeploy" {
|
|
t.Fatalf("unexpected executor_type: %q", state.ExecutorType.ValueString())
|
|
}
|
|
if state.FunctionTimeout.ValueInt64() != 120 {
|
|
t.Fatalf("unexpected function_timeout: %d", state.FunctionTimeout.ValueInt64())
|
|
}
|
|
if state.IdleTimeout.ValueInt64() != 60 {
|
|
t.Fatalf("unexpected idle_timeout: %d", state.IdleTimeout.ValueInt64())
|
|
}
|
|
if state.MinScale.ValueInt64() != 1 {
|
|
t.Fatalf("unexpected min_scale: %d", state.MinScale.ValueInt64())
|
|
}
|
|
if state.MaxScale.ValueInt64() != 5 {
|
|
t.Fatalf("unexpected max_scale: %d", state.MaxScale.ValueInt64())
|
|
}
|
|
|
|
// Verify executor type in unstructured
|
|
et, _, _ := unstructured.NestedString(obj.Object, "spec", "InvokeStrategy", "ExecutionStrategy", "ExecutorType")
|
|
if et != "newdeploy" {
|
|
t.Fatalf("unexpected ExecutorType in unstructured: %q", et)
|
|
}
|
|
}
|
|
|
|
func TestValidateEntrypointAgainstPackageSourcePythonOK(t *testing.T) {
|
|
source := "def main():\n return 'ok'\n"
|
|
pkg := &unstructured.Unstructured{Object: map[string]interface{}{
|
|
"spec": map[string]interface{}{
|
|
"deployment": map[string]interface{}{
|
|
"literal": base64.StdEncoding.EncodeToString([]byte(source)),
|
|
},
|
|
},
|
|
}}
|
|
|
|
if err := validateEntrypointAgainstPackageSource("main.main", pkg); err != nil {
|
|
t.Fatalf("expected valid entrypoint, got error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateEntrypointAgainstPackageSourcePythonMissing(t *testing.T) {
|
|
source := "def another():\n return 'ok'\n"
|
|
pkg := &unstructured.Unstructured{Object: map[string]interface{}{
|
|
"spec": map[string]interface{}{
|
|
"deployment": map[string]interface{}{
|
|
"literal": base64.StdEncoding.EncodeToString([]byte(source)),
|
|
},
|
|
},
|
|
}}
|
|
|
|
if err := validateEntrypointAgainstPackageSource("main.main", pkg); err == nil {
|
|
t.Fatalf("expected validation error for missing python function")
|
|
}
|
|
}
|
|
|
|
func TestValidateEntrypointAgainstPackageSourceBadFormat(t *testing.T) {
|
|
pkg := &unstructured.Unstructured{}
|
|
// Пустой entrypoint должен быть ошибкой
|
|
if err := validateEntrypointAgainstPackageSource("", pkg); err == nil {
|
|
t.Fatalf("expected validation error for empty entrypoint")
|
|
}
|
|
// Одиночное слово допустимо (Ruby, Perl)
|
|
if err := validateEntrypointAgainstPackageSource("handler", pkg); err != nil {
|
|
t.Fatalf("unexpected error for single-word entrypoint: %v", err)
|
|
}
|
|
}
|