From e3d753bd651ae92c3fe0faa38f2bca220ae2db6e Mon Sep 17 00:00:00 2001
From: Diego Alfonso <dalfonso@vmware.com>
Date: Wed, 24 May 2023 17:01:58 -0500
Subject: [PATCH 1/7] fix: Update subpath from DeepCopy instead of pointer

Signed-off-by: Diego Alfonso <dalfonso@vmware.com>
---
 .../cartographer/v1alpha1/workload_helpers.go |  9 +++++----
 .../cartographer/v1alpha1/workload_test.go    | 19 -------------------
 2 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/pkg/apis/cartographer/v1alpha1/workload_helpers.go b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
index ba38ebcad..721af95b2 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_helpers.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
@@ -222,7 +222,8 @@ func (w *WorkloadSpec) Merge(updates *WorkloadSpec) {
 	if updates.Image != "" {
 		w.MergeImage(updates.Image)
 	}
-	if s := updates.Source; s != nil {
+	if updates.Source != nil {
+		s := updates.Source.DeepCopy()
 		if s.Git != nil {
 			w.MergeGit(*s.Git)
 		}
@@ -326,7 +327,7 @@ func (w *WorkloadSpec) ResetSource() {
 }
 
 func (w *WorkloadSpec) MergeGit(git GitSource) {
-	stash := w.Source
+	stash := w.Source.DeepCopy()
 	image := w.Image
 	w.ResetSource()
 
@@ -348,13 +349,13 @@ func (w *WorkloadSpec) MergeGit(git GitSource) {
 }
 
 func (w *WorkloadSpec) MergeSourceImage(image string) {
-	stash := w.Source
+	stash := w.Source.DeepCopy()
 	w.ResetSource()
 
 	w.Source = &Source{
 		Image: image,
 	}
-	if stash != nil && stash.Image != "" {
+	if stash != nil && stash.Subpath != "" {
 		w.Source.Subpath = stash.Subpath
 	}
 }
diff --git a/pkg/apis/cartographer/v1alpha1/workload_test.go b/pkg/apis/cartographer/v1alpha1/workload_test.go
index cc3678fe1..ac0aecef1 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_test.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_test.go
@@ -1884,25 +1884,6 @@ func TestWorkloadSpec_MergeSourceImage(t *testing.T) {
 				Subpath: "my-subpath",
 			},
 		},
-	}, {
-		name: "update deleting subpath",
-		seed: &WorkloadSpec{
-			Source: &Source{
-				Git: &GitSource{
-					URL: "git@github.com:example/repo.git",
-					Ref: GitRef{
-						Branch: "main",
-					},
-				},
-				Subpath: "my-subpath",
-			},
-		},
-		sourceImage: "my-registry.nip.io/my-folder/my-image:latest@sha:my-sha1234567890",
-		want: &WorkloadSpec{
-			Source: &Source{
-				Image: "my-registry.nip.io/my-folder/my-image:latest@sha:my-sha1234567890",
-			},
-		},
 	}}
 
 	for _, test := range tests {

From fd3b47a123e91e793c2481455e0cda54fe2007d2 Mon Sep 17 00:00:00 2001
From: Diego Alfonso <dalfonso@vmware.com>
Date: Thu, 25 May 2023 11:01:42 -0500
Subject: [PATCH 2/7] chore: Add test for source updated

Signed-off-by: Diego Alfonso <dalfonso@vmware.com>
---
 .../testdata/workload-lsp-subPath.yaml        | 31 ++++++++
 pkg/commands/workload_apply_test.go           | 70 +++++++++++++++++++
 2 files changed, 101 insertions(+)
 create mode 100644 pkg/commands/testdata/workload-lsp-subPath.yaml

diff --git a/pkg/commands/testdata/workload-lsp-subPath.yaml b/pkg/commands/testdata/workload-lsp-subPath.yaml
new file mode 100644
index 000000000..1137155c4
--- /dev/null
+++ b/pkg/commands/testdata/workload-lsp-subPath.yaml
@@ -0,0 +1,31 @@
+# Copyright 2023 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: carto.run/v1alpha1
+kind: Workload
+metadata:
+  annotations:
+    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+  labels:
+    apps.tanzu.vmware.com/workload-type: web
+  name: my-workload
+  namespace: default
+spec:
+  params:
+    - name: annotations
+      value:
+        autoscaling.knative.dev/minScale: "2"
+  source:
+    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+    subPath: new-subpath
diff --git a/pkg/commands/workload_apply_test.go b/pkg/commands/workload_apply_test.go
index a1a94bca8..7620bf232 100644
--- a/pkg/commands/workload_apply_test.go
+++ b/pkg/commands/workload_apply_test.go
@@ -8909,6 +8909,76 @@ To get status: "tanzu apps workload get my-workload"
 				}
 			},
 		},
