feat: trigger.enabled + job.run_id lifecycle control (operator v0.1.6, provider v0.1.4)

- TriggerSpec.Enabled bool (default=true): enabled=false масштабирует Deployment до 0
- FunctionJobSpec.RunID int64 (default=0): run_id=0 = skip, >0 = run
- API: PATCH /v1/namespaces/{ns}/triggers/{name} (UpdateTrigger)
- Provider: enabled attribute (Optional, Computed, in-place update)
- Provider: run_id attribute (Optional, Computed, default=0, RequiresReplace)
- operator image: naeel/sless-operator:v0.1.6
- provider: terra.k8c.ru/naeel/sless v0.1.4
This commit is contained in:
“Naeel”
2026-03-08 10:10:32 +04:00
parent 8fb0ef5ea1
commit d67b9745a8
20 changed files with 509 additions and 143 deletions
+8 -1
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-03-07
// Изменено: 2026-03-08
// Описание CRD FunctionJob — одноразовый запуск функции.
// Отдельный ресурс (не Trigger) потому что семантика принципиально другая:
// - Trigger: постоянно живёт, описывает КАК функцию вызывают (http/cron)
@@ -15,6 +15,13 @@ import (
// FunctionJobSpec — параметры одноразового запуска функции.
type FunctionJobSpec struct {
// RunID — идентификатор запуска. 0 = не запускать.
// Каждое ненулевое значение уникально идентифицирует запуск.
// Увеличь RunID (1→2→3) для повторного запуска джоба.
// При RunID=0 FunctionJob создаётся в кластере, но k8s Job не запускается.
// +kubebuilder:default=0
RunID int64 `json:"runId"`
// FunctionRef — имя Function ресурса в том же namespace
// +kubebuilder:validation:Required
FunctionRef string `json:"functionRef"`
+7 -1
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-03-07
// Изменено: 2026-03-08
// Описание CRD Trigger — триггер для функции (HTTP или Cron).
// Один Trigger ссылается на одну Function и определяет способ вызова.
@@ -20,6 +20,12 @@ const (
// TriggerSpec — желаемое состояние триггера.
type TriggerSpec struct {
// Enabled — если false, Deployment функции масштабируется до 0 (функция не принимает запросы).
// При true — функция запускается. По умолчанию true.
// Позволяет "заморозить" функцию без удаления ресурса.
// +kubebuilder:default=true
Enabled bool `json:"enabled"`
// FunctionRef — имя Function ресурса в том же namespace
// +kubebuilder:validation:Required
FunctionRef string `json:"functionRef"`
+98 -98
View File
@@ -21,7 +21,7 @@ limitations under the License.
package v1alpha1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -52,6 +52,103 @@ func (in *Function) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJob) DeepCopyInto(out *FunctionJob) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJob.
func (in *FunctionJob) DeepCopy() *FunctionJob {
if in == nil {
return nil
}
out := new(FunctionJob)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FunctionJob) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJobList) DeepCopyInto(out *FunctionJobList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]FunctionJob, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJobList.
func (in *FunctionJobList) DeepCopy() *FunctionJobList {
if in == nil {
return nil
}
out := new(FunctionJobList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FunctionJobList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJobSpec) DeepCopyInto(out *FunctionJobSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJobSpec.
func (in *FunctionJobSpec) DeepCopy() *FunctionJobSpec {
if in == nil {
return nil
}
out := new(FunctionJobSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJobStatus) DeepCopyInto(out *FunctionJobStatus) {
*out = *in
if in.StartTime != nil {
in, out := &in.StartTime, &out.StartTime
*out = (*in).DeepCopy()
}
if in.CompletionTime != nil {
in, out := &in.CompletionTime, &out.CompletionTime
*out = (*in).DeepCopy()
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJobStatus.
func (in *FunctionJobStatus) DeepCopy() *FunctionJobStatus {
if in == nil {
return nil
}
out := new(FunctionJobStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionList) DeepCopyInto(out *FunctionList) {
*out = *in
@@ -224,100 +321,3 @@ func (in *TriggerStatus) DeepCopy() *TriggerStatus {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJob) DeepCopyInto(out *FunctionJob) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJob.
func (in *FunctionJob) DeepCopy() *FunctionJob {
if in == nil {
return nil
}
out := new(FunctionJob)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FunctionJob) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJobList) DeepCopyInto(out *FunctionJobList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]FunctionJob, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJobList.
func (in *FunctionJobList) DeepCopy() *FunctionJobList {
if in == nil {
return nil
}
out := new(FunctionJobList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FunctionJobList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJobSpec) DeepCopyInto(out *FunctionJobSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJobSpec.
func (in *FunctionJobSpec) DeepCopy() *FunctionJobSpec {
if in == nil {
return nil
}
out := new(FunctionJobSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FunctionJobStatus) DeepCopyInto(out *FunctionJobStatus) {
*out = *in
if in.StartTime != nil {
in, out := &in.StartTime, &out.StartTime
*out = (*in).DeepCopy()
}
if in.CompletionTime != nil {
in, out := &in.CompletionTime, &out.CompletionTime
*out = (*in).DeepCopy()
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionJobStatus.
func (in *FunctionJobStatus) DeepCopy() *FunctionJobStatus {
if in == nil {
return nil
}
out := new(FunctionJobStatus)
in.DeepCopyInto(out)
return out
}