Add uninstallation support.
authorPatrick Uiterwijk <puiterwijk@redhat.com>
Wed, 4 Feb 2015 09:58:14 +0000 (10:58 +0100)
committerRob Crittenden <rcritten@redhat.com>
Thu, 26 Feb 2015 20:18:02 +0000 (15:18 -0500)
As part of this, made all plugins use a Installer baseclass.

https://fedorahosted.org/ipsilon/ticket/38

Signed-off-by: Patrick Uiterwijk <puiterwijk@redhat.com>
Reviewed-by: Rob Crittenden <rcritten@redhat.com>
15 files changed:
ipsilon/helpers/common.py
ipsilon/helpers/ipa.py
ipsilon/info/common.py
ipsilon/install/ipsilon-server-install
ipsilon/login/authfas.py
ipsilon/login/authform.py
ipsilon/login/authkrb.py
ipsilon/login/authldap.py
ipsilon/login/authpam.py
ipsilon/login/authtest.py
ipsilon/login/common.py
ipsilon/providers/common.py
ipsilon/providers/openidp.py
ipsilon/providers/personaidp.py
ipsilon/providers/saml2idp.py

index e2839bf..dcbde2b 100644 (file)
@@ -21,6 +21,22 @@ from ipsilon.util.plugin import PluginInstaller
 FACILITY = 'environment_helpers'
 
 
 FACILITY = 'environment_helpers'
 
 
+class EnvHelpersInstaller(object):
+    def __init__(self):
+        self.facility = FACILITY
+        self.ptype = 'helper'
+        self.name = None
+
+    def unconfigure(self, opts):
+        return
+
+    def install_args(self, group):
+        raise NotImplementedError
+
+    def configure_server(self, opts):
+        raise NotImplementedError
+
+
 class EnvHelpersInstall(object):
 
     def __init__(self):
 class EnvHelpersInstall(object):
 
     def __init__(self):
index 58a77df..9298c08 100644 (file)
@@ -22,6 +22,8 @@ import socket
 import subprocess
 import sys
 
 import subprocess
 import sys
 
+from ipsilon.helpers.common import EnvHelpersInstaller
+
 
 IPA_CONFIG_FILE = '/etc/ipa/default.conf'
 HTTPD_IPA_KEYTAB = '/etc/httpd/conf/ipa.keytab'
 
 IPA_CONFIG_FILE = '/etc/ipa/default.conf'
 HTTPD_IPA_KEYTAB = '/etc/httpd/conf/ipa.keytab'
@@ -42,9 +44,10 @@ failure (see logs) and retry.
 """
 
 
 """
 
 
