github.com/masahide/goansible@v0.0.0-20160116054156-01eac649e9f2/template.go (about) 1 package goansible 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "syscall" 11 ) 12 13 type TemplateCmd struct { 14 Src string `goansible:"src,required"` 15 Dest string `goansible:"dest,required"` 16 Owner string `goansible:"owner"` 17 Uid int `goansible:"uid"` 18 Gid int `goansible:"gid"` 19 Mode int `goansible:"mode"` 20 } 21 22 func (cmd *TemplateCmd) Run(env *CommandEnv) (*Result, error) { 23 var src string 24 //pp.Print(env) 25 if cmd.Mode == 0 { 26 cmd.Mode = 0644 27 } 28 29 if cmd.Src[0] == '/' { 30 src = cmd.Src 31 } else { 32 src = env.Paths.TemplateFile(cmd.Src) 33 } 34 35 //input, err := os.Open(src) 36 b, err := ioutil.ReadFile(src) 37 38 if err != nil { 39 return FailureResult(err), err 40 } 41 42 expand, err := ExpandTemplates(env.Env.Vars, string(b)) 43 if err != nil { 44 return FailureResult(err), err 45 } 46 47 srcDigest := md5string(expand) 48 49 var dstDigest []byte 50 51 dest := cmd.Dest 52 53 link := false 54 55 destStat, err := os.Lstat(dest) 56 if err == nil { 57 if destStat.IsDir() { 58 dest = filepath.Join(dest, filepath.Base(src)) 59 } else { 60 dstDigest, _ = md5file(dest) 61 } 62 63 link = destStat.Mode()&os.ModeSymlink != 0 64 } 65 66 rd := ResultData{ 67 "md5sum": Any(hex.EncodeToString(srcDigest)), 68 "src": Any(src), 69 "dest": Any(dest), 70 } 71 72 //pp.Print(dstDigest, srcDigest) 73 if dstDigest != nil && bytes.Equal(srcDigest, dstDigest) { 74 changed := false 75 76 if cmd.Mode != 0 && destStat.Mode() != os.FileMode(cmd.Mode) { 77 changed = true 78 if err := os.Chmod(dest, os.FileMode(cmd.Mode)); err != nil { 79 return FailureResult(err), err 80 } 81 } 82 if cmd.Uid, cmd.Gid, err = ChangePerm(cmd.Owner, cmd.Uid, cmd.Gid); err != nil { 83 return FailureResult(err), err 84 } 85 if estat, ok := destStat.Sys().(*syscall.Stat_t); ok { 86 if cmd.Uid != int(estat.Uid) || cmd.Gid != int(estat.Gid) { 87 changed = true 88 os.Chown(dest, cmd.Uid, cmd.Gid) 89 } 90 } 91 92 return WrapResult(changed, rd), nil 93 } 94 95 tmp := fmt.Sprintf("%s.tmp.%d", cmd.Dest, os.Getpid()) 96 97 // output, err := os.OpenFile(tmp, os.O_CREATE|os.O_WRONLY, 0644) 98 err = ioutil.WriteFile(tmp, []byte(expand), 0644) 99 100 if err != nil { 101 return FailureResult(err), err 102 } 103 104 if link { 105 os.Remove(dest) 106 } 107 108 if err := os.Chmod(tmp, os.FileMode(cmd.Mode)); err != nil { 109 os.Remove(tmp) 110 return FailureResult(err), err 111 } 112 113 if cmd.Uid, cmd.Gid, err = ChangePerm(cmd.Owner, cmd.Uid, cmd.Gid); err != nil { 114 return FailureResult(err), err 115 } 116 os.Chown(tmp, cmd.Uid, cmd.Gid) 117 118 err = os.Rename(tmp, dest) 119 if err != nil { 120 os.Remove(tmp) 121 return FailureResult(err), err 122 } 123 124 return WrapResult(true, rd), nil 125 } 126 127 func init() { 128 RegisterCommand("template", &TemplateCmd{}) 129 }