URL: https://github.com/freeipa/freeipa/pull/492
Author: HonzaCholasta
 Title: #492: [WIP] config: remove meaningless defaults
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/492/head:pr492
git checkout pr492
From a6ac65697b212a02e3032d34bcc847a56d757afa Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 23 Feb 2017 09:44:04 +0000
Subject: [PATCH 1/6] user, migration: use LDAPClient for ad-hoc LDAP
 connections

Use LDAPClient instead of ldap2 for ad-hoc remote LDAP connections in the
user_status and migrate-ds plugins.
---
 ipaserver/plugins/migration.py | 15 +++++----------
 ipaserver/plugins/user.py      | 12 +++++-------
 2 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/ipaserver/plugins/migration.py b/ipaserver/plugins/migration.py
index 72abd14..e8d102a 100644
--- a/ipaserver/plugins/migration.py
+++ b/ipaserver/plugins/migration.py
@@ -28,13 +28,9 @@
 from ipalib.cli import to_cli
 from ipalib.plugable import Registry
 from .user import NO_UPG_MAGIC
-if api.env.in_server and api.env.context in ['lite', 'server']:
-    try:
-        from ipaserver.plugins.ldap2 import ldap2
-    except Exception as e:
-        raise e
 from ipalib import _
 from ipapython.dn import DN
+from ipapython.ipaldap import LDAPClient
 from ipapython.ipautil import write_tmp_file
 from ipapython.kerberos import Principal
 import datetime
@@ -885,8 +881,6 @@ def execute(self, ldapuri, bindpw, **options):
             return dict(result={}, failed={}, enabled=False, compat=True)
 
         # connect to DS
-        ds_ldap = ldap2(self.api, ldap_uri=ldapuri)
-
         cacert = None
         if options.get('cacertfile') is not None:
             # store CA cert into file
@@ -894,12 +888,13 @@ def execute(self, ldapuri, bindpw, **options):
             cacert = tmp_ca_cert_f.name
 
             # start TLS connection
-            ds_ldap.connect(bind_dn=options['binddn'], bind_pw=bindpw,
-                            cacert=cacert)
+            ds_ldap = LDAPClient(ldapuri, cacert=cacert)
+            ds_ldap.simple_bind(options['binddn'], bindpw)
 
             tmp_ca_cert_f.close()
         else:
-            ds_ldap.connect(bind_dn=options['binddn'], bind_pw=bindpw)
+            ds_ldap = LDAPClient(ldapuri, cacert=cacert)
+            ds_ldap.simple_bind(options['binddn'], bindpw)
 
         # check whether the compat plugin is enabled
         if not options.get('compat'):
diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py
index 2d29dfb..afaa828 100644
--- a/ipaserver/plugins/user.py
+++ b/ipaserver/plugins/user.py
@@ -21,7 +21,7 @@
 import time
 from time import gmtime, strftime
 import posixpath
-import os
+
 import six
 
 from ipalib import api
@@ -63,12 +63,10 @@
 from ipalib import output
 from ipaplatform.paths import paths
 from ipapython.dn import DN
+from ipapython.ipaldap import LDAPClient
 from ipapython.ipautil import ipa_generate_password, TMP_PWD_ENTROPY_BITS
 from ipalib.capabilities import client_has_capability
 
-if api.env.in_server:
-    from ipaserver.plugins.ldap2 import ldap2
-
 if six.PY3:
     unicode = str
 
@@ -1124,9 +1122,9 @@ def execute(self, *keys, **options):
             if host == api.env.host:
                 other_ldap = self.obj.backend
             else:
-                other_ldap = ldap2(self.api, ldap_uri='ldap://%s' % host)
                 try:
-                    other_ldap.connect(ccache=os.environ['KRB5CCNAME'])
+                    other_ldap = LDAPClient(ldap_uri='ldap://%s' % host)
+                    other_ldap.gssapi_bind()
                 except Exception as e:
                     self.error("user_status: Connecting to %s failed with %s" % (host, str(e)))
                     newresult = {'dn': dn}
@@ -1171,7 +1169,7 @@ def execute(self, *keys, **options):
                 count += 1
 
             if host != api.env.host:
