diff --git a/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.test.ts b/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.test.ts index 9e39fe510..c3a39f109 100644 --- a/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.test.ts +++ b/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.test.ts @@ -282,6 +282,11 @@ const createComplicatedStatefulSetSummaries: Array = [ kind: 'Ingress', name: 'default-ingress-3', }, + { + action: 'Create', + kind: 'PersistentVolumeClaim', + name: 'my-app-6be07c40-de3a-4775-a29b-19a60890052e-my-app-0', + }, { action: 'Create', kind: 'HorizontalPodAutoscaler', @@ -464,6 +469,11 @@ const updateComplicatedStatefulSetSummaries: Array = [ name: 'my-app-3', type: 'LoadBalancer', }, + { + action: 'Create', + kind: 'PersistentVolumeClaim', + name: 'test-6be07c40-de3a-4775-a29b-19a60890052e-test-0-my-app-0', + }, ]; const updateDeploymentToStatefulSetSummaries: Array = [ @@ -477,6 +487,11 @@ const updateDeploymentToStatefulSetSummaries: Array = [ kind: 'StatefulSet', name: 'my-app', }, + { + action: 'Create', + kind: 'PersistentVolumeClaim', + name: 'test-6be07c40-de3a-4775-a29b-19a60890052e-test-0-my-app-0', + }, { action: 'Create', kind: 'HorizontalPodAutoscaler', diff --git a/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.ts b/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.ts index f69328f23..46babdb59 100644 --- a/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.ts +++ b/app/react/kubernetes/applications/components/ApplicationSummarySection/utils.ts @@ -88,23 +88,7 @@ function getCreatedApplicationResourcesNew( }) || []; // persistent volume claim (pvc) summaries - const pvcSummaries: Array = - // apps with a isolated data access policy are statefulsets. - // statefulset pvcs are defined in spec.volumeClaimTemplates. - // https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-storage - formValues.DataAccessPolicy === 'Shared' - ? formValues.PersistedFolders?.filter( - // only create pvc summaries for new pvcs - (volume) => !volume.existingVolume?.PersistentVolumeClaim.Name - ).map((volume) => ({ - action: 'Create', - kind: 'PersistentVolumeClaim', - name: - volume.existingVolume?.PersistentVolumeClaim.Name || - volume.persistentVolumeClaimName || - '', - })) || [] - : []; + const pvcSummaries: Array = getPVCSummaries(formValues); // horizontal pod autoscaler summaries const hpaSummary: Array = @@ -181,36 +165,10 @@ function getUpdatedApplicationResources( const ingressSummaries = getIngressUpdateSummary(oldIngresses, newIngresses); // persistent volume claim (pvc) summaries - const pvcSummaries: Array = - // apps with a isolated data access policy are statefulsets. - // statefulset pvcs are defined in spec.volumeClaimTemplates. - // https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-storage - newFormValues.DataAccessPolicy === 'Shared' - ? newFormValues.PersistedFolders?.filter( - // only create pvc summaries for new pvcs - (volume) => !volume.existingVolume?.PersistentVolumeClaim.Name - ).flatMap((newVolume) => { - const oldVolume = oldFormValues.PersistedFolders?.find( - (oldVolume) => - oldVolume.persistentVolumeClaimName === - newVolume.persistentVolumeClaimName - ); - if (!oldVolume) { - return [ - { - action: 'Create', - kind: 'PersistentVolumeClaim', - name: - newVolume.existingVolume?.PersistentVolumeClaim.Name || - newVolume.persistentVolumeClaimName || - '', - }, - ]; - } - // updating a pvc is not supported - return []; - }) || [] - : []; + const pvcSummaries: Array = getPVCSummaries( + newFormValues, + oldFormValues + ); // TODO: horizontal pod autoscaler summaries const createHPASummary: Array = @@ -266,6 +224,77 @@ function getUpdatedApplicationResources( ]; } +function getPVCSummaries( + newFormValues: ApplicationFormValues, + oldFormValues?: ApplicationFormValues +): Array { + // only create pvc summaries for new pvcs + const newVolumeClaims = + newFormValues.PersistedFolders?.filter((volume) => { + // if the volume is an existing volume + if (volume.existingVolume?.PersistentVolumeClaim.Name) { + return false; + } + // to be sure the volume is new, check if it was in the old form values + const oldVolume = oldFormValues?.PersistedFolders?.find( + (oldVolume) => + oldVolume.persistentVolumeClaimName === + volume.persistentVolumeClaimName + ); + if (oldVolume) { + return false; + } + return true; + }) || []; + + if (newFormValues.DataAccessPolicy === 'Shared') { + return newVolumeClaims.map((newVolume) => { + const name = + newVolume.existingVolume?.PersistentVolumeClaim.Name || + newVolume.persistentVolumeClaimName || + ''; + return { + action: 'Create', + kind: 'PersistentVolumeClaim', + name, + }; + }); + } + + if (newFormValues.DataAccessPolicy === 'Isolated') { + // apps with a isolated data access policy are statefulsets. + // statefulset pvcs are defined in spec.volumeClaimTemplates. + // they aren't directly created with manifests, but are created when the statefulset is created (1 PVC PER POD), so should be included + // https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-storage + + // for each volume claim, there is a PVC created per pod + const newFormReplicas = newFormValues.ReplicaCount || 0; + const newPVCAppendedIndexStrings = Array.from( + { length: newFormReplicas }, + (_, i) => i + ); + const PVCSummariesFromNewVolumeClaims: Summary[] = newVolumeClaims.flatMap( + (volume) => + newPVCAppendedIndexStrings.map((appendedIndex) => { + const prefixName = + volume.existingVolume?.PersistentVolumeClaim.Name || + volume.persistentVolumeClaimName || + ''; + return { + action: 'Create', + kind: 'PersistentVolumeClaim', + // name in the same way that the statefulset would name it + name: `${prefixName}-${newFormValues.Name}-${appendedIndex}`, + }; + }) + ); + // kubernetes blocks editing statefulset volume claims, so we don't need to handle updating them + return PVCSummariesFromNewVolumeClaims; + } + + return []; +} + // getServiceUpdateResourceSummary replicates KubernetesServiceService.patch function getServiceUpdateResourceSummary( oldServices?: Array,