Skip to content

Commit 959156c

Browse files
authored
Merge pull request #372 from Mossaka/workload-id
feat: add ServiceAccountName field to SpinApp
2 parents 9c326eb + 40c8d82 commit 959156c

File tree

6 files changed

+98
-6
lines changed

6 files changed

+98
-6
lines changed

api/v1alpha1/spinapp_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ type SpinAppSpec struct {
8686
// If this is not provided all components are executed.
8787
// +kubebuilder:validation:MinItems:=1
8888
Components []string `json:"components,omitempty"`
89+
90+
// ServiceAccountName is the name of the Kubernetes service account to use for the pod.
91+
// If not specified, the default service account will be used.
92+
// +optional
93+
ServiceAccountName string `json:"serviceAccountName,omitempty"`
8994
}
9095

9196
// SpinAppStatus defines the observed state of SpinApp

config/crd/bases/core.spinkube.dev_spinapps.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,11 @@ spec:
532532
type: object
533533
type: array
534534
type: object
535+
serviceAccountName:
536+
description: |-
537+
ServiceAccountName is the name of the Kubernetes service account to use for the pod.
538+
If not specified, the default service account will be used.
539+
type: string
535540
serviceAnnotations:
536541
additionalProperties:
537542
type: string

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
6868
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
6969
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
7070
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
71-
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
7271
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
7372
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
7473
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
@@ -214,7 +213,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
214213
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
215214
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
216215
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
217-
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
218216
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
219217
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
220218
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA=

internal/controller/spinapp_controller.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,8 @@ func constructDeployment(ctx context.Context, app *spinv1alpha1.SpinApp, config
444444

445445
labels := constructAppLabels(app)
446446

447+
serviceAccountName := getServiceAccountName(ctx, app)
448+
447449
var container corev1.Container
448450
if config.RuntimeClassName != nil {
449451
container = corev1.Container{
@@ -508,10 +510,11 @@ func constructDeployment(ctx context.Context, app *spinv1alpha1.SpinApp, config
508510
Annotations: templateAnnotations,
509511
},
510512
Spec: corev1.PodSpec{
511-
RuntimeClassName: config.RuntimeClassName,
512-
Containers: []corev1.Container{container},
513-
ImagePullSecrets: app.Spec.ImagePullSecrets,
514-
Volumes: volumes,
513+
RuntimeClassName: config.RuntimeClassName,
514+
ServiceAccountName: serviceAccountName,
515+
Containers: []corev1.Container{container},
516+
ImagePullSecrets: app.Spec.ImagePullSecrets,
517+
Volumes: volumes,
515518
},
516519
},
517520
},
@@ -530,6 +533,25 @@ func constructDeployment(ctx context.Context, app *spinv1alpha1.SpinApp, config
530533
return dep, nil
531534
}
532535

536+
// getServiceAccountName returns the service account name to use for the deployment.
537+
// If serviceAccountName is specified on the SpinApp, it returns that value.
538+
// Otherwise, it returns "default" which is the Kubernetes default.
539+
func getServiceAccountName(ctx context.Context, app *spinv1alpha1.SpinApp) string {
540+
log := logging.FromContext(ctx).WithValues("component", "getServiceAccountName")
541+
542+
log.Debug("Determining service account name",
543+
"app", app.Name,
544+
"namespace", app.Namespace,
545+
"serviceAccountNameInSpec", app.Spec.ServiceAccountName)
546+
547+
if app.Spec.ServiceAccountName != "" {
548+
log.Debug("Using service account from SpinApp", "serviceAccountName", app.Spec.ServiceAccountName)
549+
return app.Spec.ServiceAccountName
550+
}
551+
552+
return "default"
553+
}
554+
533555
// findDeploymentForApp finds the deployment for a SpinApp.
534556
func (r *SpinAppReconciler) findDeploymentForApp(ctx context.Context, app *spinv1alpha1.SpinApp) (*appsv1.Deployment, error) {
535557
var deployment appsv1.Deployment

internal/controller/spinapp_controller_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,64 @@ func TestReconcile_Integration_Deployment_SpinCAInjection(t *testing.T) {
630630
cancelFunc()
631631
wg.Wait()
632632
}
633+
634+
func TestReconcile_Integration_Deployment_ServiceAccountName(t *testing.T) {
635+
t.Parallel()
636+
637+
envTest, mgr, _ := setupController(t)
638+
639+
ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)
640+
defer cancelFunc()
641+
642+
var wg sync.WaitGroup
643+
wg.Add(1)
644+
go func() {
645+
require.NoError(t, mgr.Start(ctx))
646+
wg.Done()
647+
}()
648+
649+
executor := &spinv1alpha1.SpinAppExecutor{
650+
ObjectMeta: metav1.ObjectMeta{
651+
Name: "executor",
652+
Namespace: "default",
653+
},
654+
Spec: spinv1alpha1.SpinAppExecutorSpec{
655+
CreateDeployment: true,
656+
DeploymentConfig: &spinv1alpha1.ExecutorDeploymentConfig{
657+
RuntimeClassName: generics.Ptr("foobar"),
658+
},
659+
},
660+
}
661+
662+
require.NoError(t, envTest.k8sClient.Create(ctx, executor))
663+
664+
spinApp := &spinv1alpha1.SpinApp{
665+
ObjectMeta: metav1.ObjectMeta{
666+
Name: "app",
667+
Namespace: "default",
668+
},
669+
Spec: spinv1alpha1.SpinAppSpec{
670+
Executor: "executor",
671+
Image: "ghcr.io/radu-matei/perftest:v1",
672+
ServiceAccountName: "my-service-account",
673+
},
674+
}
675+
676+
require.NoError(t, envTest.k8sClient.Create(ctx, spinApp))
677+
678+
var deployment appsv1.Deployment
679+
require.Eventually(t, func() bool {
680+
err := envTest.k8sClient.Get(ctx,
681+
types.NamespacedName{
682+
Namespace: "default",
683+
Name: spinApp.Name},
684+
&deployment)
685+
return err == nil
686+
}, 3*time.Second, 100*time.Millisecond)
687+
688+
require.Equal(t, "my-service-account", deployment.Spec.Template.Spec.ServiceAccountName)
689+
690+
// Terminate the context to force the manager to shut down.
691+
cancelFunc()
692+
wg.Wait()
693+
}

internal/webhook/spinapp_validating.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ func (v *SpinAppValidator) validateSpinApp(ctx context.Context, spinApp *spinv1a
6464
if err := validateAnnotations(spinApp.Spec, executor); err != nil {
6565
allErrs = append(allErrs, err)
6666
}
67+
6768
if len(allErrs) == 0 {
6869
return nil
6970
}

0 commit comments

Comments
 (0)