Skip to content

Commit 7670c3f

Browse files
committed
Endpoints configuration improvements.
Added support spring boot actuator endpoints. Added support groups to endpoints. Fixed #2076
1 parent 30281b6 commit 7670c3f

25 files changed

Lines changed: 698 additions & 72 deletions

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ developers=Puneet Behl,Álvaro Sánchez-Mariscal,Iván López
1010
org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8
1111
org.gradle.configuration-cache=false
1212
org.gradle.configuration-cache.parallel=false
13-
org.gradle.caching=true
13+
org.gradle.caching=false
1414
org.gradle.parallel=true
1515
kotlin.stdlib.default.dependency=false
1616

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-start
102102
spring-boot-starter-validation = { module = "org.springframework.boot:spring-boot-starter-validation" }
103103
spring-boot-starter-data-rest = { module = "org.springframework.boot:spring-boot-starter-data-rest" }
104104
spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test" }
105+
spring-boot-starter-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator" }
105106
openapi-generator = { module = "org.openapitools:openapi-generator", version.ref = "openapi-generator" }
106107
swagger-parser = { module = "io.swagger:swagger-parser", version.ref = "swagger-parser" }
107108
swagger-parser-v3 = { module = "io.swagger.parser.v3:swagger-parser-v3", version.ref = "swagger-parser-v3" }

openapi-annotations/src/main/java/io/micronaut/openapi/annotation/OpenAPIManagement.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,17 @@
5050
*/
5151
SecurityRequirement[] security() default {};
5252

53+
/**
54+
* @return Array of groups to which this controller should be included.
55+
*
56+
* @since 4.16.0
57+
*/
58+
String[] groups() default {};
59+
60+
/**
61+
* @return Array of groups to which this controller should not be included.
62+
*
63+
* @since 4.16.0
64+
*/
65+
String[] groupsExcluded() default {};
5366
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
endpoints.enabled=true
2+
endpoints.groups=v1, management
3+
endpoints.tags=Management
4+
endpoints.refresh.enabled=false

openapi/src/main/java/io/micronaut/openapi/annotation/mappers/OpenAPIManagementAnnotationMapper.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
import java.util.List;
2626

2727
import static io.micronaut.openapi.visitor.ElementUtils.EMPTY_ANNOTATION_VALUES_ARRAY;
28+
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_GROUPS;
29+
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_GROUPS_EXCLUDED;
2830
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_SECURITY;
2931
import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_TAGS;
32+
import static io.micronaut.openapi.visitor.management.EndpointUtils.ALL_MANAGEMENT_ENDPOINT_CLASSES_ARRAY;
3033

