private static Optional<ConfigValue> resolveStreamsConfig( final String maybePrefixedKey, final Object value) { final String key = maybePrefixedKey.startsWith(KSQL_STREAMS_PREFIX) ? maybePrefixedKey.substring(KSQL_STREAMS_PREFIX.length()) : maybePrefixedKey; if (key.startsWith(KsqlConfig.KSQL_CONFIG_PROPERTY_PREFIX)) { return Optional.empty(); } return new KsqlConfigResolver().resolve(maybePrefixedKey, false) .map(configItem -> new ConfigValue(configItem, key, configItem.parseValue(value))); }
@Override public Object parse(final String property, final Object value) { if (property.equalsIgnoreCase(DdlConfig.AVRO_SCHEMA) || property.equalsIgnoreCase(KsqlConstants.RUN_SCRIPT_STATEMENTS_CONTENT)) { validator.validate(property, value); return value; } final ConfigItem configItem = resolver.resolve(property, true) .orElseThrow(() -> new IllegalArgumentException(String.format( "Not recognizable as ksql, streams, consumer, or producer property: '%s'", property))); final Object parsedValue = configItem.parseValue(value); validator.validate(configItem.getPropertyName(), parsedValue); return parsedValue; } }
private String convertToObfuscatedString() { return configItem.convertToString(value); } }
@Override protected boolean matchesSafely( final Optional<ConfigItem> possibleConfig, final Description desc) { if (!possibleConfig.isPresent()) { desc.appendText(" but the name was not known"); return false; } final ConfigItem configItem = possibleConfig.get(); if (!(configItem instanceof ConfigItem.Unresolved)) { desc.appendText(" but was resolved item ").appendValue(configItem); return false; } if (!configItem.getPropertyName().equals(propertyName)) { desc.appendText(" but propertyName was ").appendValue(configItem.getPropertyName()); return false; } return true; }
private PropertiesList listProperties( final PreparedStatement<ListProperties> statement, final Map<String, Object> propertyOverrides ) { final KsqlConfigResolver resolver = new KsqlConfigResolver(); final Map<String, String> engineProperties = ksqlConfig.getAllConfigPropsWithSecretsObfuscated(); final Map<String, String> mergedProperties = ksqlConfig .cloneWithPropertyOverwrite(propertyOverrides) .getAllConfigPropsWithSecretsObfuscated(); final List<String> overwritten = mergedProperties.entrySet() .stream() .filter(e -> !Objects.equals(engineProperties.get(e.getKey()), e.getValue())) .map(Entry::getKey) .collect(Collectors.toList()); final List<String> defaultProps = mergedProperties.entrySet().stream() .filter(e -> resolver.resolve(e.getKey(), false) .map(resolved -> resolved.isDefaultValue(e.getValue())) .orElse(false)) .map(Entry::getKey) .collect(Collectors.toList()); return new PropertiesList( statement.getStatementText(), mergedProperties, overwritten, defaultProps); }
private boolean isResolved() { return configItem.isResolved(); }
private static Optional<ConfigItem> resolveKsqlConfig(final String propertyName) { final Optional<ConfigItem> possibleItem = resolveConfig("", KSQL_CONFIG_DEF, propertyName); if (possibleItem.isPresent()) { return possibleItem; } if (propertyName.startsWith(KsqlConfig.KSQL_FUNCTIONS_PROPERTY_PREFIX)) { // Functions properties are free form, so can not be resolved / validated: return Optional.of(ConfigItem.unresolved(propertyName)); } return Optional.empty(); }
private static Optional<ConfigItem> resolveConfig( final String prefix, final ConfigDef def, final String propertyName) { if (!propertyName.startsWith(prefix)) { return Optional.empty(); } final String keyNoPrefix = stripPrefix(propertyName, prefix); final ConfigKey configKey = def.configKeys().get(keyNoPrefix); if (configKey == null) { return Optional.empty(); } return Optional.of(ConfigItem.resolved(configKey)); }
@Test public void shouldReturnPropertyName() { assertThat(RESOLVED_NO_VALIDATOR.getPropertyName(), is(KsqlConfig.SINK_NUMBER_OF_PARTITIONS_PROPERTY)); assertThat(RESOLVED_WITH_VALIDATOR.getPropertyName(), is(StreamsConfig.SEND_BUFFER_CONFIG)); assertThat(UNRESOLVED.getPropertyName(), is("some.unresolved.prop")); }
@Test public void shouldNotBeDefaultValueIfNotResolved() { assertThat(UNRESOLVED.isDefaultValue("anything"), is(false)); assertThat(UNRESOLVED.isDefaultValue(null), is(false)); }
@Test public void shouldReturnResolved() { assertThat(RESOLVED_NO_VALIDATOR.isResolved(), is(true)); assertThat(UNRESOLVED.isResolved(), is(false)); }
private static Optional<ConfigItem> resolveStreamsConfig( final String propertyName, final boolean strict) { final String key = stripPrefix(propertyName, KsqlConfig.KSQL_STREAMS_PREFIX); final Optional<ConfigItem> resolved = STREAM_CONFIG_DEFS .stream() .map(def -> resolveConfig(def.prefix, def.def, key)) .filter(Optional::isPresent) .map(Optional::get) .findFirst(); if (resolved.isPresent()) { return resolved; } if (key.startsWith(StreamsConfig.CONSUMER_PREFIX) || key.startsWith(StreamsConfig.PRODUCER_PREFIX)) { return Optional.empty(); // Unknown producer / consumer config } if (propertyName.startsWith(KsqlConfig.KSQL_STREAMS_PREFIX)) { return Optional.empty(); // Unknown streams config } // Unknown config (which could be used): return strict ? Optional.empty() : Optional.of(ConfigItem.unresolved(key)); }
@Test(expected = ConfigException.class) public void shouldThrowIfCanNotCoerceParsedValue() { RESOLVED_WITH_VALIDATOR.parseValue("not a number"); }
@Before public void setUp() { parser = new LocalPropertyParser(resolver, validator); when(configItem.parseValue(any(Object.class))) .thenReturn(PARSED_VALUE); when(configItem.getPropertyName()) .thenReturn(PARSED_PROP_NAME); when(resolver.resolve(anyString(), anyBoolean())) .thenReturn(Optional.of(configItem)); }
@Override protected boolean matchesSafely( final Optional<ConfigItem> possibleConfig, final Description desc) { if (!possibleConfig.isPresent()) { desc.appendText(" but the name was not known"); return false; } final ConfigItem configItem = possibleConfig.get(); if (!(configItem instanceof ConfigItem.Resolved)) { desc.appendText(" but was unresolved item ").appendValue(configItem); return false; } if (!configItem.getPropertyName().equals(propertyName)) { desc.appendText(" but propertyName was ").appendValue(configItem.getPropertyName()); return false; } final ConfigItem.Resolved resolvedItem = (Resolved) configItem; if (expectedKey.map(k -> !k.equals(resolvedItem.getKey())).orElse(false)) { desc.appendText(" but key was ").appendValue(resolvedItem.getKey()); return false; } return true; }
@Test public void shouldCoerceBeforeCheckingIfDefaultValue() { assertThat(RESOLVED_NO_VALIDATOR .isDefaultValue("" + KsqlConstants.defaultSinkNumberOfPartitions), is(true)); }
@Test public void shouldPassThroughUnresolvedOnConvertToString() { assertThat(UNRESOLVED.convertToString(12345L), is("12345")); assertThat(UNRESOLVED.convertToString(null), is("NULL")); }
@Test public void shouldPassThroughUnresolvedValueOnParse() { assertThat(UNRESOLVED.parseValue("anything"), is("anything")); assertThat(UNRESOLVED.parseValue(12345L), is(12345L)); }
@Test public void shouldHandlePasswordDefaultValue() { assertThat(RESOLVED_PASSWORD.isDefaultValue("anything"), is(false)); } }
@Test public void shouldObfuscatePasswordsOnResolveToString() { assertThat(RESOLVED_PASSWORD.convertToString("Sensitive"), is("[hidden]")); }