Skip to content

Commit a825c88

Browse files
committed
helm/v2: Extract image and resources from kustomize / Fixes #5113
1 parent 72d4edb commit a825c88

File tree

10 files changed

+510
-66
lines changed

10 files changed

+510
-66
lines changed

docs/book/src/cronjob-tutorial/testdata/project/dist/chart/templates/manager/manager.yaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ spec:
3434
{{- end }}
3535
command:
3636
- /manager
37+
{{- if .Values.controllerManager.image.digest }}
38+
image: "{{ .Values.controllerManager.image.repository }}@{{ .Values.controllerManager.image.digest }}"
39+
{{- else }}
3740
image: "{{ .Values.controllerManager.image.repository }}:{{ .Values.controllerManager.image.tag }}"
41+
{{- end }}
42+
imagePullPolicy: "{{ .Values.controllerManager.image.pullPolicy }}"
3843
livenessProbe:
3944
httpGet:
4045
path: /healthz
@@ -52,13 +57,10 @@ spec:
5257
port: 8081
5358
initialDelaySeconds: 5
5459
periodSeconds: 10
60+
{{- with .Values.controllerManager.resources }}
5561
resources:
56-
limits:
57-
cpu: 500m
58-
memory: 128Mi
59-
requests:
60-
cpu: 10m
61-
memory: 64Mi
62+
{{- toYaml . | nindent 20 }}
63+
{{- end }}
6264
securityContext:
6365
allowPrivilegeEscalation: false
6466
capabilities:

docs/book/src/getting-started/testdata/project/dist/chart/templates/manager/manager.yaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ spec:
2828
- --health-probe-bind-address=:8081
2929
command:
3030
- /manager
31+
{{- if .Values.controllerManager.image.digest }}
32+
image: "{{ .Values.controllerManager.image.repository }}@{{ .Values.controllerManager.image.digest }}"
33+
{{- else }}
3134
image: "{{ .Values.controllerManager.image.repository }}:{{ .Values.controllerManager.image.tag }}"
35+
{{- end }}
36+
imagePullPolicy: "{{ .Values.controllerManager.image.pullPolicy }}"
3237
livenessProbe:
3338
httpGet:
3439
path: /healthz
@@ -43,13 +48,10 @@ spec:
4348
port: 8081
4449
initialDelaySeconds: 5
4550
periodSeconds: 10
51+
{{- with .Values.controllerManager.resources }}
4652
resources:
47-
limits:
48-
cpu: 500m
49-
memory: 128Mi
50-
requests:
51-
cpu: 10m
52-
memory: 64Mi
53+
{{- toYaml . | nindent 20 }}
54+
{{- end }}
5355
securityContext:
5456
allowPrivilegeEscalation: false
5557
capabilities:

docs/book/src/multiversion-tutorial/testdata/project/dist/chart/templates/manager/manager.yaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ spec:
3434
{{- end }}
3535
command:
3636
- /manager
37+
{{- if .Values.controllerManager.image.digest }}
38+
image: "{{ .Values.controllerManager.image.repository }}@{{ .Values.controllerManager.image.digest }}"
39+
{{- else }}
3740
image: "{{ .Values.controllerManager.image.repository }}:{{ .Values.controllerManager.image.tag }}"
41+
{{- end }}
42+
imagePullPolicy: "{{ .Values.controllerManager.image.pullPolicy }}"
3843
livenessProbe:
3944
httpGet:
4045
path: /healthz
@@ -52,13 +57,10 @@ spec:
5257
port: 8081
5358
initialDelaySeconds: 5
5459
periodSeconds: 10
60+
{{- with .Values.controllerManager.resources }}
5561
resources:
56-
limits:
57-
cpu: 500m
58-
memory: 128Mi
59-
requests:
60-
cpu: 10m
61-
memory: 64Mi
62+
{{- toYaml . | nindent 20 }}
63+
{{- end }}
6264
securityContext:
6365
allowPrivilegeEscalation: false
6466
capabilities:

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/chart_converter.go

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package kustomize
1818