3134
/**
3235
* Mapper for management endpoints.
@@ -40,21 +43,14 @@ public Class<OpenAPIManagement> annotationType() {
4043

4144
@Override
4245
public List<AnnotationValue<?>> map(AnnotationValue<OpenAPIManagement> annotation, VisitorContext context) {
46+
4347
return Collections.singletonList(
4448
AnnotationValue.builder(OpenAPIInclude.class)
45-
.values(
46-
"io.micronaut.management.endpoint.beans.BeansEndpoint",
47-
"io.micronaut.management.endpoint.env.EnvironmentEndpoint",
48-
"io.micronaut.management.endpoint.health.HealthEndpoint",
49-
"io.micronaut.management.endpoint.info.InfoEndpoint",
50-
"io.micronaut.management.endpoint.loggers.LoggersEndpoint",
51-
"io.micronaut.management.endpoint.refresh.RefreshEndpoint",
52-
"io.micronaut.management.endpoint.routes.RoutesEndpoint",
53-
"io.micronaut.management.endpoint.stop.ServerStopEndpoint",
54-
"io.micronaut.management.endpoint.threads.ThreadDumpEndpoint"
55-
)
49+
.values(ALL_MANAGEMENT_ENDPOINT_CLASSES_ARRAY)
5650
.member(PROP_TAGS, annotation.getAnnotations(PROP_TAGS).toArray(EMPTY_ANNOTATION_VALUES_ARRAY))
5751
.member(PROP_SECURITY, annotation.getAnnotations(PROP_SECURITY).toArray(EMPTY_ANNOTATION_VALUES_ARRAY))
52+
.member(PROP_GROUPS, annotation.stringValues(PROP_GROUPS))
53+
.member(PROP_GROUPS_EXCLUDED, annotation.stringValues(PROP_GROUPS_EXCLUDED))
5854
.build()
5955
);
6056
}

openapi/src/main/java/io/micronaut/openapi/visitor/ConfigUtils.java

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import java.util.List;
5858
import java.util.Locale;
5959
import java.util.Map;
60+
import java.util.Map.Entry;
6061
import java.util.Optional;
6162
import java.util.Properties;
6263

@@ -85,6 +86,8 @@
8586
import static io.micronaut.openapi.visitor.FileUtils.resolve;
8687
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.ALL;
8788
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.ENDPOINTS_EXTENSIONS;
89+
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.ENDPOINTS_GROUPS;
90+
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.ENDPOINTS_GROUPS_EXCLUDED;
8891
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.ENDPOINTS_PATH;
8992
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.ENDPOINTS_SECURITY_REQUIREMENTS;
9093
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.ENDPOINTS_SERVERS;
@@ -147,6 +150,8 @@
147150
import static io.micronaut.openapi.visitor.UrlUtils.parsePath;
148151
import static io.micronaut.openapi.visitor.group.RouterVersioningProperties.DEFAULT_HEADER_NAME;
149152
import static io.micronaut.openapi.visitor.group.RouterVersioningProperties.DEFAULT_PARAMETER_NAME;
153+
import static io.micronaut.openapi.visitor.management.EndpointUtils.ALL_MICRONAUT_MANAGEMENT_ENDPOINTS;
154+
import static io.micronaut.openapi.visitor.management.SpringActuatorConfigUtils.mergeWithActuatorProperties;
150155

151156
/**
152157
* Configuration utilities methods.
@@ -157,12 +162,11 @@
157162
public final class ConfigUtils {
158163

159164
public static final String ALL_ENDPOINTS_NAME = "all";
165+
public static final String ALL_SPRING_ACTUATOR_ENDPOINTS_NAME = "*";
160166

161167
private static final String LOADED_POSTFIX = ".loaded";
162168
private static final String VALUE_POSTFIX = ".value";
163169

164-
public static final String ALL_ENDPOINTS_NAME = "all";
165-
166170
private static final List<String> DEFAULT_PREFIXES = List.of("");
167171
private static final List<String> DEFAULT_POSTFIXES = List.of("controller", "api", "endpoints", "endpoint");
168172

@@ -200,22 +204,22 @@ public static SchemaDecorator getSchemaDecoration(String packageName, VisitorCon
200204
// third read environments properties
201205
Environment environment = getEnv(context);
202206
if (environment != null) {
203-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_PREFIX, StringConvention.RAW).entrySet()) {
207+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_PREFIX, StringConvention.RAW).entrySet()) {
204208
SchemaDecorator decorator = schemaDecorators.computeIfAbsent(entry.getKey(), k -> new SchemaDecorator());
205209
decorator.setPrefix((String) entry.getValue());
206210
}
207211

208-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_POSTFIX, StringConvention.RAW).entrySet()) {
212+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_POSTFIX, StringConvention.RAW).entrySet()) {
209213
SchemaDecorator decorator = schemaDecorators.computeIfAbsent(entry.getKey(), k -> new SchemaDecorator());
210214
decorator.setPostfix((String) entry.getValue());
211215
}
212216

213-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_PREFIX, StringConvention.RAW).entrySet()) {
217+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_PREFIX, StringConvention.RAW).entrySet()) {
214218
SchemaDecorator decorator = schemaDecorators.computeIfAbsent(entry.getKey(), k -> new SchemaDecorator());
215219
decorator.setPrefix((String) entry.getValue());
216220
}
217221

218-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_POSTFIX, StringConvention.RAW).entrySet()) {
222+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_POSTFIX, StringConvention.RAW).entrySet()) {
219223
SchemaDecorator decorator = schemaDecorators.computeIfAbsent(entry.getKey(), k -> new SchemaDecorator());
220224
decorator.setPostfix((String) entry.getValue());
221225
}
@@ -254,7 +258,7 @@ public static ClassElement getCustomSchema(String className, Map<String, ClassEl
254258
// third read environments properties
255259
Environment environment = getEnv(context);
256260
if (environment != null) {
257-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA, StringConvention.RAW).entrySet()) {
261+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA, StringConvention.RAW).entrySet()) {
258262

259263
String configuredClassName = entry.getKey();
260264
// Remove this check, after we remove MICRONAUT_OPENAPI_SCHEMA property
@@ -266,7 +270,7 @@ public static ClassElement getCustomSchema(String className, Map<String, ClassEl
266270
String targetClassName = (String) entry.getValue();
267271
readCustomSchema(configuredClassName, targetClassName, customSchemas, context);
268272
}
269-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_MAPPING, StringConvention.RAW).entrySet()) {
273+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_MAPPING, StringConvention.RAW).entrySet()) {
270274
String configuredClassName = entry.getKey();
271275

272276
// Remove this check, after we remove MICRONAUT_OPENAPI_SCHEMA property
@@ -512,14 +516,14 @@ public static List<Pair<String, String>> getExpandableProperties(VisitorContext
512516

513517
var expandedPropsMap = new HashMap<String, String>();
514518
if (CollectionUtils.isNotEmpty(propertiesFromEnv)) {
515-
for (Map.Entry<String, Object> entry : propertiesFromEnv.entrySet()) {
519+
for (Entry<String, Object> entry : propertiesFromEnv.entrySet()) {
516520
expandedPropsMap.put(entry.getKey(), entry.getValue().toString());
517521
}
518522
}
519523

520524
// next, read openapi.properties file
521525
Properties openapiProps = readOpenApiConfigFile(context);
522-
for (Map.Entry<Object, Object> entry : openapiProps.entrySet()) {
526+
for (Entry<Object, Object> entry : openapiProps.entrySet()) {
523527
String key = entry.getKey().toString();
524528
if (!key.startsWith(expandPrefix)) {
525529
continue;
@@ -529,7 +533,7 @@ public static List<Pair<String, String>> getExpandableProperties(VisitorContext
529533

530534
// next, read system properties
531535
if (CollectionUtils.isNotEmpty(System.getProperties())) {
532-
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
536+
for (Entry<Object, Object> entry : System.getProperties().entrySet()) {
533537
String key = entry.getKey().toString();
534538
if (!key.startsWith(expandPrefix)) {
535539
continue;
@@ -538,7 +542,7 @@ public static List<Pair<String, String>> getExpandableProperties(VisitorContext
538542
}
539543
}
540544

541-
for (Map.Entry<String, String> entry : expandedPropsMap.entrySet()) {
545+
for (Entry<String, String> entry : expandedPropsMap.entrySet()) {
542546
String key = entry.getKey();
543547
if (key.startsWith(expandPrefix)) {
544548
key = key.substring(expandPrefix.length());
@@ -585,7 +589,7 @@ public static Map<String, String> getAdocProperties(OpenApiInfo openApiInfo, boo
585589

586590
// next, read openapi.properties file
587591
Properties openapiProps = readOpenApiConfigFile(context);
588-
for (Map.Entry<Object, Object> entry : openapiProps.entrySet()) {
592+
for (Entry<Object, Object> entry : openapiProps.entrySet()) {
589593
String key = entry.getKey().toString();
590594
if (!key.startsWith(expandPrefix)) {
591595
continue;
@@ -595,7 +599,7 @@ public static Map<String, String> getAdocProperties(OpenApiInfo openApiInfo, boo
595599

596600
// next, read system properties
597601
if (CollectionUtils.isNotEmpty(System.getProperties())) {
598-
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
602+
for (Entry<Object, Object> entry : System.getProperties().entrySet()) {
599603
String key = entry.getKey().toString();
600604
if (!key.startsWith(expandPrefix)) {
601605
continue;
@@ -723,7 +727,7 @@ public static Map<String, GroupProperties> getGroupsPropertiesMap(VisitorContext
723727
// third read environments properties
724728
Environment environment = getEnv(context);
725729
if (environment != null) {
726-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_GROUPS, StringConvention.RAW).entrySet()) {
730+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_GROUPS, StringConvention.RAW).entrySet()) {
727731
String entryKey = entry.getKey();
728732
String[] propParts = entryKey.split("\\.");
729733
String propName = propParts[propParts.length - 1];
@@ -823,21 +827,25 @@ private static void setGroupProperty(String groupName, String propertyName, Obje
823827
* @return The EndpointsConfiguration.
824828
*/
825829
public static EndpointsConfig getEndpointsConfig(VisitorContext context) {
826-
var cfg = ContextUtils.get(MICRONAUT_INTERNAL_OPENAPI_ENDPOINTS, EndpointsConfig.class, context);
827-
if (cfg != null) {
828-
return cfg;
830+
var endpointsConfig = ContextUtils.get(MICRONAUT_INTERNAL_OPENAPI_ENDPOINTS, EndpointsConfig.class, context);
831+
if (endpointsConfig != null) {
832+
return endpointsConfig;
829833
}
830834

831-
cfg = new EndpointsConfig(isEndpointsEnabled(context));
832-
cfg.setPath(parsePath(getConfigProperty(ENDPOINTS_PATH, context)));
833-
cfg.setTags(parseTags(getConfigProperty(ENDPOINTS_TAGS, context)));
834-
cfg.setServers(parseServers(getConfigProperty(ENDPOINTS_SERVERS, context), context));
835-
cfg.setSecurityRequirements(parseSecurityRequirements(getConfigProperty(ENDPOINTS_SECURITY_REQUIREMENTS, context), context));
836-
cfg.setExtensions(parseExtensions(getConfigProperty(ENDPOINTS_EXTENSIONS, context), context));
837-
cfg.setEndpoints(endpointsProperties(context));
835+
endpointsConfig = new EndpointsConfig(isEndpointsEnabled(context));
836+
endpointsConfig.setPath(parsePath(getConfigProperty(ENDPOINTS_PATH, context)));
837+
endpointsConfig.setTags(parseTags(getConfigProperty(ENDPOINTS_TAGS, context)));
838+
endpointsConfig.setServers(parseServers(getConfigProperty(ENDPOINTS_SERVERS, context), context));
839+
endpointsConfig.setSecurityRequirements(parseSecurityRequirements(getConfigProperty(ENDPOINTS_SECURITY_REQUIREMENTS, context), context));
840+
endpointsConfig.setExtensions(parseExtensions(getConfigProperty(ENDPOINTS_EXTENSIONS, context), context));
841+
endpointsConfig.setGroups(getListStringsProperty(ENDPOINTS_GROUPS, Collections.emptyList(), context));
842+
endpointsConfig.setGroupsExcluded(getListStringsProperty(ENDPOINTS_GROUPS_EXCLUDED, Collections.emptyList(), context));
843+
endpointsConfig.setEndpoints(endpointsProperties(context));
844+
845+
mergeWithActuatorProperties(endpointsConfig, context);
838846

839-
ContextUtils.put(MICRONAUT_INTERNAL_OPENAPI_ENDPOINTS, cfg, context);
840-
return cfg;
847+
ContextUtils.put(MICRONAUT_INTERNAL_OPENAPI_ENDPOINTS, endpointsConfig, context);
848+
return endpointsConfig;
841849
}
842850

843851
public static Map<String, EndpointProperties> endpointsProperties(VisitorContext context) {
@@ -855,14 +863,33 @@ public static Map<String, EndpointProperties> endpointsProperties(VisitorContext
855863
// third read environments properties
856864
Environment environment = getEnv(context);
857865
if (environment != null) {
858-
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_ENDPOINTS_PREFIX, StringConvention.RAW).entrySet()) {
866+
for (Entry<String, Object> entry : environment.getProperties(MICRONAUT_ENDPOINTS_PREFIX, StringConvention.RAW).entrySet()) {
859867
String entryKey = entry.getKey();
860868
String endpointName = entryKey.substring(0, entryKey.indexOf('.'));
861869
String propName = entryKey.substring(endpointName.length() + 1);
862870
setEndpointProperty(endpointName, propName, entry.getValue(), endpointPropertiesMap, context);
863871
}
864872
}
865873

874+
// set standard endpoints implementations, if not set in config
875+
for (var entry : ALL_MICRONAUT_MANAGEMENT_ENDPOINTS.entrySet()) {
876+
var endpointName = entry.getKey();
877+
var endpointProperties = endpointPropertiesMap.get(endpointName);
878+
if (endpointProperties == null) {
879+
endpointProperties = new EndpointProperties(endpointName);
880+
endpointPropertiesMap.put(endpointName, endpointProperties);
881+
}
882+
if (endpointProperties.getElement() != null) {
883+
continue;
884+
}
885+
var className = entry.getValue();
886+
if (className == null) {
887+
continue;
888+
}
889+
var classEl = ContextUtils.getClassElement(className, context);
890+
endpointProperties.setElement(classEl);
891+
}
892+
866893
return endpointPropertiesMap;
867894
}
868895

openapi/src/main/java/io/micronaut/openapi/visitor/ContextProperty.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ public interface ContextProperty {
2929
* Loaded micronaut environment.
3030
*/
3131
String MICRONAUT_INTERNAL_ENVIRONMENT = "micronaut.internal.environment";
32+
/**
33+
* Loaded spring openapi endpoints settings.
34+
*/
35+
String MICRONAUT_INTERNAL_SPRING_OPENAPI_ENDPOINTS = "micronaut.internal.spring.openapi.endpoints";
3236
/**
3337
* Loaded micronaut openapi endpoints settings.
3438
*/

0 commit comments

Comments
 (0)