@@ -16,14 +16,8 @@ import { toast } from "sonner";
1616import { AppExtendedModel } from "@/shared/model/app-extended.model" ;
1717import { Trash2 , Plus } from "lucide-react" ;
1818import { z } from "zod" ;
19-
20- // Zod schema for the container config form
21- const appContainerConfigZodModel = z . object ( {
22- containerCommand : z . string ( ) . trim ( ) . nullish ( ) ,
23- containerArgs : z . array ( z . object ( {
24- value : z . string ( ) . trim ( )
25- } ) ) . optional ( ) ,
26- } ) ;
19+ import { appContainerConfigZodModel } from "@/shared/model/app-container-config.model" ;
20+ import FormLabelWithQuestion from "@/components/custom/form-label-with-question" ;
2721
2822export type AppContainerConfigInputModel = z . infer < typeof appContainerConfigZodModel > ;
2923
@@ -41,6 +35,9 @@ export default function GeneralAppContainerConfig({ app, readonly }: {
4135 defaultValues : {
4236 containerCommand : app . containerCommand || '' ,
4337 containerArgs : initialArgs ,
38+ securityContextRunAsUser : app . securityContextRunAsUser ?? undefined ,
39+ securityContextRunAsGroup : app . securityContextRunAsGroup ?? undefined ,
40+ securityContextFsGroup : app . securityContextFsGroup ?? undefined ,
4441 } ,
4542 disabled : readonly ,
4643 } ) ;
@@ -150,6 +147,80 @@ export default function GeneralAppContainerConfig({ app, readonly }: {
150147 </ Button >
151148 ) }
152149 </ div >
150+
151+ < div className = "space-y-4" >
152+ < div >
153+ < p className = "text-sm font-medium" > Security Context (optional)</ p >
154+ < p className = "text-sm text-muted-foreground mt-1" >
155+ Use this when your app requires specific user/group permissions or needs to run with a specific filesystem group for volume access.
156+ </ p >
157+ </ div >
158+ < div className = "grid grid-cols-3 gap-4" >
159+ < FormField
160+ control = { form . control }
161+ name = "securityContextRunAsUser"
162+ render = { ( { field } ) => (
163+ < FormItem >
164+ < FormLabelWithQuestion hint = "The UID to run the container process as. Corresponds to runAsUser in the Kubernetes pod securityContext." >
165+ Run As User
166+ </ FormLabelWithQuestion >
167+ < FormControl >
168+ < Input
169+ type = "number"
170+ placeholder = "e.g., 1001"
171+ { ...field }
172+ value = { field . value ?? '' }
173+ onChange = { e => field . onChange ( e . target . value === '' ? null : Number ( e . target . value ) ) }
174+ />
175+ </ FormControl >
176+ < FormMessage />
177+ </ FormItem >
178+ ) }
179+ />
180+ < FormField
181+ control = { form . control }
182+ name = "securityContextRunAsGroup"
183+ render = { ( { field } ) => (
184+ < FormItem >
185+ < FormLabelWithQuestion hint = "The GID to run the container process as. Corresponds to runAsGroup in the Kubernetes pod securityContext." >
186+ Run As Group
187+ </ FormLabelWithQuestion >
188+ < FormControl >
189+ < Input
190+ type = "number"
191+ placeholder = "e.g., 1001"
192+ { ...field }
193+ value = { field . value ?? '' }
194+ onChange = { e => field . onChange ( e . target . value === '' ? null : Number ( e . target . value ) ) }
195+ />
196+ </ FormControl >
197+ < FormMessage />
198+ </ FormItem >
199+ ) }
200+ />
201+ < FormField
202+ control = { form . control }
203+ name = "securityContextFsGroup"
204+ render = { ( { field } ) => (
205+ < FormItem >
206+ < FormLabelWithQuestion hint = "A special supplemental group applied to all containers in the pod. Volume ownership will be set to this GID. Corresponds to fsGroup in the Kubernetes pod securityContext." >
207+ FS Group
208+ </ FormLabelWithQuestion >
209+ < FormControl >
210+ < Input
211+ type = "number"
212+ placeholder = "e.g., 1001"
213+ { ...field }
214+ value = { field . value ?? '' }
215+ onChange = { e => field . onChange ( e . target . value === '' ? null : Number ( e . target . value ) ) }
216+ />
217+ </ FormControl >
218+ < FormMessage />
219+ </ FormItem >
220+ ) }
221+ />
222+ </ div >
223+ </ div >
153224 </ CardContent >
154225 { ! readonly && (
155226 < CardFooter className = "gap-4" >
0 commit comments