router/migrate.go
func MigrateUniqueCollection() error {
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	coll := conn.Collection("routers")
	appColl := conn.Apps()
	var appNames []string
	err = appColl.Find(nil).Distinct("name", &appNames)
	if err != nil {
		return err
	}
	_, err = coll.RemoveAll(bson.M{"app": bson.M{"$nin": appNames}, "router": bson.M{"$nin": appNames}})
	if err != nil {
		return err
	}
	byAppMap, err := allDupEntries(coll)
	if err != nil {
		return err
	}
	var toRemove []bson.ObjectId
	for appName, appEntries := range byAppMap {
		toRemoveDups := checkAllDups(appEntries)
		toRemove = append(toRemove, toRemoveDups...)
		var toRemoveAddrs []bson.ObjectId
		toRemoveAddrs, err = checkAppAddr(appColl, appName, appEntries)
		if err != nil {
			return err
		}
		toRemove = append(toRemove, toRemoveAddrs...)
	}
	_, err = coll.RemoveAll(bson.M{"_id": bson.M{"$in": toRemove}})
	if err != nil {
		return err
	}
	var routerAppNames []string
	err = coll.Find(nil).Distinct("app", &routerAppNames)
	if err != nil {
		return err
	}
	var missingApps []string
	err = appColl.Find(bson.M{"name": bson.M{"$nin": routerAppNames}}).Distinct("name", &missingApps)
	if err != nil {
		return err
	}
	for _, missingEntry := range missingApps {
		err = coll.Insert(routerAppEntry{
			App:    missingEntry,
			Router: missingEntry,
		})
		if err != nil {
			return err
		}
	}
	byAppMap, err = allDupEntries(coll)
	if err != nil {
		return err
	}
	if len(byAppMap) == 0 {
		_, err = collection()
		return err
	}
	errBuf := bytes.NewBuffer(nil)
	fmt.Fprintln(errBuf, `ERROR: The following entries in 'db.routers' collection have inconsistent
duplicated entries that could not be fixed automatically. This could have
happened after running app-swap due to a bug in previous tsuru versions. You'll
have to manually check if the apps are swapped or not and remove the duplicated
entries accordingly:`)
	for appName, entries := range byAppMap {
		fmt.Fprintf(errBuf, "app %q:\n", appName)
		for _, e := range entries {
			fmt.Fprintf(errBuf, "  %#v\n", e)
		}
	}
	return errors.New(errBuf.String())
}
func MigrateUniqueCollection() error {
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	coll := conn.Collection("routers")
	appColl := conn.Apps()
	var appNames []string
	err = appColl.Find(nil).Distinct("name", &appNames)
	if err != nil {
		return err
	}
	_, err = coll.RemoveAll(bson.M{"app": bson.M{"$nin": appNames}, "router": bson.M{"$nin": appNames}})
	if err != nil {
		return err
	}
	byAppMap, err := allDupEntries(coll)
	if err != nil {
		return err
	}
	var toRemove []bson.ObjectId
	for appName, appEntries := range byAppMap {
		toRemoveDups := checkAllDups(appEntries)
		toRemove = append(toRemove, toRemoveDups...)
		var toRemoveAddrs []bson.ObjectId
		toRemoveAddrs, err = checkAppAddr(appColl, appName, appEntries)
		if err != nil {
			return err
		}
		toRemove = append(toRemove, toRemoveAddrs...)
	}
	_, err = coll.RemoveAll(bson.M{"_id": bson.M{"$in": toRemove}})
	if err != nil {
		return err
	}
	var routerAppNames []string
	err = coll.Find(nil).Distinct("app", &routerAppNames)
	if err != nil {
		return err
	}
	var missingApps []string
	err = appColl.Find(bson.M{"name": bson.M{"$nin": routerAppNames}}).Distinct("name", &missingApps)
	if err != nil {
		return err
	}
	for _, missingEntry := range missingApps {
		err = coll.Insert(routerAppEntry{
			App:    missingEntry,
			Router: missingEntry,
		})
		if err != nil {
			return err
		}
	}
	byAppMap, err = allDupEntries(coll)
	if err != nil {
		return err
	}
	if len(byAppMap) == 0 {
		_, err = collection()
		return err
	}
	errBuf := bytes.NewBuffer(nil)
	fmt.Fprintln(errBuf, `ERROR: The following entries in 'db.routers' collection have inconsistent
duplicated entries that could not be fixed automatically. This could have
happened after running app-swap due to a bug in previous tsuru versions. You'll
have to manually check if the apps are swapped or not and remove the duplicated
entries accordingly:`)
	for appName, entries := range byAppMap {
		fmt.Fprintf(errBuf, "app %q:\n", appName)
		for _, e := range entries {
			fmt.Fprintf(errBuf, "  %#v\n", e)
		}
	}
	return errors.New(errBuf.String())
}
// MigrateUniqueCollection only exists because old versions of tsuru (<1.2.0)
// allowed the insertion of incorrect duplicated entries in the db.routers
// collection. This migration tries its best to fix the inconsistencies in this
// collection and fails if that's not possible.