ClustersProperties.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package com.provectus.kafka.ui.config;
  2. import static com.provectus.kafka.ui.model.MetricsScrapeProperties.JMX_METRICS_TYPE;
  3. import jakarta.annotation.PostConstruct;
  4. import java.util.ArrayList;
  5. import java.util.HashMap;
  6. import java.util.HashSet;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Set;
  10. import javax.annotation.Nullable;
  11. import lombok.AllArgsConstructor;
  12. import lombok.Builder;
  13. import lombok.Data;
  14. import lombok.NoArgsConstructor;
  15. import lombok.ToString;
  16. import org.springframework.boot.context.properties.ConfigurationProperties;
  17. import org.springframework.context.annotation.Configuration;
  18. import org.springframework.util.StringUtils;
  19. @Configuration
  20. @ConfigurationProperties("kafka")
  21. @Data
  22. public class ClustersProperties {
  23. List<Cluster> clusters = new ArrayList<>();
  24. String internalTopicPrefix;
  25. Integer adminClientTimeout;
  26. PollingProperties polling = new PollingProperties();
  27. @Data
  28. public static class Cluster {
  29. String name;
  30. String bootstrapServers;
  31. String schemaRegistry;
  32. SchemaRegistryAuth schemaRegistryAuth;
  33. KeystoreConfig schemaRegistrySsl;
  34. String ksqldbServer;
  35. KsqldbServerAuth ksqldbServerAuth;
  36. KeystoreConfig ksqldbServerSsl;
  37. List<ConnectCluster> kafkaConnect;
  38. MetricsConfig metrics;
  39. Map<String, Object> properties;
  40. boolean readOnly = false;
  41. List<SerdeConfig> serde;
  42. String defaultKeySerde;
  43. String defaultValueSerde;
  44. List<Masking> masking;
  45. Long pollingThrottleRate;
  46. TruststoreConfig ssl;
  47. AuditProperties audit;
  48. }
  49. @Data
  50. public static class PollingProperties {
  51. Integer pollTimeoutMs;
  52. Integer partitionPollTimeout;
  53. Integer noDataEmptyPolls;
  54. Integer maxPageSize;
  55. Integer defaultPageSize;
  56. }
  57. @Data
  58. @ToString(exclude = {"password", "keystorePassword"})
  59. public static class MetricsConfig {
  60. String type;
  61. Integer port;
  62. Boolean ssl;
  63. String username;
  64. String password;
  65. String keystoreLocation;
  66. String keystorePassword;
  67. MetricsStorage store;
  68. }
  69. @Data
  70. public static class MetricsStorage {
  71. PrometheusStorage prometheus;
  72. }
  73. @Data
  74. @ToString(exclude = {"pushGatewayPassword"})
  75. public static class PrometheusStorage {
  76. String url;
  77. String pushGatewayUrl;
  78. String pushGatewayUsername;
  79. String pushGatewayPassword;
  80. String pushGatewayJobName;
  81. Boolean remoteWrite;
  82. }
  83. @Data
  84. @NoArgsConstructor
  85. @AllArgsConstructor
  86. @Builder(toBuilder = true)
  87. @ToString(exclude = {"password", "keystorePassword"})
  88. public static class ConnectCluster {
  89. String name;
  90. String address;
  91. String username;
  92. String password;
  93. String keystoreLocation;
  94. String keystorePassword;
  95. }
  96. @Data
  97. @ToString(exclude = {"password"})
  98. public static class SchemaRegistryAuth {
  99. String username;
  100. String password;
  101. }
  102. @Data
  103. @ToString(exclude = {"truststorePassword"})
  104. public static class TruststoreConfig {
  105. String truststoreLocation;
  106. String truststorePassword;
  107. }
  108. @Data
  109. public static class SerdeConfig {
  110. String name;
  111. String className;
  112. String filePath;
  113. Map<String, Object> properties;
  114. String topicKeysPattern;
  115. String topicValuesPattern;
  116. }
  117. @Data
  118. @ToString(exclude = "password")
  119. public static class KsqldbServerAuth {
  120. String username;
  121. String password;
  122. }
  123. @Data
  124. @NoArgsConstructor
  125. @AllArgsConstructor
  126. @ToString(exclude = {"keystorePassword"})
  127. public static class KeystoreConfig {
  128. String keystoreLocation;
  129. String keystorePassword;
  130. }
  131. @Data
  132. public static class Masking {
  133. Type type;
  134. List<String> fields;
  135. String fieldsNamePattern;
  136. List<String> maskingCharsReplacement; //used when type=MASK
  137. String replacement; //used when type=REPLACE
  138. String topicKeysPattern;
  139. String topicValuesPattern;
  140. public enum Type {
  141. REMOVE, MASK, REPLACE
  142. }
  143. }
  144. @Data
  145. @NoArgsConstructor
  146. @AllArgsConstructor
  147. public static class AuditProperties {
  148. String topic;
  149. Integer auditTopicsPartitions;
  150. Boolean topicAuditEnabled;
  151. Boolean consoleAuditEnabled;
  152. Map<String, String> auditTopicProperties;
  153. }
  154. @PostConstruct
  155. public void validateAndSetDefaults() {
  156. if (clusters != null) {
  157. validateClusterNames();
  158. flattenClusterProperties();
  159. setMetricsDefaults();
  160. }
  161. }
  162. private void setMetricsDefaults() {
  163. for (Cluster cluster : clusters) {
  164. if (cluster.getMetrics() != null && !StringUtils.hasText(cluster.getMetrics().getType())) {
  165. cluster.getMetrics().setType(JMX_METRICS_TYPE);
  166. }
  167. }
  168. }
  169. private void flattenClusterProperties() {
  170. for (Cluster cluster : clusters) {
  171. cluster.setProperties(flattenClusterProperties(null, cluster.getProperties()));
  172. }
  173. }
  174. private Map<String, Object> flattenClusterProperties(@Nullable String prefix,
  175. @Nullable Map<String, Object> propertiesMap) {
  176. Map<String, Object> flattened = new HashMap<>();
  177. if (propertiesMap != null) {
  178. propertiesMap.forEach((k, v) -> {
  179. String key = prefix == null ? k : prefix + "." + k;
  180. if (v instanceof Map<?, ?>) {
  181. flattened.putAll(flattenClusterProperties(key, (Map<String, Object>) v));
  182. } else {
  183. flattened.put(key, v);
  184. }
  185. });
  186. }
  187. return flattened;
  188. }
  189. private void validateClusterNames() {
  190. // if only one cluster provided it is ok not to set name
  191. if (clusters.size() == 1 && !StringUtils.hasText(clusters.get(0).getName())) {
  192. clusters.get(0).setName("Default");
  193. return;
  194. }
  195. Set<String> clusterNames = new HashSet<>();
  196. for (Cluster clusterProperties : clusters) {
  197. if (!StringUtils.hasText(clusterProperties.getName())) {
  198. throw new IllegalStateException(
  199. "Application config isn't valid. "
  200. + "Cluster names should be provided in case of multiple clusters present");
  201. }
  202. if (!clusterNames.add(clusterProperties.getName())) {
  203. throw new IllegalStateException(
  204. "Application config isn't valid. Two clusters can't have the same name");
  205. }
  206. }
  207. }
  208. }