Skip to content

Commit 372f5a9

Browse files
author
Per Goncalves da Silva
committed
Add controller image build and publish support to test registry
Signed-off-by: Per Goncalves da Silva <pegoncal@redhat.com>
1 parent 8d449d1 commit 372f5a9

2 files changed

Lines changed: 123 additions & 7 deletions

File tree

testdata/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
push/bin
2+
images/controllers

testdata/push/push.go

Lines changed: 122 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
11
package main
22

33
import (
4+
"archive/tar"
5+
"bytes"
46
"flag"
57
"fmt"
8+
"github.com/google/go-containerregistry/pkg/v1/empty"
9+
"github.com/google/go-containerregistry/pkg/v1/tarball"
10+
"io"
611
"io/fs"
712
"log"
813
"os"
14+
"path/filepath"
15+
"sort"
916
"strings"
1017

1118
"github.com/google/go-containerregistry/pkg/crane"
12-
v1 "github.com/google/go-containerregistry/pkg/v1"
19+
"github.com/google/go-containerregistry/pkg/v1"
1320
"github.com/google/go-containerregistry/pkg/v1/mutate"
1421
"github.com/spf13/pflag"
1522
"gopkg.in/yaml.v2"
1623
)
1724

1825
const (
19-
bundlesSubPath string = "bundles"
20-
catalogsSubPath string = "catalogs"
26+
controllersSubPath string = "controllers"
27+
bundlesSubPath string = "bundles"
28+
catalogsSubPath string = "catalogs"
2129
)
2230

