mirror of
https://github.com/siderolabs/talos.git
synced 2025-12-18 07:51:56 +01:00
See https://github.com/siderolabs/image-factory/issues/43 Two fixes: * pass path to the dtb, uboot and rpi-firmware explicitly * include dtb, uboot and rpi-firmware into arm64 installer image when generated via imager (regular arm64 installer was fine) (The generation of SBC images was not broken for Talos itself, but only when used via Image Factory). Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
// Package filemap provides a way to create reproducible layers from a file system.
|
|
package filemap
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
|
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
|
"github.com/google/go-containerregistry/pkg/v1/tarball"
|
|
)
|
|
|
|
// File is a path -> file content map representing a file system.
|
|
type File struct {
|
|
ImagePath string
|
|
SourcePath string
|
|
}
|
|
|
|
// Walk the filesystem generating a filemap.
|
|
func Walk(sourceBasePath, imageBasePath string) ([]File, error) {
|
|
var filemap []File
|
|
|
|
err := filepath.WalkDir(sourceBasePath, func(path string, d os.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if d.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
rel, err := filepath.Rel(sourceBasePath, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
filemap = append(filemap, File{
|
|
ImagePath: filepath.Join(imageBasePath, rel),
|
|
SourcePath: path,
|
|
})
|
|
|
|
return nil
|
|
})
|
|
|
|
return filemap, err
|
|
}
|
|
|
|
// Layer creates a layer from a single file map.
|
|
//
|
|
// These layers are reproducible and consistent.
|
|
//
|
|
// A filemap is a path -> file content map representing a file system.
|
|
func Layer(filemap []File) (v1.Layer, error) {
|
|
b := &bytes.Buffer{}
|
|
w := tar.NewWriter(b)
|
|
|
|
sort.Slice(filemap, func(i, j int) bool {
|
|
return filemap[i].ImagePath < filemap[j].ImagePath
|
|
})
|
|
|
|
for _, entry := range filemap {
|
|
if err := func(entry File) error {
|
|
in, err := os.Open(entry.SourcePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer in.Close() //nolint:errcheck
|
|
|
|
st, err := in.Stat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = w.WriteHeader(&tar.Header{
|
|
Name: entry.ImagePath,
|
|
Size: st.Size(),
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = io.Copy(w, in)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return in.Close()
|
|
}(entry); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if err := w.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Return a new copy of the buffer each time it's opened.
|
|
return tarball.LayerFromOpener(func() (io.ReadCloser, error) {
|
|
return io.NopCloser(bytes.NewReader(b.Bytes())), nil
|
|
})
|
|
}
|