diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f88d493..9218c6a0f 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.9] +### Changed +- separated ingress route for /status* paths + ## [0.22.8] ### Changed - added tests for missing and malformed JWT token scenarios diff --git a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactory.kt b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactory.kt index 52468d9d9..d7fc9a1db 100644 --- a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactory.kt +++ b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactory.kt @@ -7,6 +7,7 @@ import com.google.protobuf.util.Durations import io.envoyproxy.envoy.config.core.v3.HeaderValue import io.envoyproxy.envoy.config.core.v3.HeaderValueOption import io.envoyproxy.envoy.config.core.v3.Metadata +import io.envoyproxy.envoy.config.core.v3.RoutingPriority import io.envoyproxy.envoy.config.route.v3.HeaderMatcher import io.envoyproxy.envoy.config.route.v3.RateLimit import io.envoyproxy.envoy.config.route.v3.RetryPolicy @@ -49,6 +50,7 @@ class EnvoyIngressRoutesFactory( idleTimeout: Duration?, clusterName: String = "local_service", serviceName: String = "", + priority: RoutingPriority = RoutingPriority.DEFAULT, rateLimitEndpoints: List = emptyList() ): RouteAction.Builder { val timeoutResponse = responseTimeout ?: Durations.fromMillis( @@ -59,6 +61,7 @@ class EnvoyIngressRoutesFactory( .setCluster(clusterName) .setTimeout(timeoutResponse) .setIdleTimeout(timeoutIdle) + .setPriority(priority) .addIngressRateLimits(serviceName, rateLimitEndpoints) } @@ -73,19 +76,25 @@ class EnvoyIngressRoutesFactory( .addHeaders(createHeaderMatcher(endpoint.pathMatchingType, endpoint.path)) if (endpoint.methods.isNotEmpty()) { - match.addHeaders(HeaderMatcher.newBuilder() - .setRe2Match(endpoint.methods.joinToString( - separator = "|", - transform = { "^$it\$" })) - .setName(":method") + match.addHeaders( + HeaderMatcher.newBuilder() + .setRe2Match( + endpoint.methods.joinToString( + separator = "|", + transform = { "^$it\$" }) + ) + .setName(":method") ) } if (endpoint.clients.isNotEmpty() && endpoint.clients != allClients) { - match.addHeaders(HeaderMatcher.newBuilder() - .setRe2Match(endpoint.clients.joinToString( - separator = "|", - transform = { "^${it.compositeName()}\$" })) - .setName(properties.incomingPermissions.serviceNameHeader) + match.addHeaders( + HeaderMatcher.newBuilder() + .setRe2Match( + endpoint.clients.joinToString( + separator = "|", + transform = { "^${it.compositeName()}\$" }) + ) + .setName(properties.incomingPermissions.serviceNameHeader) ) } addRateLimits( @@ -171,11 +180,29 @@ class EnvoyIngressRoutesFactory( .map { HttpMethod.valueOf(it.key) to retryPolicy(it.value) } .toMap() - private fun ingressRoutes(localRouteAction: RouteAction.Builder, group: Group): List { + private fun ingressRoutes(proxySettings: ProxySettings, group: Group): List { + return ingressRoute(proxySettings, group, RoutingPriority.HIGH, "/status/") + + ingressRoute(proxySettings, group, RoutingPriority.DEFAULT, "/") + } + + private fun ingressRoute( + proxySettings: ProxySettings, + group: Group, + priority: RoutingPriority, + prefix: String + ): List { + val localRouteAction = clusterRouteAction( + proxySettings.incoming.timeoutPolicy.responseTimeout, + proxySettings.incoming.timeoutPolicy.idleTimeout, + priority = priority, + serviceName = group.serviceName, + rateLimitEndpoints = proxySettings.incoming.rateLimitEndpoints + ) + val nonRetryRoute = Route.newBuilder() .setMatch( RouteMatch.newBuilder() - .setPrefix("/") + .setPrefix(prefix) ) .setRoute(localRouteAction) val retryRoutes = perMethodRetryPolicies @@ -184,7 +211,7 @@ class EnvoyIngressRoutesFactory( .setMatch( RouteMatch.newBuilder() .addHeaders(httpMethodMatcher(method)) - .setPrefix("/") + .setPrefix(prefix) ) .setRoute(clusterRouteActionWithRetryPolicy(retryPolicy, localRouteAction)) } @@ -228,6 +255,7 @@ class EnvoyIngressRoutesFactory( true -> { statusClusters + endpoints } + false -> emptyList() } @@ -275,16 +303,10 @@ class EnvoyIngressRoutesFactory( } private fun generateSecuredIngressRoutes(proxySettings: ProxySettings, group: Group): List { - val localRouteAction = clusterRouteAction( - proxySettings.incoming.timeoutPolicy.responseTimeout, - proxySettings.incoming.timeoutPolicy.idleTimeout, - serviceName = group.serviceName, - rateLimitEndpoints = proxySettings.incoming.rateLimitEndpoints - ) val customHealthCheckRoute = customHealthCheckRoute(proxySettings) - return customHealthCheckRoute + ingressRoutes(localRouteAction, group) + return customHealthCheckRoute + ingressRoutes(proxySettings, group) } private fun statusRouteVirtualClusterEnabled() = diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/RoutesAssertions.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/RoutesAssertions.kt index ad89091ee..fcf537ba8 100644 --- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/RoutesAssertions.kt +++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/groups/RoutesAssertions.kt @@ -234,12 +234,18 @@ fun Route.hasRetryPolicy() { assertThat(this.route.hasRetryPolicy()).isTrue() } -fun Route.ingressRoute() { +fun Route.ingressServiceRoute() { this.matchingOnPrefix("/") .publicAccess() .toCluster("local_service") } +fun Route.ingresStatusRoute() { + this.matchingOnPrefix("/status/") + .publicAccess() + .toCluster("local_service") +} + fun Route.hasRateLimitsInOrder(vararg conditions: RateLimit.() -> Unit): Route = apply { assertThat(this.route.rateLimitsList).hasSameSizeAs(conditions) assertThat( diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactoryTest.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactoryTest.kt index 40a37ed86..8d16b0dcd 100644 --- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactoryTest.kt +++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/routes/EnvoyIngressRoutesFactoryTest.kt @@ -29,7 +29,8 @@ import pl.allegro.tech.servicemesh.envoycontrol.groups.hasRequestHeadersToRemove import pl.allegro.tech.servicemesh.envoycontrol.groups.hasResponseHeaderToAdd import pl.allegro.tech.servicemesh.envoycontrol.groups.hasSingleVirtualHostThat import pl.allegro.tech.servicemesh.envoycontrol.groups.hasStatusVirtualClusters -import pl.allegro.tech.servicemesh.envoycontrol.groups.ingressRoute +import pl.allegro.tech.servicemesh.envoycontrol.groups.ingresStatusRoute +import pl.allegro.tech.servicemesh.envoycontrol.groups.ingressServiceRoute import pl.allegro.tech.servicemesh.envoycontrol.groups.matchingOnAnyMethod import pl.allegro.tech.servicemesh.envoycontrol.groups.matchingOnMethod import pl.allegro.tech.servicemesh.envoycontrol.groups.matchingOnPrefix @@ -88,6 +89,7 @@ internal class EnvoyIngressRoutesFactoryTest { private val currentZone = "dc1" @Test + @Suppress("LongMethod") fun `should create route config with health check and response timeout defined`() { // given val routesFactory = EnvoyIngressRoutesFactory(SnapshotProperties().apply { @@ -164,7 +166,22 @@ internal class EnvoyIngressRoutesFactoryTest { }, *adminRoutes, { - ingressRoute() + ingresStatusRoute() + matchingOnMethod("GET") + matchingRetryPolicy(retryPolicyProps.perHttpMethod["GET"]!!) + }, + { + ingresStatusRoute() + matchingOnMethod("HEAD") + matchingRetryPolicy(retryPolicyProps.perHttpMethod["HEAD"]!!) + }, + { + ingresStatusRoute() + matchingOnAnyMethod() + hasNoRetryPolicy() + }, + { + ingressServiceRoute() matchingOnMethod("GET") matchingRetryPolicy(retryPolicyProps.perHttpMethod["GET"]!!) hasRateLimitsInOrder( @@ -190,12 +207,12 @@ internal class EnvoyIngressRoutesFactoryTest { ) }, { - ingressRoute() + ingressServiceRoute() matchingOnMethod("HEAD") matchingRetryPolicy(retryPolicyProps.perHttpMethod["HEAD"]!!) }, { - ingressRoute() + ingressServiceRoute() matchingOnAnyMethod() hasNoRetryPolicy() }