@@ -52,6 +52,7 @@ type SandboxReconciler struct {
5252
5353//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch;create;update;patch;delete
5454//+kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete
55+ //+kubebuilder:rbac:groups=core,resources=persistentvolumeclaims,verbs=get;list;watch;create;update;patch;delete
5556
5657// Reconcile is part of the main kubernetes reconciliation loop which aims to
5758// move the current state of the cluster closer to the desired state.
@@ -86,9 +87,13 @@ func (r *SandboxReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
8687
8788 var allErrors error
8889
90+ // Reconcile PVCs
91+ err := r .reconcilePVCs (ctx , sandbox )
92+ allErrors = errors .Join (allErrors , err )
93+
8994 // Reconcile Pod
9095 pod , err := r .reconcilePod (ctx , sandbox , nameHash )
91- allErrors = errors .Join (err )
96+ allErrors = errors .Join (allErrors , err )
9297
9398 // Reconcile Service
9499 svc , err := r .reconcileService (ctx , sandbox , nameHash )
@@ -259,14 +264,27 @@ func (r *SandboxReconciler) reconcilePod(ctx context.Context, sandbox *sandboxv1
259264 annotations [k ] = v
260265 }
261266
267+ mutatedSpec := sandbox .Spec .PodTemplate .Spec .DeepCopy ()
268+
269+ for _ , pvcTemplate := range sandbox .Spec .VolumeClaimTemplates {
270+ pvcName := pvcTemplate .ObjectMeta .Name + "-" + sandbox .Name
271+ mutatedSpec .Volumes = append (mutatedSpec .Volumes , corev1.Volume {
272+ Name : pvcTemplate .ObjectMeta .Name ,
273+ VolumeSource : corev1.VolumeSource {
274+ PersistentVolumeClaim : & corev1.PersistentVolumeClaimVolumeSource {
275+ ClaimName : pvcName ,
276+ },
277+ },
278+ })
279+ }
262280 pod = & corev1.Pod {
263281 ObjectMeta : metav1.ObjectMeta {
264282 Name : sandbox .Name ,
265283 Namespace : sandbox .Namespace ,
266284 Labels : labels ,
267285 Annotations : annotations ,
268286 },
269- Spec : sandbox . Spec . PodTemplate . Spec ,
287+ Spec : * mutatedSpec ,
270288 }
271289 pod .SetGroupVersionKind (corev1 .SchemeGroupVersion .WithKind ("Pod" ))
272290 if err := ctrl .SetControllerReference (sandbox , pod , r .Scheme ); err != nil {
@@ -280,6 +298,38 @@ func (r *SandboxReconciler) reconcilePod(ctx context.Context, sandbox *sandboxv1
280298 return pod , nil
281299}
282300
301+ func (r * SandboxReconciler ) reconcilePVCs (ctx context.Context , sandbox * sandboxv1alpha1.Sandbox ) error {
302+ log := log .FromContext (ctx )
303+ for _ , pvcTemplate := range sandbox .Spec .VolumeClaimTemplates {
304+ pvc := & corev1.PersistentVolumeClaim {}
305+ pvcName := pvcTemplate .ObjectMeta .Name + "-" + sandbox .Name
306+ err := r .Get (ctx , types.NamespacedName {Name : pvcName , Namespace : sandbox .Namespace }, pvc )
307+ if err != nil {
308+ if k8serrors .IsNotFound (err ) {
309+ log .Info ("Creating a new PVC" , "PVC.Namespace" , sandbox .Namespace , "PVC.Name" , pvcName )
310+ pvc = & corev1.PersistentVolumeClaim {
311+ ObjectMeta : metav1.ObjectMeta {
312+ Name : pvcName ,
313+ Namespace : sandbox .Namespace ,
314+ },
315+ Spec : pvcTemplate .Spec ,
316+ }
317+ if err := ctrl .SetControllerReference (sandbox , pvc , r .Scheme ); err != nil {
318+ return fmt .Errorf ("SetControllerReference for PVC failed: %w" , err )
319+ }
320+ if err := r .Create (ctx , pvc , client .FieldOwner ("sandbox-controller" )); err != nil {
321+ log .Error (err , "Failed to create PVC" , "PVC.Namespace" , sandbox .Namespace , "PVC.Name" , pvcName )
322+ return err
323+ }
324+ } else {
325+ log .Error (err , "Failed to get PVC" )
326+ return fmt .Errorf ("PVC Get Failed: %w" , err )
327+ }
328+ }
329+ }
330+ return nil
331+ }
332+
283333// SetupWithManager sets up the controller with the Manager.
284334func (r * SandboxReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
285335 labelSelectorPredicate , err := predicate .LabelSelectorPredicate (metav1.LabelSelector {
0 commit comments