+		{
+			Name: "update from local source using lsp changing subpath",
+			Skip: runtm.GOOS == "windows",
+			Args: []string{workloadName, flags.LocalPathFlagName, localSource, flags.FilePathFlagName, "./testdata/workload-lsp-subPath.yaml", flags.YesFlagName},
+			GivenObjects: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(&cartov1alpha1.Source{
+						Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+						Subpath: "old-subpath",
+					})
+				}),
+			},
+			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
+			ExpectUpdates: []client.Object{
+				&cartov1alpha1.Workload{
+					ObjectMeta: metav1.ObjectMeta{
+						Namespace: defaultNamespace,
+						Name:      workloadName,
+						Labels: map[string]string{
+							apis.WorkloadTypeLabelName: "web",
+						},
+						Annotations: map[string]string{
+							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+						},
+					},
+					Spec: cartov1alpha1.WorkloadSpec{
+						Source: &cartov1alpha1.Source{
+							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Subpath: "new-subpath",
+						},
+						Params: []cartov1alpha1.Param{
+							{
+								Name:  "annotations",
+								Value: apiextensionsv1.JSON{Raw: []byte(`{"autoscaling.knative.dev/minScale":"2"}`)},
+							},
+						},
+					},
+				},
+			},
+			ExpectOutput: fmt.Sprintf(`
+❗ WARNING: Configuration file update strategy is changing. By default, provided configuration files will replace rather than merge existing configuration. The change will take place in the January 2024 TAP release (use "--update-strategy" to control strategy explicitly).
+
+Publishing source in "%s" to "local-source-proxy.tap-local-source-system.svc.cluster.local/source:default-my-workload"...
+No source code is changed
+
+🔎 Update workload:
+...
+  8,  8   |    apps.tanzu.vmware.com/workload-type: web
+  9,  9   |  name: my-workload
+ 10, 10   |  namespace: default
+ 11, 11   |spec:
+     12 + |  params:
+     13 + |  - name: annotations
+     14 + |    value:
+     15 + |      autoscaling.knative.dev/minScale: "2"
+ 12, 16   |  source:
+ 13, 17   |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+ 14     - |    subPath: old-subpath
+     18 + |    subPath: new-subpath
+👍 Updated workload "my-workload"
+
+To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
+To get status: "tanzu apps workload get my-workload"
+
+`, localSource),
+		},
 	}
 
 	table.Run(t, scheme, func(ctx context.Context, c *cli.Config) *cobra.Command {

From 570becafe9816a90c6ea9e62fbf46ece4a6ca57d Mon Sep 17 00:00:00 2001
From: Diego Alfonso <dalfonso@vmware.com>
Date: Thu, 25 May 2023 11:27:46 -0500
Subject: [PATCH 3/7] chore: Remove extra empty subpath validation on
 MergeSourceImage

Signed-off-by: Diego Alfonso <dalfonso@vmware.com>
---
 pkg/apis/cartographer/v1alpha1/workload_helpers.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pkg/apis/cartographer/v1alpha1/workload_helpers.go b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
index 721af95b2..5df482859 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_helpers.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
@@ -355,7 +355,7 @@ func (w *WorkloadSpec) MergeSourceImage(image string) {
 	w.Source = &Source{
 		Image: image,
 	}
-	if stash != nil && stash.Subpath != "" {
+	if stash != nil {
 		w.Source.Subpath = stash.Subpath
 	}
 }

From 081a2d729211a7acad5dfb6d3488d2a76f8fec26 Mon Sep 17 00:00:00 2001
From: Diego Alfonso <dalfonso@vmware.com>
Date: Thu, 25 May 2023 13:34:41 -0500
Subject: [PATCH 4/7] fix: Update subpath only if provided when merge

Signed-off-by: Diego Alfonso <dalfonso@vmware.com>
---
 .../cartographer/v1alpha1/workload_helpers.go | 23 +++----
 .../cartographer/v1alpha1/workload_test.go    | 57 ++++++++-------
 .../testdata/workload-lsp-non-subPath.yaml    | 30 ++++++++
 pkg/commands/workload_apply_test.go           | 69 +++++++++++++++++++
 4 files changed, 141 insertions(+), 38 deletions(-)
 create mode 100644 pkg/commands/testdata/workload-lsp-non-subPath.yaml

diff --git a/pkg/apis/cartographer/v1alpha1/workload_helpers.go b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
index 5df482859..9fbbf2a0f 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_helpers.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
@@ -219,9 +219,6 @@ func (w *WorkloadSpec) Merge(updates *WorkloadSpec) {
 	for _, p := range updates.Params {
 		w.MergeParams(p.Name, p.Value)
 	}
-	if updates.Image != "" {
-		w.MergeImage(updates.Image)
-	}
 	if updates.Source != nil {
 		s := updates.Source.DeepCopy()
 		if s.Git != nil {
@@ -234,6 +231,9 @@ func (w *WorkloadSpec) Merge(updates *WorkloadSpec) {
 			w.MergeSubPath(s.Subpath)
 		}
 	}
+	if updates.Image != "" {
+		w.MergeImage(updates.Image)
+	}
 	for _, e := range updates.Env {
 		w.MergeEnv(e)
 	}
@@ -342,35 +342,30 @@ func (w *WorkloadSpec) MergeGit(git GitSource) {
 		w.Source = &Source{
 			Git: &git,
 		}
-		if stash != nil && stash.Git != nil {
+		if stash != nil && stash.Subpath != "" {
 			w.Source.Subpath = stash.Subpath
 		}
 	}
 }
 
 func (w *WorkloadSpec) MergeSourceImage(image string) {
-	stash := w.Source.DeepCopy()
-	w.ResetSource()
-
-	w.Source = &Source{
-		Image: image,
-	}
-	if stash != nil {
-		w.Source.Subpath = stash.Subpath
+	src := &Source{Image: image}
+	if w.Source != nil {
+		src.Subpath = w.Source.Subpath
 	}
+	w.ResetSource()
+	w.Source = src
 }
 
 func (w *WorkloadSpec) MergeSubPath(subPath string) {
 	if w.Source == nil {
 		w.Source = &Source{}
 	}
-
 	w.Source.Subpath = subPath
 }
 
 func (w *WorkloadSpec) MergeImage(image string) {
 	w.ResetSource()
-
 	w.Image = image
 }
 
diff --git a/pkg/apis/cartographer/v1alpha1/workload_test.go b/pkg/apis/cartographer/v1alpha1/workload_test.go
index ac0aecef1..3bdf34bde 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_test.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_test.go
@@ -1001,6 +1001,39 @@ func TestWorkload_Merge(t *testing.T) {
 				Image: "ubuntu:bionic",
 			},
 		},
+	}, {
+		name: "image without source",
+		seed: &Workload{},
+		update: &Workload{
+			Spec: WorkloadSpec{
+				Image: "ubuntu:bionic",
+			},
+		},
+		want: &Workload{
+			Spec: WorkloadSpec{
+				Image: "ubuntu:bionic",
+			},
+		},
+	}, {
+		name: "image with subpath",
+		seed: &Workload{
+			Spec: WorkloadSpec{
+				Image: "alpine:latest",
+				Source: &Source{
+					Subpath: "/sys",
+				},
+			},
+		},
+		update: &Workload{
+			Spec: WorkloadSpec{
+				Image: "ubuntu:bionic",
+			},
+		},
+		want: &Workload{
+			Spec: WorkloadSpec{
+				Image: "ubuntu:bionic",
+			},
+		},
 	}, {
 		name: "git",
 		seed: &Workload{
@@ -1767,30 +1800,6 @@ func TestWorkloadSpec_MergeGit(t *testing.T) {
 				Subpath: "my-subpath",
 			},
 		},
-	}, {
-		name: "update to git source deleting subpath",
-		seed: &WorkloadSpec{
-			Source: &Source{
-				Image:   "my-registry.nip.io/my-folder/my-image:latest@sha:my-sha1234567890",
-				Subpath: "my-subpath",
-			},
-		},
-		git: GitSource{
-			URL: "git@github.com:example/repo.git",
-			Ref: GitRef{
-				Branch: "main",
-			},
-		},
-		want: &WorkloadSpec{
-			Source: &Source{
-				Git: &GitSource{
-					URL: "git@github.com:example/repo.git",
-					Ref: GitRef{
-						Branch: "main",
-					},
-				},
-			},
-		},
 	}, {
 		name: "delete source when setting repo to empty string",
 		seed: &WorkloadSpec{
diff --git a/pkg/commands/testdata/workload-lsp-non-subPath.yaml b/pkg/commands/testdata/workload-lsp-non-subPath.yaml
new file mode 100644
index 000000000..ff03e1c25
--- /dev/null
+++ b/pkg/commands/testdata/workload-lsp-non-subPath.yaml
@@ -0,0 +1,30 @@
+# Copyright 2023 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: carto.run/v1alpha1
+kind: Workload
+metadata:
+  annotations:
+    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+  labels:
+    apps.tanzu.vmware.com/workload-type: web
+  name: my-workload
+  namespace: default
+spec:
+  params:
+    - name: annotations
+      value:
+        autoscaling.knative.dev/minScale: "2"
+  source:
+    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
diff --git a/pkg/commands/workload_apply_test.go b/pkg/commands/workload_apply_test.go
index 7620bf232..2d66c12d4 100644
--- a/pkg/commands/workload_apply_test.go
+++ b/pkg/commands/workload_apply_test.go
@@ -8977,6 +8977,75 @@ No source code is changed
 To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
 To get status: "tanzu apps workload get my-workload"
 
+`, localSource),
+		},
+		{
+			Name: "update from local source using lsp from file without subpath",
+			Skip: runtm.GOOS == "windows",
+			Args: []string{workloadName, flags.LocalPathFlagName, localSource, flags.FilePathFlagName, "./testdata/workload-lsp-non-subPath.yaml", flags.YesFlagName},
+			GivenObjects: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(&cartov1alpha1.Source{
+						Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+						Subpath: "current-subpath",
+					})
+				}),
+			},
+			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
+			ExpectUpdates: []client.Object{
+				&cartov1alpha1.Workload{
+					ObjectMeta: metav1.ObjectMeta{
+						Namespace: defaultNamespace,
+						Name:      workloadName,
+						Labels: map[string]string{
+							apis.WorkloadTypeLabelName: "web",
+						},
+						Annotations: map[string]string{
+							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+						},
+					},
+					Spec: cartov1alpha1.WorkloadSpec{
+						Source: &cartov1alpha1.Source{
+							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Subpath: "current-subpath",
+						},
+						Params: []cartov1alpha1.Param{
+							{
+								Name:  "annotations",
+								Value: apiextensionsv1.JSON{Raw: []byte(`{"autoscaling.knative.dev/minScale":"2"}`)},
+							},
+						},
+					},
+				},
+			},
+			ExpectOutput: fmt.Sprintf(`
+❗ WARNING: Configuration file update strategy is changing. By default, provided configuration files will replace rather than merge existing configuration. The change will take place in the January 2024 TAP release (use "--update-strategy" to control strategy explicitly).
+
+Publishing source in "%s" to "local-source-proxy.tap-local-source-system.svc.cluster.local/source:default-my-workload"...
+No source code is changed
+
+🔎 Update workload:
+...
+  8,  8   |    apps.tanzu.vmware.com/workload-type: web
+  9,  9   |  name: my-workload
+ 10, 10   |  namespace: default
+ 11, 11   |spec:
+     12 + |  params:
+     13 + |  - name: annotations
+     14 + |    value:
+     15 + |      autoscaling.knative.dev/minScale: "2"
+ 12, 16   |  source:
+ 13, 17   |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+ 14, 18   |    subPath: current-subpath
+👍 Updated workload "my-workload"
+
+To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
+To get status: "tanzu apps workload get my-workload"
+
 `, localSource),
 		},
 	}

From d66f14f1cb8bda96ab39c0c411cfb35b1a85eefb Mon Sep 17 00:00:00 2001
From: Diego Alfonso <dalfonso@vmware.com>
Date: Thu, 25 May 2023 17:21:34 -0500
Subject: [PATCH 5/7] chore: Ignore subpath when image is used

Signed-off-by: Diego Alfonso <dalfonso@vmware.com>
---
 .../cartographer/v1alpha1/workload_helpers.go |  18 +-
 .../cartographer/v1alpha1/workload_test.go    | 103 ++++++-
 .../workload-lsp-image-non-subPath.yaml       |  31 ++
 pkg/commands/workload_apply_test.go           | 290 ++++++++++++++++++
 4 files changed, 431 insertions(+), 11 deletions(-)
 create mode 100644 pkg/commands/testdata/workload-lsp-image-non-subPath.yaml

diff --git a/pkg/apis/cartographer/v1alpha1/workload_helpers.go b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
index 9fbbf2a0f..6f80aa1ab 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_helpers.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_helpers.go
@@ -219,6 +219,19 @@ func (w *WorkloadSpec) Merge(updates *WorkloadSpec) {
 	for _, p := range updates.Params {
 		w.MergeParams(p.Name, p.Value)
 	}
+	sp := ""
+	if w.Source != nil {
+		sp = w.Source.Subpath
+	}
+	if updates.Image != "" {
+		w.MergeImage(updates.Image)
+	}
+	if updates.Source != nil && (updates.Source.Git != nil || updates.Source.Image != "") && sp != "" {
+		if w.Source == nil {
+			w.Source = &Source{}
+		}
+		w.Source.Subpath = sp
+	}
 	if updates.Source != nil {
 		s := updates.Source.DeepCopy()
 		if s.Git != nil {
@@ -227,13 +240,10 @@ func (w *WorkloadSpec) Merge(updates *WorkloadSpec) {
 		if s.Image != "" {
 			w.MergeSourceImage(s.Image)
 		}
-		if s.Subpath != "" {
+		if s.Subpath != "" && w.Source != nil && (w.Source.Git != nil || w.Source.Image != "") {
 			w.MergeSubPath(s.Subpath)
 		}
 	}
-	if updates.Image != "" {
-		w.MergeImage(updates.Image)
-	}
 	for _, e := range updates.Env {
 		w.MergeEnv(e)
 	}
diff --git a/pkg/apis/cartographer/v1alpha1/workload_test.go b/pkg/apis/cartographer/v1alpha1/workload_test.go
index 3bdf34bde..738adc27c 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_test.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_test.go
@@ -1034,6 +1034,101 @@ func TestWorkload_Merge(t *testing.T) {
 				Image: "ubuntu:bionic",
 			},
 		},
+	}, {
+		name: "image with sources nill",
+		seed: &Workload{
+			Spec: WorkloadSpec{
+				Image: "alpine:latest",
+			},
+		},
+		update: &Workload{
+			Spec: WorkloadSpec{
+				Image:  "ubuntu:bionic",
+				Source: &Source{Subpath: "my-subpath"},
+			},
+		},
+		want: &Workload{
+			Spec: WorkloadSpec{
+				Image: "ubuntu:bionic",
+			},
+		},
+	}, {
+		name: "image with sources source image and subpath",
+		seed: &Workload{
+			Spec: WorkloadSpec{
+				Image: "alpine:latest",
+			},
+		},
+		update: &Workload{
+			Spec: WorkloadSpec{
+				Image: "ubuntu:bionic",
+				Source: &Source{
+					Image:   "ubuntu:bionic",
+					Subpath: "my-subpath",
+				},
+			},
+		},
+		want: &Workload{
+			Spec: WorkloadSpec{
+				Source: &Source{
+					Image:   "ubuntu:bionic",
+					Subpath: "my-subpath",
+				},
+			},
+		},
+	}, {
+		name: "image update sources source image and subpath",
+		seed: &Workload{
+			Spec: WorkloadSpec{
+				Image: "alpine:latest",
+				Source: &Source{
+					Subpath: "new-subpath",
+				},
+			},
+		},
+		update: &Workload{
+			Spec: WorkloadSpec{
+				Image: "ubuntu:bionic",
+				Source: &Source{
+					Image:   "ubuntu:bionic",
+					Subpath: "my-subpath",
+				},
+			},
+		},
+		want: &Workload{
+			Spec: WorkloadSpec{
+				Source: &Source{
+					Image:   "ubuntu:bionic",
+					Subpath: "my-subpath",
+				},
+			},
+		},
+	}, {
+		name: "local source image with subpath update source image and subpath",
+		seed: &Workload{
+			Spec: WorkloadSpec{
+				Source: &Source{
+					Image:   "ubuntu:bionic",
+					Subpath: "/opt",
+				},
+			},
+		},
+		update: &Workload{
+			Spec: WorkloadSpec{
+				Source: &Source{
+					Image:   "ubuntu:bionic",
+					Subpath: "/sys",
+				},
+			},
+		},
+		want: &Workload{
+			Spec: WorkloadSpec{
+				Source: &Source{
+					Image:   "ubuntu:bionic",
+					Subpath: "/sys",
+				},
+			},
+		},
 	}, {
 		name: "git",
 		seed: &Workload{
@@ -1092,13 +1187,7 @@ func TestWorkload_Merge(t *testing.T) {
 				},
 			},
 		},
-		want: &Workload{
-			Spec: WorkloadSpec{
-				Source: &Source{
-					Subpath: "test-path",
-				},
-			},
-		},
+		want: &Workload{},
 	}, {
 		name: "env",
 		seed: &Workload{
diff --git a/pkg/commands/testdata/workload-lsp-image-non-subPath.yaml b/pkg/commands/testdata/workload-lsp-image-non-subPath.yaml
new file mode 100644
index 000000000..275c93965
--- /dev/null
+++ b/pkg/commands/testdata/workload-lsp-image-non-subPath.yaml
@@ -0,0 +1,31 @@
+# Copyright 2023 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: carto.run/v1alpha1
+kind: Workload
+metadata:
+  annotations:
+    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+  labels:
+    apps.tanzu.vmware.com/workload-type: web
+  name: my-workload
+  namespace: default
+spec:
+  params:
+    - name: annotations
+      value:
+        autoscaling.knative.dev/minScale: "2"
+  image: my-registry/default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+  source:
+    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
diff --git a/pkg/commands/workload_apply_test.go b/pkg/commands/workload_apply_test.go
index 2d66c12d4..1ed6daef1 100644
--- a/pkg/commands/workload_apply_test.go
+++ b/pkg/commands/workload_apply_test.go
@@ -9048,6 +9048,296 @@ To get status: "tanzu apps workload get my-workload"
 
 `, localSource),
 		},
+		{
+			Name: "update from local source using lsp from file with image",
+			Skip: runtm.GOOS == "windows",
+			Args: []string{workloadName, flags.LocalPathFlagName, localSource, flags.FilePathFlagName, "./testdata/workload-lsp-image-non-subPath.yaml", flags.YesFlagName},
+			GivenObjects: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(&cartov1alpha1.Source{
+						Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+						Subpath: "current-subpath",
+					})
+				}),
+			},
+			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
+			ExpectUpdates: []client.Object{
+				&cartov1alpha1.Workload{
+					ObjectMeta: metav1.ObjectMeta{
+						Namespace: defaultNamespace,
+						Name:      workloadName,
+						Labels: map[string]string{
+							apis.WorkloadTypeLabelName: "web",
+						},
+						Annotations: map[string]string{
+							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+						},
+					},
+					Spec: cartov1alpha1.WorkloadSpec{
+						Source: &cartov1alpha1.Source{
+							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Subpath: "current-subpath",
+						},
+						Params: []cartov1alpha1.Param{
+							{
+								Name:  "annotations",
+								Value: apiextensionsv1.JSON{Raw: []byte(`{"autoscaling.knative.dev/minScale":"2"}`)},
+							},
+						},
+					},
+				},
+			},
+			ExpectOutput: fmt.Sprintf(`
+❗ WARNING: Configuration file update strategy is changing. By default, provided configuration files will replace rather than merge existing configuration. The change will take place in the January 2024 TAP release (use "--update-strategy" to control strategy explicitly).
+
+Publishing source in "%s" to "local-source-proxy.tap-local-source-system.svc.cluster.local/source:default-my-workload"...
+No source code is changed
+
+🔎 Update workload:
+...
+  8,  8   |    apps.tanzu.vmware.com/workload-type: web
+  9,  9   |  name: my-workload
+ 10, 10   |  namespace: default
+ 11, 11   |spec:
+     12 + |  params:
+     13 + |  - name: annotations
+     14 + |    value:
+     15 + |      autoscaling.knative.dev/minScale: "2"
+ 12, 16   |  source:
+ 13, 17   |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+ 14, 18   |    subPath: current-subpath
+👍 Updated workload "my-workload"
+
+To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
+To get status: "tanzu apps workload get my-workload"
+
+`, localSource),
+		},
+		{
+			Name: "update image to local source with subpath using flags",
+			Skip: runtm.GOOS == "windows",
+			Args: []string{workloadName, flags.LocalPathFlagName, localSource, flags.SubPathFlagName, subpath, flags.YesFlagName},
+			GivenObjects: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Image(":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69")
+				}),
+			},
+			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
+			ExpectUpdates: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(
+						&cartov1alpha1.Source{
+							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Subpath: subpath,
+						},
+					)
+				}),
+			},
+			ExpectOutput: fmt.Sprintf(`
+Publishing source in "%s" to "local-source-proxy.tap-local-source-system.svc.cluster.local/source:default-my-workload"...
+📥 Published source
+
+🔎 Update workload:
+  1,  1   |---
+  2,  2   |apiVersion: carto.run/v1alpha1
+  3,  3   |kind: Workload
+  4,  4   |metadata:
+      5 + |  annotations:
+      6 + |    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+  5,  7   |  labels:
+  6,  8   |    apps.tanzu.vmware.com/workload-type: web
+  7,  9   |  name: my-workload
+  8, 10   |  namespace: default
+  9, 11   |spec:
+ 10     - |  image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+     12 + |  source:
+     13 + |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+     14 + |    subPath: testdata/local-source/subpath
+👍 Updated workload "my-workload"
+
+To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
+To get status: "tanzu apps workload get my-workload"
+
+`, localSource),
+		},
+		{
+			Name: "update image to git with subpath using flags",
+			Skip: runtm.GOOS == "windows",
+			Args: []string{workloadName, flags.GitBranchFlagName, "main", flags.GitRepoFlagName, "my-repo-server/my-repo", flags.SubPathFlagName, subpath, flags.YesFlagName},
+			GivenObjects: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Image(":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69")
+				}),
+			},
+			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
+			ExpectUpdates: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(
+						&cartov1alpha1.Source{
+							Git: &cartov1alpha1.GitSource{
+								URL: "my-repo-server/my-repo",
+								Ref: cartov1alpha1.GitRef{
+									Branch: "main",
+								},
+							},
+							Subpath: subpath,
+						},
+					)
+				}),
+			},
+			ExpectOutput: `
+🔎 Update workload:
+...
+  6,  6   |    apps.tanzu.vmware.com/workload-type: web
+  7,  7   |  name: my-workload
+  8,  8   |  namespace: default
+  9,  9   |spec:
+ 10     - |  image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+     10 + |  source:
+     11 + |    git:
+     12 + |      ref:
+     13 + |        branch: main
+     14 + |      url: my-repo-server/my-repo
+     15 + |    subPath: testdata/local-source/subpath
+👍 Updated workload "my-workload"
+
+To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
+To get status: "tanzu apps workload get my-workload"
+
+`,
+		},
+		{
+			Name: "update local source to git without changing subpath using flags",
+			Skip: runtm.GOOS == "windows",
+			Args: []string{workloadName, flags.GitBranchFlagName, "main", flags.GitRepoFlagName, "my-repo-server/my-repo", flags.YesFlagName},
+			GivenObjects: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(
+						&cartov1alpha1.Source{
+							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Subpath: subpath,
+						},
+					)
+				}),
+			},
+			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
+			ExpectUpdates: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(
+						&cartov1alpha1.Source{
+							Git: &cartov1alpha1.GitSource{
+								URL: "my-repo-server/my-repo",
+								Ref: cartov1alpha1.GitRef{
+									Branch: "main",
+								},
+							},
+							Subpath: subpath,
+						},
+					)
+				}),
+			},
+			ExpectOutput: `
+🔎 Update workload:
+  1,  1   |---
+  2,  2   |apiVersion: carto.run/v1alpha1
+  3,  3   |kind: Workload
+  4,  4   |metadata:
+  5     - |  annotations:
+  6     - |    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+  7,  5   |  labels:
+  8,  6   |    apps.tanzu.vmware.com/workload-type: web
+  9,  7   |  name: my-workload
+ 10,  8   |  namespace: default
+ 11,  9   |spec:
+ 12, 10   |  source:
+ 13     - |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+     11 + |    git:
+     12 + |      ref:
+     13 + |        branch: main
+     14 + |      url: my-repo-server/my-repo
+ 14, 15   |    subPath: testdata/local-source/subpath
+👍 Updated workload "my-workload"
+
+To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
+To get status: "tanzu apps workload get my-workload"
+
+`,
+		},
+		{
+			Name: "update local source to image using flags",
+			Skip: runtm.GOOS == "windows",
+			Args: []string{workloadName, flags.ImageFlagName, ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69", flags.YesFlagName},
+			GivenObjects: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Source(
+						&cartov1alpha1.Source{
+							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Subpath: subpath,
+						},
+					)
+				}),
+			},
+			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
+			ExpectUpdates: []client.Object{
+				parent.
+					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
+						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
+					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
+					d.Image(":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69")
+				}),
+			},
+			ExpectOutput: `
+🔎 Update workload:
+  1,  1   |---
+  2,  2   |apiVersion: carto.run/v1alpha1
+  3,  3   |kind: Workload
+  4,  4   |metadata:
+  5     - |  annotations:
+  6     - |    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+  7,  5   |  labels:
+  8,  6   |    apps.tanzu.vmware.com/workload-type: web
+  9,  7   |  name: my-workload
+ 10,  8   |  namespace: default
+ 11,  9   |spec:
+ 12     - |  source:
+ 13     - |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+ 14     - |    subPath: testdata/local-source/subpath
+     10 + |  image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+👍 Updated workload "my-workload"
+
+To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
+To get status: "tanzu apps workload get my-workload"
+
+`,
+		},
 	}
 
 	table.Run(t, scheme, func(ctx context.Context, c *cli.Config) *cobra.Command {

From 10677d1cf99f83aa20960c8a3454279d433266a5 Mon Sep 17 00:00:00 2001
From: Diego Alfonso <dalfonso@vmware.com>
Date: Mon, 29 May 2023 11:05:27 -0500
Subject: [PATCH 6/7] chore: Fix nill word and remove not used test config

Signed-off-by: Diego Alfonso <dalfonso@vmware.com>
---
 .../cartographer/v1alpha1/workload_test.go    |  4 +--
 pkg/commands/workload_apply_test.go           | 34 ++++++++-----------
 2 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/pkg/apis/cartographer/v1alpha1/workload_test.go b/pkg/apis/cartographer/v1alpha1/workload_test.go
index 738adc27c..51d389301 100644
--- a/pkg/apis/cartographer/v1alpha1/workload_test.go
+++ b/pkg/apis/cartographer/v1alpha1/workload_test.go
@@ -1035,7 +1035,7 @@ func TestWorkload_Merge(t *testing.T) {
 			},
 		},
 	}, {
-		name: "image with sources nill",
+		name: "image with sources nil",
 		seed: &Workload{
 			Spec: WorkloadSpec{
 				Image: "alpine:latest",
@@ -1053,7 +1053,7 @@ func TestWorkload_Merge(t *testing.T) {
 			},
 		},
 	}, {
-		name: "image with sources source image and subpath",
+		name: "workload with multiple sources and subpath",
 		seed: &Workload{
 			Spec: WorkloadSpec{
 				Image: "alpine:latest",
diff --git a/pkg/commands/workload_apply_test.go b/pkg/commands/workload_apply_test.go
index 1ed6daef1..caae6ae87 100644
--- a/pkg/commands/workload_apply_test.go
+++ b/pkg/commands/workload_apply_test.go
@@ -7766,7 +7766,7 @@ To get status: "tanzu apps workload get spring-petclinic"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -7816,7 +7816,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -7866,7 +7866,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -7919,7 +7919,7 @@ To get status: "tanzu apps workload get my-workload"
 							"apps.tanzu.vmware.com/workload-type": "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8287,7 +8287,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8344,7 +8344,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8399,7 +8399,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8452,7 +8452,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8517,7 +8517,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8584,7 +8584,7 @@ To get status: "tanzu apps workload get my-workload"
 							"apps.tanzu.vmware.com/workload-type": "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8672,7 +8672,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8729,7 +8729,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -8935,7 +8935,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -9005,7 +9005,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -9074,7 +9074,7 @@ To get status: "tanzu apps workload get my-workload"
 							apis.WorkloadTypeLabelName: "web",
 						},
 						Annotations: map[string]string{
-							"local-source-proxy.apps.tanzu.vmware.com": ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
 						},
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
@@ -9173,7 +9173,6 @@ To get status: "tanzu apps workload get my-workload"
 		},
 		{
 			Name: "update image to git with subpath using flags",
-			Skip: runtm.GOOS == "windows",
 			Args: []string{workloadName, flags.GitBranchFlagName, "main", flags.GitRepoFlagName, "my-repo-server/my-repo", flags.SubPathFlagName, subpath, flags.YesFlagName},
 			GivenObjects: []client.Object{
 				parent.
@@ -9183,7 +9182,6 @@ To get status: "tanzu apps workload get my-workload"
 					d.Image(":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69")
 				}),
 			},
-			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
 			ExpectUpdates: []client.Object{
 				parent.
 					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
@@ -9289,7 +9287,6 @@ To get status: "tanzu apps workload get my-workload"
 		},
 		{
 			Name: "update local source to image using flags",
-			Skip: runtm.GOOS == "windows",
 			Args: []string{workloadName, flags.ImageFlagName, ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69", flags.YesFlagName},
 			GivenObjects: []client.Object{
 				parent.
@@ -9305,7 +9302,6 @@ To get status: "tanzu apps workload get my-workload"
 					)
 				}),
 			},
