Skip to content

Commit

Permalink
PROM-5262 | x-service-tag-preference e2e tests WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcinFalkowski committed Mar 7, 2025
1 parent 96007b0 commit 5aa6306
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -318,20 +318,6 @@ abstract class EnvoyControlTestConfiguration : BaseEnvoyTest() {
}
}

protected fun callServiceRepeatedly(
service: String,
stats: CallStats,
minRepeat: Int = 1,
maxRepeat: Int = 100,
repeatUntil: (ResponseWithBody) -> Boolean = { false },
headers: Map<String, String> = mapOf(),
pathAndQuery: String = "",
assertNoErrors: Boolean = true,
fromEnvoy: EnvoyContainer = envoyContainer1
): CallStats = EgressOperations(fromEnvoy).callServiceRepeatedly(
service, stats, minRepeat, maxRepeat, repeatUntil, headers, pathAndQuery, assertNoErrors
)

private fun waitForEchoServices(instances: Int) {
untilAsserted {
assertThat(envoyContainer1.admin().numOfEndpoints(clusterName = "echo")).isEqualTo(instances)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package pl.allegro.tech.servicemesh.envoycontrol.config.envoy

import org.assertj.core.api.Assertions.assertThat
import pl.allegro.tech.servicemesh.envoycontrol.config.service.EchoServiceExtension

class CallStats(private val serviceExtensions: List<EchoServiceExtension>) {
Expand All @@ -15,7 +16,8 @@ class CallStats(private val serviceExtensions: List<EchoServiceExtension>) {
serviceExtensions
.map { it.container() }
.firstOrNull { response.isFrom(it) }
?.let { containerHits.compute(it.containerId) { _, i -> i?.inc() } }
.let { it ?: throw AssertionError("response from unknown instance") }
.let { containerHits.compute(it.containerId) { _, i -> i?.inc() } }
if (!response.isOk()) failedHits++
totalHits++
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package pl.allegro.tech.servicemesh.envoycontrol.routing

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
import pl.allegro.tech.servicemesh.envoycontrol.config.consul.ConsulExtension
import pl.allegro.tech.servicemesh.envoycontrol.config.envoy.CallStats
import pl.allegro.tech.servicemesh.envoycontrol.config.envoy.EnvoyExtension
import pl.allegro.tech.servicemesh.envoycontrol.config.envoycontrol.EnvoyControlExtension
import pl.allegro.tech.servicemesh.envoycontrol.config.service.EchoServiceExtension

class ServiceTagPreferenceTest {

companion object {

val properties = mapOf(
"envoy-control.envoy.snapshot.routing.service-tags.enabled" to true,
"envoy-control.envoy.snapshot.routing.service-tags.auto-service-tag-enabled" to true, // TODO: testing with false?
"envoy-control.envoy.snapshot.routing.service-tags.add-upstream-service-tags-header" to true,
"envoy-control.envoy.snapshot.routing.service-tags.preference-header" to "x-service-tags-preference",
"envoy-control.envoy.snapshot.routing.service-tags.preference-routing-enabled" to true // TODO: add property
)

@JvmField
@RegisterExtension
val consul = ConsulExtension()

@JvmField
@RegisterExtension
val envoyControl: EnvoyControlExtension = EnvoyControlExtension(consul = consul, properties = properties)

@JvmField
@RegisterExtension
val envoyGlobal = EnvoyExtension(envoyControl = envoyControl)

@JvmField
@RegisterExtension
val envoyVte12 = EnvoyExtension(envoyControl = envoyControl).also {
it.container.withEnv("DEFAULT_SERVICE_TAG_PREFERENCE", "vte12|global")
}

@JvmField
@RegisterExtension
val envoyVte12Lvte1 = EnvoyExtension(envoyControl = envoyControl).also {
it.container.withEnv("DEFAULT_SERVICE_TAG_PREFERENCE", "lvte1|vte12|global")
}

@JvmField
@RegisterExtension
val echoGlobal = EchoServiceExtension()

@JvmField
@RegisterExtension
val echoVte12 = EchoServiceExtension()

@JvmField
@RegisterExtension
val echoVte12Lvte1 = EchoServiceExtension()

@JvmField
@RegisterExtension
val echoVte33 = EchoServiceExtension()

val allServices = listOf(echoGlobal, echoVte12, echoVte12Lvte1, echoVte33)
}

@Test
fun `requests are routed according to default service tag preference`() {
// given
consul.server.operations.registerService(name = "echo", extension = echoGlobal, tags = listOf("global", "other-1"))
consul.server.operations.registerService(name = "echo", extension = echoVte12, tags = listOf("vte12", "other-2"))
consul.server.operations.registerService(name = "echo", extension = echoVte12Lvte1, tags = listOf("lvte1", "other-3"))
consul.server.operations.registerService(name = "echo", extension = echoVte33, tags = listOf("vte33", "other-3"))

listOf(envoyGlobal, envoyVte12, envoyVte12Lvte1).forEach { envoy ->
allServices.forEach { service ->
envoy.waitForClusterEndpointHealthy("echo", service.container().ipAddress())
}
}

// expects
envoyGlobal.callServiceRepeatedly(service = "echo")
.assertAllResponsesOkAndFrom(instance = echoGlobal)

envoyVte12.callServiceRepeatedly(service = "echo")
.assertAllResponsesOkAndFrom(instance = echoVte12)

envoyVte12Lvte1.callServiceRepeatedly(service = "echo")
.assertAllResponsesOkAndFrom(instance = echoVte12Lvte1)
}

@Test
fun `x-service-tag-preference from request overrides default one`() {
// TODO: implement
throw NotImplementedError()
}

@Test
fun `x-service-tag overrides x-service-tag-preference`() {
// TODO: implement
throw NotImplementedError()
}

private val repeat = 10

private fun EnvoyExtension.callServiceRepeatedly(service: String): CallStats =
this.egressOperations.callServiceRepeatedly(
service = service, stats = CallStats(allServices), minRepeat = repeat, maxRepeat = repeat
)

private fun CallStats.assertAllResponsesOkAndFrom(instance: EchoServiceExtension) {
assertThat(failedHits).isEqualTo(0)
assertThat(hits(instance))
.describedAs {
"hits: {global: ${hits(echoGlobal)}, vte12: ${hits(echoVte12)}, lvte1: ${hits(echoVte12Lvte1)}, vte33: ${hits(echoVte33)}}"
}
.isEqualTo(totalHits).isEqualTo(repeat)
}
}

0 comments on commit 5aa6306

Please sign in to comment.