Search in sources :

Example 16 with ConfigModel

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;
}
Also used : Scope(io.strimzi.kafka.config.model.Scope) AbstractJsonDiff(io.strimzi.operator.common.operator.resource.AbstractJsonDiff) Config(org.apache.kafka.clients.admin.Config) ReconciliationLogger(io.strimzi.operator.common.ReconciliationLogger) OrderedProperties(io.strimzi.operator.common.model.OrderedProperties) Collection(java.util.Collection) KafkaVersion(io.strimzi.operator.cluster.model.KafkaVersion) ConfigEntry(org.apache.kafka.clients.admin.ConfigEntry) JsonDiff(io.fabric8.zjsonpatch.JsonDiff) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) ConfigModel(io.strimzi.kafka.config.model.ConfigModel) Reconciliation(io.strimzi.operator.common.Reconciliation) AlterConfigOp(org.apache.kafka.clients.admin.AlterConfigOp) PatchUtils.patchMapper(io.fabric8.kubernetes.client.internal.PatchUtils.patchMapper) KafkaConfiguration(io.strimzi.operator.cluster.model.KafkaConfiguration) Map(java.util.Map) Optional(java.util.Optional) JsonNode(com.fasterxml.jackson.databind.JsonNode) SerializationFeature(com.fasterxml.jackson.databind.SerializationFeature) Pattern(java.util.regex.Pattern) Collections(java.util.Collections) ConfigEntry(org.apache.kafka.clients.admin.ConfigEntry) ArrayList(java.util.ArrayList) AlterConfigOp(org.apache.kafka.clients.admin.AlterConfigOp) OrderedProperties(io.strimzi.operator.common.model.OrderedProperties) JsonNode(com.fasterxml.jackson.databind.JsonNode)

Example 17 with ConfigModel

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;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ConfigModel(io.strimzi.kafka.config.model.ConfigModel) Iterator(scala.collection.Iterator) List(java.util.List) RaftConfig(org.apache.kafka.raft.RaftConfig) ApiVersionValidator$(kafka.api.ApiVersionValidator$) ApiVersion(kafka.api.ApiVersion) Method(java.lang.reflect.Method) TreeMap(java.util.TreeMap) Type(io.strimzi.kafka.config.model.Type) Scope(io.strimzi.kafka.config.model.Scope) ConfigDef(org.apache.kafka.common.config.ConfigDef)

Example 18 with ConfigModel

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()));
}
Also used : ConfigModel(io.strimzi.kafka.config.model.ConfigModel) Test(org.junit.jupiter.api.Test)

Example 19 with ConfigModel

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")));
}
Also used : ConfigModel(io.strimzi.kafka.config.model.ConfigModel) Test(org.junit.jupiter.api.Test)

Example 20 with ConfigModel

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]")));
}
Also used : ConfigModel(io.strimzi.kafka.config.model.ConfigModel) Test(org.junit.jupiter.api.Test)

Aggregations

ConfigModel (io.strimzi.kafka.config.model.ConfigModel)28 Test (org.junit.jupiter.api.Test)18 Scope (io.strimzi.kafka.config.model.Scope)4 Type (io.strimzi.kafka.config.model.Type)4 ArrayList (java.util.ArrayList)4 Map (java.util.Map)4 JsonNode (com.fasterxml.jackson.databind.JsonNode)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)2 SerializationFeature (com.fasterxml.jackson.databind.SerializationFeature)2 PatchUtils.patchMapper (io.fabric8.kubernetes.client.internal.PatchUtils.patchMapper)2 JsonDiff (io.fabric8.zjsonpatch.JsonDiff)2 ConfigModels (io.strimzi.kafka.config.model.ConfigModels)2 KafkaConfiguration (io.strimzi.operator.cluster.model.KafkaConfiguration)2 KafkaVersion (io.strimzi.operator.cluster.model.KafkaVersion)2 Reconciliation (io.strimzi.operator.common.Reconciliation)2 ReconciliationLogger (io.strimzi.operator.common.ReconciliationLogger)2 OrderedProperties (io.strimzi.operator.common.model.OrderedProperties)2 AbstractJsonDiff (io.strimzi.operator.common.operator.resource.AbstractJsonDiff)2 File (java.io.File)2 Method (java.lang.reflect.Method)2