URL: https://github.com/freeipa/freeipa/pull/302
Author: pvoborni
 Title: #302: Use env var IPA_CONFDIR to get confdir for 'cli' context 
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/302/head:pr302
git checkout pr302
From 5a213f334d14bba8ad06240a37d843555db6dc2b Mon Sep 17 00:00:00 2001
From: Christian Heimes <chei...@redhat.com>
Date: Mon, 24 Oct 2016 10:35:41 +0200
Subject: [PATCH 1/2] Use env var IPA_CONFDIR to get confdir

The environment variable IPA_CONFDIR overrides the default confdir path.
The value of the environment variable must be an absolute path to an existing
directory. The new variable makes it much simpler to use the 'ipa'
command and ipalib with a local configuration directory.

Some scripts (e.g. servers, installers, and upgrades) set the confdir
explicitly and do not support the env var.

Signed-off-by: Christian Heimes <chei...@redhat.com>
---
 client/man/ipa.1                      |  4 ++++
 ipalib/config.py                      | 12 ++++++++++-
 ipalib/plugable.py                    |  9 ++++++++
 ipatests/test_ipalib/test_plugable.py | 40 +++++++++++++++++++++++++++++++++--
 ipatests/util.py                      |  6 ++++++
 5 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/client/man/ipa.1 b/client/man/ipa.1
index cc5641b..f35f557 100644
--- a/client/man/ipa.1
+++ b/client/man/ipa.1
@@ -190,6 +190,10 @@ The ipa client will determine which server to connect to in this order:
 
 .TP
 If a kerberos error is raised by any of the requests then it will stop processing and display the error message.
+.SH "ENVIRONMENT VARIABLES"
+.TP
+\fBIPA_CONFDIR\fR
+Override path to confdir (default: \fB/etc/ipa\fR).
 .SH "FILES"
 .TP
 \fB/etc/ipa/default.conf\fR
diff --git a/ipalib/config.py b/ipalib/config.py
index 1075d62..9d87782 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -43,6 +43,7 @@
 from ipalib.base import check_name
 from ipalib.constants import CONFIG_SECTION
 from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
+from ipapython.admintool import ScriptError
 
 if six.PY3:
     unicode = str
@@ -460,8 +461,17 @@ def _bootstrap(self, **overrides):
             self.context = 'default'
 
         # Set confdir:
+        self.env_confdir = os.environ.get('IPA_CONFDIR')
         if 'confdir' not in self:
-            if self.in_tree:
+            if self.env_confdir is not None:
+                if (not path.isabs(self.env_confdir)
+                        or not path.isdir(self.env_confdir)):
+                    raise ScriptError(
+                        "IPA_CONFDIR env var must be an absolute path to an "
+                        "existing directory, got '{}'.".format(
+                            self.env_confdir))
+                self.confdir = self.env_confdir
+            elif self.in_tree:
                 self.confdir = self.dot_ipa
             else:
                 self.confdir = path.join('/', 'etc', 'ipa')
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index 503534f..142b3e6 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -713,6 +713,15 @@ def finalize(self):
         self.__doing('finalize')
         self.__do_if_not_done('load_plugins')
 
+        if self.env.env_confdir is not None:
+            if self.env.env_confdir == self.env.confdir:
+                self.log.info(
+                    "IPA_CONFDIR env sets confdir to '%s'.", self.env.confdir)
+            else:
+                self.log.warn(
+                    "IPA_CONFDIR env is overridden by an explicit confdir "
+                    "argument.")
+
         for plugin in self.__plugins:
             if not self.env.validate_api:
                 if plugin.full_name not in DEFAULT_PLUGINS:
diff --git a/ipatests/test_ipalib/test_plugable.py b/ipatests/test_ipalib/test_plugable.py
index 1ee1102..ff22446 100644
--- a/ipatests/test_ipalib/test_plugable.py
+++ b/ipatests/test_ipalib/test_plugable.py
@@ -24,9 +24,13 @@
 # FIXME: Pylint errors
 # pylint: disable=no-member
 
+import os
+import textwrap
+
+from ipalib import plugable, errors, create_api
+from ipapython.admintool import ScriptError
 from ipatests.util import raises, read_only
-from ipatests.util import ClassChecker, create_test_api
-from ipalib import plugable, errors
+from ipatests.util import ClassChecker, create_test_api, TempHome
 
 import pytest
 
