Skip to content

Commit

Permalink
create separrated status route with high priority
Browse files Browse the repository at this point in the history
  • Loading branch information
radoslaw.chrzanowski committed Feb 20, 2025
1 parent 12e5ee0 commit 128c727
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 25 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -49,6 +50,7 @@ class EnvoyIngressRoutesFactory(
idleTimeout: Duration?,
clusterName: String = "local_service",
serviceName: String = "",
priority: RoutingPriority = RoutingPriority.DEFAULT,
rateLimitEndpoints: List<IncomingRateLimitEndpoint> = emptyList()
): RouteAction.Builder {
val timeoutResponse = responseTimeout ?: Durations.fromMillis(
Expand All @@ -59,6 +61,7 @@ class EnvoyIngressRoutesFactory(
.setCluster(clusterName)
.setTimeout(timeoutResponse)
.setIdleTimeout(timeoutIdle)
.setPriority(priority)
.addIngressRateLimits(serviceName, rateLimitEndpoints)
}

Expand All @@ -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(
Expand Down Expand Up @@ -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<Route> {
private fun ingressRoutes(proxySettings: ProxySettings, group: Group): List<Route> {
return ingressRoute(proxySettings, group, RoutingPriority.HIGH, "/status/") +
ingressRoute(proxySettings, group, RoutingPriority.DEFAULT, "/")
}

private fun ingressRoute(
proxySettings: ProxySettings,
group: Group,
priority: RoutingPriority,
prefix: String
): List<Route> {
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
Expand All @@ -184,7 +211,7 @@ class EnvoyIngressRoutesFactory(
.setMatch(
RouteMatch.newBuilder()
.addHeaders(httpMethodMatcher(method))
.setPrefix("/")
.setPrefix(prefix)
)
.setRoute(clusterRouteActionWithRetryPolicy(retryPolicy, localRouteAction))
}
Expand Down Expand Up @@ -228,6 +255,7 @@ class EnvoyIngressRoutesFactory(
true -> {
statusClusters + endpoints
}

false ->
emptyList()
}
Expand Down Expand Up @@ -275,16 +303,10 @@ class EnvoyIngressRoutesFactory(
}

private fun generateSecuredIngressRoutes(proxySettings: ProxySettings, group: Group): List<Route> {
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() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand All @@ -190,12 +207,12 @@ internal class EnvoyIngressRoutesFactoryTest {
)
},
{
ingressRoute()
ingressServiceRoute()
matchingOnMethod("HEAD")
matchingRetryPolicy(retryPolicyProps.perHttpMethod["HEAD"]!!)
},
{
ingressRoute()
ingressServiceRoute()
matchingOnAnyMethod()
hasNoRetryPolicy()
}
Expand Down

0 comments on commit 128c727

Please sign in to comment.