FileBasedTenantService implements TenantService, TenantManagementService, Lifecycle { @Override public Future<Void> start() { final Promise<Void> startPromise = Promise.promise(); if (running.compareAndSet(false, true)) { if (!getConfig().isModificationEnabled()) { LOG.info("modification of registered tenants has been disabled"); } if (getConfig().getFilename() == null) { LOG.debug("tenant file name is not set, tenant information will not be loaded"); startPromise.complete(); } else { checkFileExists(getConfig().isSaveToFile()) .compose(ok -> loadTenantData()) .onSuccess(ok -> { if (getConfig().isSaveToFile()) { LOG.info("saving tenants to file every 3 seconds"); vertx.setPeriodic(3000, tid -> saveToFile()); } else { LOG.info("persistence is disabled, will not save tenants to file"); } }) .onFailure(t -> { LOG.error("failed to start up service", t); running.set(false); }) .onComplete(startPromise); } } else { startPromise.complete(); } return startPromise.future(); } @Autowired  FileBasedTenantService(final Vertx vertx); @Autowired void setConfig(final FileBasedTenantsConfigProperties configuration); @Override Future<Void> start(); @Override Future<Void> stop(); @Override Future<TenantResult<JsonObject>> get(final String tenantId); @Override Future<TenantResult<JsonObject>> get(final String tenantId, final Span span); @Override Future<TenantResult<JsonObject>> get(final X500Principal subjectDn); @Override Future<OperationResult<Tenant>> readTenant(final String tenantId, final Span span); @Override Future<TenantResult<JsonObject>> get(final X500Principal subjectDn, final Span span); @Override Future<Result<Void>> deleteTenant(final String tenantId, final Optional<String> resourceVersion,
            final Span span); @Override Future<OperationResult<Id>> createTenant(final Optional<String> tenantId, final Tenant tenantSpec,
            final Span span); @Override Future<OperationResult<Void>> updateTenant(final String tenantId, final Tenant tenantSpec,
            final Optional<String> expectedResourceVersion,
            final Span span); OperationResult<Void> update(
            final String tenantId,
            final Tenant tenantSpec,
            final Optional<String> expectedResourceVersion,
            final Span span); void clear(); @Override String toString();  }
@SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void testDoStartIgnoresMalformedJson(final VertxTestContext ctx) { props.setFilename(FILE_NAME); when(fileSystem.existsBlocking(FILE_NAME)).thenReturn(Boolean.TRUE); doAnswer(invocation -> { final Buffer data = mock(Buffer.class); when(data.getBytes()).thenReturn("NO JSON".getBytes(StandardCharsets.UTF_8)); final Handler handler = invocation.getArgument(1); handler.handle(Future.succeededFuture(data)); return null; }).when(fileSystem).readFile(eq(props.getFilename()), any(Handler.class)); final Promise<Void> startupTracker = Promise.promise(); startupTracker.future().onComplete(ctx.completing( )); svc.start().onComplete(startupTracker); }
@SuppressWarnings({ "unchecked" }) @Test public void testDoStartWithStartEmptyIgnoreTenants(final VertxTestContext ctx) { props.setFilename(FILE_NAME); props.setStartEmpty(true); when(fileSystem.existsBlocking(props.getFilename())).thenReturn(Boolean.TRUE); final Promise<Void> startupTracker = Promise.promise(); startupTracker.future().onComplete(ctx.succeeding(s -> ctx.verify(() -> { verify(fileSystem, never()).readFile(anyString(), any(Handler.class)); ctx.completeNow(); }))); svc.start().onComplete(startupTracker); }
@SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void testDoStartCreatesFile(final VertxTestContext ctx) { props.setSaveToFile(true); props.setFilename(FILE_NAME); when(fileSystem.existsBlocking(FILE_NAME)).thenReturn(Boolean.FALSE); doAnswer(invocation -> { final Handler handler = invocation.getArgument(1); handler.handle(Future.succeededFuture()); return null; }).when(fileSystem).createFile(eq(props.getFilename()), any(Handler.class)); doAnswer(invocation -> { final Handler handler = invocation.getArgument(1); handler.handle(Future.failedFuture("malformed file")); return null; }).when(fileSystem).readFile(eq(props.getFilename()), any(Handler.class)); final Promise<Void> startupTracker = Promise.promise(); startupTracker.future().onComplete(ctx.succeeding(started -> ctx.verify(() -> { verify(fileSystem).createFile(eq(FILE_NAME), any(Handler.class)); ctx.completeNow(); }))); svc.start().onComplete(startupTracker); }
@SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void testDoStartFailsIfFileCannotBeCreated(final VertxTestContext ctx) { props.setSaveToFile(true); props.setFilename(FILE_NAME); when(fileSystem.existsBlocking(FILE_NAME)).thenReturn(Boolean.FALSE); doAnswer(invocation -> { final Handler handler = invocation.getArgument(1); handler.handle(Future.failedFuture("no access")); return null; }).when(fileSystem).createFile(eq(props.getFilename()), any(Handler.class)); final Promise<Void> startupTracker = Promise.promise(); startupTracker.future().onComplete(ctx.failing(started -> { ctx.completeNow(); })); svc.start().onComplete(startupTracker); }