Skip to content

Commit 5b29a87

Browse files
authored
Add support for image registry proxy in Kibishii installation (#9063)
* Add support for image registry proxy in Kibishii installation Signed-off-by: Priyansh Choudhary <im1706@gmail.com>
1 parent 2e83a3c commit 5b29a87

2 files changed

Lines changed: 229 additions & 17 deletions

File tree

test/util/kibishii/kibishii_utils.go

Lines changed: 140 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -323,22 +323,36 @@ func installKibishii(
323323
fmt.Printf("targetKustomizeDir for windows %s\n", targetKustomizeDir)
324324
}
325325
fmt.Printf("The installed Kibishii Kustomize package directory is %s.\n", targetKustomizeDir)
326+
}
326327

327-
kibishiiImage := readBaseKibishiiImage(path.Join(kibishiiDirectory, "base", "kibishii.yaml"))
328-
if err := generateKibishiiImagePatch(
329-
path.Join(imageRegistryProxy, kibishiiImage),
330-
path.Join(targetKustomizeDir, "worker-image-patch.yaml"),
331-
); err != nil {
332-
return nil
333-
}
328+
// update kibishi images with image registry proxy if it is set
329+
baseDir := resolveBasePath(kibishiiDirectory)
330+
fmt.Printf("Using image registry proxy %s to patch Kibishii images. Base Dir: %s\n", imageRegistryProxy, baseDir)
334331

335-
jumpPadImage := readBaseJumpPadImage(path.Join(kibishiiDirectory, "base", "jump-pad.yaml"))
336-
if err := generateJumpPadPatch(
337-
path.Join(imageRegistryProxy, jumpPadImage),
338-
path.Join(targetKustomizeDir, "jump-pad-image-patch.yaml"),
339-
); err != nil {
340-
return nil
341-
}
332+
sanitizedTargetKustomizeDir := strings.ReplaceAll(targetKustomizeDir, "overlays/sc-reclaim-policy", "")
333+
334+
kibishiiImage := readBaseKibishiiImage(path.Join(baseDir, "base", "kibishii.yaml"))
335+
if err := generateKibishiiImagePatch(
336+
path.Join(imageRegistryProxy, kibishiiImage),
337+
path.Join(sanitizedTargetKustomizeDir, "worker-image-patch.yaml"),
338+
); err != nil {
339+
return nil
340+
}
341+
342+
jumpPadImage := readBaseJumpPadImage(path.Join(baseDir, "base", "jump-pad.yaml"))
343+
if err := generateJumpPadPatch(
344+
path.Join(imageRegistryProxy, jumpPadImage),
345+
path.Join(sanitizedTargetKustomizeDir, "jump-pad-image-patch.yaml"),
346+
); err != nil {
347+
return nil
348+
}
349+
350+
etcdImage := readBaseEtcdImage(path.Join(baseDir, "base", "etcd.yaml"))
351+
if err := generateEtcdImagePatch(
352+
path.Join(imageRegistryProxy, etcdImage),
353+
path.Join(sanitizedTargetKustomizeDir, "etcd-image-patch.yaml"),
354+
); err != nil {
355+
return nil
342356
}
343357

344358
// We use kustomize to generate YAML for Kibishii from the checked-in yaml directories
@@ -397,6 +411,24 @@ func installKibishii(
397411
return err
398412
}
399413

