Skip to content

Commit 399d62c

Browse files
Implement handling of annotations
1 parent 4b53c5f commit 399d62c

3 files changed

Lines changed: 112 additions & 0 deletions

File tree

‎infra/feast-operator/api/v1alpha1/featurestore_types.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ type FeastInitOptions struct {
111111

112112
// FeastCronJob defines a CronJob to execute against a Feature Store deployment.
113113
type FeastCronJob struct {
114+
// Annotations to be added to the CronJob metadata.
115+
Annotations map[string]string `json:"annotations,omitempty"`
116+
114117
// Specification of the desired behavior of a job.
115118
JobSpec *JobSpec `json:"jobSpec,omitempty"`
116119
ContainerConfigs *CronJobContainerConfigs `json:"containerConfigs,omitempty"`

‎infra/feast-operator/internal/controller/services/cronjob.go‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ func (feast *FeastServices) initCronJob() *batchv1.CronJob {
5454
func (feast *FeastServices) setCronJob(cronJob *batchv1.CronJob) error {
5555
appliedCronJob := feast.Handler.FeatureStore.Status.Applied.CronJob
5656
cronJob.Labels = feast.getFeastTypeLabels(CronJobFeastType)
57+
if appliedCronJob.Annotations != nil {
58+
if cronJob.Annotations == nil {
59+
cronJob.Annotations = make(map[string]string)
60+
}
61+
for k, v := range appliedCronJob.Annotations {
62+
cronJob.Annotations[k] = v
63+
}
64+
}
5765
cronJob.Spec = batchv1.CronJobSpec{
5866
Schedule: appliedCronJob.Schedule,
5967
JobTemplate: batchv1.JobTemplateSpec{

‎infra/feast-operator/test/api/featurestore_types_test.go‎

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,35 @@ func registryWithGRPCFalse(featureStore *feastdevv1alpha1.FeatureStore) *feastde
438438
return fsCopy
439439
}
440440

441+
func cronJobWithAnnotations(featureStore *feastdevv1alpha1.FeatureStore) *feastdevv1alpha1.FeatureStore {
442+
fsCopy := featureStore.DeepCopy()
443+
fsCopy.Spec.CronJob = &feastdevv1alpha1.FeastCronJob{
444+
Annotations: map[string]string{
445+
"test-annotation": "test-value",
446+
"another-annotation": "another-value",
447+
},
448+
Schedule: "0 0 * * *",
449+
}
450+
return fsCopy
451+
}
452+
453+
func cronJobWithEmptyAnnotations(featureStore *feastdevv1alpha1.FeatureStore) *feastdevv1alpha1.FeatureStore {
454+
fsCopy := featureStore.DeepCopy()
455+
fsCopy.Spec.CronJob = &feastdevv1alpha1.FeastCronJob{
456+
Annotations: map[string]string{},
457+
Schedule: "0 0 * * *",
458+
}
459+
return fsCopy
460+
}
461+
462+
func cronJobWithoutAnnotations(featureStore *feastdevv1alpha1.FeatureStore) *feastdevv1alpha1.FeatureStore {
463+
fsCopy := featureStore.DeepCopy()
464+
fsCopy.Spec.CronJob = &feastdevv1alpha1.FeastCronJob{
465+
Schedule: "0 0 * * *",
466+
}
467+
return fsCopy
468+
}
469+
441470
func quotedSlice(stringSlice []string) string {
442471
quotedSlice := make([]string, len(stringSlice))
443472

@@ -645,4 +674,76 @@ var _ = Describe("FeatureStore API", func() {
645674
})
646675
})
647676
})
677+
678+
Context("When creating a CronJob", func() {
679+
ctx := context.Background()
680+
681+
BeforeEach(func() {
682+
By("verifying the custom resource FeatureStore is not there")
683+
resource := &feastdevv1alpha1.FeatureStore{}
684+
err := k8sClient.Get(ctx, typeNamespacedName, resource)
685+
Expect(err != nil && errors.IsNotFound(err)).To(BeTrue())
686+
})
687+
AfterEach(func() {
688+
By("Cleaning up the test resource")
689+
resource := &feastdevv1alpha1.FeatureStore{}
690+
err := k8sClient.Get(ctx, typeNamespacedName, resource)
691+
if err == nil {
692+
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
693+
}
694+
err = k8sClient.Get(ctx, typeNamespacedName, resource)
695+
Expect(err != nil && errors.IsNotFound(err)).To(BeTrue())
696+
})
697+
698+
Context("with annotations", func() {
699+
It("should succeed when annotations are provided", func() {
700+
featurestore := createFeatureStore()
701+
resource := cronJobWithAnnotations(featurestore)
702+
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
703+
})
704+
705+
It("should succeed when annotations are empty", func() {
706+
featurestore := createFeatureStore()
707+
resource := cronJobWithEmptyAnnotations(featurestore)
708+
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
709+
})
710+
711+
It("should succeed when annotations are not specified", func() {
712+
featurestore := createFeatureStore()
713+
resource := cronJobWithoutAnnotations(featurestore)
714+
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
715+
})
716+
717+
It("should apply the annotations correctly in the status", func() {
718+
featurestore := createFeatureStore()
719+
resource := cronJobWithAnnotations(featurestore)
720+
services.ApplyDefaultsToStatus(resource)
721+
722+
Expect(resource.Status.Applied.CronJob).NotTo(BeNil())
723+
Expect(resource.Status.Applied.CronJob.Annotations).NotTo(BeNil())
724+
Expect(resource.Status.Applied.CronJob.Annotations).To(HaveLen(2))
725+
Expect(resource.Status.Applied.CronJob.Annotations["test-annotation"]).To(Equal("test-value"))
726+
Expect(resource.Status.Applied.CronJob.Annotations["another-annotation"]).To(Equal("another-value"))
727+
})
728+
729+
It("should keep empty annotations in the status", func() {
730+
featurestore := createFeatureStore()
731+
resource := cronJobWithEmptyAnnotations(featurestore)
732+
services.ApplyDefaultsToStatus(resource)
733+
734+
Expect(resource.Status.Applied.CronJob).NotTo(BeNil())
735+
Expect(resource.Status.Applied.CronJob.Annotations).NotTo(BeNil())
736+
Expect(resource.Status.Applied.CronJob.Annotations).To(BeEmpty())
737+
})
738+
739+
It("should have nil annotations in status when not specified", func() {
740+
featurestore := createFeatureStore()
741+
resource := cronJobWithoutAnnotations(featurestore)
742+
services.ApplyDefaultsToStatus(resource)
743+
744+
Expect(resource.Status.Applied.CronJob).NotTo(BeNil())
745+
Expect(resource.Status.Applied.CronJob.Annotations).To(BeNil())
746+
})
747+
})
748+
})
648749
})

0 commit comments

Comments
 (0)