31+
type headerWithData struct {
32+
tar.Header
33+
Data []byte
34+
}
35+
2336
func main() {
2437
var (
2538
registryAddr string
@@ -34,6 +47,7 @@ func main() {
3447

3548
bundlesFullPath := fmt.Sprintf("%s/%s", imagesPath, bundlesSubPath)
3649
catalogsFullPath := fmt.Sprintf("%s/%s", imagesPath, catalogsSubPath)
50+
controllersFullPath := fmt.Sprintf("%s/%s", imagesPath, controllersSubPath)
3751

3852
bundles, err := buildBundles(bundlesFullPath)
3953
if err != nil {
@@ -43,6 +57,10 @@ func main() {
4357
if err != nil {
4458
log.Fatalf("failed to build catalogs: %s", err.Error())
4559
}
60+
controllers, err := buildControllers(controllersFullPath)
61+
if err != nil {
62+
log.Fatalf("failed to build controllers: %s", err.Error())
63+
}
4664
// Push the images
4765
for name, image := range bundles {
4866
dest := fmt.Sprintf("%s/%s", registryAddr, name)
@@ -58,6 +76,13 @@ func main() {
5876
log.Fatalf("failed to push catalog images: %s", err.Error())
5977
}
6078
}
79+
for name, image := range controllers {
80+
dest := fmt.Sprintf("%s/%s", registryAddr, name)
81+
log.Printf("pushing controller %s to %s", name, dest)
82+
if err := crane.Push(image, dest); err != nil {
83+
log.Fatalf("failed to push controller images: %s", err.Error())
84+
}
85+
}
6186
log.Printf("finished")
6287
os.Exit(0)
6388
}
@@ -122,6 +147,27 @@ func buildCatalogs(path string) (map[string]v1.Image, error) {
122147
return mutatedMap, nil
123148
}
124149

150+
func buildControllers(path string) (map[string]v1.Image, error) {
151+
controllers, err := processImageDirTree(path)
152+
if err != nil {
153+
return nil, err
154+
}
155+
mutatedMap := make(map[string]v1.Image, 0)
156+
// Apply required catalog label
157+
for key, img := range controllers {
158+
cfg := v1.Config{
159+
WorkingDir: "/",
160+
Entrypoint: []string{"/manager"},
161+
User: "65532:65532",
162+
}
163+
mutatedMap[fmt.Sprintf("controllers/%s", key)], err = mutate.Config(img, cfg)
164+
if err != nil {
165+
return nil, fmt.Errorf("failed to apply image labels: %w", err)
166+
}
167+
}
168+
return mutatedMap, nil
169+
}
170+
125171
func processImageDirTree(path string) (map[string]v1.Image, error) {
126172
imageMap := make(map[string]v1.Image, 0)
127173
images, err := os.ReadDir(path)
@@ -145,16 +191,53 @@ func processImageDirTree(path string) (map[string]v1.Image, error) {
145191
continue
146192
}
147193
tagFullPath := fmt.Sprintf("%s/%s", entryFullPath, tag.Name())
194+
b := &bytes.Buffer{}
195+
w := tar.NewWriter(b)
148196

149-
var fileMap map[string][]byte
150-
fileMap, err = createFileMap(tagFullPath)
197+
files, err := collectFiles(tagFullPath)
151198
if err != nil {
152199
return nil, fmt.Errorf("failed to read files for image: %w", err)
153200
}
201+
sort.Strings(files)
202+
203+
for _, f := range files {
204+
filePath := filepath.Join(tagFullPath, f)
205+
fileBytes, err := os.ReadFile(filePath)
206+
if err != nil {
207+
return nil, fmt.Errorf("failed to read file %q for image: %w", filePath, err)
208+
}
209+
//mode, err := getFileMode(filePath)
210+
//if err != nil {
211+
// return nil, fmt.Errorf("failed to determine mode for file %q for image: %w", filePath, err)
212+
//}
213+
if err := w.WriteHeader(&tar.Header{
214+
Name: f,
215+
Mode: 0777,
216+
Size: int64(len(fileBytes)),
217+
}); err != nil {
218+
return nil, err
219+
}
220+
log.Printf("added file %s with mode %d", filePath, 0777)
221+
222+
if _, err := w.Write(fileBytes); err != nil {
223+
return nil, err
224+
}
225+
}
226+
if err := w.Close(); err != nil {
227+
return nil, err
228+
}
229+
230+
// Return a new copy of the buffer each time it's opened.
231+
layer, err := tarball.LayerFromOpener(func() (io.ReadCloser, error) {
232+
return io.NopCloser(bytes.NewBuffer(b.Bytes())), nil
233+
})
234+
if err != nil {
235+
return nil, fmt.Errorf("failed to create image layer: %w", err)
236+
}
154237

155-
image, err := crane.Image(fileMap)
238+
image, err := mutate.AppendLayers(empty.Image, layer)
156239
if err != nil {
157-
return nil, fmt.Errorf("failed to generate image: %w", err)
240+
return nil, fmt.Errorf("failed to append layer to image: %w", err)
158241
}
159242
imageMap[fmt.Sprintf("%s:%s", entry.Name(), tag.Name())] = image
160243
}
@@ -180,3 +263,35 @@ func createFileMap(originPath string) (map[string][]byte, error) {
180263
}
181264
return fileMap, nil
182265
}
266+
267+
func collectFiles(originPath string) ([]string, error) {
268+
var files []string
269+
if err := fs.WalkDir(os.DirFS(originPath), ".", func(path string, d fs.DirEntry, err error) error {
270+
if err != nil {
271+
return err
272+
}
273+
if d != nil && !d.IsDir() {
274+
files = append(files, path)
275+
}
276+
return nil
277+
}); err != nil {
278+
return nil, err
279+
}
280+
return files, nil
281+
}
282+
283+
func getFileMode(path string) (int64, error) {
284+
info, err := os.Stat(path)
285+
if err != nil {
286+
return 0, err
287+
}
288+
289+
// return owner read/write by default
290+
var fileMode int64 = 0655
291+
292+
// or owner read/write/execute if the executable bit is set
293+
if info.Mode()&0111 != 0 {
294+
fileMode = 0755
295+
}
296+
return fileMode, nil
297+
}

0 commit comments

Comments
 (0)