Пример #1
0
func DeleteRoute(route core.Route) error {
	// in case of failure
	oldRoutes, err := database.GetRoutes()
	if err != nil {
		return err
	}

	// apply to proxymgr
	err = proxymgr.DeleteRoute(route)
	if err != nil {
		return err
	}

	if !database.CentralStore {
		// save to backend
		err = database.DeleteRoute(route)
		if err != nil {
			// undo proxymgr action
			if uerr := proxymgr.SetRoutes(oldRoutes); uerr != nil {
				err = fmt.Errorf("%v - %v", err.Error(), uerr.Error())
			}
			return err
		}
	}
	return nil
}
Пример #2
0
func TestNoneDeleteRoute(t *testing.T) {
	if err := cluster.DeleteRoute(testRoute); err != nil {
		t.Errorf("Failed to DELETE route - %v", err)
		t.FailNow()
	}

	// don't use cluster.GetRoutes()
	routes, err := database.GetRoutes()
	if len(routes) != 0 {
		t.Error("Failed to DELETE route - %v", err)
	}
}
Пример #3
0
func TestDeleteRoute(t *testing.T) {
	if err := database.DeleteRoute(testRoute); err != nil {
		t.Errorf("Failed to DELETE route - %v", err)
	}

	routes, err := database.GetRoutes()
	if err != nil {
		t.Error(err)
	}

	if len(routes) != 0 {
		t.Errorf("Failed to delete route")
	}
}
Пример #4
0
////////////////////////////////////////////////////////////////////////////////
// ROUTES
////////////////////////////////////////////////////////////////////////////////
func TestNoneSetRoute(t *testing.T) {
	if err := cluster.SetRoute(testRoute); err != nil {
		t.Errorf("Failed to SET route - %v", err)
		t.FailNow()
	}

	routes, err := database.GetRoutes()
	if err != nil {
		t.Error(err)
	}

	if len(routes) != 1 || routes[0].Domain != testRoute.Domain {
		t.Errorf("Read route differs from written route")
	}
}
Пример #5
0
func TestSetRoutes(t *testing.T) {
	routes := []core.Route{testRoute}

	if err := database.SetRoutes(routes); err != nil {
		t.Errorf("Failed to SET routes - %v", err)
	}

	routes, err := database.GetRoutes()
	if err != nil {
		t.Error(err)
	}

	if len(routes) != 1 {
		t.Errorf("Wrong number of routes")
	}
}
Пример #6
0
func TestNoneSetRoutes(t *testing.T) {
	routes := []core.Route{testRoute}

	if err := cluster.SetRoutes(routes); err != nil {
		t.Errorf("Failed to SET routes - %v", err)
		t.FailNow()
	}

	// don't use cluster.GetRoutes()
	routes, err := database.GetRoutes()
	if err != nil {
		t.Error(err)
	}

	if len(routes) != 1 || routes[0].Domain != testRoute.Domain {
		t.Errorf("Read route differs from written route")
	}
}
Пример #7
0
// GetRoutes gets a list of routes from the database, or another cluster member.
func (r *Redis) GetRoutes() ([]core.Route, error) {
	if database.CentralStore {
		return database.GetRoutes()
	}

	conn := pool.Get()
	defer conn.Close()

	// get known members(other than me) to 'poll' for routes
	members, _ := redis.Strings(conn.Do("SMEMBERS", "members"))
	if len(members) == 0 {
		// should only happen on new cluster
		// assume i'm ok to be master so don't reset imported routes
		config.Log.Trace("[cluster] - Assuming OK to be master, using routes from my database...")
		return common.GetRoutes()
	}
	for i := range members {
		if members[i] == self {
			// if i'm in the list of members, new requests should have failed while `waitForMembers`ing
			config.Log.Trace("[cluster] - Assuming I was in sync, using routes from my database...")
			return common.GetRoutes()
		}
	}

	c, err := redis.DialURL(config.ClusterConnection, redis.DialConnectTimeout(15*time.Second), redis.DialPassword(config.ClusterToken))
	if err != nil {
		return nil, fmt.Errorf("Failed to reach redis for routes subscriber - %v", err)
	}
	defer c.Close()

	message := make(chan interface{})
	subconn := redis.PubSubConn{c}

	// subscribe to channel that routes will be published on
	if err := subconn.Subscribe("routes"); err != nil {
		return nil, fmt.Errorf("Failed to reach redis for routes subscriber - %v", err)
	}
	defer subconn.Close()

	// listen always
	go func() {
		for {
			message <- subconn.Receive()
		}
	}()

	// todo: maybe use ttl?
	// timeout is how long to wait for the listed members to come back online
	timeout := time.After(time.Duration(20) * time.Second)

	// loop attempts for timeout, allows last dead members to start back up
	for {
		select {
		case <-timeout:
			return nil, fmt.Errorf("Timed out waiting for routes from %v", strings.Join(members, ", "))
		default:
			// request routes from each member until successful
			for _, member := range members {
				// memberTimeout is how long to wait for a member to respond with list of routes
				memberTimeout := time.After(3 * time.Second)

				// ask a member for its routes
				config.Log.Trace("[cluster] - Attempting to request routes from %v...", member)
				_, err := conn.Do("PUBLISH", "portal", fmt.Sprintf("get-routes %s", member))
				if err != nil {
					return nil, err
				}

				// wait for member to respond
				for {
					select {
					case <-memberTimeout:
						config.Log.Debug("[cluster] - Timed out waiting for routes from %v", member)
						goto nextRouteMember
					case msg := <-message:
						switch v := msg.(type) {
						case redis.Message:
							config.Log.Trace("[cluster] - Received message on 'routes' channel")
							var routes []core.Route
							err = parseBody(v.Data, &routes)
							if err != nil {
								return nil, fmt.Errorf("Failed to marshal routes - %v", err.Error())
							}
							config.Log.Trace("[cluster] - Routes from cluster: %#v\n", routes)
							return routes, nil
						case error:
							return nil, fmt.Errorf("Subscriber failed to receive routes - %v", v.Error())
						}
					}
				}
			nextRouteMember:
			}
		}
	}
}
Пример #8
0
func GetRoutes() ([]core.Route, error) {
	return database.GetRoutes()
}