-			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
 			ExpectUpdates: []client.Object{
 				parent.
 					MetadataDie(func(d *diemetav1.ObjectMetaDie) {

From 6668c910cfb072371707975eb7442bbc0a47c6c7 Mon Sep 17 00:00:00 2001
From: Diego Alfonso <dalfonso@vmware.com>
Date: Mon, 29 May 2023 11:23:40 -0500
Subject: [PATCH 7/7] chore: Remove duplicate tests

Signed-off-by: Diego Alfonso <dalfonso@vmware.com>
---
 pkg/commands/workload_apply_test.go | 119 +++-------------------------
 1 file changed, 10 insertions(+), 109 deletions(-)

diff --git a/pkg/commands/workload_apply_test.go b/pkg/commands/workload_apply_test.go
index caae6ae87..7b5b4f5c4 100644
--- a/pkg/commands/workload_apply_test.go
+++ b/pkg/commands/workload_apply_test.go
@@ -8225,7 +8225,8 @@ To get status: "tanzu apps workload get my-workload"
 						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: "my-old-image"})
 					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
 					d.Source(&cartov1alpha1.Source{
-						Image: "my-lsp-image@sha256:1234567890",
+						Image:   "my-lsp-image@sha256:1234567890",
+						Subpath: "my-subpath",
 					})
 				}),
 			},
