Skip to content

Commit 269d899

Browse files
authored
Merge pull request #224 from weaviate/activate_deactivate_tenants_support
Activate deactivate tenants support
2 parents 0ab5c7e + 0211627 commit 269d899

20 files changed

+639
-249
lines changed

src/main/java/io/weaviate/client/v1/schema/Schema.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.weaviate.client.v1.schema.api.TenantsCreator;
1616
import io.weaviate.client.v1.schema.api.TenantsDeleter;
1717
import io.weaviate.client.v1.schema.api.TenantsGetter;
18+
import io.weaviate.client.v1.schema.api.TenantsUpdater;
1819

1920
public class Schema {
2021
private final Config config;
@@ -69,6 +70,10 @@ public TenantsCreator tenantsCreator() {
6970
return new TenantsCreator(httpClient, config);
7071
}
7172

73+
public TenantsUpdater tenantsUpdater() {
74+
return new TenantsUpdater(httpClient, config);
75+
}
76+
7277
public TenantsDeleter tenantsDeleter() {
7378
return new TenantsDeleter(httpClient, config);
7479
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.weaviate.client.v1.schema.api;
2+
3+
import io.weaviate.client.Config;
4+
import io.weaviate.client.base.BaseClient;
5+
import io.weaviate.client.base.ClientResult;
6+
import io.weaviate.client.base.Response;
7+
import io.weaviate.client.base.Result;
8+
import io.weaviate.client.base.http.HttpClient;
9+
import io.weaviate.client.base.util.UrlEncoder;
10+
import io.weaviate.client.v1.schema.model.Tenant;
11+
import org.apache.http.HttpStatus;
12+
13+
public class TenantsUpdater extends BaseClient<Tenant[]> implements ClientResult<Boolean> {
14+
15+
private String className;
16+
private Tenant[] tenants;
17+
18+
public TenantsUpdater(HttpClient httpClient, Config config) {
19+
super(httpClient, config);
20+
}
21+
22+
public TenantsUpdater withClassName(String className) {
23+
this.className = className;
24+
return this;
25+
}
26+
27+
public TenantsUpdater withTenants(Tenant... tenants) {
28+
this.tenants = tenants;
29+
return this;
30+
}
31+
32+
@Override
33+
public Result<Boolean> run() {
34+
String path = String.format("/schema/%s/tenants", UrlEncoder.encodePathParam(className));
35+
Response<Tenant[]> resp = sendPutRequest(path, tenants, Tenant[].class);
36+
return new Result<>(resp.getStatusCode(), resp.getStatusCode() == HttpStatus.SC_OK, resp.getErrors());
37+
}
38+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.weaviate.client.v1.schema.model;
2+
3+
public interface ActivityStatus {
4+
String HOT = "HOT";
5+
String WARM = "WARM";
6+
String COLD = "COLD";
7+
String FROZEN = "FROZEN";
8+
}

src/main/java/io/weaviate/client/v1/schema/model/Tenant.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
1515
public class Tenant {
1616
String name;
17+
String activityStatus;
1718
}

src/test/java/io/weaviate/integration/client/AssertMultiTenancy.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
import io.weaviate.client.base.WeaviateError;
66
import io.weaviate.client.base.WeaviateErrorMessage;
77
import io.weaviate.client.v1.data.model.WeaviateObject;
8+
import io.weaviate.client.v1.schema.model.ActivityStatus;
9+
import io.weaviate.client.v1.schema.model.Tenant;
810

911
import java.util.List;
12+
import java.util.Objects;
13+
import java.util.Optional;
1014

1115
import static org.assertj.core.api.Assertions.assertThat;
1216
import static org.assertj.core.api.InstanceOfAssertFactories.STRING;
@@ -70,4 +74,51 @@ public <T> void error(Result<T> result, T expectedValue, int expectedStatusCode,
7074
.extracting(m -> ((WeaviateErrorMessage) m).getMessage()).asInstanceOf(STRING)
7175
.contains(expectedContains);
7276
}
77+
78+
public void tenantActive(String className, String tenantName) {
79+
tenantStatus(className, tenantName, ActivityStatus.HOT);
80+
}
81+
82+
public void tenantInactive(String className, String tenantName) {
83+
tenantStatus(className, tenantName, ActivityStatus.COLD);
84+
}
85+
86+
private void tenantStatus(String className, String tenantName, String activityStatus) {
87+
Result<List<Tenant>> result = client.schema().tenantsGetter()
88+
.withClassName(className)
89+
.run();
90+
91+
assertThat(result).isNotNull()
92+
.returns(false, Result::hasErrors)
93+
.extracting(Result::getResult).isNotNull();
94+
95+
Optional<Tenant> maybeTenant = result.getResult().stream()
96+
.filter(Objects::nonNull)
97+
.filter(tenant -> tenantName.equals(tenant.getName()))
98+
.filter(tenant -> activityStatus.equals(tenant.getActivityStatus()))
99+
.findFirst();
100+
101+
assertThat(maybeTenant).isNotEmpty();
102+
}
103+
104+
public void tenantActiveGetsObjects(String className, String tenantName, int objectsCount) {
105+
Result<List<WeaviateObject>> result = client.data().objectsGetter()
106+
.withClassName(className)
107+
.withTenant(tenantName)
108+
.run();
109+
110+
assertThat(result).isNotNull()
111+
.returns(false, Result::hasErrors)
112+
.extracting(Result::getResult).asList()
113+
.hasSize(objectsCount);
114+
}
115+
116+
public void tenantInactiveGetsNoObjects(String className, String tenantName) {
117+
Result<List<WeaviateObject>> result = client.data().objectsGetter()
118+
.withClassName(className)
119+
.withTenant(tenantName)
120+
.run();
121+
122+
error(result, null, 422, "tenant not active");
123+
}
73124
}

src/test/java/io/weaviate/integration/client/WeaviateTestGenerics.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ public class WeaviateTestGenerics {
6161
));
6262
}
6363

