示例#1
0
func flatten(imageID string) error {
	config := docker.Config{
		Image:        imageID,
		Cmd:          []string{"/bin/bash"},
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
	}
	_, c, err := dockerCluster().CreateContainer(&config)
	if err != nil {
		return err
	}
	buf := &bytes.Buffer{}
	if err := dockerCluster().ExportContainer(c.ID, buf); err != nil {
		log.Errorf("Flatten: Caugh error while exporting container %s: %s", c.ID, err.Error())
		return err
	}
	out := &bytes.Buffer{}
	opts := dcli.ImportImageOptions{Repository: imageID, Source: "-"}
	if err := dockerCluster().ImportImage(opts, buf, out); err != nil {
		log.Errorf("Flatten: Caugh error while importing image from container %s: %s", c.ID, err.Error())
		return err
	}
	if err := dockerCluster().RemoveContainer(c.ID); err != nil {
		log.Errorf("Flatten: Caugh error while removing container %s: %s", c.ID, err.Error())
	}
	removeFromRegistry(imageID)
	return nil
}
示例#2
0
文件: router.go 项目: rpeterson/tsuru
func (r hipacheRouter) AddRoute(name, address string) error {
	backendName, err := router.Retrieve(name)
	if err != nil {
		return err
	}
	domain, err := config.GetString("hipache:domain")
	if err != nil {
		log.Errorf("error on getting hipache domain in add route for %s - %s", backendName, address)
		return &routeError{"add", err}
	}
	frontend := "frontend:" + backendName + "." + domain
	if err := r.addRoute(frontend, address); err != nil {
		log.Errorf("error on add route for %s - %s", backendName, address)
		return &routeError{"add", err}
	}
	cname, err := r.getCName(backendName)
	if err != nil {
		log.Errorf("error on get cname in add route for %s - %s", backendName, address)
		return err
	}
	if cname == "" {
		return nil
	}
	return r.addRoute("frontend:"+cname, address)
}
示例#3
0
文件: docker.go 项目: pdaniel/tsuru
// replicateImage replicates the given image through all nodes in the cluster.
func replicateImage(name string) error {
	var buf safe.Buffer
	if _, err := config.GetString("docker:registry"); err == nil {
		pushOpts := docker.PushImageOptions{Name: name, OutputStream: &buf}
		for i := 0; i < maxTry; i++ {
			err = dockerCluster().PushImage(pushOpts, docker.AuthConfiguration{})
			if err == nil {
				buf.Reset()
				break
			}
			log.Errorf("[docker] Failed to push image %q (%s): %s", name, err, buf.String())
			buf.Reset()
		}
		if err != nil {
			return err
		}
		pullOpts := docker.PullImageOptions{Repository: name, OutputStream: &buf}
		for i := 0; i < maxTry; i++ {
			err = dockerCluster().PullImage(pullOpts)
			if err == nil {
				break
			}
			buf.Reset()
		}
		if err != nil {
			log.Errorf("[docker] Failed to replicate image %q through nodes (%s): %s", name, err, buf.String())
			return err
		}
	}
	return nil
}
示例#4
0
文件: docker.go 项目: prodigeni/tsuru
func deploy(app provision.App, version string, w io.Writer) (string, error) {
	commands, err := deployCmds(app, version)
	if err != nil {
		return "", err
	}
	imageId := getImage(app)
	actions := []*action.Action{&createContainer, &startContainer, &insertContainer}
	pipeline := action.NewPipeline(actions...)
	err = pipeline.Execute(app, imageId, commands)
	if err != nil {
		log.Errorf("error on execute deploy pipeline for app %s - %s", app.GetName(), err)
		return "", err
	}
	c := pipeline.Result().(container)
	err = c.logs(w)
	if err != nil {
		log.Errorf("error on get logs for container %s - %s", c.ID, err)
		return "", err
	}
	_, err = dockerCluster().WaitContainer(c.ID)
	if err != nil {
		log.Errorf("Process failed for container %q: %s", c.ID, err)
		return "", err
	}
	imageId, err = c.commit()
	if err != nil {
		log.Errorf("error on commit container %s - %s", c.ID, err)
		return "", err
	}
	c.remove()
	return imageId, nil
}
示例#5
0
文件: docker.go 项目: prodigeni/tsuru
// replicateImage replicates the given image through all nodes in the cluster.
func replicateImage(name string) error {
	var buf bytes.Buffer
	if registry, err := config.GetString("docker:registry"); err == nil {
		if !strings.HasPrefix(name, registry) {
			name = registry + "/" + name
		}
		pushOpts := dclient.PushImageOptions{Name: name}
		for i := 0; i < maxTry; i++ {
			err = dockerCluster().PushImage(pushOpts, dclient.AuthConfiguration{}, &buf)
			if err == nil {
				buf.Reset()
				break
			}
			log.Errorf("[docker] Failed to push image %q (%s): %s", name, err, buf.String())
			buf.Reset()
		}
		if err != nil {
			return err
		}
		pullOpts := dclient.PullImageOptions{Repository: name}
		for i := 0; i < maxTry; i++ {
			err = dockerCluster().PullImage(pullOpts, &buf)
			if err == nil {
				break
			}
			buf.Reset()
		}
		if err != nil {
			log.Errorf("[docker] Failed to replicate image %q through nodes (%s): %s", name, err, buf.String())
			return err
		}
	}
	return nil
}
示例#6
0
文件: docker.go 项目: nemx/tsuru
// newContainer creates a new container in Docker and stores it in the database.
func newContainer(app provision.App, imageId string, cmds []string) (container, error) {
	cont := container{
		AppName: app.GetName(),
		Type:    app.GetPlatform(),
	}
	port, err := getPort()
	if err != nil {
		log.Errorf("error on getting port for container %s - %s", cont.AppName, port)
		return container{}, err
	}
	user, _ := config.GetString("docker:ssh:user")
	config := docker.Config{
		Image:        imageId,
		Cmd:          cmds,
		User:         user,
		PortSpecs:    []string{port},
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
	}
	hostID, c, err := dockerCluster().CreateContainer(&config)
	if err != nil {
		log.Errorf("error on creating container in docker %s - %s", cont.AppName, err)
		return container{}, err
	}
	cont.ID = c.ID
	cont.Port = port
	cont.HostAddr = getHostAddr(hostID)
	return cont, nil
}
示例#7
0
func handle(msg *queue.Message) {
	if msg.Action == addUnitToLoadBalancer {
		if len(msg.Args) < 1 {
			log.Errorf("Failed to handle %q: it requires at least one argument.", msg.Action)
			return
		}
		a := qApp{name: msg.Args[0]}
		unitNames := msg.Args[1:]
		sort.Strings(unitNames)
		status, err := (&JujuProvisioner{}).collectStatus()
		if err != nil {
			log.Errorf("Failed to handle %q: juju status failed.\n%s.", msg.Action, err)
			return
		}
		var units []provision.Unit
		for _, u := range status {
			if u.AppName != a.name {
				continue
			}
			n := sort.SearchStrings(unitNames, u.Name)
			if len(unitNames) == 0 ||
				n < len(unitNames) && unitNames[n] == u.Name {
				units = append(units, u)
			}
		}
		if len(units) == 0 {
			log.Errorf("Failed to handle %q: units not found.", msg.Action)
			return
		}
		var noID []string
		var ok []provision.Unit
		for _, u := range units {
			if u.InstanceId == "pending" || u.InstanceId == "" {
				noID = append(noID, u.Name)
			} else {
				ok = append(ok, u)
			}
		}
		if len(noID) == len(units) {
			getQueue(queueName).Put(msg, 0)
		} else {
			router, _ := Router()
			for _, u := range units {
				router.AddRoute(a.GetName(), u.InstanceId)
			}
			if len(noID) > 0 {
				args := []string{a.name}
				args = append(args, noID...)
				msg := queue.Message{
					Action: msg.Action,
					Args:   args,
				}
				getQueue(queueName).Put(&msg, 1e9)
			}
		}
	}
}
示例#8
0
func removeContainer(c *container) error {
	err := c.stop()
	if err != nil {
		log.Errorf("error on stop unit %s - %s", c.ID, err)
	}
	err = c.remove()
	if err != nil {
		log.Errorf("error on remove container %s - %s", c.ID, err)
	}
	return err
}
示例#9
0
// newContainer creates a new container in Docker and stores it in the database.
func newContainer(app provision.App, imageId string, cmds []string) (container, error) {
	contName := containerName()
	cont := container{
		AppName: app.GetName(),
		Type:    app.GetPlatform(),
		Name:    contName,
		Status:  "created",
	}
	coll := collection()
	defer coll.Close()
	if err := coll.Insert(cont); err != nil {
		log.Errorf("error on inserting container into database %s - %s", cont.Name, err)
		return container{}, err
	}
	port, err := getPort()
	if err != nil {
		log.Errorf("error on getting port for container %s - %s", cont.AppName, port)
		return container{}, err
	}
	user, _ := config.GetString("docker:ssh:user")
	exposedPorts := make(map[docker.Port]struct{}, 1)
	p := docker.Port(fmt.Sprintf("%s/tcp", port))
	exposedPorts[p] = struct{}{}
	config := docker.Config{
		Image:        imageId,
		Cmd:          cmds,
		User:         user,
		ExposedPorts: exposedPorts,
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
	}
	opts := dclient.CreateContainerOptions{Name: contName}
	hostID, c, err := dockerCluster().CreateContainer(opts, &config)
	if err == dclient.ErrNoSuchImage {
		var buf bytes.Buffer
		pullOpts := dclient.PullImageOptions{Repository: imageId}
		dockerCluster().PullImage(pullOpts, &buf)
		hostID, c, err = dockerCluster().CreateContainer(opts, &config)
	}
	if err != nil {
		log.Errorf("error on creating container in docker %s - %s", cont.AppName, err)
		return container{}, err
	}
	cont.ID = c.ID
	cont.Port = port
	cont.HostAddr = getHostAddr(hostID)
	err = coll.Update(bson.M{"name": cont.Name}, cont)
	if err != nil {
		log.Errorf("error on updating container into database %s - %s", cont.ID, err)
		return container{}, err
	}
	return cont, nil
}
示例#10
0
文件: user.go 项目: rpeterson/tsuru
func (u *User) sendResetPassword(t *passwordToken) {
	var body bytes.Buffer
	err := resetEmailData.Execute(&body, t)
	if err != nil {
		log.Errorf("Failed to send password token to user %q: %s", u.Email, err)
		return
	}
	err = sendEmail(u.Email, body.Bytes())
	if err != nil {
		log.Errorf("Failed to send password token for user %q: %s", u.Email, err)
	}
}
示例#11
0
func (*dockerProvisioner) Addr(app provision.App) (string, error) {
	r, err := getRouter()
	if err != nil {
		log.Errorf("Failed to get router: %s", err)
		return "", err
	}
	addr, err := r.Addr(app.GetName())
	if err != nil {
		log.Errorf("Failed to obtain app %s address: %s", app.GetName(), err)
		return "", err
	}
	return addr, nil
}
示例#12
0
func injectEnvsAndRestart(a provision.App) {
	time.Sleep(5e9)
	err := a.SerializeEnvVars()
	if err != nil {
		log.Errorf("Failed to serialize env vars: %s.", err)
	}
	var buf bytes.Buffer
	w := app.LogWriter{App: a, Writer: &buf}
	err = a.Restart(&w)
	if err != nil {
		log.Errorf("Failed to restart app %q (%s): %s.", a.GetName(), err, buf.String())
	}
}
示例#13
0
// Creates a new user and write his/her keys into authorized_keys file.
//
// The authorized_keys file belongs to the user running the process.
func New(name string, keys map[string]string) (*User, error) {
	log.Debugf(`Creating user "%s"`, name)
	u := &User{Name: name}
	if v, err := u.isValid(); !v {
		log.Errorf("user.New: %s", err.Error())
		return u, err
	}
	if err := db.Session.User().Insert(&u); err != nil {
		log.Errorf("user.New: %s", err.Error())
		return u, err
	}
	return u, addKeys(keys, u.Name)
}
示例#14
0
文件: auth.go 项目: nemx/tsuru
// removeUser removes the user from the database and from gandalf server
//
// If the user is the only one in a team an error will be returned.
func removeUser(w http.ResponseWriter, r *http.Request, t *auth.Token) error {
	u, err := t.User()
	if err != nil {
		return err
	}
	gURL := repository.ServerURL()
	c := gandalf.Client{Endpoint: gURL}
	alwdApps, err := u.AllowedApps()
	if err != nil {
		return err
	}
	if err := c.RevokeAccess(alwdApps, []string{u.Email}); err != nil {
		log.Errorf("Failed to revoke access in Gandalf: %s", err)
		return fmt.Errorf("Failed to revoke acess from git repositories: %s", err)
	}
	teams, err := u.Teams()
	if err != nil {
		return err
	}
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	for _, team := range teams {
		if len(team.Users) < 2 {
			msg := fmt.Sprintf(`This user is the last member of the team "%s", so it cannot be removed.

Please remove the team, them remove the user.`, team.Name)
			return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
		}
		err = team.RemoveUser(u)
		if err != nil {
			return err
		}
		// this can be done without the loop
		err = conn.Teams().Update(bson.M{"_id": team.Name}, team)
		if err != nil {
			return err
		}
	}
	rec.Log(u.Email, "remove-user")
	if err := c.RemoveUser(u.Email); err != nil {
		log.Errorf("Failed to remove user from gandalf: %s", err)
		return fmt.Errorf("Failed to remove the user from the git server: %s", err)
	}
	quota.Delete(u.Email)
	return conn.Users().Remove(bson.M{"email": u.Email})
}
示例#15
0
func (p *dockerProvisioner) Stop(app provision.App) error {
	containers, err := listAppContainers(app.GetName())
	if err != nil {
		log.Errorf("Got error while getting app containers: %s", err)
		return nil
	}
	for _, c := range containers {
		err := c.stop()
		if err != nil {
			log.Errorf("Failed to stop %q: %s", app.GetName(), err)
			return err
		}
	}
	return nil
}
示例#16
0
func setQueue() {
	var err error
	qfactory, err = queue.Factory()
	if err != nil {
		log.Errorf("Failed to get the queue instance: %s", err)
	}
	_handler, err = qfactory.Handler(handle, queueName)
	if err != nil {
		log.Errorf("Failed to create the queue handler: %s", err)
	}
	_queue, err = qfactory.Get(queueName)
	if err != nil {
		log.Errorf("Failed to get the queue instance: %s", err)
	}
}
示例#17
0
文件: queue.go 项目: nemx/tsuru
// 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.Errorf("Error handling %q: this action requires at least 1 argument.", msg.Action)
			msg.Delete()
			return
		}
		app, err := ensureAppIsStarted(msg)
		if err != nil {
			log.Error(err.Error())
			return
		}
		msg.Delete()
		app.SerializeEnvVars()
		fallthrough
	case startApp:
		if msg.Action == regenerateApprc {
			break
		}
		if len(msg.Args) < 1 {
			log.Errorf("Error handling %q: this action requires at least 1 argument.", msg.Action)
		}
		app, err := ensureAppIsStarted(msg)
		if err != nil {
			log.Error(err.Error())
			return
		}
		err = app.Restart(ioutil.Discard)
		if err != nil {
			log.Errorf("Error handling %q. App failed to start:\n%s.", msg.Action, err)
			return
		}
		msg.Delete()
	case BindService:
		err := bindUnit(msg)
		if err != nil {
			log.Error(err.Error())
			return
		}
		msg.Delete()
	default:
		log.Errorf("Error handling %q: invalid action.", msg.Action)
		msg.Delete()
	}
}
示例#18
0
文件: user.go 项目: rpeterson/tsuru
func (u *User) sendNewPassword(password string) {
	m := map[string]string{
		"password": password,
		"email":    u.Email,
	}
	var body bytes.Buffer
	err := passwordResetConfirm.Execute(&body, m)
	if err != nil {
		log.Errorf("Failed to send new password to user %q: %s", u.Email, err)
		return
	}
	err = sendEmail(u.Email, body.Bytes())
	if err != nil {
		log.Errorf("Failed to send new password to user %q: %s", u.Email, err)
	}
}
示例#19
0
func (p *dockerProvisioner) Destroy(app provision.App) error {
	containers, _ := listAppContainers(app.GetName())
	go func(c []container) {
		var containersGroup sync.WaitGroup
		containersGroup.Add(len(containers))
		for _, c := range containers {
			go func(c container) {
				defer containersGroup.Done()
				err := removeContainer(&c)
				if err != nil {
					log.Error(err.Error())
				}
			}(c)
		}
		containersGroup.Wait()
		err := removeImage(assembleImageName(app.GetName()))
		if err != nil {
			log.Error(err.Error())
		}
	}(containers)
	r, err := getRouter()
	if err != nil {
		log.Errorf("Failed to get router: %s", err)
		return err
	}
	return r.RemoveBackend(app.GetName())
}
示例#20
0
文件: collector.go 项目: nemx/tsuru
func collectUnit(container container, units chan<- provision.Unit, wg *sync.WaitGroup) {
	defer wg.Done()
	unit := provision.Unit{
		Name:    container.ID,
		AppName: container.AppName,
		Type:    container.Type,
	}
	if container.Status == "error" {
		unit.Status = provision.StatusDown
		units <- unit
		return
	}
	if container.Status == "running" {
		unit.Ip = container.HostAddr
		if ip, hostPort, err := container.networkInfo(); err == nil &&
			(hostPort != container.HostPort || ip != container.IP) {
			err = fixContainer(&container, ip, hostPort)
			if err != nil {
				log.Errorf("error on fix container hostport for [container %s]", container.ID)
				return
			}
		}
		addr := strings.Replace(container.getAddress(), "http://", "", 1)
		conn, err := net.Dial("tcp", addr)
		if err != nil {
			unit.Status = provision.StatusUnreachable
		} else {
			conn.Close()
			unit.Status = provision.StatusStarted
		}
		log.Debugf("collected data for [container %s] - [app %s]", container.ID, container.AppName)
		units <- unit
	}
}
示例#21
0
文件: docker.go 项目: prodigeni/tsuru
// stop stops the container.
func (c *container) stop() error {
	err := dockerCluster().StopContainer(c.ID, 10)
	if err != nil {
		log.Errorf("error on stop container %s: %s", c.ID, err)
	}
	return err
}
示例#22
0
// bindUnit handles the bind-service message, binding a unit to all service
// instances bound to the app.
func bindUnit(msg *queue.Message) error {
	app, err := GetByName(msg.Args[0])
	if err != nil {
		return fmt.Errorf("Error handling %q: app %q does not exist.", msg.Action, app.Name)
	}
	conn, err := db.Conn()
	if err != nil {
		return fmt.Errorf("Error handling %q: %s", msg.Action, err)
	}
	defer conn.Close()
	units := getUnits(app, msg.Args[1:])
	if len(units) == 0 {
		return errors.New("Unknown unit in the message.")
	}
	unit := units[0]
	var instances []service.ServiceInstance
	q := bson.M{"apps": bson.M{"$in": []string{app.Name}}}
	err = conn.ServiceInstances().Find(q).All(&instances)
	if err != nil {
		return err
	}
	for _, instance := range instances {
		_, err = instance.BindUnit(app, &unit)
		if err != nil {
			log.Errorf("Error binding the unit %s with the service instance %s: %s", unit.Name, instance.Name, err)
		}
	}
	return nil
}
示例#23
0
文件: team.go 项目: nemx/tsuru
func CheckUserAccess(teamNames []string, u *User) bool {
	q := bson.M{"_id": bson.M{"$in": teamNames}}
	var teams []Team
	conn, err := db.Conn()
	if err != nil {
		log.Errorf("Failed to connect to the database: %s", err)
		return false
	}
	defer conn.Close()
	conn.Teams().Find(q).All(&teams)
	var wg sync.WaitGroup
	found := make(chan bool, len(teams)+1)
	for _, team := range teams {
		wg.Add(1)
		go func(t Team) {
			if t.ContainsUser(u) {
				found <- true
			}
			wg.Done()
		}(team)
	}
	go func() {
		wg.Wait()
		found <- false
	}()
	return <-found
}
示例#24
0
文件: provisioner.go 项目: nemx/tsuru
func (p *JujuProvisioner) Deploy(a provision.App, version string, w io.Writer) error {
	var buf bytes.Buffer
	setOption := []string{"set", a.GetName(), "app-version=" + version}
	if err := runCmd(true, &buf, &buf, setOption...); err != nil {
		log.Errorf("juju: Failed to set app-version. Error: %s.\nCommand output: %s", err, &buf)
	}
	return deploy.Git(p, a, version, w)
}
示例#25
0
文件: app.go 项目: nemx/tsuru
// Restart runs the restart hook for the app, writing its output to w.
func (app *App) Restart(w io.Writer) error {
	err := app.hookRunner().Restart(app, w, "before")
	if err != nil {
		return err
	}
	err = log.Write(w, []byte("\n ---> Restarting your app\n"))
	if err != nil {
		log.Errorf("[restart] error on write app log for the app %s - %s", app.Name, err)
		return err
	}
	err = Provisioner.Restart(app)
	if err != nil {
		log.Errorf("[restart] error on restart the app %s - %s", app.Name, err)
		return err
	}
	return app.hookRunner().Restart(app, w, "after")
}
示例#26
0
func (h ContainerHealer) Heal() error {
	containers, err := h.collectContainers()
	if err != nil {
		return err
	}
	unhealthy := h.unhealthyRunningContainers(containers)
	for _, c := range unhealthy {
		log.Debugf("Attempting to heal container %s", c.ID)
		if err := dockerCluster().StopContainer(c.ID, 10); err != nil {
			log.Errorf("Caught error while stopping container %s for healing: %s", c.ID, err.Error())
			continue
		}
		if err := dockerCluster().StartContainer(c.ID, nil); err != nil {
			log.Errorf("Caught error while starting container %s for healing: %s", c.ID, err.Error())
		}
	}
	return nil
}
示例#27
0
// ReadOnlyURL returns the url for communication with git-daemon.
func ReadOnlyURL(app string) string {
	c := gandalf.Client{Endpoint: ServerURL()}
	repository, err := c.GetRepository(app)
	if err != nil {
		log.Errorf("Caught error while retrieving repository: %s", err.Error())
		return ""
	}
	return repository.GitURL
}
示例#28
0
文件: endpoint.go 项目: nemx/tsuru
func (c *Client) jsonFromResponse(resp *http.Response, v interface{}) error {
	log.Debug("Parsing response json...")
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Errorf("Got error while parsing json: %s", err)
		return err
	}
	return json.Unmarshal(body, &v)
}
示例#29
0
文件: router.go 项目: rpeterson/tsuru
func (hipacheRouter) addRoute(name, address string) error {
	conn := connect()
	defer conn.Close()
	_, err := conn.Do("RPUSH", name, address)
	if err != nil {
		log.Errorf("error on store in redis in add route for %s - %s", name, address)
		return &routeError{"add", err}
	}
	return nil
}
示例#30
0
文件: app.go 项目: nemx/tsuru
// GetTeams returns a slice of teams that have access to the app.
func (app *App) GetTeams() []auth.Team {
	var teams []auth.Team
	conn, err := db.Conn()
	if err != nil {
		log.Errorf("Failed to connect to the database: %s", err)
		return nil
	}
	defer conn.Close()
	conn.Teams().Find(bson.M{"_id": bson.M{"$in": app.Teams}}).All(&teams)
	return teams
}