fix(provider): detect source code drift and validate package/function references
This commit is contained in:
@@ -2,7 +2,9 @@ package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
@@ -107,6 +109,22 @@ func (r *FunctionResource) Create(ctx context.Context, req resource.CreateReques
|
||||
}
|
||||
|
||||
namespace := resolveNamespace(plan.Namespace, r.client.Namespace)
|
||||
if err := ensureEnvironmentExists(ctx, r.client, namespace, plan.Environment.ValueString()); err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка валидации Environment для Function", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
pkg, err := ensurePackageExists(ctx, r.client, namespace, plan.PackageName.ValueString())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка валидации Package для Function", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := validateEntrypointAgainstPackageSource(plan.Entrypoint.ValueString(), pkg); err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка валидации entrypoint", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
functionObject := functionToUnstructured(plan, namespace)
|
||||
|
||||
createdFunction, err := r.client.CreateFunction(ctx, functionObject)
|
||||
@@ -152,6 +170,22 @@ func (r *FunctionResource) Update(ctx context.Context, req resource.UpdateReques
|
||||
}
|
||||
|
||||
namespace := resolveNamespace(plan.Namespace, r.client.Namespace)
|
||||
if err := ensureEnvironmentExists(ctx, r.client, namespace, plan.Environment.ValueString()); err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка валидации Environment для Function", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
pkg, err := ensurePackageExists(ctx, r.client, namespace, plan.PackageName.ValueString())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка валидации Package для Function", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := validateEntrypointAgainstPackageSource(plan.Entrypoint.ValueString(), pkg); err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка валидации entrypoint", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
existingFunction, err := r.client.GetFunction(ctx, namespace, plan.Name.ValueString())
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка получения Function перед обновлением", err.Error())
|
||||
@@ -254,3 +288,47 @@ func unstructuredToFunctionModel(functionObject *unstructured.Unstructured, base
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func validateEntrypointAgainstPackageSource(entrypoint string, pkg *unstructured.Unstructured) error {
|
||||
parts := strings.Split(entrypoint, ".")
|
||||
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
|
||||
return fmt.Errorf("entrypoint %q должен иметь формат module.function", entrypoint)
|
||||
}
|
||||
|
||||
if parts[0] != "main" {
|
||||
return nil
|
||||
}
|
||||
|
||||
literalSource, found, err := unstructured.NestedString(pkg.Object, "spec", "deployment", "literal")
|
||||
if err != nil || !found || literalSource == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
literalBytes, err := base64.StdEncoding.DecodeString(literalSource)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
source := string(literalBytes)
|
||||
if looksLikePythonSource(source) {
|
||||
signature := fmt.Sprintf("def %s(", parts[1])
|
||||
if !strings.Contains(source, signature) {
|
||||
return fmt.Errorf("entrypoint %q не найден в Python исходнике пакета (ожидался %q)", entrypoint, signature)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func looksLikePythonSource(source string) bool {
|
||||
trimmed := strings.TrimSpace(source)
|
||||
if strings.HasPrefix(trimmed, "def ") || strings.Contains(source, "\ndef ") {
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.Contains(source, "import ") && !strings.Contains(source, "func ") && !strings.Contains(source, "module.exports") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user