ClustersProperties.java 5.3 KB

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