-                other_ldap.disconnect()
+                other_ldap.close()
 
         return dict(result=entries,
                     count=count,

From ceacb79493bd1ffa0c048a58bf97a9f161081a79 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 23 Feb 2017 09:52:51 +0000
Subject: [PATCH 2/6] {ca,kra}instance: drop redundant URI argument from ad-hoc
 ldap2 connections

Use the default LDAP URI from api.env.ldap_uri instead of specifying a
custom URI in the argument, as the custom URI is always the same as the
default URI.
---
 ipaserver/install/cainstance.py  | 19 +++++--------------
 ipaserver/install/krainstance.py |  4 +---
 2 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 0991883..b3aeec6 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -726,9 +726,7 @@ def __create_ca_agent(self):
         cert_data = self.ra_cert.public_bytes(serialization.Encoding.DER)
 
         # connect to CA database
-        server_id = installutils.realm_to_serverid(api.env.realm)
-        dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
-        conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
+        conn = ldap2.ldap2(api)
         conn.connect(autobind=True)
 
         # create ipara user with RA certificate
@@ -1331,14 +1329,12 @@ def __update_entry_from_cert(make_filter, make_entry, dercert):
     base_dn = DN(('o', 'ipaca'))
 
     attempts = 0
-    server_id = installutils.realm_to_serverid(api.env.realm)
-    dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
     updated = False
 
     while attempts < 10:
         conn = None
         try:
-            conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
+            conn = ldap2.ldap2(api)
             conn.connect(autobind=True)
 
             db_filter = make_filter(dercert)
@@ -1368,7 +1364,7 @@ def __update_entry_from_cert(make_filter, make_entry, dercert):
         except errors.NetworkError:
             syslog.syslog(
                 syslog.LOG_ERR,
-                'Connection to %s failed, sleeping 30s' % dogtag_uri)
+                'Connection to %s failed, sleeping 30s' % api.env.ldap_uri)
             time.sleep(30)
             attempts += 1
         except Exception as e:
@@ -1458,10 +1454,7 @@ def ensure_entry(dn, **attrs):
     otherwise add the entry and return ``True``.
 
     """
-    server_id = installutils.realm_to_serverid(api.env.realm)
-    dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
-
-    conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
+    conn = ldap2.ldap2(api)
     if not conn.isconnected():
         conn.connect(autobind=True)
 
@@ -1548,9 +1541,7 @@ def __get_profile_config(profile_id):
         '/usr/share/ipa/profiles/{}.cfg'.format(profile_id), sub_dict)
 
 def import_included_profiles():
-    server_id = installutils.realm_to_serverid(api.env.realm)
-    dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
-    conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
+    conn = ldap2.ldap2(api)
     if not conn.isconnected():
         conn.connect(autobind=True)
 
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
index 5ee08dc..0ab3805 100644
--- a/ipaserver/install/krainstance.py
+++ b/ipaserver/install/krainstance.py
@@ -295,9 +295,7 @@ def __create_kra_agent(self):
         cert_data = cert.public_bytes(serialization.Encoding.DER)
 
         # connect to KRA database
-        server_id = installutils.realm_to_serverid(api.env.realm)
-        dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
-        conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
+        conn = ldap2.ldap2(api)
         conn.connect(autobind=True)
 
         # create ipakra user with RA agent certificate

From d85301371e9655b76068681a9729fb0ee7344f7c Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 23 Feb 2017 10:14:41 +0000
Subject: [PATCH 3/6] test_ldap: drop redundant URI argument

Use the default LDAP URI from api.env.ldap_uri instead of specifying a
custom URI in the argument. The default URI might be ldapi://, so make sure
autobind is not attempted where the custom URI was ldap://.
---
 ipatests/test_ipaserver/test_ldap.py | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/ipatests/test_ipaserver/test_ldap.py b/ipatests/test_ipaserver/test_ldap.py
index e7ba867..1d76319 100644
--- a/ipatests/test_ipaserver/test_ldap.py
+++ b/ipatests/test_ipaserver/test_ldap.py
@@ -34,7 +34,7 @@
 import six
 
 from ipaplatform.paths import paths
-from ipaserver.plugins.ldap2 import ldap2
+from ipaserver.plugins.ldap2 import ldap2, AUTOBIND_DISABLED
 from ipalib import api, x509, create_api, errors
 from ipapython import ipautil
 from ipapython.dn import DN
@@ -51,7 +51,7 @@ class test_ldap(object):
 
     def setup(self):
         self.conn = None
-        self.ldapuri = 'ldap://%s' % ipautil.format_netloc(api.env.host)
+        self.ldapuri = api.env.ldap_uri
         self.dn = DN(('krbprincipalname','ldap/%s@%s' % (api.env.host, api.env.realm)),
                      ('cn','services'),('cn','accounts'),api.env.basedn)
 
@@ -63,8 +63,8 @@ def test_anonymous(self):
         """
         Test an anonymous LDAP bind using ldap2
         """
-        self.conn = ldap2(api, ldap_uri=self.ldapuri)
-        self.conn.connect()
+        self.conn = ldap2(api)
+        self.conn.connect(autobind=AUTOBIND_DISABLED)
         dn = api.env.basedn
         entry_attrs = self.conn.get_entry(dn, ['associateddomain'])
         domain = entry_attrs.single_value['associateddomain']
@@ -74,8 +74,8 @@ def test_GSSAPI(self):
         """
         Test a GSSAPI LDAP bind using ldap2
         """
-        self.conn = ldap2(api, ldap_uri=self.ldapuri)
-        self.conn.connect()
+        self.conn = ldap2(api)
+        self.conn.connect(autobind=AUTOBIND_DISABLED)
         entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
         cert = entry_attrs.get('usercertificate')
         cert = cert[0]
@@ -93,7 +93,7 @@ def test_simple(self):
             fp.close()
         else:
             raise nose.SkipTest("No directory manager password in %s" % pwfile)
-        self.conn = ldap2(api, ldap_uri=self.ldapuri)
+        self.conn = ldap2(api)
         self.conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
         entry_attrs = self.conn.get_entry(self.dn, ['usercertificate'])
         cert = entry_attrs.get('usercertificate')
@@ -133,8 +133,7 @@ def test_autobind(self):
         """
         Test an autobind LDAP bind using ldap2
         """
-        ldapuri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % api.env.realm.replace('.','-')
-        self.conn = ldap2(api, ldap_uri=ldapuri)
+        self.conn = ldap2(api)
         try:
             self.conn.connect(autobind=True)
         except errors.ACIError:
@@ -157,9 +156,9 @@ class test_LDAPEntry(object):
     dn2 = DN(('cn', cn2[0]))
 
     def setup(self):
-        self.ldapuri = 'ldap://%s' % ipautil.format_netloc(api.env.host)
-        self.conn = ldap2(api, ldap_uri=self.ldapuri)
-        self.conn.connect()
+        self.ldapuri = api.env.ldap_uri
+        self.conn = ldap2(api)
+        self.conn.connect(autobind=AUTOBIND_DISABLED)
 
         self.entry = self.conn.make_entry(self.dn1, cn=self.cn1)
 

From e8012f680fd57ca0bbda1c84e1007778be8fb3bb Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 23 Feb 2017 10:15:52 +0000
Subject: [PATCH 4/6] ldap2: remove URI argument from ldap2 constructor

LDAPClient should be used for ad-hoc connections, so the argument is not
necessary, and currently also unused.
---
 ipapython/ipaldap.py       | 19 ++++++++++---------
 ipaserver/plugins/ldap2.py | 11 ++++++-----
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index b158598..542c4bf 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -701,7 +701,16 @@ def __init__(self, ldap_uri, start_tls=False, force_schema_updates=False,
             If true, attributes are decoded to Python types according to their
             syntax.
         """
-        self.ldap_uri = ldap_uri
+        if ldap_uri is not None:
+            self.ldap_uri = ldap_uri
+            self.host = 'localhost'
+            self.port = None
+            url_data = urlparse(ldap_uri)
+            self._protocol = url_data.scheme
+            if self._protocol in ('ldap', 'ldaps'):
+                self.host = url_data.hostname
+                self.port = url_data.port
+
         self._start_tls = start_tls
         self._force_schema_updates = force_schema_updates
         self._no_schema = no_schema
