Skip to content

Commit

Permalink
feat: Operator will create k8s serviceaccount for each feast service (#…
Browse files Browse the repository at this point in the history
…4767)

create a serviceaccount for each feast service

Signed-off-by: Tommy Hughes <tohughes@redhat.com>
  • Loading branch information
tchughesiv authored Nov 19, 2024
1 parent 7ec5b09 commit cde5760
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 8 deletions.
1 change: 1 addition & 0 deletions infra/feast-operator/config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ rules:
resources:
- configmaps
- persistentvolumeclaims
- serviceaccounts
- services
verbs:
- create
Expand Down
1 change: 1 addition & 0 deletions infra/feast-operator/dist/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,7 @@ rules:
resources:
- configmaps
- persistentvolumeclaims
- serviceaccounts
- services
verbs:
- create
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type FeatureStoreReconciler struct {
//+kubebuilder:rbac:groups=feast.dev,resources=featurestores/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=feast.dev,resources=featurestores/finalizers,verbs=update
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;create;update;watch;delete
//+kubebuilder:rbac:groups=core,resources=services;configmaps;persistentvolumeclaims,verbs=get;list;create;update;watch;delete
//+kubebuilder:rbac:groups=core,resources=services;configmaps;persistentvolumeclaims;serviceaccounts,verbs=get;list;create;update;watch;delete

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down Expand Up @@ -143,6 +143,7 @@ func (r *FeatureStoreReconciler) SetupWithManager(mgr ctrl.Manager) error {
Owns(&appsv1.Deployment{}).
Owns(&corev1.Service{}).
Owns(&corev1.PersistentVolumeClaim{}).
Owns(&corev1.ServiceAccount{}).
Watches(&feastdevv1alpha1.FeatureStore{}, handler.EnqueueRequestsFromMapFunc(r.mapFeastRefsToFeastRequests)).
Complete(r)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ var _ = Describe("FeatureStore Controller", func() {
Expect(err).NotTo(HaveOccurred())
Expect(deploy.Spec.Replicas).To(Equal(&services.DefaultReplicas))
Expect(controllerutil.HasControllerReference(deploy)).To(BeTrue())
Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name))
Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1))

svc := &corev1.Service{}
Expand Down Expand Up @@ -216,6 +217,7 @@ var _ = Describe("FeatureStore Controller", func() {
},
deploy)
Expect(err).NotTo(HaveOccurred())
Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name))
Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1))
Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(1))
env := getFeatureStoreYamlEnvVar(deploy.Spec.Template.Spec.Containers[0].Env)
Expand Down Expand Up @@ -517,6 +519,7 @@ var _ = Describe("FeatureStore Controller", func() {
Expect(err).NotTo(HaveOccurred())
Expect(deploy.Spec.Replicas).To(Equal(&services.DefaultReplicas))
Expect(controllerutil.HasControllerReference(deploy)).To(BeTrue())
Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name))
Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1))

