ClustersProperties.java 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package com.provectus.kafka.ui.config;
  2. import com.provectus.kafka.ui.model.MetricsConfig;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.HashSet;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Set;
  9. import javax.annotation.Nullable;
  10. import javax.annotation.PostConstruct;
  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. @Data
  25. public static class Cluster {
  26. String name;
  27. String bootstrapServers;
  28. String schemaRegistry;
  29. SchemaRegistryAuth schemaRegistryAuth;
  30. KeystoreConfig schemaRegistrySsl;
  31. String ksqldbServer;
  32. KsqldbServerAuth ksqldbServerAuth;
  33. KeystoreConfig ksqldbServerSsl;
  34. List<ConnectCluster> kafkaConnect;
  35. MetricsConfigData metrics;
  36. Map<String, Object> properties;
  37. boolean readOnly = false;
  38. List<SerdeConfig> serde;
  39. String defaultKeySerde;
  40. String defaultValueSerde;
  41. List<Masking> masking;
  42. Long pollingThrottleRate;
  43. TruststoreConfig ssl;
  44. }
  45. @Data
  46. @ToString(exclude = "password")
  47. public static class MetricsConfigData {
  48. String type;
  49. Integer port;
  50. Boolean ssl;
  51. String username;
  52. String password;
  53. String keystoreLocation;
  54. String keystorePassword;
  55. }
  56. @Data
  57. @NoArgsConstructor
  58. @AllArgsConstructor
  59. @Builder(toBuilder = true)
  60. @ToString(exclude = {"password", "keystorePassword"})
  61. public static class ConnectCluster {
  62. String name;
  63. String address;
  64. String username;
  65. String password;
  66. String keystoreLocation;
  67. String keystorePassword;
  68. }
  69. @Data
  70. @ToString(exclude = {"password"})
  71. public static class SchemaRegistryAuth {
  72. String username;
  73. String password;
  74. }
  75. @Data
  76. @ToString(exclude = {"truststorePassword"})
  77. public static class TruststoreConfig {
  78. String truststoreLocation;
  79. String truststorePassword;
  80. }
  81. @Data
  82. public static class SerdeConfig {
  83. String name;
  84. String className;
  85. String filePath;
  86. Map<String, Object> properties;
  87. String topicKeysPattern;
  88. String topicValuesPattern;
  89. }
  90. @Data
  91. @ToString(exclude = "password")
  92. public static class KsqldbServerAuth {
  93. String username;
  94. String password;
  95. }
  96. @Data
  97. @NoArgsConstructor
  98. @AllArgsConstructor
  99. @ToString(exclude = {"keystorePassword"})
  100. public static class KeystoreConfig {
  101. String keystoreLocation;
  102. String keystorePassword;
  103. }
  104. @Data
  105. public static class Masking {
  106. Type type;
  107. List<String> fields; //if null or empty list - policy will be applied to all fields
  108. List<String> pattern; //used when type=MASK
  109. String replacement; //used when type=REPLACE
  110. String topicKeysPattern;
  111. String topicValuesPattern;
  112. public enum Type {
  113. REMOVE, MASK, REPLACE
  114. }
  115. }
  116. @PostConstruct
  117. public void validateAndSetDefaults() {
  118. if (clusters != null) {
  119. validateClusterNames();
  120. flattenClusterProperties();
  121. setMetricsDefaults();
  122. }
  123. }
  124. private void setMetricsDefaults() {
  125. for (Cluster cluster : clusters) {
  126. if (cluster.getMetrics() != null && !StringUtils.hasText(cluster.getMetrics().getType())) {
  127. cluster.getMetrics().setType(MetricsConfig.JMX_METRICS_TYPE);
  128. }
  129. }
  130. }
  131. private void flattenClusterProperties() {
  132. for (Cluster cluster : clusters) {
  133. cluster.setProperties(flattenClusterProperties(null, cluster.getProperties()));
  134. }
  135. }
  136. private Map<String, Object> flattenClusterProperties(@Nullable String prefix,
  137. @Nullable Map<String, Object> propertiesMap) {
  138. Map<String, Object> flattened = new HashMap<>();
  139. if (propertiesMap != null) {
  140. propertiesMap.forEach((k, v) -> {
  141. String key = prefix == null ? k : prefix + "." + k;
  142. if (v instanceof Map<?, ?>) {
  143. flattened.putAll(flattenClusterProperties(key, (Map<String, Object>) v));
  144. } else {
  145. flattened.put(key, v);
  146. }
  147. });
  148. }
  149. return flattened;
  150. }
  151. private void validateClusterNames() {
  152. // if only one cluster provided it is ok not to set name
  153. if (clusters.size() == 1 && !StringUtils.hasText(clusters.get(0).getName())) {
  154. clusters.get(0).setName("Default");
  155. return;
  156. }
  157. Set<String> clusterNames = new HashSet<>();
  158. for (Cluster clusterProperties : clusters) {
  159. if (!StringUtils.hasText(clusterProperties.getName())) {
  160. throw new IllegalStateException(
  161. "Application config isn't valid. "
  162. + "Cluster names should be provided in case of multiple clusters present");
  163. }
  164. if (!clusterNames.add(clusterProperties.getName())) {
  165. throw new IllegalStateException(
  166. "Application config isn't valid. Two clusters can't have the same name");
  167. }
  168. }
  169. }
  170. }