func Run() { Watcher.Add(&DockerContainers{}) for { select { case data := <-Watcher.DataCh: { view = data log.Debugf("name: %s, data: %v", data.Dependency.Name(), data.Data) switch data.Dependency.Name() { case "docker_containers": { containers := data.Data.([]*Container) localComps := LocalComponents() log.Infoln("localComps = ", localComps) for _, comp := range localComps { switch comp.Name { case "dis-collectd": { err := rewriteConfigForCollectd(comp, containers) if err != nil { log.Errorln(err) continue } out, err := utils.ExecCommand(false, comp.DeployFilepath, "reload") if err != nil { log.Errorf("Execute command '%s reload' error: %s", comp.DeployFilepath, err) continue } log.Debugln(out) } case "logstash-forwarder": { err := rewriteConfigForLogstashForwarder(comp, containers) if err != nil { log.Errorln(err) continue } out, err := utils.ExecCommand(false, comp.DeployFilepath, "restart") if err != nil { log.Errorf("Execute command '%s restart' error: %s", comp.DeployFilepath, err.Error()) continue } log.Debugln(out) } } } } } } case err := <-Watcher.ErrCh: log.Errorln(err) } } }
func rewriteConfigForLogstashForwarder(comp *model.Component, containers []*Container) error { log.Infoln("rewrite configuration file ", comp.Name) // 1. Load configuration file. c := &Config{} err := LoadConfig(comp.ConfigFilepath, c) if err != nil { return err } newFiles := make([]FileConfig, 0, 10) // 2. Change the configuration content. for _, fileCfg := range c.Files { var pathsContainsUPM_DATA bool = false for _, fp := range fileCfg.Paths { if strings.Contains(fp, "upm-data") { pathsContainsUPM_DATA = true break } } if !pathsContainsUPM_DATA { newFiles = append(newFiles, fileCfg) } } for _, ctn := range containers { fileCfg := FileConfig{ Fields: make(map[string]string, 5), } if len(ctn.Names) > 0 { _path := fmt.Sprintf("/upm-data/%s/logs/*log*", path.Base(ctn.Names[0])) fileCfg.Paths = append(fileCfg.Paths, _path) fileCfg.Fields["type"] = strings.Split(path.Base(ctn.Image), ":")[0] fileCfg.Fields["image"] = ctn.Image fileCfg.Fields["cid"] = ctn.ID fileCfg.Fields["created"] = strconv.FormatInt(ctn.Created, 10) fileCfg.Fields["name"] = path.Base(ctn.Names[0]) } newFiles = append(newFiles, fileCfg) } c.Files = newFiles // 3. Rewrite the configuration file. ret, err := json.MarshalIndent(c, "", " ") if err != nil { return err } log.Debugln("configuration file path is ", comp.ConfigFilepath) err = utils.WriteFile(comp.ConfigFilepath, ret, 0644) return err }
func LocalComponents() (remoteComponents map[string]*model.Component) { subDirs, err := utils.SubDirs(stackDir) if err != nil { log.Errorln(err) return } remoteComponents = make(map[string]*model.Component) for _, subDir := range subDirs { log.Infoln("subDir: ", subDir) // If .version file not found in current directory, so we considered that not a remote component existed. versionFile := path.Join(stackDir, subDir, ".version") if !utils.IsExist(versionFile) { log.Errorf("Can't found .version file: %s", versionFile) continue } versionBytes, err := utils.ReadFile(versionFile) if err != nil { log.Errorf("Failed to read %s/.version : %v", subDir, err) continue } version := strings.TrimSpace(string(versionBytes)) cmd := exec.Command("./deploy", "status") cmd.Dir = path.Join(stackDir, subDir, version) statusOutput, err := cmd.CombinedOutput() if err != nil { log.Errorf("Failed to run command: %s ,error: %v", "./deploy status", err) continue } status := strings.TrimSpace(string(statusOutput)) log.Infof("local componet: %s, stauts: %s", subDir, status) if strings.Contains(status, "stoped") { os.Remove(versionFile) continue } remoteComp := &model.Component{ Name: subDir, Version: version, Status: status, Timestamp: time.Now(), } remoteComp.InitAttrs(stackDir) remoteComponents[remoteComp.Name] = remoteComp } return }
func Start() { if !config.AppConfig().Http.Enabled { return } addr := config.AppConfig().Http.Listen if addr == "" { return } server := &http.Server{ Addr: addr, Handler: initRouter(), } log.Infoln("http listening on ", addr) log.Fatalln(server.ListenAndServe()) }
func rewriteConfigForCollectd(comp *model.Component, containers []*Container) error { log.Infoln("rewrite configuration file ", comp.Name) // 1. Load configuration file. c := &cfg_collected.Config{} _, err := toml.DecodeFile(comp.ConfigFilepath, c) if err != nil { return err } // 2. Change the configuration content. inputConfig := &cfg_collected.InputConfig{ Enabled: true, Interval: DefaultInterval, SubInput: make([]*cfg_collected.InputConfig, len(containers)), } for i, ctn := range containers { serviceType := strings.Split(path.Base(ctn.Image), ":")[0] var interval int itv, ok := config.AppConfig().Intervals[serviceType] if !ok { log.Warnf("service %s hasn't config interval, using default %d", serviceType, DefaultInterval) interval = DefaultInterval } else { interval = itv.Value } subConfig := &cfg_collected.InputConfig{ Enabled: true, Interval: interval, Tags: fmt.Sprintf("cid:%s", ctn.ID), } inputConfig.SubInput[i] = subConfig } c.Input["container"] = inputConfig // 3. Rewrite the configuration file. buf := bytes.NewBuffer(nil) encoder := toml.NewEncoder(buf) err = encoder.Encode(c) if err != nil { return err } encoder.Indent = " " log.Debugln("configuration file path is ", comp.ConfigFilepath) err = utils.WriteFile(comp.ConfigFilepath, buf.Bytes(), 0644) return err }
// Update or create func heartbeat() { log.Debugln("heartbeat......") log.Debugln("stackDir is ", stackDir) localComps := LocalComponents() hbtRequest, err := buildHeartbeatRequest() if err != nil { log.Errorln(err) return } hbtRequest.RemoteComponents = localComps log.Infoln("request: ", hbtRequest) // http request to server heartbeat url. if config.AppConfig().Server == "" { log.Errorln("configuration server is blank.") return } heartbeatURL := fmt.Sprintf("http://%s/heartbeat", config.AppConfig().Server) hbtResponse, err := requestHeartbeat(heartbeatURL, hbtRequest) if err != nil { log.Errorln(err) return } log.Infoln("response: ", hbtResponse) if hbtResponse != nil && hbtResponse.Components != nil { log.Infoln("response comps : ", hbtResponse.Components) for _, newComp := range hbtResponse.Components { newComp.InitAttrs(stackDir) log.Debugf("newComp: %s", newComp) // 1. Create version directory. stack_dir/comp_name/version_number/ if utils.IsExist(newComp.VersionDir) { _, err := utils.ExecCommand(false, "mkdir", "-p", newComp.VersionDir) if err != nil { log.Errorln(err) continue } } // 2. Download new version component. downURL := fmt.Sprintf("http://%s/%s", config.AppConfig().Server, newComp.TarballFilename) err = downloadFromURL(newComp.TarballFilepath, downURL) if err != nil { log.Errorln(err) continue } // 3. Uncompress the new component file. output, err := utils.ExecCommand(false, "tar", "-zxf", newComp.TarballFilepath, "-C", newComp.VersionDir) if err != nil { log.Errorln(err) continue } log.Debugf("Untar file: %s , output: %s", newComp.TarballFilepath, output) if newComp.Cmd == "start" { if view != nil { containers := view.Data.([]*Container) switch newComp.Name { case "dis-collectd": { err := rewriteConfigForCollectd(newComp, containers) if err != nil { log.Errorln("rewriteConfigForCollectd error: ", err) continue } } case "logstash-forwarder": { err := rewriteConfigForLogstashForwarder(newComp, containers) if err != nil { log.Errorln("rewriteConfigForLogstashForwarder error: ", err) continue } } } } log.Debugln("new component DeployFilepath = ", newComp.DeployFilepath) output, err = utils.ExecCommand(false, newComp.DeployFilepath, "start") if err != nil { log.Errorln(err) continue } log.Debugf("Execute command: %s %s, output: %s\n", newComp.DeployFilepath, newComp.Cmd, output) // Componet directory was existed, then shutdown old verison component. if utils.IsExist(path.Join(newComp.Directory, ".version")) { oldVersion_b, err := utils.ReadFile(path.Join(newComp.Directory, ".version")) if err != nil { log.Errorln(err) continue } oldDeployFilePath := path.Join(newComp.Directory, strings.TrimSpace(string(oldVersion_b)), "deploy") _, err = utils.ExecCommand(false, oldDeployFilePath, "stop") if err != nil { log.Errorln(err) continue } } // Write the verion number to .version in the parent directory. log.Debugln("write version number file, ", newComp.Directory) err = utils.WriteFile(path.Join(newComp.Directory, ".version"), []byte(newComp.Version), 0644) if err != nil { log.Errorln(err) continue } // Register this component to consul. err = common.ConsulRegister(newComp.Name, newComp.DeployFilepath) if err != nil { log.Errorln(err) continue } } else { log.Debugln("new component DeployFilepath = ", newComp.DeployFilepath) output, err = utils.ExecCommand(false, newComp.DeployFilepath, newComp.Cmd) if err != nil { log.Errorln(err) continue } log.Debugln("Execute command: %s %s, output: %s\n", newComp.DeployFilepath, newComp.Cmd, output) } } } }
func (c *Context) Heartbeat(rw web.ResponseWriter, req *web.Request) { log.Infoln(req.RemoteAddr, " heartbeating...") hbtResponse := &model.HeartbeatResponse{} defer c.WriteResponse(hbtResponse) if req.ContentLength == 0 { rw.WriteHeader(http.StatusBadRequest) hbtResponse.Message = "body is blank" return } hbtRequest := &model.HeartbeatRequest{} decoder := json.NewDecoder(req.Body) err := decoder.Decode(hbtRequest) if err != nil { rw.WriteHeader(http.StatusBadRequest) hbtResponse.Message = err.Error() return } if hbtRequest.Hostname == "" { rw.WriteHeader(http.StatusBadRequest) hbtResponse.Message = "hostname is blank" return } hbtResponse.Components = make(map[string]*model.Component) // if hbtRequest.RemoteComponents == nil || len(hbtRequest.RemoteComponents) == 0 { agent, exist := cache.Agents.Get(hbtRequest.Hostname) if exist { agent.Address = req.RemoteAddr agent.Components = hbtRequest.RemoteComponents agent.Timestamp = time.Now() } else { agent = &cache.Agent{ Hostname: hbtRequest.Hostname, Address: req.RemoteAddr, Components: hbtRequest.RemoteComponents, Timestamp: time.Now(), } cache.Agents.Put(hbtRequest.Hostname, agent) } log.Debugln("remote: ", hbtRequest) log.Debugln("server: ", cache.Components) for name, component := range cache.Components.Map { comp, ok := hbtRequest.RemoteComponents[name] if !ok { // Remote component does not exist. // Add to response hbtResponse.Components[name] = component continue } // Check whether the latest version. if comp.Version >= component.Version { continue } hbtResponse.Components[name] = component } // } log.Debugln("response: ", hbtResponse) }