Skip to content

Commit 1e8a4d9

Browse files
authored
Merge pull request #527 from FedeAlonso/feat/e2e_test_for_request_command_cli
feat: new e2e automated test RHOAS (Kafka instances)
2 parents 842d3c8 + f881eef commit 1e8a4d9

File tree

4 files changed

+86
-40
lines changed

4 files changed

+86
-40
lines changed

src/main/java/io/managed/services/test/Environment.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ public class Environment {
108108
* Setup constants from env variables or set default
109109
*/
110110
public static final String CLOUD_PROVIDER = getOrDefault(CLOUD_PROVIDER_ENV, "aws");
111-
112111
public static final String SUITE_ROOT = System.getProperty("user.dir");
113112
public static final Path LOG_DIR = getOrDefault(LOG_DIR_ENV, Paths::get, Paths.get(SUITE_ROOT, "target", "logs")).resolve("test-run-" + DATE_FORMAT.format(LocalDateTime.now()));
114113

src/main/java/io/managed/services/test/cli/CLI.java

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import lombok.extern.log4j.Log4j2;
2525
import org.openapitools.jackson.nullable.JsonNullableModule;
2626
import org.testng.Assert;
27+
2728
import java.io.File;
2829
import java.io.IOException;
2930
import java.nio.file.Path;
@@ -34,6 +35,7 @@
3435
import java.util.Locale;
3536
import java.util.concurrent.ExecutionException;
3637
import java.util.stream.Collectors;
38+
3739
import static java.time.Duration.ofMinutes;
3840
import static lombok.Lombok.sneakyThrow;
3941

@@ -44,7 +46,7 @@ public class CLI {
4446
private static final Duration DEFAULT_TIMEOUT = ofMinutes(3);
4547

4648
private static final String CLUSTER_CAPACITY_EXHAUSTED_CODE = "KAFKAS-MGMT-24";
47-
49+
4850
private static final Locale LOCALE_EN = Locale.ENGLISH;
4951

5052
private final String workdir;
@@ -161,6 +163,15 @@ public KafkaRequestList listKafka() throws CliGenericException {
161163
.getObjectValue(KafkaRequestList::createFromDiscriminatorValue);
162164
}
163165

166+
public void UpdateKafkaOwner(String userName, String instanceName) throws CliGenericException {
167+
retry(() -> exec("kafka", "update", "--owner", userName, "--name", instanceName, "-y"));
168+
}
169+
170+
public void UpdateKafkaReauthentication(String newStatus, String instanceName) throws CliGenericException {
171+
retry(() -> exec("kafka", "update", "--reauthentication", newStatus.toLowerCase(LOCALE_EN), "--name",
172+
instanceName, "-y"));
173+
}
174+
164175
public KafkaRequestList searchKafkaByName(String name) throws CliGenericException {
165176
return retry(() -> exec("kafka", "list", "--search", name, "-o", "json"))
166177
.parseNodeFromProcessOutput()
@@ -175,8 +186,8 @@ public ServiceAccountData describeServiceAccount(String id) throws CliGenericExc
175186

176187
public List<ServiceAccountData> listServiceAccount() throws CliGenericException {
177188
return retry(() -> exec("service-account", "list", "-o", "json"))
178-
.parseNodeFromProcessOutput()
179-
.getCollectionOfObjectValues(ServiceAccountData::createFromDiscriminatorValue);
189+
.parseNodeFromProcessOutput()
190+
.getCollectionOfObjectValues(ServiceAccountData::createFromDiscriminatorValue);
180191
}
181192

182193
public void deleteServiceAccount(String id) throws CliGenericException {
@@ -252,6 +263,7 @@ private ACLEntityType(String name, String flag) {
252263
this.flag = flag;
253264
}
254265
}
266+
255267
//// kafka acl create
256268
public void createAcl(ACLEntityType aclEntityType, String entityIdentificator, AclOperation operation, AclPermissionType permission, String topic) throws CliGenericException {
257269
retry(() -> exec("kafka", "acl", "create", "-y", aclEntityType.flag, entityIdentificator, "--topic", topic, "--permission", permission.toString().toLowerCase(LOCALE_EN), "--operation", operation.toString().toLowerCase(LOCALE_EN)));
@@ -298,7 +310,7 @@ public Registry createServiceRegistry(String name) throws CliGenericException {
298310
.getObjectValue(Registry::createFromDiscriminatorValue);
299311
}
300312

301-
public Registry describeServiceRegistry(String id) throws CliGenericException {
313+
public Registry describeServiceRegistry(String id) throws CliGenericException {
302314
return retry(() -> exec("service-registry", "describe", "--id", id))
303315
.parseNodeFromProcessOutput()
304316
.getObjectValue(Registry::createFromDiscriminatorValue);
@@ -326,43 +338,43 @@ public void deleteServiceRegistry(String name) throws CliGenericException {
326338

327339
public List<Record> consumeRecords(String topicName, String instanceId, int partition, int offset) throws CliGenericException, JsonProcessingException {
328340
List<String> cmd = List.of("kafka", "topic", "consume",
329-
"--instance-id", instanceId,
330-
"--name", topicName,
331-
"--offset", Integer.toString(offset),
332-
"--partition", Integer.toString(partition),
333-
"--format", "json"
341+
"--instance-id", instanceId,
342+
"--name", topicName,
343+
"--offset", Integer.toString(offset),
344+
"--partition", Integer.toString(partition),
345+
"--format", "json"
334346
);
335347

336348
return consumeRecords(cmd);
337349
}
338350

339351
public List<Record> consumeRecords(String topicName, String instanceId, int partition) throws CliGenericException, JsonProcessingException {
340352
List<String> cmd = List.of("kafka", "topic", "consume",
341-
"--instance-id", instanceId,
342-
"--name", topicName,
343-
"--partition", Integer.toString(partition),
344-
"--format", "json"
353+
"--instance-id", instanceId,
354+
"--name", topicName,
355+
"--partition", Integer.toString(partition),
356+
"--format", "json"
345357
);
346358

347359
return consumeRecords(cmd);
348360
}
349361

350362
public Record produceRecords(String topicName, String instanceId, String message, int partition, String recordKey)
351-
throws InterruptedException, ExecutionException, IOException {
363+
throws InterruptedException, ExecutionException, IOException {
352364
List<String> cmd = List.of("kafka", "topic", "produce",
353-
"--instance-id", instanceId,
354-
"--name", topicName,
355-
"--partition", Integer.toString(partition),
356-
"--key", recordKey
365+
"--instance-id", instanceId,
366+
"--name", topicName,
367+
"--partition", Integer.toString(partition),
368+
"--key", recordKey
357369
);
358370
return produceRecords(message, cmd);
359371
}
360372

361373
public Record produceRecords(String topicName, String instanceId, String message)
362-
throws IOException, ExecutionException, InterruptedException {
374+
throws IOException, ExecutionException, InterruptedException {
363375
List<String> cmd = List.of("kafka", "topic", "produce",
364-
"--instance-id", instanceId,
365-
"--name", topicName
376+
"--instance-id", instanceId,
377+
"--name", topicName
366378
);
367379
return produceRecords(message, cmd);
368380
}
@@ -395,20 +407,20 @@ private List<Record> consumeRecords(List<String> cmd) throws CliGenericException
395407
if (output.isEmpty()) {
396408
return new ArrayList<Record>();
397409
}
398-
410+
399411
// specific separated JSON objects \n}\n which is separator of multiple inline jsons
400412
String[] lines = output.split("\n\\}\n");
401413
// append back '}' (i.e. curly bracket) so JSON objects will not miss this end symbol
402-
List<String> messagesWithFixedFormat = Arrays.stream(lines).map(in -> in + "}").collect(Collectors.toList());
414+
List<String> messagesWithFixedFormat = Arrays.stream(lines).map(in -> in + "}").collect(Collectors.toList());
403415

404-
var objectMapper = new ObjectMapper()
405-
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
406-
.registerModule(new JavaTimeModule())
407-
.registerModule(new JsonNullableModule());
416+
var objectMapper = new ObjectMapper()
417+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
418+
.registerModule(new JavaTimeModule())
419+
.registerModule(new JsonNullableModule());
408420
List<Record> records = new ArrayList<>();
409421

410422
// each object is read as separated Record
411-
for (String line: messagesWithFixedFormat) {
423+
for (String line : messagesWithFixedFormat) {
412424
Record record = objectMapper.readValue(line, Record.class);
413425
records.add(record);
414426
}
@@ -421,7 +433,7 @@ private <T, E extends Throwable> T retry(ThrowingSupplier<T, E> call) throws E {
421433

422434
private <T, E extends Throwable> T retryKafkaCreation(ThrowingSupplier<T, E> call) throws E {
423435
return RetryUtils.retry(
424-
1, null, call, CLI::retryConditionKafkaCreation, 12, Duration.ofSeconds(10));
436+
1, null, call, CLI::retryConditionKafkaCreation, 12, Duration.ofSeconds(10));
425437
}
426438

427439
private static boolean retryConditionKafkaCreation(Throwable t) {

src/test/java/io/managed/services/test/kafka/KafkaAccessMgmtTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ public void testUserCannotAccessSystemTopics() {
308308
LOGGER.info("Test user cannot access '__consumer_offsets' and '__transaction_state'");
309309
var instanceApiTopics = primaryKafkaInstanceAPI.getTopics();
310310
var o = instanceApiTopics.getItems().stream()
311-
.filter(k -> "__consumer_offsets".equals(k.getName()) || "__transaction_state".equals(k.getName()))
312-
.findAny();
311+
.filter(k -> "__consumer_offsets".equals(k.getName()) || "__transaction_state".equals(k.getName()))
312+
.findAny();
313313
assertTrue(o.isEmpty());
314314
}
315315

@@ -682,7 +682,7 @@ public void testDefaultSecondaryUserCanNotDeleteACLs() {
682682
// TODO investigate if acl should be able to be creatd even even its provide null values
683683
LOGGER.info("Test that the secondary user by default can not delete ACLs");
684684
assertThrows(ApiForbiddenException.class, () ->
685-
secondaryKafkaInstanceAPI.deleteAcls(AclResourceType.TOPIC, "abc", AclPatternType.LITERAL, "cde", AclOperation.ALL, AclPermissionType.ALLOW));
685+
secondaryKafkaInstanceAPI.deleteAcls(AclResourceType.TOPIC, "abc", AclPatternType.LITERAL, "cde", AclOperation.ALL, AclPermissionType.ALLOW));
686686
}
687687

688688
@Test(priority = 6, groups = TestGroups.INTEGRATION)
@@ -757,7 +757,7 @@ public void testDefaultAdminUserCanNotDeleteACLs() {
757757

758758
LOGGER.info("Test that the admin user can not delete ACLs");
759759
assertThrows(ApiForbiddenException.class, () -> adminKafkaInstanceAPI.deleteAcls(
760-
AclResourceType.TOPIC, "xx", AclPatternType.LITERAL, "123", AclOperation.READ, AclPermissionType.ALLOW));
760+
AclResourceType.TOPIC, "xx", AclPatternType.LITERAL, "123", AclOperation.READ, AclPermissionType.ALLOW));
761761
}
762762

763763
@SneakyThrows
@@ -879,7 +879,7 @@ public void testPrimaryUserCanNotDeleteTheKafkaInstance() {
879879

880880
@Test(priority = 11, dependsOnMethods = "testAdminUserCanChangeTheKafkaInstanceOwner", groups = TestGroups.INTEGRATION)
881881
public void testAlienUserCanNotDeleteTheKafkaInstance() {
882-
LOGGER.info("Test that the aline user can not delete the Kafka instance");
882+
LOGGER.info("Test that the alien user can not delete the Kafka instance");
883883
assertThrows(ApiNotFoundException.class, () -> alienAPI.kafkaMgmt().deleteKafkaById(kafka.getId(), true));
884884
}
885885

src/test/java/io/managed/services/test/rhoas/KafkaRhoasBasicTests.java

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@
2222
import org.apache.logging.log4j.Logger;
2323
import org.testng.SkipException;
2424
import org.testng.annotations.AfterClass;
25+
import org.testng.annotations.AfterMethod;
2526
import org.testng.annotations.BeforeClass;
2627
import org.testng.annotations.Test;
2728

2829
import java.io.File;
2930
import java.util.List;
3031
import java.util.Objects;
32+
import java.lang.reflect.Method;
3133

3234
import static io.managed.services.test.TestUtils.bwait;
3335
import static io.managed.services.test.client.kafka.KafkaMessagingUtils.testTopic;
3436
import static org.testng.Assert.assertEquals;
3537
import static org.testng.Assert.assertNotNull;
3638
import static org.testng.Assert.assertThrows;
3739
import static org.testng.Assert.assertTrue;
40+
import static org.testng.Assert.assertFalse;
3841

3942

4043
/**
@@ -86,15 +89,28 @@ public void bootstrap() {
8689
assertNotNull(Environment.PRIMARY_USERNAME, "the PRIMARY_USERNAME env is null");
8790
assertNotNull(Environment.PRIMARY_PASSWORD, "the PRIMARY_PASSWORD env is null");
8891
assertNotNull(Environment.PRIMARY_OFFLINE_TOKEN, "the PRIMARY_OFFLINE_TOKEN env is null");
92+
assertNotNull(Environment.SECONDARY_USERNAME, "the SECONDARY_USERNAME env is null");
93+
}
94+
95+
@AfterMethod(alwaysRun = true)
96+
@SneakyThrows
97+
public void cleanMethod(Method method) {
98+
// Restore the owner to PRIMARY, after testing that changing owners works.
99+
if (method.getName().equals("testUpdateKafkaOwner")) {
100+
var adminOfflineToken = Environment.ADMIN_OFFLINE_TOKEN;
101+
var kafkaMgmtApi = KafkaMgmtApiUtils.kafkaMgmtApi(Environment.OPENSHIFT_API_URI, adminOfflineToken);
102+
KafkaMgmtApiUtils.changeKafkaInstanceOwner(kafkaMgmtApi, kafka, Environment.PRIMARY_USERNAME);
103+
}
89104
}
90105

91106
@AfterClass(alwaysRun = true)
92107
@SneakyThrows
93108
public void clean() {
94109

95110
var offlineToken = Environment.PRIMARY_OFFLINE_TOKEN;
111+
var adminOfflineToken = Environment.ADMIN_OFFLINE_TOKEN;
96112

97-
var kafkaMgmtApi = KafkaMgmtApiUtils.kafkaMgmtApi(Environment.OPENSHIFT_API_URI, offlineToken);
113+
var kafkaMgmtApi = KafkaMgmtApiUtils.kafkaMgmtApi(Environment.OPENSHIFT_API_URI, adminOfflineToken);
98114
var securityMgmtApi = SecurityMgmtAPIUtils.securityMgmtApi(Environment.OPENSHIFT_API_URI, offlineToken);
99115
var kafkaInstanceApi = KafkaInstanceApiUtils.kafkaInstanceApi(Environment.OPENSHIFT_API_URI, offlineToken);
100116

@@ -121,7 +137,7 @@ public void clean() {
121137

122138
return;
123139
}
124-
140+
125141
try {
126142
KafkaMgmtApiUtils.deleteKafkaByNameIfExists(kafkaMgmtApi, KAFKA_INSTANCE_NAME);
127143
} catch (Throwable t) {
@@ -170,7 +186,7 @@ public void testDownloadCLI() {
170186
@Test(dependsOnMethods = "testDownloadCLI")
171187
@SneakyThrows
172188
public void testLogin() {
173-
189+
174190
LOGGER.info("login the CLI");
175191
CLIUtils.login(vertx, cli, Environment.PRIMARY_USERNAME, Environment.PRIMARY_PASSWORD).get();
176192

@@ -181,7 +197,7 @@ public void testLogin() {
181197
@Test(dependsOnMethods = "testLogin")
182198
@SneakyThrows
183199
public void testCreateServiceAccount() {
184-
200+
185201
LOGGER.info("create a service account");
186202
serviceAccountSecret = CLIUtils.createServiceAccount(cli, SERVICE_ACCOUNT_NAME);
187203

@@ -206,7 +222,7 @@ public void testDescribeServiceAccount() {
206222

207223
assertEquals(sa.getName(), SERVICE_ACCOUNT_NAME);
208224
}
209-
225+
210226
@Test(dependsOnMethods = "testLogin")
211227
@SneakyThrows
212228
public void testApplyKafkaInstance() {
@@ -517,6 +533,24 @@ public void testDeleteServiceAccount() {
517533
() -> cli.describeServiceAccount(serviceAccount.getClientId()));
518534
}
519535

536+
@Test(dependsOnMethods = "testApplyKafkaInstance", enabled = true)
537+
@SneakyThrows
538+
public void testUpdateKafkaOwner() {
539+
cli.UpdateKafkaOwner(Environment.SECONDARY_USERNAME, KAFKA_INSTANCE_NAME);
540+
var k = cli.describeKafkaByName(KAFKA_INSTANCE_NAME);
541+
LOGGER.debug(k);
542+
assertEquals(Environment.SECONDARY_USERNAME, k.getOwner());
543+
}
544+
545+
@Test(dependsOnMethods = "testApplyKafkaInstance", enabled = true)
546+
@SneakyThrows
547+
public void testUpdateKafkaReauthentication() {
548+
cli.UpdateKafkaReauthentication("false", KAFKA_INSTANCE_NAME);
549+
var k = cli.describeKafkaByName(KAFKA_INSTANCE_NAME);
550+
LOGGER.debug(k);
551+
assertFalse(k.getReauthenticationEnabled());
552+
}
553+
520554
@Test(dependsOnMethods = "testApplyKafkaInstance", priority = 3, enabled = true)
521555
@SneakyThrows
522556
public void testDeleteKafkaInstance() {
@@ -546,3 +580,4 @@ public void testLogout() {
546580
assertThrows(CliGenericException.class, () -> cli.listKafka()); // unable to run the same command after logout
547581
}
548582
}
583+

0 commit comments

Comments
 (0)