-class Installer(object):
+class Installer(EnvHelpersInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'ipa'
         self.ptype = 'helper'
         self.logger = None
         self.name = 'ipa'
         self.ptype = 'helper'
         self.logger = None
index 0a5cb74..725f0fa 100644 (file)
@@ -94,6 +94,9 @@ class InfoProviderInstaller(object):
     def install_args(self, group):
         raise NotImplementedError
 
     def install_args(self, group):
         raise NotImplementedError
 
+    def unconfigure(self, opts):
+        return
+
     def configure(self, opts):
         raise NotImplementedError
 
     def configure(self, opts):
         raise NotImplementedError
 
index dfd2ffe..307f1e4 100755 (executable)
@@ -206,9 +206,59 @@ def install(plugins, args):
     except Exception:  # pylint: disable=broad-except
         pass
 
     except Exception:  # pylint: disable=broad-except
         pass
 
+
 def uninstall(plugins, args):
     logger.info('Uninstallation initiated')
 def uninstall(plugins, args):
     logger.info('Uninstallation initiated')
-    raise Exception('Not Implemented')
+    instance_conf = os.path.join(CONFDIR, args['instance'])
+
+    httpd_conf = os.path.join(HTTPDCONFD,
+                              'ipsilon-%s.conf' % args['instance'])
+    data_dir = os.path.join(DATADIR, args['instance'])
+
+    if not os.path.exists(instance_conf):
+        raise Exception('Could not find instance %s configuration'
+                        % args['instance'])
+    if not os.path.exists(httpd_conf):
+        raise Exception('Could not find instance %s httpd configuration'
+                        % args['instance'])
+    if not args['yes']:
+        sure = raw_input(('Are you certain you want to erase instance %s ' +
+                          '[yes/NO]: ')
+                         % args['instance'])
+        if sure != 'yes':
+            raise Exception('Aborting')
+
+    logger.info('Removing environment helpers')
+    for plugin_name in plugins['Environment Helpers']:
+        plugin = plugins['Environment Helpers'][plugin_name]
+        if plugin.unconfigure(args) == False:
+            print 'Removal of environment helper %s failed' % plugin_name
+
+    logger.info('Removing login managers')
+    for plugin_name in args['lm_order']:
+        plugin = plugins['Login Managers'][plugin_name]
+        if plugin.unconfigure(args) == False:
+            print 'Removal of login manager %s failed' % plugin_name
+
+    logger.info('Removing Info providers')
+    for plugin_name in plugins['Info Provider']:
+        plugin = plugins['Info Provider'][plugin_name]
+        if plugin.unconfigure(args) == False:
+            print 'Removal of info provider %s failed' % plugin_name
+
+    logger.info('Removing Authentication Providers')
+    for plugin_name in plugins['Auth Providers']:
+        plugin = plugins['Auth Providers'][plugin_name]
+        if plugin.unconfigure(args) == False:
+            print 'Removal of auth provider %s failed' % plugin_name
+
+    logger.info('Removing httpd configuration')
+    os.remove(httpd_conf)
+    logger.info('Erasing instance configuration')
+    shutil.rmtree(instance_conf)
+    logger.info('Erasing instance data')
+    shutil.rmtree(data_dir)
+    logger.info('Uninstalled instance %s' % args['instance'])
 
 
 def find_plugins():
 
 
 def find_plugins():
@@ -273,6 +323,8 @@ def parse_args(plugins):
                         help="Enable debugging")
     parser.add_argument('--uninstall', action='store_true',
                         help="Uninstall the server and all data")
                         help="Enable debugging")
     parser.add_argument('--uninstall', action='store_true',
                         help="Uninstall the server and all data")
+    parser.add_argument('--yes', action='store_true',
+                        help="Always answer yes")
 
     lms = []
 
 
     lms = []
 
@@ -335,9 +387,12 @@ if __name__ == '__main__':
             logger.info('%s: %s', k, opts[k])
 
         if 'uninstall' in opts and opts['uninstall'] is True:
             logger.info('%s: %s', k, opts[k])
 
         if 'uninstall' in opts and opts['uninstall'] is True:
+            if not os.path.exists(os.path.join(CONFDIR, opts['instance'])):
+                print 'Instance %s could not be found' % opts['instance']
+                sys.exit(0)
             uninstall(fplugins, opts)
             uninstall(fplugins, opts)
-
-        install(fplugins, opts)
+        else:
+            install(fplugins, opts)
     except Exception, e:  # pylint: disable=broad-except
         logger.exception(e)
         if 'uninstall' in opts and opts['uninstall'] is True:
     except Exception, e:  # pylint: disable=broad-except
         logger.exception(e)
         if 'uninstall' in opts and opts['uninstall'] is True:
index a44b470..46dd7b7 100644 (file)
@@ -1,7 +1,8 @@
 # Copyright (C) 2014 Ipsilon contributors, see COPYING file for license
 
 
 # Copyright (C) 2014 Ipsilon contributors, see COPYING file for license
 
 
-from ipsilon.login.common import LoginFormBase, LoginManagerBase
+from ipsilon.login.common import LoginFormBase, LoginManagerBase, \
+    LoginManagerInstaller
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.policy import Policy
 from ipsilon.util import config as pconfig
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.policy import Policy
 from ipsilon.util import config as pconfig
@@ -170,11 +171,11 @@ Form based login Manager that uses the Fedora Authentication Server
         return self.page
 
 
         return self.page
 
 
