ClustersProperties.java 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package com.provectus.kafka.ui.config;
  2. import com.provectus.kafka.ui.model.MetricsConfig;
  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. MetricsConfigData 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")
  59. public static class MetricsConfigData {
  60. String type;
  61. Integer port;
  62. Boolean ssl;
  63. String username;
  64. String password;
  65. String keystoreLocation;
  66. String keystorePassword;
  67. }
  68. @Data
  69. @NoArgsConstructor
  70. @AllArgsConstructor
  71. @Builder(toBuilder = true)
  72. @ToString(exclude = {"password", "keystorePassword"})
  73. public static class ConnectCluster {
  74. String name;
  75. String address;
  76. String username;
  77. String password;
  78. String keystoreLocation;
  79. String keystorePassword;
  80. }
  81. @Data
  82. @ToString(exclude = {"password"})
  83. public static class SchemaRegistryAuth {
  84. String username;
  85. String password;
  86. }
  87. @Data
  88. @ToString(exclude = {"truststorePassword"})
  89. public static class TruststoreConfig {
  90. String truststoreLocation;
  91. String truststorePassword;
  92. }
  93. @Data
  94. public static class SerdeConfig {
  95. String name;
  96. String className;
  97. String filePath;
  98. Map<String, Object> properties;
  99. String topicKeysPattern;
  100. String topicValuesPattern;
  101. }
  102. @Data
  103. @ToString(exclude = "password")
  104. public static class KsqldbServerAuth {
  105. String username;
  106. String password;
  107. }
  108. @Data
  109. @NoArgsConstructor
  110. @AllArgsConstructor
  111. @ToString(exclude = {"keystorePassword"})
  112. public static class KeystoreConfig {
  113. String keystoreLocation;
  114. String keystorePassword;
  115. }
  116. @Data
  117. public static class Masking {
  118. Type type;
  119. List<String> fields;
  120. String fieldsNamePattern;
  121. List<String> maskingCharsReplacement; //used when type=MASK
  122. String replacement; //used when type=REPLACE
  123. String topicKeysPattern;
  124. String topicValuesPattern;
  125. public enum Type {
  126. REMOVE, MASK, REPLACE
  127. }
  128. }
  129. @Data
  130. @NoArgsConstructor
  131. @AllArgsConstructor
  132. public static class AuditProperties {
  133. String topic;
  134. Integer auditTopicsPartitions;
  135. Boolean topicAuditEnabled;
  136. Boolean consoleAuditEnabled;
  137. LogLevel level;
  138. Map<String, String> auditTopicProperties;
  139. public enum LogLevel {
  140. ALL,
  141. ALTER_ONLY //default
  142. }
  143. }
  144. @PostConstruct
  145. public void validateAndSetDefaults() {
  146. if (clusters != null) {
  147. validateClusterNames();
  148. flattenClusterProperties();
  149. setMetricsDefaults();
  150. }
  151. }
  152. private void setMetricsDefaults() {
  153. for (Cluster cluster : clusters) {
  154. if (cluster.getMetrics() != null && !StringUtils.hasText(cluster.getMetrics().getType())) {
  155. cluster.getMetrics().setType(MetricsConfig.JMX_METRICS_TYPE);
  156. }
  157. }
  158. }
  159. private void flattenClusterProperties() {
  160. for (Cluster cluster : clusters) {
  161. cluster.setProperties(flattenClusterProperties(null, cluster.getProperties()));
  162. }
  163. }
  164. private Map<String, Object> flattenClusterProperties(@Nullable String prefix,
  165. @Nullable Map<String, Object> propertiesMap) {
  166. Map<String, Object> flattened = new HashMap<>();
  167. if (propertiesMap != null) {
  168. propertiesMap.forEach((k, v) -> {
  169. String key = prefix == null ? k : prefix + "." + k;
  170. if (v instanceof Map<?, ?>) {
  171. flattened.putAll(flattenClusterProperties(key, (Map<String, Object>) v));
  172. } else {
  173. flattened.put(key, v);
  174. }
  175. });
  176. }
  177. return flattened;
  178. }
  179. private void validateClusterNames() {
  180. // if only one cluster provided it is ok not to set name
  181. if (clusters.size() == 1 && !StringUtils.hasText(clusters.get(0).getName())) {
  182. clusters.get(0).setName("Default");
  183. return;
  184. }
  185. Set<String> clusterNames = new HashSet<>();
  186. for (Cluster clusterProperties : clusters) {
  187. if (!StringUtils.hasText(clusterProperties.getName())) {
  188. throw new IllegalStateException(
  189. "Application config isn't valid. "
  190. + "Cluster names should be provided in case of multiple clusters present");
  191. }
  192. if (!clusterNames.add(clusterProperties.getName())) {
  193. throw new IllegalStateException(
  194. "Application config isn't valid. Two clusters can't have the same name");
  195. }
  196. }
  197. }
  198. }