Ejemplo n.º 1
0
func (s *S) TestManaged(c *C) {
	conns := make([]*ldapConn, 0, 3)
	dials := 0
	ldap.TestDial = func(c *ldap.Config) (ldap.Conn, error) {
		dials++
		if dials == 1 {
			return nil, fmt.Errorf("temporary error")
		}
		conn := &ldapConn{config: c}
		if dials == 2 {
			conn.fail = true
		}
		conns = append(conns, conn)
		return conn, nil
	}
	defer func() {
		ldap.TestDial = nil
	}()

	mconn := ldap.DialManaged(config)

	conn := mconn.Conn()
	defer conn.Close()
	res, err := conn.Search(&ldap.Search{Filter: "test-filter1"})
	c.Assert(err, ErrorMatches, "test-error")
	c.Assert(res, IsNil)

	c.Assert(conn.Close(), IsNil)
	c.Assert(conn.Close(), IsNil)

	_, err = conn.Search(&ldap.Search{})
	c.Assert(err, ErrorMatches, "LDAP connection already closed")

	conn = mconn.Conn()
	defer conn.Close()

	c.Assert(mconn.Close(), IsNil)
	c.Assert(mconn.Close(), IsNil)

	res, err = conn.Search(&ldap.Search{Filter: "test-filter2"})
	c.Assert(err, IsNil)
	c.Assert(res, HasLen, 1)
	c.Assert(res[0].DN, Equals, "test-dn")

	c.Assert(conn.Close(), IsNil)

	c.Assert(func() { mconn.Conn() }, PanicMatches, "ManagedConn.Conn called after closing connection")

	c.Assert(conns, HasLen, 2)
	c.Assert(conns[0].closed, Equals, true)
	c.Assert(conns[0].config, DeepEquals, config)
	c.Assert(conns[0].search.Filter, Equals, "test-filter1")
	c.Assert(conns[1].closed, Equals, true)
	c.Assert(conns[1].config, DeepEquals, config)
	c.Assert(conns[1].search.Filter, Equals, "test-filter2")
}
Ejemplo n.º 2
0
func (m *pluginManager) refreshLdaps() {
	changed := false
	defer func() {
		if changed {
			m.ldapConnsMutex.Lock()
			m.ldapConns = make(map[string]*ldap.ManagedConn)
			for name, state := range m.ldaps {
				m.ldapConns[name] = state.conn
			}
			m.ldapConnsMutex.Unlock()
		}
	}()

	// Start new LDAP instances, and stop/restart updated ones.
	var raw bson.Raw
	var infos = make([]ldapInfo, 0, len(m.ldaps))
	var found int
	var known = len(m.ldaps)
	iter := m.database.C("ldap").Find(nil).Iter()
	for iter.Next(&raw) {
		var info ldapInfo
		if err := raw.Unmarshal(&info); err != nil {
			logf("Cannot unmarshal LDAP document: %v", err)
			continue
		}
		infos = append(infos, info)
		if state, ok := m.ldaps[info.Name]; ok {
			found++
			if bytes.Equal(state.raw.Data, raw.Data) {
				continue
			}
			logf("LDAP connection %q changed. Closing and restarting it.", info.Name)
			err := state.conn.Close()
			if err != nil {
				logf("LDAP connection %q closed with an error: %v", info.Name, err)
			}
			delete(m.ldaps, info.Name)
		} else {
			logf("LDAP %q starting.", info.Name)
		}

		m.ldaps[info.Name] = &ldapState{
			raw:  raw,
			info: info,
			conn: ldap.DialManaged(&info.Config),
		}
		changed = true
	}
	if iter.Err() != nil {
		// TODO Reduce frequency of logged messages if the database goes down.
		logf("Cannot fetch LDAP connection information from the database: %v", iter.Err())
		return
	}

	// If there are known LDAPs that were not observed in the current
	// set of LDAPs, they must be stopped and removed.
	if known != found {
	NextLDAP:
		for name, state := range m.ldaps {
			for i := range infos {
				if infos[i].Name == name {
					continue NextLDAP
				}
			}
			logf("LDAP connection %q removed. Closing it.", state.info.Name)
			err := state.conn.Close()
			if err != nil {
				logf("LDAP connection %q closed with an error: %v", state.info.Name, err)
			}
			delete(m.ldaps, name)
			changed = true
		}
	}
}