-class Installer(object):
+class Installer(LoginManagerInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'fas'
         self.name = 'fas'
-        self.ptype = 'login'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index 7d84a95..808c32c 100644 (file)
@@ -15,7 +15,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ipsilon.login.common import LoginFormBase, LoginManagerBase
+from ipsilon.login.common import LoginFormBase, LoginManagerBase, \
+    LoginManagerInstaller
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.user import UserSession
 from ipsilon.util import config as pconfig
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.user import UserSession
 from ipsilon.util import config as pconfig
@@ -100,11 +101,11 @@ LoadModule authnz_pam_module modules/mod_authnz_pam.so
 """
 
 
 """
 
 
-class Installer(object):
+class Installer(LoginManagerInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'form'
         self.name = 'form'
-        self.ptype = 'login'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index e352aa2..60eeb6b 100644 (file)
@@ -15,7 +15,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ipsilon.login.common import LoginPageBase, LoginManagerBase
+from ipsilon.login.common import LoginPageBase, LoginManagerBase, \
+    LoginManagerInstaller
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.user import UserSession
 from string import Template
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.user import UserSession
 from string import Template
@@ -113,11 +114,11 @@ CONF_TEMPLATE = """
 """
 
 
 """
 
 
-class Installer(object):
+class Installer(LoginManagerInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'krb'
         self.name = 'krb'
-        self.ptype = 'login'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index 8958410..0161abc 100644 (file)
@@ -1,6 +1,7 @@
 # Copyright (C) 2014  Ipsilon Contributors, see COPYING for license
 
 # Copyright (C) 2014  Ipsilon Contributors, see COPYING for license
 
-from ipsilon.login.common import LoginFormBase, LoginManagerBase
+from ipsilon.login.common import LoginFormBase, LoginManagerBase, \
+    LoginManagerInstaller
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.log import Log
 from ipsilon.util import config as pconfig
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util.log import Log
 from ipsilon.util import config as pconfig
@@ -163,11 +164,11 @@ authentication. """
         return self.page
 
 
         return self.page
 
 
-class Installer(object):
+class Installer(LoginManagerInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'ldap'
         self.name = 'ldap'
-        self.ptype = 'login'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index 1de8e0f..104dd4c 100644 (file)
@@ -15,7 +15,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ipsilon.login.common import LoginFormBase, LoginManagerBase
+from ipsilon.login.common import LoginFormBase, LoginManagerBase, \
+    LoginManagerInstaller
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util import config as pconfig
 import pam
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util import config as pconfig
 import pam
@@ -115,11 +116,11 @@ for authentication. """
         return self.page
 
 
         return self.page
 
 
-class Installer(object):
+class Installer(LoginManagerInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'pam'
         self.name = 'pam'
-        self.ptype = 'login'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index 39e0f39..6c11ba1 100644 (file)
@@ -15,7 +15,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ipsilon.login.common import LoginFormBase, LoginManagerBase
+from ipsilon.login.common import LoginFormBase, LoginManagerBase, \
+    LoginManagerInstaller
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util import config as pconfig
 import cherrypy
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util import config as pconfig
 import cherrypy
@@ -97,11 +98,11 @@ Form based TEST login Manager, DO NOT EVER ACTIVATE IN PRODUCTION """
         return self.page
 
 
         return self.page
 
 
-class Installer(object):
+class Installer(LoginManagerInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'testauth'
         self.name = 'testauth'
-        self.ptype = 'login'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index 3002d78..4b715f3 100644 (file)
@@ -292,6 +292,22 @@ class Cancel(Page):
             return op(*args, **kwargs)
 
 
             return op(*args, **kwargs)
 
 
+class LoginManagerInstaller(object):
+    def __init__(self):
+        self.facility = FACILITY
+        self.ptype = 'login'
+        self.name = None
+
+    def unconfigure(self, opts):
+        return
+
+    def install_args(self, group):
+        raise NotImplementedError
+
+    def configure(self, opts):
+        raise NotImplementedError
+
+
 class LoginMgrsInstall(object):
 
     def __init__(self):
 class LoginMgrsInstall(object):
 
     def __init__(self):
index dfa2627..4206387 100644 (file)
@@ -111,6 +111,22 @@ class ProviderPageBase(Page):
 FACILITY = 'provider_config'
 
 
 FACILITY = 'provider_config'
 
 
+class ProviderInstaller(object):
+    def __init__(self):
+        self.facility = FACILITY
+        self.ptype = 'provider'
+        self.name = None
+
+    def unconfigure(self, opts):
+        return
+
+    def install_args(self, group):
+        raise NotImplementedError
+
+    def configure(self, opts):
+        raise NotImplementedError
+
+
 class LoadProviders(Log):
 
     def __init__(self, root, site):
 class LoadProviders(Log):
 
     def __init__(self, root, site):
index 6bdf557..f79435f 100644 (file)
@@ -2,7 +2,7 @@
 
 from __future__ import absolute_import
 
 
 from __future__ import absolute_import
 
-from ipsilon.providers.common import ProviderBase
+from ipsilon.providers.common import ProviderBase, ProviderInstaller
 from ipsilon.providers.openid.store import OpenIDStore
 from ipsilon.providers.openid.auth import OpenID
 from ipsilon.providers.openid.extensions.common import LoadExtensions
 from ipsilon.providers.openid.store import OpenIDStore
 from ipsilon.providers.openid.auth import OpenID
 from ipsilon.providers.openid.extensions.common import LoadExtensions
@@ -131,11 +131,11 @@ Provides OpenID 2.0 authentication infrastructure. """
         self.extensions.enable(self._config['enabled extensions'].get_value())
 
 
         self.extensions.enable(self._config['enabled extensions'].get_value())
 
 
-class Installer(object):
+class Installer(ProviderInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'openid'
         self.name = 'openid'
-        self.ptype = 'provider'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index 0096c7a..74e19d3 100644 (file)
@@ -2,7 +2,7 @@
 
 from __future__ import absolute_import
 
 
 from __future__ import absolute_import
 
-from ipsilon.providers.common import ProviderBase
+from ipsilon.providers.common import ProviderBase, ProviderInstaller
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util import config as pconfig
 from ipsilon.info.common import InfoMapping
 from ipsilon.util.plugin import PluginObject
 from ipsilon.util import config as pconfig
 from ipsilon.info.common import InfoMapping
@@ -74,11 +74,11 @@ Provides Persona authentication infrastructure. """
         self.init_idp()
 
 
         self.init_idp()
 
 
-class Installer(object):
+class Installer(ProviderInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'persona'
         self.name = 'persona'
-        self.ptype = 'provider'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):
index 9fa2fd6..89e1346 100644 (file)
@@ -15,7 +15,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from ipsilon.providers.common import ProviderBase, ProviderPageBase
+from ipsilon.providers.common import ProviderBase, ProviderPageBase, \
+    ProviderInstaller
 from ipsilon.providers.saml2.auth import AuthenticateRequest
 from ipsilon.providers.saml2.logout import LogoutRequest
 from ipsilon.providers.saml2.admin import Saml2AdminPage
 from ipsilon.providers.saml2.auth import AuthenticateRequest
 from ipsilon.providers.saml2.logout import LogoutRequest
 from ipsilon.providers.saml2.admin import Saml2AdminPage
@@ -330,11 +331,11 @@ class IdpMetadataGenerator(object):
         return self.meta.output(path)
 
 
         return self.meta.output(path)
 
 
-class Installer(object):
+class Installer(ProviderInstaller):
 
     def __init__(self, *pargs):
 
     def __init__(self, *pargs):
+        super(Installer, self).__init__()
         self.name = 'saml2'
         self.name = 'saml2'
-        self.ptype = 'provider'
         self.pargs = pargs
 
     def install_args(self, group):
         self.pargs = pargs
 
     def install_args(self, group):