64+
public static final Tenant TENANT_1 = Tenant.builder()
65+
.name("TenantNo1")
66+
.build();
67+
public static final Tenant TENANT_2 = Tenant.builder()
68+
.name("TenantNo2")
69+
.build();
70+
6471

6572
public void createWeaviateTestSchemaFood(WeaviateClient client) {
6673
createWeaviateTestSchemaFood(client, false);
@@ -368,27 +375,23 @@ private void createSchema(WeaviateClient client, WeaviateClass cl) {
368375
}
369376

370377

371-
public void createTenantsPizza(WeaviateClient client, String... tenants) {
378+
public void createTenantsPizza(WeaviateClient client, Tenant... tenants) {
372379
createTenants(client, "Pizza", tenants);
373380
}
374381

375-
public void createTenantsSoup(WeaviateClient client, String... tenants) {
382+
public void createTenantsSoup(WeaviateClient client, Tenant... tenants) {
376383
createTenants(client, "Soup", tenants);
377384
}
378385

379-
public void createTenantsFood(WeaviateClient client, String... tenants) {
386+
public void createTenantsFood(WeaviateClient client, Tenant... tenants) {
380387
createTenantsPizza(client, tenants);
381388
createTenantsSoup(client, tenants);
382389
}
383390

384-
private void createTenants(WeaviateClient client, String className, String[] tenants) {
385-
Tenant[] t = Arrays.stream(tenants)
386-
.map(tenant -> Tenant.builder().name(tenant).build())
387-
.toArray(Tenant[]::new);
388-
391+
private void createTenants(WeaviateClient client, String className, Tenant[] tenants) {
389392
Result<Boolean> createStatus = client.schema().tenantsCreator()
390393
.withClassName(className)
391-
.withTenants(t)
394+
.withTenants(tenants)
392395
.run();
393396
assertThat(createStatus).isNotNull()
394397
.returns(false, Result::hasErrors)

src/test/java/io/weaviate/integration/client/WeaviateVersion.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
public class WeaviateVersion {
44

55
// to be set according to weaviate docker image
6-
public static final String EXPECTED_WEAVIATE_VERSION = "1.20.0";
6+
public static final String EXPECTED_WEAVIATE_VERSION = "1.21.0-rc.1";
77
// to be set according to weaviate docker image
8-
public static final String EXPECTED_WEAVIATE_GIT_HASH = "7865a4a";
8+
public static final String EXPECTED_WEAVIATE_GIT_HASH = "b0d0063";
99

1010
private WeaviateVersion() {}
1111
}

src/test/java/io/weaviate/integration/client/batch/ClientBatchMultiTenancyTest.java

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.weaviate.client.v1.data.model.WeaviateObject;
1111
import io.weaviate.client.v1.filters.Operator;
1212
import io.weaviate.client.v1.filters.WhereFilter;
13+
import io.weaviate.client.v1.schema.model.Tenant;
1314
import io.weaviate.integration.client.AssertMultiTenancy;
1415
import io.weaviate.integration.client.WeaviateTestGenerics;
1516
import org.junit.After;
@@ -59,7 +60,10 @@ public void after() {
5960

6061
@Test
6162
public void shouldCreateObjects() {
62-
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
63+
Tenant[] tenants = new Tenant[]{
64+
WeaviateTestGenerics.TENANT_1,
65+
WeaviateTestGenerics.TENANT_2,
66+
};
6367
testGenerics.createSchemaPizzaForTenants(client);
6468
testGenerics.createSchemaSoupForTenants(client);
6569
testGenerics.createTenantsPizza(client, tenants);
@@ -100,28 +104,28 @@ public void shouldCreateObjects() {
100104
.id(WeaviateTestGenerics.PIZZA_QUATTRO_FORMAGGI_ID)
101105
.className("Pizza")
102106
.properties(propsQuatroFormaggi)
103-
.tenant(tenant)
107+
.tenant(tenant.getName())
104108
.build();
105109

106110
WeaviateObject pizzaFruttiDiMare = WeaviateObject.builder()
107111
.id(WeaviateTestGenerics.PIZZA_FRUTTI_DI_MARE_ID)
108112
.className("Pizza")
109113
.properties(propsFruttiDiMare)
110-
.tenant(tenant)
114+
.tenant(tenant.getName())
111115
.build();
112116

113117
WeaviateObject soupChicken = WeaviateObject.builder()
114118
.id(WeaviateTestGenerics.SOUP_CHICKENSOUP_ID)
115119
.className("Soup")
116120
.properties(propsChicken)
117-
.tenant(tenant)
121+
.tenant(tenant.getName())
118122
.build();
119123

120124
WeaviateObject soupBeautiful = WeaviateObject.builder()
121125
.id(WeaviateTestGenerics.SOUP_BEAUTIFUL_ID)
122126
.className("Soup")
123127
.properties(propsBeautiful)
124-
.tenant(tenant)
128+
.tenant(tenant.getName())
125129
.build();
126130

127131
return Stream.of(pizzaQuatroFormaggi, pizzaFruttiDiMare, soupChicken, soupBeautiful);
@@ -139,14 +143,14 @@ public void shouldCreateObjects() {
139143
Map<String, List<ObjectGetResponse>> grouped = Arrays.stream(result.getResult())
140144
.collect(Collectors.groupingBy(ObjectGetResponse::getTenant));
141145
Arrays.stream(tenants).forEach(tenant -> {
142-
assertThat(grouped.get(tenant)).isNotNull()
146+
assertThat(grouped.get(tenant.getName())).isNotNull()
143147
.hasSize(4)
144148
.extracting(ObjectGetResponse::getId)
145149
.containsExactlyInAnyOrderElementsOf(ids.keySet());
146150

147-
grouped.get(tenant).forEach(item ->
151+
grouped.get(tenant.getName()).forEach(item ->
148152
assertThat(item).isNotNull()
149-
.returns(tenant, ObjectGetResponse::getTenant)
153+
.returns(tenant.getName(), ObjectGetResponse::getTenant)
150154
.extracting(ObjectGetResponse::getResult)
151155
.returns(ObjectGetResponseStatus.SUCCESS, ObjectsGetResponseAO2Result::getStatus)
152156
);
@@ -155,14 +159,17 @@ public void shouldCreateObjects() {
155159
// verify created
156160
Arrays.stream(tenants).forEach(tenant ->
157161
ids.forEach((id, className) ->
158-
assertMT.objectExists(className, id, tenant)
162+
assertMT.objectExists(className, id, tenant.getName())
159163
)
160164
);
161165
}
162166

163167
@Test
164168
public void shouldNotCreateObjectsWithoutTenant() {
165-
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
169+
Tenant[] tenants = new Tenant[]{
170+
WeaviateTestGenerics.TENANT_1,
171+
WeaviateTestGenerics.TENANT_2,
172+
};
166173
testGenerics.createSchemaPizzaForTenants(client);
167174
testGenerics.createSchemaSoupForTenants(client);
168175
testGenerics.createTenantsPizza(client, tenants);
@@ -243,23 +250,27 @@ public void shouldNotCreateObjectsWithoutTenant() {
243250
// verify not created
244251
Arrays.stream(tenants).forEach(tenant ->
245252
ids.forEach((id, className) ->
246-
assertMT.objectDoesNotExist(className, id, tenant)
253+
assertMT.objectDoesNotExist(className, id, tenant.getName())
247254
)
248255
);
249256
}
250257

251258
@Test
252259
public void shouldDeleteObjects() {
253-
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
260+
Tenant[] tenants = new Tenant[]{
261+
WeaviateTestGenerics.TENANT_1,
262+
WeaviateTestGenerics.TENANT_2,
263+
};
264+
String[] tenantNames = Arrays.stream(tenants).map(Tenant::getName).toArray(String[]::new);
254265
testGenerics.createSchemaFoodForTenants(client);
255266
testGenerics.createTenantsFood(client, tenants);
256-
testGenerics.createDataFoodForTenants(client, tenants);
267+
testGenerics.createDataFoodForTenants(client, tenantNames);
257268

258269
Arrays.stream(tenants).forEach(tenant ->
259270
WeaviateTestGenerics.IDS_BY_CLASS.forEach((className, ids) -> {
260271
Result<BatchDeleteResponse> result = client.batch().objectsBatchDeleter()
261272
.withClassName(className)
262-
.withTenant(tenant)
273+
.withTenant(tenant.getName())
263274
.withWhere(WhereFilter.builder()
264275
.operator(Operator.Like)
265276
.path(new String[]{"_id"})
@@ -275,17 +286,21 @@ public void shouldDeleteObjects() {
275286
.returns((long) ids.size(), BatchDeleteResponse.Results::getSuccessful);
276287

277288
// verify deleted
278-
ids.forEach(id -> assertMT.objectDoesNotExist(className, id, tenant));
289+
ids.forEach(id -> assertMT.objectDoesNotExist(className, id, tenant.getName()));
279290
})
280291
);
281292
}
282293

283294
@Test
284295
public void shouldNotDeleteObjectsWithoutTenant() {
285-
String[] tenants = new String[]{"TenantNo1", "TenantNo2"};
296+
Tenant[] tenants = new Tenant[]{
297+
WeaviateTestGenerics.TENANT_1,
298+
WeaviateTestGenerics.TENANT_2,
299+
};
300+
String[] tenantNames = Arrays.stream(tenants).map(Tenant::getName).toArray(String[]::new);
286301
testGenerics.createSchemaFoodForTenants(client);
287302
testGenerics.createTenantsFood(client, tenants);
288-
testGenerics.createDataFoodForTenants(client, tenants);
303+
testGenerics.createDataFoodForTenants(client, tenantNames);
289304

290305
WeaviateTestGenerics.IDS_BY_CLASS.forEach((className, ids) -> {
291306
Result<BatchDeleteResponse> result = client.batch().objectsBatchDeleter()
@@ -302,7 +317,7 @@ public void shouldNotDeleteObjectsWithoutTenant() {
302317

303318
Arrays.stream(tenants).forEach(tenant ->
304319
WeaviateTestGenerics.IDS_BY_CLASS.forEach((className, ids) ->
305-
ids.forEach(id -> assertMT.objectExists(className, id, tenant))
320+
ids.forEach(id -> assertMT.objectExists(className, id, tenant.getName()))
306321
)
307322
);
308323
}

0 commit comments

Comments
 (0)