use of io.strimzi.kafka.config.model.ConfigModel in project strimzi by strimzi.
the class KafkaBrokerConfigurationDiff method diff.
/**
* Computes diff between two maps. Entries in IGNORABLE_PROPERTIES are skipped
* @param brokerId id of compared broker
* @param desired desired configuration, may be null if the related ConfigMap does not exist yet or no changes are required
* @param brokerConfigs current configuration
* @param configModel default configuration for {@code kafkaVersion} of broker
* @return Collection of AlterConfigOp containing all entries which were changed from current in desired configuration
*/
private Collection<AlterConfigOp> diff(int brokerId, String desired, Config brokerConfigs, Map<String, ConfigModel> configModel) {
if (brokerConfigs == null || desired == null) {
return Collections.emptyList();
}
Map<String, String> currentMap;
Collection<AlterConfigOp> updatedCE = new ArrayList<>();
currentMap = brokerConfigs.entries().stream().collect(Collectors.toMap(ConfigEntry::name, configEntry -> configEntry.value() == null ? "null" : configEntry.value()));
OrderedProperties orderedProperties = new OrderedProperties();
orderedProperties.addStringPairs(desired);
Map<String, String> desiredMap = orderedProperties.asMap();
fillPlaceholderValue(desiredMap, Integer.toString(brokerId));
JsonNode source = patchMapper().configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true).valueToTree(currentMap);
JsonNode target = patchMapper().configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true).valueToTree(desiredMap);
JsonNode jsonDiff = JsonDiff.asJson(source, target);
for (JsonNode d : jsonDiff) {
String pathValue = d.get("path").asText();
String pathValueWithoutSlash = pathValue.substring(1);
Optional<ConfigEntry> optEntry = brokerConfigs.entries().stream().filter(configEntry -> configEntry.name().equals(pathValueWithoutSlash)).findFirst();
String op = d.get("op").asText();
if (optEntry.isPresent()) {
ConfigEntry entry = optEntry.get();
if ("remove".equals(op)) {
removeProperty(configModel, updatedCE, pathValueWithoutSlash, entry);
} else if ("replace".equals(op)) {
// entry is in the current, desired is updated value
updateOrAdd(entry.name(), configModel, desiredMap, updatedCE);
}
} else {
if ("add".equals(op)) {
// entry is not in the current, it is added
updateOrAdd(pathValueWithoutSlash, configModel, desiredMap, updatedCE);
}
}
if ("remove".equals(op)) {
// there is a lot of properties set by default - not having them in desired causes very noisy log output
LOGGER.traceCr(reconciliation, "Kafka Broker {} Config Differs : {}", brokerId, d);
LOGGER.traceCr(reconciliation, "Current Kafka Broker Config path {} has value {}", pathValueWithoutSlash, lookupPath(source, pathValue));
LOGGER.traceCr(reconciliation, "Desired Kafka Broker Config path {} has value {}", pathValueWithoutSlash, lookupPath(target, pathValue));
} else {
LOGGER.debugCr(reconciliation, "Kafka Broker {} Config Differs : {}", brokerId, d);
LOGGER.debugCr(reconciliation, "Current Kafka Broker Config path {} has value {}", pathValueWithoutSlash, lookupPath(source, pathValue));
LOGGER.debugCr(reconciliation, "Desired Kafka Broker Config path {} has value {}", pathValueWithoutSlash, lookupPath(target, pathValue));
}
}
return updatedCE;
}
use of io.strimzi.kafka.config.model.ConfigModel in project strimzi by strimzi.
the class KafkaConfigModelGenerator method configs.
private static Map<String, ConfigModel> configs() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
ConfigDef def = brokerConfigs();
Map<String, String> dynamicUpdates = brokerDynamicUpdates();
Method getConfigValueMethod = def.getClass().getDeclaredMethod("getConfigValue", ConfigDef.ConfigKey.class, String.class);
getConfigValueMethod.setAccessible(true);
Method sortedConfigs = ConfigDef.class.getDeclaredMethod("sortedConfigs");
sortedConfigs.setAccessible(true);
List<ConfigDef.ConfigKey> keys = (List) sortedConfigs.invoke(def);
Map<String, ConfigModel> result = new TreeMap<>();
for (ConfigDef.ConfigKey key : keys) {
String configName = String.valueOf(getConfigValueMethod.invoke(def, key, "Name"));
Type type = parseType(String.valueOf(getConfigValueMethod.invoke(def, key, "Type")));
Scope scope = parseScope(dynamicUpdates.getOrDefault(key.name, "read-only"));
ConfigModel descriptor = new ConfigModel();
descriptor.setType(type);
descriptor.setScope(scope);
if (key.validator instanceof ConfigDef.Range) {
descriptor = range(key, descriptor);
} else if (key.validator instanceof ConfigDef.ValidString) {
descriptor.setValues(enumer(key.validator));
} else if (key.validator instanceof ConfigDef.ValidList) {
descriptor.setItems(validList(key));
} else if (key.validator instanceof ApiVersionValidator$) {
Iterator<ApiVersion> iterator = ApiVersion$.MODULE$.allVersions().iterator();
LinkedHashSet<String> versions = new LinkedHashSet<>();
while (iterator.hasNext()) {
ApiVersion next = iterator.next();
ApiVersion$.MODULE$.apply(next.shortVersion());
versions.add(Pattern.quote(next.shortVersion()) + "(\\.[0-9]+)*");
ApiVersion$.MODULE$.apply(next.version());
versions.add(Pattern.quote(next.version()));
}
descriptor.setPattern(String.join("|", versions));
} else if (key.validator instanceof ConfigDef.NonEmptyString) {
descriptor.setPattern(".+");
} else if (key.validator instanceof RaftConfig.ControllerQuorumVotersValidator) {
continue;
} else if (key.validator != null) {
throw new IllegalStateException("Invalid validator class " + key.validator.getClass() + " for option " + configName);
}
result.put(configName, descriptor);
}
return result;
}
use of io.strimzi.kafka.config.model.ConfigModel in project strimzi by strimzi.
the class ConfigModelTest method testPasswordValidation.
@Test
public void testPasswordValidation() {
ConfigModel cm = new ConfigModel();
cm.setType(Type.PASSWORD);
assertThat(cm.validate("test", "whatever"), is(emptyList()));
}
use of io.strimzi.kafka.config.model.ConfigModel in project strimzi by strimzi.
the class ConfigModelTest method testShortValidation.
@Test
public void testShortValidation() {
ConfigModel cm = new ConfigModel();
cm.setType(Type.SHORT);
assertThat(cm.validate("test", "1"), is(emptyList()));
assertThat(cm.validate("test", Short.valueOf(Short.MAX_VALUE).toString()), is(emptyList()));
assertThat(cm.validate("test", Short.valueOf(Short.MIN_VALUE).toString()), is(emptyList()));
assertThat(cm.validate("test", Integer.valueOf((int) Short.MAX_VALUE + 1).toString()), is(singletonList("test has value '32768' which is not a short")));
assertThat(cm.validate("test", Integer.valueOf((int) Short.MIN_VALUE - 1).toString()), is(singletonList("test has value '-32769' which is not a short")));
cm.setMinimum(0);
assertThat(cm.validate("test", "-1"), is(singletonList("test has value -1 which less than the minimum value 0")));
cm.setMaximum(1);
assertThat(cm.validate("test", "2"), is(singletonList("test has value 2 which greater than the maximum value 1")));
}
use of io.strimzi.kafka.config.model.ConfigModel in project strimzi by strimzi.
the class ConfigModelTest method testListValidation.
@Test
public void testListValidation() {
ConfigModel cm = new ConfigModel();
cm.setType(Type.LIST);
assertThat(cm.validate("test", "foo"), is(emptyList()));
assertThat(cm.validate("test", "foo,bar"), is(emptyList()));
cm.setItems(asList("foo", "bar"));
assertThat(cm.validate("test", "foo"), is(emptyList()));
assertThat(cm.validate("test", "foo,bar"), is(emptyList()));
assertThat(cm.validate("test", "foo,bar,baz"), is(singletonList("test contains values [baz] which are not in the allowed items [foo, bar]")));
assertThat(cm.validate("test", "foo, bar, baz"), is(singletonList("test contains values [baz] which are not in the allowed items [foo, bar]")));
assertThat(cm.validate("test", " foo , bar, baz "), is(singletonList("test contains values [baz] which are not in the allowed items [foo, bar]")));
assertThat(cm.validate("test", " foo , bar,,"), is(singletonList("test contains values [] which are not in the allowed items [foo, bar]")));
}
Aggregations