Skip to content

Commit

Permalink
feat: [TKC-2726] cron jobs config model (#305)
Browse files Browse the repository at this point in the history
* feat: cron jobs config model

Signed-off-by: Vladislav Sukhin <[email protected]>

* fix: pass config to cronjob

Signed-off-by: Vladislav Sukhin <[email protected]>

* fix: merge cronjob config

Signed-off-by: Vladislav Sukhin <[email protected]>

* fix: allow multiple crons for different config

Signed-off-by: Vladislav Sukhin <[email protected]>

* fix: remove merge similar config

Signed-off-by: Vladislav Sukhin <[email protected]>

---------

Signed-off-by: Vladislav Sukhin <[email protected]>
  • Loading branch information
vsukhin authored Oct 30, 2024
1 parent ba9b7a6 commit 2a57f6e
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 24 deletions.
2 changes: 2 additions & 0 deletions api/testworkflows/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ type CronJobConfig struct {
Labels map[string]string `json:"labels,omitempty" expr:"template,template"`
// annotations to attach to the cron job
Annotations map[string]string `json:"annotations,omitempty" expr:"template,template"`
// configuration to pass for the workflow
Config map[string]intstr.IntOrString `json:"config,omitempty" expr:"template,template"`
}

type TestWorkflowTagSchema struct {
Expand Down
7 changes: 7 additions & 0 deletions api/testworkflows/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions config/crd/bases/testworkflows.testkube.io_testworkflows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3581,6 +3581,14 @@ spec:
type: string
description: annotations to attach to the cron job
type: object
config:
additionalProperties:
anyOf:
- type: integer
- type: string
x-kubernetes-int-or-string: true
description: configuration to pass for the workflow
type: object
cron:
description: cron schedule to run a test workflow
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3507,6 +3507,14 @@ spec:
type: string
description: annotations to attach to the cron job
type: object
config:
additionalProperties:
anyOf:
- type: integer
- type: string
x-kubernetes-int-or-string: true
description: configuration to pass for the workflow
type: object
cron:
description: cron schedule to run a test workflow
type: string
Expand Down
52 changes: 32 additions & 20 deletions internal/controller/testworkflows/testworkflow_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,32 @@ func (r *TestWorkflowReconciler) Reconcile(ctx context.Context, req ctrl.Request
}

for i := range cronJobList.Items {
oldCronJobs[cronJobList.Items[i].Spec.Schedule] = &cronJobList.Items[i]
oldCronJobs[cronJobList.Items[i].Name] = &cronJobList.Items[i]
}

for _, event := range events {
if event.Cronjob != nil {
if cronJob, ok := newCronJobConfigs[event.Cronjob.Cron]; !ok {
newCronJobConfigs[event.Cronjob.Cron] = &testworkflowsv1.CronJobConfig{
name, err := cronjob.GetHashedMetadataName(testWorkflow.Name, event.Cronjob.Cron, event.Cronjob.Config)
if err != nil {
return ctrl.Result{}, err
}

if cronJob, ok := newCronJobConfigs[name]; !ok {
newCronJobConfigs[name] = &testworkflowsv1.CronJobConfig{
Cron: event.Cronjob.Cron,
Labels: event.Cronjob.Labels,
Annotations: event.Cronjob.Annotations,
Config: event.Cronjob.Config,
}
} else {
newCronJobConfigs[cronJob.Cron] = MergeCronJobJobConfig(cronJob, event.Cronjob)
newCronJobConfigs[name] = MergeCronJobJobConfig(cronJob, event.Cronjob)
}
}
}

interface_ := testworkflowsv1.API_TestWorkflowRunningContextInterfaceType
actor := testworkflowsv1.CRON_TestWorkflowRunningContextActorType
data, err := json.Marshal(testworkflowsv1.TestWorkflowExecutionRequest{
request := testworkflowsv1.TestWorkflowExecutionRequest{
RunningContext: &testworkflowsv1.TestWorkflowRunningContext{
Interface_: &testworkflowsv1.TestWorkflowRunningContextInterface{
Type_: &interface_,
Expand All @@ -147,16 +153,12 @@ func (r *TestWorkflowReconciler) Reconcile(ctx context.Context, req ctrl.Request
Type_: &actor,
},
},
})
if err != nil {
return ctrl.Result{}, err
}

for schedule, oldCronJob := range oldCronJobs {
if newCronJobConfig, ok := newCronJobConfigs[schedule]; !ok {
for name, oldCronJob := range oldCronJobs {
if newCronJobConfig, ok := newCronJobConfigs[name]; !ok {
// Delete removed Cron Jobs
if err = r.CronJobClient.Delete(ctx,
cronjob.GetHashedMetadataName(testWorkflow.Name, schedule), testWorkflow.Namespace); err != nil {
if err = r.CronJobClient.Delete(ctx, name, testWorkflow.Namespace); err != nil {
return ctrl.Result{}, err
}
} else {
Expand All @@ -165,9 +167,15 @@ func (r *TestWorkflowReconciler) Reconcile(ctx context.Context, req ctrl.Request
newCronJobConfig.Labels = make(map[string]string)
}

request.Config = newCronJobConfig.Config
data, err := json.Marshal(request)
if err != nil {
return ctrl.Result{}, err
}

newCronJobConfig.Labels[cronjob.TestWorkflowResourceURI] = testWorkflow.Name
options := cronjob.CronJobOptions{
Schedule: schedule,
Schedule: newCronJobConfig.Cron,
Group: testworkflowsv1.Group,
Resource: testworkflowsv1.Resource,
Version: testworkflowsv1.Version,
Expand All @@ -177,24 +185,29 @@ func (r *TestWorkflowReconciler) Reconcile(ctx context.Context, req ctrl.Request
Data: string(data),
}

if err = r.CronJobClient.Update(ctx, oldCronJob, testWorkflow.Name,
cronjob.GetHashedMetadataName(testWorkflow.Name, schedule), testWorkflow.Namespace,
if err = r.CronJobClient.Update(ctx, oldCronJob, testWorkflow.Name, name, testWorkflow.Namespace,
string(testWorkflow.UID), options); err != nil {
return ctrl.Result{}, err
}
}
}

for schedule, newCronJobConfig := range newCronJobConfigs {
if _, ok = oldCronJobs[schedule]; !ok {
for name, newCronJobConfig := range newCronJobConfigs {
if _, ok = oldCronJobs[name]; !ok {
// Create new Cron Jobs
if newCronJobConfig.Labels == nil {
newCronJobConfig.Labels = make(map[string]string)
}

request.Config = newCronJobConfig.Config
data, err := json.Marshal(request)
if err != nil {
return ctrl.Result{}, err
}

newCronJobConfig.Labels[cronjob.TestWorkflowResourceURI] = testWorkflow.Name
options := cronjob.CronJobOptions{
Schedule: schedule,
Schedule: newCronJobConfig.Cron,
Group: testworkflowsv1.Group,
Resource: testworkflowsv1.Resource,
Version: testworkflowsv1.Version,
Expand All @@ -204,8 +217,7 @@ func (r *TestWorkflowReconciler) Reconcile(ctx context.Context, req ctrl.Request
Data: string(data),
}

if err = r.CronJobClient.Create(ctx, testWorkflow.Name,
cronjob.GetHashedMetadataName(testWorkflow.Name, schedule), testWorkflow.Namespace,
if err = r.CronJobClient.Create(ctx, testWorkflow.Name, name, testWorkflow.Namespace,
string(testWorkflow.UID), options); err != nil {
return ctrl.Result{}, err
}
Expand Down
16 changes: 12 additions & 4 deletions pkg/cronjob/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cronjob
import (
"bytes"
"context"
"encoding/json"
"fmt"
"hash/fnv"
"maps"
Expand All @@ -14,6 +15,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/controller-runtime/pkg/client"
kyaml "sigs.k8s.io/kustomize/kyaml/yaml"
Expand Down Expand Up @@ -294,17 +296,23 @@ func GetMetadataName(name, resource string) string {
}

// GetHashedMetadataName returns cron job hashed metadata name
func GetHashedMetadataName(name, schedule string) string {
h := fnv.New32a()
func GetHashedMetadataName(name, schedule string, config map[string]intstr.IntOrString) (string, error) {
data, err := json.Marshal(config)
if err != nil {
return "", err
}

h := fnv.New64a()
h.Write([]byte(schedule))
h.Write(data)

hash := fmt.Sprintf("-%d", h.Sum32())
hash := fmt.Sprintf("-%d", h.Sum64())

if len(name) > 52-len(hash) {
name = name[:52-len(hash)]
}

return name + hash
return name + hash, nil
}

// GetSelector returns cron job selecttor
Expand Down

0 comments on commit 2a57f6e

Please sign in to comment.