Skip to content

Commit

Permalink
#624 Set flat priority only for services with traffic splitting
Browse files Browse the repository at this point in the history
  • Loading branch information
nastassia-dailidava committed Mar 27, 2024
1 parent 8e902af commit 539c435
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class TrafficSplittingProperties {
var zoneName = ""
var headerName = ""
var weightsByService: Map<String, ZoneWeights> = mapOf()
var zonesAllowingTrafficSplitting = listOf<String>()
}

class ZoneWeights {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,27 @@ class EnvoyEndpointsFactory(
) {
companion object {
private val logger by logger()
private const val HIGHEST_PRIORITY = 0
}

fun createLoadAssignment(
clusters: Set<String>,
multiClusterState: MultiClusterState
): List<ClusterLoadAssignment> {

return clusters
.map { serviceName ->
val localityLbEndpoints = multiClusterState
.map {
val locality = it.locality
val cluster = it.cluster

createEndpointsGroup(it.servicesState[serviceName], cluster, locality)
}
val endpoints = duplicateAndOverridePriorityForLocalityLbEndpoints(serviceName, localityLbEndpoints)
?.let { localityLbEndpoints + it } ?: localityLbEndpoints

ClusterLoadAssignment.newBuilder()
.setClusterName(serviceName)
.addAllEndpoints(localityLbEndpoints)
.addAllEndpoints(endpoints)
.build()
}
}
Expand Down Expand Up @@ -90,6 +91,25 @@ class EnvoyEndpointsFactory(
} else loadAssignment
}

private fun duplicateAndOverridePriorityForLocalityLbEndpoints(
serviceName: String,
localityLbEndpoints: List<LocalityLbEndpoints>
): LocalityLbEndpoints? {
val weightsByService = properties.loadBalancing.trafficSplitting.weightsByService
val trafficSplittingEnabled = weightsByService.isNotEmpty()
val serviceNotListed = !weightsByService.containsKey(serviceName)
val zoneAllowsTrafficSplitting =
properties.loadBalancing.trafficSplitting.zonesAllowingTrafficSplitting.contains(currentZone)
return if (trafficSplittingEnabled && serviceNotListed && zoneAllowsTrafficSplitting) {
localityLbEndpoints
.find { properties.loadBalancing.trafficSplitting.zoneName == it.locality.zone }
?.let { LocalityLbEndpoints.newBuilder(it)
.setPriority(HIGHEST_PRIORITY)
.build()
}
} else null
}

private fun assignWeights(
llbEndpointsList: List<LocalityLbEndpoints>, weights: ZoneWeights
): List<LocalityLbEndpoints> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ class EnvoyAdmin(
}
}

