Example #1
0
// GetSSHAddr returns the username and the hostname of the remove machine to ssh.
//
// It assume user exists on the remove machine with the same Koding username.
// It may also return a custom port number, if other than a default should
// be used.
func (s *SSHKey) GetSSHAddr(name string) (userhost, port string, err error) {
	infos, err := s.Klient.RemoteList()
	if err != nil {
		return "", "", err
	}

	info, ok := infos.FindFromName(name)

	if !ok {
		s.Log.Error("No machine found with specified name: `%s`", name)
		return "", "", ErrMachineNotFound
	}

	remoteUsername, err := s.GetUsername(name)
	if err != nil {
		return "", "", err
	}

	endpoints, err := s.Discover.Discover(info.IP, "ssh")
	if err != nil {
		return fmt.Sprintf("%s@%s", remoteUsername, info.IP), "", nil
	}

	addr := endpoints[0].Addr

	// We prefer local routes to use first, if there's none, we use first
	// discovered route.
	if e := endpoints.Filter(discover.ByLocal(true)); len(e) != 0 {

		// All local routes will do, typically there's only one,
		// we use the first one and ignore the rest.
		addr = e[0].Addr
	}

	host, port, err := net.SplitHostPort(addr)
	if err != nil {
		host = addr
	}

	return fmt.Sprintf("%s@%s", remoteUsername, host), port, nil
}
Example #2
0
File: ssh.go Project: koding/koding
// Create updates internal state of machine group. It gets the current
// information about user machines so it can add new ones to group.
func (g *Group) SSH(req *SSHRequest) (*SSHResponse, error) {
	if req == nil {
		return nil, errors.New("invalid nil request")
	}

	c, err := g.client.Client(req.ID)
	if err != nil {
		return nil, err
	}

	// Use provided username or ask remote machine to return it.
	username := req.Username
	if username == "" {
		if username, err = c.CurrentUser(); err != nil {
			return nil, err
		}
	}

	// Add pubic key to remote machine authorized keys.
	if req.PublicKey != "" {
		if err := c.SSHAddKeys(username, req.PublicKey); err != nil {
			return nil, err
		}
	}

	// Check for tunneled connections.
	addr, err := g.address.Latest(req.ID, "tunnel")
	if err != nil {
		// There are no tunnel addresses. Get latest IP.
		if addr, err = g.address.Latest(req.ID, "ip"); err != nil {
			return nil, err
		}

		return &SSHResponse{
			Username: username,
			Host:     addr.Value,
		}, nil
	}

	// Discover tunnel SSH address.
	endpoints, err := g.discover.Discover(addr.Value, "ssh")
	if err != nil {
		return &SSHResponse{
			Username: username,
			Host:     addr.Value,
		}, nil
	}

	tuneladdr := endpoints[0].Addr
	// We prefer local routes to use first, if there's none, we use first
	// discovered route.
	if e := endpoints.Filter(discover.ByLocal(true)); len(e) != 0 {
		// All local routes will do, typically there's only one,
		// we use the first one and ignore the rest.
		tuneladdr = e[0].Addr
	}

	host, port, err := net.SplitHostPort(tuneladdr)
	if err != nil {
		host, port = tuneladdr, "0"
	}

	n, err := strconv.Atoi(port)
	if err != nil {
		return nil, err
	}

	return &SSHResponse{
		Username: username,
		Host:     host,
		Port:     n,
	}, nil
}