diff --git a/apps/api/prisma/migrations/20221026115123_service_persistent_unique/migration.sql b/apps/api/prisma/migrations/20221026115123_service_persistent_unique/migration.sql new file mode 100644 index 000000000..dae80a76a --- /dev/null +++ b/apps/api/prisma/migrations/20221026115123_service_persistent_unique/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - A unique constraint covering the columns `[serviceId,containerId,path]` on the table `ServicePersistentStorage` will be added. If there are existing duplicate values, this will fail. + +*/ +-- DropIndex +DROP INDEX "ServicePersistentStorage_serviceId_path_key"; + +-- CreateIndex +CREATE UNIQUE INDEX "ServicePersistentStorage_serviceId_containerId_path_key" ON "ServicePersistentStorage"("serviceId", "containerId", "path"); diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index c52d0a9cc..495d881a8 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -203,7 +203,7 @@ model ServicePersistentStorage { updatedAt DateTime @updatedAt service Service @relation(fields: [serviceId], references: [id]) - @@unique([serviceId, path]) + @@unique([serviceId, containerId, path]) } model Secret { diff --git a/apps/api/src/lib/services/handlers.ts b/apps/api/src/lib/services/handlers.ts index 29e487749..e32de36bb 100644 --- a/apps/api/src/lib/services/handlers.ts +++ b/apps/api/src/lib/services/handlers.ts @@ -75,12 +75,12 @@ export async function startService(request: FastifyRequest) { } } } - const customVolumes = await prisma.servicePersistentStorage.findMany({ where: { serviceId: service } }) + const customVolumes = await prisma.servicePersistentStorage.findMany({ where: { serviceId: id } }) let volumes = arm ? template.services[service].volumesArm : template.services[service].volumes if (customVolumes.length > 0) { for (const customVolume of customVolumes) { - const { volumeName, path } = customVolume - if (!volumes.includes(`${volumeName}:${path}`)) { + const { volumeName, path, containerId } = customVolume + if (!volumes.includes(`${volumeName}:${path}`) && containerId === service) { volumes.push(`${volumeName}:${path}`) } } @@ -102,7 +102,7 @@ export async function startService(request: FastifyRequest) { labels: makeLabelForServices(type), ...defaultComposeConfiguration(network), } - + // Generate files for builds if (template.services[service]?.files?.length > 0) { if (!template.services[service].build) { diff --git a/apps/api/src/routes/api/v1/services/handlers.ts b/apps/api/src/routes/api/v1/services/handlers.ts index 092656771..9721af81c 100644 --- a/apps/api/src/routes/api/v1/services/handlers.ts +++ b/apps/api/src/routes/api/v1/services/handlers.ts @@ -613,9 +613,8 @@ export async function saveServiceStorage(request: FastifyRequest) { try { - const { id } = request.params - const { path } = request.body - await prisma.servicePersistentStorage.deleteMany({ where: { serviceId: id, path } }); + const { storageId } = request.body + await prisma.servicePersistentStorage.deleteMany({ where: { id: storageId } }); return {} } catch ({ status, message }) { return errorHandler({ status, message }) diff --git a/apps/api/src/routes/api/v1/services/types.ts b/apps/api/src/routes/api/v1/services/types.ts index 0ade00359..f2ecbed8f 100644 --- a/apps/api/src/routes/api/v1/services/types.ts +++ b/apps/api/src/routes/api/v1/services/types.ts @@ -74,7 +74,7 @@ export interface SaveServiceStorage extends OnlyId { export interface DeleteServiceStorage extends OnlyId { Body: { - path: string, + storageId: string, } } export interface ServiceStartStop { diff --git a/apps/ui/src/routes/services/[id]/_Storage.svelte b/apps/ui/src/routes/services/[id]/_Storage.svelte index 97e3b1632..7a9e3368b 100644 --- a/apps/ui/src/routes/services/[id]/_Storage.svelte +++ b/apps/ui/src/routes/services/[id]/_Storage.svelte @@ -56,14 +56,20 @@ return errorNotification(error); } } - async function removeStorage(path: string) { + async function removeStorage(removableStorage: any) { try { - await del(`/services/${id}/storages`, { path: storage.path }); - dispatch('refresh'); - addToast({ - message: $t('application.storage.storage_deleted'), - type: 'success' - }); + const { id: storageId, volumeName, path } = removableStorage; + const sure = confirm( + `Are you sure you want to delete this storage ${volumeName + ':' + path}?` + ); + if (sure) { + await del(`/services/${id}/storages`, { storageId }); + dispatch('refresh'); + addToast({ + message: $t('application.storage.storage_deleted'), + type: 'success' + }); + } } catch (error) { return errorNotification(error); } @@ -97,13 +103,13 @@ {:else if isNew}
-
-
+
+
-
-
- -
+
{:else}
- + s.id === storage.containerId).name || storage.containerId}`} + />
diff --git a/apps/ui/src/routes/services/[id]/storages.svelte b/apps/ui/src/routes/services/[id]/storages.svelte index 10013d938..c7b12a029 100644 --- a/apps/ui/src/routes/services/[id]/storages.svelte +++ b/apps/ui/src/routes/services/[id]/storages.svelte @@ -62,20 +62,29 @@
Volume ID : Mount Dir
+ + {#each persistentStorages.filter((s) => s.predefined) as storage} + {#key storage.id} + + {/key} + {/each} {/if} - {#each persistentStorages.filter((s) => s.predefined) as storage} - {#key storage.id} - - {/key} - {/each} + + {#if persistentStorages.filter((s) => !s.predefined).length > 0} +
s.predefined).length > 0}> + Custom Volumes +
+ + {#each persistentStorages.filter((s) => !s.predefined) as storage} + {#key storage.id} + + {/key} + {/each} + {/if} +
s.predefined).length > 0}> - Custom Volumes + Add New Volume
- {#each persistentStorages.filter((s) => !s.predefined) as storage} - {#key storage.id} - - {/key} - {/each}