svc := &corev1.Service{}
Expand Down Expand Up @@ -555,6 +558,11 @@ var _ = Describe("FeatureStore Controller", func() {
Expect(err).NotTo(HaveOccurred())
Expect(deployList.Items).To(HaveLen(3))

saList := corev1.ServiceAccountList{}
err = k8sClient.List(ctx, &saList, listOpts)
Expect(err).NotTo(HaveOccurred())
Expect(saList.Items).To(HaveLen(3))

svcList := corev1.ServiceList{}
err = k8sClient.List(ctx, &svcList, listOpts)
Expect(err).NotTo(HaveOccurred())
Expand All @@ -580,6 +588,7 @@ var _ = Describe("FeatureStore Controller", func() {
},
deploy)
Expect(err).NotTo(HaveOccurred())
Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name))
Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1))
Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(1))
env := getFeatureStoreYamlEnvVar(deploy.Spec.Template.Spec.Containers[0].Env)
Expand Down Expand Up @@ -613,6 +622,7 @@ var _ = Describe("FeatureStore Controller", func() {
},
deploy)
Expect(err).NotTo(HaveOccurred())
Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name))
Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1))
Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(1))
env = getFeatureStoreYamlEnvVar(deploy.Spec.Template.Spec.Containers[0].Env)
Expand Down Expand Up @@ -650,6 +660,7 @@ var _ = Describe("FeatureStore Controller", func() {
},
deploy)
Expect(err).NotTo(HaveOccurred())
Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name))
Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1))
Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(3))
Expect(deploy.Spec.Template.Spec.Containers[0].ImagePullPolicy).To(Equal(corev1.PullAlways))
Expand Down Expand Up @@ -799,6 +810,7 @@ var _ = Describe("FeatureStore Controller", func() {
},
deploy)
Expect(err).NotTo(HaveOccurred())
Expect(deploy.Spec.Template.Spec.ServiceAccountName).To(Equal(deploy.Name))
Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1))
Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(HaveLen(3))
Expect(areEnvVarArraysEqual(deploy.Spec.Template.Spec.Containers[0].Env, []corev1.EnvVar{{Name: testEnvVarName, Value: testEnvVarValue}, {Name: services.FeatureStoreYamlEnvVar, Value: fsYamlStr}, {Name: "fieldRefName", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.namespace"}}}})).To(BeTrue())
Expand Down
48 changes: 41 additions & 7 deletions infra/feast-operator/internal/controller/services/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,27 +88,33 @@ func (feast *FeastServices) Deploy() error {
}

func (feast *FeastServices) deployFeastServiceByType(feastType FeastServiceType) error {
if err := feast.createService(feastType); err != nil {
return feast.setFeastServiceCondition(err, feastType)
}
if err := feast.createDeployment(feastType); err != nil {
return feast.setFeastServiceCondition(err, feastType)
}
if pvcCreate, shouldCreate := shouldCreatePvc(feast.FeatureStore, feastType); shouldCreate {
if err := feast.createPVC(pvcCreate, feastType); err != nil {
return feast.setFeastServiceCondition(err, feastType)
}
} else {
_ = feast.deleteOwnedFeastObj(feast.initPVC(feastType))
}
if err := feast.createServiceAccount(feastType); err != nil {
return feast.setFeastServiceCondition(err, feastType)
}
if err := feast.createDeployment(feastType); err != nil {
return feast.setFeastServiceCondition(err, feastType)
}
if err := feast.createService(feastType); err != nil {
return feast.setFeastServiceCondition(err, feastType)
}
return feast.setFeastServiceCondition(nil, feastType)
}

func (feast *FeastServices) removeFeastServiceByType(feastType FeastServiceType) error {
if err := feast.deleteOwnedFeastObj(feast.initFeastSvc(feastType)); err != nil {
return err
}
if err := feast.deleteOwnedFeastObj(feast.initFeastDeploy(feastType)); err != nil {
return err
}
if err := feast.deleteOwnedFeastObj(feast.initFeastSvc(feastType)); err != nil {
if err := feast.deleteOwnedFeastObj(feast.initFeastSA(feastType)); err != nil {
return err
}
if err := feast.deleteOwnedFeastObj(feast.initPVC(feastType)); err != nil {
Expand All @@ -131,6 +137,19 @@ func (feast *FeastServices) createService(feastType FeastServiceType) error {
return nil
}

func (feast *FeastServices) createServiceAccount(feastType FeastServiceType) error {
logger := log.FromContext(feast.Context)
sa := feast.initFeastSA(feastType)
if op, err := controllerutil.CreateOrUpdate(feast.Context, feast.Client, sa, controllerutil.MutateFn(func() error {
return feast.setServiceAccount(sa, feastType)
})); err != nil {
return err
} else if op == controllerutil.OperationResultCreated || op == controllerutil.OperationResultUpdated {
logger.Info("Successfully reconciled", "ServiceAccount", sa.Name, "operation", op)
}
return nil
}

func (feast *FeastServices) createDeployment(feastType FeastServiceType) error {
logger := log.FromContext(feast.Context)
deploy := feast.initFeastDeploy(feastType)
Expand Down Expand Up @@ -173,6 +192,7 @@ func (feast *FeastServices) setDeployment(deploy *appsv1.Deployment, feastType F
deploySettings := FeastServiceConstants[feastType]
serviceConfigs := feast.getServiceConfigs(feastType)
defaultServiceConfigs := serviceConfigs.DefaultConfigs
sa := feast.initFeastSA(feastType)

// standard configs are applied here
probeHandler := corev1.ProbeHandler{
Expand All @@ -188,6 +208,7 @@ func (feast *FeastServices) setDeployment(deploy *appsv1.Deployment, feastType F
Labels: deploy.GetLabels(),
},
Spec: corev1.PodSpec{
ServiceAccountName: sa.Name,
Containers: []corev1.Container{
{
Name: string(feastType),
Expand Down Expand Up @@ -252,6 +273,11 @@ func (feast *FeastServices) setService(svc *corev1.Service, feastType FeastServi
return controllerutil.SetControllerReference(feast.FeatureStore, svc, feast.Scheme)
}

func (feast *FeastServices) setServiceAccount(sa *corev1.ServiceAccount, feastType FeastServiceType) error {
sa.Labels = feast.getLabels(feastType)
return controllerutil.SetControllerReference(feast.FeatureStore, sa, feast.Scheme)
}

func (feast *FeastServices) createNewPVC(pvcCreate *feastdevv1alpha1.PvcCreate, feastType FeastServiceType) (*corev1.PersistentVolumeClaim, error) {
pvc := feast.initPVC(feastType)

Expand Down Expand Up @@ -426,6 +452,14 @@ func (feast *FeastServices) initFeastSvc(feastType FeastServiceType) *corev1.Ser
return svc
}

func (feast *FeastServices) initFeastSA(feastType FeastServiceType) *corev1.ServiceAccount {
sa := &corev1.ServiceAccount{
ObjectMeta: feast.GetObjectMeta(feastType),
}
sa.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("ServiceAccount"))
return sa
}

func (feast *FeastServices) initPVC(feastType FeastServiceType) *corev1.PersistentVolumeClaim {
pvc := &corev1.PersistentVolumeClaim{
ObjectMeta: feast.GetObjectMeta(feastType),
Expand Down

0 comments on commit cde5760

Please sign in to comment.