feat: configurable timeouts for sless_function and sless_job

- sless_function: build_timeout_sec (optional, default 300s = 5 min)
- sless_job: wait_timeout_sec (optional, default 600s = 10 min)
- provider v0.1.3 published to terra.k8c.ru
This commit is contained in:
“Naeel”
2026-03-07 17:49:07 +04:00
parent f405596d42
commit a6bc67de05
2 changed files with 68 additions and 26 deletions
@@ -32,8 +32,9 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
)
// buildTimeout — максимальное время ожидания kaniko-сборки образа.
const buildTimeout = 5 * time.Minute
// defaultBuildTimeoutSec — дефолтный таймаут ожидания kaniko-сборки (300 сек = 5 мин).
// Пользователь может переопределить через build_timeout_sec.
const defaultBuildTimeoutSec = 300
var _ resource.Resource = &FunctionResource{}
@@ -58,8 +59,10 @@ type FunctionModel struct {
// code_hash — sha256/md5 zip-файла, пользователь задаёт через filemd5().
// Изменение hash → провайдер перезагружает код и запускает пересборку.
CodeHash types.String `tfsdk:"code_hash"`
Phase types.String `tfsdk:"phase"`
ImageRef types.String `tfsdk:"image_ref"`
// build_timeout_sec — максимальное ожидание kaniko-сборки. Дефолт 300 сек.
BuildTimeoutSec types.Int64 `tfsdk:"build_timeout_sec"`
Phase types.String `tfsdk:"phase"`
ImageRef types.String `tfsdk:"image_ref"`
}
func (r *FunctionResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
@@ -114,6 +117,13 @@ func (r *FunctionResource) Schema(_ context.Context, _ resource.SchemaRequest, r
"code_hash": schema.StringAttribute{
Optional: true,
},
// build_timeout_sec — таймаут ожидания kaniko-сборки. Дефолт 300 сек (5 мин).
// Увеличь если функция с тяжёлыми зависимостями (например torch).
"build_timeout_sec": schema.Int64Attribute{
Optional: true,
Computed: true,
MarkdownDescription: "Таймаут ожидания сборки образа в секундах. По умолчанию 300 (5 мин).",
},
// phase, image_ref — только для чтения, вычисляются оператором
"phase": schema.StringAttribute{
Computed: true,
@@ -178,7 +188,11 @@ func (r *FunctionResource) Create(ctx context.Context, req resource.CreateReques
resp.Diagnostics.AddError("upload code", err.Error())
return
}
fn, err = r.client.WaitReady(ctx, ns, fn.Name, buildTimeout)
buildSec := plan.BuildTimeoutSec.ValueInt64()
if buildSec <= 0 {
buildSec = defaultBuildTimeoutSec
}
fn, err = r.client.WaitReady(ctx, ns, fn.Name, time.Duration(buildSec)*time.Second)
if err != nil {
resp.Diagnostics.AddError("waiting for function ready", err.Error())
return
@@ -246,7 +260,11 @@ func (r *FunctionResource) Update(ctx context.Context, req resource.UpdateReques
resp.Diagnostics.AddError("upload code", err.Error())
return
}
fn, err = r.client.WaitReady(ctx, ns, name, buildTimeout)
buildSec := plan.BuildTimeoutSec.ValueInt64()
if buildSec <= 0 {
buildSec = defaultBuildTimeoutSec
}
fn, err = r.client.WaitReady(ctx, ns, name, time.Duration(buildSec)*time.Second)
if err != nil {
resp.Diagnostics.AddError("waiting for function ready", err.Error())
return
@@ -269,20 +287,26 @@ func (r *FunctionResource) Delete(ctx context.Context, req resource.DeleteReques
}
// fnToModel конвертирует API-ответ + plan (для локальных полей) → state модель.
// plan используется для code_path и code_hash — API их не хранит.
// plan используется для code_path, code_hash, build_timeout_sec — API их не хранит.
func fnToModel(plan FunctionModel, fn *client.FunctionResponse) FunctionModel {
buildTimeoutSec := plan.BuildTimeoutSec
// Если не задан пользователем — записываем дефолт чтобы не было null в state
if buildTimeoutSec.IsNull() || buildTimeoutSec.IsUnknown() || buildTimeoutSec.ValueInt64() <= 0 {
buildTimeoutSec = types.Int64Value(defaultBuildTimeoutSec)
}
return FunctionModel{
Namespace: types.StringValue(fn.Namespace),
Name: types.StringValue(fn.Name),
Runtime: types.StringValue(fn.Runtime),
Entrypoint: types.StringValue(fn.Entrypoint),
MemoryMB: types.Int64Value(int64(fn.MemoryMB)),
TimeoutSec: types.Int64Value(int64(fn.TimeoutSec)),
EnvVars: plan.EnvVars, // API возвращает null для пустого map — берём из plan
CodePath: plan.CodePath,
CodeHash: plan.CodeHash,
Phase: types.StringValue(fn.Phase),
ImageRef: types.StringValue(fn.ImageRef),
Namespace: types.StringValue(fn.Namespace),
Name: types.StringValue(fn.Name),
Runtime: types.StringValue(fn.Runtime),
Entrypoint: types.StringValue(fn.Entrypoint),
MemoryMB: types.Int64Value(int64(fn.MemoryMB)),
TimeoutSec: types.Int64Value(int64(fn.TimeoutSec)),
EnvVars: plan.EnvVars, // API возвращает null для пустого map — берём из plan
CodePath: plan.CodePath,
CodeHash: plan.CodeHash,
BuildTimeoutSec: buildTimeoutSec,
Phase: types.StringValue(fn.Phase),
ImageRef: types.StringValue(fn.ImageRef),
}
}