From 82d999571775eff0202d542206e53c4285bb8595 Mon Sep 17 00:00:00 2001 From: Christian Sailer Date: Thu, 19 Mar 2020 15:43:08 +0000 Subject: [PATCH] ENT-5109 Harmonize config-common, make everything compile again and harmonize NetworkParameterOverridesSpec. (#6082) --- .../parsing/internal/Configuration.kt | 110 ++++++++------- .../parsing/internal/Properties.kt | 107 +++++++------- .../configuration/parsing/internal/Schema.kt | 6 +- .../configuration/parsing/internal/Utils.kt | 15 +- .../internal/versioned/VersionExtractor.kt | 8 +- .../parsing/internal/PropertyTest.kt | 32 ++--- .../internal/PropertyValidationTest.kt | 36 ++--- .../parsing/internal/SchemaTest.kt | 16 +-- .../parsing/internal/SpecificationTest.kt | 18 +-- .../parsing/internal/TestUtils.kt | 2 +- .../network/NetworkParameterOverridesSpec.kt | 30 ++-- .../net/corda/node/NodeCmdLineOptions.kt | 2 +- .../subcommands/ValidateConfigurationCli.kt | 2 +- .../node/services/config/ConfigUtilities.kt | 2 +- .../node/services/config/NodeConfiguration.kt | 2 +- .../config/schema/v1/ConfigSections.kt | 131 ++++++++++-------- .../schema/v1/V1NodeConfigurationSpec.kt | 109 +++++++-------- 17 files changed, 326 insertions(+), 302 deletions(-) diff --git a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Configuration.kt b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Configuration.kt index 7883f82586..ba623b2b56 100644 --- a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Configuration.kt +++ b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Configuration.kt @@ -21,7 +21,7 @@ object Configuration { /** * Describes a [Config] hiding sensitive data. */ - fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue = { value -> ConfigValueFactory.fromAnyRef(value.toString()) }): ConfigValue? + fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue = { value -> ConfigValueFactory.fromAnyRef(value.toString()) }, options: Options): ConfigValue? } object Value { @@ -36,10 +36,11 @@ object Configuration { * * @throws ConfigException.Missing if the [Config] does not specify the value. * @throws ConfigException.WrongType if the [Config] specifies a value of the wrong type. - * @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to application-level validation rules.. + * @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to + * application-level validation rules. */ @Throws(ConfigException.Missing::class, ConfigException.WrongType::class, ConfigException.BadValue::class) - fun valueIn(configuration: Config): TYPE + fun valueIn(configuration: Config, options: Options): TYPE /** * Returns whether the value is specified by the [Config]. @@ -50,27 +51,28 @@ object Configuration { * Returns a value out of a [Config] if all is good, or null if no value is present. Otherwise, it throws an exception. * * @throws ConfigException.WrongType if the [Config] specifies a value of the wrong type. - * @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to application-level validation rules.. + * @throws ConfigException.BadValue if the [Config] specifies a value of the correct type, but this in unacceptable according to + * application-level validation rules. */ @Throws(ConfigException.WrongType::class, ConfigException.BadValue::class) - fun valueInOrNull(configuration: Config): TYPE? { + fun valueInOrNull(configuration: Config, options: Options): TYPE? { return when { - isSpecifiedBy(configuration) -> valueIn(configuration) + isSpecifiedBy(configuration) -> valueIn(configuration, options) else -> null } } } /** - * Able to parse a value from a [Config] and [Configuration.Validation.Options], returning a [Valid] result containing either the value itself, or some [Configuration.Validation.Error]s. + * Able to parse a value from a [Config] and [Configuration.Options], returning a [Valid] result containing either the value itself, or some [Configuration.Validation.Error]s. */ interface Parser { /** * Returns a [Valid] wrapper either around a valid value extracted from the [Config], or around a set of [Configuration.Validation.Error] with details about what went wrong. */ - fun parse(configuration: Config, options: Configuration.Validation.Options = Configuration.Validation.Options.defaults): Valid + fun parse(configuration: Config, options: Options = Options.defaults): Valid } } @@ -109,11 +111,6 @@ object Configuration { */ interface Definition : Configuration.Property.Metadata, Configuration.Validator, Configuration.Value.Extractor, Configuration.Describer, Configuration.Value.Parser { - /** - * Validates target [Config] with default [Configuration.Validation.Options]. - */ - fun validate(target: Config): Valid = validate(target, Configuration.Validation.Options.defaults) - override fun isSpecifiedBy(configuration: Config): Boolean = configuration.hasPath(key) /** @@ -181,9 +178,8 @@ object Configuration { fun map(mappedTypeName: String, convert: (TYPE) -> MAPPED): Standard = mapValid(mappedTypeName) { value -> valid(convert.invoke(value)) } } - override fun parse(configuration: Config, options: Configuration.Validation.Options): Validated { - - return validate(configuration, options).mapValid { config -> valid(valueIn(config)) } + override fun parse(configuration: Config, options: Configuration.Options): Validated { + return validate(configuration, options).mapValid { config -> valid(valueIn(config, options)) } } companion object { @@ -199,7 +195,6 @@ object Configuration { * Returns a [Configuration.Property.Definition.Standard] with value of type [Int]. */ fun int(key: String, sensitive: Boolean = false): Standard = long(key, sensitive).mapValid { value -> - try { valid(Math.toIntExact(value)) } catch (e: ArithmeticException) { @@ -210,18 +205,17 @@ object Configuration { /** * Returns a [Configuration.Property.Definition.Standard] with value of type [Boolean]. */ - fun boolean(key: String, sensitive: Boolean = false): Standard = StandardProperty(key, Boolean::class.javaObjectType.simpleName, Config::getBoolean, Config::getBooleanList, sensitive) + fun boolean(key: String, sensitive: Boolean = false): Standard = StandardProperty(key, Boolean::class.javaObjectType.simpleName, { config, path, _ -> config.getBoolean(path) }, { config, path, _ -> config.getBooleanList(path) }, sensitive) /** * Returns a [Configuration.Property.Definition.Standard] with value of type [Double]. */ - fun double(key: String, sensitive: Boolean = false): Standard = StandardProperty(key, Double::class.javaObjectType.simpleName, Config::getDouble, Config::getDoubleList, sensitive) + fun double(key: String, sensitive: Boolean = false): Standard = StandardProperty(key, Double::class.javaObjectType.simpleName, { config, path, _ -> config.getDouble(path) }, { config, path, _ -> config.getDoubleList(path) }, sensitive) /** * Returns a [Configuration.Property.Definition.Standard] with value of type [Float]. */ fun float(key: String, sensitive: Boolean = false): Standard = double(key, sensitive).mapValid { value -> - val floatValue = value.toFloat() if (floatValue.isInfinite() || floatValue.isNaN()) { invalid(Configuration.Validation.Error.BadValue.of(key, Float::class.javaObjectType.simpleName, "Provided value exceeds Float range.")) @@ -233,24 +227,43 @@ object Configuration { /** * Returns a [Configuration.Property.Definition.Standard] with value of type [String]. */ - fun string(key: String, sensitive: Boolean = false): Standard = StandardProperty(key, String::class.java.simpleName, Config::getString, Config::getStringList, sensitive) + fun string(key: String, sensitive: Boolean = false): Standard = StandardProperty( + key, + String::class.java.simpleName, + { config, path, _ -> config.getString(path) }, + { config, path, _ -> config.getStringList(path) }, + sensitive + ) /** * Returns a [Configuration.Property.Definition.Standard] with value of type [Duration]. */ - fun duration(key: String, sensitive: Boolean = false): Standard = StandardProperty(key, Duration::class.java.simpleName, Config::getDuration, Config::getDurationList, sensitive) + fun duration(key: String, sensitive: Boolean = false): Standard = StandardProperty(key, Duration::class.java.simpleName, { config, path, _ -> config.getDuration(path) }, { config, path, _ -> config.getDurationList(path) }, sensitive) /** * Returns a [Configuration.Property.Definition.Standard] with value of type [ConfigObject]. * It supports an optional [Configuration.Schema], which is used for validation and more when provided. */ - fun nestedObject(key: String, schema: Schema? = null, sensitive: Boolean = false): Standard = StandardProperty(key, ConfigObject::class.java.simpleName, Config::getObject, Config::getObjectList, sensitive, schema) + fun nestedObject(key: String, schema: Schema? = null, sensitive: Boolean = false): Standard = StandardProperty( + key, + ConfigObject::class.java.simpleName, + { config, path, _ -> config.getObject(path) }, + { config, path, _ -> config.getObjectList(path) }, + sensitive, + schema + ) /** * Returns a [Configuration.Property.Definition.Standard] with value of type [ENUM]. * This property expects a value in the configuration matching one of the cases of [ENUM], as text, in uppercase. */ - fun > enum(key: String, enumClass: KClass, sensitive: Boolean = false): Standard = StandardProperty(key, enumClass.java.simpleName, { conf: Config, propertyKey: String -> conf.getEnum(enumClass.java, propertyKey) }, { conf: Config, propertyKey: String -> conf.getEnumList(enumClass.java, propertyKey) }, sensitive) + fun > enum(key: String, enumClass: KClass, sensitive: Boolean = false): Standard = StandardProperty( + key, + enumClass.java.simpleName, + { conf: Config, propertyKey: String, _ -> conf.getEnum(enumClass.java, propertyKey) }, + { conf: Config, propertyKey: String, _ -> conf.getEnumList(enumClass.java, propertyKey) }, + sensitive + ) } } } @@ -275,12 +288,7 @@ object Configuration { */ val properties: Set> - /** - * Validates target [Config] with default [Configuration.Validation.Options]. - */ - fun validate(target: Config): Valid = validate(target, Configuration.Validation.Options.defaults) - - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue companion object { @@ -368,35 +376,35 @@ object Configuration { override fun description() = schema.description() - override fun validate(target: Config, options: Validation.Options) = schema.validate(target, options) + override fun validate(target: Config, options: Options) = schema.validate(target, options) - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue) = schema.describe(configuration, serialiseValue) + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options) = schema.describe(configuration, serialiseValue, options) - final override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid = validate(configuration, options).mapValid(::parseValid) + final override fun parse(configuration: Config, options: Options): Valid = validate(configuration, options).mapValid { parseValid(it, options) } /** * Implement to define further mapping and validation logic, assuming the underlying raw [Config] is correct in terms of this [Configuration.Specification]. */ - protected abstract fun parseValid(configuration: Config): Valid + protected abstract fun parseValid(configuration: Config, options: Options): Valid + } + + /** + * Validation and processing options. + * @property strict whether to raise unknown property keys as errors. + */ + class Options(val strict: Boolean = false) { + + companion object { + + /** + * Default [Config] options, without [strict] parsing enabled. + */ + val defaults: Configuration.Options = Options() + } } object Validation { - /** - * [Config] validation options. - * @property strict whether to raise unknown property keys as errors. - */ - data class Options(val strict: Boolean) { - - companion object { - - /** - * Default [Config] validation options, without [strict] parsing enabled. - */ - val defaults: Configuration.Validation.Options = Options(strict = false) - } - } - /** * Super-type for the errors raised by the parsing and validation of a [Config] object. * @@ -531,7 +539,7 @@ object Configuration { } /** - * Raised when a key-value pair appeared in the [Config] object without a matching property in the [Configuration.Schema], and [Configuration.Validation.Options.strict] was enabled. + * Raised when a key-value pair appeared in the [Config] object without a matching property in the [Configuration.Schema], and [Configuration.Options.strict] was enabled. */ class Unknown private constructor(override val keyName: String, containingPath: List = emptyList()) : Configuration.Validation.Error(keyName, null, message(keyName), containingPath) { @@ -586,5 +594,5 @@ object Configuration { /** * Defines the ability to validate a [Config] object, producing a valid [Config] or a set of [Configuration.Validation.Error]. */ - interface Validator : net.corda.common.validation.internal.Validator + interface Validator : net.corda.common.validation.internal.Validator } \ No newline at end of file diff --git a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Properties.kt b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Properties.kt index 4ce49fc5e6..048492240a 100644 --- a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Properties.kt +++ b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Properties.kt @@ -5,10 +5,9 @@ import net.corda.common.validation.internal.Validated import net.corda.common.validation.internal.Validated.Companion.invalid import net.corda.common.validation.internal.Validated.Companion.valid -internal class LongProperty(key: String, sensitive: Boolean = false) : StandardProperty(key, Long::class.javaObjectType.simpleName, Config::getLong, Config::getLongList, sensitive) { - - override fun validate(target: Config, options: Configuration.Validation.Options): Valid { +internal class LongProperty(key: String, sensitive: Boolean = false) : StandardProperty(key, Long::class.javaObjectType.simpleName, { config, path, _ -> config.getLong(path) }, { config, path, _ -> config.getLongList(path) }, sensitive) { + override fun validate(target: Config, options: Configuration.Options): Valid { val validated = super.validate(target, options) if (validated.isValid && target.getValue(key).unwrapped().toString().contains(".")) { return invalid(ConfigException.WrongType(target.origin(), key, Long::class.javaObjectType.simpleName, Double::class.javaObjectType.simpleName).toValidationError(key, typeName)) @@ -17,9 +16,11 @@ internal class LongProperty(key: String, sensitive: Boolean = false) : StandardP } } -internal open class StandardProperty(override val key: String, typeNameArg: String, private val extractSingleValue: (Config, String) -> TYPE, internal val extractListValue: (Config, String) -> List, override val isSensitive: Boolean = false, final override val schema: Configuration.Schema? = null) : Configuration.Property.Definition.Standard { +typealias ValueSelector = (Config, String, Configuration.Options) -> T - override fun valueIn(configuration: Config) = extractSingleValue.invoke(configuration, key) +internal open class StandardProperty(override val key: String, typeNameArg: String, private val extractSingleValue: ValueSelector, internal val extractListValue: ValueSelector>, override val isSensitive: Boolean = false, final override val schema: Configuration.Schema? = null) : Configuration.Property.Definition.Standard { + + override fun valueIn(configuration: Config, options: Configuration.Options) = extractSingleValue.invoke(configuration, key, options) override val typeName: String = schema?.let { "#${it.name ?: "Object@$key"}" } ?: typeNameArg @@ -29,20 +30,18 @@ internal open class StandardProperty(override val key: String, typeN override fun list(): Configuration.Property.Definition.RequiredList = ListProperty(this) - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue { - + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue { if (isSensitive) { return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue) } - return schema?.describe(configuration.getConfig(key), serialiseValue) ?: valueDescription(valueIn(configuration), serialiseValue) + return schema?.describe(configuration.getConfig(key), serialiseValue, options) ?: valueDescription(valueIn(configuration, options), serialiseValue) } override val isMandatory = true - override fun validate(target: Config, options: Configuration.Validation.Options): Valid { - + override fun validate(target: Config, options: Configuration.Options): Valid { val errors = mutableSetOf() - errors += errorsWhenExtractingValue(target) + errors += errorsWhenExtractingValue(target, options) if (errors.isEmpty()) { schema?.let { nestedSchema -> val nestedConfig: Config? = target.getConfig(key) @@ -61,15 +60,19 @@ private class ListProperty(delegate: StandardProperty) : Requi override val typeName: String = "List<${delegate.typeName}>" - override fun valueIn(configuration: Config): List = delegate.extractListValue.invoke(configuration, key) - - override fun validate(target: Config, options: Configuration.Validation.Options): Valid { + override fun valueIn(configuration: Config, options: Configuration.Options): List = delegate.extractListValue.invoke(configuration, key, options) + override fun validate(target: Config, options: Configuration.Options): Valid { val errors = mutableSetOf() - errors += errorsWhenExtractingValue(target) + errors += errorsWhenExtractingValue(target, options) if (errors.isEmpty()) { delegate.schema?.let { schema -> - errors += valueIn(target).asSequence().map { element -> element as ConfigObject }.map(ConfigObject::toConfig).mapIndexed { index, targetConfig -> schema.validate(targetConfig, options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }.fold(emptyList()) { one, other -> one + other }.toSet() + errors += valueIn(target, options).asSequence() + .map { element -> element as ConfigObject } + .map(ConfigObject::toConfig) + .mapIndexed { index, targetConfig -> schema.validate(targetConfig, options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } } + .fold(emptyList()) { one, other -> one + other } + .toSet() } } return Validated.withResult(target, errors) @@ -77,17 +80,16 @@ private class ListProperty(delegate: StandardProperty) : Requi override fun mapValid(mappedTypeName: String, convert: (List) -> Validated): Configuration.Property.Definition.Required = ListMappingProperty(this, mappedTypeName, convert) - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue { - + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue { if (isSensitive) { return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue) } return when { delegate.schema != null -> { - val elementsDescription = valueIn(configuration).asSequence().map { it as ConfigObject }.map(ConfigObject::toConfig).map { delegate.schema.describe(it, serialiseValue) }.toList() + val elementsDescription = valueIn(configuration, options).asSequence().map { it as ConfigObject }.map(ConfigObject::toConfig).map { delegate.schema.describe(it, serialiseValue, options) }.toList() ConfigValueFactory.fromIterable(elementsDescription) } - else -> valueDescription(valueIn(configuration), serialiseValue) + else -> valueDescription(valueIn(configuration, options), serialiseValue) } } @@ -106,16 +108,17 @@ private class OptionalPropertyWithDefault(delegate: Configuration.Property override val typeName: String = delegate.typeName.removeSuffix("?") - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue? = delegate.describe(configuration, serialiseValue) ?: valueDescription(if (isSensitive) Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER else defaultValue, serialiseValue) + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue? = delegate.describe(configuration, serialiseValue, options) ?: valueDescription(if (isSensitive) Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER else defaultValue, serialiseValue) - override fun valueIn(configuration: Config): TYPE = delegate.valueIn(configuration) ?: defaultValue + override fun valueIn(configuration: Config, options: Configuration.Options): TYPE = delegate.valueIn(configuration, options) ?: defaultValue - override fun validate(target: Config, options: Configuration.Validation.Options): Valid = delegate.validate(target, options) + override fun validate(target: Config, options: Configuration.Options): Valid = delegate.validate(target, options) } -private class FunctionalProperty(delegate: Configuration.Property.Definition.Standard, private val mappedTypeName: String, internal val extractListValue: (Config, String) -> List, private val convert: (TYPE) -> Valid) : RequiredDelegatedProperty>(delegate), Configuration.Property.Definition.Standard { +private class FunctionalProperty(delegate: Configuration.Property.Definition.Standard, private val mappedTypeName: String, internal val extractListValue: ValueSelector>, private val convert: (TYPE) -> Valid) + : RequiredDelegatedProperty>(delegate), Configuration.Property.Definition.Standard { - override fun valueIn(configuration: Config) = convert.invoke(delegate.valueIn(configuration)).value() + override fun valueIn(configuration: Config, options: Configuration.Options) = convert.invoke(delegate.valueIn(configuration, options)).value() override val typeName: String = if (super.typeName == "#$mappedTypeName") super.typeName else "$mappedTypeName(${super.typeName})" @@ -123,29 +126,31 @@ private class FunctionalProperty(delegate: Configuration.Property. override fun list(): Configuration.Property.Definition.RequiredList = FunctionalListProperty(this) - override fun validate(target: Config, options: Configuration.Validation.Options): Valid { - + override fun validate(target: Config, options: Configuration.Options): Valid { val errors = mutableSetOf() errors += delegate.validate(target, options).errors if (errors.isEmpty()) { - errors += convert.invoke(delegate.valueIn(target)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors + errors += convert.invoke(delegate.valueIn(target, options)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors } return Validated.withResult(target, errors) } - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue) = delegate.describe(configuration, serialiseValue) + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options) = delegate.describe(configuration, serialiseValue, options) } private class FunctionalListProperty(delegate: FunctionalProperty) : RequiredDelegatedProperty, FunctionalProperty>(delegate), Configuration.Property.Definition.RequiredList { override val typeName: String = "List<${super.typeName}>" - override fun valueIn(configuration: Config): List = delegate.extractListValue.invoke(configuration, key).asSequence().map { configObject(key to ConfigValueFactory.fromAnyRef(it)) }.map(ConfigObject::toConfig).map(delegate::valueIn).toList() - - override fun validate(target: Config, options: Configuration.Validation.Options): Valid { + override fun valueIn(configuration: Config, options: Configuration.Options): List = delegate.extractListValue.invoke(configuration, key, options).asSequence() + .map { configObject(key to ConfigValueFactory.fromAnyRef(it)) } + .map(ConfigObject::toConfig) + .map { delegate.valueIn(it, options) } + .toList() + override fun validate(target: Config, options: Configuration.Options): Valid { val list = try { - delegate.extractListValue.invoke(target, key) + delegate.extractListValue.invoke(target, key, options) } catch (e: ConfigException) { if (isErrorExpected(e)) { return invalid(e.toValidationError(key, typeName)) @@ -153,7 +158,11 @@ private class FunctionalListProperty(delegate: FunctionalProperty delegate.validate(value.toConfig(), options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } }.fold(emptyList()) { one, other -> one + other }.toSet() + val errors = list.asSequence() + .map { configObject(key to ConfigValueFactory.fromAnyRef(it)) } + .mapIndexed { index, value -> delegate.validate(value.toConfig(), options).errors.map { error -> error.withContainingPath(*error.containingPath(index).toTypedArray()) } } + .fold(emptyList()) { one, other -> one + other } + .toSet() return Validated.withResult(target, errors) } @@ -165,12 +174,11 @@ private class FunctionalListProperty(delegate: FunctionalProperty ConfigValue): ConfigValue { - + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue { if (isSensitive) { return valueDescription(Configuration.Property.Definition.SENSITIVE_DATA_PLACEHOLDER, serialiseValue) } - return delegate.schema?.let { schema -> valueDescription(valueIn(configuration).asSequence().map { element -> valueDescription(element, serialiseValue) }.map { it as ConfigObject }.map(ConfigObject::toConfig).map { schema.describe(it, serialiseValue) }.toList(), serialiseValue) } ?: valueDescription(valueIn(configuration), serialiseValue) + return delegate.schema?.let { schema -> valueDescription(valueIn(configuration, options).asSequence() .map { element -> valueDescription(element, serialiseValue) } .map { it as ConfigObject } .map(ConfigObject::toConfig) .map { schema.describe(it, serialiseValue, options) } .toList(), serialiseValue) } ?: valueDescription(valueIn(configuration, options), serialiseValue) } override fun mapValid(mappedTypeName: String, convert: (List) -> Validated): Configuration.Property.Definition.Required = ListMappingProperty(this, mappedTypeName, convert) @@ -187,18 +195,16 @@ private class OptionalDelegatedProperty(private val delegate: Configuratio override val typeName: String = "${delegate.typeName}?" - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue) = if (isSpecifiedBy(configuration)) delegate.describe(configuration, serialiseValue) else null - - override fun valueIn(configuration: Config): TYPE? { + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options) = if (isSpecifiedBy(configuration)) delegate.describe(configuration, serialiseValue, options) else null + override fun valueIn(configuration: Config, options: Configuration.Options): TYPE? { return when { - isSpecifiedBy(configuration) -> delegate.valueIn(configuration) + isSpecifiedBy(configuration) -> delegate.valueIn(configuration, options) else -> null } } - override fun validate(target: Config, options: Configuration.Validation.Options): Valid { - + override fun validate(target: Config, options: Configuration.Options): Valid { val result = delegate.validate(target, options) val errors = result.errors val missingValueError = errors.asSequence().filterIsInstance().filter { it.pathAsString == key }.singleOrNull() @@ -221,18 +227,17 @@ private abstract class RequiredDelegatedProperty(private val delegate: Configuration.Property.Definition.RequiredList, private val mappedTypeName: String, private val convert: (List) -> Validated) : Configuration.Property.Definition.Required { - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue? = delegate.describe(configuration, serialiseValue) + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue? = delegate.describe(configuration, serialiseValue, options) - override fun valueIn(configuration: Config) = convert.invoke(delegate.valueIn(configuration)).value() + override fun valueIn(configuration: Config, options: Configuration.Options) = convert.invoke(delegate.valueIn(configuration, options)).value() override fun optional(): Configuration.Property.Definition.Optional = OptionalDelegatedProperty(this) - override fun validate(target: Config, options: Configuration.Validation.Options): Validated { - + override fun validate(target: Config, options: Configuration.Options): Validated { val errors = mutableSetOf() errors += delegate.validate(target, options).errors if (errors.isEmpty()) { - errors += convert.invoke(delegate.valueIn(target)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors + errors += convert.invoke(delegate.valueIn(target, options)).mapErrors { error -> error.with(delegate.key, mappedTypeName) }.errors } return Validated.withResult(target, errors) } @@ -248,7 +253,6 @@ private class ListMappingProperty(private val delegate: Configurat } fun ConfigException.toValidationError(keyName: String? = null, typeName: String): Configuration.Validation.Error { - val toError = when (this) { is ConfigException.Missing -> Configuration.Validation.Error.MissingValue.Companion::of is ConfigException.WrongType -> Configuration.Validation.Error.WrongType.Companion::of @@ -260,10 +264,9 @@ fun ConfigException.toValidationError(keyName: String? = null, typeName: String) return toError.invoke(message!!, keyName, typeName, emptyList()) } -private fun Configuration.Property.Definition<*>.errorsWhenExtractingValue(target: Config): Set { - +private fun Configuration.Property.Definition<*>.errorsWhenExtractingValue(target: Config, options: Configuration.Options): Set { try { - valueIn(target) + valueIn(target, options) return emptySet() } catch (exception: ConfigException) { if (isErrorExpected(exception)) { diff --git a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Schema.kt b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Schema.kt index 348714fef5..48b3fa78d0 100644 --- a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Schema.kt +++ b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Schema.kt @@ -16,7 +16,7 @@ internal class Schema(override val name: String?, unorderedProperties: Iterable< } } - override fun validate(target: Config, options: Configuration.Validation.Options): Valid { + override fun validate(target: Config, options: Configuration.Options): Valid { val propertyErrors = properties.flatMap { property -> property.validate(target, options).errors @@ -47,9 +47,9 @@ internal class Schema(override val name: String?, unorderedProperties: Iterable< return description.toString() } - override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue): ConfigValue { + override fun describe(configuration: Config, serialiseValue: (Any?) -> ConfigValue, options: Configuration.Options): ConfigValue { - return properties.asSequence().map { it.key to it.describe(configuration, serialiseValue) }.filter { it.second != null }.fold(configObject()) { config, (key, value) -> config.withValue(key, value) } + return properties.asSequence().map { it.key to it.describe(configuration, serialiseValue, options) }.filter { it.second != null }.fold(configObject()) { config, (key, value) -> config.withValue(key, value) } } override fun equals(other: Any?): Boolean { diff --git a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Utils.kt b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Utils.kt index e7455a38a7..e2ba999108 100644 --- a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Utils.kt +++ b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/Utils.kt @@ -21,7 +21,11 @@ inline fun Configuration.Property.Definition.RequiredList inline fun Configuration.Property.Definition.RequiredList.map(noinline convert: (List) -> MAPPED): Configuration.Property.Definition.Required = map(MAPPED::class.java.simpleName, convert) -operator fun Config.get(property: Configuration.Property.Definition): TYPE = property.valueIn(this) +fun Config.withOptions(options: Configuration.Options) = ConfigurationWithOptions(this, options) + +data class ConfigurationWithOptions(private val config: Config, private val options: Configuration.Options) { + operator fun get(property: Configuration.Value.Extractor): TYPE = property.valueIn(config, options) +} inline fun Configuration.Specification<*>.nested(specification: Configuration.Specification, key: String? = null, sensitive: Boolean = false): PropertyDelegate.Standard = nestedObject(schema = specification, key = key, sensitive = sensitive).map(ConfigObject::toConfig).mapValid { value -> specification.parse(value) } @@ -66,15 +70,6 @@ internal typealias Valid = Validated valid(target: TYPE) = Validated.valid(target) -/** - * Value extracted from a configuration file is a function of the actual value specified and configuration options. - * E.g. password value may be stored in the encrypted form rather than in a clear text. - */ -data class ConfigurationWithOptions(private val config: Config, private val options: Configuration.Validation.Options) { - operator fun get(property: Configuration.Property.Definition): TYPE = property.valueIn(config) - operator fun get(property: Configuration.Value.Extractor): TYPE = property.valueIn(config) -} - /** * Helper interface to mark objects that will have [ConfigurationWithOptions] in them. */ diff --git a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/versioned/VersionExtractor.kt b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/versioned/VersionExtractor.kt index 55e34d6467..aefe57d132 100644 --- a/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/versioned/VersionExtractor.kt +++ b/common/configuration-parsing/src/main/kotlin/net/corda/common/configuration/parsing/internal/versioned/VersionExtractor.kt @@ -6,21 +6,17 @@ import net.corda.common.configuration.parsing.internal.Valid import net.corda.common.configuration.parsing.internal.valid internal class VersionExtractor(versionPath: String, versionDefaultValue: Int) : Configuration.Version.Extractor { - private val containingPath = versionPath.split(".").let { if (it.size > 1) it.subList(0, it.size - 1) else null } private val key = versionPath.split(".").last() private val spec = Spec(key, versionDefaultValue, containingPath?.joinToString(".")) - override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid { - + override fun parse(configuration: Config, options: Configuration.Options): Valid { return spec.parse(configuration) } private class Spec(key: String, versionDefaultValue: Int, prefix: String?) : Configuration.Specification("Version", prefix) { - private val version by int(key = key).optional().withDefaultValue(versionDefaultValue) - - override fun parseValid(configuration: Config) = valid(version.valueIn(configuration)) + override fun parseValid(configuration: Config, options: Configuration.Options) = valid(version.valueIn(configuration, options)) } } \ No newline at end of file diff --git a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyTest.kt b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyTest.kt index 61dbd39551..75a08a2f59 100644 --- a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyTest.kt +++ b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyTest.kt @@ -21,8 +21,8 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThat(property.valueIn(configuration)).isEqualTo(value) - assertThat(configuration[property]).isEqualTo(value) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value) + assertThat(configuration.withOptions(Configuration.Options.defaults)[property]).isEqualTo(value) } @Test(timeout=300_000) @@ -38,7 +38,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThatThrownBy { property.valueIn(configuration) }.isInstanceOf(ConfigException.WrongType::class.java) + assertThatThrownBy { property.valueIn(configuration, Configuration.Options.defaults) }.isInstanceOf(ConfigException.WrongType::class.java) } @Test(timeout=300_000) @@ -54,7 +54,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThat(property.valueIn(configuration)).isEqualTo(value) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value) } @Test(timeout=300_000) @@ -70,7 +70,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThat(property.valueIn(configuration)).isEqualTo(value.max()) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value.max()) } @Test(timeout=300_000) @@ -85,7 +85,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse() - assertThat(property.valueIn(configuration)).isEqualTo(null) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(null) } @Test(timeout=300_000) @@ -101,7 +101,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isTrue() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThat(property.valueIn(configuration)).isEqualTo(value.max()) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value.max()) } @Test(timeout=300_000) @@ -116,7 +116,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse() - assertThat(property.valueIn(configuration)).isEqualTo(null) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(null) } @Test(timeout=300_000) @@ -132,7 +132,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThat(property.valueIn(configuration)).isEqualTo(value) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value) } @Test(timeout=300_000) @@ -147,7 +147,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse() - assertThat(property.valueIn(configuration)).isNull() + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isNull() } @@ -164,7 +164,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse() - assertThat(property.valueIn(configuration)).isEqualTo(defaultValue) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(defaultValue) } @Test(timeout=300_000) @@ -179,7 +179,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isTrue() assertThat(property.isSpecifiedBy(configuration)).isFalse() - assertThatThrownBy { property.valueIn(configuration) }.isInstanceOf(ConfigException.Missing::class.java) + assertThatThrownBy { property.valueIn(configuration, Configuration.Options.defaults) }.isInstanceOf(ConfigException.Missing::class.java) } @Test(timeout=300_000) @@ -195,7 +195,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThat(property.valueIn(configuration)).isEqualTo(value) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(value) } @Test(timeout=300_000) @@ -211,7 +211,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isTrue() - assertThatThrownBy { property.valueIn(configuration) }.isInstanceOf(ConfigException.WrongType::class.java) + assertThatThrownBy { property.valueIn(configuration, Configuration.Options.defaults) }.isInstanceOf(ConfigException.WrongType::class.java) } @Test(timeout=300_000) @@ -226,7 +226,7 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse() - assertThat(property.valueIn(configuration)).isNull() + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isNull() } @Test(timeout=300_000) @@ -242,6 +242,6 @@ class PropertyTest { assertThat(property.key).isEqualTo(key) assertThat(property.isMandatory).isFalse() assertThat(property.isSpecifiedBy(configuration)).isFalse() - assertThat(property.valueIn(configuration)).isEqualTo(defaultValue) + assertThat(property.valueIn(configuration, Configuration.Options.defaults)).isEqualTo(defaultValue) } } \ No newline at end of file diff --git a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyValidationTest.kt b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyValidationTest.kt index 3c03a74c33..0c748f2e70 100644 --- a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyValidationTest.kt +++ b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/PropertyValidationTest.kt @@ -15,7 +15,7 @@ class PropertyValidationTest { val property = Configuration.Property.Definition.long(key) - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> @@ -34,7 +34,7 @@ class PropertyValidationTest { val property = Configuration.Property.Definition.long(key) - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> @@ -53,7 +53,7 @@ class PropertyValidationTest { val property = Configuration.Property.Definition.long(key).list() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> @@ -72,7 +72,7 @@ class PropertyValidationTest { val property = Configuration.Property.Definition.long(key).list() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> @@ -94,7 +94,7 @@ class PropertyValidationTest { val property = Configuration.Property.Definition.long(key).list().mapValid(::parseMax) - assertThat(property.validate(configuration).errors).isEmpty() + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).isEmpty() } @Test(timeout=300_000) @@ -114,7 +114,7 @@ class PropertyValidationTest { val property = Configuration.Property.Definition.long(key).list().mapValid(::parseMax) - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.BadValue::class.java) { error -> @@ -134,7 +134,7 @@ class PropertyValidationTest { val configuration = configObject(key to false).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> @@ -154,7 +154,7 @@ class PropertyValidationTest { val configuration = configObject(key to 1.2).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> @@ -174,7 +174,7 @@ class PropertyValidationTest { val configuration = configObject(key to 1).toConfig() - assertThat(property.validate(configuration).isValid).isTrue() + assertThat(property.validate(configuration, Configuration.Options.defaults).isValid).isTrue() } @Test(timeout=300_000) @@ -186,7 +186,7 @@ class PropertyValidationTest { val configuration = configObject(key to listOf(false, true)).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> @@ -206,7 +206,7 @@ class PropertyValidationTest { val configuration = configObject(key to listOf(1, 2, 3)).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> @@ -226,7 +226,7 @@ class PropertyValidationTest { val configuration = configObject(key to 1).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> @@ -249,7 +249,7 @@ class PropertyValidationTest { val configuration = configObject(key to configObject(nestedKey to false)).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.WrongType::class.java) { error -> @@ -272,7 +272,7 @@ class PropertyValidationTest { val configuration = configObject(key to configObject()).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> @@ -295,7 +295,7 @@ class PropertyValidationTest { val configuration = configObject(key to configObject(nestedKey to null)).toConfig() - assertThat(property.validate(configuration).errors).satisfies { errors -> + assertThat(property.validate(configuration, Configuration.Options.defaults).errors).satisfies { errors -> assertThat(errors).hasSize(1) assertThat(errors.first()).isInstanceOfSatisfying(Configuration.Validation.Error.MissingValue::class.java) { error -> @@ -317,7 +317,7 @@ class PropertyValidationTest { val configuration = configObject(key to configObject(nestedKey to false)).toConfig() - assertThat(property.validate(configuration).isValid).isTrue() + assertThat(property.validate(configuration, Configuration.Options.defaults).isValid).isTrue() } @Test(timeout=300_000) @@ -333,7 +333,7 @@ class PropertyValidationTest { val configuration = configObject(key to value).toConfig() - assertThat(property.validate(configuration).isValid).isTrue() + assertThat(property.validate(configuration, Configuration.Options.defaults).isValid).isTrue() } @Test(timeout=300_000) @@ -350,7 +350,7 @@ class PropertyValidationTest { val configuration = configObject(key to value).toConfig() - val result = property.validate(configuration) + val result = property.validate(configuration, Configuration.Options.defaults) assertThat(result.errors).satisfies { errors -> diff --git a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SchemaTest.kt b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SchemaTest.kt index f6393bd39b..2ad58808f2 100644 --- a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SchemaTest.kt +++ b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SchemaTest.kt @@ -29,7 +29,7 @@ class SchemaTest { val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), double("prop5")) } val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } - val result = barConfigSchema.validate(configuration) + val result = barConfigSchema.validate(configuration, Configuration.Options.defaults) println(barConfigSchema.description()) assertThat(result.isValid).isTrue() @@ -59,17 +59,17 @@ class SchemaTest { val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) } val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } - val strictErrors = barConfigSchema.validate(configuration, Configuration.Validation.Options(strict = true)).errors + val strictErrors = barConfigSchema.validate(configuration, Configuration.Options(strict = true)).errors assertThat(strictErrors).hasSize(2) assertThat(strictErrors.filter { error -> error.keyName == "prop4" }).hasSize(1) assertThat(strictErrors.filter { error -> error.keyName == "prop6" }).hasSize(1) - val errors = barConfigSchema.validate(configuration, Configuration.Validation.Options(strict = false)).errors + val errors = barConfigSchema.validate(configuration, Configuration.Options(strict = false)).errors assertThat(errors).isEmpty() - val errorsWithDefaultOptions = barConfigSchema.validate(configuration).errors + val errorsWithDefaultOptions = barConfigSchema.validate(configuration, Configuration.Options.defaults).errors assertThat(errorsWithDefaultOptions).isEmpty() } @@ -98,7 +98,7 @@ class SchemaTest { val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) } val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } - val result = barConfigSchema.validate(configuration) + val result = barConfigSchema.validate(configuration, Configuration.Options.defaults) assertThat(result.isValid).isTrue() } @@ -127,7 +127,7 @@ class SchemaTest { val fooConfigSchema = Configuration.Schema.withProperties { setOf(boolean("prop4"), double("prop5")) } val barConfigSchema = Configuration.Schema.withProperties { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } - val errors = barConfigSchema.validate(configuration).errors + val errors = barConfigSchema.validate(configuration, Configuration.Options.defaults).errors errors.forEach(::println) assertThat(errors).hasSize(2) @@ -154,7 +154,7 @@ class SchemaTest { val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), string("prop5", sensitive = true)) } val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema)) } - val printedConfiguration = barConfigSchema.describe(configuration) + val printedConfiguration = barConfigSchema.describe(configuration, options = Configuration.Options.defaults) val description = printedConfiguration.serialize().also { println(it) } @@ -185,7 +185,7 @@ class SchemaTest { val fooConfigSchema = Configuration.Schema.withProperties(name = "Foo") { setOf(boolean("prop4"), string("prop5", sensitive = true)) } val barConfigSchema = Configuration.Schema.withProperties(name = "Bar") { setOf(string(prop1), long(prop2), nestedObject("prop3", fooConfigSchema).list()) } - val printedConfiguration = barConfigSchema.describe(configuration) + val printedConfiguration = barConfigSchema.describe(configuration, options = Configuration.Options.defaults) val description = printedConfiguration.serialize().also { println(it) } diff --git a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SpecificationTest.kt b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SpecificationTest.kt index a78ef5ee59..ace4e2bbe7 100644 --- a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SpecificationTest.kt +++ b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/SpecificationTest.kt @@ -16,7 +16,7 @@ class SpecificationTest { val principal by string().mapValid(::parseAddress) val admin by string().mapValid(::parseAddress) - override fun parseValid(configuration: Config) = valid(Addresses(configuration[principal], configuration[admin])) + override fun parseValid(configuration: Config, options: Configuration.Options) = configuration.withOptions(options).let { valid(Addresses(it[principal], it[admin])) } private fun parseAddress(rawValue: String): Valid
{ @@ -27,7 +27,7 @@ class SpecificationTest { val useSsl by boolean() val addresses by nested(AddressesSpec) - override fun parseValid(configuration: Config) = valid(RpcSettingsImpl(configuration[addresses], configuration[useSsl])) + override fun parseValid(configuration: Config, options: Configuration.Options) = configuration.withOptions(options).let { valid(RpcSettingsImpl(it[addresses], it[useSsl])) } } @Test(timeout=300_000) @@ -60,9 +60,9 @@ class SpecificationTest { private val maxElement by long("elements").list().map { elements -> elements.max() } - override fun parseValid(configuration: Config): Valid { - - return valid(AtomicLong(configuration[maxElement]!!)) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(AtomicLong(config[maxElement]!!)) } } @@ -111,9 +111,9 @@ class SpecificationTest { private val maxElement by long("elements").list().mapValid(::parseMax) - override fun parseValid(configuration: Config): Valid { - - return valid(AtomicLong(configuration[maxElement])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(AtomicLong(config[maxElement])) } } @@ -159,7 +159,7 @@ class SpecificationTest { @Suppress("unused") val myProp by string().list().optional() - override fun parseValid(configuration: Config) = valid(configuration[myProp]) + override fun parseValid(configuration: Config, options: Configuration.Options) = configuration.withOptions(options).let { valid(it[myProp]) } } assertThat(spec.properties).hasSize(1) diff --git a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/TestUtils.kt b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/TestUtils.kt index bf2c2f92bf..5e604fd765 100644 --- a/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/TestUtils.kt +++ b/common/configuration-parsing/src/test/kotlin/net/corda/common/configuration/parsing/internal/TestUtils.kt @@ -15,5 +15,5 @@ internal fun extractValueWithErrors(errors: Set extractValue(value: Valid) = object : Configuration.Value.Parser { - override fun parse(configuration: Config, options: Configuration.Validation.Options): Valid = value + override fun parse(configuration: Config, options: Configuration.Options): Valid = value } \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkParameterOverridesSpec.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkParameterOverridesSpec.kt index c4f159528f..ba15d49f9e 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkParameterOverridesSpec.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/network/NetworkParameterOverridesSpec.kt @@ -2,9 +2,9 @@ package net.corda.nodeapi.internal.network import com.typesafe.config.Config import net.corda.common.configuration.parsing.internal.Configuration -import net.corda.common.configuration.parsing.internal.get import net.corda.common.configuration.parsing.internal.mapValid import net.corda.common.configuration.parsing.internal.nested +import net.corda.common.configuration.parsing.internal.withOptions import net.corda.common.validation.internal.Validated import net.corda.core.internal.noPackageOverlap import net.corda.core.internal.requirePackageValid @@ -17,7 +17,7 @@ import java.security.KeyStoreException typealias Valid = Validated -fun Config.parseAsNetworkParametersConfiguration(options: Configuration.Validation.Options = Configuration.Validation.Options(strict = false)): +fun Config.parseAsNetworkParametersConfiguration(options: Configuration.Options = Configuration.Options.defaults): Valid = NetworkParameterOverridesSpec.parse(this, options) internal fun badValue(msg: String): Valid = Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of(msg)).toSet()) @@ -36,11 +36,12 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification { - val suppliedKeystorePath = configuration[keystore] - val keystorePassword = configuration[keystorePassword] + override fun parseValid(configuration: Config, options: Configuration.Options): Validated { + val config = configuration.withOptions(options) + val suppliedKeystorePath = config[keystore] + val keystorePassword = config[keystorePassword] return try { - val javaPackageName = configuration[packageName] + val javaPackageName = config[packageName] val absoluteKeystorePath = if (suppliedKeystorePath.isAbsolute) { suppliedKeystorePath } else { @@ -49,10 +50,10 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification { - val packageOwnership = configuration[packageOwnership] + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + val packageOwnership = config[packageOwnership] if (packageOwnership != null && !noPackageOverlap(packageOwnership.map { it.javaPackageName })) { return Validated.invalid(sequenceOf(Configuration.Validation.Error.BadValue.of( "Package namespaces must not overlap", @@ -89,11 +91,11 @@ internal object NetworkParameterOverridesSpec : Configuration.Specification { - val option = Configuration.Validation.Options(strict = unknownConfigKeysPolicy == UnknownConfigKeysPolicy.FAIL) + val option = Configuration.Options(strict = unknownConfigKeysPolicy == UnknownConfigKeysPolicy.FAIL) return configuration.parseAsNodeConfiguration(option) } diff --git a/node/src/main/kotlin/net/corda/node/internal/subcommands/ValidateConfigurationCli.kt b/node/src/main/kotlin/net/corda/node/internal/subcommands/ValidateConfigurationCli.kt index 00bbdb1ffc..1024f10cff 100644 --- a/node/src/main/kotlin/net/corda/node/internal/subcommands/ValidateConfigurationCli.kt +++ b/node/src/main/kotlin/net/corda/node/internal/subcommands/ValidateConfigurationCli.kt @@ -26,7 +26,7 @@ internal class ValidateConfigurationCli : CliWrapperBase("validate-configuration return "for path: \"$pathAsString\": $message" } - internal fun logRawConfig(config: Config) = logger.info("Actual configuration:\n${V1NodeConfigurationSpec.describe(config, Any?::toConfigValue).render(configRenderingOptions)}") + internal fun logRawConfig(config: Config) = logger.info("Actual configuration:\n${V1NodeConfigurationSpec.describe(config, Any?::toConfigValue, Configuration.Options()).render(configRenderingOptions)}") } @Mixin diff --git a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt index 080e4e200c..b2dc5dd773 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt @@ -107,7 +107,7 @@ object ConfigHelper { newKey.let { key -> val cfg = ConfigFactory.parseMap(mapOf(key to it.value)) - val result = V1NodeConfigurationSpec.validate(cfg, Configuration.Validation.Options(strict = true)) + val result = V1NodeConfigurationSpec.validate(cfg, Configuration.Options(strict = true)) val isInvalidProperty = result.errors.any { err -> err is Configuration.Validation.Error.Unknown } if (isInvalidProperty) { diff --git a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt index 010e40007f..824a019df2 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt @@ -217,7 +217,7 @@ data class FlowTimeoutConfiguration( internal typealias Valid = Validated -fun Config.parseAsNodeConfiguration(options: Configuration.Validation.Options = Configuration.Validation.Options(strict = true)): Valid = V1NodeConfigurationSpec.parse(this, options) +fun Config.parseAsNodeConfiguration(options: Configuration.Options = Configuration.Options(strict = true)): Valid = V1NodeConfigurationSpec.parse(this, options) data class NodeH2Settings( val address: NetworkHostAndPort? diff --git a/node/src/main/kotlin/net/corda/node/services/config/schema/v1/ConfigSections.kt b/node/src/main/kotlin/net/corda/node/services/config/schema/v1/ConfigSections.kt index 6e516a6bad..0132ecee53 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/schema/v1/ConfigSections.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/schema/v1/ConfigSections.kt @@ -5,11 +5,11 @@ package net.corda.node.services.config.schema.v1 import com.typesafe.config.Config import com.typesafe.config.ConfigObject import net.corda.common.configuration.parsing.internal.Configuration -import net.corda.common.configuration.parsing.internal.get import net.corda.common.configuration.parsing.internal.listOrEmpty import net.corda.common.configuration.parsing.internal.map import net.corda.common.configuration.parsing.internal.mapValid import net.corda.common.configuration.parsing.internal.nested +import net.corda.common.configuration.parsing.internal.withOptions import net.corda.common.validation.internal.Validated.Companion.invalid import net.corda.common.validation.internal.Validated.Companion.valid import net.corda.core.context.AuthServiceId @@ -55,11 +55,12 @@ internal object UserSpec : Configuration.Specification("User") { private val password by string(sensitive = true) private val permissions by string().listOrEmpty() - override fun parseValid(configuration: Config): Valid { - val username = configuration[username] ?: configuration[user] + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + val username = config[username] ?: config[user] return when (username) { null -> invalid(Configuration.Validation.Error.MissingValue.forKey("username")) - else -> valid(User(username, configuration[password], configuration[permissions].toSet())) + else -> valid(User(username, config[password], config[permissions].toSet())) } } } @@ -72,11 +73,12 @@ internal object SecurityConfigurationSpec : Configuration.Specification { - val type = configuration[type] - val passwordEncryption = configuration[passwordEncryption] - val connection = configuration[connection] - val users = configuration[users] + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + val type = config[type] + val passwordEncryption = config[passwordEncryption] + val connection = config[connection] + val users = config[users] return when { type == AuthDataSourceType.INMEMORY && (users == null || connection != null) -> badValue("\"INMEMORY\" data source type requires \"users\" and cannot specify \"connection\"") @@ -91,15 +93,17 @@ internal object SecurityConfigurationSpec : Configuration.Specification if (value >= 0) validValue(value) else badValue("cannot be less than 0'") } private val maxEntries by long().mapValid { value -> if (value >= 0) validValue(value) else badValue("cannot be less than 0'") } - override fun parseValid(configuration: Config): Valid { - return valid(SecurityConfiguration.AuthService.Options.Cache(configuration[expireAfterSecs], configuration[maxEntries])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(SecurityConfiguration.AuthService.Options.Cache(config[expireAfterSecs], config[maxEntries])) } } private val cache by nested(CacheSpec).optional() - override fun parseValid(configuration: Config): Valid { - return valid(SecurityConfiguration.AuthService.Options(configuration[cache])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(SecurityConfiguration.AuthService.Options(config[cache])) } } @@ -107,21 +111,23 @@ internal object SecurityConfigurationSpec : Configuration.Specification { - val dataSource = configuration[dataSource] - val id = configuration[id] ?: defaultAuthServiceId(dataSource.type) - val options = configuration[options] + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + val dataSource = config[dataSource] + val id = config[id] ?: defaultAuthServiceId(dataSource.type) + val authServiceOptions = config[this.options] return when { - dataSource.type == AuthDataSourceType.INMEMORY && options?.cache != null -> badValue("no cache supported for \"INMEMORY\" data provider") - else -> valid(SecurityConfiguration.AuthService(dataSource, id, options)) + dataSource.type == AuthDataSourceType.INMEMORY && authServiceOptions?.cache != null -> badValue("no cache supported for \"INMEMORY\" data provider") + else -> valid(SecurityConfiguration.AuthService(dataSource, id, authServiceOptions)) } } } private val authService by nested(AuthServiceSpec) - override fun parseValid(configuration: Config): Valid { - return valid(SecurityConfiguration(configuration[authService])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(SecurityConfiguration(config[authService])) } } @@ -134,13 +140,15 @@ internal object DevModeOptionsSpec : Configuration.Specification private val bootstrapSource by string().optional() private val cordaSource by string().list() - override fun parseValid(configuration: Config): Valid { - return valid(DJVMOptions(configuration[bootstrapSource], configuration[cordaSource])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(DJVMOptions(config[bootstrapSource], config[cordaSource])) } } - override fun parseValid(configuration: Config): Valid { - return valid(DevModeOptions(configuration[disableCheckpointChecker], configuration[allowCompatibilityZone], configuration[djvm])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(DevModeOptions(config[disableCheckpointChecker], config[allowCompatibilityZone], config[djvm])) } } @@ -151,8 +159,9 @@ internal object NetworkServicesConfigSpec : Configuration.Specification { - return valid(NetworkServicesConfig(configuration[doormanURL], configuration[networkMapURL], configuration[pnm], configuration[inferred], configuration[csrToken])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(NetworkServicesConfig(config[doormanURL], config[networkMapURL], config[pnm], config[inferred], config[csrToken])) } } @@ -160,22 +169,24 @@ internal object NetworkParameterAcceptanceSettingsSpec : Configuration.Specification("NetworkParameterAcceptanceSettings") { private val autoAcceptEnabled by boolean().optional().withDefaultValue(true) private val excludedAutoAcceptableParameters by string().listOrEmpty() - override fun parseValid(configuration: Config): Valid { - return valid(NetworkParameterAcceptanceSettings(configuration[autoAcceptEnabled], - configuration[excludedAutoAcceptableParameters].toSet()) + override fun parseValid(configuration: Config, options: Configuration.Options): + Valid { + val config = configuration.withOptions(options) + return valid(NetworkParameterAcceptanceSettings(config[autoAcceptEnabled], + config[excludedAutoAcceptableParameters].toSet()) ) } } - @Suppress("DEPRECATION") internal object CertChainPolicyConfigSpec : Configuration.Specification("CertChainPolicyConfig") { private val role by string() private val policy by enum(CertChainPolicyType::class) private val trustedAliases by string().listOrEmpty() - override fun parseValid(configuration: Config): Valid { - return valid(CertChainPolicyConfig(configuration[role], configuration[policy], configuration[trustedAliases].toSet())) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(CertChainPolicyConfig(config[role], config[policy], config[trustedAliases].toSet())) } } @@ -184,8 +195,9 @@ internal object FlowTimeoutConfigurationSpec : Configuration.Specification { - return valid(FlowTimeoutConfiguration(configuration[timeout], configuration[maxRestartCount], configuration[backoffBase])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(FlowTimeoutConfiguration(config[timeout], config[maxRestartCount], config[backoffBase])) } } @@ -198,8 +210,9 @@ internal object NotaryConfigSpec : Configuration.Specification("No private val raft by nested(RaftConfigSpec).optional() private val bftSMaRt by nested(BFTSmartConfigSpec).optional() - override fun parseValid(configuration: Config): Valid { - return valid(NotaryConfig(configuration[validating], configuration[serviceLegalName], configuration[className], configuration[etaMessageThresholdSeconds], configuration[extraConfig], configuration[raft], configuration[bftSMaRt])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(NotaryConfig(config[validating], config[serviceLegalName], config[className], config[etaMessageThresholdSeconds], config[extraConfig], config[raft], config[bftSMaRt])) } } @@ -207,8 +220,9 @@ internal object RaftConfigSpec : Configuration.Specification("RaftCo private val nodeAddress by string().mapValid(::toNetworkHostAndPort) private val clusterAddresses by string().mapValid(::toNetworkHostAndPort).listOrEmpty() - override fun parseValid(configuration: Config): Valid { - return valid(RaftConfig(configuration[nodeAddress], configuration[clusterAddresses])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(RaftConfig(config[nodeAddress], config[clusterAddresses])) } } @@ -218,19 +232,20 @@ internal object BFTSmartConfigSpec : Configuration.Specification private val debug by boolean().optional().withDefaultValue(false) private val exposeRaces by boolean().optional().withDefaultValue(false) - override fun parseValid(configuration: Config): Valid { - return valid(BFTSmartConfig(configuration[replicaId], configuration[clusterAddresses], configuration[debug], configuration[exposeRaces])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(BFTSmartConfig(config[replicaId], config[clusterAddresses], config[debug], config[exposeRaces])) } } - internal object NodeRpcSettingsSpec : Configuration.Specification("NodeRpcSettings") { internal object BrokerRpcSslOptionsSpec : Configuration.Specification("BrokerRpcSslOptions") { private val keyStorePath by string().mapValid(::toPath) private val keyStorePassword by string(sensitive = true) - override fun parseValid(configuration: Config): Valid { - return valid(BrokerRpcSslOptions(configuration[keyStorePath], configuration[keyStorePassword])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(BrokerRpcSslOptions(config[keyStorePath], config[keyStorePassword])) } } @@ -240,18 +255,18 @@ internal object NodeRpcSettingsSpec : Configuration.Specification { - return valid(NodeRpcSettings(configuration[address], configuration[adminAddress], configuration[standAloneBroker], configuration[useSsl], configuration[ssl])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(NodeRpcSettings(config[address], config[adminAddress], config[standAloneBroker], config[useSsl], config[ssl])) } } internal object SSHDConfigurationSpec : Configuration.Specification("SSHDConfiguration") { private val port by int() - override fun parseValid(configuration: Config): Valid = attempt { SSHDConfiguration(configuration[port]) } + override fun parseValid(configuration: Config, options: Configuration.Options): Valid = attempt { SSHDConfiguration(configuration.withOptions(options)[port]) } } - internal object DatabaseConfigSpec : Configuration.Specification("DatabaseConfig") { private val initialiseSchema by boolean().optional().withDefaultValue(DatabaseConfig.Defaults.initialiseSchema) private val initialiseAppSchema by enum(SchemaInitializationType::class).optional().withDefaultValue(DatabaseConfig.Defaults.initialiseAppSchema) @@ -259,16 +274,18 @@ internal object DatabaseConfigSpec : Configuration.Specification private val exportHibernateJMXStatistics by boolean().optional().withDefaultValue(DatabaseConfig.Defaults.exportHibernateJMXStatistics) private val mappedSchemaCacheSize by long().optional().withDefaultValue(DatabaseConfig.Defaults.mappedSchemaCacheSize) - override fun parseValid(configuration: Config): Valid { - return valid(DatabaseConfig(configuration[initialiseSchema], configuration[initialiseAppSchema], configuration[transactionIsolationLevel], configuration[exportHibernateJMXStatistics], configuration[mappedSchemaCacheSize])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(DatabaseConfig(config[initialiseSchema], config[initialiseAppSchema], config[transactionIsolationLevel], config[exportHibernateJMXStatistics], config[mappedSchemaCacheSize])) } } internal object NodeH2SettingsSpec : Configuration.Specification("NodeH2Settings") { private val address by string().mapValid(::toNetworkHostAndPort).optional() - override fun parseValid(configuration: Config): Valid { - return valid(NodeH2Settings(configuration[address])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(NodeH2Settings(config[address])) } } @@ -277,14 +294,16 @@ internal object FlowOverridesConfigSpec : Configuration.Specification { - return valid(FlowOverride(configuration[initiator], configuration[responder])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(FlowOverride(config[initiator], config[responder])) } } private val overrides by nested(FlowOverridesConfigSpec.SingleSpec).listOrEmpty() - override fun parseValid(configuration: Config): Valid { - return valid(FlowOverrideConfig(configuration[overrides])) + override fun parseValid(configuration: Config, options: Configuration.Options): Valid { + val config = configuration.withOptions(options) + return valid(FlowOverrideConfig(config[overrides])) } } \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/services/config/schema/v1/V1NodeConfigurationSpec.kt b/node/src/main/kotlin/net/corda/node/services/config/schema/v1/V1NodeConfigurationSpec.kt index 7f7b66bc9f..084faa1545 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/schema/v1/V1NodeConfigurationSpec.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/schema/v1/V1NodeConfigurationSpec.kt @@ -70,67 +70,68 @@ internal object V1NodeConfigurationSpec : Configuration.Specification { + override fun parseValid(configuration: Config, options: Configuration.Options): Validated { + val config = configuration.withOptions(options) - val messagingServerExternal = configuration[messagingServerExternal] ?: Defaults.messagingServerExternal(configuration[messagingServerAddress]) - val database = configuration[database] ?: Defaults.database(configuration[devMode]) - val baseDirectoryPath = configuration[baseDirectory] - val cordappDirectories = configuration[cordappDirectories] ?: Defaults.cordappsDirectories(baseDirectoryPath) + val messagingServerExternal = config[messagingServerExternal] ?: Defaults.messagingServerExternal(config[messagingServerAddress]) + val database = config[database] ?: Defaults.database(config[devMode]) + val baseDirectoryPath = config[baseDirectory] + val cordappDirectories = config[cordappDirectories] ?: Defaults.cordappsDirectories(baseDirectoryPath) val result = try { valid(NodeConfigurationImpl( baseDirectory = baseDirectoryPath, - myLegalName = configuration[myLegalName], - emailAddress = configuration[emailAddress], - p2pAddress = configuration[p2pAddress], - keyStorePassword = configuration[keyStorePassword], - trustStorePassword = configuration[trustStorePassword], - crlCheckSoftFail = configuration[crlCheckSoftFail], - dataSourceProperties = configuration[dataSourceProperties], - rpcUsers = configuration[rpcUsers], - verifierType = configuration[verifierType], - flowTimeout = configuration[flowTimeout], - rpcSettings = configuration[rpcSettings], - messagingServerAddress = configuration[messagingServerAddress], - notary = configuration[notary], - flowOverrides = configuration[flowOverrides], - additionalP2PAddresses = configuration[additionalP2PAddresses], - additionalNodeInfoPollingFrequencyMsec = configuration[additionalNodeInfoPollingFrequencyMsec], - jmxMonitoringHttpPort = configuration[jmxMonitoringHttpPort], - security = configuration[security], - devMode = configuration[devMode], - devModeOptions = configuration[devModeOptions], - compatibilityZoneURL = configuration[compatibilityZoneURL], - networkServices = configuration[networkServices], - certificateChainCheckPolicies = configuration[certificateChainCheckPolicies], + myLegalName = config[myLegalName], + emailAddress = config[emailAddress], + p2pAddress = config[p2pAddress], + keyStorePassword = config[keyStorePassword], + trustStorePassword = config[trustStorePassword], + crlCheckSoftFail = config[crlCheckSoftFail], + dataSourceProperties = config[dataSourceProperties], + rpcUsers = config[rpcUsers], + verifierType = config[verifierType], + flowTimeout = config[flowTimeout], + rpcSettings = config[rpcSettings], + messagingServerAddress = config[messagingServerAddress], + notary = config[notary], + flowOverrides = config[flowOverrides], + additionalP2PAddresses = config[additionalP2PAddresses], + additionalNodeInfoPollingFrequencyMsec = config[additionalNodeInfoPollingFrequencyMsec], + jmxMonitoringHttpPort = config[jmxMonitoringHttpPort], + security = config[security], + devMode = config[devMode], + devModeOptions = config[devModeOptions], + compatibilityZoneURL = config[compatibilityZoneURL], + networkServices = config[networkServices], + certificateChainCheckPolicies = config[certificateChainCheckPolicies], messagingServerExternal = messagingServerExternal, - useTestClock = configuration[useTestClock], - lazyBridgeStart = configuration[lazyBridgeStart], - detectPublicIp = configuration[detectPublicIp], - sshd = configuration[sshd], - localShellAllowExitInSafeMode = configuration[localShellAllowExitInSafeMode], - localShellUnsafe = configuration[localShellUnsafe], + useTestClock = config[useTestClock], + lazyBridgeStart = config[lazyBridgeStart], + detectPublicIp = config[detectPublicIp], + sshd = config[sshd], + localShellAllowExitInSafeMode = config[localShellAllowExitInSafeMode], + localShellUnsafe = config[localShellUnsafe], database = database, - noLocalShell = configuration[noLocalShell], - attachmentCacheBound = configuration[attachmentCacheBound], - extraNetworkMapKeys = configuration[extraNetworkMapKeys], - tlsCertCrlDistPoint = configuration[tlsCertCrlDistPoint], - tlsCertCrlIssuer = configuration[tlsCertCrlIssuer], - h2Settings = configuration[h2Settings], - flowMonitorPeriodMillis = configuration[flowMonitorPeriodMillis], - flowMonitorSuspensionLoggingThresholdMillis = configuration[flowMonitorSuspensionLoggingThresholdMillis], - jmxReporterType = configuration[jmxReporterType], - rpcAddress = configuration[rpcAddress], - transactionCacheSizeMegaBytes = configuration[transactionCacheSizeMegaBytes], - attachmentContentCacheSizeMegaBytes = configuration[attachmentContentCacheSizeMegaBytes], - h2port = configuration[h2port], - jarDirs = configuration[jarDirs], + noLocalShell = config[noLocalShell], + attachmentCacheBound = config[attachmentCacheBound], + extraNetworkMapKeys = config[extraNetworkMapKeys], + tlsCertCrlDistPoint = config[tlsCertCrlDistPoint], + tlsCertCrlIssuer = config[tlsCertCrlIssuer], + h2Settings = config[h2Settings], + flowMonitorPeriodMillis = config[flowMonitorPeriodMillis], + flowMonitorSuspensionLoggingThresholdMillis = config[flowMonitorSuspensionLoggingThresholdMillis], + jmxReporterType = config[jmxReporterType], + rpcAddress = config[rpcAddress], + transactionCacheSizeMegaBytes = config[transactionCacheSizeMegaBytes], + attachmentContentCacheSizeMegaBytes = config[attachmentContentCacheSizeMegaBytes], + h2port = config[h2port], + jarDirs = config[jarDirs], cordappDirectories = cordappDirectories.map { baseDirectoryPath.resolve(it) }, - cordappSignerKeyFingerprintBlacklist = configuration[cordappSignerKeyFingerprintBlacklist], - blacklistedAttachmentSigningKeys = configuration[blacklistedAttachmentSigningKeys], - networkParameterAcceptanceSettings = configuration[networkParameterAcceptanceSettings], - configurationWithOptions = ConfigurationWithOptions(configuration, Configuration.Validation.Options.defaults), - flowExternalOperationThreadPoolSize = configuration[flowExternalOperationThreadPoolSize], - quasarExcludePackages = configuration[quasarExcludePackages] + cordappSignerKeyFingerprintBlacklist = config[cordappSignerKeyFingerprintBlacklist], + blacklistedAttachmentSigningKeys = config[blacklistedAttachmentSigningKeys], + networkParameterAcceptanceSettings = config[networkParameterAcceptanceSettings], + configurationWithOptions = ConfigurationWithOptions(configuration, Configuration.Options.defaults), + flowExternalOperationThreadPoolSize = config[flowExternalOperationThreadPoolSize], + quasarExcludePackages = config[quasarExcludePackages] )) } catch (e: Exception) { return when (e) {