@@ -272,3 +276,35 @@ def test_load_plugins(self):
         assert o.isdone('load_plugins') is True
         e = raises(Exception, o.load_plugins)
         assert str(e) == 'API.load_plugins() already called'
+
+    def test_ipaconf_env(self):
+        ipa_confdir = os.environ.get('IPA_CONFDIR', None)
+        try:
+            with TempHome() as home:
+                defaultconf = home.join('default.conf')
+                with open(defaultconf, 'w') as f:
+                    f.write(textwrap.dedent("""
+                        [global]
+                        basedn = dc=ipa,dc=test
+                        realm = IPA.TEST
+                        domain = ipa.test
+                        """)
+                    )
+                os.environ['IPA_CONFDIR'] = home.path
+                api = create_api(mode='unit_test')
+                api.bootstrap()
+                api.finalize()
+                assert api.env.confdir == home.path
+                assert api.env.conf_default == defaultconf
+                assert api.env.realm == 'IPA.TEST'
+                assert api.env.domain == 'ipa.test'
+
+                os.environ['IPA_CONFDIR'] = home.join('invalid')
+                api = create_api(mode='unit_test')
+                with pytest.raises(ScriptError):
+                    api.bootstrap()
+        finally:
+            if ipa_confdir:
+                os.environ['IPA_CONFDIR'] = ipa_confdir
+            else:
+                os.environ.pop('IPA_CONFDIR')
diff --git a/ipatests/util.py b/ipatests/util.py
index 3f66b59..7b5e317 100644
--- a/ipatests/util.py
+++ b/ipatests/util.py
@@ -96,6 +96,12 @@ def join(self, *parts):
     def __del__(self):
         self.rmtree()
 
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.rmtree()
+
 
 class TempHome(TempDir):
     def __init__(self):

From 6d509a5c23df64415f9f59097adb1c14755e07c4 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Fri, 2 Dec 2016 13:16:13 +0100
Subject: [PATCH 2/2] Raise errors.EnvironmentError if IPA_CONFDIR var is
 incorrectly used

---
 ipalib/config.py   | 10 ++++++++--
 ipalib/errors.py   |  7 +++++++
 ipalib/plugable.py |  4 ----
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 9d87782..20591db 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -43,7 +43,7 @@
 from ipalib.base import check_name
 from ipalib.constants import CONFIG_SECTION
 from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
-from ipapython.admintool import ScriptError
+from ipalib import errors
 
 if six.PY3:
     unicode = str
@@ -462,11 +462,17 @@ def _bootstrap(self, **overrides):
 
         # Set confdir:
         self.env_confdir = os.environ.get('IPA_CONFDIR')
+
+        if 'confdir' in self and self.env_confdir is not None:
+            raise errors.EnvironmentError(
+                    "IPA_CONFDIR env cannot be set because explicit confdir "
+                    "is used")
+
         if 'confdir' not in self:
             if self.env_confdir is not None:
                 if (not path.isabs(self.env_confdir)
                         or not path.isdir(self.env_confdir)):
-                    raise ScriptError(
+                    raise errors.EnvironmentError(
                         "IPA_CONFDIR env var must be an absolute path to an "
                         "existing directory, got '{}'.".format(
                             self.env_confdir))
diff --git a/ipalib/errors.py b/ipalib/errors.py
index d1fe5f0..88707ac 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -445,6 +445,13 @@ class RefererError(PublicError):
     format = _('Missing or invalid HTTP Referer, %(referer)s')
 
 
+class EnvironmentError(PublicError):
+    """
+    **912** Raised when a command is called with invalid environment settings
+    """
+
+    errno = 912
+
 ##############################################################################
 # 1000 - 1999: Authentication errors
 class AuthenticationError(PublicError):
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index 142b3e6..1a9164f 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -717,10 +717,6 @@ def finalize(self):
             if self.env.env_confdir == self.env.confdir:
                 self.log.info(
                     "IPA_CONFDIR env sets confdir to '%s'.", self.env.confdir)
-            else:
-                self.log.warn(
-                    "IPA_CONFDIR env is overridden by an explicit confdir "
-                    "argument.")
 
         for plugin in self.__plugins:
             if not self.env.validate_api:
-- 
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