private fun configDump(): String {
val response = get("config_dump")
fun configDump(): String {
val response = get("config_dump?include_eds=on")
return response.body.use { it!!.string() }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import pl.allegro.tech.servicemesh.envoycontrol.config.envoy.EnvoyExtension
import pl.allegro.tech.servicemesh.envoycontrol.config.envoycontrol.EnvoyControlClusteredExtension
import pl.allegro.tech.servicemesh.envoycontrol.config.service.EchoServiceExtension
import verifyCallsCountCloseTo
import verifyCallsCountEq
import verifyIsReachable
import java.time.Duration

class WeightedClustersRoutingTest {
class LocalityWeightedLoadBalancingRoutingTest {
companion object {
private const val forceTrafficZone = "dc2"

Expand All @@ -24,17 +25,18 @@ class WeightedClustersRoutingTest {
"envoy-control.envoy.snapshot.stateSampleDuration" to Duration.ofSeconds(0),
"envoy-control.sync.enabled" to true,
"envoy-control.envoy.snapshot.load-balancing.trafficSplitting.zoneName" to forceTrafficZone,
"envoy-control.envoy.snapshot.load-balancing.trafficSplitting.zonesAllowingTrafficSplitting" to "dc1",
"envoy-control.envoy.snapshot.load-balancing.trafficSplitting.weightsByService.$serviceName.weightByZone.dc1" to 30,
"envoy-control.envoy.snapshot.load-balancing.trafficSplitting.weightsByService.$serviceName.weightByZone.dc2" to 10,
"envoy-control.envoy.snapshot.load-balancing.trafficSplitting.weightsByService.$serviceName.weightByZone.dc3" to 1,
"envoy-control.envoy.snapshot.load-balancing.priorities.zonePriorities" to mapOf(
"dc1" to mapOf(
"dc1" to 0,
"dc2" to 0,
"dc2" to 1,
"dc3" to 3,
),
"dc2" to mapOf(
"dc1" to 0,
"dc1" to 1,
"dc2" to 0,
"dc3" to 3,
),
Expand All @@ -53,9 +55,11 @@ class WeightedClustersRoutingTest {
outgoing:
dependencies:
- service: "service-1"
- service: "service-2"
""".trimIndent()

private val config = Xds.copy(configOverride = echo2Config, serviceName = "echo2")
private val configEcho = Xds.copy(configOverride = echo2Config, serviceName = "echo")

@JvmField
@RegisterExtension
Expand All @@ -76,6 +80,10 @@ class WeightedClustersRoutingTest {
val envoyControl3 =
EnvoyControlClusteredExtension(consul.serverThird, { properties }, listOf(consul))

@JvmField
@RegisterExtension
val echo2ServiceDC1 = EchoServiceExtension()

@JvmField
@RegisterExtension
val echoServiceDC1 = EchoServiceExtension()
Expand All @@ -94,44 +102,62 @@ class WeightedClustersRoutingTest {

@JvmField
@RegisterExtension
val echoEnvoyDC1 = EnvoyExtension(envoyControl, localService = echoServiceDC1, config)
val echo2EnvoyDC1 = EnvoyExtension(envoyControl, localService = echo2ServiceDC1, config)

@JvmField
@RegisterExtension
val echoEnvoyDC2 = EnvoyExtension(envoyControl2)
val echoEnvoyDC1 = EnvoyExtension(envoyControl, localService = echoServiceDC1, configEcho)

@JvmField
@RegisterExtension
val echoEnvoyDC3 = EnvoyExtension(envoyControl3)
val echoEnvoyDC2 = EnvoyExtension(envoyControl2)
}

@Test
fun `should route traffic according to weights`() {
consul.serverFirst.operations.registerServiceWithEnvoyOnEgress(echoEnvoyDC1, name = serviceName)
consul.serverFirst.operations.registerServiceWithEnvoyOnEgress(echo2EnvoyDC1, name = serviceName)

consul.serverFirst.operations.registerService(upstreamServiceDC1, name = upstreamServiceName)
echoEnvoyDC1.verifyIsReachable(upstreamServiceDC1, upstreamServiceName)
echo2EnvoyDC1.verifyIsReachable(upstreamServiceDC1, upstreamServiceName)

consul.serverSecond.operations.registerService(upstreamServiceDC2, name = upstreamServiceName)
echoEnvoyDC1.verifyIsReachable(upstreamServiceDC2, upstreamServiceName)
echo2EnvoyDC1.verifyIsReachable(upstreamServiceDC2, upstreamServiceName)

Check failure on line 124 in envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/trafficsplitting/LocalityWeightedLoadBalancingRoutingTest.kt

View workflow job for this annotation

GitHub Actions / JUnit Test Report

LocalityWeightedLoadBalancingRoutingTest.should route traffic according to weights()

org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt Expecting actual: Response{protocol=http/1.1, code=200, message=OK, url=http://localhost:33101/} to match given predicate. You can use 'matches(Predicate p, String description)' to have a better error message For example: assertThat(player).matches(p -> p.isRookie(), "is rookie"); will give an error message looking like: Expecting actual: player to match 'is rookie' predicate within 1 minutes 30 seconds.
Raw output
org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt 
Expecting actual:
  Response{protocol=http/1.1, code=200, message=OK, url=http://localhost:33101/}
to match given predicate.

You can use 'matches(Predicate p, String description)' to have a better error message
For example:
  assertThat(player).matches(p -> p.isRookie(), "is rookie");
will give an error message looking like:

Expecting actual:
  player
to match 'is rookie' predicate within 1 minutes  30 seconds.
	at app//org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at app//org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at app//org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)
	at app//org.awaitility.core.ConditionFactory.until(ConditionFactory.java:985)
	at app//org.awaitility.core.ConditionFactory.untilAsserted(ConditionFactory.java:769)
	at app//pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt.untilAsserted(AwaitAssertions.kt:15)
	at app//pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt.untilAsserted$default(AwaitAssertions.kt:7)
	at app//TrafficSplittingKt.verifyIsReachable(TrafficSplitting.kt:19)
	at app//pl.allegro.tech.servicemesh.envoycontrol.trafficsplitting.LocalityWeightedLoadBalancingRoutingTest.should route traffic according to weights(LocalityWeightedLoadBalancingRoutingTest.kt:124)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base@17.0.10/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base@17.0.10/java.lang.reflect.Method.invoke(Method.java:568)
	at app//org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
	at app//org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at app//org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base@17.0.10/java.util.ArrayList.forEach(ArrayList.java:1511)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base@17.0.10/java.util.ArrayList.forEach(ArrayList.java:1511)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at app//org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:118)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:93)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:88)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base@17.0.10/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base@17.0.10/java.lang.reflect.Method.invoke(Method.java:568)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.AssertionError: 
Expecting actual:
  Response{protocol=http/1.1, code=200, message=OK, url=http://localhost:33101/}
to match given predicate.

You can use 'matches(Predicate p, String description)' to have a better error message
For example:
  assertThat(player).matches(p -> p.isRookie(), "is rookie");
will give an error message looking like:

Expecting actual:
  player
to match 'is rookie' predicate
	at pl.allegro.tech.servicemesh.envoycontrol.assertions.ResponseAssertionsKt.isFrom(ResponseAssertions.kt:29)
	at TrafficSplittingKt$verifyIsReachable$1.invoke(TrafficSplitting.kt:21)
	at TrafficSplittingKt$verifyIsReachable$1.invoke(TrafficSplitting.kt:19)
	at pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt.untilAsserted$lambda$0(AwaitAssertions.kt:15)
	at org.awaitility.core.AssertionCondition.lambda$new$0(AssertionCondition.java:53)
	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:248)
	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:235)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:840)

echoEnvoyDC1.callUpstreamServiceRepeatedly(upstreamServiceDC1, upstreamServiceDC2)
echo2EnvoyDC1.callUpstreamServiceRepeatedly(upstreamServiceDC1, upstreamServiceDC2)
.verifyCallsCountCloseTo(upstreamServiceDC1, 75)
.verifyCallsCountCloseTo(upstreamServiceDC2, 25)
println("snapshot: " + envoyControl.app.getGlobalSnapshot(false).toString())
.verifyCallsCountEq(upstreamServiceDC3, 0)
}

@Test
fun `should route traffic according to weights with service tag`() {
consul.serverFirst.operations.registerServiceWithEnvoyOnEgress(echoEnvoyDC1, name = serviceName)
consul.serverFirst.operations.registerServiceWithEnvoyOnEgress(echo2EnvoyDC1, name = serviceName)

consul.serverFirst.operations.registerService(upstreamServiceDC1, name = upstreamServiceName, tags = listOf("tag"))
echoEnvoyDC1.verifyIsReachable(upstreamServiceDC1, upstreamServiceName)
echo2EnvoyDC1.verifyIsReachable(upstreamServiceDC1, upstreamServiceName)

consul.serverSecond.operations.registerService(upstreamServiceDC2, name = upstreamServiceName, tags = listOf("tag"))
echoEnvoyDC1.verifyIsReachable(upstreamServiceDC2, upstreamServiceName)
echo2EnvoyDC1.verifyIsReachable(upstreamServiceDC2, upstreamServiceName)

Check failure on line 140 in envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/trafficsplitting/LocalityWeightedLoadBalancingRoutingTest.kt

View workflow job for this annotation

GitHub Actions / JUnit Test Report

LocalityWeightedLoadBalancingRoutingTest.should route traffic according to weights with service tag()

org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt Expecting actual: Response{protocol=http/1.1, code=200, message=OK, url=http://localhost:33101/} to match given predicate. You can use 'matches(Predicate p, String description)' to have a better error message For example: assertThat(player).matches(p -> p.isRookie(), "is rookie"); will give an error message looking like: Expecting actual: player to match 'is rookie' predicate within 1 minutes 30 seconds.
Raw output
org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt 
Expecting actual:
  Response{protocol=http/1.1, code=200, message=OK, url=http://localhost:33101/}
to match given predicate.

You can use 'matches(Predicate p, String description)' to have a better error message
For example:
  assertThat(player).matches(p -> p.isRookie(), "is rookie");
will give an error message looking like:

Expecting actual:
  player
to match 'is rookie' predicate within 1 minutes  30 seconds.
	at app//org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at app//org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at app//org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)
	at app//org.awaitility.core.ConditionFactory.until(ConditionFactory.java:985)
	at app//org.awaitility.core.ConditionFactory.untilAsserted(ConditionFactory.java:769)
	at app//pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt.untilAsserted(AwaitAssertions.kt:15)
	at app//pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt.untilAsserted$default(AwaitAssertions.kt:7)
	at app//TrafficSplittingKt.verifyIsReachable(TrafficSplitting.kt:19)
	at app//pl.allegro.tech.servicemesh.envoycontrol.trafficsplitting.LocalityWeightedLoadBalancingRoutingTest.should route traffic according to weights with service tag(LocalityWeightedLoadBalancingRoutingTest.kt:140)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base@17.0.10/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base@17.0.10/java.lang.reflect.Method.invoke(Method.java:568)
	at app//org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
	at app//org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at app//org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at app//org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at app//org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base@17.0.10/java.util.ArrayList.forEach(ArrayList.java:1511)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base@17.0.10/java.util.ArrayList.forEach(ArrayList.java:1511)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at app//org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:118)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:93)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:88)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base@17.0.10/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base@17.0.10/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base@17.0.10/java.lang.reflect.Method.invoke(Method.java:568)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.AssertionError: 
Expecting actual:
  Response{protocol=http/1.1, code=200, message=OK, url=http://localhost:33101/}
to match given predicate.

You can use 'matches(Predicate p, String description)' to have a better error message
For example:
  assertThat(player).matches(p -> p.isRookie(), "is rookie");
will give an error message looking like:

Expecting actual:
  player
to match 'is rookie' predicate
	at pl.allegro.tech.servicemesh.envoycontrol.assertions.ResponseAssertionsKt.isFrom(ResponseAssertions.kt:29)
	at TrafficSplittingKt$verifyIsReachable$1.invoke(TrafficSplitting.kt:21)
	at TrafficSplittingKt$verifyIsReachable$1.invoke(TrafficSplitting.kt:19)
	at pl.allegro.tech.servicemesh.envoycontrol.assertions.AwaitAssertionsKt.untilAsserted$lambda$0(AwaitAssertions.kt:15)
	at org.awaitility.core.AssertionCondition.lambda$new$0(AssertionCondition.java:53)
	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:248)
	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:235)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:840)

echoEnvoyDC1.callUpstreamServiceRepeatedly(upstreamServiceDC1, upstreamServiceDC2, tag = "tag")
echo2EnvoyDC1.callUpstreamServiceRepeatedly(upstreamServiceDC1, upstreamServiceDC2, tag = "tag")
.verifyCallsCountCloseTo(upstreamServiceDC1, 75)
.verifyCallsCountCloseTo(upstreamServiceDC2, 25)
.verifyCallsCountEq(upstreamServiceDC3, 0)
}

@Test
fun `should not split traffic for not listed service`() {
consul.serverFirst.operations.registerServiceWithEnvoyOnEgress(echoEnvoyDC1, name = "echo")

consul.serverFirst.operations.registerService(upstreamServiceDC1, name = upstreamServiceName,)
echoEnvoyDC1.verifyIsReachable(upstreamServiceDC1, upstreamServiceName)

consul.serverSecond.operations.registerService(upstreamServiceDC2, name = upstreamServiceName)
echoEnvoyDC2.verifyIsReachable(upstreamServiceDC2, upstreamServiceName)

echoEnvoyDC1.callUpstreamServiceRepeatedly(upstreamServiceDC1, upstreamServiceDC2)
.verifyCallsCountEq(upstreamServiceDC1, 100)
.verifyCallsCountEq(upstreamServiceDC2, 0)
.verifyCallsCountEq(upstreamServiceDC3, 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ fun CallStats.verifyCallsCountCloseTo(service: EchoServiceExtension, expectedCou
return this
}

fun CallStats.verifyCallsCountGreaterThan(service: EchoServiceExtension, hits: Int): CallStats {
Assertions.assertThat(this.hits(service)).isGreaterThan(hits)
fun CallStats.verifyCallsCountEq(service: EchoServiceExtension, expectedCount: Int): CallStats {
Assertions.assertThat(this.hits(service)).isEqualTo(expectedCount)
return this
}

Expand Down

0 comments on commit 539c435

Please sign in to comment.