@@ -8259,6 +8260,7 @@ To get status: "tanzu apps workload get my-workload"
  11,  9   |spec:
  12     - |  source:
  13     - |    image: my-lsp-image@sha256:1234567890
+ 14     - |    subPath: my-subpath
      10 + |  image: my-image
 👍 Updated workload "my-workload"
 
@@ -8270,7 +8272,7 @@ To get status: "tanzu apps workload get my-workload"
 		{
 			Name: "update from image to lsp",
 			Skip: runtm.GOOS == "windows",
-			Args: []string{workloadName, flags.LocalPathFlagName, localSource, flags.YesFlagName},
+			Args: []string{workloadName, flags.LocalPathFlagName, localSource, flags.SubPathFlagName, subpath, flags.YesFlagName},
 			GivenObjects: []client.Object{
 				parent.
 					SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
@@ -8292,7 +8294,8 @@ To get status: "tanzu apps workload get my-workload"
 					},
 					Spec: cartov1alpha1.WorkloadSpec{
 						Source: &cartov1alpha1.Source{
-							Image: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
+							Subpath: subpath,
 						},
 					},
 				},
@@ -8316,6 +8319,7 @@ Publishing source in "%s" to "local-source-proxy.tap-local-source-system.svc.clu
  10     - |  image: my-image
      12 + |  source:
      13 + |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
