func InsureNewVersionFiles(da *model.DesiredAgent) error { if FilesReady(da) { return nil } downloadTarballCmd := BuildCommand(da.RunUser, "wget", "-q", da.TarballUrl, "-O", path.Join(da.AgentVersionDir, da.TarballFilename)) downloadTarballCmd.Dir = file.SelfDir() _, err := ExecuteCommandWithOutput(downloadTarballCmd) if err != nil { logger.Errorln("wget -q", da.TarballUrl, "-O", da.TarballFilename, "fail", err) return err } downloadMd5Cmd := BuildCommand(da.RunUser, "wget", "-q", da.Md5Url, "-O", path.Join(da.AgentVersionDir, da.Md5Filename)) downloadMd5Cmd.Dir = file.SelfDir() _, err = ExecuteCommandWithOutput(downloadMd5Cmd) if err != nil { log.Println("wget -q", da.Md5Url, "-O", da.Md5Filename, "fail", err) return err } if "" != da.ConfigFileName && "" != da.ConfigRemoteUrl { downloadConfigCmd := BuildCommand(da.RunUser, "wget", "-q", da.ConfigRemoteUrl, "-O", path.Join(da.AgentVersionDir, da.ConfigFileName)) downloadConfigCmd.Dir = file.SelfDir() _, err := ExecuteCommandWithOutput(downloadConfigCmd) if err != nil { logger.Errorln("wget -q", da.ConfigRemoteUrl, "-O", da.ConfigFileName, "fail", err) } return err } return Md5sumCheck(da.RunUser, da.AgentVersionDir, da.TarballFilename, da.Md5Filename) }
func WriteVersion(da *model.DesiredAgent) (err error) { if CurrentUser == da.RunUser { file.WriteString(path.Join(da.AgentDir, ".version"), da.Version) } else { file.WriteString(path.Join(file.SelfDir(), ".version"), da.Version) _, err = utils.ExecuteCommand(file.SelfDir(), fmt.Sprintf("sudo mv .version %s/", da.AgentDir)) if nil != err { return } _, err = utils.ExecuteCommand(file.SelfDir(), fmt.Sprintf("sudo chown -R %s:%s %s", da.RunUser, da.RunUser, path.Join(da.AgentDir, ".version"))) } return }
func StopAgentOf(da *model.DesiredAgent, lastRunUser, lastWorkDir string) error { agentDir := path.Join(lastWorkDir, da.Name) version := ReadVersion(lastRunUser, agentDir) if "" == version { version = da.Version } if version == da.Version && da.RunUser == lastRunUser && da.WorkDir == lastWorkDir { // do nothing return nil } versionDir := path.Join(agentDir, version) if !CheckDirectoryExists(lastRunUser, versionDir) { logger.Warn("user: %s, %s nonexistent", lastRunUser, versionDir) return nil } err := ControlStopIn(lastRunUser, versionDir) if nil != err { return err } cmd := BuildCommand(lastRunUser, "rm", "-rf", versionDir) cmd.Dir = file.SelfDir() _, err = ExecuteCommandWithOutput(cmd) return err }
func Md5sumCheck(runUser, workdir, tarfile, md5file string) error { var cmd *exec.Cmd var md5Actual string if "darwin" == runtime.GOOS { cmd = BuildCommand(runUser, "md5", "-q", path.Join(workdir, tarfile)) } else { cmd = BuildCommand(runUser, "md5sum", path.Join(workdir, tarfile)) } cmd.Dir = file.SelfDir() bs, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("cd %s; md5sum -c %s fail", workdir, md5file) } strMd5file, _ := file.ToString(path.Join(workdir, md5file)) if "" == strMd5file { return fmt.Errorf("md5file is empty") } if "darwin" == runtime.GOOS { md5Actual = strings.Replace(string(bs), "\n", "", -1) } else { md5Actual = strings.Fields(string(bs))[0] } md5Except := strings.Fields(strMd5file)[0] if md5Actual == md5Except { return nil } return fmt.Errorf("md5Actual:%s, md5Except:%s<<<===end", md5Actual, md5Except) }
func configCommonRoutes() { http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) }) http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(g.VERSION)) }) http.HandleFunc("/workdir", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, file.SelfDir()) }) http.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, g.Config()) }) http.HandleFunc("/config/reload", func(w http.ResponseWriter, r *http.Request) { if strings.HasPrefix(r.RemoteAddr, "127.0.0.1") { g.ParseConfig(g.ConfigFile) RenderDataJson(w, "ok") } else { RenderDataJson(w, "no privilege") } }) }
func CheckUserExists(username string) bool { _, err := ExecuteCommand(file.SelfDir(), fmt.Sprintf("id -u %s", username)) if nil != err { return false } return true }
func configAdminRoutes() { http.HandleFunc("/exit", func(w http.ResponseWriter, r *http.Request) { if g.IsTrustable(r.RemoteAddr) { w.Write([]byte("exiting...")) go func() { time.Sleep(time.Second) os.Exit(0) }() } else { w.Write([]byte("no privilege")) } }) http.HandleFunc("/config/reload", func(w http.ResponseWriter, r *http.Request) { if g.IsTrustable(r.RemoteAddr) { g.ParseConfig(g.ConfigFile) RenderDataJson(w, g.Config()) } else { w.Write([]byte("no privilege")) } }) http.HandleFunc("/workdir", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, file.SelfDir()) }) http.HandleFunc("/ips", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, g.TrustableIps()) }) }
func Control(runUser, workdir, arg string) (string, error) { cmd := BuildCommand(runUser, path.Join(workdir, "control"), arg) cmd.Dir = file.SelfDir() out, err := ExecuteCommandWithOutput(cmd) if err != nil { logger.Error("cd %s; ./control %s fail %v. output: %s\n", workdir, arg, err, out) } return out, err }
func GetUserByPid(pid int) string { cmd := exec.Command("sh", "-c", fmt.Sprintf("ps aux|awk '{if(%d==$2){print $1}}'", pid)) cmd.Dir = file.SelfDir() bs, err := cmd.CombinedOutput() if nil != err { log.Println("getUserByPid error", err) return "" } return strings.Replace(string(bs), "\n", "", -1) }
func Untar(da *model.DesiredAgent) error { cmd := BuildCommand(da.RunUser, "tar", "zxf", path.Join(da.AgentVersionDir, da.TarballFilename), "-C", da.AgentVersionDir) cmd.Dir = file.SelfDir() err := cmd.Run() if err != nil { log.Println("tar zxf", da.TarballFilename, "fail", err) return err } return nil }
func ReadVersion(username, agentDir string) string { versionFile := path.Join(agentDir, ".version") cmd := BuildCommand(username, "sh", "read_file.sh", versionFile) cmd.Dir = file.SelfDir() version, err := ExecuteCommandWithOutput(cmd) if err != nil { logger.Warn("%s is nonexistent,error: %v", versionFile, err) return "" } return version }
func InsureRunUserExists(da *model.DesiredAgent) error { if CurrentUser == da.RunUser { //ops-updater和 Agent运行用户一致 return nil } else if HasSudoPermission { if utils.CheckUserExists(da.RunUser) { return nil } _, err := utils.ExecuteCommand(file.SelfDir(), fmt.Sprintf("sudo useradd %s", da.RunUser)) return err } return fmt.Errorf("you donot have permission to insure user %s", da.RunUser) }
func InsureUserDir(fp, username string, createByRoot bool) error { var err error if CheckDirectoryExists(username, fp) { return nil } if CurrentUser == username { return os.MkdirAll(fp, os.ModePerm) } else if HasSudoPermission { if createByRoot { _, err = utils.ExecuteCommand(file.SelfDir(), fmt.Sprintf("sudo mkdir -p %s", fp)) if nil != err { return err } _, err = utils.ExecuteCommand(file.SelfDir(), fmt.Sprintf("sudo chown -R %s:%s %s", username, username, fp)) } else { _, err = utils.ExecuteCommand(file.SelfDir(), fmt.Sprintf("sudo -u %s mkdir -p %s", username, fp)) } } return err }
func CheckFileOrDirExists(username, fp, fileType string) bool { if CurrentUser == username { return file.IsExist(fp) } else { cmd := BuildCommand(username, "sh", "check_file.sh", fileType, fp) cmd.Dir = file.SelfDir() strOut, err := ExecuteCommandWithOutput(cmd) if nil != err { logger.Errorln("check dir exists", strOut, err) return false } result, _ := strconv.ParseBool(strings.Replace(strOut, "\n", "", -1)) return result } return false }
func configCommonRoutes() { http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok\n")) }) http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(fmt.Sprintf("%s\n", g.VERSION))) }) http.HandleFunc("/workdir", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(fmt.Sprintf("%s\n", file.SelfDir()))) }) http.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, g.Config()) }) }
func BuildHeartbeatRequest(hostname string, desiredAgents []*model.DesiredAgent) model.HeartbeatRequest { req := model.HeartbeatRequest{Hostname: hostname} req.Ip = utils.GetLocalIP() req.UpdaterVersion = g.VERSION req.RunUser = CurrentUser realAgents := []*model.RealAgent{} now := time.Now().Unix() for _, da := range desiredAgents { agentDir := path.Join(da.WorkDir, da.Name) // 如果目录下没有.version,我们认为这根本不是一个agent version := ReadVersion(da.RunUser, agentDir) if "" == version { logger.Error("read %s/.version fail\n", agentDir) continue } controlFile := path.Join(agentDir, version, "control") if !CheckFileExists(da.RunUser, controlFile) { logger.Errorln(controlFile, "is nonexistent, user:"******"control"), "status") cmd.Dir = f.SelfDir() status, err := ExecuteCommandWithOutput(cmd) if err != nil { status = err.Error() } realAgent := &model.RealAgent{ Name: da.Name, Version: version, Status: status, Timestamp: now, } realAgent.RunUser = da.RunUser realAgent.WorkDir = da.WorkDir realAgents = append(realAgents, realAgent) } req.RealAgents = realAgents return req }
func configCommonRoutes() { http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) }) http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(g.VERSION)) }) http.HandleFunc("/versiongit", func(w http.ResponseWriter, r *http.Request) { s := fmt.Sprintf("%s %s", g.VERSION, g.COMMIT) w.Write([]byte(s)) }) http.HandleFunc("/workdir", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, file.SelfDir()) }) }
func ReadDesiredAgents() []*model.DesiredAgent { var desiredAgents []*model.DesiredAgent strJson, err := f.ToTrimString(path.Join(f.SelfDir(), "desired_agent.json")) if nil != err { logger.Errorln("read desired agent file error", err) return desiredAgents } err = json.Unmarshal([]byte(strJson), &desiredAgents) if nil != err { logger.Errorln("unmarshal json error", strJson, err) } for _, da := range desiredAgents { actualVersion := ReadVersion(da.RunUser, path.Join(da.WorkDir, da.Name)) if "" != actualVersion { da.Version = actualVersion } } return desiredAgents }
func configRoutes() { // GET http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if nil != checkLoggedIn(w, r) { return } queries, err := url.ParseQuery(r.URL.RawQuery) var perPage int = 20 var start int = 0 if err == nil && len(queries["start"]) > 0 { start, _ = strconv.Atoi(queries["start"][0]) } var stop int = start + perPage - 1 if err == nil && len(queries["stop"]) > 0 { stop, _ = strconv.Atoi(queries["stop"][0]) } var currentPage int = start/perPage + 1 var prePageStart int = 0 var prePageStop int = 19 var nextPageStart int = 20 var nextPageStop int = 39 var showPrePage = false if currentPage > 1 { showPrePage = true prePageStart = (currentPage - 2) * perPage prePageStop = prePageStart + perPage - 1 } nextPageStart = currentPage * perPage nextPageStop = nextPageStart + perPage - 1 logs, err := mail.GetMailLog(start, stop) if err != nil { w.Write([]byte(err.Error())) return } var mailLogs []model.EmailLog for _, l := range logs.([]interface{}) { var m model.EmailLog err := json.Unmarshal(l.([]byte), &m) if err != nil { log.Println("HandleFunc: / Unmarshal error - ", err.Error()) } else { mailLogs = append(mailLogs, m) } } data := map[string]interface{}{ "mailLogs": mailLogs, "start": start, "stop": stop, "currentPage": currentPage, "showPrePage": showPrePage, "prePageStart": prePageStart, "prePageStop": prePageStop, "nextPageStart": nextPageStart, "nextPageStop": nextPageStop, } Render(w, "home/index.html", data) }) // GET http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { data := status.Check() Render(w, "status/index.html", data) }) // GET http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { Render(w, "home/login.html", nil) }) http.HandleFunc("/doLogin", func(w http.ResponseWriter, r *http.Request) { if !lastErrorTime.IsZero() && (time.Now().Sub(lastErrorTime) < time.Minute) { w.Write([]byte("Pls try after " + time.Now().Add(time.Minute).String())) return } r.ParseForm() if len(r.Form["password"]) < 1 { w.Write([]byte("Need password.")) return } if len(r.Form["username"]) < 1 { w.Write([]byte("Need username.")) return } password := r.Form["password"][0] username := r.Form["username"][0] if password != config.Config().Password || username != config.Config().Username { lastErrorTime = time.Now() w.Write([]byte("I love you, Pls don't hurt me.")) return } else { storeUsername(w, r, username) http.Redirect(w, r, "/", http.StatusFound) return } }) http.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) { storeUsername(w, r, "") http.Redirect(w, r, "/login", http.StatusFound) return }) http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok\n")) }) http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { if nil != checkLoggedIn(w, r) { return } w.Write([]byte(fmt.Sprintf("%s\n", config.VERSION))) }) http.HandleFunc("/workdir", func(w http.ResponseWriter, r *http.Request) { if nil != checkLoggedIn(w, r) { return } w.Write([]byte(fmt.Sprintf("%s\n", file.SelfDir()))) }) http.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) { if nil != checkLoggedIn(w, r) { return } RenderOKJson(w, config.Config()) }) http.HandleFunc("/config/reload", func(w http.ResponseWriter, r *http.Request) { if nil != checkLoggedIn(w, r) { return } config.Parse(config.ConfigFile) RenderOKJson(w, config.Config()) }) http.HandleFunc("/public/", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, r.URL.Path[1:]) }) }
func (this *FrameController) WorkDir() { this.Ctx.WriteString(file.SelfDir()) }
func (this *MainController) Workdir() { this.Ctx.WriteString(fmt.Sprintf("%s", file.SelfDir())) }
func InitGlobalVariables() { SelfDir = file.SelfDir() }