diff --git a/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/DebugTest.kt b/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/DebugTest.kt new file mode 100644 index 000000000..385da23f2 --- /dev/null +++ b/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/DebugTest.kt @@ -0,0 +1,129 @@ +package pl.allegro.tech.servicemesh.envoycontrol.routing + +import io.micrometer.core.instrument.MeterRegistry +import okhttp3.Response +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.ExtensionContext +import org.junit.jupiter.api.extension.RegisterExtension +import pl.allegro.tech.servicemesh.envoycontrol.chaos.api.NetworkDelay +import pl.allegro.tech.servicemesh.envoycontrol.config.EnvoyConfig +import pl.allegro.tech.servicemesh.envoycontrol.config.envoy.EnvoyExtension +import pl.allegro.tech.servicemesh.envoycontrol.config.envoycontrol.EnvoyControlExtensionBase +import pl.allegro.tech.servicemesh.envoycontrol.config.envoycontrol.EnvoyControlTestApp +import pl.allegro.tech.servicemesh.envoycontrol.config.envoycontrol.Health +import pl.allegro.tech.servicemesh.envoycontrol.config.envoycontrol.SnapshotDebugResponse +import pl.allegro.tech.servicemesh.envoycontrol.services.ServicesState + +class DebugTest { + + companion object { + // language=yaml + private val config = """ + static_resources: + listeners: + - name: egress + address: { socket_address: { address: 0.0.0.0, port_value: 5000 }} + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: e + route_config: {} + - name: ingress + address: { socket_address: { address: 0.0.0.0, port_value: 5001 }} + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: i + route_config: {} + + admin: + address: { socket_address: { address: 0.0.0.0, port_value: 10000 }} + """.trimIndent() + + @JvmField + @RegisterExtension + val envoy = EnvoyExtension( + envoyControl = FakeEnvoyControl(), + config = EnvoyConfig("envoy/empty.yaml", configOverride = config), + ) + } + + @Test + @ExtendWith + fun debug() { + + + } +} + + +private class FakeEnvoyControl : EnvoyControlExtensionBase { + override val app: EnvoyControlTestApp = object : EnvoyControlTestApp { + override val appPort: Int + get() { throw UnsupportedOperationException() } + override val grpcPort: Int = 0 + override val appName: String + get() { throw UnsupportedOperationException() } + + override fun run() { + throw UnsupportedOperationException() + } + + override fun stop() { + throw UnsupportedOperationException() + } + + override fun isHealthy(): Boolean { + throw UnsupportedOperationException() + } + + override fun getState(): ServicesState { + throw UnsupportedOperationException() + } + + override fun getSnapshot(nodeJson: String): SnapshotDebugResponse { + throw UnsupportedOperationException() + } + + override fun getGlobalSnapshot(xds: Boolean?): SnapshotDebugResponse { + throw UnsupportedOperationException() + } + + override fun getHealthStatus(): Health { + throw UnsupportedOperationException() + } + + override fun postChaosFaultRequest( + username: String, + password: String, + networkDelay: NetworkDelay + ): Response { + throw UnsupportedOperationException() + } + + override fun getExperimentsListRequest(username: String, password: String): Response { + throw UnsupportedOperationException() + } + + override fun deleteChaosFaultRequest( + username: String, + password: String, + faultId: String + ): Response { + throw UnsupportedOperationException() + } + + override fun meterRegistry(): MeterRegistry { + throw UnsupportedOperationException() + } + } + + override fun beforeAll(context: ExtensionContext?) {} + + override fun afterAll(context: ExtensionContext?) {} +} diff --git a/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/RoutingHeadersTest.kt b/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/RoutingHeadersTest.kt new file mode 100644 index 000000000..bc234518c --- /dev/null +++ b/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/RoutingHeadersTest.kt @@ -0,0 +1,129 @@ +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.assertions.isOk +import pl.allegro.tech.servicemesh.envoycontrol.config.RandomConfigFile +import pl.allegro.tech.servicemesh.envoycontrol.config.consul.ConsulExtension +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.GenericServiceExtension +import pl.allegro.tech.servicemesh.envoycontrol.config.service.HttpsEchoContainer +import pl.allegro.tech.servicemesh.envoycontrol.config.service.ServiceExtension +import pl.allegro.tech.servicemesh.envoycontrol.config.service.asHttpsEchoResponse + +class RoutingHeadersTest { + + companion object { + private 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 + ) + + @JvmField + @RegisterExtension + val consul = ConsulExtension() + + @JvmField + @RegisterExtension + val envoyControl = EnvoyControlExtension(consul, properties) + + @JvmField + @RegisterExtension + val echoService = GenericServiceExtension(HttpsEchoContainer()) + + // language=yaml + private var proxySettings = """ + node: + metadata: + proxy_settings: + outgoing: + routingPolicy: + autoServiceTag: true + serviceTagPreference: ["ipsum", "lorem"] + fallbackToAnyInstance: true + dependencies: + - service: "echo" + - service: "echo-disabled" + routingPolicy: + autoServiceTag: false + - service: "echo-one-tag" + routingPolicy: + serviceTagPreference: ["one"] + - service: "echo-no-tag" + routingPolicy: + serviceTagPreference: [] + + """.trimIndent() + + @JvmField + @RegisterExtension + val envoy = EnvoyExtension(envoyControl, config = RandomConfigFile.copy(configOverride = proxySettings)) + + private val allTags = listOf("ipsum", "lorem", "one") + } + + @Test + fun `should add correct x-service-tag-preference header to upstream request`() { + // given + listOf("echo", "echo-disabled", "echo-one-tag", "echo-no-tag").forEach { service -> + consul.server.operations.registerService(name = service, extension = echoService, tags = allTags) + } + listOf("echo", "echo-disabled", "echo-one-tag", "echo-no-tag").forEach { service -> + waitForEndpointReady(service, echoService, envoy) + } + + // when + val echoResponse = envoy.egressOperations.callService("echo").asHttpsEchoResponse() + val echoDisabledResponse = envoy.egressOperations.callService("echo-disabled").asHttpsEchoResponse() + val echoOneTagResponse = envoy.egressOperations.callService("echo-one-tag").asHttpsEchoResponse() + val echoNoTagResponse = envoy.egressOperations.callService("echo-no-tag").asHttpsEchoResponse() + + // then + assertThat(echoResponse).isOk() + assertThat(echoResponse.requestHeaders).containsEntry("x-service-tag-preference", "ipsum|lorem") + + assertThat(echoDisabledResponse).isOk() + assertThat(echoDisabledResponse.requestHeaders).doesNotContainKey("x-service-tag-preference") + + assertThat(echoOneTagResponse).isOk() + assertThat(echoOneTagResponse.requestHeaders).containsEntry("x-service-tag-preference", "one") + + assertThat(echoNoTagResponse).isOk() + assertThat(echoNoTagResponse.requestHeaders).doesNotContainKey("x-service-tag-preference") + } + + @Test + fun `should not override service-tag preference header already set in the request`() { + // TODO(implement) + throw NotImplementedError("Service tag preference header already set") + } + + @Test + fun `should return upstream service tags in response if service-tag preference was used`() { + // given + listOf("echo", "echo-disabled").forEach { service -> + consul.server.operations.registerService(name = service, extension = echoService, tags = allTags) + } + listOf("echo", "echo-disabled").forEach { service -> + waitForEndpointReady(service, echoService, envoy) + } + + // when + val echoResponse = envoy.egressOperations.callService("echo") + val echoDisabledResponse = envoy.egressOperations.callService("echo-disabled") + + // then + assertThat(echoResponse.headers("x-envoy-upstream-service-tags")).isEqualTo(listOf("""["ipsum","lorem","one"]""")) + assertThat(echoDisabledResponse.headers("x-envoy-upstream-service-tags")).isEmpty() + } + + private fun waitForEndpointReady( + serviceName: String, + serviceInstance: ServiceExtension<*>, + envoy: EnvoyExtension + ) { + envoy.waitForClusterEndpointHealthy(cluster = serviceName, endpointIp = serviceInstance.container().ipAddress()) + } +} diff --git a/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/ServiceTagPreferenceTest.kt b/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/ServiceTagPreferenceTest.kt index f364fbbb9..320260bac 100644 --- a/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/ServiceTagPreferenceTest.kt +++ b/envoy-control-tests/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/routing/ServiceTagPreferenceTest.kt @@ -1,123 +1,8 @@ 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.assertions.isOk -import pl.allegro.tech.servicemesh.envoycontrol.config.RandomConfigFile -import pl.allegro.tech.servicemesh.envoycontrol.config.consul.ConsulExtension -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.GenericServiceExtension -import pl.allegro.tech.servicemesh.envoycontrol.config.service.HttpsEchoContainer -import pl.allegro.tech.servicemesh.envoycontrol.config.service.ServiceExtension -import pl.allegro.tech.servicemesh.envoycontrol.config.service.asHttpsEchoResponse - class ServiceTagPreferenceTest { companion object { - private 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 - ) - - @JvmField - @RegisterExtension - val consul = ConsulExtension() - - @JvmField - @RegisterExtension - val envoyControl = EnvoyControlExtension(consul, properties) - - @JvmField - @RegisterExtension - val echoService = GenericServiceExtension(HttpsEchoContainer()) - - // language=yaml - private var proxySettings = """ - node: - metadata: - proxy_settings: - outgoing: - routingPolicy: - autoServiceTag: true - serviceTagPreference: ["ipsum", "lorem"] - fallbackToAnyInstance: true - dependencies: - - service: "echo" - - service: "echo-disabled" - routingPolicy: - autoServiceTag: false - - service: "echo-one-tag" - routingPolicy: - serviceTagPreference: ["one"] - - service: "echo-no-tag" - routingPolicy: - serviceTagPreference: [] - - """.trimIndent() - - @JvmField - @RegisterExtension - val envoy = EnvoyExtension(envoyControl, config = RandomConfigFile.copy(configOverride = proxySettings)) - - private val allTags = listOf("ipsum", "lorem", "one") - } - - @Test - fun `should add correct x-service-tag-preference header to upstream request`() { - // given - listOf("echo", "echo-disabled", "echo-one-tag", "echo-no-tag").forEach { service -> - consul.server.operations.registerService(name = service, extension = echoService, tags = allTags) - } - listOf("echo", "echo-disabled", "echo-one-tag", "echo-no-tag").forEach { service -> - waitForEndpointReady(service, echoService, envoy) - } - - // when - val echoResponse = envoy.egressOperations.callService("echo").asHttpsEchoResponse() - val echoDisabledResponse = envoy.egressOperations.callService("echo-disabled").asHttpsEchoResponse() - val echoOneTagResponse = envoy.egressOperations.callService("echo-one-tag").asHttpsEchoResponse() - val echoNoTagResponse = envoy.egressOperations.callService("echo-no-tag").asHttpsEchoResponse() - - // then - assertThat(echoResponse).isOk() - assertThat(echoResponse.requestHeaders).containsEntry("x-service-tag-preference", "ipsum|lorem") - - assertThat(echoDisabledResponse).isOk() - assertThat(echoDisabledResponse.requestHeaders).doesNotContainKey("x-service-tag-preference") - - assertThat(echoOneTagResponse).isOk() - assertThat(echoOneTagResponse.requestHeaders).containsEntry("x-service-tag-preference", "one") - - assertThat(echoNoTagResponse).isOk() - assertThat(echoNoTagResponse.requestHeaders).doesNotContainKey("x-service-tag-preference") - } - - @Test - fun `should return upstream service tags in response if service-tag preference was used`() { - // given - listOf("echo", "echo-disabled").forEach { service -> - consul.server.operations.registerService(name = service, extension = echoService, tags = allTags) - } - listOf("echo", "echo-disabled").forEach { service -> - waitForEndpointReady(service, echoService, envoy) - } - - // when - val echoResponse = envoy.egressOperations.callService("echo") - val echoDisabledResponse = envoy.egressOperations.callService("echo-disabled") - - // then - assertThat(echoResponse.headers("x-envoy-upstream-service-tags")).isEqualTo(listOf("""["ipsum","lorem","one"]""")) - assertThat(echoDisabledResponse.headers("x-envoy-upstream-service-tags")).isEmpty() - } - private fun waitForEndpointReady( - serviceName: String, - serviceInstance: ServiceExtension<*>, - envoy: EnvoyExtension - ) { - envoy.waitForClusterEndpointHealthy(cluster = serviceName, endpointIp = serviceInstance.container().ipAddress()) } } diff --git a/envoy-control-tests/src/main/resources/envoy/empty.yaml b/envoy-control-tests/src/main/resources/envoy/empty.yaml new file mode 100644 index 000000000..dd1349652 --- /dev/null +++ b/envoy-control-tests/src/main/resources/envoy/empty.yaml @@ -0,0 +1,2 @@ +# TODO: to delete +{}