+     14 + |    subPath: testdata/local-source/subpath
 👍 Updated workload "my-workload"
 
 To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
@@ -9115,60 +9119,6 @@ No source code is changed
 To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
 To get status: "tanzu apps workload get my-workload"
 
-`, localSource),
-		},
-		{
-			Name: "update image to local source with subpath using flags",
-			Skip: runtm.GOOS == "windows",
-			Args: []string{workloadName, flags.LocalPathFlagName, localSource, flags.SubPathFlagName, subpath, flags.YesFlagName},
-			GivenObjects: []client.Object{
-				parent.
-					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
-						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
-					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
-					d.Image(":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69")
-				}),
-			},
-			KubeConfigTransport: clitesting.NewFakeTransportFromResponse(respCreator(http.StatusOK, `{"statuscode": "200", "message": "any ignored message"}`, myWorkloadHeader)),
-			ExpectUpdates: []client.Object{
-				parent.
-					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
-						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
-						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
-					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
-					d.Source(
-						&cartov1alpha1.Source{
-							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
-							Subpath: subpath,
-						},
-					)
-				}),
-			},
-			ExpectOutput: fmt.Sprintf(`
-Publishing source in "%s" to "local-source-proxy.tap-local-source-system.svc.cluster.local/source:default-my-workload"...
-📥 Published source
-
-🔎 Update workload:
-  1,  1   |---
-  2,  2   |apiVersion: carto.run/v1alpha1
-  3,  3   |kind: Workload
-  4,  4   |metadata:
-      5 + |  annotations:
-      6 + |    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
-  5,  7   |  labels:
-  6,  8   |    apps.tanzu.vmware.com/workload-type: web
-  7,  9   |  name: my-workload
-  8, 10   |  namespace: default
-  9, 11   |spec:
- 10     - |  image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
-     12 + |  source:
-     13 + |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
-     14 + |    subPath: testdata/local-source/subpath
-👍 Updated workload "my-workload"
-
-To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
-To get status: "tanzu apps workload get my-workload"
-
 `, localSource),
 		},
 		{
@@ -9200,7 +9150,7 @@ To get status: "tanzu apps workload get my-workload"
 					)
 				}),
 			},
-			ExpectOutput: `
+			ExpectOutput: fmt.Sprintf(`
 🔎 Update workload:
 ...
   6,  6   |    apps.tanzu.vmware.com/workload-type: web
@@ -9213,13 +9163,13 @@ To get status: "tanzu apps workload get my-workload"
      12 + |      ref:
      13 + |        branch: main
      14 + |      url: my-repo-server/my-repo
-     15 + |    subPath: testdata/local-source/subpath
+     15 + |    subPath: %s
 👍 Updated workload "my-workload"
 
 To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
 To get status: "tanzu apps workload get my-workload"
 
-`,
+`, subpath),
 		},
 		{
 			Name: "update local source to git without changing subpath using flags",
@@ -9283,55 +9233,6 @@ To get status: "tanzu apps workload get my-workload"
 To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
 To get status: "tanzu apps workload get my-workload"
 
-`,
-		},
-		{
-			Name: "update local source to image using flags",
-			Args: []string{workloadName, flags.ImageFlagName, ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69", flags.YesFlagName},
-			GivenObjects: []client.Object{
-				parent.
-					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
-						d.Annotations(map[string]string{apis.LocalSourceProxyAnnotationName: ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69"})
-						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
-					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
-					d.Source(
-						&cartov1alpha1.Source{
-							Image:   ":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69",
-							Subpath: subpath,
-						},
-					)
-				}),
-			},
-			ExpectUpdates: []client.Object{
-				parent.
-					MetadataDie(func(d *diemetav1.ObjectMetaDie) {
-						d.Labels(map[string]string{apis.WorkloadTypeLabelName: "web"})
-					}).SpecDie(func(d *diecartov1alpha1.WorkloadSpecDie) {
-					d.Image(":default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69")
-				}),
-			},
-			ExpectOutput: `
-🔎 Update workload:
-  1,  1   |---
-  2,  2   |apiVersion: carto.run/v1alpha1
-  3,  3   |kind: Workload
-  4,  4   |metadata:
-  5     - |  annotations:
-  6     - |    local-source-proxy.apps.tanzu.vmware.com: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
-  7,  5   |  labels:
-  8,  6   |    apps.tanzu.vmware.com/workload-type: web
-  9,  7   |  name: my-workload
- 10,  8   |  namespace: default
- 11,  9   |spec:
- 12     - |  source:
- 13     - |    image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
- 14     - |    subPath: testdata/local-source/subpath
-     10 + |  image: :default-my-workload@sha256:978be33a7f0cbe89bf48fbb438846047a28e1298d6d10d0de2d64bdc102a9e69
-👍 Updated workload "my-workload"
-
-To see logs:   "tanzu apps workload tail my-workload --timestamp --since 1h"
-To get status: "tanzu apps workload get my-workload"
-
 `,
 		},
 	}