414+
func resolveBasePath(dir string) string {
415+
// If the path includes "overlays", strip everything up to "overlays/"
416+
parts := strings.Split(dir, "overlays")
417+
if len(parts) > 1 {
418+
// Assume root of repo is before "overlays", add "/base"
419+
return parts[0]
420+
}
421+
return dir // no "overlays" found, return original path
422+
}
423+
424+
func stripRegistry(image string) string {
425+
// If the image includes a registry (quay.io, docker.io, etc.), strip it
426+
if parts := strings.SplitN(image, "/", 2); len(parts) == 2 && strings.Contains(parts[0], ".") {
427+
return parts[1] // remove the registry
428+
}
429+
return image // already no registry
430+
}
431+
400432
func readBaseKibishiiImage(kibishiiFilePath string) string {
401433
bytes, err := os.ReadFile(kibishiiFilePath)
402434
if err != nil {
@@ -435,6 +467,51 @@ func readBaseJumpPadImage(jumpPadFilePath string) string {
435467
return jumpPadImage
436468
}
437469

470+
func readBaseEtcdImage(etcdFilePath string) string {
471+
bytes, err := os.ReadFile(etcdFilePath)
472+
if err != nil {
473+
fmt.Printf("Failed to read etcd pod yaml file: %v\n", err)
474+
return ""
475+
}
476+
477+
// Split on document marker
478+
docs := strings.Split(string(bytes), "---")
479+
480+
for _, doc := range docs {
481+
doc = strings.TrimSpace(doc)
482+
if doc == "" {
483+
continue
484+
}
485+
486+
var typeMeta corev1api.TypedLocalObjectReference
487+
if err := yaml.Unmarshal([]byte(doc), &typeMeta); err != nil {
488+
continue
489+
}
490+
491+
if typeMeta.Kind != "Pod" {
492+
continue
493+
}
494+
495+
var pod corev1api.Pod
496+
if err := yaml.Unmarshal([]byte(doc), &pod); err != nil {
497+
fmt.Printf("Failed to unmarshal pod: %v\n", err)
498+
continue
499+
}
500+
501+
if len(pod.Spec.Containers) > 0 {
502+
fullImage := pod.Spec.Containers[0].Image
503+
fmt.Printf("Full etcd image: %s\n", fullImage)
504+
505+
imageWithoutRegistry := stripRegistry(fullImage)
506+
fmt.Printf("Stripped etcd image: %s\n", imageWithoutRegistry)
507+
return imageWithoutRegistry
508+
}
509+
}
510+
511+
fmt.Println("No etcd pod with container image found.")
512+
return ""
513+
}
514+
438515
type patchImageData struct {
439516
Image string
440517
}
@@ -454,11 +531,10 @@ spec:
454531
`
455532

456533
file, err := os.OpenFile(patchDirectory, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
457-
defer file.Close()
458-
459534
if err != nil {
460535
return err
461536
}
537+
defer file.Close()
462538

463539
patchTemplate, err := template.New("imagePatch").Parse(patchString)
464540
if err != nil {
@@ -484,18 +560,65 @@ spec:
484560
image: {{.Image}}
485561
`
486562
file, err := os.OpenFile(patchDirectory, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
563+
if err != nil {
564+
return err
565+
}
487566
defer file.Close()
488567

568+
patchTemplate, err := template.New("imagePatch").Parse(patchString)
489569
if err != nil {
490570
return err
491571
}
492572

573+
if err := patchTemplate.Execute(file, patchImageData{Image: jumpPadImage}); err != nil {
574+
return err
575+
}
576+
577+
return nil
578+
}
579+
580+
func generateEtcdImagePatch(etcdImage string, patchPath string) error {
581+
patchString := `
582+
apiVersion: v1
583+
kind: Pod
584+
metadata:
585+
name: etcd0
586+
spec:
587+
containers:
588+
- name: etcd0
589+
image: {{.Image}}
590+
---
591+
apiVersion: v1
592+
kind: Pod
593+
metadata:
594+
name: etcd1
595+
spec:
596+
containers:
597+
- name: etcd1
598+
image: {{.Image}}
599+
---
600+
apiVersion: v1
601+
kind: Pod
602+
metadata:
603+
name: etcd2
604+
spec:
605+
containers:
606+
- name: etcd2
607+
image: {{.Image}}
608+
`
609+
610+
file, err := os.OpenFile(patchPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
611+
if err != nil {
612+
return err
613+
}
614+
defer file.Close()
615+
493616
patchTemplate, err := template.New("imagePatch").Parse(patchString)
494617
if err != nil {
495618
return err
496619
}
497620

498-
if err := patchTemplate.Execute(file, patchImageData{Image: jumpPadImage}); err != nil {
621+
if err := patchTemplate.Execute(file, patchImageData{Image: etcdImage}); err != nil {
499622
return err
500623
}
501624

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
Copyright the Velero contributors.
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 kibishii
18+
19+
import "testing"
20+
21+
func TestResolveBasePath(t *testing.T) {
22+
tests := []struct {
23+
input string
24+
expected string
25+
}{
26+
{
27+
input: "/home/user/project/overlays/sc-reclaim-policy/azure",
28+
expected: "/home/user/project/",
29+
},
30+
{
31+
input: "/go/src/github.com/org/repo/base",
32+
expected: "/go/src/github.com/org/repo/base",
33+
},
34+
{
35+
input: "/some/dir/overlays",
36+
expected: "/some/dir/",
37+
},
38+
{
39+
input: "overlays/sc-reclaim-policy/azure",
40+
expected: "",
41+
},
42+
}
43+
44+
for _, tt := range tests {
45+
actual := resolveBasePath(tt.input)
46+
if actual != tt.expected {
47+
t.Errorf("resolveBasePath(%q) = %q; want %q", tt.input, actual, tt.expected)
48+
}
49+
}
50+
}
51+
52+
func TestStripRegistry(t *testing.T) {
53+
tests := []struct {
54+
input string
55+
expected string
56+
}{
57+
{
58+
input: "quay.io/example/image:tag",
59+
expected: "example/image:tag",
60+
},
61+
{
62+
input: "docker.io/library/nginx:latest",
63+
expected: "library/nginx:latest",
64+
},
65+
{
66+
input: "gcr.io/project/app",
67+
expected: "project/app",
68+
},
69+
{
70+
input: "my-custom-reg.io/myapp",
71+
expected: "myapp",
72+
},
73+
{
74+
input: "ubuntu:20.04",
75+
expected: "ubuntu:20.04",
76+
},
77+
{
78+
input: "library/nginx",
79+
expected: "library/nginx",
80+
},
81+
}
82+
83+
for _, tt := range tests {
84+
actual := stripRegistry(tt.input)
85+
if actual != tt.expected {
86+
t.Errorf("stripRegistry(%q) = %q; want %q", tt.input, actual, tt.expected)
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)