1919
import (
2020
"fmt"
21+
"strings"
2122

2223
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2324

@@ -128,12 +129,30 @@ func (c *ChartConverter) ExtractDeploymentConfig() map[string]interface{} {
128129
return config
129130
}
130131

131-
// Use the first container (manager container)
132-
firstContainer, ok := containersList[0].(map[string]interface{})
133-
if !ok {
134-
return config
132+
// Find manager container by name, fallback to first container
133+
var targetContainer map[string]interface{}
134+
for _, c := range containersList {
135+
container, ok := c.(map[string]interface{})
136+
if !ok {
137+
continue
138+
}
139+
if name, nameOk := container["name"].(string); nameOk && name == "manager" {
140+
targetContainer = container
141+
break
142+
}
143+
}
144+
145+
// Fallback to first container if manager not found
146+
if targetContainer == nil {
147+
if firstContainer, ok := containersList[0].(map[string]interface{}); ok {
148+
targetContainer = firstContainer
149+
} else {
150+
return config
151+
}
135152
}
136153

154+
firstContainer := targetContainer
155+
137156
// Extract environment variables
138157
if env, envFound, envErr := unstructured.NestedFieldNoCopy(firstContainer, "env"); envFound && envErr == nil {
139158
if envList, envOk := env.([]interface{}); envOk && len(envList) > 0 {
@@ -157,5 +176,48 @@ func (c *ChartConverter) ExtractDeploymentConfig() map[string]interface{} {
157176
}
158177
}
159178

179+
// Extract image configuration
180+
if image, found, err := unstructured.NestedString(firstContainer, "image"); found && err == nil && image != "" {
181+
config["image"] = parseImageString(image)
182+
}
183+
184+
// Extract imagePullPolicy
185+
if pullPolicy, found, err := unstructured.NestedString(firstContainer, "imagePullPolicy"); found && err == nil && pullPolicy != "" {
186+
config["imagePullPolicy"] = pullPolicy
187+
}
188+
160189
return config
161190
}
191+
192+
// parseImageString parses "<repo>[@<digest>]" or "<repo>[:<tag>]".
193+
// It distinguishes registry ports from tags by requiring the tag colon
194+
// to come AFTER the last '/'.
195+
func parseImageString(image string) map[string]interface{} {
196+
out := make(map[string]interface{})
197+
198+
// Digest form takes precedence
199+
if at := strings.IndexByte(image, '@'); at != -1 {
200+
out["repository"] = image[:at]
201+
if at+1 < len(image) {
202+
out["digest"] = image[at+1:]
203+
}
204+
return out
205+
}
206+
207+
lastSlash := strings.LastIndexByte(image, '/')
208+
lastColon := strings.LastIndexByte(image, ':')
209+
210+
// Tag only if the colon comes after the last slash
211+
if lastColon != -1 && lastColon > lastSlash {
212+
out["repository"] = image[:lastColon]
213+
if lastColon+1 < len(image) {
214+
out["tag"] = image[lastColon+1:]
215+
}
216+
return out
217+
}
218+
219+
// Untagged/undigested; kube will pull :latest, but we surface it explicitly
220+
out["repository"] = image
221+
out["tag"] = "latest"
222+
return out
223+
}

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/chart_converter_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ var _ = Describe("ChartConverter", func() {
158158
Expect(config).NotTo(BeNil())
159159
Expect(config).To(HaveKey("env"))
160160
Expect(config).To(HaveKey("resources"))
161+
162+
// Verify image extraction
163+
Expect(config).To(HaveKey("image"))
164+
imageConfig := config["image"].(map[string]interface{})
165+
Expect(imageConfig["repository"]).To(Equal("controller"))
166+
Expect(imageConfig["tag"]).To(Equal("latest"))
161167
})
162168

163169
It("should handle deployment without containers", func() {

0 commit comments

Comments
 (0)