1
0
mirror of https://github.com/lxc/incus.git synced 2026-02-05 09:46:19 +01:00
Files
incus/cmd/incus-agent/templates.go
Stéphane Graber db29bd7aa8 Limit new() calls
Be more explicit about variable types.

Signed-off-by: Stéphane Graber <stgraber@stgraber.org>
2025-04-24 00:49:56 -04:00

149 lines
2.9 KiB
Go

package main
import (
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strconv"
"gopkg.in/yaml.v2"
"github.com/lxc/incus/v6/shared/api"
"github.com/lxc/incus/v6/shared/util"
)
func templatesApply(path string) ([]string, error) {
metaName := filepath.Join(path, "metadata.yaml")
if !util.PathExists(metaName) {
return nil, nil
}
// Parse the metadata.
content, err := os.ReadFile(metaName)
if err != nil {
return nil, fmt.Errorf("Failed to read metadata: %w", err)
}
metadata := &api.ImageMetadata{}
err = yaml.Unmarshal(content, metadata)
if err != nil {
return nil, fmt.Errorf("Could not parse metadata.yaml: %w", err)
}
// Go through the files and copy them into place.
files := []string{}
for tplPath, tpl := range metadata.Templates {
err = func(tplPath string, tpl *api.ImageMetadataTemplate) error {
filePath := filepath.Join(path, fmt.Sprintf("%s.out", tpl.Template))
if !util.PathExists(filePath) {
return nil
}
var w *os.File
if util.PathExists(tplPath) {
if tpl.CreateOnly {
return nil
}
// Open the existing file.
w, err = os.Create(tplPath)
if err != nil {
return fmt.Errorf("Failed to create template file: %w", err)
}
} else {
// UID and GID
fileUID := int64(0)
fileGID := int64(0)
if tpl.UID != "" {
id, err := strconv.ParseInt(tpl.UID, 10, 64)
if err != nil {
return fmt.Errorf("Bad file UID %q for %q: %w", tpl.UID, tplPath, err)
}
fileUID = id
}
if tpl.GID != "" {
id, err := strconv.ParseInt(tpl.GID, 10, 64)
if err != nil {
return fmt.Errorf("Bad file GID %q for %q: %w", tpl.GID, tplPath, err)
}
fileGID = id
}
// Mode
fileMode := fs.FileMode(0o644)
if tpl.Mode != "" {
if len(tpl.Mode) == 3 {
tpl.Mode = fmt.Sprintf("0%s", tpl.Mode)
}
mode, err := strconv.ParseInt(tpl.Mode, 0, 0)
if err != nil {
return fmt.Errorf("Bad mode %q for %q: %w", tpl.Mode, tplPath, err)
}
fileMode = os.FileMode(mode) & os.ModePerm
}
// Create the directories leading to the file.
err := os.MkdirAll(filepath.Dir(tplPath), 0o755)
if err != nil {
return err
}
// Create the file itself.
w, err = os.Create(tplPath)
if err != nil {
return err
}
// Fix ownership.
err = w.Chown(int(fileUID), int(fileGID))
if err != nil {
return err
}
// Fix mode.
err = w.Chmod(fileMode)
if err != nil {
return err
}
}
defer func() { _ = w.Close() }()
// Do the copy.
src, err := os.Open(filePath)
if err != nil {
return err
}
defer func() { _ = src.Close() }()
_, err = io.Copy(w, src)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
files = append(files, tplPath)
return nil
}(tplPath, tpl)
if err != nil {
return nil, err
}
}
return files, nil
}