func TestGetContainerClient(t *testing.T) { t.Parallel() targetContainer := 1 workerHost := "worker" leaderHost := "leader" passedClient := &mocks.Client{} mockGetter := mockAddrClientGetter{ func(host string) (client.Client, error) { switch host { case api.RemoteAddress(leaderHost): return &mocks.Client{ ContainerReturn: []db.Container{ { StitchID: targetContainer, Minion: workerHost, }, { StitchID: 5, Minion: "bad", }, }, EtcdReturn: []db.Etcd{ { LeaderIP: leaderHost, }, }, }, nil case api.RemoteAddress(workerHost): return passedClient, nil default: t.Fatalf("Unexpected call to getClient with host %s", host) } panic("unreached") }, } localClient := &mocks.Client{ MachineReturn: []db.Machine{ { PublicIP: leaderHost, PrivateIP: leaderHost, }, { PrivateIP: workerHost, PublicIP: workerHost, }, }, } res, err := clientGetterImpl{mockGetter}.ContainerClient( localClient, targetContainer) assert.Nil(t, err) assert.Equal(t, passedClient, res) }
func TestGetLeaderClient(t *testing.T) { t.Parallel() passedClient := &mocks.Client{} mockGetter := mockAddrClientGetter{ func(host string) (client.Client, error) { switch host { // One machine doesn't know the LeaderIP case api.RemoteAddress("8.8.8.8"): return &mocks.Client{ EtcdReturn: []db.Etcd{ { LeaderIP: "", }, }, }, nil // The other machine knows the LeaderIP case api.RemoteAddress("9.9.9.9"): return &mocks.Client{ EtcdReturn: []db.Etcd{ { LeaderIP: "leader-priv", }, }, }, nil case api.RemoteAddress("leader"): return passedClient, nil default: t.Fatalf("Unexpected call to getClient with host %s", host) } panic("unreached") }, } localClient := &mocks.Client{ MachineReturn: []db.Machine{ { PublicIP: "8.8.8.8", }, { PublicIP: "9.9.9.9", }, { PublicIP: "leader", PrivateIP: "leader-priv", }, }, } res, err := clientGetterImpl{mockGetter}.LeaderClient(localClient) assert.Nil(t, err) assert.Equal(t, passedClient, res) }
func (getter clientGetterImpl) ContainerClient(localClient client.Client, stitchID int) (client.Client, error) { leaderClient, err := getter.LeaderClient(localClient) if err != nil { return nil, err } defer leaderClient.Close() containerInfo, err := util.GetContainer(leaderClient, stitchID) if err != nil { return nil, err } if containerInfo.Minion == "" { return nil, errors.New("container hasn't been scheduled yet") } containerIP, err := getPublicIP(localClient, containerInfo.Minion) if err != nil { return nil, err } return getter.Client(api.RemoteAddress(containerIP)) }
// Get the public IP of the lead minion by querying the remote machine's etcd // table for the private IP, and then searching for the public IP in the local // daemon. func (getter clientGetterImpl) getLeaderIP(localClient client.Client, daemonIP string) (string, error) { remoteClient, err := getter.Client(api.RemoteAddress(daemonIP)) if err != nil { return "", err } defer remoteClient.Close() etcds, err := remoteClient.QueryEtcd() if err != nil { return "", err } if len(etcds) == 0 || etcds[0].LeaderIP == "" { return "", fmt.Errorf("no leader information on host %s", daemonIP) } return getPublicIP(localClient, etcds[0].LeaderIP) }
func (getter clientGetterImpl) LeaderClient(localClient client.Client) ( client.Client, error) { machines, err := localClient.QueryMachines() if err != nil { return nil, fmt.Errorf("unable to query machines: %s", err.Error()) } // Try to figure out the lead minion's IP by asking each of the machines // tracked by the local daemon. for _, m := range machines { if m.PublicIP == "" { continue } ip, err := getter.getLeaderIP(localClient, m.PublicIP) if err == nil { return getter.Client(api.RemoteAddress(ip)) } log.WithError(err).Debug("Unable to get leader IP") } return nil, errors.New("no leader found") }