diff --git a/cmd/icinga-kubernetes/main.go b/cmd/icinga-kubernetes/main.go index da6e8f47..48d11d1e 100644 --- a/cmd/icinga-kubernetes/main.go +++ b/cmd/icinga-kubernetes/main.go @@ -211,6 +211,11 @@ func main() { return s.Run(ctx) }) + g.Go(func() error { + s := syncv1.NewSync(db, factory.Batch().V1().CronJobs().Informer(), log.WithName("cron-jobs"), schemav1.NewCronJob) + + return s.Run(ctx) + }) if err := g.Wait(); err != nil { klog.Fatal(err) } diff --git a/pkg/schema/v1/cron_job.go b/pkg/schema/v1/cron_job.go new file mode 100644 index 00000000..fe0ed3bd --- /dev/null +++ b/pkg/schema/v1/cron_job.go @@ -0,0 +1,101 @@ +package v1 + +import ( + "github.com/icinga/icinga-kubernetes/pkg/database" + "github.com/icinga/icinga-kubernetes/pkg/types" + kbatchv1 "k8s.io/api/batch/v1" + kmetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "strings" +) + +type CronJob struct { + Meta + Id types.Binary + Schedule string + Timezone string + StartingDeadlineSeconds int64 + ConcurrencyPolicy string + Suspend types.Bool + SuccessfulJobsHistoryLimit int32 + FailedJobsHistoryLimit int32 + Active int32 + LastScheduleTime types.UnixMilli + LastSuccessfulTime types.UnixMilli + Labels []Label `db:"-"` + CronJobLabels []CronJobLabel `db:"-"` +} + +type CronJobLabel struct { + CronJobId types.Binary + LabelId types.Binary +} + +func NewCronJob() Resource { + return &CronJob{} +} + +func (c *CronJob) Obtain(k8s kmetav1.Object) { + c.ObtainMeta(k8s) + + cronJob := k8s.(*kbatchv1.CronJob) + + var timeZone string + if cronJob.Spec.TimeZone != nil { + timeZone = *cronJob.Spec.TimeZone + } + var startingDeadlineSeconds int64 + if cronJob.Spec.StartingDeadlineSeconds != nil { + startingDeadlineSeconds = *cronJob.Spec.StartingDeadlineSeconds + } + var suspend types.Bool + if cronJob.Spec.Suspend != nil { + suspend.Bool = *cronJob.Spec.Suspend + suspend.Valid = true + } + var successfulJobsHistoryLimit int32 + if cronJob.Spec.SuccessfulJobsHistoryLimit != nil { + successfulJobsHistoryLimit = *cronJob.Spec.SuccessfulJobsHistoryLimit + } + var failedJobsHistoryLimit int32 + if cronJob.Spec.FailedJobsHistoryLimit != nil { + failedJobsHistoryLimit = *cronJob.Spec.FailedJobsHistoryLimit + } + if cronJob.Status.LastScheduleTime != nil { + c.LastScheduleTime = types.UnixMilli(cronJob.Status.LastScheduleTime.Time) + } + if cronJob.Status.LastSuccessfulTime != nil { + c.LastSuccessfulTime = types.UnixMilli(cronJob.Status.LastSuccessfulTime.Time) + } + + c.Id = types.Checksum(c.Namespace + "/" + c.Name) + c.Schedule = cronJob.Spec.Schedule + c.Timezone = timeZone + c.StartingDeadlineSeconds = startingDeadlineSeconds + c.ConcurrencyPolicy = string(cronJob.Spec.ConcurrencyPolicy) + c.Suspend = suspend + c.SuccessfulJobsHistoryLimit = successfulJobsHistoryLimit + c.FailedJobsHistoryLimit = failedJobsHistoryLimit + c.Active = int32(len(cronJob.Status.Active)) + + for labelName, labelValue := range cronJob.Labels { + labelId := types.Checksum(strings.ToLower(labelName + ":" + labelValue)) + c.Labels = append(c.Labels, Label{ + Id: labelId, + Name: labelName, + Value: labelValue, + }) + c.CronJobLabels = append(c.CronJobLabels, CronJobLabel{ + CronJobId: c.Id, + LabelId: labelId, + }) + } +} + +func (c *CronJob) Relations() []database.Relation { + fk := database.WithForeignKey("cron_job_id") + + return []database.Relation{ + database.HasMany(c.Labels, database.WithoutCascadeDelete()), + database.HasMany(c.CronJobLabels, fk), + } +} diff --git a/schema/mysql/schema.sql b/schema/mysql/schema.sql index 32129342..7835c56c 100644 --- a/schema/mysql/schema.sql +++ b/schema/mysql/schema.sql @@ -531,3 +531,29 @@ CREATE TABLE job_label ( label_id binary(20) NOT NULL, PRIMARY KEY (job_id, label_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +CREATE TABLE cron_job ( + id binary(20) NOT NULL, + namespace varchar(63) COLLATE utf8mb4_unicode_ci NOT NULL, + name varchar(63) COLLATE utf8mb4_unicode_ci NOT NULL, + uid varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + resource_version varchar(255) NOT NULL, + schedule varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + timezone varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + starting_deadline_seconds bigint unsigned NOT NULL, + concurrency_policy enum('allow', 'forbid', 'replace') COLLATE utf8mb4_unicode_ci NOT NULL, + suspend enum('n', 'y') COLLATE utf8mb4_unicode_ci NOT NULL, + active int unsigned NOT NULL, + successful_jobs_history_limit int unsigned NOT NULL, + failed_jobs_history_limit int unsigned NOT NULL, + last_schedule_time bigint unsigned NULL DEFAULT NULL, + last_successful_time bigint unsigned NULL DEFAULT NULL, + created bigint unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +CREATE TABLE cron_job_label ( + cron_job_id binary(20) NOT NULL, + label_id binary(20) NOT NULL, + PRIMARY KEY (cron_job_id, label_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;