diff --git a/src/main/java/net/siegeln/cameleer/saas/portal/TenantPortalService.java b/src/main/java/net/siegeln/cameleer/saas/portal/TenantPortalService.java index cd23ea8..f29db99 100644 --- a/src/main/java/net/siegeln/cameleer/saas/portal/TenantPortalService.java +++ b/src/main/java/net/siegeln/cameleer/saas/portal/TenantPortalService.java @@ -9,6 +9,10 @@ import net.siegeln.cameleer.saas.provisioning.ProvisioningProperties; import net.siegeln.cameleer.saas.provisioning.TenantProvisioner; import net.siegeln.cameleer.saas.tenant.TenantEntity; import net.siegeln.cameleer.saas.tenant.TenantService; +import net.siegeln.cameleer.saas.vendor.VendorTenantService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.time.Instant; @@ -20,25 +24,30 @@ import java.util.UUID; @Service public class TenantPortalService { + private static final Logger log = LoggerFactory.getLogger(TenantPortalService.class); + private final TenantService tenantService; private final LicenseService licenseService; private final ServerApiClient serverApiClient; private final LogtoManagementClient logtoClient; private final TenantProvisioner tenantProvisioner; private final ProvisioningProperties provisioningProps; + private final VendorTenantService vendorTenantService; public TenantPortalService(TenantService tenantService, LicenseService licenseService, ServerApiClient serverApiClient, LogtoManagementClient logtoClient, TenantProvisioner tenantProvisioner, - ProvisioningProperties provisioningProps) { + ProvisioningProperties provisioningProps, + @Lazy VendorTenantService vendorTenantService) { this.tenantService = tenantService; this.licenseService = licenseService; this.serverApiClient = serverApiClient; this.logtoClient = logtoClient; this.tenantProvisioner = tenantProvisioner; this.provisioningProps = provisioningProps; + this.vendorTenantService = vendorTenantService; } // --- Inner records --- @@ -180,9 +189,22 @@ public class TenantPortalService { public void restartServer() { TenantEntity tenant = resolveTenant(); - if (tenantProvisioner.isAvailable()) { - tenantProvisioner.stop(tenant.getSlug()); + if (!tenantProvisioner.isAvailable()) return; + + tenantProvisioner.stop(tenant.getSlug()); + try { tenantProvisioner.start(tenant.getSlug()); + } catch (RuntimeException e) { + if (e.getMessage() != null && e.getMessage().contains("re-provision required")) { + log.info("Containers missing for '{}' — re-provisioning", tenant.getSlug()); + tenantProvisioner.remove(tenant.getSlug()); + var license = licenseService.getActiveLicense(tenant.getId()).orElse(null); + String token = license != null ? license.getToken() : ""; + vendorTenantService.provisionAsync( + tenant.getId(), tenant.getSlug(), tenant.getTier().name(), token, null); + return; + } + throw e; } } } diff --git a/src/main/java/net/siegeln/cameleer/saas/provisioning/DockerTenantProvisioner.java b/src/main/java/net/siegeln/cameleer/saas/provisioning/DockerTenantProvisioner.java index e329f47..ab43101 100644 --- a/src/main/java/net/siegeln/cameleer/saas/provisioning/DockerTenantProvisioner.java +++ b/src/main/java/net/siegeln/cameleer/saas/provisioning/DockerTenantProvisioner.java @@ -73,6 +73,9 @@ public class DockerTenantProvisioner implements TenantProvisioner { try { docker.startContainerCmd(serverContainerName(slug)).exec(); docker.startContainerCmd(uiContainerName(slug)).exec(); + } catch (NotFoundException e) { + log.warn("Containers for '{}' not found — cannot start (re-provision needed)", slug); + throw new RuntimeException("Containers not found for '" + slug + "' — re-provision required", e); } catch (Exception e) { log.error("Failed to start containers for '{}'", slug, e); throw new RuntimeException("Start failed: " + e.getMessage(), e); diff --git a/src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantService.java b/src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantService.java index 5f9eebb..6237dab 100644 --- a/src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantService.java +++ b/src/main/java/net/siegeln/cameleer/saas/vendor/VendorTenantService.java @@ -220,9 +220,21 @@ public class VendorTenantService { public void restartServer(UUID tenantId) { TenantEntity tenant = tenantService.getById(tenantId) .orElseThrow(() -> new IllegalArgumentException("Tenant not found")); - if (tenantProvisioner.isAvailable()) { - tenantProvisioner.stop(tenant.getSlug()); + if (!tenantProvisioner.isAvailable()) return; + + tenantProvisioner.stop(tenant.getSlug()); + try { tenantProvisioner.start(tenant.getSlug()); + } catch (RuntimeException e) { + if (e.getMessage() != null && e.getMessage().contains("re-provision required")) { + log.info("Containers missing for '{}' — re-provisioning", tenant.getSlug()); + tenantProvisioner.remove(tenant.getSlug()); + var license = licenseService.getActiveLicense(tenantId).orElse(null); + String token = license != null ? license.getToken() : ""; + provisionAsync(tenantId, tenant.getSlug(), tenant.getTier().name(), token, null); + return; + } + throw e; } } diff --git a/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java b/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java index 42c3c11..18466a3 100644 --- a/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java +++ b/src/test/java/net/siegeln/cameleer/saas/portal/TenantPortalServiceTest.java @@ -56,7 +56,7 @@ class TenantPortalServiceTest { @BeforeEach void setUp() { TenantContext.setTenantId(tenantId); - tenantPortalService = new TenantPortalService(tenantService, licenseService, serverApiClient, logtoClient, tenantProvisioner, provisioningProps); + tenantPortalService = new TenantPortalService(tenantService, licenseService, serverApiClient, logtoClient, tenantProvisioner, provisioningProps, null); } @AfterEach