@@ -709,14 +718,6 @@ def __init__(self, ldap_uri, start_tls=False, force_schema_updates=False,
         self._cacert = cacert
         self._sasl_nocanon = sasl_nocanon
 
-        self.host = 'localhost'
-        self.port = None
-        url_data = urlparse(ldap_uri)
-        self._protocol = url_data.scheme
-        if self._protocol in ('ldap', 'ldaps'):
-            self.host = url_data.hostname
-            self.port = url_data.port
-
         self.log = log_mgr.get_logger(self)
         self._has_schema = False
         self._schema = None
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index e671ecb..3cff47b 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -67,20 +67,21 @@ class ldap2(CrudBackend, LDAPClient):
     LDAP Backend Take 2.
     """
 
-    def __init__(self, api, ldap_uri=None):
-        if ldap_uri is None:
-            ldap_uri = api.env.ldap_uri
-
+    def __init__(self, api):
         force_schema_updates = api.env.context in ('installer', 'updates')
 
         CrudBackend.__init__(self, api)
-        LDAPClient.__init__(self, ldap_uri,
+        LDAPClient.__init__(self, None,
                             force_schema_updates=force_schema_updates)
 
         self.__time_limit = float(LDAPClient.time_limit)
         self.__size_limit = int(LDAPClient.size_limit)
 
     @property
+    def ldap_uri(self):
+        return self.api.env.ldap_uri
+
+    @property
     def time_limit(self):
         if self.__time_limit is None:
             return float(self.get_ipa_config().single_value.get(

From 4ef3f95ad2dffe8a34036992e56db105b928d37a Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Tue, 10 May 2016 14:20:15 +0200
Subject: [PATCH 5/6] ipalib.constants: Remove default domain, realm, basedn,
 xmlrpc_uri, ldap_uri

Domain, realm, basedn, xmlrpc_uri, ldap_uri do not have any reasonable default.
This patch removes hardcoded default so the so the code which depends
on these values blows up early and does not do crazy stuff
with default values instead of real ones.

This should help to uncover issues caused by improper ipalib
initialization.
---
 ipalib/constants.py | 16 +++++++++++-----
 makeaci             |  3 +++
 makeapi             |  6 ++++++
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/ipalib/constants.py b/ipalib/constants.py
index 8789a95..4c7fa45 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -67,9 +67,12 @@
     ('version', VERSION),
 
     # Domain, realm, basedn:
-    ('domain', 'example.com'),
-    ('realm', 'EXAMPLE.COM'),
-    ('basedn', DN(('dc', 'example'), ('dc', 'com'))),
+    # Following values do not have any reasonable default.
+    # Do not initialize them so the code which depends on them blows up early
+    # and does not do crazy stuff with default values instead of real ones.
+    # ('domain', 'example.com'),
+    # ('realm', 'EXAMPLE.COM'),
+    # ('basedn', DN(('dc', 'example'), ('dc', 'com'))),
 
     # LDAP containers:
     ('container_accounts', DN(('cn', 'accounts'))),
@@ -126,9 +129,12 @@
     ('container_certmaprules', DN(('cn', 'certmaprules'), ('cn', 'certmap'))),
 
     # Ports, hosts, and URIs:
-    ('xmlrpc_uri', 'http://localhost:8888/ipa/xml'),
+    # Following values do not have any reasonable default.
+    # Do not initialize them so the code which depends on them blows up early
+    # and does not do crazy stuff with default values instead of real ones.
+    # ('xmlrpc_uri', 'http://localhost:8888/ipa/xml'),
     # jsonrpc_uri is set in Env._finalize_core()
-    ('ldap_uri', 'ldap://localhost:389'),
+    # ('ldap_uri', 'ldap://localhost:389'),
 
     ('rpc_protocol', 'jsonrpc'),
 
diff --git a/makeaci b/makeaci
index 98b199c..813ecc7 100755
--- a/makeaci
+++ b/makeaci
@@ -98,6 +98,9 @@ def main(options):
         plugins_on_demand=False,
         basedn=DN('dc=ipa,dc=example'),
         realm='IPA.EXAMPLE',
+        domain="example.com",
+        xmlrpc_uri="http://localhost:8888/ipa/xml";,
+        ldap_uri="ldap://localhost:389";,
     )
 
     from ipaserver.install.plugins import update_managed_permissions
diff --git a/makeapi b/makeapi
index d0a7295..729b922 100755
--- a/makeapi
+++ b/makeapi
@@ -40,6 +40,7 @@ from ipalib.parameters import Param
 from ipalib.output import Output
 from ipalib.text import Gettext, NGettext, ConcatenatedLazyText
 from ipalib.capabilities import capabilities
+from ipapython.dn import DN
 
 API_FILE='API.txt'
 
@@ -513,6 +514,11 @@ def main():
         enable_ra=True,
         mode='developer',
         plugins_on_demand=False,
+        basedn=DN(('dc', 'example'), ('dc', 'com')),
+        realm="EXAMPLE.COM",
+        domain="example.com",
+        xmlrpc_uri="http://localhost:8888/ipa/xml";,
+        ldap_uri="ldap://localhost:389";,
     )
 
     api.bootstrap(**cfg)

From f0b00cd8c2d4c36d03bda877d5ef79258c0db413 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Tue, 21 Feb 2017 13:24:51 +0000
Subject: [PATCH 6/6] config: provide defaults for `xmlrpc_uri`, `ldap_uri` and
 `basedn`

Derive the default value of `xmlrpc_uri` and `ldap_uri` from `server`.
Derive the default value of `basedn` from `domain`.
---
 ipalib/config.py    | 14 ++++++++++++++
 ipalib/constants.py |  5 ++---
 makeaci             |  2 --
 makeapi             |  4 ----
 pylint_plugins.py   |  4 +++-
 5 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 45052ad..0567c5b 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -577,6 +577,20 @@ def _finalize_core(self, **defaults):
         if 'log' not in self:
             self.log = self._join('logdir', '%s.log' % self.context)
 
+        if 'basedn' not in self and 'domain' in self:
+            self.basedn = DN(*(('dc', dc) for dc in self.domain.split('.')))
+
+        # Derive xmlrpc_uri from server
+        # (Note that this is done before deriving jsonrpc_uri from xmlrpc_uri
+        # and server from jsonrpc_uri so that when only server or xmlrpc_uri
+        # is specified, all 3 keys have a value.)
+        if 'xmlrpc_uri' not in self and 'server' in self:
+            self.xmlrpc_uri = 'https://{}/ipa/xml'.format(self.server)
+
+        # Derive ldap_uri from server
+        if 'ldap_uri' not in self and 'server' in self:
+            self.ldap_uri = 'ldap://{}'.format(self.server)
+
         # Derive jsonrpc_uri from xmlrpc_uri
         if 'jsonrpc_uri' not in self:
             if 'xmlrpc_uri' in self:
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 4c7fa45..e040d66 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -132,8 +132,9 @@
     # Following values do not have any reasonable default.
     # Do not initialize them so the code which depends on them blows up early
     # and does not do crazy stuff with default values instead of real ones.
+    # ('server', 'localhost'),
     # ('xmlrpc_uri', 'http://localhost:8888/ipa/xml'),
-    # jsonrpc_uri is set in Env._finalize_core()
+    # ('jsonrpc_uri', 'http://localhost:8888/ipa/json'),
     # ('ldap_uri', 'ldap://localhost:389'),
 
     ('rpc_protocol', 'jsonrpc'),
@@ -240,8 +241,6 @@
     ('in_server', object),  # Whether or not running in-server (bool)
     ('logdir', object),  # Directory containing log files
     ('log', object),  # Path to context specific log file
-    ('jsonrpc_uri', object),  # derived from xmlrpc_uri in Env._finalize_core()
-    ('server', object),  # derived from jsonrpc_uri in Env._finalize_core()
 
 )
 
diff --git a/makeaci b/makeaci
index 813ecc7..57622fe 100755
--- a/makeaci
+++ b/makeaci
@@ -99,8 +99,6 @@ def main(options):
         basedn=DN('dc=ipa,dc=example'),
         realm='IPA.EXAMPLE',
         domain="example.com",
-        xmlrpc_uri="http://localhost:8888/ipa/xml";,
-        ldap_uri="ldap://localhost:389";,
     )
 
     from ipaserver.install.plugins import update_managed_permissions
diff --git a/makeapi b/makeapi
index 729b922..2b1d154 100755
--- a/makeapi
+++ b/makeapi
@@ -40,7 +40,6 @@ from ipalib.parameters import Param
 from ipalib.output import Output
 from ipalib.text import Gettext, NGettext, ConcatenatedLazyText
 from ipalib.capabilities import capabilities
-from ipapython.dn import DN
 
 API_FILE='API.txt'
 
@@ -514,11 +513,8 @@ def main():
         enable_ra=True,
         mode='developer',
         plugins_on_demand=False,
-        basedn=DN(('dc', 'example'), ('dc', 'com')),
         realm="EXAMPLE.COM",
         domain="example.com",
-        xmlrpc_uri="http://localhost:8888/ipa/xml";,
-        ldap_uri="ldap://localhost:389";,
     )
 
     api.bootstrap(**cfg)
diff --git a/pylint_plugins.py b/pylint_plugins.py
index 45adf71..5d7da73 100644
--- a/pylint_plugins.py
+++ b/pylint_plugins.py
@@ -94,7 +94,9 @@ def fake_class(name_or_class_obj, members=()):
         'xmlrpc_uri',
         'validate_api',
         'startup_traceback',
-        'verbose'
+        'verbose',
+        'server',
+        {'domain': dir(str)},
     ] + LOGGING_ATTRS,
     'ipalib.errors.ACIError': [
         'info',
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to