From 58c0ab52a9024118f34d4e5d5e0308bfacfcb405 Mon Sep 17 00:00:00 2001
From: "nastassia.dailidava" <nastassia.dailidava@allegrogroup.com>
Date: Wed, 16 Oct 2024 12:10:52 +0200
Subject: [PATCH 1/2] allegro-internal/flex-roadmap#814 Added service-specific
 zone priorities

---
 .../snapshot/SnapshotProperties.kt            |  1 +
 .../endpoints/EnvoyEndpointsFactory.kt        | 12 +++--
 .../endpoints/EnvoyEndpointsFactoryTest.kt    | 45 ++++++++++++++++++-
 3 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/SnapshotProperties.kt b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/SnapshotProperties.kt
index 6c64b7405..228e6c188 100644
--- a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/SnapshotProperties.kt
+++ b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/SnapshotProperties.kt
@@ -157,6 +157,7 @@ class LoadBalancingProperties {
     var policy = Cluster.LbPolicy.LEAST_REQUEST
     var useKeysSubsetFallbackPolicy = true
     var priorities = LoadBalancingPriorityProperties()
+    var servicePriorities: Map<String, LoadBalancingPriorityProperties> = mapOf()
 }
 
 class CanaryProperties {
diff --git a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactory.kt b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactory.kt
index b6ab798e3..483911b19 100644
--- a/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactory.kt
+++ b/envoy-control-core/src/main/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactory.kt
@@ -188,7 +188,7 @@ class EnvoyEndpointsFactory(
                 ?.map {
                     createLbEndpoint(it, serviceInstances.serviceName, locality)
                 } ?: emptyList())
-            .setPriority(toEnvoyPriority(zone, locality))
+            .setPriority(toEnvoyPriority(zone, locality, serviceInstances))
             .build()
     }
 
@@ -286,8 +286,14 @@ class EnvoyEndpointsFactory(
             false -> this
         }
 
-    private fun toEnvoyPriority(zone: String, locality: Locality): Int {
-        val zonePriorities = properties.loadBalancing.priorities.zonePriorities
+    private fun toEnvoyPriority(zone: String, locality: Locality, serviceInstances: ServiceInstances?): Int {
+        var zonePriorities = properties.loadBalancing.priorities.zonePriorities
+        serviceInstances?.let {
+            if (properties.loadBalancing.servicePriorities.containsKey(serviceInstances.serviceName)) {
+                zonePriorities =
+                    properties.loadBalancing.servicePriorities[serviceInstances.serviceName]!!.zonePriorities
+            }
+        }
         return when (zonePriorities.isNotEmpty()) {
             true -> zonePriorities[currentZone]?.get(zone) ?: toEnvoyPriority(locality)
             false -> toEnvoyPriority(locality)
diff --git a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactoryTest.kt b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactoryTest.kt
index de151d627..b3c787a0e 100644
--- a/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactoryTest.kt
+++ b/envoy-control-core/src/test/kotlin/pl/allegro/tech/servicemesh/envoycontrol/snapshot/resource/endpoints/EnvoyEndpointsFactoryTest.kt
@@ -406,6 +406,40 @@ internal class EnvoyEndpointsFactoryTest {
             .anySatisfy { it.hasZoneWithPriority("DC3", 2) }
     }
 
+    @Test
+    fun `should create load assignment with service zone priorities`() {
+        val envoyEndpointsFactory = EnvoyEndpointsFactory(
+            snapshotPropertiesWithPriorities
+                (
+                mapOf("DC2" to mapOf("DC1" to 1, "DC2" to 1, "DC3" to 1)),
+                mapOf("DC2" to mapOf("DC1" to 2, "DC2" to 2, "DC3" to 2)),
+                serviceName
+            ),
+            currentZone = "DC2"
+        )
+        val loadAssignments = envoyEndpointsFactory.createLoadAssignment(setOf(serviceName), multiClusterStateDC2Local)
+        loadAssignments.assertHasLoadAssignment(
+            mapOf("DC1" to 2, "DC2" to 2, "DC3" to 2)
+        )
+    }
+
+    @Test
+    fun `should create load assignment with global zone priorities when no service config found`() {
+        val envoyEndpointsFactory = EnvoyEndpointsFactory(
+            snapshotPropertiesWithPriorities
+                (
+                mapOf("DC2" to mapOf("DC1" to 1, "DC2" to 1, "DC3" to 1)),
+                mapOf("DC2" to mapOf("DC1" to 2, "DC2" to 2, "DC3" to 2)),
+                "another-service"
+            ),
+            currentZone = "DC2"
+        )
+        val loadAssignments = envoyEndpointsFactory.createLoadAssignment(setOf(serviceName), multiClusterStateDC2Local)
+        loadAssignments.assertHasLoadAssignment(
+            mapOf("DC1" to 1, "DC2" to 1, "DC3" to 1)
+        )
+    }
+
     private fun List<ClusterLoadAssignment>.assertHasLoadAssignment(map: Map<String, Int>) {
         assertThat(this)
             .isNotEmpty()
@@ -453,13 +487,22 @@ internal class EnvoyEndpointsFactoryTest {
         assertThat(this.locality.zone).isEqualTo(zone)
     }
 
-    private fun snapshotPropertiesWithPriorities(priorities: Map<String, Map<String, Int>>) =
+    private fun snapshotPropertiesWithPriorities(
+        priorities: Map<String, Map<String, Int>>,
+        servicePriorities: Map<String, Map<String, Int>> = mapOf(),
+        serviceName: String? = null
+    ) =
         SnapshotProperties().apply {
             loadBalancing = LoadBalancingProperties()
                 .apply {
                     this.priorities = LoadBalancingPriorityProperties().apply {
                         zonePriorities = priorities
                     }
+                    serviceName?.let {
+                        this.servicePriorities = mapOf(serviceName to LoadBalancingPriorityProperties().apply {
+                            zonePriorities = servicePriorities
+                        })
+                    }
                 }
         }
 

From a045c54363e5bfd883c25c4ee5ec1ffa5a727090 Mon Sep 17 00:00:00 2001
From: "nastassia.dailidava" <nastassia.dailidava@allegrogroup.com>
Date: Wed, 16 Oct 2024 12:12:04 +0200
Subject: [PATCH 2/2] allegro-internal/flex-roadmap#814 Added service-specific
 zone priorities

---
 CHANGELOG.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25dd586c6..e47c4de73 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 Lists all changes with user impact.
 The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
+## [0.22.3]
+### Changed
+- Added service-specific zone priorities
+
 ## [0.22.2]
 ### Changed
 - Migrated metrics to prometheus