)
func handleFiles(cfg *Config, state *State) error {
+ // Split into fetch and deploy phase to prevent updates of only some
+ // files which might lead to inconsistent state; obviously this won't
+ // work during the deploy phase, but it helps if the web server fails
+ // to deliver some files
+
for i, f := range cfg.Files {
err := fetchFile(&cfg.Files[i], state)
if err != nil {
defer os.Remove(f.Name())
defer f.Close()
- // Apply permissions/user/group from the target file
+ // Apply permissions/user/group from the target file, use Stat instead
+ // of Lstat as only the target's permissions are relevant
stat, err := os.Stat(file.Path)
if err != nil {
// We do not create the path if it doesn't exist, because we
Name string
Passwd string
Gid uint64
- Members string
+ Members string // "," separated
}
func toKey(g Group) GroupKey {
}
// ParseGroups parses a file in the format of /etc/group and returns all
-// entries as Group structs.
+// entries as slice of Group structs.
func ParseGroups(r io.Reader) ([]Group, error) {
var res []Group
}
// ParsePasswds parses a file in the format of /etc/passwd and returns all
-// entries as Passwd structs.
+// entries as slice of Passwd structs.
func ParsePasswds(r io.Reader) ([]Passwd, error) {
var res []Passwd