Skip to content

Commit

Permalink
test(config): add test docs for /config actuator
Browse files Browse the repository at this point in the history
Signed-off-by: Gaurav Mishra <mishra.gaurav@siemens.com>
  • Loading branch information
GMishx committed Dec 2, 2024
1 parent 95397c9 commit 50e6d13
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 3 deletions.
32 changes: 32 additions & 0 deletions rest/resource-server/src/docs/asciidoc/config.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Copyright Siemens AG, 2024. Part of the SW360 Portal Project.
//
// This program and the accompanying materials are made
// available under the terms of the Eclipse Public License 2.0
// which is available at https://www.eclipse.org/legal/epl-2.0/
//
// SPDX-License-Identifier: EPL-2.0
//
[[resources-config]]
=== Config

The config resource is used to give information from the `sw360.properties` file.
The configurations exposed are useful for the frontend UI. The backend only configs are not exposed.

[[resources-config-get]]
==== Getting config

A `GET` request will get the service's configurations.

===== Example request
include::{snippets}/should_document_get_config/curl-request.adoc[]

The response structure is the config object of the config actuator.

===== Response structure
include::{snippets}/should_document_get_config/response-fields.adoc[]

===== Example response
include::{snippets}/should_document_get_config/http-response.adoc[]

The response structure is not complete as it will grow overtime. But it is a key-value pair of strings.
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,24 @@ public OpenAPI customOpenAPI() {
.schema(new Schema<Health>())
))
))
))
.path("/config", new PathItem().get(
new Operation().tags(Collections.singletonList("Health"))
.summary("Configuration properties").operationId("config")
.responses(new ApiResponses().addApiResponse("200",
new ApiResponse().description("OK")
.content(new Content()
.addMediaType("application/json", new MediaType()
.example("""
{
"property.1": "value1",
"property.2": "false",
"property.3": "value3,value4"
}
""")
.schema(new Schema<Map<String, String>>())
))
))
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class ResourceServerConfiguration {
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers("/", "/*/*.html", "/*/*.css", "/*/*.js", "/*.js", "/*.json",
"/*/*.json", "/*/*.png", "/*/*.gif", "/*/*.ico", "/*/*.woff/*", "/*/*.ttf", "/*/*.html", "/*/*/*.html",
"/*/*.yaml", "/v3/api-docs/**", "/api/health", "/api/info");
"/*/*.yaml", "/v3/api-docs/**", "/api/health", "/api/info", "/api/config");
}

@Bean
Expand All @@ -84,6 +84,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
return http.addFilterBefore(filter, BasicAuthenticationFilter.class).authorizeHttpRequests(auth -> {
auth.requestMatchers(HttpMethod.GET, "/api/health").permitAll();
auth.requestMatchers(HttpMethod.GET, "/api/info").hasAuthority("WRITE");
auth.requestMatchers(HttpMethod.GET, "/api/config").permitAll();
auth.requestMatchers(HttpMethod.GET, "/api").permitAll();
auth.requestMatchers(HttpMethod.GET, "/api/reports/download").permitAll();
auth.requestMatchers(HttpMethod.GET, "/api/**").hasAuthority("READ");
Expand Down
3 changes: 2 additions & 1 deletion rest/resource-server/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ management:
web:
base-path: /
exposure:
include: health,info
include: health,info,config
path-mapping:
health: /api/health
info: /api/info
config: /api/config
endpoint:
health:
show-details: always
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright Siemens AG, 2024. Part of the SW360 Portal Project.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.sw360.rest.resourceserver.actuator;

import org.eclipse.sw360.rest.resourceserver.Sw360ResourceServer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Map;

import static org.assertj.core.api.BDDAssertions.then;

/* @DirtiesContext is necessary because the context needs to be reloaded inbetween the tests
otherwise the responses of previous tests are taken. NoOpCacheManager through @AutoConfigureCache
was not enough to avoid this bug.
*/
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Sw360ResourceServer.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SW360ConfigActuatorTest {

@LocalServerPort
private int port;

@SpyBean
private SW360ConfigActuator restConfigActuatorMock;

@Autowired
private TestRestTemplate testRestTemplate;

/**
* Makes a request to localhost with the default server port and returns
* the response as a response entity with type Map
* @param endpoint endpoint that will be called
* @return response of request
*/
private ResponseEntity<Map> getMapResponseEntityForHealthEndpointRequest(String endpoint) {
return this.testRestTemplate.getForEntity(
"http://localhost:" + this.port + Sw360ResourceServer.REST_BASE_PATH + endpoint, Map.class);
}

@Test
public void config_should_return_200() {
ResponseEntity<Map> entity = getMapResponseEntityForHealthEndpointRequest("/config");

then(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public SecurityFilterChain appSecurtiy(HttpSecurity httpSecurity) throws Excepti
authz -> authz
.requestMatchers(HttpMethod.GET, "/api/health").permitAll()
.requestMatchers(HttpMethod.GET, "/api/info").permitAll()
.requestMatchers(HttpMethod.GET, "/api/config").permitAll()
.anyRequest().authenticated()
).httpBasic(Customizer.withDefaults()).formLogin(Customizer.withDefaults())
.exceptionHandling(x -> x.authenticationEntryPoint(saep));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright Siemens AG, 2024. Part of the SW360 Portal Project.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.sw360.rest.resourceserver.restdocs;

import org.eclipse.sw360.rest.resourceserver.actuator.SW360ConfigActuator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static org.mockito.BDDMockito.given;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class ConfigSpecTest extends TestRestDocsSpecBase{

@MockBean
private SW360ConfigActuator restConfigActuatorMock;

@Test
public void should_document_get_config() throws Exception {
Map<String, String> properties = new ConcurrentHashMap<>();
properties.put("admin.private.project.access.enabled", "true");
properties.put("clearing.teams", "org1,org2,org3");
properties.put("rest.apitoken.read.validity.days", "90");
properties.put("rest.write.access.usergroup", "ADMIN");

given(this.restConfigActuatorMock.config()).willReturn(properties);

mockMvc.perform(get("/api/config")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(this.documentationHandler.document(
responseFields(
fieldWithPath("admin.private.project.access.enabled").description("Sample boolean property."),
fieldWithPath("clearing.teams").description("Sample set property (separated by comma)."),
fieldWithPath("rest.apitoken.read.validity.days").description("Sample integer property."),
fieldWithPath("rest.write.access.usergroup").description("Sample string property.")
)
));
}
}
3 changes: 2 additions & 1 deletion rest/resource-server/src/test/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ management:
web:
base-path: /
exposure:
include: health,info
include: health,info,config
path-mapping:
health: /api/health
info: /api/info
config: /api/config
endpoint:
health:
show-details: always
Expand Down

0 comments on commit 50e6d13

Please sign in to comment.