feat: add ability to append to existing files with extrafiles

This PR introduces "op" to the extra files options. This allows for a
user to specify "append" as the op, which will create a copy of the file
specified, add the extra data provided, and bind mount over the existing
file. Will close #1467

Signed-off-by: Spencer Smith <robertspencersmith@gmail.com>
This commit is contained in:
Spencer Smith
2019-12-05 14:13:15 -05:00
committed by Andrew Rynhard
parent 264c5440ef
commit 84354c5941
2 changed files with 40 additions and 1 deletions

View File

@@ -5,11 +5,14 @@
package config
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/hashicorp/go-multierror"
"golang.org/x/sys/unix"
"github.com/talos-systems/talos/internal/app/machined/internal/phase"
"github.com/talos-systems/talos/internal/pkg/runtime"
@@ -32,13 +35,48 @@ func (task *ExtraFiles) runtime(r runtime.Runtime) (err error) {
var result *multierror.Error
for _, f := range r.Config().Machine().Files() {
p := filepath.Join("/var", f.Path)
// Slurp existing file if append is our op and add contents to it
if f.Op == "append" {
var existingFileContents []byte
existingFileContents, err = ioutil.ReadFile(f.Path)
if err != nil {
result = multierror.Append(result, err)
continue
}
f.Contents = string(existingFileContents) + "\n" + f.Contents
}
// Determine if supplied path is in /var or not.
// If not, we'll write it to /var anyways and bind mount below
p := f.Path
inVar := true
explodedPath := strings.Split(
strings.TrimLeft(f.Path, "/"),
string(os.PathSeparator),
)
if explodedPath[0] != "var" {
p = filepath.Join("/var", f.Path)
inVar = false
}
if err = os.MkdirAll(filepath.Dir(p), os.ModeDir); err != nil {
result = multierror.Append(result, err)
continue
}
if err = ioutil.WriteFile(p, []byte(f.Contents), f.Permissions); err != nil {
result = multierror.Append(result, err)
continue
}
// File path was not /var/... so we assume a bind mount is wanted
if !inVar {
if err = unix.Mount(p, f.Path, "", unix.MS_BIND|unix.MS_RDONLY, ""); err != nil {
result = multierror.Append(result, fmt.Errorf("failed to create bind mount for %s: %w", p, err))
}
}
}

View File

@@ -47,6 +47,7 @@ type File struct {
Contents string `yaml:"contents"`
Permissions os.FileMode `yaml:"permissions"`
Path string `yaml:"path"`
Op string `yaml:"op"`
}
// Security defines the requirements for a config that pertains to security