Skip to content

Commit

Permalink
feat: test workflow cron job (#240)
Browse files Browse the repository at this point in the history
* feat: test workflow cron job model

* fix: exclude preserved fields

* fix: remove duplicated description

* feat: manage cron job for workflows

* feat: add cron from workflow templates

* feat: check for test workflow template changes

* fix: support logging

* fix: init client

* fix: reconcile test workflow template

* fix: move date to annotations

* fix: add expr to fields

* fix: return nil for success

* fix: skip non existed templates

* fix: refactor loop

* fix: use testworkflow object
  • Loading branch information
vsukhin authored Apr 17, 2024
1 parent 3be9f81 commit cb78b80
Show file tree
Hide file tree
Showing 12 changed files with 444 additions and 21 deletions.
3 changes: 3 additions & 0 deletions api/testworkflows/v1/base_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ type TestWorkflowSpecBase struct {

// configuration for the scheduled pod
Pod *PodConfig `json:"pod,omitempty" expr:"include"`

// events triggering execution of the test workflow
Events []Event `json:"events,omitempty" expr:"include"`
}
11 changes: 10 additions & 1 deletion api/testworkflows/v1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,17 @@ import (
)

var (
// Group represents the API Group
Group = "testworkflows.testkube.io"

// Version represents the Resource version
Version = "v1"

// Resource corresponds to the CRD Kind
Resource = "TestWorkflow"

// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "testworkflows.testkube.io", Version: "v1"}
GroupVersion = schema.GroupVersion{Group: Group, Version: Version}

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
Expand Down
14 changes: 14 additions & 0 deletions api/testworkflows/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,17 @@ func (s DynamicList) MarshalJSON() ([]byte, error) {
}
return json.Marshal(s.Static)
}

type Event struct {
Cronjob *CronJobConfig `json:"cronjob,omitempty"`
}

// cron job configuration
type CronJobConfig struct {
// cron schedule to run a test workflow
Cron string `json:"cron" expr:"template"`
// labels to attach to the cron job
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"`
}
55 changes: 55 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.

26 changes: 17 additions & 9 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ func main() {
os.Exit(1)
}

cronJobClient := cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port,
templateCronjob, httpConfig.Registry, httpConfig.UseArgocdSync)
if err = (&scriptcontrollers.ScriptReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Expand All @@ -160,19 +162,17 @@ func main() {
os.Exit(1)
}
if err = (&testscontrollers.TestReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port,
templateCronjob, httpConfig.Registry, httpConfig.UseArgocdSync),
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CronJobClient: cronJobClient,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Test")
os.Exit(1)
}
if err = (&testsuitecontrollers.TestSuiteReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port,
templateCronjob, httpConfig.Registry, httpConfig.UseArgocdSync),
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CronJobClient: cronJobClient,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TestSuite")
os.Exit(1)
Expand Down Expand Up @@ -225,10 +225,18 @@ func main() {
os.Exit(1)
}
if err = (&testworkflowscontrollers.TestWorkflowReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CronJobClient: cronJobClient,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TestWorkflow")
os.Exit(1)
}
if err = (&testworkflowscontrollers.TestWorkflowTemplateReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "TestWorkflow")
setupLog.Error(err, "unable to create controller", "controller", "TestWorkflowTemplate")
os.Exit(1)
}
//+kubebuilder:scaffold:builder
Expand Down
25 changes: 25 additions & 0 deletions config/crd/bases/testworkflows.testkube.io_testworkflows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2483,6 +2483,31 @@ spec:
type: object
type: object
type: object
events:
description: events triggering execution of the test workflow
items:
properties:
cronjob:
description: cron job configuration
properties:
annotations:
additionalProperties:
type: string
description: annotations to attach to the cron job
type: object
cron:
description: cron schedule to run a test workflow
type: string
labels:
additionalProperties:
type: string
description: labels to attach to the cron job
type: object
required:
- cron
type: object
type: object
type: array
job:
description: configuration for the scheduled job
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2445,6 +2445,31 @@ spec:
type: object
type: object
type: object
events:
description: events triggering execution of the test workflow
items:
properties:
cronjob:
description: cron job configuration
properties:
annotations:
additionalProperties:
type: string
description: annotations to attach to the cron job
type: object
cron:
description: cron schedule to run a test workflow
type: string
labels:
additionalProperties:
type: string
description: labels to attach to the cron job
type: object
required:
- cron
type: object
type: object
type: array
job:
description: configuration for the scheduled job
properties:
Expand Down
10 changes: 6 additions & 4 deletions internal/controller/tests/test_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.

// Delete CronJob if it was created for deleted Test
var test testsv3.Test
err := r.Get(ctx, req.NamespacedName, &test)
if err != nil {
if err := r.Get(ctx, req.NamespacedName, &test); err != nil {
if errors.IsNotFound(err) {
if err = r.CronJobClient.Delete(ctx,
cronjob.GetMetadataName(req.NamespacedName.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace); err != nil {
Expand Down Expand Up @@ -116,6 +115,7 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.

options := cronjob.CronJobOptions{
Schedule: test.Spec.Schedule,
Group: testsv3.Group,
Resource: testsv3.Resource,
Version: testsv3.Version,
ResourceURI: cronjob.TestResourceURI,
Expand All @@ -131,7 +131,8 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.
if err != nil {
if errors.IsNotFound(err) {
if err = r.CronJobClient.Create(ctx, test.Name,
cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace, string(test.UID), options); err != nil {
cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace,
string(test.UID), options); err != nil {
return ctrl.Result{}, err
}
}
Expand All @@ -141,7 +142,8 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.

// Update CronJob if it was created before provided Test schedule
if err = r.CronJobClient.Update(ctx, cronJob, test.Name,
cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace, string(test.UID), options); err != nil {
cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace,
string(test.UID), options); err != nil {
return ctrl.Result{}, err
}

Expand Down
10 changes: 6 additions & 4 deletions internal/controller/testsuite/testsuite_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

// Delete CronJob if it was created for deleted TestSuite
var testSuite testsuitev3.TestSuite
err := r.Get(ctx, req.NamespacedName, &testSuite)
if err != nil {
if err := r.Get(ctx, req.NamespacedName, &testSuite); err != nil {
if errors.IsNotFound(err) {
if err = r.CronJobClient.Delete(ctx,
cronjob.GetMetadataName(req.NamespacedName.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace); err != nil {
Expand Down Expand Up @@ -116,6 +115,7 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

options := cronjob.CronJobOptions{
Schedule: testSuite.Spec.Schedule,
Group: testsuitev3.Group,
Resource: testsuitev3.Resource,
Version: testsuitev3.Version,
ResourceURI: cronjob.TestSuiteResourceURI,
Expand All @@ -131,7 +131,8 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
if err != nil {
if errors.IsNotFound(err) {
if err = r.CronJobClient.Create(ctx, testSuite.Name,
cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace, string(testSuite.UID), options); err != nil {
cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace,
string(testSuite.UID), options); err != nil {
return ctrl.Result{}, err
}
}
Expand All @@ -141,7 +142,8 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

// Update CronJob if it was created before provided Test schedule
if err = r.CronJobClient.Update(ctx, cronJob, testSuite.Name,
cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace, string(testSuite.UID), options); err != nil {
cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace,
string(testSuite.UID), options); err != nil {
return ctrl.Result{}, err
}

Expand Down
Loading

0 comments on commit cb78b80

Please sign in to comment.