Skip to content

Commit fae5fb4

Browse files
authored
fix: Update the k8s Job container logic for custom actions to match v… (#9584)
* fix: Update the k8s Job container logic for custom actions to match verify * chore: add license to new test file * chore: adjust import order to address linter errors * chore: fix license formatting in new test file
1 parent d53620f commit fae5fb4

File tree

2 files changed

+158
-6
lines changed

2 files changed

+158
-6
lines changed

pkg/skaffold/actions/k8sjob/task.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,17 @@ func (t Task) Exec(ctx context.Context, out io.Writer) error {
8787
}
8888

8989
c := t.getContainerToDeploy()
90-
t.setManifestValues(c)
90+
var original corev1.Container
91+
for _, ec := range t.jobManifest.Spec.Template.Spec.Containers {
92+
if ec.Name == c.Name {
93+
original = ec
94+
break
95+
}
96+
}
97+
patchToK8sContainer(c, &original)
98+
99+
t.jobManifest.Spec.Template.Spec.Containers = []corev1.Container{original}
100+
t.jobManifest.ObjectMeta.Name = t.Name()
91101

92102
if err := k8sjobutil.ForceJobDelete(ctx, t.jobManifest.Name, jm, t.kubectl); err != nil {
93103
return errors.Wrap(err, fmt.Sprintf("preparing job %v for execution", t.jobManifest.Name))
@@ -110,6 +120,20 @@ func (t Task) Exec(ctx context.Context, out io.Writer) error {
110120
return err
111121
}
112122

123+
func patchToK8sContainer(container corev1.Container, dst *corev1.Container) {
124+
dst.Name = container.Name
125+
dst.Image = container.Image
126+
dst.Command = container.Command
127+
dst.Args = container.Args
128+
129+
for _, e := range container.Env {
130+
dst.Env = append(dst.Env, corev1.EnvVar{
131+
Name: e.Name,
132+
Value: e.Value,
133+
})
134+
}
135+
}
136+
113137
func (t Task) Cleanup(ctx context.Context, out io.Writer) error {
114138
jm, err := t.jobsManager()
115139
if err != nil {
@@ -145,11 +169,6 @@ func (t Task) getK8SEnvVars(envVars []latest.VerifyEnvVar) (k8sEnvVar []corev1.E
145169
return
146170
}
147171

148-
func (t *Task) setManifestValues(c corev1.Container) {
149-
t.jobManifest.Spec.Template.Spec.Containers = []corev1.Container{c}
150-
t.jobManifest.ObjectMeta.Name = t.Name()
151-
}
152-
153172
func (t Task) deployJob(ctx context.Context, jobManifest batchv1.Job, jobsManager typesbatchv1.JobInterface) error {
154173
return k8sjobutil.WithRetryablePoll(ctx, func(ctx context.Context) error {
155174
_, err := jobsManager.Create(ctx, &jobManifest, v1.CreateOptions{})
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
Copyright 2024 The Skaffold Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package k8sjob
18+
19+
import (
20+
"testing"
21+
22+
corev1 "k8s.io/api/core/v1"
23+
24+
"github.com/GoogleContainerTools/skaffold/v2/testutil"
25+
)
26+
27+
func TestPatchToK8sContainer(t *testing.T) {
28+
tests := []struct {
29+
description string
30+
actionContainer corev1.Container
31+
k8sContainer corev1.Container
32+
expected corev1.Container
33+
}{
34+
{
35+
description: "update all fields",
36+
actionContainer: corev1.Container{
37+
Image: "my-image:latest",
38+
Command: []string{"/bin/bash"},
39+
Args: []string{"-c", "echo hello world"},
40+
Name: "my-container",
41+
Env: []corev1.EnvVar{
42+
{Name: "FOO", Value: "BAR"},
43+
},
44+
},
45+
k8sContainer: corev1.Container{},
46+
expected: corev1.Container{
47+
Image: "my-image:latest",
48+
Command: []string{"/bin/bash"},
49+
Args: []string{"-c", "echo hello world"},
50+
Name: "my-container",
51+
Env: []corev1.EnvVar{
52+
{Name: "FOO", Value: "BAR"},
53+
},
54+
},
55+
},
56+
{
57+
description: "update image",
58+
actionContainer: corev1.Container{
59+
Image: "my-new-image:latest",
60+
},
61+
k8sContainer: corev1.Container{
62+
Image: "my-image:latest",
63+
},
64+
expected: corev1.Container{
65+
Image: "my-new-image:latest",
66+
},
67+
},
68+
{
69+
description: "update command",
70+
actionContainer: corev1.Container{
71+
Command: []string{"/bin/ls"},
72+
},
73+
k8sContainer: corev1.Container{
74+
Command: []string{"/bin/bash"},
75+
},
76+
expected: corev1.Container{
77+
Command: []string{"/bin/ls"},
78+
},
79+
},
80+
{
81+
description: "update args",
82+
actionContainer: corev1.Container{
83+
Args: []string{"-l"},
84+
},
85+
k8sContainer: corev1.Container{
86+
Args: []string{"-c", "echo hello world"},
87+
},
88+
expected: corev1.Container{
89+
Args: []string{"-l"},
90+
},
91+
},
92+
{
93+
description: "update name",
94+
actionContainer: corev1.Container{
95+
Name: "my-new-container",
96+
},
97+
k8sContainer: corev1.Container{
98+
Name: "my-container",
99+
},
100+
expected: corev1.Container{
101+
Name: "my-new-container",
102+
},
103+
},
104+
{
105+
description: "update env",
106+
actionContainer: corev1.Container{
107+
Env: []corev1.EnvVar{
108+
{Name: "FOO", Value: "BARR"},
109+
{Name: "BAZ", Value: "QUX"},
110+
},
111+
},
112+
k8sContainer: corev1.Container{
113+
Env: []corev1.EnvVar{
114+
{Name: "FOO", Value: "BAR"},
115+
},
116+
},
117+
// Duplicate name should be ok, as the last writer should win.
118+
expected: corev1.Container{
119+
Env: []corev1.EnvVar{
120+
{Name: "FOO", Value: "BAR"},
121+
{Name: "FOO", Value: "BARR"},
122+
{Name: "BAZ", Value: "QUX"},
123+
},
124+
},
125+
},
126+
}
127+
for _, test := range tests {
128+
testutil.Run(t, test.description, func(t *testutil.T) {
129+
patchToK8sContainer(test.actionContainer, &test.k8sContainer)
130+
t.CheckDeepEqual(test.expected, test.k8sContainer)
131+
})
132+
}
133+
}

0 commit comments

Comments
 (0)