Exemple #1
0
// LastLogs returns a list of the last `lines` log of the app, matching the
// fields in the log instance received as an example.
func (app *App) LastLogs(lines int, filterLog Applog) ([]Applog, error) {
	logsProvisioner, ok := Provisioner.(provision.OptionalLogsProvisioner)
	if ok {
		enabled, doc, err := logsProvisioner.LogsEnabled(app)
		if err != nil {
			return nil, err
		}
		if !enabled {
			return nil, stderr.New(doc)
		}
	}
	conn, err := db.LogConn()
	if err != nil {
		return nil, err
	}
	defer conn.Close()
	logs := []Applog{}
	q := bson.M{}
	if filterLog.Source != "" {
		q["source"] = filterLog.Source
	}
	if filterLog.Unit != "" {
		q["unit"] = filterLog.Unit
	}
	err = conn.Logs(app.Name).Find(q).Sort("-$natural").Limit(lines).All(&logs)
	if err != nil {
		return nil, err
	}
	l := len(logs)
	for i := 0; i < l/2; i++ {
		logs[i], logs[l-1-i] = logs[l-1-i], logs[i]
	}
	return logs, nil
}
Exemple #2
0
func (d *appLogDispatcher) runFlusher() {
	defer close(d.errCh)
	t := time.NewTimer(bulkMaxWaitTime)
	bulkBuffer := make([]interface{}, 0, 100)
	conn, err := db.LogConn()
	if err != nil {
		d.errCh <- err
		return
	}
	defer conn.Close()
	coll := conn.Logs(d.appName)
	for {
		var flush bool
		select {
		case <-d.done:
			return
		case msg := <-d.toFlush:
			bulkBuffer = append(bulkBuffer, msg)
			flush = len(bulkBuffer) == cap(bulkBuffer)
			if !flush {
				t.Reset(bulkMaxWaitTime)
			}
		case <-t.C:
			flush = len(bulkBuffer) > 0
		}
		if flush {
			err := coll.Insert(bulkBuffer...)
			if err != nil {
				d.errCh <- err
				return
			}
			bulkBuffer = bulkBuffer[:0]
		}
	}
}
Exemple #3
0
func LogReceiver() (chan<- *Applog, <-chan error) {
	ch := make(chan *Applog)
	errCh := make(chan error)
	go func() {
		collMap := map[string]*storage.Collection{}
		messages := make([]interface{}, 1)
		for msg := range ch {
			messages[0] = msg
			notify(msg.AppName, messages)
			coll := collMap[msg.AppName]
			if coll == nil {
				conn, err := db.LogConn()
				if err != nil {
					errCh <- err
					break
				}
				coll = conn.Logs(msg.AppName)
				collMap[msg.AppName] = coll
			}
			err := coll.Insert(msg)
			if err != nil {
				errCh <- err
				break
			}
		}
		for _, coll := range collMap {
			coll.Close()
		}
		close(errCh)
	}()
	return ch, errCh
}
Exemple #4
0
// Log adds a log message to the app. Specifying a good source is good so the
// user can filter where the message come from.
func (app *App) Log(message, source, unit string) error {
	messages := strings.Split(message, "\n")
	logs := make([]interface{}, 0, len(messages))
	for _, msg := range messages {
		if msg != "" {
			l := Applog{
				Date:    time.Now().In(time.UTC),
				Message: msg,
				Source:  source,
				AppName: app.Name,
				Unit:    unit,
			}
			logs = append(logs, l)
		}
	}
	if len(logs) > 0 {
		notify(app.Name, logs)
		conn, err := db.LogConn()
		if err != nil {
			return err
		}
		defer conn.Close()
		return conn.Logs(app.Name).Insert(logs...)
	}
	return nil
}
Exemple #5
0
func (s *S) SetUpTest(c *check.C) {
	routertest.FakeRouter.Reset()
	repositorytest.Reset()
	var err error
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	dbtest.ClearAllCollections(s.conn.Apps().Database)
	s.logConn, err = db.LogConn()
	c.Assert(err, check.IsNil)
	s.createUserAndTeam(c)
	s.provisioner = provisiontest.NewFakeProvisioner()
	app.Provisioner = s.provisioner
	app.AuthScheme = nativeScheme
	p := app.Platform{Name: "zend"}
	s.conn.Platforms().Insert(p)
	s.Pool = "test1"
	opts := provision.AddPoolOptions{Name: "test1", Default: true}
	err = provision.AddPool(opts)
	c.Assert(err, check.IsNil)
	repository.Manager().CreateUser(s.user.Email)
	repository.Manager().CreateUser(s.adminuser.Email)
	factory, err := queue.Factory()
	c.Assert(err, check.IsNil)
	factory.Reset()
}
Exemple #6
0
func (s *LogSuite) SetUpTest(c *check.C) {
	repositorytest.Reset()
	var err error
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	dbtest.ClearAllCollections(s.conn.Apps().Database)
	s.logConn, err = db.LogConn()
	c.Assert(err, check.IsNil)
	s.createUserAndTeam(c)
}
Exemple #7
0
func (s *LogSuite) TearDownSuite(c *check.C) {
	conn, err := db.Conn()
	c.Assert(err, check.IsNil)
	defer conn.Close()
	conn.Apps().Database.DropDatabase()
	logConn, err := db.LogConn()
	c.Assert(err, check.IsNil)
	defer logConn.Close()
	logConn.Logs("myapp").Database.DropDatabase()
}
Exemple #8
0
func (s *DeploySuite) SetUpSuite(c *check.C) {
	config.Set("database:url", "127.0.0.1:27017")
	config.Set("database:name", "tsuru_deploy_api_tests")
	config.Set("auth:hash-cost", 4)
	config.Set("repo-manager", "fake")
	var err error
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	s.logConn, err = db.LogConn()
	c.Assert(err, check.IsNil)
}
Exemple #9
0
func (s *EventSuite) SetUpSuite(c *check.C) {
	err := config.ReadConfigFile("testdata/config.yaml")
	c.Assert(err, check.IsNil)
	config.Set("database:url", "127.0.0.1:27017")
	config.Set("database:name", "tsuru_events_api_tests")
	config.Set("auth:hash-cost", 4)
	config.Set("repo-manager", "fake")
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	s.logConn, err = db.LogConn()
	c.Assert(err, check.IsNil)
}
Exemple #10
0
// Delete deletes an app.
//
// Delete an app is a process composed of three steps:
//
//       1. Destroy the app unit
//       2. Unbind all service instances from the app
//       3. Remove the app from the database
func Delete(app *App) error {
	appName := app.Name
	wg := asyncDestroyAppProvisioner(app)
	wg.Add(1)
	defer wg.Done()
	go func() {
		defer ReleaseApplicationLock(appName)
		wg.Wait()
		logConn, err := db.LogConn()
		if err != nil {
			log.Errorf("Unable to delete app %s from db: %s", appName, err.Error())
		}
		defer logConn.Close()
		conn, err := db.Conn()
		if err != nil {
			log.Errorf("Unable to delete app %s from db: %s", appName, err.Error())
		}
		defer conn.Close()
		err = logConn.Logs(appName).DropCollection()
		if err != nil {
			log.Errorf("Ignored error dropping logs collection for app %s: %s", appName, err.Error())
		}
		err = conn.Apps().Remove(bson.M{"name": appName})
		if err != nil {
			log.Errorf("Error trying to destroy app %s from db: %s", appName, err.Error())
		}
		err = markDeploysAsRemoved(appName)
		if err != nil {
			log.Errorf("Error trying to mark old deploys as removed for app %s: %s", appName, err.Error())
		}
	}()
	err := repository.Manager().RemoveRepository(appName)
	if err != nil {
		log.Errorf("failed to remove app %q from repository manager: %s", appName, err)
	}
	token := app.Env["TSURU_APP_TOKEN"].Value
	err = AuthScheme.Logout(token)
	if err != nil {
		log.Errorf("Unable to remove app token in destroy: %s", err.Error())
	}
	owner, err := auth.GetUserByEmail(app.Owner)
	if err != nil {
		log.Errorf("Unable to get app owner in destroy: %s", err.Error())
	} else {
		err = auth.ReleaseApp(owner)
		if err != nil {
			log.Errorf("Unable to release app quota: %s", err.Error())
		}
	}
	return nil
}
Exemple #11
0
func (s *DeploySuite) SetUpSuite(c *check.C) {
	config.Set("database:url", "127.0.0.1:27017")
	config.Set("database:name", "tsuru_deploy_api_tests")
	config.Set("aut:hash-cost", 4)
	config.Set("admin-team", "tsuruteam")
	config.Set("repo-manager", "fake")
	var err error
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	s.logConn, err = db.LogConn()
	c.Assert(err, check.IsNil)
	s.provisioner = provisiontest.NewFakeProvisioner()
	app.Provisioner = s.provisioner
}
Exemple #12
0
func (s *S) SetUpSuite(c *check.C) {
	err := config.ReadConfigFile("testdata/config.yaml")
	c.Assert(err, check.IsNil)
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	s.logConn, err = db.LogConn()
	c.Assert(err, check.IsNil)
	s.provisioner = provisiontest.NewFakeProvisioner()
	Provisioner = s.provisioner
	AuthScheme = nativeScheme
	data, err := json.Marshal(AppLock{})
	c.Assert(err, check.IsNil)
	err = json.Unmarshal(data, &s.zeroLock)
	c.Assert(err, check.IsNil)
}
Exemple #13
0
func (s *S) SetUpSuite(c *check.C) {
	err := config.ReadConfigFile("testdata/config.yaml")
	c.Assert(err, check.IsNil)
	config.Set("queue:mongo-url", "127.0.0.1:27017")
	config.Set("queue:mongo-database", "queue_app_pkg_tests")
	config.Set("queue:mongo-polling-interval", 0.01)
	config.Set("docker:registry", "registry.somewhere")
	s.conn, err = db.Conn()
	c.Assert(err, check.IsNil)
	s.logConn, err = db.LogConn()
	c.Assert(err, check.IsNil)
	s.provisioner = provisiontest.ProvisionerInstance
	provision.DefaultProvisioner = "fake"
	AuthScheme = nativeScheme
	data, err := json.Marshal(AppLock{})
	c.Assert(err, check.IsNil)
	err = json.Unmarshal(data, &s.zeroLock)
	c.Assert(err, check.IsNil)
	LogPubSubQueuePrefix = "pubsub:app-test:"
}
Exemple #14
0
// LogRemove removes the app log.
func LogRemove(a *App) error {
	conn, err := db.LogConn()
	if err != nil {
		return err
	}
	defer conn.Close()
	if a != nil {
		return conn.Logs(a.Name).DropCollection()
	}
	colls, err := conn.LogsCollections()
	if err != nil {
		return err
	}
	for _, coll := range colls {
		err = coll.DropCollection()
		if err != nil {
			log.Errorf("Error trying to drop collection %s", coll.Name)
		}
	}
	return nil
}
Exemple #15
0
func (d *appLogDispatcher) runFlusher() {
	defer close(d.errCh)
	t := time.NewTimer(bulkMaxWaitTime)
	pos := 0
	sz := 200
	bulkBuffer := make([]interface{}, sz)
	for {
		var flush bool
		select {
		case <-d.done:
			return
		case msg := <-d.toFlush:
			bulkBuffer[pos] = msg
			pos++
			flush = sz == pos
			if flush {
				t.Stop()
			} else {
				t.Reset(bulkMaxWaitTime)
			}
		case <-t.C:
			flush = pos > 0
		}
		if flush {
			conn, err := db.LogConn()
			if err != nil {
				d.errCh <- err
				return
			}
			coll := conn.Logs(d.appName)
			err = coll.Insert(bulkBuffer[:pos]...)
			coll.Close()
			if err != nil {
				d.errCh <- err
				return
			}
			pos = 0
		}
	}
}
Exemple #16
0
func (d *appLogDispatcher) runFlusher() {
	t := time.NewTimer(bulkMaxWaitTime)
	pos := 0
	sz := 200
	bulkBuffer := make([]interface{}, sz)
	for {
		var flush bool
		select {
		case <-d.done:
			return
		case msg := <-d.toFlush:
			if pos == sz {
				flush = true
				break
			}
			bulkBuffer[pos] = msg
			pos++
			flush = sz == pos
		case <-t.C:
			flush = pos > 0
			t.Reset(bulkMaxWaitTime)
		}
		if flush {
			conn, err := db.LogConn()
			if err != nil {
				log.Errorf("[log flusher] unable to connect to mongodb: %s", err)
				continue
			}
			coll := conn.Logs(d.appName)
			err = coll.Insert(bulkBuffer[:pos]...)
			coll.Close()
			if err != nil {
				log.Errorf("[log flusher] unable to insert logs: %s", err)
				continue
			}
			pos = 0
		}
	}
}
Exemple #17
0
// LastLogs returns a list of the last `lines` log of the app, matching the
// fields in the log instance received as an example.
func (app *App) LastLogs(lines int, filterLog Applog) ([]Applog, error) {
	conn, err := db.LogConn()
	if err != nil {
		return nil, err
	}
	defer conn.Close()
	logs := []Applog{}
	q := bson.M{}
	if filterLog.Source != "" {
		q["source"] = filterLog.Source
	}
	if filterLog.Unit != "" {
		q["unit"] = filterLog.Unit
	}
	err = conn.Logs(app.Name).Find(q).Sort("-$natural").Limit(lines).All(&logs)
	if err != nil {
		return nil, err
	}
	l := len(logs)
	for i := 0; i < l/2; i++ {
		logs[i], logs[l-1-i] = logs[l-1-i], logs[i]
	}
	return logs, nil
}
Exemple #18
0
// Delete deletes an app.
func Delete(app *App, w io.Writer) error {
	isSwapped, swappedWith, err := router.IsSwapped(app.GetName())
	if err != nil {
		return fmt.Errorf("unable to check if app is swapped: %s", err)
	}
	if isSwapped {
		return fmt.Errorf("application is swapped with %q, cannot remove it", swappedWith)
	}
	appName := app.Name
	if w == nil {
		w = ioutil.Discard
	}
	fmt.Fprintf(w, "---- Removing application %q...\n", appName)
	var hasErrors bool
	defer func() {
		var problems string
		if hasErrors {
			problems = " Some errors occurred during removal."
		}
		fmt.Fprintf(w, "---- Done removing application.%s\n", problems)
	}()
	logErr := func(msg string, err error) {
		msg = fmt.Sprintf("%s: %s", msg, err)
		fmt.Fprintf(w, "%s\n", msg)
		log.Errorf("[delete-app: %s] %s", appName, msg)
		hasErrors = true
	}
	err = Provisioner.Destroy(app)
	if err != nil {
		logErr("Unable to destroy app in provisioner", err)
	}
	err = app.unbind()
	if err != nil {
		logErr("Unable to unbind app", err)
	}
	err = repository.Manager().RemoveRepository(appName)
	if err != nil {
		logErr("Unable to remove app from repository manager", err)
	}
	token := app.Env["TSURU_APP_TOKEN"].Value
	err = AuthScheme.AppLogout(token)
	if err != nil {
		logErr("Unable to remove app token in destroy", err)
	}
	owner, err := auth.GetUserByEmail(app.Owner)
	if err == nil {
		err = auth.ReleaseApp(owner)
	}
	if err != nil {
		logErr("Unable to release app quota", err)
	}
	logConn, err := db.LogConn()
	if err == nil {
		defer logConn.Close()
		err = logConn.Logs(appName).DropCollection()
	}
	if err != nil {
		logErr("Unable to remove logs collection", err)
	}
	conn, err := db.Conn()
	if err == nil {
		defer conn.Close()
		err = conn.Apps().Remove(bson.M{"name": appName})
	}
	if err != nil {
		logErr("Unable to remove app from db", err)
	}
	err = markDeploysAsRemoved(appName)
	if err != nil {
		logErr("Unable to mark old deploys as removed", err)
	}
	return nil
}