diff --git a/pkg/app/pipedv1/plugin/kubernetes/deployment/determine.go b/pkg/app/pipedv1/plugin/kubernetes/deployment/determine.go index 717b69ffb6..443d39f39f 100644 --- a/pkg/app/pipedv1/plugin/kubernetes/deployment/determine.go +++ b/pkg/app/pipedv1/plugin/kubernetes/deployment/determine.go @@ -124,3 +124,35 @@ func findWorkloadManifests(manifests []provider.Manifest, refs []config.K8sResou } return workloads } + +type workloadPair struct { + old provider.Manifest + new provider.Manifest +} + +func findUpdatedWorkloads(olds, news []provider.Manifest) []workloadPair { + pairs := make([]workloadPair, 0) + oldMap := make(map[provider.ResourceKey]provider.Manifest, len(olds)) + nomalizeKey := func(k provider.ResourceKey) provider.ResourceKey { + // Ignoring APIVersion because user can upgrade to the new APIVersion for the same workload. + k.APIVersion = "" + if k.Namespace == provider.DefaultNamespace { + k.Namespace = "" + } + return k + } + for _, m := range olds { + key := nomalizeKey(m.Key) + oldMap[key] = m + } + for _, n := range news { + key := nomalizeKey(n.Key) + if o, ok := oldMap[key]; ok { + pairs = append(pairs, workloadPair{ + old: o, + new: n, + }) + } + } + return pairs +} diff --git a/pkg/app/pipedv1/plugin/kubernetes/deployment/determine_test.go b/pkg/app/pipedv1/plugin/kubernetes/deployment/determine_test.go index 84a9824693..2127e8de5e 100644 --- a/pkg/app/pipedv1/plugin/kubernetes/deployment/determine_test.go +++ b/pkg/app/pipedv1/plugin/kubernetes/deployment/determine_test.go @@ -44,6 +44,15 @@ func mustUnmarshalYAML[T any](t *testing.T, data []byte) T { return m } +func mustParseManifests(t *testing.T, data string) []provider.Manifest { + t.Helper() + + manifests, err := provider.ParseManifests(data) + require.NoError(t, err) + + return manifests +} + func TestParseContainerImage(t *testing.T) { tests := []struct { name string @@ -621,3 +630,222 @@ spec: }) } } + +func TestFindUpdatedWorkloads(t *testing.T) { + tests := []struct { + name string + olds []string + news []string + want []workloadPair + }{ + { + name: "single updated workload", + olds: []string{ + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.3 +`, + }, + news: []string{ + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.4 +`, + }, + want: []workloadPair{ + { + old: mustParseManifests(t, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.3 +`)[0], + new: mustParseManifests(t, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.4 +`)[0], + }, + }, + }, + { + name: "multiple updated workloads", + olds: []string{ + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.3 +`, + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deployment +spec: + template: + spec: + containers: + - name: redis + image: redis:6.0.9 +`, + }, + news: []string{ + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.4 +`, + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deployment +spec: + template: + spec: + containers: + - name: redis + image: redis:6.0.10 +`, + }, + want: []workloadPair{ + { + old: mustParseManifests(t, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.3 +`)[0], + new: mustParseManifests(t, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.4 +`)[0], + }, + { + old: mustParseManifests(t, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deployment +spec: + template: + spec: + containers: + - name: redis + image: redis:6.0.9 +`)[0], + new: mustParseManifests(t, ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deployment +spec: + template: + spec: + containers: + - name: redis + image: redis:6.0.10 +`)[0], + }, + }, + }, + { + name: "no updated workloads", + olds: []string{ + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + template: + spec: + containers: + - name: nginx + image: nginx:1.19.3 +`, + }, + news: []string{ + ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deployment +spec: + template: + spec: + containers: + - name: redis + image: redis:7.0.0 +`, + }, + want: []workloadPair{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + oldManifests := mustParseManifests(t, strings.Join(tt.olds, "\n---\n")) + newManifests := mustParseManifests(t, strings.Join(tt.news, "\n---\n")) + got := findUpdatedWorkloads(oldManifests, newManifests) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/app/pipedv1/plugin/kubernetes/provider/resource.go b/pkg/app/pipedv1/plugin/kubernetes/provider/resource.go index 35e5f009aa..0b99d1dd81 100644 --- a/pkg/app/pipedv1/plugin/kubernetes/provider/resource.go +++ b/pkg/app/pipedv1/plugin/kubernetes/provider/resource.go @@ -60,6 +60,8 @@ var builtInAPIVersions = map[string]struct{}{ const ( KindDeployment = "Deployment" KindSecret = "Secret" + + DefaultNamespace = "default" ) type ResourceKey struct {