Пример #1
0
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)
	}
}
Пример #2
0
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)
	}
}
Пример #3
0
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}
}
Пример #4
0
// 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 ""
}
Пример #5
0
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
}
Пример #6
0
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
}
Пример #7
0
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
}
Пример #8
0
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
}
Пример #9
0
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}
}
Пример #10
0
// 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()
	}
}
Пример #11
0
// 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
}
Пример #12
0
// 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
}
Пример #13
0
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
}
Пример #14
0
// 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
}
Пример #15
0
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)
	}
}
Пример #16
0
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)
	}
}
Пример #17
0
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)
	}
}
Пример #18
0
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)
	}
}
Пример #19
0
// 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
}
Пример #20
0
//  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
}
Пример #21
0
// 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)
}
Пример #22
0
// 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)
}
Пример #23
0
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
}
Пример #24
0
// 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
}
Пример #25
0
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
}
Пример #26
0
// 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()
	}
}
Пример #27
0
// 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
}
Пример #28
0
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)
}
Пример #29
0
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
}
Пример #30
0
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)
	}
}