func (h *MessageHandler) handle(msg queue.Message) { if msg.Visits >= MaxVisits { log.Printf("Error handling %q: this message has been visited more than %d times.", msg.Action, MaxVisits) return } switch msg.Action { case app.RegenerateApprc: if len(msg.Args) < 1 { log.Printf("Error handling %q: this action requires at least 1 argument.", msg.Action) return } app, err := h.ensureAppIsStarted(msg) if err != nil { log.Print(err) return } app.SerializeEnvVars() case app.StartApp: if len(msg.Args) < 1 { log.Printf("Error handling %q: this action requires at least 1 argument.", msg.Action) } app, err := h.ensureAppIsStarted(msg) if err != nil { log.Print(err) return } err = app.Restart(ioutil.Discard) if err != nil { log.Printf("Error handling %q. App failed to start:\n%s.", msg.Action, err) } default: log.Printf("Error handling %q: invalid action.", msg.Action) } }
func handle(msg *queue.Message) { switch msg.Action { case app.RegenerateApprc: if len(msg.Args) < 1 { log.Printf("Error handling %q: this action requires at least 1 argument.", msg.Action) return } app, err := ensureAppIsStarted(msg) if err != nil { log.Print(err) return } app.SerializeEnvVars() case app.StartApp: if len(msg.Args) < 1 { log.Printf("Error handling %q: this action requires at least 1 argument.", msg.Action) } app, err := ensureAppIsStarted(msg) if err != nil { log.Print(err) return } err = app.Restart(ioutil.Discard) if err != nil { log.Printf("Error handling %q. App failed to start:\n%s.", msg.Action, err) } default: log.Printf("Error handling %q: invalid action.", msg.Action) } }
func (c *Client) Bind(instance *ServiceInstance, app bind.App, unit bind.Unit) (map[string]string, error) { log.Print("Attempting to call bind of service instance " + instance.Name + " and unit " + unit.GetIp() + " at " + instance.ServiceName + " api") var resp *http.Response params := map[string][]string{ "unit-host": {unit.GetIp()}, "app-host": {app.GetIp()}, } resp, err := c.issueRequest("/resources/"+instance.Name, "POST", params) if err != nil { if m, _ := regexp.MatchString("", err.Error()); m { return nil, fmt.Errorf("%s api is down.", instance.Name) } return nil, err } if err == nil && resp.StatusCode < 300 { var result map[string]string err = c.jsonFromResponse(resp, &result) if err != nil { return nil, err } return result, nil } if resp.StatusCode == http.StatusPreconditionFailed { return nil, &errors.HTTP{Code: resp.StatusCode, Message: "You cannot bind any app to this service instance because it is not ready yet."} } msg := "Failed to bind instance " + instance.Name + " to the unit " + unit.GetIp() + ": " + c.buildErrorMessage(err, resp) log.Print(msg) return nil, &errors.HTTP{Code: http.StatusInternalServerError, Message: msg} }
// Ip returns the ip for the container. func (c *container) IP() string { if c.ip != "" { return c.ip } timeout, err := config.GetInt("lxc:ip-timeout") if err != nil { timeout = 60 } quit := time.After(time.Duration(timeout) * time.Second) tick := time.Tick(2 * time.Second) stop := false for !stop { select { case <-tick: file, _ := filesystem().Open("/var/lib/misc/dnsmasq.leases") data, _ := ioutil.ReadAll(file) log.Print("dnsmasq.leases") log.Print(string(data)) for _, line := range strings.Split(string(data), "\n") { if strings.Index(line, c.name) != -1 { log.Printf("ip in %s", line) c.ip = strings.Split(line, " ")[2] return c.ip } } case <-quit: stop = true default: time.Sleep(1 * time.Second) } } return "" }
func (p *LocalProvisioner) setup(ip, framework string) error { formulasPath, err := config.GetString("local:formulas-path") if err != nil { return err } log.Printf("Creating hooks dir for %s", ip) cmd := exec.Command("ssh", "-q", "-o", "StrictHostKeyChecking no", "-l", "ubuntu", ip, "sudo mkdir -p /var/lib/tsuru/hooks") err = cmd.Run() if err != nil { log.Printf("error on creating hooks dir for %s", ip) log.Print(err) return err } log.Printf("Permissons on hooks dir for %s", ip) cmd = exec.Command("ssh", "-q", "-o", "StrictHostKeyChecking no", "-l", "ubuntu", ip, "sudo chown -R ubuntu /var/lib/tsuru/hooks") err = cmd.Run() if err != nil { log.Printf("error on permissions for %s", ip) log.Print(err) return err } log.Printf("coping hooks to %s", ip) cmd = exec.Command("scp", "-q", "-o", "StrictHostKeyChecking no", "-r", formulasPath+"/"+framework+"/hooks", "ubuntu@"+ip+":/var/lib/tsuru") output, err := cmd.CombinedOutput() if err != nil { log.Printf("error on execute scp with the args: %#v", cmd.Args) log.Print(string(output)) log.Print(err) return err } return nil }
func (c *Client) Destroy(instance *ServiceInstance) error { log.Print("Attempting to call destroy of service instance " + instance.Name + " at " + instance.ServiceName + " api") resp, err := c.issueRequest("/resources/"+instance.Name, "DELETE", nil) if err == nil && resp.StatusCode > 299 { msg := "Failed to destroy the instance " + instance.Name + ": " + c.buildErrorMessage(err, resp) log.Print(msg) return &errors.HTTP{Code: http.StatusInternalServerError, Message: msg} } return err }
func (c *Client) Unbind(instance *ServiceInstance, app bind.App) (err error) { log.Print("Attempting to call unbind of service instance " + instance.Name + " and app " + app.GetName() + " at " + instance.ServiceName + " api") var resp *http.Response url := "/resources/" + instance.Name + "/hostname/" + app.GetUnits()[0].GetIp() if resp, err = c.issueRequest(url, "DELETE", nil); err == nil && resp.StatusCode > 299 { msg := "Failed to unbind instance " + instance.Name + " from the app " + app.GetName() + ": " + c.buildErrorMessage(err, resp) log.Print(msg) err = &errors.Http{Code: http.StatusInternalServerError, Message: msg} } return }
func (c *Client) Unbind(instance *ServiceInstance, unit bind.Unit) error { log.Print("Attempting to call unbind of service instance " + instance.Name + " and unit " + unit.GetIp() + " at " + instance.ServiceName + " api") var resp *http.Response url := "/resources/" + instance.Name + "/hostname/" + unit.GetIp() resp, err := c.issueRequest(url, "DELETE", nil) if err == nil && resp.StatusCode > 299 { msg := "Failed to unbind instance " + instance.Name + " from the unit " + unit.GetIp() + ": " + c.buildErrorMessage(err, resp) log.Print(msg) return &errors.HTTP{Code: http.StatusInternalServerError, Message: msg} } return err }
func (c *Client) Create(instance *ServiceInstance) error { var err error log.Print("Attempting to call creation of service instance " + instance.Name + " at " + instance.ServiceName + " api") var resp *http.Response params := map[string][]string{ "name": {instance.Name}, } if resp, err = c.issueRequest("/resources", "POST", params); err == nil && resp.StatusCode < 300 { return nil } msg := "Failed to create the instance " + instance.Name + ": " + c.buildErrorMessage(err, resp) log.Print(msg) return &errors.HTTP{Code: http.StatusInternalServerError, Message: msg} }
// handle is the function called by the queue handler on each message. func handle(msg *queue.Message) { switch msg.Action { case RegenerateApprcAndStart: fallthrough case regenerateApprc: if len(msg.Args) < 1 { log.Printf("Error handling %q: this action requires at least 1 argument.", msg.Action) msg.Delete() return } app, err := ensureAppIsStarted(msg) if err != nil { log.Print(err) return } msg.Delete() app.SerializeEnvVars() fallthrough case startApp: if msg.Action == regenerateApprc { break } if len(msg.Args) < 1 { log.Printf("Error handling %q: this action requires at least 1 argument.", msg.Action) } app, err := ensureAppIsStarted(msg) if err != nil { log.Print(err) return } err = app.Restart(ioutil.Discard) if err != nil { log.Printf("Error handling %q. App failed to start:\n%s.", msg.Action, err) return } msg.Delete() case BindService: err := bindUnit(msg) if err != nil { log.Print(err) return } msg.Delete() default: log.Printf("Error handling %q: invalid action.", msg.Action) msg.Delete() } }
// runCmd executes commands and log the given stdout and stderror. func runCmd(cmd string, args ...string) error { command := exec.Command(cmd, args...) out, err := command.CombinedOutput() log.Printf("running the cmd: %s with the args: %s", cmd, args) log.Print(string(out)) return err }
// ip returns the ip for the container. func (c *container) ip() (string, error) { docker, err := config.GetString("docker:binary") if err != nil { return "", err } log.Printf("Getting ipaddress to instance %s", c.id) instanceJson, err := runCmd(docker, "inspect", c.id) if err != nil { msg := "error(%s) trying to inspect docker instance(%s) to get ipaddress" log.Printf(msg, err) return "", errors.New(msg) } var result map[string]interface{} if err := json.Unmarshal([]byte(instanceJson), &result); err != nil { msg := "error(%s) parsing json from docker when trying to get ipaddress" log.Printf(msg, err) return "", errors.New(msg) } if ns, ok := result["NetworkSettings"]; !ok || ns == nil { msg := "Error when getting container information. NetworkSettings is missing." log.Printf(msg) return "", errors.New(msg) } networkSettings := result["NetworkSettings"].(map[string]interface{}) instanceIp := networkSettings["IpAddress"].(string) if instanceIp == "" { msg := "error: Can't get ipaddress..." log.Print(msg) return "", errors.New(msg) } log.Printf("Instance IpAddress: %s", instanceIp) return instanceIp, nil }
func (h elbInstanceHealer) Heal() error { apps := h.getUnhealthyApps() if len(apps) == 0 { log.Print("No app is down.") return nil } names := make([]string, len(apps)) i := 0 for n := range apps { names[i] = n i++ } if instances, err := h.checkInstances(names); err == nil && len(instances) > 0 { for _, instance := range instances { a := apps[instance.lb] if err := a.RemoveUnit(instance.id); err != nil { return err } if err := a.AddUnits(1); err != nil { return err } } } return nil }
// runCmd executes commands and log the given stdout and stderror. func runCmd(cmd string, args ...string) error { output := bytes.Buffer{} err := executor().Execute(cmd, args, nil, &output, &output) log.Printf("running the cmd: %s with the args: %s", cmd, args) log.Print(output.String()) return err }
func (fn AuthorizationRequiredHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { setVersionHeaders(w) defer func() { if r.Body != nil { r.Body.Close() } }() fw := FlushingWriter{w, false} token := r.Header.Get("Authorization") if token == "" { http.Error(&fw, "You must provide the Authorization header", http.StatusUnauthorized) } else if user, err := auth.CheckToken(token); err != nil { http.Error(&fw, "Invalid token", http.StatusUnauthorized) } else if err = fn(&fw, r, user); err != nil { code := http.StatusInternalServerError if e, ok := err.(*errors.Http); ok { code = e.Code } if fw.wrote { fmt.Fprintln(&fw, err) } else { http.Error(&fw, err.Error(), code) } log.Print(err) } }
func update(units []provision.Unit) { log.Print("updating status from provisioner") var l AppList for _, unit := range units { a, index := l.Search(unit.AppName) if index > -1 { err := a.Get() if err != nil { log.Printf("collector: app %q not found. Skipping.\n", unit.AppName) continue } } u := app.Unit{} u.Name = unit.Name u.Type = unit.Type u.Machine = unit.Machine u.InstanceId = unit.InstanceId u.Ip = unit.Ip u.State = string(unit.Status) a.State = string(unit.Status) a.Ip = unit.Ip a.AddUnit(&u) if index > -1 { l.Add(a, index) } } for _, a := range l { db.Session.Apps().Update(bson.M{"name": a.Name}, a) } }
func (fn adminRequiredHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { setVersionHeaders(w) defer func() { if r.Body != nil { r.Body.Close() } }() fw := io.FlushingWriter{ResponseWriter: w} header := r.Header.Get("Authorization") if header == "" { http.Error(&fw, "You must provide the Authorization header", http.StatusUnauthorized) } else if t, err := auth.GetToken(header); err != nil { http.Error(&fw, "Invalid token", http.StatusUnauthorized) } else if user, err := t.User(); err != nil || !user.IsAdmin() { http.Error(&fw, "Forbidden", http.StatusForbidden) } else if err = fn(&fw, r, t); err != nil { code := http.StatusInternalServerError if e, ok := err.(*errors.HTTP); ok { code = e.Code } if fw.Wrote() { fmt.Fprintln(&fw, err) } else { http.Error(&fw, err.Error(), code) } log.Print(err) } }
func update(units []provision.Unit) { log.Print("updating status from provisioner") var l AppList for _, unit := range units { a, index := l.Search(unit.AppName) if index > -1 { err := a.Get() if err != nil { log.Printf("collector: app %q not found. Skipping.\n", unit.AppName) continue } } u := app.Unit{} u.Name = unit.Name u.Type = unit.Type u.Machine = unit.Machine u.InstanceId = unit.InstanceId u.Ip = unit.Ip u.State = string(unit.Status) a.AddUnit(&u) if index > -1 { l.Add(a, index) } } conn, err := db.Conn() if err != nil { log.Printf("collector failed to connect to the database: %s", err) return } defer conn.Close() for _, a := range l { a.Ip, _ = app.Provisioner.Addr(a) conn.Apps().Update(bson.M{"name": a.Name}, a) } }
// ServerURL returns the URL to Gandalf API. func ServerURL() string { server, err := config.GetString("git:api-server") if err != nil { log.Print("git:api-server config not found") panic(err) } return server }
// joins the protocol, server and port together and returns. // // This functions makes uses of three configurations: // - git:host // - git:protocol // - git:port (optional) // // If some of the required configuration is not found, this function panics. func GitServerUri() string { server, err := config.GetString("git:host") if err != nil { log.Print("git:host config not found") panic(err) } protocol, err := config.GetString("git:protocol") if err != nil { log.Print("git:protocol config not found") panic(err) } uri := fmt.Sprintf("%s://%s", protocol, server) if port, err := config.Get("git:port"); err == nil { uri = fmt.Sprintf("%s:%d", uri, port) } return uri }
// ReadOnlyURL returns the url for communication with git-daemon. func ReadOnlyURL(app string) string { roHost, err := config.GetString("git:ro-host") if err != nil { log.Print("git:ro-host config not found") panic(err) } return fmt.Sprintf("git://%s/%s.git", roHost, app) }
// ReadWriteURL returns the SSH URL, for writing and reading operations. func ReadWriteURL(app string) string { publicHost, err := config.GetString("git:rw-host") if err != nil { log.Print("git:rw-host config not found") panic(err) } return fmt.Sprintf("git@%s:%s.git", publicHost, app) }
func (c *Client) Bind(instance *ServiceInstance, app bind.App) (envVars map[string]string, err error) { log.Print("Attempting to call bind of service instance " + instance.Name + " and app " + app.GetName() + " at " + instance.ServiceName + " api") var resp *http.Response params := map[string][]string{ "hostname": {app.GetUnits()[0].GetIp()}, } if resp, err = c.issueRequest("/resources/"+instance.Name, "POST", params); err == nil && resp.StatusCode < 300 { return c.jsonFromResponse(resp) } else if resp.StatusCode == http.StatusPreconditionFailed { err = &errors.Http{Code: resp.StatusCode, Message: "You cannot bind any app to this service instance because it is not ready yet."} } else { msg := "Failed to bind instance " + instance.Name + " to the app " + app.GetName() + ": " + c.buildErrorMessage(err, resp) log.Print(msg) err = &errors.Http{Code: http.StatusInternalServerError, Message: msg} } return }
// getGitServer returns the git server defined in the tsuru.conf file. // // If git:host configuration is not defined, this function panics. func getGitServer() string { gitServer, err := config.GetString("git:host") if err != nil { log.Print("git:host config not found") panic(err) } return gitServer }
func CreateInstanceHandler(w http.ResponseWriter, r *http.Request, u *auth.User) error { log.Print("Receiving request to create a service instance") b, err := ioutil.ReadAll(r.Body) if err != nil { log.Print("Got error while reading request body:") log.Print(err.Error()) return &errors.Http{Code: http.StatusInternalServerError, Message: err.Error()} } var sJson map[string]string err = json.Unmarshal(b, &sJson) if err != nil { log.Print("Got a problem while unmarshalling request's json:") log.Print(err.Error()) return &errors.Http{Code: http.StatusInternalServerError, Message: err.Error()} } var s service.Service err = validateInstanceForCreation(&s, sJson, u) if err != nil { log.Print("Got error while validation:") log.Print(err.Error()) return err } var teamNames []string teams, err := u.Teams() if err != nil { return err } for _, t := range teams { if s.HasTeam(&t) || !s.IsRestricted { teamNames = append(teamNames, t.Name) } } si := service.ServiceInstance{ Name: sJson["name"], ServiceName: sJson["service_name"], Teams: teamNames, } if err = s.ProductionEndpoint().Create(&si); err != nil { log.Print("Error while calling create action from service api.") log.Print(err.Error()) return err } err = si.Create() if err != nil { return err } fmt.Fprint(w, "success") return nil }
// HealTicker execute the registered healers registered by RegisterHealerTicker. func HealTicker(ticker <-chan time.Time) { log.Print("running heal ticker") var wg sync.WaitGroup for _ = range ticker { healers := getHealers() wg.Add(len(healers)) for name, h := range healers { log.Printf("running verification/heal for %s", name) go func(healer *healer) { err := healer.heal() if err != nil { log.Print(err.Error()) } wg.Done() }(h) } wg.Wait() } }
// ip returns the ip for the container. func (c *container) ip() (string, error) { dockerContainer, err := dockerCluster().InspectContainer(c.ID) if err != nil { return "", err } if dockerContainer.NetworkSettings == nil { msg := "Error when getting container information. NetworkSettings is missing." log.Print(msg) return "", errors.New(msg) } instanceIP := dockerContainer.NetworkSettings.IPAddress if instanceIP == "" { msg := "error: Can't get ipaddress..." log.Print(msg) return "", errors.New(msg) } log.Printf("Instance IpAddress: %s", instanceIP) return instanceIP, nil }
func (c *Client) jsonFromResponse(resp *http.Response, v interface{}) error { log.Print("Parsing response json...") defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("Got error while parsing json: %s", err) return err } return json.Unmarshal(body, &v) }
func (p *LocalProvisioner) install(ip string) error { log.Printf("executing the install hook for %s", ip) cmd := exec.Command("ssh", "-q", "-o", "StrictHostKeyChecking no", "-l", "ubuntu", ip, "sudo /var/lib/tsuru/hooks/install") err := cmd.Run() if err != nil { log.Printf("error on install for %s", ip) log.Print(err) return err } return nil }
func collect(ticker <-chan time.Time) { for _ = range ticker { log.Print("Collecting status from provisioner") units, err := app.Provisioner.CollectStatus() if err != nil { log.Printf("Failed to collect status within the provisioner: %s.", err) continue } update(units) } }