diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ac7ecff3..0ac335f2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Lists all changes with user impact. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). +## [0.22.6] +### Changed +- Changed api for pathNormalization + ## [0.22.5] ### Changed - Add possibility to create custom routes diff --git a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/Groups.kt b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/Groups.kt index 00eba523c..8551183ad 100644 --- a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/Groups.kt +++ b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/Groups.kt @@ -8,7 +8,7 @@ sealed class Group { abstract val serviceId: Int? abstract val discoveryServiceName: String? abstract val proxySettings: ProxySettings - abstract val pathNormalizationConfig: PathNormalizationConfig + abstract val pathNormalizationPolicy: PathNormalizationPolicy abstract val listenersConfig: ListenersConfig? abstract val compressionConfig: CompressionConfig } @@ -19,7 +19,7 @@ data class ServicesGroup( override val serviceId: Int? = null, override val discoveryServiceName: String? = null, override val proxySettings: ProxySettings = ProxySettings(), - override val pathNormalizationConfig: PathNormalizationConfig = PathNormalizationConfig(), + override val pathNormalizationPolicy: PathNormalizationPolicy = PathNormalizationPolicy(), override val listenersConfig: ListenersConfig? = null, override val compressionConfig: CompressionConfig = CompressionConfig(), ) : Group() @@ -30,12 +30,12 @@ data class AllServicesGroup( override val serviceId: Int? = null, override val discoveryServiceName: String? = null, override val proxySettings: ProxySettings = ProxySettings(), - override val pathNormalizationConfig: PathNormalizationConfig = PathNormalizationConfig(), + override val pathNormalizationPolicy: PathNormalizationPolicy = PathNormalizationPolicy(), override val listenersConfig: ListenersConfig? = null, override val compressionConfig: CompressionConfig = CompressionConfig(), ) : Group() -data class PathNormalizationConfig( +data class PathNormalizationPolicy( val normalizationEnabled: Boolean? = null, val mergeSlashes: Boolean? = null, val pathWithEscapedSlashesAction: String? = null diff --git a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadata.kt b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadata.kt index c3e57573d..83a48e006 100644 --- a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadata.kt +++ b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadata.kt @@ -73,8 +73,17 @@ data class ProxySettings( ) } -fun getPathNormalization(proto: Value?, snapshotProperties: SnapshotProperties): PathNormalizationConfig { - val defaultNormalizationConfig = PathNormalizationConfig( +fun Value.toPathNormalization(snapshotProperties: SnapshotProperties): PathNormalizationPolicy { + return PathNormalizationPolicy( + normalizationEnabled = this.field("enabled")?.boolValue ?: snapshotProperties.pathNormalization.enabled, + mergeSlashes = this.field("mergeSlashes")?.boolValue ?: snapshotProperties.pathNormalization.mergeSlashes, + pathWithEscapedSlashesAction = this.field("escapedSlashesAction")?.stringValue + ?: snapshotProperties.pathNormalization.pathWithEscapedSlashesAction + ) +} + +fun getPathNormalization(proto: Value?, snapshotProperties: SnapshotProperties): PathNormalizationPolicy { + val defaultNormalizationConfig = PathNormalizationPolicy( snapshotProperties.pathNormalization.enabled, snapshotProperties.pathNormalization.mergeSlashes, snapshotProperties.pathNormalization.pathWithEscapedSlashesAction @@ -82,7 +91,7 @@ fun getPathNormalization(proto: Value?, snapshotProperties: SnapshotProperties): if (proto == null) { return defaultNormalizationConfig } - return PathNormalizationConfig( + return PathNormalizationPolicy( normalizationEnabled = proto.field("enabled")?.boolValue ?: defaultNormalizationConfig.normalizationEnabled, mergeSlashes = proto.field("merge_slashes")?.boolValue ?: defaultNormalizationConfig.mergeSlashes, pathWithEscapedSlashesAction = proto.field("path_with_escaped_slashes_action")?.stringValue @@ -357,6 +366,7 @@ fun Value?.toIncoming(properties: SnapshotProperties): Incoming { rateLimitEndpoints = rateLimitEndpointsField.orEmpty().map(Value::toIncomingRateLimitEndpoint), // if there is no endpoint field defined in metadata, we allow for all traffic permissionsEnabled = endpointsField != null, + pathNormalizationPolicy = this?.field("pathNormalizationPolicy")?.toPathNormalization(properties), healthCheck = this?.field("healthCheck").toHealthCheck(), roles = this?.field("roles")?.list().orEmpty().map { Role(it) }, timeoutPolicy = this?.field("timeoutPolicy").toIncomingTimeoutPolicy(), @@ -402,7 +412,8 @@ fun Value.toIncomingEndpoint(properties: SnapshotProperties): IncomingEndpoint { if (isMoreThanOnePropertyDefined(paths, path, pathPrefix, pathRegex)) { throw NodeMetadataValidationException( - "Precisely one of 'paths', 'path', 'pathPrefix' or 'pathRegex' field is allowed") + "Precisely one of 'paths', 'path', 'pathPrefix' or 'pathRegex' field is allowed" + ) } val methods = this.field("methods")?.list().orEmpty().map { it.stringValue }.toSet() @@ -412,9 +423,13 @@ fun Value.toIncomingEndpoint(properties: SnapshotProperties): IncomingEndpoint { return when { paths.isNotEmpty() -> IncomingEndpoint( - paths, "", PathMatchingType.PATH, methods, clients, unlistedClientsPolicy, oauth) + paths, "", PathMatchingType.PATH, methods, clients, unlistedClientsPolicy, oauth + ) + path != null -> IncomingEndpoint( - paths, path, PathMatchingType.PATH, methods, clients, unlistedClientsPolicy, oauth) + paths, path, PathMatchingType.PATH, methods, clients, unlistedClientsPolicy, oauth + ) + pathPrefix != null -> IncomingEndpoint( paths, pathPrefix, PathMatchingType.PATH_PREFIX, methods, clients, unlistedClientsPolicy, oauth ) @@ -424,7 +439,8 @@ fun Value.toIncomingEndpoint(properties: SnapshotProperties): IncomingEndpoint { ) else -> throw NodeMetadataValidationException( - "One of 'paths', 'path', 'pathPrefix' or 'pathRegex' field is required") + "One of 'paths', 'path', 'pathPrefix' or 'pathRegex' field is required" + ) } } @@ -580,6 +596,7 @@ data class Incoming( val permissionsEnabled: Boolean = false, val healthCheck: HealthCheck = HealthCheck(), val roles: List = emptyList(), + val pathNormalizationPolicy: PathNormalizationPolicy? = null, val timeoutPolicy: TimeoutPolicy = TimeoutPolicy( idleTimeout = null, responseTimeout = null, connectionIdleTimeout = null ), diff --git a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/listeners/filters/HttpConnectionManagerFactory.kt b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/listeners/filters/HttpConnectionManagerFactory.kt index 0f0283118..491f9bf50 100644 --- a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/listeners/filters/HttpConnectionManagerFactory.kt +++ b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/listeners/filters/HttpConnectionManagerFactory.kt @@ -51,7 +51,7 @@ class HttpConnectionManagerFactory( ): HttpConnectionManager? { val listenersConfig = group.listenersConfig!! - val normalizationConfig = group.pathNormalizationConfig + val normalizationConfig = group.proxySettings.incoming.pathNormalizationPolicy ?: group.pathNormalizationPolicy val connectionManagerBuilder = HttpConnectionManager.newBuilder() .setStatPrefix(statPrefix) .setRds(setupRds(group.communicationMode, initialFetchTimeout, routeConfigName)) diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/EnvoySnapshotFactoryTest.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/EnvoySnapshotFactoryTest.kt index e27446fdd..6e6c38eff 100644 --- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/EnvoySnapshotFactoryTest.kt +++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/EnvoySnapshotFactoryTest.kt @@ -17,7 +17,7 @@ import pl.allegro.tech.servicemesh.envoycontrol.groups.Group import pl.allegro.tech.servicemesh.envoycontrol.groups.IncomingRateLimitEndpoint import pl.allegro.tech.servicemesh.envoycontrol.groups.ListenersConfig import pl.allegro.tech.servicemesh.envoycontrol.groups.Outgoing -import pl.allegro.tech.servicemesh.envoycontrol.groups.PathNormalizationConfig +import pl.allegro.tech.servicemesh.envoycontrol.groups.PathNormalizationPolicy import pl.allegro.tech.servicemesh.envoycontrol.groups.ProxySettings import pl.allegro.tech.servicemesh.envoycontrol.groups.ServicesGroup import pl.allegro.tech.servicemesh.envoycontrol.groups.with @@ -411,7 +411,7 @@ class EnvoySnapshotFactoryTest { serviceDependencies = serviceDependencies(*dependencies), rateLimitEndpoints = rateLimitEndpoints ), - pathNormalizationConfig = PathNormalizationConfig(), + pathNormalizationPolicy = PathNormalizationPolicy(), listenersConfig = listenersConfig ) } @@ -437,7 +437,7 @@ class EnvoySnapshotFactoryTest { serviceDependencies = serviceDependencies(*dependencies), defaultServiceSettings = defaultServiceSettings ), - pathNormalizationConfig = PathNormalizationConfig(), + pathNormalizationPolicy = PathNormalizationPolicy(), listenersConfig = listenersConfig ) } diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/MetadataNodeGroupTest.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/MetadataNodeGroupTest.kt index 80b9cf4f5..a44698c8d 100644 --- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/MetadataNodeGroupTest.kt +++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/MetadataNodeGroupTest.kt @@ -25,7 +25,7 @@ import io.envoyproxy.envoy.config.core.v3.Node as NodeV3 class MetadataNodeGroupTest { - private val defaultNormalizationConfig = PathNormalizationConfig( + private val defaultNormalizationConfig = PathNormalizationPolicy( normalizationEnabled = true, mergeSlashes = true, pathWithEscapedSlashesAction = "KEEP_UNCHANGED" @@ -49,7 +49,7 @@ class MetadataNodeGroupTest { // because service may define different settings for different dependencies (for example endpoints, which // will be implemented in https://github.com/allegro/envoy-control/issues/6 communicationMode = XDS, - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, proxySettings = ProxySettings().with( serviceDependencies = serviceDependencies("a", "b", "c"), allServicesDependencies = true @@ -71,7 +71,7 @@ class MetadataNodeGroupTest { assertThat(group).isEqualTo( ServicesGroup( proxySettings = ProxySettings().with(serviceDependencies = setOf()), - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, communicationMode = XDS, compressionConfig = compressionConfig ) @@ -91,7 +91,7 @@ class MetadataNodeGroupTest { assertThat(group).isEqualTo( ServicesGroup( proxySettings = ProxySettings().with(serviceDependencies = serviceDependencies("a", "b", "c")), - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, communicationMode = XDS, compressionConfig = compressionConfig ) @@ -111,7 +111,7 @@ class MetadataNodeGroupTest { assertThat(group).isEqualTo( AllServicesGroup( communicationMode = ADS, - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, proxySettings = ProxySettings().with(allServicesDependencies = true), compressionConfig = compressionConfig ) @@ -131,7 +131,7 @@ class MetadataNodeGroupTest { assertThat(group).isEqualTo( ServicesGroup( proxySettings = ProxySettings().with(serviceDependencies = serviceDependencies("a", "b", "c")), - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, communicationMode = ADS, compressionConfig = compressionConfig ) @@ -153,7 +153,7 @@ class MetadataNodeGroupTest { // we have to preserve all services even if outgoingPermissions is disabled, // because service may define different settings for different dependencies (for example retry config) communicationMode = ADS, - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, proxySettings = ProxySettings().with(serviceDependencies = serviceDependencies("a", "b", "c")), compressionConfig = compressionConfig ) @@ -204,7 +204,7 @@ class MetadataNodeGroupTest { assertThat(group).isEqualTo( ServicesGroup( proxySettings = ProxySettings().with(serviceDependencies = serviceDependencies("a", "b", "c")), - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, communicationMode = XDS, serviceName = "app1", compressionConfig = compressionConfig @@ -246,7 +246,7 @@ class MetadataNodeGroupTest { ServicesGroup( communicationMode = ADS, serviceName = "app1", - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, proxySettings = addedProxySettings.with(serviceDependencies = serviceDependencies("a", "b")), compressionConfig = compressionConfig ) @@ -269,7 +269,7 @@ class MetadataNodeGroupTest { AllServicesGroup( communicationMode = XDS, serviceName = "app1", - pathNormalizationConfig = defaultNormalizationConfig, + pathNormalizationPolicy = defaultNormalizationConfig, proxySettings = addedProxySettings.with(allServicesDependencies = true), compressionConfig = compressionConfig ) diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadataValidatorTest.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadataValidatorTest.kt index 034e756fe..84271d998 100644 --- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadataValidatorTest.kt +++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/NodeMetadataValidatorTest.kt @@ -265,7 +265,7 @@ class NodeMetadataValidatorTest { fun `should throw an exception when PathWithEscapedSlashesAction is invalid`() { // given val node = nodeV3( - pathNormalization = PathNormalizationConfig(pathWithEscapedSlashesAction = "foo", normalizationEnabled = true, mergeSlashes = true) + pathNormalization = PathNormalizationPolicy(pathWithEscapedSlashesAction = "foo", normalizationEnabled = true, mergeSlashes = true) ) val request = DiscoveryRequestV3.newBuilder() .setNode(node) diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/TestNodeFactory.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/TestNodeFactory.kt index 6a0277df5..3536c34f6 100644 --- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/TestNodeFactory.kt +++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/TestNodeFactory.kt @@ -23,7 +23,7 @@ fun nodeV3( healthCheckPath: String? = null, healthCheckClusterName: String? = null, rateLimit: String? = null, - pathNormalization: PathNormalizationConfig? = null + pathNormalization: PathNormalizationPolicy? = null ): NodeV3 { val meta = NodeV3.newBuilder().metadataBuilder diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/utils/GroupsOperations.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/utils/GroupsOperations.kt index f5883fb1f..b52768001 100644 --- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/utils/GroupsOperations.kt +++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/utils/GroupsOperations.kt @@ -7,7 +7,7 @@ import pl.allegro.tech.servicemesh.envoycontrol.groups.DependencySettings import pl.allegro.tech.servicemesh.envoycontrol.groups.IncomingRateLimitEndpoint import pl.allegro.tech.servicemesh.envoycontrol.groups.ListenersConfig import pl.allegro.tech.servicemesh.envoycontrol.groups.Outgoing -import pl.allegro.tech.servicemesh.envoycontrol.groups.PathNormalizationConfig +import pl.allegro.tech.servicemesh.envoycontrol.groups.PathNormalizationPolicy import pl.allegro.tech.servicemesh.envoycontrol.groups.ProxySettings import pl.allegro.tech.servicemesh.envoycontrol.groups.ServicesGroup import pl.allegro.tech.servicemesh.envoycontrol.groups.with @@ -31,7 +31,7 @@ fun createServicesGroup( serviceDependencies = serviceDependencies(*dependencies), rateLimitEndpoints = rateLimitEndpoints ), - pathNormalizationConfig = PathNormalizationConfig(), + pathNormalizationPolicy = PathNormalizationPolicy(), listenersConfig = listenersConfig ) } @@ -57,7 +57,7 @@ fun createAllServicesGroup( serviceDependencies = serviceDependencies(*dependencies), defaultServiceSettings = defaultServiceSettings ), - pathNormalizationConfig = PathNormalizationConfig(), + pathNormalizationPolicy = PathNormalizationPolicy(), listenersConfig = listenersConfig ) }