Repository: kumahq/kuma
Pull request #2512 (2021-08-06 12:19:34)

fix(kuma-cp): Sort services by name when selecting them (backport #2505)
This is an automatic backport of pull request #2505 done by [Mergify](https://mergify.io).
Cherry-pick of d22deab9f9beb7dfafb2ec332478bd1b53d78d6f has failed:
```
On branch mergify/bp/release-1.2/pr-2505
Your branch is up to date with 'origin/release-1.2'.

You are currently cherry-picking commit d22deab9.
  (fix conflicts and run "git cherry-pick --continue")
  (use "git cherry-pick --skip" to skip this patch)
  (use "git cherry-pick --abort" to cancel the cherry-pick operation)

Changes to be committed:
	modified:   pkg/plugins/runtime/k8s/util/util.go

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   pkg/plugins/runtime/k8s/util/util_test.go

```


To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/github/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally

---


<details>
<summary>Mergify commands and options</summary>

<br />

More conditions and actions can be found in the [documentation](https://docs.mergify.io/).

You can also trigger Mergify actions by commenting on this pull request:

- `@Mergifyio refresh` will re-evaluate the rules
- `@Mergifyio rebase` will rebase this PR on its base branch
- `@Mergifyio update` will merge the base branch into this PR
- `@Mergifyio backport <destination>` will backport this PR on `<destination>` branch

Additionally, on Mergify [dashboard](https://dashboard.mergify.io/) you can:

- look at your merge queues
- generate the Mergify configuration with the config editor.

Finally, you can contact us on https://mergify.io/
</details>


codecov-commenter: # [Codecov](https://codecov.io/gh/kumahq/kuma/pull/2512?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq) Report
> :exclamation: No coverage uploaded for pull request base (`release-1.2@3c502ff`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq#section-missing-base-commit).
> The diff coverage is `n/a`.

> :exclamation: Current head d22deab differs from pull request most recent head 6dfea5f. Consider uploading reports for the commit 6dfea5f to get more accurate results
[![Impacted file tree graph](https://codecov.io/gh/kumahq/kuma/pull/2512/graphs/tree.svg?width=650&height=150&src=pr&token=D7Yvqs6rwV&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq)](https://codecov.io/gh/kumahq/kuma/pull/2512?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq)

```diff
@@              Coverage Diff               @@
##             release-1.2    #2512   +/-   ##
==============================================
  Coverage               ?   52.14%           
==============================================
  Files                  ?      866           
  Lines                  ?    48307           
  Branches               ?        0           
==============================================
  Hits                   ?    25191           
  Misses                 ?    21080           
  Partials               ?     2036           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/kumahq/kuma/pull/2512?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/kumahq/kuma/pull/2512?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq). Last update [3c502ff...6dfea5f](https://codecov.io/gh/kumahq/kuma/pull/2512?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq).


Patch:
diff --git a/pkg/plugins/runtime/k8s/util/util.go b/pkg/plugins/runtime/k8s/util/util.go
index 7edd7ce94..9b3095c0d 100644
--- a/pkg/plugins/runtime/k8s/util/util.go
+++ b/pkg/plugins/runtime/k8s/util/util.go
@@ -2,6 +2,7 @@ package util
 
 import (
 	"fmt"
+	"sort"
 
 	kube_core "k8s.io/api/core/v1"
 	kube_labels "k8s.io/apimachinery/pkg/labels"
@@ -42,6 +43,10 @@ func FindServices(svcs *kube_core.ServiceList, predicates ...ServicePredicate) [
 			matching = append(matching, svc)
 		}
 	}
+	// Sort by name so that inbound order is similar across zones regardless of the order services got created.
+	sort.Slice(matching, func(i, j int) bool {
+		return matching[i].Name < matching[j].Name
+	})
 	return matching
 }
 


Test patch:
diff --git a/pkg/plugins/runtime/k8s/util/util_test.go b/pkg/plugins/runtime/k8s/util/util_test.go
index eac54dc0f..5aed0b0d3 100644
--- a/pkg/plugins/runtime/k8s/util/util_test.go
+++ b/pkg/plugins/runtime/k8s/util/util_test.go
@@ -1,6 +1,8 @@
 package util_test
 
 import (
+	"time"
+
 	"github.com/ghodss/yaml"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/ginkgo/extensions/table"
@@ -64,19 +66,31 @@ var _ = Describe("Util", func() {
 		})
 	})
 
-	Describe("FindServices", func() {
-		It("should match Services by a predicate", func() {
-			// given
-			pod := &kube_core.Pod{
+	exampleTime := time.Date(2020, 01, 01, 01, 12, 00, 00, time.UTC)
+	DescribeTable("FindServices",
+		func(pod *kube_core.Pod, svcs *kube_core.ServiceList, matchSvcNames []string) {
+			// when
+			matchingServices := FindServices(svcs, AnySelector(), MatchServiceThatSelectsPod(pod))
+			// then
+			Expect(matchingServices).To(WithTransform(func(svcs []*kube_core.Service) []string {
+				var res []string
+				for i := range svcs {
+					res = append(res, svcs[i].Name)
+				}
+				return res
+			}, Equal(matchSvcNames)))
+		},
+		Entry("should match services by a predicate",
+			&kube_core.Pod{
 				ObjectMeta: kube_meta.ObjectMeta{
 					Labels: map[string]string{
 						"app":               "demo-app",
 						"pod-template-hash": "7cbbd658d5",
 					},
 				},
-			}
+			},
 			// and
-			svcs := &kube_core.ServiceList{
+			&kube_core.ServiceList{
 				Items: []kube_core.Service{
 					{
 						ObjectMeta: kube_meta.ObjectMeta{
@@ -106,15 +120,67 @@ var _ = Describe("Util", func() {
 						Spec: kube_core.ServiceSpec{},
 					},
 				},
-			}
-
-			// when
-			matchingServices := FindServices(svcs, AnySelector(), MatchServiceThatSelectsPod(pod))
-			// then
-			Expect(matchingServices).To(HaveLen(1))
-			Expect(matchingServices).To(ConsistOf(&svcs.Items[0]))
-		})
-	})
+			},
+			[]string{"demo-app"},
+		),
+		Entry("should match multiple services in order",
+			&kube_core.Pod{
+				ObjectMeta: kube_meta.ObjectMeta{
+					Labels: map[string]string{
+						"app":               "demo-app",
+						"pod-template-hash": "7cbbd658d5",
+					},
+				},
+			},
+			// and
+			&kube_core.ServiceList{
+				Items: []kube_core.Service{
+					{
+						ObjectMeta: kube_meta.ObjectMeta{
+							CreationTimestamp: kube_meta.NewTime(exampleTime),
+							Name:              "demo-app2",
+						},
+						Spec: kube_core.ServiceSpec{
+							Selector: map[string]string{
+								"app": "demo-app",
+							},
+						},
+					},
+					{
+						ObjectMeta: kube_meta.ObjectMeta{
+							CreationTimestamp: kube_meta.NewTime(exampleTime),
+							Name:              "demo-app",
+						},
+						Spec: kube_core.ServiceSpec{
+							Selector: map[string]string{
+								"app": "demo-app",
+							},
+						},
+					},
+					{
+						ObjectMeta: kube_meta.ObjectMeta{
+							CreationTimestamp: kube_meta.NewTime(exampleTime.Add(-time.Hour)),
+							Name:              "nginx",
+						},
+						Spec: kube_core.ServiceSpec{
+							Selector: map[string]string{
+								"app": "demo-app",
+							},
+						},
+					},
+					{
+						ObjectMeta: kube_meta.ObjectMeta{
+							CreationTimestamp: kube_meta.NewTime(exampleTime),
+							Name:              "kubernetes",
+							Namespace:         "default",
+						},
+						Spec: kube_core.ServiceSpec{},
+					},
+				},
+			},
+			[]string{"demo-app", "demo-app2", "nginx"},
+		),
+	)
 
 	Describe("CopyStringMap", func() {
 		It("should return nil if input is nil", func() {