Skip to content

Commit

Permalink
Added endpoint for admins to check topics of all namespaces (#222)
Browse files Browse the repository at this point in the history
* Added endpoint for admins to check topics of all namespaces

* Fixed test
  • Loading branch information
Loïc GREFFIER authored Nov 9, 2022
1 parent 3baffa2 commit 5f33076
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.michelin.ns4kafka.controllers;
package com.michelin.ns4kafka.controllers.quota;

import com.michelin.ns4kafka.controllers.generic.NamespacedResourceController;
import com.michelin.ns4kafka.models.Namespace;
import com.michelin.ns4kafka.models.quota.ResourceQuota;
import com.michelin.ns4kafka.models.quota.ResourceQuotaResponse;
import com.michelin.ns4kafka.security.ResourceBasedSecurityRule;
import com.michelin.ns4kafka.services.ResourceQuotaService;
import com.michelin.ns4kafka.utils.enums.ApplyStatus;
import com.michelin.ns4kafka.utils.exceptions.ResourceValidationException;
Expand All @@ -15,7 +14,6 @@
import io.micronaut.scheduling.annotation.ExecuteOn;
import io.swagger.v3.oas.annotations.tags.Tag;

import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.validation.Valid;
import java.time.Instant;
Expand All @@ -30,16 +28,6 @@ public class ResourceQuotaController extends NamespacedResourceController {
@Inject
ResourceQuotaService resourceQuotaService;

/**
* Get all the quotas of all namespaces
* @return A list of quotas
*/
@Get("/all")
@RolesAllowed(ResourceBasedSecurityRule.IS_ADMIN)
public List<ResourceQuotaResponse> listAll(String namespace) {
return resourceQuotaService.getUsedResourcesByQuotaForAllNamespaces();
}

/**
* Get all the quotas by namespace
* @param namespace The namespace
Expand Down Expand Up @@ -75,8 +63,8 @@ public Optional<ResourceQuotaResponse> get(String namespace, String quota) {
* @param dryrun Does the creation is a dry run
* @return The created role binding
*/
@Post("/{?dryrun}")
HttpResponse<ResourceQuota> apply(String namespace, @Body @Valid ResourceQuota quota, @QueryValue(defaultValue = "false") boolean dryrun){
@Post("{?dryrun}")
public HttpResponse<ResourceQuota> apply(String namespace, @Body @Valid ResourceQuota quota, @QueryValue(defaultValue = "false") boolean dryrun){
Namespace ns = getNamespace(namespace);

quota.getMetadata().setCreationTimestamp(Date.from(Instant.now()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.michelin.ns4kafka.controllers.quota;

import com.michelin.ns4kafka.controllers.generic.NonNamespacedResourceController;
import com.michelin.ns4kafka.models.quota.ResourceQuotaResponse;
import com.michelin.ns4kafka.security.ResourceBasedSecurityRule;
import com.michelin.ns4kafka.services.ResourceQuotaService;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.swagger.v3.oas.annotations.tags.Tag;

import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import java.util.List;

@Tag(name = "Resource Quotas")
@Controller(value = "/api/resource-quotas")
@RolesAllowed(ResourceBasedSecurityRule.IS_ADMIN)
public class ResourceQuotaNonNamespacedController extends NonNamespacedResourceController {
@Inject
ResourceQuotaService resourceQuotaService;

/**
* Get all the quotas of all namespaces
* @return A list of quotas
*/
@Get
public List<ResourceQuotaResponse> listAll() {
return resourceQuotaService.getUsedResourcesByQuotaForAllNamespaces();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.michelin.ns4kafka.controllers;
package com.michelin.ns4kafka.controllers.topic;

import com.michelin.ns4kafka.controllers.generic.NamespacedResourceController;
import com.michelin.ns4kafka.models.DeleteRecordsResponse;
Expand Down Expand Up @@ -28,15 +28,9 @@
@Tag(name = "Topics")
@Controller(value = "/api/namespaces/{namespace}/topics")
public class TopicController extends NamespacedResourceController {
/**
* The topic service
*/
@Inject
TopicService topicService;

/**
* The resource quota service
*/
@Inject
ResourceQuotaService resourceQuotaService;

Expand Down Expand Up @@ -70,7 +64,7 @@ public Optional<Topic> getTopic(String namespace, String topic) {
* @param dryrun Is dry run mode or not ?
* @return An HTTP response
*/
@Post("{?dryrun}")
@Post
public HttpResponse<Topic> apply(String namespace, @Valid @Body Topic topic, @QueryValue(defaultValue = "false") boolean dryrun) throws InterruptedException, ExecutionException, TimeoutException {
Namespace ns = getNamespace(namespace);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.michelin.ns4kafka.controllers.topic;

import com.michelin.ns4kafka.controllers.generic.NonNamespacedResourceController;
import com.michelin.ns4kafka.models.Topic;
import com.michelin.ns4kafka.security.ResourceBasedSecurityRule;
import com.michelin.ns4kafka.services.TopicService;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.swagger.v3.oas.annotations.tags.Tag;

import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import java.util.List;

@Tag(name = "Topics")
@Controller(value = "/api/topics")
@RolesAllowed(ResourceBasedSecurityRule.IS_ADMIN)
public class TopicNonNamespacedController extends NonNamespacedResourceController {
@Inject
TopicService topicService;

/**
* Get all the topics of all namespaces
* @return A list of topics
*/
@Get
public List<Topic> listAll() {
return topicService.findAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
import java.util.List;

public interface TopicRepository {
/**
* Find all topics
* @return The list of topics
*/
List<Topic> findAll();

/**
* Find all topics by cluster
* @param cluster The cluster
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ void receive(ConsumerRecord<String, Topic> record) {
super.receive(record);
}

/**
* Find all topics
* @return The list of topics
*/
@Override
public List<Topic> findAll() {
return new ArrayList<>(getKafkaStore().values());
}

/**
* Find all topics by cluster
* @param cluster The cluster
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ public class TopicService {
@Inject
List<KafkaAsyncExecutorConfig> kafkaAsyncExecutorConfig;

/**
* Find all topics
* @return The list of topics
*/
public List<Topic> findAll() {
return topicRepository.findAll();
}

/**
* Find all topics by given namespace
* @param namespace The namespace
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.michelin.ns4kafka.controllers;

import com.michelin.ns4kafka.controllers.quota.ResourceQuotaController;
import com.michelin.ns4kafka.models.Namespace;
import com.michelin.ns4kafka.models.ObjectMeta;
import com.michelin.ns4kafka.models.quota.ResourceQuota;
Expand Down Expand Up @@ -44,26 +45,6 @@ class ResourceQuotaControllerTest {
@Mock
ApplicationEventPublisher applicationEventPublisher;

/**
* Validate quota listing
*/
@Test
void listAll() {
ResourceQuotaResponse response = ResourceQuotaResponse.builder()
.spec(ResourceQuotaResponse.ResourceQuotaResponseSpec.builder()
.countTopic("2/5")
.countPartition("2/10")
.countConnector("5/5")
.build())
.build();

when(resourceQuotaService.getUsedResourcesByQuotaForAllNamespaces()).thenReturn(List.of(response));

List<ResourceQuotaResponse> actual = resourceQuotaController.listAll("ns");
Assertions.assertEquals(1, actual.size());
Assertions.assertEquals(response, actual.get(0));
}

/**
* Validate quota listing
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.michelin.ns4kafka.controllers;

import com.michelin.ns4kafka.controllers.quota.ResourceQuotaNonNamespacedController;
import com.michelin.ns4kafka.models.quota.ResourceQuotaResponse;
import com.michelin.ns4kafka.services.ResourceQuotaService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.List;

import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class ResourceQuotaNonNamespacedControllerTest {
@InjectMocks
ResourceQuotaNonNamespacedController resourceQuotaController;

@Mock
ResourceQuotaService resourceQuotaService;

/**
* Validate quota listing
*/
@Test
void listAll() {
ResourceQuotaResponse response = ResourceQuotaResponse.builder()
.spec(ResourceQuotaResponse.ResourceQuotaResponseSpec.builder()
.countTopic("2/5")
.countPartition("2/10")
.countConnector("5/5")
.build())
.build();

when(resourceQuotaService.getUsedResourcesByQuotaForAllNamespaces()).thenReturn(List.of(response));

List<ResourceQuotaResponse> actual = resourceQuotaController.listAll();
Assertions.assertEquals(1, actual.size());
Assertions.assertEquals(response, actual.get(0));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.michelin.ns4kafka.controllers;

import com.michelin.ns4kafka.controllers.topic.TopicController;
import com.michelin.ns4kafka.models.DeleteRecordsResponse;
import com.michelin.ns4kafka.models.Namespace;
import com.michelin.ns4kafka.models.Namespace.NamespaceSpec;
Expand Down Expand Up @@ -38,39 +39,21 @@

@ExtendWith(MockitoExtension.class)
class TopicControllerTest {
/**
* The mocked namespace service
*/
@Mock
NamespaceService namespaceService;

/**
* The mocked topic service
*/
@Mock
TopicService topicService;

/**
* The mocked app event publisher
*/
@Mock
ApplicationEventPublisher applicationEventPublisher;

/**
* The mocked security service
*/
@Mock
SecurityService securityService;

/**
* The mocked resource quota service
*/
@Mock
ResourceQuotaService resourceQuotaService;

/**
* The mocked topic controller
*/
@InjectMocks
TopicController topicController;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.michelin.ns4kafka.controllers;

import com.michelin.ns4kafka.controllers.topic.TopicNonNamespacedController;
import com.michelin.ns4kafka.models.ObjectMeta;
import com.michelin.ns4kafka.models.Topic;
import com.michelin.ns4kafka.services.NamespaceService;
import com.michelin.ns4kafka.services.TopicService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.List;

import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class TopicNonNamespacedControllerTest {
@Mock
NamespaceService namespaceService;

@Mock
TopicService topicService;

@InjectMocks
TopicNonNamespacedController topicController;

/**
* Validate topics listing
*/
@Test
void listAll() {
when(topicService.findAll())
.thenReturn(List.of(
Topic.builder().metadata(ObjectMeta.builder().name("topic1").build()).build(),
Topic.builder().metadata(ObjectMeta.builder().name("topic2").build()).build()
));

List<Topic> actual = topicController.listAll();

Assertions.assertEquals(2, actual.size());
Assertions.assertEquals("topic1", actual.get(0).getMetadata().getName());
Assertions.assertEquals("topic2", actual.get(1).getMetadata().getName());
}
}
Loading

0 comments on commit 5f33076

Please sign in to comment.