summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Cholasta <jcholast@redhat.com>2016-04-28 10:15:01 +0200
committerJan Cholasta <jcholast@redhat.com>2016-06-03 09:00:34 +0200
commit4c7be74526bd89ed1b481f3a1ac4bb467ee0ea2c (patch)
tree3db268df3cfa41bd8a3c4655967e6931428b1ba9
parent6cfb9d73d9701767d8b76d7ff5bbc080a6be9386 (diff)
downloadfreeipa-4c7be74526bd89ed1b481f3a1ac4bb467ee0ea2c.tar.gz
freeipa-4c7be74526bd89ed1b481f3a1ac4bb467ee0ea2c.tar.xz
freeipa-4c7be74526bd89ed1b481f3a1ac4bb467ee0ea2c.zip
ipalib: split off client-side plugin code into ipaclient
Provide client-side overrides for command plugins which implement any of the client-side `interactive_prompt_callback`, `forward` or `output_for_cli` methods and move the methods from the original plugins to the overrides. https://fedorahosted.org/freeipa/ticket/4739 Reviewed-By: David Kupka <dkupka@redhat.com>
-rw-r--r--ipaclient/plugins/automount.py53
-rw-r--r--ipaclient/plugins/cert.py43
-rw-r--r--ipaclient/plugins/certprofile.py28
-rw-r--r--ipaclient/plugins/dns.py325
-rw-r--r--ipaclient/plugins/hbacrule.py45
-rw-r--r--ipaclient/plugins/hbactest.py55
-rw-r--r--ipaclient/plugins/host.py49
-rw-r--r--ipaclient/plugins/idrange.py89
-rw-r--r--ipaclient/plugins/internal.py42
-rw-r--r--ipaclient/plugins/migration.py71
-rw-r--r--ipaclient/plugins/otptoken.py82
-rw-r--r--ipaclient/plugins/service.py51
-rw-r--r--ipaclient/plugins/sudorule.py57
-rw-r--r--ipaclient/plugins/topology.py54
-rw-r--r--ipaclient/plugins/trust.py51
-rw-r--r--ipaclient/plugins/user.py82
-rw-r--r--ipaclient/plugins/vault.py20
-rw-r--r--ipalib/plugins/automount.py48
-rw-r--r--ipalib/plugins/cert.py13
-rw-r--r--ipalib/plugins/certprofile.py16
-rw-r--r--ipalib/plugins/dns.py266
-rw-r--r--ipalib/plugins/hbacrule.py16
-rw-r--r--ipalib/plugins/hbactest.py25
-rw-r--r--ipalib/plugins/host.py19
-rw-r--r--ipalib/plugins/idrange.py62
-rw-r--r--ipalib/plugins/internal.py10
-rw-r--r--ipalib/plugins/migration.py38
-rw-r--r--ipalib/plugins/otptoken.py77
-rw-r--r--ipalib/plugins/service.py19
-rw-r--r--ipalib/plugins/sudorule.py22
-rw-r--r--ipalib/plugins/topology.py37
-rw-r--r--ipalib/plugins/trust.py24
-rw-r--r--ipalib/plugins/user.py42
-rw-r--r--ipalib/plugins/vault.py18
34 files changed, 1198 insertions, 751 deletions
diff --git a/ipaclient/plugins/automount.py b/ipaclient/plugins/automount.py
index 096315818..57a804446 100644
--- a/ipaclient/plugins/automount.py
+++ b/ipaclient/plugins/automount.py
@@ -22,11 +22,13 @@ import os
import six
+from ipaclient.frontend import MethodOverride
from ipalib import api, errors
from ipalib import Flag, Str
from ipalib.frontend import Command
from ipalib.plugable import Registry
from ipalib import _
+from ipapython.dn import DN
if six.PY3:
unicode = str
@@ -37,6 +39,57 @@ DEFAULT_MAPS = (u'auto.direct', )
DEFAULT_KEYS = (u'/-', )
+@register(override=True)
+class automountlocation_tofiles(MethodOverride):
+ def output_for_cli(self, textui, result, *keys, **options):
+ maps = result['result']['maps']
+ keys = result['result']['keys']
+ orphanmaps = result['result']['orphanmaps']
+ orphankeys = result['result']['orphankeys']
+
+ textui.print_plain('/etc/auto.master:')
+ for m in maps:
+ if m['automountinformation'][0].startswith('-'):
+ textui.print_plain(
+ '%s\t%s' % (
+ m['automountkey'][0], m['automountinformation'][0]
+ )
+ )
+ else:
+ textui.print_plain(
+ '%s\t/etc/%s' % (
+ m['automountkey'][0], m['automountinformation'][0]
+ )
+ )
+ for m in maps:
+ if m['automountinformation'][0].startswith('-'):
+ continue
+ info = m['automountinformation'][0]
+ textui.print_plain('---------------------------')
+ textui.print_plain('/etc/%s:' % info)
+ for k in keys[info]:
+ textui.print_plain(
+ '%s\t%s' % (
+ k['automountkey'][0], k['automountinformation'][0]
+ )
+ )
+
+ textui.print_plain('')
+ textui.print_plain(_('maps not connected to /etc/auto.master:'))
+ for m in orphanmaps:
+ textui.print_plain('---------------------------')
+ textui.print_plain('/etc/%s:' % m['automountmapname'])
+ for k in orphankeys:
+ if len(k) == 0: continue
+ dn = DN(k[0]['dn'])
+ if dn['automountmapname'] == m['automountmapname'][0]:
+ textui.print_plain(
+ '%s\t%s' % (
+ k[0]['automountkey'][0], k[0]['automountinformation'][0]
+ )
+ )
+
+
@register()
class automountlocation_import(Command):
__doc__ = _('Import automount files for a specific location.')
diff --git a/ipaclient/plugins/cert.py b/ipaclient/plugins/cert.py
new file mode 100644
index 000000000..722743e2f
--- /dev/null
+++ b/ipaclient/plugins/cert.py
@@ -0,0 +1,43 @@
+# Authors:
+# Andrew Wnuk <awnuk@redhat.com>
+# Jason Gerard DeRose <jderose@redhat.com>
+# John Dennis <jdennis@redhat.com>
+#
+# Copyright (C) 2009 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import CommandOverride
+from ipalib import errors
+from ipalib import x509
+from ipalib import util
+from ipalib.plugable import Registry
+
+register = Registry()
+
+
+@register(override=True)
+class cert_show(CommandOverride):
+ def forward(self, *keys, **options):
+ if 'out' in options:
+ util.check_writable_file(options['out'])
+ result = super(cert_show, self).forward(*keys, **options)
+ if 'certificate' in result['result']:
+ x509.write_certificate(result['result']['certificate'], options['out'])
+ return result
+ else:
+ raise errors.NoCertificateError(entry=keys[-1])
+ else:
+ return super(cert_show, self).forward(*keys, **options)
diff --git a/ipaclient/plugins/certprofile.py b/ipaclient/plugins/certprofile.py
new file mode 100644
index 000000000..4fe1026d0
--- /dev/null
+++ b/ipaclient/plugins/certprofile.py
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
+#
+
+from ipaclient.frontend import MethodOverride
+from ipalib import util
+from ipalib.plugable import Registry
+from ipalib.text import _
+
+register = Registry()
+
+
+@register(override=True)
+class certprofile_show(MethodOverride):
+ def forward(self, *keys, **options):
+ if 'out' in options:
+ util.check_writable_file(options['out'])
+
+ result = super(certprofile_show, self).forward(*keys, **options)
+ if 'out' in options and 'config' in result['result']:
+ with open(options['out'], 'wb') as f:
+ f.write(result['result'].pop('config'))
+ result['summary'] = (
+ _("Profile configuration stored in file '%(file)s'")
+ % dict(file=options['out'])
+ )
+
+ return result
diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py
new file mode 100644
index 000000000..6fca7cd24
--- /dev/null
+++ b/ipaclient/plugins/dns.py
@@ -0,0 +1,325 @@
+# Authors:
+# Martin Kosek <mkosek@redhat.com>
+# Pavel Zuna <pzuna@redhat.com>
+#
+# Copyright (C) 2010 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 __future__ import print_function
+
+import six
+
+from ipaclient.frontend import MethodOverride
+from ipalib import errors
+from ipalib.dns import (get_record_rrtype,
+ has_cli_options,
+ iterate_rrparams_by_parts,
+ record_name_format)
+from ipalib.plugable import Registry
+from ipalib import _, ngettext
+from ipapython.dnsutil import DNSName
+
+if six.PY3:
+ unicode = str
+
+register = Registry()
+
+# most used record types, always ask for those in interactive prompt
+_top_record_types = ('A', 'AAAA', )
+_rev_top_record_types = ('PTR', )
+_zone_top_record_types = ('NS', 'MX', 'LOC', )
+
+
+def __get_part_param(cmd, part, output_kw, default=None):
+ name = part.name
+ label = unicode(part.label)
+ optional = not part.required
+
+ output_kw[name] = cmd.prompt_param(part,
+ optional=optional,
+ label=label)
+
+
+def prompt_parts(rrtype, cmd, mod_dnsvalue=None):
+ mod_parts = None
+ if mod_dnsvalue is not None:
+ name = record_name_format % rrtype.lower()
+ mod_parts = cmd.api.Command.dnsrecord_split_parts(
+ name, mod_dnsvalue)['result']
+
+ user_options = {}
+ parts = [p for p in cmd.params() if 'dnsrecord_part' in p.flags]
+ if not parts:
+ return user_options
+
+ for part_id, part in enumerate(parts):
+ if mod_parts:
+ default = mod_parts[part_id]
+ else:
+ default = None
+
+ __get_part_param(cmd, part, user_options, default)
+
+ return user_options
+
+
+def prompt_missing_parts(rrtype, cmd, kw, prompt_optional=False):
+ user_options = {}
+ parts = [p for p in cmd.params() if 'dnsrecord_part' in p.flags]
+ if not parts:
+ return user_options
+
+ for part in parts:
+ name = part.name
+
+ if name in kw:
+ continue
+
+ optional = not part.required
+ if optional and not prompt_optional:
+ continue
+
+ default = part.get_default(**kw)
+ __get_part_param(cmd, part, user_options, default)
+
+ return user_options
+
+
+@register(override=True)
+class dnsrecord_add(MethodOverride):
+ no_option_msg = 'No options to add a specific record provided.\n' \
+ "Command help may be consulted for all supported record types."
+
+ def interactive_prompt_callback(self, kw):
+ try:
+ has_cli_options(self, kw, self.no_option_msg)
+
+ # Some DNS records were entered, do not use full interactive help
+ # We should still ask user for required parts of DNS parts he is
+ # trying to add in the same way we do for standard LDAP parameters
+ #
+ # Do not ask for required parts when any "extra" option is used,
+ # it can be used to fill all required params by itself
+ new_kw = {}
+ for rrparam in iterate_rrparams_by_parts(self, kw,
+ skip_extra=True):
+ rrtype = get_record_rrtype(rrparam.name)
+ user_options = prompt_missing_parts(rrtype, self, kw,
+ prompt_optional=False)
+ new_kw.update(user_options)
+ kw.update(new_kw)
+ return
+ except errors.OptionError:
+ pass
+
+ try:
+ idnsname = DNSName(kw['idnsname'])
+ except Exception as e:
+ raise errors.ValidationError(name='idnsname', error=unicode(e))
+
+ try:
+ zonename = DNSName(kw['dnszoneidnsname'])
+ except Exception as e:
+ raise errors.ValidationError(name='dnszoneidnsname', error=unicode(e))
+
+ # check zone type
+ if idnsname.is_empty():
+ common_types = u', '.join(_zone_top_record_types)
+ elif zonename.is_reverse():
+ common_types = u', '.join(_rev_top_record_types)
+ else:
+ common_types = u', '.join(_top_record_types)
+
+ self.Backend.textui.print_plain(_(u'Please choose a type of DNS resource record to be added'))
+ self.Backend.textui.print_plain(_(u'The most common types for this type of zone are: %s\n') %\
+ common_types)
+
+ ok = False
+ while not ok:
+ rrtype = self.Backend.textui.prompt(_(u'DNS resource record type'))
+
+ if rrtype is None:
+ return
+
+ try:
+ name = record_name_format % rrtype.lower()
+ param = self.params[name]
+
+ if 'no_option' in param.flags:
+ raise ValueError()
+ except (KeyError, ValueError):
+ all_types = u', '.join(get_record_rrtype(p.name)
+ for p in self.params()
+ if (get_record_rrtype(p.name) and
+ 'no_option' not in p.flags))
+ self.Backend.textui.print_plain(_(u'Invalid or unsupported type. Allowed values are: %s') % all_types)
+ continue
+ ok = True
+
+ user_options = prompt_parts(rrtype, self)
+ kw.update(user_options)
+
+
+@register(override=True)
+class dnsrecord_mod(MethodOverride):
+ no_option_msg = 'No options to modify a specific record provided.'
+
+ def interactive_prompt_callback(self, kw):
+ try:
+ has_cli_options(self, kw, self.no_option_msg, True)
+ except errors.OptionError:
+ pass
+ else:
+ # some record type entered, skip this helper
+ return
+
+ # get DNS record first so that the NotFound exception is raised
+ # before the helper would start
+ dns_record = self.api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result']
+
+ self.Backend.textui.print_plain(_("No option to modify specific record provided."))
+
+ # ask user for records to be removed
+ self.Backend.textui.print_plain(_(u'Current DNS record contents:\n'))
+ record_params = []
+
+ for attr in dns_record:
+ try:
+ param = self.params[attr]
+ except KeyError:
+ continue
+ rrtype = get_record_rrtype(param.name)
+ if not rrtype:
+ continue
+
+ record_params.append((param, rrtype))
+ rec_type_content = u', '.join(dns_record[param.name])
+ self.Backend.textui.print_plain(u'%s: %s' % (param.label, rec_type_content))
+ self.Backend.textui.print_plain(u'')
+
+ # ask what records to remove
+ for param, rrtype in record_params:
+ rec_values = list(dns_record[param.name])
+ for rec_value in dns_record[param.name]:
+ rec_values.remove(rec_value)
+ mod_value = self.Backend.textui.prompt_yesno(
+ _("Modify %(name)s '%(value)s'?") % dict(name=param.label, value=rec_value), default=False)
+ if mod_value is True:
+ user_options = prompt_parts(rrtype, self,
+ mod_dnsvalue=rec_value)
+ kw[param.name] = [rec_value]
+ kw.update(user_options)
+
+ if rec_values:
+ self.Backend.textui.print_plain(ngettext(
+ u'%(count)d %(type)s record skipped. Only one value per DNS record type can be modified at one time.',
+ u'%(count)d %(type)s records skipped. Only one value per DNS record type can be modified at one time.',
+ 0) % dict(count=len(rec_values), type=rrtype))
+ break
+
+
+@register(override=True)
+class dnsrecord_del(MethodOverride):
+ no_option_msg = _('Neither --del-all nor options to delete a specific record provided.\n'\
+ "Command help may be consulted for all supported record types.")
+
+ def interactive_prompt_callback(self, kw):
+ if kw.get('del_all', False):
+ return
+ try:
+ has_cli_options(self, kw, self.no_option_msg)
+ except errors.OptionError:
+ pass
+ else:
+ # some record type entered, skip this helper
+ return
+
+ # get DNS record first so that the NotFound exception is raised
+ # before the helper would start
+ dns_record = self.api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result']
+
+ self.Backend.textui.print_plain(_("No option to delete specific record provided."))
+ user_del_all = self.Backend.textui.prompt_yesno(_("Delete all?"), default=False)
+
+ if user_del_all is True:
+ kw['del_all'] = True
+ return
+
+ # ask user for records to be removed
+ self.Backend.textui.print_plain(_(u'Current DNS record contents:\n'))
+ present_params = []
+
+ for attr in dns_record:
+ try:
+ param = self.params[attr]
+ except KeyError:
+ continue
+ if not get_record_rrtype(param.name):
+ continue
+
+ present_params.append(param)
+ rec_type_content = u', '.join(dns_record[param.name])
+ self.Backend.textui.print_plain(u'%s: %s' % (param.label, rec_type_content))
+ self.Backend.textui.print_plain(u'')
+
+ # ask what records to remove
+ for param in present_params:
+ deleted_values = []
+ for rec_value in dns_record[param.name]:
+ user_del_value = self.Backend.textui.prompt_yesno(
+ _("Delete %(name)s '%(value)s'?")
+ % dict(name=param.label, value=rec_value), default=False)
+ if user_del_value is True:
+ deleted_values.append(rec_value)
+ if deleted_values:
+ kw[param.name] = tuple(deleted_values)
+
+
+@register(override=True)
+class dnsconfig_mod(MethodOverride):
+ def interactive_prompt_callback(self, kw):
+
+ # show informative message on client side
+ # server cannot send messages asynchronous
+ if kw.get('idnsforwarders', False):
+ self.Backend.textui.print_plain(
+ _("Server will check DNS forwarder(s)."))
+ self.Backend.textui.print_plain(
+ _("This may take some time, please wait ..."))
+
+
+@register(override=True)
+class dnsforwardzone_add(MethodOverride):
+ def interactive_prompt_callback(self, kw):
+ # show informative message on client side
+ # server cannot send messages asynchronous
+ if kw.get('idnsforwarders', False):
+ self.Backend.textui.print_plain(
+ _("Server will check DNS forwarder(s)."))
+ self.Backend.textui.print_plain(
+ _("This may take some time, please wait ..."))
+
+
+@register(override=True)
+class dnsforwardzone_mod(MethodOverride):
+ def interactive_prompt_callback(self, kw):
+ # show informative message on client side
+ # server cannot send messages asynchronous
+ if kw.get('idnsforwarders', False):
+ self.Backend.textui.print_plain(
+ _("Server will check DNS forwarder(s)."))
+ self.Backend.textui.print_plain(
+ _("This may take some time, please wait ..."))
diff --git a/ipaclient/plugins/hbacrule.py b/ipaclient/plugins/hbacrule.py
new file mode 100644
index 000000000..826ed7a88
--- /dev/null
+++ b/ipaclient/plugins/hbacrule.py
@@ -0,0 +1,45 @@
+# Authors:
+# Pavel Zuna <pzuna@redhat.com>
+#
+# Copyright (C) 2009 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import MethodOverride
+from ipalib.plugable import Registry
+
+register = Registry()
+
+
+#@register()
+class hbacrule_add_accesstime(MethodOverride):
+ def output_for_cli(self, textui, result, cn, **options):
+ textui.print_name(self.name)
+ textui.print_dashed(
+ 'Added access time "%s" to HBAC rule "%s"' % (
+ options['accesstime'], cn
+ )
+ )
+
+
+#@register()
+class hbacrule_remove_accesstime(MethodOverride):
+ def output_for_cli(self, textui, result, cn, **options):
+ textui.print_name(self.name)
+ textui.print_dashed(
+ 'Removed access time "%s" from HBAC rule "%s"' % (
+ options['accesstime'], cn
+ )
+ )
diff --git a/ipaclient/plugins/hbactest.py b/ipaclient/plugins/hbactest.py
new file mode 100644
index 000000000..10a640a5a
--- /dev/null
+++ b/ipaclient/plugins/hbactest.py
@@ -0,0 +1,55 @@
+# Authors:
+# Alexander Bokovoy <abokovoy@redhat.com>
+#
+# Copyright (C) 2011 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import CommandOverride
+from ipalib.plugable import Registry
+
+import six
+
+if six.PY3:
+ unicode = str
+
+register = Registry()
+
+
+@register(override=True)
+class hbactest(CommandOverride):
+ def output_for_cli(self, textui, output, *args, **options):
+ """
+ Command.output_for_cli() uses --all option to decide whether to print detailed output.
+ We use --detail to allow that, thus we need to redefine output_for_cli().
+ """
+ # Note that we don't actually use --detail below to see if details need
+ # to be printed as our execute() method will return None for corresponding
+ # entries and None entries will be skipped.
+ for o in self.output:
+ outp = self.output[o]
+ if 'no_display' in outp.flags:
+ continue
+ result = output[o]
+ if isinstance(result, (list, tuple)):
+ textui.print_attribute(unicode(outp.doc), result, '%s: %s', 1, True)
+ elif isinstance(result, (unicode, bool)):
+ if o == 'summary':
+ textui.print_summary(result)
+ else:
+ textui.print_indented(result)
+
+ # Propagate integer value for result. It will give proper command line result for scripts
+ return int(not output['value'])
diff --git a/ipaclient/plugins/host.py b/ipaclient/plugins/host.py
new file mode 100644
index 000000000..a346226b5
--- /dev/null
+++ b/ipaclient/plugins/host.py
@@ -0,0 +1,49 @@
+# Authors:
+# Rob Crittenden <rcritten@redhat.com>
+# Pavel Zuna <pzuna@redhat.com>
+#
+# Copyright (C) 2008 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import MethodOverride
+from ipalib import errors, util
+from ipalib.plugable import Registry
+from ipalib import _
+from ipalib import x509
+
+register = Registry()
+
+
+@register(override=True)
+class host_show(MethodOverride):
+ def forward(self, *keys, **options):
+ if 'out' in options:
+ util.check_writable_file(options['out'])
+ result = super(host_show, self).forward(*keys, **options)
+ if 'usercertificate' in result['result']:
+ x509.write_certificate_list(
+ result['result']['usercertificate'],
+ options['out']
+ )
+ result['summary'] = (
+ _('Certificate(s) stored in file \'%(file)s\'')
+ % dict(file=options['out'])
+ )
+ return result
+ else:
+ raise errors.NoCertificateError(entry=keys[-1])
+ else:
+ return super(host_show, self).forward(*keys, **options)
diff --git a/ipaclient/plugins/idrange.py b/ipaclient/plugins/idrange.py
new file mode 100644
index 000000000..83ad8fdcf
--- /dev/null
+++ b/ipaclient/plugins/idrange.py
@@ -0,0 +1,89 @@
+# Authors:
+# Sumit Bose <sbose@redhat.com>
+#
+# Copyright (C) 2012 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import MethodOverride
+from ipalib.plugable import Registry
+from ipalib import api
+
+register = Registry()
+
+
+@register(override=True)
+class idrange_add(MethodOverride):
+ def interactive_prompt_callback(self, kw):
+ """
+ Ensure that rid-base is prompted for when dom-sid is specified.
+
+ Also ensure that secondary-rid-base is prompted for when rid-base is
+ specified and vice versa, in case that dom-sid was not specified.
+
+ Also ensure that rid-base and secondary-rid-base is prompted for
+ if ipa-adtrust-install has been run on the system.
+ """
+
+ # dom-sid can be specified using dom-sid or dom-name options
+
+ # it can be also set using --setattr or --addattr, in these cases
+ # we will not prompt, but raise an ValidationError later
+
+ dom_sid_set = any(dom_id in kw for dom_id in
+ ('ipanttrusteddomainname', 'ipanttrusteddomainsid'))
+
+ rid_base = kw.get('ipabaserid', None)
+ secondary_rid_base = kw.get('ipasecondarybaserid', None)
+ range_type = kw.get('iparangetype', None)
+
+ def set_from_prompt(param):
+ value = self.prompt_param(self.params[param])
+ update = {param: value}
+ kw.update(update)
+
+ if dom_sid_set:
+ # This is a trusted range
+
+ # Prompt for RID base if domain SID / name was given
+ if rid_base is None and range_type != u'ipa-ad-trust-posix':
+ set_from_prompt('ipabaserid')
+
+ else:
+ # This is a local range
+ # Find out whether ipa-adtrust-install has been ran
+ adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
+
+ if adtrust_is_enabled:
+ # If ipa-adtrust-install has been ran, all local ranges
+ # require both RID base and secondary RID base
+
+ if rid_base is None:
+ set_from_prompt('ipabaserid')
+
+ if secondary_rid_base is None:
+ set_from_prompt('ipasecondarybaserid')
+
+ else:
+ # This is a local range on a server with no adtrust support
+
+ # Prompt for secondary RID base only if RID base was given
+ if rid_base is not None and secondary_rid_base is None:
+ set_from_prompt('ipasecondarybaserid')
+
+ # Symetrically, prompt for RID base if secondary RID base was
+ # given
+ if rid_base is None and secondary_rid_base is not None:
+ set_from_prompt('ipabaserid')
diff --git a/ipaclient/plugins/internal.py b/ipaclient/plugins/internal.py
new file mode 100644
index 000000000..65cbbe7a5
--- /dev/null
+++ b/ipaclient/plugins/internal.py
@@ -0,0 +1,42 @@
+# Authors:
+# Pavel Zuna <pzuna@redhat.com>
+# Adam Young <ayoung@redhat.com>
+# Endi S. Dewata <edewata@redhat.com>
+#
+# Copyright (c) 2010 Red Hat
+# See file 'copying' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 __future__ import print_function
+
+import json
+
+from ipaclient.frontend import CommandOverride
+from ipalib.util import json_serialize
+from ipalib.plugable import Registry
+
+register = Registry()
+
+
+@register(override=True)
+class json_metadata(CommandOverride):
+ def output_for_cli(self, textui, result, *args, **options):
+ print(json.dumps(result, default=json_serialize))
+
+
+@register(override=True)
+class i18n_messages(CommandOverride):
+ def output_for_cli(self, textui, result, *args, **options):
+ print(json.dumps(result, default=json_serialize))
diff --git a/ipaclient/plugins/migration.py b/ipaclient/plugins/migration.py
new file mode 100644
index 000000000..1a184b963
--- /dev/null
+++ b/ipaclient/plugins/migration.py
@@ -0,0 +1,71 @@
+# Authors:
+# Pavel Zuna <pzuna@redhat.com>
+#
+# Copyright (C) 2009 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import six
+
+from ipaclient.frontend import CommandOverride
+from ipalib.plugable import Registry
+from ipalib import _
+
+if six.PY3:
+ unicode = str
+
+register = Registry()
+
+
+@register(override=True)
+class migrate_ds(CommandOverride):
+ migrate_order = ('user', 'group')
+
+ migration_disabled_msg = _('''\
+Migration mode is disabled. Use \'ipa config-mod\' to enable it.''')
+
+ pwd_migration_msg = _('''\
+Passwords have been migrated in pre-hashed format.
+IPA is unable to generate Kerberos keys unless provided
+with clear text passwords. All migrated users need to
+login at https://your.domain/ipa/migration/ before they
+can use their Kerberos accounts.''')
+
+ def output_for_cli(self, textui, result, ldapuri, bindpw, **options):
+ textui.print_name(self.name)
+ if not result['enabled']:
+ textui.print_plain(self.migration_disabled_msg)
+ return 1
+ if not result['compat']:
+ textui.print_plain("The compat plug-in is enabled. This can increase the memory requirements during migration. Disable the compat plug-in with \'ipa-compat-manage disable\' or re-run this script with \'--with-compat\' option.")
+ return 1
+ any_migrated = any(result['result'].values())
+ textui.print_plain('Migrated:')
+ textui.print_entry1(
+ result['result'], attr_order=self.migrate_order,
+ one_value_per_line=False
+ )
+ for ldap_obj_name in self.migrate_order:
+ textui.print_plain('Failed %s:' % ldap_obj_name)
+ textui.print_entry1(
+ result['failed'][ldap_obj_name], attr_order=self.migrate_order,
+ one_value_per_line=True,
+ )
+ textui.print_plain('-' * len(self.name))
+ if not any_migrated:
+ textui.print_plain('No users/groups were migrated from %s' %
+ ldapuri)
+ return 1
+ textui.print_plain(unicode(self.pwd_migration_msg))
diff --git a/ipaclient/plugins/otptoken.py b/ipaclient/plugins/otptoken.py
index 66a457cde..3b393794c 100644
--- a/ipaclient/plugins/otptoken.py
+++ b/ipaclient/plugins/otptoken.py
@@ -17,14 +17,24 @@
# 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 __future__ import print_function
+import sys
+
+from ipaclient.frontend import MethodOverride
from ipalib import api, Str, Password, _
+from ipalib.messages import add_message, ResultFormattingError
from ipalib.plugable import Registry
from ipalib.frontend import Local
from ipaplatform.paths import paths
from ipapython.dn import DN
from ipapython.nsslib import NSSConnection
+from ipapython.version import API_VERSION
+
+import locale
+import qrcode
import six
+from six import StringIO
from six.moves import urllib
if six.PY3:
@@ -33,6 +43,78 @@ if six.PY3:
register = Registry()
+@register(override=True)
+class otptoken_add(MethodOverride):
+ def _get_qrcode(self, output, uri, version):
+ # Print QR code to terminal if specified
+ qr_output = StringIO()
+ qr = qrcode.QRCode()
+ qr.add_data(uri)
+ qr.make()
+ qr.print_ascii(out=qr_output, tty=False)
+
+ encoding = getattr(sys.stdout, 'encoding', None)
+ if encoding is None:
+ encoding = locale.getpreferredencoding(False)
+
+ try:
+ qr_code = qr_output.getvalue().decode(encoding)
+ except UnicodeError:
+ add_message(
+ version,
+ output,
+ message=ResultFormattingError(
+ message=_("Unable to display QR code using the configured "
+ "output encoding. Please use the token URI to "
+ "configure you OTP device")
+ )
+ )
+ return None
+
+ if sys.stdout.isatty():
+ output_width = self.api.Backend.textui.get_tty_width()
+ qr_code_width = len(qr_code.splitlines()[0])
+ if qr_code_width > output_width:
+ add_message(
+ version,
+ output,
+ message=ResultFormattingError(
+ message=_(
+ "QR code width is greater than that of the output "
+ "tty. Please resize your terminal.")
+ )
+ )
+
+ return qr
+
+ def output_for_cli(self, textui, output, *args, **options):
+ # copy-pasted from ipalib/Frontend.__do_call()
+ # because option handling is broken on client-side
+ if 'version' in options:
+ pass
+ elif self.api.env.skip_version_check:
+ options['version'] = u'2.0'
+ else:
+ options['version'] = API_VERSION
+
+ uri = output['result'].get('uri', None)
+
+ if uri is not None and not options.get('no_qrcode', False):
+ qr = self._get_qrcode(output, uri, options['version'])
+ else:
+ qr = None
+
+ rv = super(otptoken_add, self).output_for_cli(
+ textui, output, *args, **options)
+
+ if qr is not None:
+ print("\n")
+ qr.print_ascii(tty=sys.stdout.isatty())
+ print("\n")
+
+ return rv
+
+
class HTTPSHandler(urllib.request.HTTPSHandler):
"Opens SSL HTTPS connections that perform hostname validation."
diff --git a/ipaclient/plugins/service.py b/ipaclient/plugins/service.py
new file mode 100644
index 000000000..72783b617
--- /dev/null
+++ b/ipaclient/plugins/service.py
@@ -0,0 +1,51 @@
+# Authors:
+# Jason Gerard DeRose <jderose@redhat.com>
+# Rob Crittenden <rcritten@redhat.com>
+# Pavel Zuna <pzuna@redhat.com>
+#
+# Copyright (C) 2008 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import MethodOverride
+from ipalib import errors
+from ipalib.plugable import Registry
+from ipalib import x509
+from ipalib import _
+from ipalib import util
+
+register = Registry()
+
+
+@register(override=True)
+class service_show(MethodOverride):
+ def forward(self, *keys, **options):
+ if 'out' in options:
+ util.check_writable_file(options['out'])
+ result = super(service_show, self).forward(*keys, **options)
+ if 'usercertificate' in result['result']:
+ x509.write_certificate_list(
+ result['result']['usercertificate'],
+ options['out']
+ )
+ result['summary'] = (
+ _('Certificate(s) stored in file \'%(file)s\'')
+ % dict(file=options['out'])
+ )
+ return result
+ else:
+ raise errors.NoCertificateError(entry=keys[-1])
+ else:
+ return super(service_show, self).forward(*keys, **options)
diff --git a/ipaclient/plugins/sudorule.py b/ipaclient/plugins/sudorule.py
new file mode 100644
index 000000000..4098eb809
--- /dev/null
+++ b/ipaclient/plugins/sudorule.py
@@ -0,0 +1,57 @@
+# Authors:
+# Jr Aquino <jr.aquino@citrixonline.com>
+#
+# Copyright (C) 2010-2014 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import MethodOverride
+from ipalib.plugable import Registry
+from ipalib import _
+
+register = Registry()
+
+
+@register(override=True)
+class sudorule_enable(MethodOverride):
+ def output_for_cli(self, textui, result, cn, **options):
+ textui.print_dashed(_('Enabled Sudo Rule "%s"') % cn)
+
+
+@register(override=True)
+class sudorule_disable(MethodOverride):
+ def output_for_cli(self, textui, result, cn, **options):
+ textui.print_dashed(_('Disabled Sudo Rule "%s"') % cn)
+
+
+@register(override=True)
+class sudorule_add_option(MethodOverride):
+ def output_for_cli(self, textui, result, cn, **options):
+ textui.print_dashed(
+ _('Added option "%(option)s" to Sudo Rule "%(rule)s"')
+ % dict(option=options['ipasudoopt'], rule=cn))
+
+ super(sudorule_add_option, self).output_for_cli(textui, result, cn,
+ **options)
+
+
+@register(override=True)
+class sudorule_remove_option(MethodOverride):
+ def output_for_cli(self, textui, result, cn, **options):
+ textui.print_dashed(
+ _('Removed option "%(option)s" from Sudo Rule "%(rule)s"')
+ % dict(option=options['ipasudoopt'], rule=cn))
+ super(sudorule_remove_option, self).output_for_cli(textui, result, cn,
+ **options)
diff --git a/ipaclient/plugins/topology.py b/ipaclient/plugins/topology.py
new file mode 100644
index 000000000..522dcfa9a
--- /dev/null
+++ b/ipaclient/plugins/topology.py
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
+#
+
+import six
+
+from ipaclient.frontend import MethodOverride
+from ipalib.plugable import Registry
+from ipalib import _
+
+if six.PY3:
+ unicode = str
+
+register = Registry()
+
+
+@register(override=True)
+class topologysuffix_verify(MethodOverride):
+ def output_for_cli(self, textui, output, *args, **options):
+
+ in_order = output['result']['in_order']
+ connect_errors = output['result']['connect_errors']
+ max_agmts_errors = output['result']['max_agmts_errors']
+
+ if in_order:
+ header = _('Replication topology of suffix "%(suffix)s" '
+ 'is in order.')
+ else:
+ header = _('Replication topology of suffix "%(suffix)s" contains '
+ 'errors.')
+ textui.print_h1(header % {'suffix': args[0]})
+
+ if connect_errors:
+ textui.print_dashed(unicode(_('Topology is disconnected')))
+ for err in connect_errors:
+ msg = _("Server %(srv)s can't contact servers: %(replicas)s")
+ msg = msg % {'srv': err[0], 'replicas': ', '.join(err[2])}
+ textui.print_indented(msg)
+
+ if max_agmts_errors:
+ textui.print_dashed(unicode(_('Recommended maximum number of '
+ 'agreements per replica exceeded')))
+ textui.print_attribute(
+ unicode(_("Maximum number of agreements per replica")),
+ [output['result']['max_agmts']]
+ )
+ for err in max_agmts_errors:
+ msg = _('Server "%(srv)s" has %(n)d agreements with servers:')
+ msg = msg % {'srv': err[0], 'n': len(err[1])}
+ textui.print_indented(msg)
+ for replica in err[1]:
+ textui.print_indented(replica, 2)
+
+ return 0
diff --git a/ipaclient/plugins/trust.py b/ipaclient/plugins/trust.py
new file mode 100644
index 000000000..004c870c3
--- /dev/null
+++ b/ipaclient/plugins/trust.py
@@ -0,0 +1,51 @@
+# Authors:
+# Alexander Bokovoy <abokovoy@redhat.com>
+# Martin Kosek <mkosek@redhat.com>
+#
+# Copyright (C) 2011 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import MethodOverride
+from ipalib.plugable import Registry
+
+register = Registry()
+
+
+@register(override=True)
+class trust_add(MethodOverride):
+ def interactive_prompt_callback(self, kw):
+ """
+ Also ensure that realm_admin is prompted for if --admin or
+ --trust-secret is not specified when 'ipa trust-add' is run on the
+ system.
+
+ Also ensure that realm_passwd is prompted for if --password or
+ --trust-secret is not specified when 'ipa trust-add' is run on the
+ system.
+ """
+
+ trust_secret = kw.get('trust_secret')
+ realm_admin = kw.get('realm_admin')
+ realm_passwd = kw.get('realm_passwd')
+
+ if trust_secret is None:
+ if realm_admin is None:
+ kw['realm_admin'] = self.prompt_param(
+ self.params['realm_admin'])
+
+ if realm_passwd is None:
+ kw['realm_passwd'] = self.Backend.textui.prompt_password(
+ self.params['realm_passwd'].label, confirm=False)
diff --git a/ipaclient/plugins/user.py b/ipaclient/plugins/user.py
new file mode 100644
index 000000000..ccff9bbbc
--- /dev/null
+++ b/ipaclient/plugins/user.py
@@ -0,0 +1,82 @@
+# Authors:
+# Jason Gerard DeRose <jderose@redhat.com>
+# Pavel Zuna <pzuna@redhat.com>
+#
+# Copyright (C) 2008 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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 ipaclient.frontend import MethodOverride
+from ipalib import errors
+from ipalib import Flag
+from ipalib import util
+from ipalib.plugable import Registry
+from ipalib import _
+from ipalib import x509
+
+register = Registry()
+
+
+@register(override=True)
+class user_del(MethodOverride):
+ def get_options(self):
+ for option in super(user_del, self).get_options():
+ yield option
+ yield Flag(
+ 'preserve?',
+ include='cli',
+ doc=_('Delete a user, keeping the entry available for future use'),
+ )
+ yield Flag(
+ 'no_preserve?',
+ include='cli',
+ doc=_('Delete a user'),
+ )
+
+ def forward(self, *keys, **options):
+ if self.api.env.context == 'cli':
+ no_preserve = options.pop('no_preserve', False)
+ preserve = options.pop('preserve', False)
+ if no_preserve and preserve:
+ raise errors.MutuallyExclusiveError(
+ reason=_("preserve and no-preserve cannot be both set"))
+ elif no_preserve:
+ options['preserve'] = False
+ elif preserve:
+ options['preserve'] = True
+
+ return super(user_del, self).forward(*keys, **options)
+
+
+@register(override=True)
+class user_show(MethodOverride):
+ def forward(self, *keys, **options):
+ if 'out' in options:
+ util.check_writable_file(options['out'])
+ result = super(user_show, self).forward(*keys, **options)
+ if 'usercertificate' in result['result']:
+ x509.write_certificate_list(
+ result['result']['usercertificate'],
+ options['out']
+ )
+ result['summary'] = (
+ _('Certificate(s) stored in file \'%(file)s\'')
+ % dict(file=options['out'])
+ )
+ return result
+ else:
+ raise errors.NoCertificateError(entry=keys[-1])
+ else:
+ return super(user_show, self).forward(*keys, **options)
diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py
index ca132e8e6..945f390c0 100644
--- a/ipaclient/plugins/vault.py
+++ b/ipaclient/plugins/vault.py
@@ -36,6 +36,7 @@ from cryptography.hazmat.primitives.serialization import load_pem_public_key,\
import nss.nss as nss
+from ipaclient.frontend import MethodOverride
from ipalib.frontend import Local
from ipalib import errors
from ipalib import Bytes, Flag, Str
@@ -492,6 +493,25 @@ class vault_mod(Local):
return response
+@register(override=True)
+class vaultconfig_show(MethodOverride):
+ def forward(self, *args, **options):
+
+ file = options.get('transport_out')
+
+ # don't send these parameters to server
+ if 'transport_out' in options:
+ del options['transport_out']
+
+ response = super(vaultconfig_show, self).forward(*args, **options)
+
+ if file:
+ with open(file, 'w') as f:
+ f.write(response['result']['transport_cert'])
+
+ return response
+
+
@register()
class vault_archive(Local):
__doc__ = _('Archive data into a vault.')
diff --git a/ipalib/plugins/automount.py b/ipalib/plugins/automount.py
index 0e0df9414..c4cf2d6db 100644
--- a/ipalib/plugins/automount.py
+++ b/ipalib/plugins/automount.py
@@ -338,54 +338,6 @@ class automountlocation_tofiles(LDAPQuery):
return dict(result=dict(maps=maps, keys=keys,
orphanmaps=orphanmaps, orphankeys=orphankeys))
- def output_for_cli(self, textui, result, *keys, **options):
- maps = result['result']['maps']
- keys = result['result']['keys']
- orphanmaps = result['result']['orphanmaps']
- orphankeys = result['result']['orphankeys']
-
- textui.print_plain('/etc/auto.master:')
- for m in maps:
- if m['automountinformation'][0].startswith('-'):
- textui.print_plain(
- '%s\t%s' % (
- m['automountkey'][0], m['automountinformation'][0]
- )
- )
- else:
- textui.print_plain(
- '%s\t/etc/%s' % (
- m['automountkey'][0], m['automountinformation'][0]
- )
- )
- for m in maps:
- if m['automountinformation'][0].startswith('-'):
- continue
- info = m['automountinformation'][0]
- textui.print_plain('---------------------------')
- textui.print_plain('/etc/%s:' % info)
- for k in keys[info]:
- textui.print_plain(
- '%s\t%s' % (
- k['automountkey'][0], k['automountinformation'][0]
- )
- )
-
- textui.print_plain('')
- textui.print_plain(_('maps not connected to /etc/auto.master:'))
- for m in orphanmaps:
- textui.print_plain('---------------------------')
- textui.print_plain('/etc/%s:' % m['automountmapname'])
- for k in orphankeys:
- if len(k) == 0: continue
- dn = DN(k[0]['dn'])
- if dn['automountmapname'] == m['automountmapname'][0]:
- textui.print_plain(
- '%s\t%s' % (
- k[0]['automountkey'][0], k[0]['automountinformation'][0]
- )
- )
-
@register()
class automountmap(LDAPObject):
diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py
index 816d84e8b..57894f5d0 100644
--- a/ipalib/plugins/cert.py
+++ b/ipalib/plugins/cert.py
@@ -28,7 +28,6 @@ from ipalib import api
from ipalib import errors
from ipalib import pkcs10
from ipalib import x509
-from ipalib import util
from ipalib import ngettext
from ipalib.plugable import Registry
from .virtual import VirtualCommand
@@ -633,18 +632,6 @@ class cert_show(VirtualCommand):
return dict(result=result)
- def forward(self, *keys, **options):
- if 'out' in options:
- util.check_writable_file(options['out'])
- result = super(cert_show, self).forward(*keys, **options)
- if 'certificate' in result['result']:
- x509.write_certificate(result['result']['certificate'], options['out'])
- return result
- else:
- raise errors.NoCertificateError(entry=keys[-1])
- else:
- return super(cert_show, self).forward(*keys, **options)
-
diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py
index 3544ea8e3..022431c44 100644
--- a/ipalib/plugins/certprofile.py
+++ b/ipalib/plugins/certprofile.py
@@ -5,7 +5,6 @@
import re
from ipalib import api, Bool, File, Str
-from ipalib import util
from ipalib.plugable import Registry
from .baseldap import (
LDAPObject, LDAPSearch, LDAPCreate,
@@ -218,21 +217,6 @@ class certprofile_show(LDAPRetrieve):
return result
- def forward(self, *keys, **options):
- if 'out' in options:
- util.check_writable_file(options['out'])
-
- result = super(certprofile_show, self).forward(*keys, **options)
- if 'out' in options and 'config' in result['result']:
- with open(options['out'], 'wb') as f:
- f.write(result['result'].pop('config'))
- result['summary'] = (
- _("Profile configuration stored in file '%(file)s'")
- % dict(file=options['out'])
- )
-
- return result
-
@register()
class certprofile_import(LDAPCreate):
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index 3a3846d48..b67642270 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -19,7 +19,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
-from __future__ import print_function
import netaddr
import time
@@ -56,7 +55,7 @@ from .baseldap import (
LDAPQuery,
LDAPDelete,
LDAPRetrieve)
-from ipalib import _, ngettext
+from ipalib import _
from ipalib import messages
from ipalib.util import (normalize_zonemgr,
get_dns_forward_zone_update_policy,
@@ -313,11 +312,6 @@ _record_types = (
# DNS zone record identificator
_dns_zone_record = DNSName.empty
-# most used record types, always ask for those in interactive prompt
-_top_record_types = ('A', 'AAAA', )
-_rev_top_record_types = ('PTR', )
-_zone_top_record_types = ('NS', 'MX', 'LOC', )
-
# attributes derived from record types
_record_attributes = [str(record_name_format % t.lower())
for t in _record_types]
@@ -673,61 +667,6 @@ def _check_DN_objectclass(ldap, dn, objectclasses):
return _check_entry_objectclass(entry, objectclasses)
-def __get_part_param(cmd, part, output_kw, default=None):
- name = part.name
- label = unicode(part.label)
- optional = not part.required
-
- output_kw[name] = cmd.prompt_param(part,
- optional=optional,
- label=label)
-
-
-def prompt_parts(rrtype, cmd, mod_dnsvalue=None):
- mod_parts = None
- if mod_dnsvalue is not None:
- name = record_name_format % rrtype.lower()
- mod_parts = cmd.api.Command.dnsrecord_split_parts(
- name, mod_dnsvalue)['result']
-
- user_options = {}
- parts = [p for p in cmd.params() if 'dnsrecord_part' in p.flags]
- if not parts:
- return user_options
-
- for part_id, part in enumerate(parts):
- if mod_parts:
- default = mod_parts[part_id]
- else:
- default = None
-
- __get_part_param(cmd, part, user_options, default)
-
- return user_options
-
-
-def prompt_missing_parts(rrtype, cmd, kw, prompt_optional=False):
- user_options = {}
- parts = [p for p in cmd.params() if 'dnsrecord_part' in p.flags]
- if not parts:
- return user_options
-
- for part in parts:
- name = part.name
-
- if name in kw:
- continue
-
- optional = not part.required
- if optional and not prompt_optional:
- continue
-
- default = part.get_default(**kw)
- __get_part_param(cmd, part, user_options, default)
-
- return user_options
-
-
class DNSRecord(Str):
# a list of parts that create the actual raw DNS record
parts = None
@@ -3575,75 +3514,6 @@ class dnsrecord_add(LDAPCreate):
has_cli_options(self, options, self.no_option_msg)
return super(dnsrecord_add, self).args_options_2_entry(*keys, **options)
- def interactive_prompt_callback(self, kw):
- try:
- has_cli_options(self, kw, self.no_option_msg)
-
- # Some DNS records were entered, do not use full interactive help
- # We should still ask user for required parts of DNS parts he is
- # trying to add in the same way we do for standard LDAP parameters
- #
- # Do not ask for required parts when any "extra" option is used,
- # it can be used to fill all required params by itself
- new_kw = {}
- for rrparam in iterate_rrparams_by_parts(self, kw,
- skip_extra=True):
- rrtype = get_record_rrtype(rrparam.name)
- user_options = prompt_missing_parts(rrtype, self, kw,
- prompt_optional=False)
- new_kw.update(user_options)
- kw.update(new_kw)
- return
- except errors.OptionError:
- pass
-
- try:
- idnsname = DNSName(kw['idnsname'])
- except Exception as e:
- raise errors.ValidationError(name='idnsname', error=unicode(e))
-
- try:
- zonename = DNSName(kw['dnszoneidnsname'])
- except Exception as e:
- raise errors.ValidationError(name='dnszoneidnsname', error=unicode(e))
-
- # check zone type
- if idnsname.is_empty():
- common_types = u', '.join(_zone_top_record_types)
- elif zonename.is_reverse():
- common_types = u', '.join(_rev_top_record_types)
- else:
- common_types = u', '.join(_top_record_types)
-
- self.Backend.textui.print_plain(_(u'Please choose a type of DNS resource record to be added'))
- self.Backend.textui.print_plain(_(u'The most common types for this type of zone are: %s\n') %\
- common_types)
-
- ok = False
- while not ok:
- rrtype = self.Backend.textui.prompt(_(u'DNS resource record type'))
-
- if rrtype is None:
- return
-
- try:
- name = record_name_format % rrtype.lower()
- param = self.params[name]
-
- if 'no_option' in param.flags:
- raise ValueError()
- except (KeyError, ValueError):
- all_types = u', '.join(get_record_rrtype(p.name)
- for p in self.params()
- if (get_record_rrtype(p.name) and
- 'no_option' not in p.flags))
- self.Backend.textui.print_plain(_(u'Invalid or unsupported type. Allowed values are: %s') % all_types)
- continue
- ok = True
-
- user_options = prompt_parts(rrtype, self)
- kw.update(user_options)
-
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
precallback_attrs = []
@@ -3898,60 +3768,6 @@ class dnsrecord_mod(LDAPUpdate):
self.obj.postprocess_record(entry_attrs, **options)
return dn
- def interactive_prompt_callback(self, kw):
- try:
- has_cli_options(self, kw, self.no_option_msg, True)
- except errors.OptionError:
- pass
- else:
- # some record type entered, skip this helper
- return
-
- # get DNS record first so that the NotFound exception is raised
- # before the helper would start
- dns_record = self.api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result']
-
- self.Backend.textui.print_plain(_("No option to modify specific record provided."))
-
- # ask user for records to be removed
- self.Backend.textui.print_plain(_(u'Current DNS record contents:\n'))
- record_params = []
-
- for attr in dns_record:
- try:
- param = self.params[attr]
- except KeyError:
- continue
- rrtype = get_record_rrtype(param.name)
- if not rrtype:
- continue
-
- record_params.append((param, rrtype))
- rec_type_content = u', '.join(dns_record[param.name])
- self.Backend.textui.print_plain(u'%s: %s' % (param.label, rec_type_content))
- self.Backend.textui.print_plain(u'')
-
- # ask what records to remove
- for param, rrtype in record_params:
- rec_values = list(dns_record[param.name])
- for rec_value in dns_record[param.name]:
- rec_values.remove(rec_value)
- mod_value = self.Backend.textui.prompt_yesno(
- _("Modify %(name)s '%(value)s'?") % dict(name=param.label, value=rec_value), default=False)
- if mod_value is True:
- user_options = prompt_parts(rrtype, self,
- mod_dnsvalue=rec_value)
- kw[param.name] = [rec_value]
- kw.update(user_options)
-
- if rec_values:
- self.Backend.textui.print_plain(ngettext(
- u'%(count)d %(type)s record skipped. Only one value per DNS record type can be modified at one time.',
- u'%(count)d %(type)s records skipped. Only one value per DNS record type can be modified at one time.',
- 0) % dict(count=len(rec_values), type=rrtype))
- break
-
-
@register()
class dnsrecord_delentry(LDAPDelete):
@@ -4085,58 +3901,6 @@ class dnsrecord_del(LDAPUpdate):
has_cli_options(self, options, self.no_option_msg)
return super(dnsrecord_del, self).args_options_2_entry(*keys, **options)
- def interactive_prompt_callback(self, kw):
- if kw.get('del_all', False):
- return
- try:
- has_cli_options(self, kw, self.no_option_msg)
- except errors.OptionError:
- pass
- else:
- # some record type entered, skip this helper
- return
-
- # get DNS record first so that the NotFound exception is raised
- # before the helper would start
- dns_record = self.api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result']
-
- self.Backend.textui.print_plain(_("No option to delete specific record provided."))
- user_del_all = self.Backend.textui.prompt_yesno(_("Delete all?"), default=False)
-
- if user_del_all is True:
- kw['del_all'] = True
- return
-
- # ask user for records to be removed
- self.Backend.textui.print_plain(_(u'Current DNS record contents:\n'))
- present_params = []
-
- for attr in dns_record:
- try:
- param = self.params[attr]
- except KeyError:
- continue
- if not get_record_rrtype(param.name):
- continue
-
- present_params.append(param)
- rec_type_content = u', '.join(dns_record[param.name])
- self.Backend.textui.print_plain(u'%s: %s' % (param.label, rec_type_content))
- self.Backend.textui.print_plain(u'')
-
- # ask what records to remove
- for param in present_params:
- deleted_values = []
- for rec_value in dns_record[param.name]:
- user_del_value = self.Backend.textui.prompt_yesno(
- _("Delete %(name)s '%(value)s'?")
- % dict(name=param.label, value=rec_value), default=False)
- if user_del_value is True:
- deleted_values.append(rec_value)
- if deleted_values:
- kw[param.name] = tuple(deleted_values)
-
-
@register()
class dnsrecord_show(LDAPRetrieve):
@@ -4354,16 +4118,6 @@ class dnsconfig_mod(LDAPUpdate):
option = option.clone(include=('installer', 'updates'))
yield option
- def interactive_prompt_callback(self, kw):
-
- # show informative message on client side
- # server cannot send messages asynchronous
- if kw.get('idnsforwarders', False):
- self.Backend.textui.print_plain(
- _("Server will check DNS forwarder(s)."))
- self.Backend.textui.print_plain(
- _("This may take some time, please wait ..."))
-
def execute(self, *keys, **options):
# test dnssec forwarders
forwarders = options.get('idnsforwarders')
@@ -4524,15 +4278,6 @@ class dnsforwardzone(DNSZoneBase):
class dnsforwardzone_add(DNSZoneBase_add):
__doc__ = _('Create new DNS forward zone.')
- def interactive_prompt_callback(self, kw):
- # show informative message on client side
- # server cannot send messages asynchronous
- if kw.get('idnsforwarders', False):
- self.Backend.textui.print_plain(
- _("Server will check DNS forwarder(s)."))
- self.Backend.textui.print_plain(
- _("This may take some time, please wait ..."))
-
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
@@ -4571,15 +4316,6 @@ class dnsforwardzone_del(DNSZoneBase_del):
class dnsforwardzone_mod(DNSZoneBase_mod):
__doc__ = _('Modify DNS forward zone.')
- def interactive_prompt_callback(self, kw):
- # show informative message on client side
- # server cannot send messages asynchronous
- if kw.get('idnsforwarders', False):
- self.Backend.textui.print_plain(
- _("Server will check DNS forwarder(s)."))
- self.Backend.textui.print_plain(
- _("This may take some time, please wait ..."))
-
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
try:
entry = ldap.get_entry(dn)
diff --git a/ipalib/plugins/hbacrule.py b/ipalib/plugins/hbacrule.py
index 96015ab65..e0301239f 100644
--- a/ipalib/plugins/hbacrule.py
+++ b/ipalib/plugins/hbacrule.py
@@ -441,14 +441,6 @@ class hbacrule_add_accesstime(LDAPQuery):
return dict(result=True)
- def output_for_cli(self, textui, result, cn, **options):
- textui.print_name(self.name)
- textui.print_dashed(
- 'Added access time "%s" to HBAC rule "%s"' % (
- options['accesstime'], cn
- )
- )
-
# @register()
class hbacrule_remove_accesstime(LDAPQuery):
@@ -480,14 +472,6 @@ class hbacrule_remove_accesstime(LDAPQuery):
return dict(result=True)
- def output_for_cli(self, textui, result, cn, **options):
- textui.print_name(self.name)
- textui.print_dashed(
- 'Removed access time "%s" from HBAC rule "%s"' % (
- options['accesstime'], cn
- )
- )
-
@register()
class hbacrule_add_user(LDAPAddMember):
diff --git a/ipalib/plugins/hbactest.py b/ipalib/plugins/hbactest.py
index 1522b9b31..2dbab510e 100644
--- a/ipalib/plugins/hbactest.py
+++ b/ipalib/plugins/hbactest.py
@@ -492,28 +492,3 @@ class hbactest(Command):
result['value'] = access_granted
return result
-
- def output_for_cli(self, textui, output, *args, **options):
- """
- Command.output_for_cli() uses --all option to decide whether to print detailed output.
- We use --detail to allow that, thus we need to redefine output_for_cli().
- """
- # Note that we don't actually use --detail below to see if details need
- # to be printed as our execute() method will return None for corresponding
- # entries and None entries will be skipped.
- for o in self.output:
- outp = self.output[o]
- if 'no_display' in outp.flags:
- continue
- result = output[o]
- if isinstance(result, (list, tuple)):
- textui.print_attribute(unicode(outp.doc), result, '%s: %s', 1, True)
- elif isinstance(result, (unicode, bool)):
- if o == 'summary':
- textui.print_summary(result)
- else:
- textui.print_indented(result)
-
- # Propagate integer value for result. It will give proper command line result for scripts
- return int(not output['value'])
-
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
index 4cd08ebb2..709b78d5b 100644
--- a/ipalib/plugins/host.py
+++ b/ipalib/plugins/host.py
@@ -1085,25 +1085,6 @@ class host_show(LDAPRetrieve):
return dn
- def forward(self, *keys, **options):
- if 'out' in options:
- util.check_writable_file(options['out'])
- result = super(host_show, self).forward(*keys, **options)
- if 'usercertificate' in result['result']:
- x509.write_certificate_list(
- result['result']['usercertificate'],
- options['out']
- )
- result['summary'] = (
- _('Certificate(s) stored in file \'%(file)s\'')
- % dict(file=options['out'])
- )
- return result
- else:
- raise errors.NoCertificateError(entry=keys[-1])
- else:
- return super(host_show, self).forward(*keys, **options)
-
@register()
class host_disable(LDAPQuery):
diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py
index 3947c640f..7e868c363 100644
--- a/ipalib/plugins/idrange.py
+++ b/ipalib/plugins/idrange.py
@@ -401,68 +401,6 @@ class idrange_add(LDAPCreate):
msg_summary = _('Added ID range "%(value)s"')
- def interactive_prompt_callback(self, kw):
- """
- Ensure that rid-base is prompted for when dom-sid is specified.
-
- Also ensure that secondary-rid-base is prompted for when rid-base is
- specified and vice versa, in case that dom-sid was not specified.
-
- Also ensure that rid-base and secondary-rid-base is prompted for
- if ipa-adtrust-install has been run on the system.
- """
-
- # dom-sid can be specified using dom-sid or dom-name options
-
- # it can be also set using --setattr or --addattr, in these cases
- # we will not prompt, but raise an ValidationError later
-
- dom_sid_set = any(dom_id in kw for dom_id in
- ('ipanttrusteddomainname', 'ipanttrusteddomainsid'))
-
- rid_base = kw.get('ipabaserid', None)
- secondary_rid_base = kw.get('ipasecondarybaserid', None)
- range_type = kw.get('iparangetype', None)
-
- def set_from_prompt(param):
- value = self.prompt_param(self.params[param])
- update = {param: value}
- kw.update(update)
-
- if dom_sid_set:
- # This is a trusted range
-
- # Prompt for RID base if domain SID / name was given
- if rid_base is None and range_type != u'ipa-ad-trust-posix':
- set_from_prompt('ipabaserid')
-
- else:
- # This is a local range
- # Find out whether ipa-adtrust-install has been ran
- adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result']
-
- if adtrust_is_enabled:
- # If ipa-adtrust-install has been ran, all local ranges
- # require both RID base and secondary RID base
-
- if rid_base is None:
- set_from_prompt('ipabaserid')
-
- if secondary_rid_base is None:
- set_from_prompt('ipasecondarybaserid')
-
- else:
- # This is a local range on a server with no adtrust support
-
- # Prompt for secondary RID base only if RID base was given
- if rid_base is not None and secondary_rid_base is None:
- set_from_prompt('ipasecondarybaserid')
-
- # Symetrically, prompt for RID base if secondary RID base was
- # given
- if rid_base is None and secondary_rid_base is not None:
- set_from_prompt('ipabaserid')
-
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py
index 175063ba1..99b0c04d1 100644
--- a/ipalib/plugins/internal.py
+++ b/ipalib/plugins/internal.py
@@ -22,10 +22,6 @@
"""
Plugins not accessible directly through the CLI, commands used internally
"""
-from __future__ import print_function
-
-import json
-
from ipalib import Command
from ipalib import Str
from ipalib.output import Output
@@ -137,9 +133,6 @@ class json_metadata(Command):
return retval
- def output_for_cli(self, textui, result, *args, **options):
- print(json.dumps(result, default=json_serialize))
-
@register()
class i18n_messages(Command):
@@ -864,6 +857,3 @@ class i18n_messages(Command):
)
def execute(self, **options):
return dict(texts=json_serialize(self.messages))
-
- def output_for_cli(self, textui, result, *args, **options):
- print(json.dumps(result, default=json_serialize))
diff --git a/ipalib/plugins/migration.py b/ipalib/plugins/migration.py
index 0fd2def0f..57d26c982 100644
--- a/ipalib/plugins/migration.py
+++ b/ipalib/plugins/migration.py
@@ -652,16 +652,6 @@ search results for objects to be migrated
have been truncated by the server;
migration process might be incomplete\n''')
- migration_disabled_msg = _('''\
-Migration mode is disabled. Use \'ipa config-mod\' to enable it.''')
-
- pwd_migration_msg = _('''\
-Passwords have been migrated in pre-hashed format.
-IPA is unable to generate Kerberos keys unless provided
-with clear text passwords. All migrated users need to
-login at https://your.domain/ipa/migration/ before they
-can use their Kerberos accounts.''')
-
def get_options(self):
"""
Call get_options of the baseclass and add "exclude" options
@@ -927,31 +917,3 @@ can use their Kerberos accounts.''')
)
return dict(result=migrated, failed=failed, enabled=True, compat=True)
-
- def output_for_cli(self, textui, result, ldapuri, bindpw, **options):
- textui.print_name(self.name)
- if not result['enabled']:
- textui.print_plain(self.migration_disabled_msg)
- return 1
- if not result['compat']:
- textui.print_plain("The compat plug-in is enabled. This can increase the memory requirements during migration. Disable the compat plug-in with \'ipa-compat-manage disable\' or re-run this script with \'--with-compat\' option.")
- return 1
- any_migrated = any(result['result'].values())
- textui.print_plain('Migrated:')
- textui.print_entry1(
- result['result'], attr_order=self.migrate_order,
- one_value_per_line=False
- )
- for ldap_obj_name in self.migrate_order:
- textui.print_plain('Failed %s:' % ldap_obj_name)
- textui.print_entry1(
- result['failed'][ldap_obj_name], attr_order=self.migrate_order,
- one_value_per_line=True,
- )
- textui.print_plain('-' * len(self.name))
- if not any_migrated:
- textui.print_plain('No users/groups were migrated from %s' %
- ldapuri)
- return 1
- textui.print_plain(unicode(self.pwd_migration_msg))
-
diff --git a/ipalib/plugins/otptoken.py b/ipalib/plugins/otptoken.py
index 2bd3d3af5..fda05ce0b 100644
--- a/ipalib/plugins/otptoken.py
+++ b/ipalib/plugins/otptoken.py
@@ -17,13 +17,9 @@
# 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 __future__ import print_function
-import sys
-
from .baseldap import LDAPObject, LDAPAddMember, LDAPRemoveMember
from .baseldap import LDAPCreate, LDAPDelete, LDAPUpdate, LDAPSearch, LDAPRetrieve
from ipalib import api, Int, Str, Bool, DateTime, Flag, Bytes, IntEnum, StrEnum, _, ngettext
-from ipalib.messages import add_message, ResultFormattingError
from ipalib.plugable import Registry
from ipalib.errors import (
PasswordMismatch,
@@ -32,16 +28,12 @@ from ipalib.errors import (
ValidationError)
from ipalib.request import context
from ipapython.dn import DN
-from ipapython.version import API_VERSION
import base64
-import locale
import uuid
-import qrcode
import os
import six
-from six import StringIO
from six.moves import urllib
if six.PY3:
@@ -361,75 +353,6 @@ class otptoken_add(LDAPCreate):
_convert_owner(self.api.Object.user, entry_attrs, options)
return super(otptoken_add, self).post_callback(ldap, dn, entry_attrs, *keys, **options)
- def _get_qrcode(self, output, uri, version):
- # Print QR code to terminal if specified
- qr_output = StringIO()
- qr = qrcode.QRCode()
- qr.add_data(uri)
- qr.make()
- qr.print_ascii(out=qr_output, tty=False)
-
- encoding = getattr(sys.stdout, 'encoding', None)
- if encoding is None:
- encoding = locale.getpreferredencoding(False)
-
- try:
- qr_code = qr_output.getvalue().decode(encoding)
- except UnicodeError:
- add_message(
- version,
- output,
- message=ResultFormattingError(
- message=_("Unable to display QR code using the configured "
- "output encoding. Please use the token URI to "
- "configure you OTP device")
- )
- )
- return None
-
- if sys.stdout.isatty():
- output_width = self.api.Backend.textui.get_tty_width()
- qr_code_width = len(qr_code.splitlines()[0])
- if qr_code_width > output_width:
- add_message(
- version,
- output,
- message=ResultFormattingError(
- message=_(
- "QR code width is greater than that of the output "
- "tty. Please resize your terminal.")
- )
- )
-
- return qr
-
- def output_for_cli(self, textui, output, *args, **options):
- # copy-pasted from ipalib/Frontend.__do_call()
- # because option handling is broken on client-side
- if 'version' in options:
- pass
- elif self.api.env.skip_version_check:
- options['version'] = u'2.0'
- else:
- options['version'] = API_VERSION
-
- uri = output['result'].get('uri', None)
-
- if uri is not None and not options.get('no_qrcode', False):
- qr = self._get_qrcode(output, uri, options['version'])
- else:
- qr = None
-
- rv = super(otptoken_add, self).output_for_cli(
- textui, output, *args, **options)
-
- if qr is not None:
- print("\n")
- qr.print_ascii(tty=sys.stdout.isatty())
- print("\n")
-
- return rv
-
@register()
class otptoken_del(LDAPDelete):
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
index ec2071b87..7e3735583 100644
--- a/ipalib/plugins/service.py
+++ b/ipalib/plugins/service.py
@@ -731,25 +731,6 @@ class service_show(LDAPRetrieve):
return dn
- def forward(self, *keys, **options):
- if 'out' in options:
- util.check_writable_file(options['out'])
- result = super(service_show, self).forward(*keys, **options)
- if 'usercertificate' in result['result']:
- x509.write_certificate_list(
- result['result']['usercertificate'],
- options['out']
- )
- result['summary'] = (
- _('Certificate(s) stored in file \'%(file)s\'')
- % dict(file=options['out'])
- )
- return result
- else:
- raise errors.NoCertificateError(entry=keys[-1])
- else:
- return super(service_show, self).forward(*keys, **options)
-
@register()
class service_add_host(LDAPAddMember):
diff --git a/ipalib/plugins/sudorule.py b/ipalib/plugins/sudorule.py
index b281c5f92..15d03c659 100644
--- a/ipalib/plugins/sudorule.py
+++ b/ipalib/plugins/sudorule.py
@@ -493,9 +493,6 @@ class sudorule_enable(LDAPQuery):
return dict(result=True)
- def output_for_cli(self, textui, result, cn, **options):
- textui.print_dashed(_('Enabled Sudo Rule "%s"') % cn)
-
@register()
class sudorule_disable(LDAPQuery):
@@ -519,9 +516,6 @@ class sudorule_disable(LDAPQuery):
return dict(result=True)
- def output_for_cli(self, textui, result, cn, **options):
- textui.print_dashed(_('Disabled Sudo Rule "%s"') % cn)
-
@register()
class sudorule_add_allow_command(LDAPAddMember):
@@ -953,14 +947,6 @@ class sudorule_add_option(LDAPQuery):
return dict(result=entry_attrs, value=pkey_to_value(cn, options))
- def output_for_cli(self, textui, result, cn, **options):
- textui.print_dashed(
- _('Added option "%(option)s" to Sudo Rule "%(rule)s"')
- % dict(option=options['ipasudoopt'], rule=cn))
-
- super(sudorule_add_option, self).output_for_cli(textui, result, cn,
- **options)
-
@register()
class sudorule_remove_option(LDAPQuery):
@@ -1010,11 +996,3 @@ class sudorule_remove_option(LDAPQuery):
entry_attrs = entry_to_dict(entry_attrs, **options)
return dict(result=entry_attrs, value=pkey_to_value(cn, options))
-
- def output_for_cli(self, textui, result, cn, **options):
- textui.print_dashed(
- _('Removed option "%(option)s" from Sudo Rule "%(rule)s"')
- % dict(option=options['ipasudoopt'], rule=cn))
- super(sudorule_remove_option, self).output_for_cli(textui, result, cn,
- **options)
-
diff --git a/ipalib/plugins/topology.py b/ipalib/plugins/topology.py
index 76cf29082..a6e638479 100644
--- a/ipalib/plugins/topology.py
+++ b/ipalib/plugins/topology.py
@@ -501,40 +501,3 @@ Checks done:
'max_agmts': self.api.env.recommended_max_agmts
},
)
-
- def output_for_cli(self, textui, output, *args, **options):
-
- in_order = output['result']['in_order']
- connect_errors = output['result']['connect_errors']
- max_agmts_errors = output['result']['max_agmts_errors']
-
- if in_order:
- header = _('Replication topology of suffix "%(suffix)s" '
- 'is in order.')
- else:
- header = _('Replication topology of suffix "%(suffix)s" contains '
- 'errors.')
- textui.print_h1(header % {'suffix': args[0]})
-
- if connect_errors:
- textui.print_dashed(unicode(_('Topology is disconnected')))
- for err in connect_errors:
- msg = _("Server %(srv)s can't contact servers: %(replicas)s")
- msg = msg % {'srv': err[0], 'replicas': ', '.join(err[2])}
- textui.print_indented(msg)
-
- if max_agmts_errors:
- textui.print_dashed(unicode(_('Recommended maximum number of '
- 'agreements per replica exceeded')))
- textui.print_attribute(
- unicode(_("Maximum number of agreements per replica")),
- [output['result']['max_agmts']]
- )
- for err in max_agmts_errors:
- msg = _('Server "%(srv)s" has %(n)d agreements with servers:')
- msg = msg % {'srv': err[0], 'n': len(err[1])}
- textui.print_indented(msg)
- for replica in err[1]:
- textui.print_indented(replica, 2)
-
- return 0
diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
index c3f616eb5..ee0ab5d10 100644
--- a/ipalib/plugins/trust.py
+++ b/ipalib/plugins/trust.py
@@ -748,30 +748,6 @@ sides.
return result
- def interactive_prompt_callback(self, kw):
- """
- Also ensure that realm_admin is prompted for if --admin or
- --trust-secret is not specified when 'ipa trust-add' is run on the
- system.
-
- Also ensure that realm_passwd is prompted for if --password or
- --trust-secret is not specified when 'ipa trust-add' is run on the
- system.
- """
-
- trust_secret = kw.get('trust_secret')
- realm_admin = kw.get('realm_admin')
- realm_passwd = kw.get('realm_passwd')
-
- if trust_secret is None:
- if realm_admin is None:
- kw['realm_admin'] = self.prompt_param(
- self.params['realm_admin'])
-
- if realm_passwd is None:
- kw['realm_passwd'] = self.Backend.textui.prompt_password(
- self.params['realm_passwd'].label, confirm=False)
-
def validate_options(self, *keys, **options):
trusted_realm_domain = keys[-1]
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 5b00b426b..adc59fcba 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -27,7 +27,6 @@ import six
from ipalib import api
from ipalib import errors
-from ipalib import util
from ipalib import Bool, Flag, Str
from .baseuser import (
baseuser,
@@ -60,7 +59,6 @@ from . import baseldap
from ipalib.request import context
from ipalib import _, ngettext
from ipalib import output
-from ipalib import x509
from ipaplatform.paths import paths
from ipapython.dn import DN
from ipapython.ipautil import ipa_generate_password
@@ -605,14 +603,6 @@ class user_del(baseuser_del):
Bool('preserve?',
exclude='cli',
),
- Flag('preserve?',
- include='cli',
- doc=_('Delete a user, keeping the entry available for future use'),
- ),
- Flag('no_preserve?',
- include='cli',
- doc=_('Delete a user'),
- ),
)
def _preserve_user(self, pkey, delete_container, **options):
@@ -673,20 +663,6 @@ class user_del(baseuser_del):
if restoreAttr:
self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs)
- def forward(self, *keys, **options):
- if self.api.env.context == 'cli':
- no_preserve = options.pop('no_preserve', False)
- preserve = options.pop('preserve', False)
- if no_preserve and preserve:
- raise errors.MutuallyExclusiveError(
- reason=_("preserve and no-preserve cannot be both set"))
- elif no_preserve:
- options['preserve'] = False
- elif preserve:
- options['preserve'] = True
-
- return super(user_del, self).forward(*keys, **options)
-
def pre_callback(self, ldap, dn, *keys, **options):
dn = self.obj.get_either_dn(*keys, **options)
@@ -846,24 +822,6 @@ class user_show(baseuser_show):
self.obj.get_preserved_attribute(entry_attrs, options)
return dn
- def forward(self, *keys, **options):
- if 'out' in options:
- util.check_writable_file(options['out'])
- result = super(user_show, self).forward(*keys, **options)
- if 'usercertificate' in result['result']:
- x509.write_certificate_list(
- result['result']['usercertificate'],
- options['out']
- )
- result['summary'] = (
- _('Certificate(s) stored in file \'%(file)s\'')
- % dict(file=options['out'])
- )
- return result
- else:
- raise errors.NoCertificateError(entry=keys[-1])
- else:
- return super(user_show, self).forward(*keys, **options)
@register()
class user_undel(LDAPQuery):
diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py
index 8de782ee9..05db63cdc 100644
--- a/ipalib/plugins/vault.py
+++ b/ipalib/plugins/vault.py
@@ -17,8 +17,6 @@
# 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 __future__ import print_function
-
from ipalib.frontend import Command, Object
from ipalib import api, errors
from ipalib import Bytes, Flag, Str, StrEnum
@@ -975,22 +973,6 @@ class vaultconfig_show(Retrieve):
),
)
- def forward(self, *args, **options):
-
- file = options.get('transport_out')
-
- # don't send these parameters to server
- if 'transport_out' in options:
- del options['transport_out']
-
- response = super(vaultconfig_show, self).forward(*args, **options)
-
- if file:
- with open(file, 'w') as f:
- f.write(response['result']['transport_cert'])
-
- return response
-
def execute(self, *args, **options):
if not self.api.Command.kra_is_enabled()['result']: