mirror of
https://git.centos.org/rpms/389-ds-base.git
synced 2025-02-23 08:12:54 +00:00
import 389-ds-base-1.4.3.16-4.module+el8.4.0+8992+caadce03
This commit is contained in:
parent
47c2e97085
commit
3bc51ab8ba
3 changed files with 1414 additions and 1 deletions
502
SOURCES/0008-Issue-3657-Add-options-to-dsctl-for-dsrc-file.patch
Normal file
502
SOURCES/0008-Issue-3657-Add-options-to-dsctl-for-dsrc-file.patch
Normal file
|
@ -0,0 +1,502 @@
|
|||
From 4faec52810e12070ef72da347bb590c57d8761e4 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Reynolds <mreynolds@redhat.com>
|
||||
Date: Fri, 20 Nov 2020 17:47:18 -0500
|
||||
Subject: [PATCH 1/2] Issue 3657 - Add options to dsctl for dsrc file
|
||||
|
||||
Description: Add options to create, modify, delete, and display
|
||||
the .dsrc CLI tool shortcut file.
|
||||
|
||||
Relates: https://github.com/389ds/389-ds-base/issues/3657
|
||||
|
||||
Reviewed by: firstyear(Thanks!)
|
||||
---
|
||||
dirsrvtests/tests/suites/clu/dsrc_test.py | 136 ++++++++++
|
||||
src/lib389/cli/dsctl | 2 +
|
||||
src/lib389/lib389/cli_ctl/dsrc.py | 312 ++++++++++++++++++++++
|
||||
3 files changed, 450 insertions(+)
|
||||
create mode 100644 dirsrvtests/tests/suites/clu/dsrc_test.py
|
||||
create mode 100644 src/lib389/lib389/cli_ctl/dsrc.py
|
||||
|
||||
diff --git a/dirsrvtests/tests/suites/clu/dsrc_test.py b/dirsrvtests/tests/suites/clu/dsrc_test.py
|
||||
new file mode 100644
|
||||
index 000000000..1b27700ec
|
||||
--- /dev/null
|
||||
+++ b/dirsrvtests/tests/suites/clu/dsrc_test.py
|
||||
@@ -0,0 +1,136 @@
|
||||
+import logging
|
||||
+import pytest
|
||||
+import os
|
||||
+from os.path import expanduser
|
||||
+from lib389.cli_base import FakeArgs
|
||||
+from lib389.cli_ctl.dsrc import create_dsrc, modify_dsrc, delete_dsrc, display_dsrc
|
||||
+from lib389._constants import DEFAULT_SUFFIX, DN_DM
|
||||
+from lib389.topologies import topology_st as topo
|
||||
+
|
||||
+log = logging.getLogger(__name__)
|
||||
+
|
||||
+
|
||||
+@pytest.fixture(scope="function")
|
||||
+def setup(topo, request):
|
||||
+ """Preserve any existing .dsrc file"""
|
||||
+
|
||||
+ dsrc_file = f'{expanduser("~")}/.dsrc'
|
||||
+ backup_file = dsrc_file + ".original"
|
||||
+ if os.path.exists(dsrc_file):
|
||||
+ os.rename(dsrc_file, backup_file)
|
||||
+
|
||||
+ def fin():
|
||||
+ if os.path.exists(backup_file):
|
||||
+ os.rename(backup_file, dsrc_file)
|
||||
+
|
||||
+ request.addfinalizer(fin)
|
||||
+
|
||||
+
|
||||
+def test_dsrc(topo, setup):
|
||||
+ """Test "dsctl dsrc" command
|
||||
+
|
||||
+ :id: 0610de6c-e167-4761-bdab-3e677b2d44bb
|
||||
+ :setup: Standalone Instance
|
||||
+ :steps:
|
||||
+ 1. Test creation works
|
||||
+ 2. Test creating duplicate section
|
||||
+ 3. Test adding an additional inst config works
|
||||
+ 4. Test removing an instance works
|
||||
+ 5. Test modify works
|
||||
+ 6. Test delete works
|
||||
+ 7. Test display fails when no file is present
|
||||
+
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ 5. Success
|
||||
+ 6. Success
|
||||
+ 7. Success
|
||||
+ """
|
||||
+
|
||||
+ inst = topo.standalone
|
||||
+ serverid = inst.serverid
|
||||
+ second_inst_name = "Second"
|
||||
+ second_inst_basedn = "o=second"
|
||||
+ different_suffix = "o=different"
|
||||
+
|
||||
+ # Setup our args
|
||||
+ args = FakeArgs()
|
||||
+ args.basedn = DEFAULT_SUFFIX
|
||||
+ args.binddn = DN_DM
|
||||
+ args.json = None
|
||||
+ args.uri = None
|
||||
+ args.saslmech = None
|
||||
+ args.tls_cacertdir = None
|
||||
+ args.tls_cert = None
|
||||
+ args.tls_key = None
|
||||
+ args.tls_reqcert = None
|
||||
+ args.starttls = None
|
||||
+ args.cancel_starttls = None
|
||||
+ args.pwdfile = None
|
||||
+ args.do_it = True
|
||||
+
|
||||
+ # Create a dsrc configuration entry
|
||||
+ create_dsrc(inst, log, args)
|
||||
+ display_dsrc(inst, topo.logcap.log, args)
|
||||
+ assert topo.logcap.contains("basedn = " + args.basedn)
|
||||
+ assert topo.logcap.contains("binddn = " + args.binddn)
|
||||
+ assert topo.logcap.contains("[" + serverid + "]")
|
||||
+ topo.logcap.flush()
|
||||
+
|
||||
+ # Attempt to add duplicate instance section
|
||||
+ with pytest.raises(ValueError):
|
||||
+ create_dsrc(inst, log, args)
|
||||
+
|
||||
+ # Test adding a second instance works correctly
|
||||
+ inst.serverid = second_inst_name
|
||||
+ args.basedn = second_inst_basedn
|
||||
+ create_dsrc(inst, log, args)
|
||||
+ display_dsrc(inst, topo.logcap.log, args)
|
||||
+ assert topo.logcap.contains("basedn = " + args.basedn)
|
||||
+ assert topo.logcap.contains("[" + second_inst_name + "]")
|
||||
+ topo.logcap.flush()
|
||||
+
|
||||
+ # Delete second instance
|
||||
+ delete_dsrc(inst, log, args)
|
||||
+ inst.serverid = serverid # Restore original instance name
|
||||
+ display_dsrc(inst, topo.logcap.log, args)
|
||||
+ assert not topo.logcap.contains("[" + second_inst_name + "]")
|
||||
+ assert not topo.logcap.contains("basedn = " + args.basedn)
|
||||
+ # Make sure first instance config is still present
|
||||
+ assert topo.logcap.contains("[" + serverid + "]")
|
||||
+ assert topo.logcap.contains("binddn = " + args.binddn)
|
||||
+ topo.logcap.flush()
|
||||
+
|
||||
+ # Modify the config
|
||||
+ args.basedn = different_suffix
|
||||
+ modify_dsrc(inst, log, args)
|
||||
+ display_dsrc(inst, topo.logcap.log, args)
|
||||
+ assert topo.logcap.contains(different_suffix)
|
||||
+ topo.logcap.flush()
|
||||
+
|
||||
+ # Remove an arg from the config
|
||||
+ args.basedn = ""
|
||||
+ modify_dsrc(inst, log, args)
|
||||
+ display_dsrc(inst, topo.logcap.log, args)
|
||||
+ assert not topo.logcap.contains(different_suffix)
|
||||
+ topo.logcap.flush()
|
||||
+
|
||||
+ # Remove the last entry, which should delete the file
|
||||
+ delete_dsrc(inst, log, args)
|
||||
+ dsrc_file = f'{expanduser("~")}/.dsrc'
|
||||
+ assert not os.path.exists(dsrc_file)
|
||||
+
|
||||
+ # Make sure display fails
|
||||
+ with pytest.raises(ValueError):
|
||||
+ display_dsrc(inst, log, args)
|
||||
+
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ # Run isolated
|
||||
+ # -s for DEBUG mode
|
||||
+ CURRENT_FILE = os.path.realpath(__file__)
|
||||
+ pytest.main(["-s", CURRENT_FILE])
|
||||
+
|
||||
diff --git a/src/lib389/cli/dsctl b/src/lib389/cli/dsctl
|
||||
index fe9bc10e9..69f069297 100755
|
||||
--- a/src/lib389/cli/dsctl
|
||||
+++ b/src/lib389/cli/dsctl
|
||||
@@ -23,6 +23,7 @@ from lib389.cli_ctl import tls as cli_tls
|
||||
from lib389.cli_ctl import health as cli_health
|
||||
from lib389.cli_ctl import nsstate as cli_nsstate
|
||||
from lib389.cli_ctl import dbgen as cli_dbgen
|
||||
+from lib389.cli_ctl import dsrc as cli_dsrc
|
||||
from lib389.cli_ctl.instance import instance_remove_all
|
||||
from lib389.cli_base import (
|
||||
disconnect_instance,
|
||||
@@ -61,6 +62,7 @@ cli_tls.create_parser(subparsers)
|
||||
cli_health.create_parser(subparsers)
|
||||
cli_nsstate.create_parser(subparsers)
|
||||
cli_dbgen.create_parser(subparsers)
|
||||
+cli_dsrc.create_parser(subparsers)
|
||||
|
||||
argcomplete.autocomplete(parser)
|
||||
|
||||
diff --git a/src/lib389/lib389/cli_ctl/dsrc.py b/src/lib389/lib389/cli_ctl/dsrc.py
|
||||
new file mode 100644
|
||||
index 000000000..e49c7f819
|
||||
--- /dev/null
|
||||
+++ b/src/lib389/lib389/cli_ctl/dsrc.py
|
||||
@@ -0,0 +1,312 @@
|
||||
+# --- BEGIN COPYRIGHT BLOCK ---
|
||||
+# Copyright (C) 2020 Red Hat, Inc.
|
||||
+# All rights reserved.
|
||||
+#
|
||||
+# License: GPL (version 3 or any later version).
|
||||
+# See LICENSE for details.
|
||||
+# --- END COPYRIGHT BLOCK ---
|
||||
+
|
||||
+import json
|
||||
+from os.path import expanduser
|
||||
+from os import path, remove
|
||||
+from ldapurl import isLDAPUrl
|
||||
+from ldap.dn import is_dn
|
||||
+import configparser
|
||||
+
|
||||
+
|
||||
+def create_dsrc(inst, log, args):
|
||||
+ """Create the .dsrc file
|
||||
+
|
||||
+ [instance]
|
||||
+ uri = ldaps://hostname:port
|
||||
+ basedn = dc=example,dc=com
|
||||
+ binddn = uid=user,....
|
||||
+ saslmech = [EXTERNAL|PLAIN]
|
||||
+ tls_cacertdir = /path/to/cacertdir
|
||||
+ tls_cert = /path/to/user.crt
|
||||
+ tls_key = /path/to/user.key
|
||||
+ tls_reqcert = [never, hard, allow]
|
||||
+ starttls = [true, false]
|
||||
+ pwdfile = /path/to/file
|
||||
+ """
|
||||
+
|
||||
+ dsrc_file = f'{expanduser("~")}/.dsrc'
|
||||
+ config = configparser.ConfigParser()
|
||||
+ config.read(dsrc_file)
|
||||
+
|
||||
+ # Verify this section does not already exist
|
||||
+ instances = config.sections()
|
||||
+ if inst.serverid in instances:
|
||||
+ raise ValueError("There is already a configuration section for this instance!")
|
||||
+
|
||||
+ # Process and validate the args
|
||||
+ config[inst.serverid] = {}
|
||||
+
|
||||
+ if args.uri is not None:
|
||||
+ if not isLDAPUrl(args.uri):
|
||||
+ raise ValueError("The uri is not a valid LDAP URL!")
|
||||
+ if args.uri.startswith("ldapi"):
|
||||
+ # We must use EXTERNAL saslmech for LDAPI
|
||||
+ args.saslmech = "EXTERNAL"
|
||||
+ config[inst.serverid]['uri'] = args.uri
|
||||
+ if args.basedn is not None:
|
||||
+ if not is_dn(args.basedn):
|
||||
+ raise ValueError("The basedn is not a valid DN!")
|
||||
+ config[inst.serverid]['basedn'] = args.basedn
|
||||
+ if args.binddn is not None:
|
||||
+ if not is_dn(args.binddn):
|
||||
+ raise ValueError("The binddn is not a valid DN!")
|
||||
+ config[inst.serverid]['binddn'] = args.binddn
|
||||
+ if args.saslmech is not None:
|
||||
+ if args.saslmech not in ['EXTERNAL', 'PLAIN']:
|
||||
+ raise ValueError("The saslmech must be EXTERNAL or PLAIN!")
|
||||
+ config[inst.serverid]['saslmech'] = args.saslmech
|
||||
+ if args.tls_cacertdir is not None:
|
||||
+ if not path.exists(args.tls_cacertdir):
|
||||
+ raise ValueError('--tls-cacertdir directory does not exist!')
|
||||
+ config[inst.serverid]['tls_cacertdir'] = args.tls_cacertdir
|
||||
+ if args.tls_cert is not None:
|
||||
+ if not path.exists(args.tls_cert):
|
||||
+ raise ValueError('--tls-cert does not point to an existing file!')
|
||||
+ config[inst.serverid]['tls_cert'] = args.tls_cert
|
||||
+ if args.tls_key is not None:
|
||||
+ if not path.exists(args.tls_key):
|
||||
+ raise ValueError('--tls-key does not point to an existing file!')
|
||||
+ config[inst.serverid]['tls_key'] = args.tls_key
|
||||
+ if args.tls_reqcert is not None:
|
||||
+ if args.tls_reqcert not in ['never', 'hard', 'allow']:
|
||||
+ raise ValueError('--tls-reqcert value is invalid (must be either "never", "allow", or "hard")!')
|
||||
+ config[inst.serverid]['tls_reqcert'] = args.tls_reqcert
|
||||
+ if args.starttls:
|
||||
+ config[inst.serverid]['starttls'] = 'true'
|
||||
+ if args.pwdfile is not None:
|
||||
+ if not path.exists(args.pwdfile):
|
||||
+ raise ValueError('--pwdfile does not exist!')
|
||||
+ config[inst.serverid]['pwdfile'] = args.pwdfile
|
||||
+
|
||||
+ if len(config[inst.serverid]) == 0:
|
||||
+ # No args set
|
||||
+ raise ValueError("You must set at least one argument for the new dsrc file!")
|
||||
+
|
||||
+ # Print a preview of the config
|
||||
+ log.info(f'Updating "{dsrc_file}" with:\n')
|
||||
+ log.info(f' [{inst.serverid}]')
|
||||
+ for k, v in config[inst.serverid].items():
|
||||
+ log.info(f' {k} = {v}')
|
||||
+
|
||||
+ # Perform confirmation?
|
||||
+ if not args.do_it:
|
||||
+ while 1:
|
||||
+ val = input(f'\nUpdate "{dsrc_file}" ? [yes]: ').rstrip().lower()
|
||||
+ if val == '' or val == 'y' or val == 'yes':
|
||||
+ break
|
||||
+ if val == 'n' or val == 'no':
|
||||
+ return
|
||||
+
|
||||
+ # Now write the file
|
||||
+ with open(dsrc_file, 'w') as configfile:
|
||||
+ config.write(configfile)
|
||||
+
|
||||
+ log.info(f'Successfully updated: {dsrc_file}')
|
||||
+
|
||||
+
|
||||
+def modify_dsrc(inst, log, args):
|
||||
+ """Modify the instance config
|
||||
+ """
|
||||
+ dsrc_file = f'{expanduser("~")}/.dsrc'
|
||||
+
|
||||
+ if path.exists(dsrc_file):
|
||||
+ config = configparser.ConfigParser()
|
||||
+ config.read(dsrc_file)
|
||||
+
|
||||
+ # Verify we have a section to modify
|
||||
+ instances = config.sections()
|
||||
+ if inst.serverid not in instances:
|
||||
+ raise ValueError("There is no configuration section for this instance to modify!")
|
||||
+
|
||||
+ # Process and validate the args
|
||||
+ if args.uri is not None:
|
||||
+ if not isLDAPUrl(args.uri):
|
||||
+ raise ValueError("The uri is not a valid LDAP URL!")
|
||||
+ if args.uri.startswith("ldapi"):
|
||||
+ # We must use EXTERNAL saslmech for LDAPI
|
||||
+ args.saslmech = "EXTERNAL"
|
||||
+ if args.uri == '':
|
||||
+ del config[inst.serverid]['uri']
|
||||
+ else:
|
||||
+ config[inst.serverid]['uri'] = args.uri
|
||||
+ if args.basedn is not None:
|
||||
+ if not is_dn(args.basedn):
|
||||
+ raise ValueError("The basedn is not a valid DN!")
|
||||
+ if args.basedn == '':
|
||||
+ del config[inst.serverid]['basedn']
|
||||
+ else:
|
||||
+ config[inst.serverid]['basedn'] = args.basedn
|
||||
+ if args.binddn is not None:
|
||||
+ if not is_dn(args.binddn):
|
||||
+ raise ValueError("The binddn is not a valid DN!")
|
||||
+ if args.binddn == '':
|
||||
+ del config[inst.serverid]['binddn']
|
||||
+ else:
|
||||
+ config[inst.serverid]['binddn'] = args.binddn
|
||||
+ if args.saslmech is not None:
|
||||
+ if args.saslmech not in ['EXTERNAL', 'PLAIN']:
|
||||
+ raise ValueError("The saslmech must be EXTERNAL or PLAIN!")
|
||||
+ if args.saslmech == '':
|
||||
+ del config[inst.serverid]['saslmech']
|
||||
+ else:
|
||||
+ config[inst.serverid]['saslmech'] = args.saslmech
|
||||
+ if args.tls_cacertdir is not None:
|
||||
+ if not path.exists(args.tls_cacertdir):
|
||||
+ raise ValueError('--tls-cacertdir directory does not exist!')
|
||||
+ if args.tls_cacertdir == '':
|
||||
+ del config[inst.serverid]['tls_cacertdir']
|
||||
+ else:
|
||||
+ config[inst.serverid]['tls_cacertdir'] = args.tls_cacertdir
|
||||
+ if args.tls_cert is not None:
|
||||
+ if not path.exists(args.tls_cert):
|
||||
+ raise ValueError('--tls-cert does not point to an existing file!')
|
||||
+ if args.tls_cert == '':
|
||||
+ del config[inst.serverid]['tls_cert']
|
||||
+ else:
|
||||
+ config[inst.serverid]['tls_cert'] = args.tls_cert
|
||||
+ if args.tls_key is not None:
|
||||
+ if not path.exists(args.tls_key):
|
||||
+ raise ValueError('--tls-key does not point to an existing file!')
|
||||
+ if args.tls_key == '':
|
||||
+ del config[inst.serverid]['tls_key']
|
||||
+ else:
|
||||
+ config[inst.serverid]['tls_key'] = args.tls_key
|
||||
+ if args.tls_reqcert is not None:
|
||||
+ if args.tls_reqcert not in ['never', 'hard', 'allow']:
|
||||
+ raise ValueError('--tls-reqcert value is invalid (must be either "never", "allow", or "hard")!')
|
||||
+ if args.tls_reqcert == '':
|
||||
+ del config[inst.serverid]['tls_reqcert']
|
||||
+ else:
|
||||
+ config[inst.serverid]['tls_reqcert'] = args.tls_reqcert
|
||||
+ if args.starttls:
|
||||
+ config[inst.serverid]['starttls'] = 'true'
|
||||
+ if args.cancel_starttls:
|
||||
+ config[inst.serverid]['starttls'] = 'false'
|
||||
+ if args.pwdfile is not None:
|
||||
+ if not path.exists(args.pwdfile):
|
||||
+ raise ValueError('--pwdfile does not exist!')
|
||||
+ if args.pwdfile == '':
|
||||
+ del config[inst.serverid]['pwdfile']
|
||||
+ else:
|
||||
+ config[inst.serverid]['pwdfile'] = args.pwdfile
|
||||
+
|
||||
+ # Okay now rewrite the file
|
||||
+ with open(dsrc_file, 'w') as configfile:
|
||||
+ config.write(configfile)
|
||||
+
|
||||
+ log.info(f'Successfully updated: {dsrc_file}')
|
||||
+ else:
|
||||
+ raise ValueError(f'There is no .dsrc file "{dsrc_file}" to update!')
|
||||
+
|
||||
+
|
||||
+def delete_dsrc(inst, log, args):
|
||||
+ """Delete the .dsrc file
|
||||
+ """
|
||||
+ dsrc_file = f'{expanduser("~")}/.dsrc'
|
||||
+ if path.exists(dsrc_file):
|
||||
+ if not args.do_it:
|
||||
+ # Get confirmation
|
||||
+ while 1:
|
||||
+ val = input(f'\nAre you sure you want to remove this instances configuration ? [no]: ').rstrip().lower()
|
||||
+ if val == 'y' or val == 'yes':
|
||||
+ break
|
||||
+ if val == '' or val == 'n' or val == 'no':
|
||||
+ return
|
||||
+
|
||||
+ config = configparser.ConfigParser()
|
||||
+ config.read(dsrc_file)
|
||||
+ instances = config.sections()
|
||||
+ if inst.serverid not in instances:
|
||||
+ raise ValueError("The is no configuration for this instance")
|
||||
+
|
||||
+ # Update the config object
|
||||
+ del config[inst.serverid]
|
||||
+
|
||||
+ if len(config.sections()) == 0:
|
||||
+ # The file would be empty so just delete it
|
||||
+ try:
|
||||
+ remove(dsrc_file)
|
||||
+ log.info(f'Successfully removed: {dsrc_file}')
|
||||
+ return
|
||||
+ except OSError as e:
|
||||
+ raise ValueError(f'Failed to delete "{dsrc_file}", error: {str(e)}')
|
||||
+ else:
|
||||
+ # write the updated config
|
||||
+ with open(dsrc_file, 'w') as configfile:
|
||||
+ config.write(configfile)
|
||||
+ else:
|
||||
+ raise ValueError(f'There is no .dsrc file "{dsrc_file}" to update!')
|
||||
+
|
||||
+ log.info(f'Successfully updated: {dsrc_file}')
|
||||
+
|
||||
+def display_dsrc(inst, log, args):
|
||||
+ """Display the contents of the ~/.dsrc file
|
||||
+ """
|
||||
+ dsrc_file = f'{expanduser("~")}/.dsrc'
|
||||
+
|
||||
+ if not path.exists(dsrc_file):
|
||||
+ raise ValueError(f'There is no dsrc file "{dsrc_file}" to display!')
|
||||
+
|
||||
+ config = configparser.ConfigParser()
|
||||
+ config.read(dsrc_file)
|
||||
+ instances = config.sections()
|
||||
+
|
||||
+ for inst_section in instances:
|
||||
+ if args.json:
|
||||
+ log.info(json.dumps({inst_section: dict(config[inst_section])}, indent=4))
|
||||
+ else:
|
||||
+ log.info(f'[{inst_section}]')
|
||||
+ for k, v in config[inst_section].items():
|
||||
+ log.info(f'{k} = {v}')
|
||||
+ log.info("")
|
||||
+
|
||||
+
|
||||
+def create_parser(subparsers):
|
||||
+ dsrc_parser = subparsers.add_parser('dsrc', help="Manage the .dsrc file")
|
||||
+ subcommands = dsrc_parser.add_subparsers(help="action")
|
||||
+
|
||||
+ # Create .dsrc file
|
||||
+ dsrc_create_parser = subcommands.add_parser('create', help='Generate the .dsrc file')
|
||||
+ dsrc_create_parser.set_defaults(func=create_dsrc)
|
||||
+ dsrc_create_parser.add_argument('--uri', help="The URI (LDAP URL) for the Directory Server instance.")
|
||||
+ dsrc_create_parser.add_argument('--basedn', help="The default database suffix.")
|
||||
+ dsrc_create_parser.add_argument('--binddn', help="The default Bind DN used or authentication.")
|
||||
+ dsrc_create_parser.add_argument('--saslmech', help="The SASL mechanism to use: PLAIN or EXTERNAL.")
|
||||
+ dsrc_create_parser.add_argument('--tls-cacertdir', help="The directory containing the Trusted Certificate Authority certificate.")
|
||||
+ dsrc_create_parser.add_argument('--tls-cert', help="The absolute file name to the server certificate.")
|
||||
+ dsrc_create_parser.add_argument('--tls-key', help="The absolute file name to the server certificate key.")
|
||||
+ dsrc_create_parser.add_argument('--tls-reqcert', help="Request certificate strength: 'never', 'allow', 'hard'")
|
||||
+ dsrc_create_parser.add_argument('--starttls', action='store_true', help="Use startTLS for connection to the server.")
|
||||
+ dsrc_create_parser.add_argument('--pwdfile', help="The absolute path to a file containing the Bind DN's password.")
|
||||
+ dsrc_create_parser.add_argument('--do-it', action='store_true', help="Create the file without any confirmation.")
|
||||
+
|
||||
+ dsrc_modify_parser = subcommands.add_parser('modify', help='Modify the .dsrc file')
|
||||
+ dsrc_modify_parser.set_defaults(func=modify_dsrc)
|
||||
+ dsrc_modify_parser.add_argument('--uri', nargs='?', const='', help="The URI (LDAP URL) for the Directory Server instance.")
|
||||
+ dsrc_modify_parser.add_argument('--basedn', nargs='?', const='', help="The default database suffix.")
|
||||
+ dsrc_modify_parser.add_argument('--binddn', nargs='?', const='', help="The default Bind DN used or authentication.")
|
||||
+ dsrc_modify_parser.add_argument('--saslmech', nargs='?', const='', help="The SASL mechanism to use: PLAIN or EXTERNAL.")
|
||||
+ dsrc_modify_parser.add_argument('--tls-cacertdir', nargs='?', const='', help="The directory containing the Trusted Certificate Authority certificate.")
|
||||
+ dsrc_modify_parser.add_argument('--tls-cert', nargs='?', const='', help="The absolute file name to the server certificate.")
|
||||
+ dsrc_modify_parser.add_argument('--tls-key', nargs='?', const='', help="The absolute file name to the server certificate key.")
|
||||
+ dsrc_modify_parser.add_argument('--tls-reqcert', nargs='?', const='', help="Request certificate strength: 'never', 'allow', 'hard'")
|
||||
+ dsrc_modify_parser.add_argument('--starttls', action='store_true', help="Use startTLS for connection to the server.")
|
||||
+ dsrc_modify_parser.add_argument('--cancel-starttls', action='store_true', help="Do not use startTLS for connection to the server.")
|
||||
+ dsrc_modify_parser.add_argument('--pwdfile', nargs='?', const='', help="The absolute path to a file containing the Bind DN's password.")
|
||||
+ dsrc_modify_parser.add_argument('--do-it', action='store_true', help="Update the file without any confirmation.")
|
||||
+
|
||||
+ # Delete the instance from the .dsrc file
|
||||
+ dsrc_delete_parser = subcommands.add_parser('delete', help='Delete instance configuration from the .dsrc file.')
|
||||
+ dsrc_delete_parser.set_defaults(func=delete_dsrc)
|
||||
+ dsrc_delete_parser.add_argument('--do-it', action='store_true',
|
||||
+ help="Delete this instance's configuration from the .dsrc file.")
|
||||
+
|
||||
+ # Display .dsrc file
|
||||
+ dsrc_display_parser = subcommands.add_parser('display', help='Display the contents of the .dsrc file.')
|
||||
+ dsrc_display_parser.set_defaults(func=display_dsrc)
|
||||
--
|
||||
2.26.2
|
||||
|
|
@ -0,0 +1,902 @@
|
|||
From 201cb1147c0a34bddbd3e5c03aecd804c47a9905 Mon Sep 17 00:00:00 2001
|
||||
From: progier389 <72748589+progier389@users.noreply.github.com>
|
||||
Date: Thu, 19 Nov 2020 10:21:10 +0100
|
||||
Subject: [PATCH 2/2] Issue 4440 - BUG - ldifgen with --start-idx option fails
|
||||
with unsupported operand (#4444)
|
||||
|
||||
Bug description:
|
||||
Got TypeError exception when usign:
|
||||
dsctl -v slapd-localhost ldifgen users --suffix
|
||||
dc=example,dc=com --parent ou=people,dc=example,dc=com
|
||||
--number 100000 --generic --start-idx=50
|
||||
The reason is that by default python parser provides
|
||||
value for numeric options:
|
||||
as an integer if specified by "--option value" or
|
||||
as a string if specified by "--option=value"
|
||||
|
||||
Fix description:
|
||||
convert the numeric parameters to integer when using it.
|
||||
options impacted are:
|
||||
- in users subcommand: --number , --start-idx
|
||||
- in mod-load subcommand: --num-users, --add-users,
|
||||
--del-users, --modrdn-users, --mod-users
|
||||
|
||||
FYI: An alternative solution would have been to indicate the
|
||||
parser that these values are an integer. But two reasons
|
||||
leaded me to implement the first solution:
|
||||
- first solution fix the problem for all users while the
|
||||
second one fixes only dsctl command.
|
||||
- first solution is easier to test:
|
||||
I just added a new test file generated by a script
|
||||
that duplicated existing ldifgen test, renamed the
|
||||
test cases and replaced the numeric arguments by
|
||||
strings.
|
||||
Second solution would need to redesign the test framework
|
||||
to be able to test the parser.
|
||||
|
||||
relates: https://github.com/389ds/389-ds-base/issues/4440
|
||||
|
||||
Reviewed by:
|
||||
|
||||
Platforms tested: F32
|
||||
|
||||
(cherry picked from commit 3c3e1f30cdb046a1aabb93aacebcf261a76a0892)
|
||||
---
|
||||
.../tests/suites/clu/dbgen_test_usan.py | 806 ++++++++++++++++++
|
||||
src/lib389/lib389/cli_ctl/dbgen.py | 10 +-
|
||||
src/lib389/lib389/dbgen.py | 3 +
|
||||
3 files changed, 814 insertions(+), 5 deletions(-)
|
||||
create mode 100644 dirsrvtests/tests/suites/clu/dbgen_test_usan.py
|
||||
|
||||
diff --git a/dirsrvtests/tests/suites/clu/dbgen_test_usan.py b/dirsrvtests/tests/suites/clu/dbgen_test_usan.py
|
||||
new file mode 100644
|
||||
index 000000000..80ff63417
|
||||
--- /dev/null
|
||||
+++ b/dirsrvtests/tests/suites/clu/dbgen_test_usan.py
|
||||
@@ -0,0 +1,806 @@
|
||||
+# --- BEGIN COPYRIGHT BLOCK ---
|
||||
+# Copyright (C) 2020 Red Hat, Inc.
|
||||
+# All rights reserved.
|
||||
+#
|
||||
+# License: GPL (version 3 or any later version).
|
||||
+# See LICENSE for details.
|
||||
+# --- END COPYRIGHT BLOCK ---
|
||||
+#
|
||||
+import time
|
||||
+
|
||||
+"""
|
||||
+ This file contains tests similar to dbgen_test.py
|
||||
+ except that paramaters that are number are expressed as string
|
||||
+ (to mimic the parameters parser default behavior which returns an
|
||||
+ int when parsing "option value" and a string when parsing "option=value"
|
||||
+ This file has been generated by usign:
|
||||
+sed '
|
||||
+9r z1
|
||||
+s/ test_/ test_usan/
|
||||
+/args.*= [0-9]/s,[0-9]*$,"&",
|
||||
+/:id:/s/.$/1/
|
||||
+' dbgen_test.py > dbgen_test_usan.py
|
||||
+ ( with z1 file containing this comment )
|
||||
+"""
|
||||
+
|
||||
+
|
||||
+
|
||||
+import subprocess
|
||||
+import pytest
|
||||
+
|
||||
+from lib389.cli_ctl.dbgen import *
|
||||
+from lib389.cos import CosClassicDefinitions, CosPointerDefinitions, CosIndirectDefinitions, CosTemplates
|
||||
+from lib389.idm.account import Accounts
|
||||
+from lib389.idm.group import Groups
|
||||
+from lib389.idm.role import ManagedRoles, FilteredRoles, NestedRoles
|
||||
+from lib389.tasks import *
|
||||
+from lib389.utils import *
|
||||
+from lib389.topologies import topology_st
|
||||
+from lib389.cli_base import FakeArgs
|
||||
+
|
||||
+pytestmark = pytest.mark.tier0
|
||||
+
|
||||
+LOG_FILE = '/tmp/dbgen.log'
|
||||
+logging.getLogger(__name__).setLevel(logging.DEBUG)
|
||||
+log = logging.getLogger(__name__)
|
||||
+
|
||||
+
|
||||
+@pytest.fixture(scope="function")
|
||||
+def set_log_file_and_ldif(topology_st, request):
|
||||
+ global ldif_file
|
||||
+ ldif_file = get_ldif_dir(topology_st.standalone) + '/created.ldif'
|
||||
+
|
||||
+ fh = logging.FileHandler(LOG_FILE)
|
||||
+ fh.setLevel(logging.DEBUG)
|
||||
+ log.addHandler(fh)
|
||||
+
|
||||
+ def fin():
|
||||
+ log.info('Delete files')
|
||||
+ os.remove(LOG_FILE)
|
||||
+ os.remove(ldif_file)
|
||||
+
|
||||
+ request.addfinalizer(fin)
|
||||
+
|
||||
+
|
||||
+def run_offline_import(instance, ldif_file):
|
||||
+ log.info('Stopping the server and running offline import...')
|
||||
+ instance.stop()
|
||||
+ assert instance.ldif2db(bename=DEFAULT_BENAME, suffixes=[DEFAULT_SUFFIX], encrypt=None, excludeSuffixes=None,
|
||||
+ import_file=ldif_file)
|
||||
+ instance.start()
|
||||
+
|
||||
+
|
||||
+def run_ldapmodify_from_file(instance, ldif_file, output_to_check=None):
|
||||
+ LDAP_MOD = '/usr/bin/ldapmodify'
|
||||
+ log.info('Add entries from ldif file with ldapmodify')
|
||||
+ result = subprocess.check_output([LDAP_MOD, '-cx', '-D', DN_DM, '-w', PASSWORD,
|
||||
+ '-h', instance.host, '-p', str(instance.port), '-af', ldif_file])
|
||||
+ if output_to_check is not None:
|
||||
+ assert output_to_check in ensure_str(result)
|
||||
+
|
||||
+
|
||||
+def check_value_in_log_and_reset(content_list):
|
||||
+ with open(LOG_FILE, 'r+') as f:
|
||||
+ file_content = f.read()
|
||||
+ log.info('Check if content is present in output')
|
||||
+ for item in content_list:
|
||||
+ assert item in file_content
|
||||
+
|
||||
+ log.info('Reset log file for next test')
|
||||
+ f.truncate(0)
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_users(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create ldif with users
|
||||
+
|
||||
+ :id: 426b5b94-9923-454d-a736-7e71ca985e91
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with users
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.suffix = DEFAULT_SUFFIX
|
||||
+ args.parent = 'ou=people,dc=example,dc=com'
|
||||
+ args.number = "1000"
|
||||
+ args.rdn_cn = False
|
||||
+ args.generic = True
|
||||
+ args.start_idx = "50"
|
||||
+ args.localize = False
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'suffix={}'.format(args.suffix),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'number={}'.format(args.number),
|
||||
+ 'rdn-cn={}'.format(args.rdn_cn),
|
||||
+ 'generic={}'.format(args.generic),
|
||||
+ 'start-idx={}'.format(args.start_idx),
|
||||
+ 'localize={}'.format(args.localize),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create users ldif')
|
||||
+ dbgen_create_users(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ log.info('Get number of accounts before import')
|
||||
+ accounts = Accounts(standalone, DEFAULT_SUFFIX)
|
||||
+ count_account = len(accounts.filter('(uid=*)'))
|
||||
+
|
||||
+ run_offline_import(standalone, ldif_file)
|
||||
+
|
||||
+ log.info('Check that accounts are imported')
|
||||
+ assert len(accounts.filter('(uid=*)')) > count_account
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_groups(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create ldif with group
|
||||
+
|
||||
+ :id: 97207413-9a93-4065-a5ec-63aa93801a31
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with group
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+ LDAP_RESULT = 'adding new entry "cn=myGroup-1,ou=groups,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.NAME = 'myGroup'
|
||||
+ args.parent = 'ou=groups,dc=example,dc=com'
|
||||
+ args.suffix = DEFAULT_SUFFIX
|
||||
+ args.number = "1"
|
||||
+ args.num_members = "1000"
|
||||
+ args.create_members = True
|
||||
+ args.member_attr = 'uniquemember'
|
||||
+ args.member_parent = 'ou=people,dc=example,dc=com'
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'number={}'.format(args.number),
|
||||
+ 'suffix={}'.format(args.suffix),
|
||||
+ 'num-members={}'.format(args.num_members),
|
||||
+ 'create-members={}'.format(args.create_members),
|
||||
+ 'member-parent={}'.format(args.member_parent),
|
||||
+ 'member-attr={}'.format(args.member_attr),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create group ldif')
|
||||
+ dbgen_create_groups(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ log.info('Get number of accounts before import')
|
||||
+ accounts = Accounts(standalone, DEFAULT_SUFFIX)
|
||||
+ count_account = len(accounts.filter('(uid=*)'))
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ # ldapmodify will complain about already existing parent which causes subprocess to return exit code != 0
|
||||
+ with pytest.raises(subprocess.CalledProcessError):
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that accounts are imported')
|
||||
+ assert len(accounts.filter('(uid=*)')) > count_account
|
||||
+
|
||||
+ log.info('Check that group is imported')
|
||||
+ groups = Groups(standalone, DEFAULT_SUFFIX)
|
||||
+ assert groups.exists(args.NAME + '-1')
|
||||
+ new_group = groups.get(args.NAME + '-1')
|
||||
+ new_group.present('uniquemember', 'uid=group_entry1-0152,ou=people,dc=example,dc=com')
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_cos_classic(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create a COS definition
|
||||
+
|
||||
+ :id: 8557f994-8a91-4f8a-86f6-9cb826a0b8f1
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with classic COS definition
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ LDAP_RESULT = 'adding new entry "cn=My_Postal_Def,ou=cos definitions,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.type = 'classic'
|
||||
+ args.NAME = 'My_Postal_Def'
|
||||
+ args.parent = 'ou=cos definitions,dc=example,dc=com'
|
||||
+ args.create_parent = True
|
||||
+ args.cos_specifier = 'businessCategory'
|
||||
+ args.cos_attr = ['postalcode', 'telephonenumber']
|
||||
+ args.cos_template = 'cn=sales,cn=classicCoS,dc=example,dc=com'
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'type={}'.format(args.type),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'cos-specifier={}'.format(args.cos_specifier),
|
||||
+ 'cos-template={}'.format(args.cos_template),
|
||||
+ 'cos-attr={}'.format(args.cos_attr),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create COS definition ldif')
|
||||
+ dbgen_create_cos_def(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that COS definition is imported')
|
||||
+ cos_def = CosClassicDefinitions(standalone, args.parent)
|
||||
+ assert cos_def.exists(args.NAME)
|
||||
+ new_cos = cos_def.get(args.NAME)
|
||||
+ assert new_cos.present('cosTemplateDN', args.cos_template)
|
||||
+ assert new_cos.present('cosSpecifier', args.cos_specifier)
|
||||
+ assert new_cos.present('cosAttribute', args.cos_attr[0])
|
||||
+ assert new_cos.present('cosAttribute', args.cos_attr[1])
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_cos_pointer(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create a COS definition
|
||||
+
|
||||
+ :id: 6b26ca6d-226a-4f93-925e-faf95cc20211
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with pointer COS definition
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ LDAP_RESULT = 'adding new entry "cn=My_Postal_Def_pointer,ou=cos pointer definitions,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.type = 'pointer'
|
||||
+ args.NAME = 'My_Postal_Def_pointer'
|
||||
+ args.parent = 'ou=cos pointer definitions,dc=example,dc=com'
|
||||
+ args.create_parent = True
|
||||
+ args.cos_specifier = None
|
||||
+ args.cos_attr = ['postalcode', 'telephonenumber']
|
||||
+ args.cos_template = 'cn=sales,cn=pointerCoS,dc=example,dc=com'
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'type={}'.format(args.type),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'cos-template={}'.format(args.cos_template),
|
||||
+ 'cos-attr={}'.format(args.cos_attr),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create COS definition ldif')
|
||||
+ dbgen_create_cos_def(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that COS definition is imported')
|
||||
+ cos_def = CosPointerDefinitions(standalone, args.parent)
|
||||
+ assert cos_def.exists(args.NAME)
|
||||
+ new_cos = cos_def.get(args.NAME)
|
||||
+ assert new_cos.present('cosTemplateDN', args.cos_template)
|
||||
+ assert new_cos.present('cosAttribute', args.cos_attr[0])
|
||||
+ assert new_cos.present('cosAttribute', args.cos_attr[1])
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_cos_indirect(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create a COS definition
|
||||
+
|
||||
+ :id: ab4b799e-e801-432a-a61d-badad2628201
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with indirect COS definition
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ LDAP_RESULT = 'adding new entry "cn=My_Postal_Def_indirect,ou=cos indirect definitions,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.type = 'indirect'
|
||||
+ args.NAME = 'My_Postal_Def_indirect'
|
||||
+ args.parent = 'ou=cos indirect definitions,dc=example,dc=com'
|
||||
+ args.create_parent = True
|
||||
+ args.cos_specifier = 'businessCategory'
|
||||
+ args.cos_attr = ['postalcode', 'telephonenumber']
|
||||
+ args.cos_template = None
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'type={}'.format(args.type),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'cos-specifier={}'.format(args.cos_specifier),
|
||||
+ 'cos-attr={}'.format(args.cos_attr),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create COS definition ldif')
|
||||
+ dbgen_create_cos_def(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that COS definition is imported')
|
||||
+ cos_def = CosIndirectDefinitions(standalone, args.parent)
|
||||
+ assert cos_def.exists(args.NAME)
|
||||
+ new_cos = cos_def.get(args.NAME)
|
||||
+ assert new_cos.present('cosIndirectSpecifier', args.cos_specifier)
|
||||
+ assert new_cos.present('cosAttribute', args.cos_attr[0])
|
||||
+ assert new_cos.present('cosAttribute', args.cos_attr[1])
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_cos_template(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create a COS template
|
||||
+
|
||||
+ :id: 544017c7-4a82-4e7d-a047-00b68a28e071
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with COS template
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ LDAP_RESULT = 'adding new entry "cn=My_Template,ou=cos templates,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.NAME = 'My_Template'
|
||||
+ args.parent = 'ou=cos templates,dc=example,dc=com'
|
||||
+ args.create_parent = True
|
||||
+ args.cos_priority = "1"
|
||||
+ args.cos_attr_val = 'postalcode:12345'
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'cos-priority={}'.format(args.cos_priority),
|
||||
+ 'cos-attr-val={}'.format(args.cos_attr_val),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create COS template ldif')
|
||||
+ dbgen_create_cos_tmp(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that COS template is imported')
|
||||
+ cos_temp = CosTemplates(standalone, args.parent)
|
||||
+ assert cos_temp.exists(args.NAME)
|
||||
+ new_cos = cos_temp.get(args.NAME)
|
||||
+ assert new_cos.present('cosPriority', str(args.cos_priority))
|
||||
+ assert new_cos.present('postalcode', '12345')
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_managed_role(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create a managed role
|
||||
+
|
||||
+ :id: 10e77b41-0bc1-4ad5-a144-2c5107455b91
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with managed role
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ LDAP_RESULT = 'adding new entry "cn=My_Managed_Role,ou=managed roles,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+
|
||||
+ args.NAME = 'My_Managed_Role'
|
||||
+ args.parent = 'ou=managed roles,dc=example,dc=com'
|
||||
+ args.create_parent = True
|
||||
+ args.type = 'managed'
|
||||
+ args.filter = None
|
||||
+ args.role_dn = None
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'type={}'.format(args.type),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create managed role ldif')
|
||||
+ dbgen_create_role(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that managed role is imported')
|
||||
+ roles = ManagedRoles(standalone, DEFAULT_SUFFIX)
|
||||
+ assert roles.exists(args.NAME)
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_filtered_role(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create a filtered role
|
||||
+
|
||||
+ :id: cb3c8ea8-4234-40e2-8810-fb6a25973921
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with filtered role
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ LDAP_RESULT = 'adding new entry "cn=My_Filtered_Role,ou=filtered roles,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+
|
||||
+ args.NAME = 'My_Filtered_Role'
|
||||
+ args.parent = 'ou=filtered roles,dc=example,dc=com'
|
||||
+ args.create_parent = True
|
||||
+ args.type = 'filtered'
|
||||
+ args.filter = '"objectclass=posixAccount"'
|
||||
+ args.role_dn = None
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'type={}'.format(args.type),
|
||||
+ 'filter={}'.format(args.filter),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create filtered role ldif')
|
||||
+ dbgen_create_role(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that filtered role is imported')
|
||||
+ roles = FilteredRoles(standalone, DEFAULT_SUFFIX)
|
||||
+ assert roles.exists(args.NAME)
|
||||
+ new_role = roles.get(args.NAME)
|
||||
+ assert new_role.present('nsRoleFilter', args.filter)
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_nested_role(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create a nested role
|
||||
+
|
||||
+ :id: 97fff0a8-3103-4adb-be04-2799ff58d8f1
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate ldif with nested role
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ LDAP_RESULT = 'adding new entry "cn=My_Nested_Role,ou=nested roles,dc=example,dc=com"'
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.NAME = 'My_Nested_Role'
|
||||
+ args.parent = 'ou=nested roles,dc=example,dc=com'
|
||||
+ args.create_parent = True
|
||||
+ args.type = 'nested'
|
||||
+ args.filter = None
|
||||
+ args.role_dn = ['cn=some_role,ou=roles,dc=example,dc=com']
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'NAME={}'.format(args.NAME),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'type={}'.format(args.type),
|
||||
+ 'role-dn={}'.format(args.role_dn),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create nested role ldif')
|
||||
+ dbgen_create_role(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file, LDAP_RESULT)
|
||||
+
|
||||
+ log.info('Check that nested role is imported')
|
||||
+ roles = NestedRoles(standalone, DEFAULT_SUFFIX)
|
||||
+ assert roles.exists(args.NAME)
|
||||
+ new_role = roles.get(args.NAME)
|
||||
+ assert new_role.present('nsRoleDN', args.role_dn[0])
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_mod_ldif_mixed(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create mixed modification ldif
|
||||
+
|
||||
+ :id: 4a2e0901-2b48-452e-a4a0-507735132c81
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate modification ldif
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.parent = DEFAULT_SUFFIX
|
||||
+ args.create_users = True
|
||||
+ args.delete_users = True
|
||||
+ args.create_parent = False
|
||||
+ args.num_users = "1000"
|
||||
+ args.add_users = "100"
|
||||
+ args.del_users = "999"
|
||||
+ args.modrdn_users = "100"
|
||||
+ args.mod_users = "10"
|
||||
+ args.mod_attrs = ['cn', 'uid', 'sn']
|
||||
+ args.randomize = False
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'create-users={}'.format(args.create_users),
|
||||
+ 'parent={}'.format(args.parent),
|
||||
+ 'create-parent={}'.format(args.create_parent),
|
||||
+ 'delete-users={}'.format(args.delete_users),
|
||||
+ 'num-users={}'.format(args.num_users),
|
||||
+ 'add-users={}'.format(args.add_users),
|
||||
+ 'del-users={}'.format(args.del_users),
|
||||
+ 'modrdn-users={}'.format(args.modrdn_users),
|
||||
+ 'mod-users={}'.format(args.mod_users),
|
||||
+ 'mod-attrs={}'.format(args.mod_attrs),
|
||||
+ 'randomize={}'.format(args.randomize),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created LDIF file: {}'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create modification ldif')
|
||||
+ dbgen_create_mods(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ log.info('Get number of accounts before import')
|
||||
+ accounts = Accounts(standalone, DEFAULT_SUFFIX)
|
||||
+ count_account = len(accounts.filter('(uid=*)'))
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ # ldapmodify will complain about a lot of changes done which causes subprocess to return exit code != 0
|
||||
+ with pytest.raises(subprocess.CalledProcessError):
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file)
|
||||
+
|
||||
+ log.info('Check that some accounts are imported')
|
||||
+ assert len(accounts.filter('(uid=*)')) > count_account
|
||||
+
|
||||
+
|
||||
+@pytest.mark.ds50545
|
||||
+@pytest.mark.bz1798394
|
||||
+@pytest.mark.skipif(ds_is_older("1.4.3"), reason="Not implemented")
|
||||
+def test_usandsconf_dbgen_nested_ldif(topology_st, set_log_file_and_ldif):
|
||||
+ """Test ldifgen (formerly dbgen) tool to create nested ldif
|
||||
+
|
||||
+ :id: 9c281c28-4169-45e0-8c07-c5502d9a7581
|
||||
+ :setup: Standalone instance
|
||||
+ :steps:
|
||||
+ 1. Create DS instance
|
||||
+ 2. Run ldifgen to generate nested ldif
|
||||
+ 3. Import generated ldif to database
|
||||
+ 4. Check it was properly imported
|
||||
+ :expectedresults:
|
||||
+ 1. Success
|
||||
+ 2. Success
|
||||
+ 3. Success
|
||||
+ 4. Success
|
||||
+ """
|
||||
+
|
||||
+ standalone = topology_st.standalone
|
||||
+
|
||||
+ args = FakeArgs()
|
||||
+ args.suffix = DEFAULT_SUFFIX
|
||||
+ args.node_limit = "100"
|
||||
+ args.num_users = "600"
|
||||
+ args.ldif_file = ldif_file
|
||||
+
|
||||
+ content_list = ['Generating LDIF with the following options:',
|
||||
+ 'suffix={}'.format(args.suffix),
|
||||
+ 'node-limit={}'.format(args.node_limit),
|
||||
+ 'num-users={}'.format(args.num_users),
|
||||
+ 'ldif-file={}'.format(args.ldif_file),
|
||||
+ 'Writing LDIF',
|
||||
+ 'Successfully created nested LDIF file ({}) containing 6 nodes/subtrees'.format(args.ldif_file)]
|
||||
+
|
||||
+ log.info('Run ldifgen to create nested ldif')
|
||||
+ dbgen_create_nested(standalone, log, args)
|
||||
+
|
||||
+ log.info('Check if file exists')
|
||||
+ assert os.path.exists(ldif_file)
|
||||
+
|
||||
+ check_value_in_log_and_reset(content_list)
|
||||
+
|
||||
+ log.info('Get number of accounts before import')
|
||||
+ accounts = Accounts(standalone, DEFAULT_SUFFIX)
|
||||
+ count_account = len(accounts.filter('(uid=*)'))
|
||||
+ count_ou = len(accounts.filter('(ou=*)'))
|
||||
+
|
||||
+ # Groups, COS, Roles and modification ldifs are designed to be used by ldapmodify, not ldif2db
|
||||
+ # ldapmodify will complain about already existing suffix which causes subprocess to return exit code != 0
|
||||
+ with pytest.raises(subprocess.CalledProcessError):
|
||||
+ run_ldapmodify_from_file(standalone, ldif_file)
|
||||
+
|
||||
+ standalone.restart()
|
||||
+
|
||||
+ log.info('Check that accounts are imported')
|
||||
+ assert len(accounts.filter('(uid=*)')) > count_account
|
||||
+ assert len(accounts.filter('(ou=*)')) > count_ou
|
||||
+
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ # Run isolated
|
||||
+ # -s for DEBUG mode
|
||||
+ CURRENT_FILE = os.path.realpath(__file__)
|
||||
+ pytest.main("-s %s" % CURRENT_FILE)
|
||||
diff --git a/src/lib389/lib389/cli_ctl/dbgen.py b/src/lib389/lib389/cli_ctl/dbgen.py
|
||||
index 7bc3892ba..058342fb1 100644
|
||||
--- a/src/lib389/lib389/cli_ctl/dbgen.py
|
||||
+++ b/src/lib389/lib389/cli_ctl/dbgen.py
|
||||
@@ -451,13 +451,13 @@ def dbgen_create_mods(inst, log, args):
|
||||
props = {
|
||||
"createUsers": args.create_users,
|
||||
"deleteUsers": args.delete_users,
|
||||
- "numUsers": args.num_users,
|
||||
+ "numUsers": int(args.num_users),
|
||||
"parent": args.parent,
|
||||
"createParent": args.create_parent,
|
||||
- "addUsers": args.add_users,
|
||||
- "delUsers": args.del_users,
|
||||
- "modrdnUsers": args.modrdn_users,
|
||||
- "modUsers": args.mod_users,
|
||||
+ "addUsers": int(args.add_users),
|
||||
+ "delUsers": int(args.del_users),
|
||||
+ "modrdnUsers": int(args.modrdn_users),
|
||||
+ "modUsers": int(args.mod_users),
|
||||
"random": args.randomize,
|
||||
"modAttrs": args.mod_attrs
|
||||
}
|
||||
diff --git a/src/lib389/lib389/dbgen.py b/src/lib389/lib389/dbgen.py
|
||||
index 6273781a2..10fb200f7 100644
|
||||
--- a/src/lib389/lib389/dbgen.py
|
||||
+++ b/src/lib389/lib389/dbgen.py
|
||||
@@ -220,6 +220,9 @@ def dbgen_users(instance, number, ldif_file, suffix, generic=False, entry_name="
|
||||
"""
|
||||
Generate an LDIF of randomly named entries
|
||||
"""
|
||||
+ # Lets insure that integer parameters are not string
|
||||
+ number=int(number)
|
||||
+ startIdx=int(startIdx)
|
||||
familyname_file = os.path.join(instance.ds_paths.data_dir, 'dirsrv/data/dbgen-FamilyNames')
|
||||
givename_file = os.path.join(instance.ds_paths.data_dir, 'dirsrv/data/dbgen-GivenNames')
|
||||
familynames = []
|
||||
--
|
||||
2.26.2
|
||||
|
|
@ -45,7 +45,7 @@ ExcludeArch: i686
|
|||
Summary: 389 Directory Server (base)
|
||||
Name: 389-ds-base
|
||||
Version: 1.4.3.16
|
||||
Release: %{?relprefix}3%{?prerel}%{?dist}
|
||||
Release: %{?relprefix}4%{?prerel}%{?dist}
|
||||
License: GPLv3+
|
||||
URL: https://www.port389.org
|
||||
Group: System Environment/Daemons
|
||||
|
@ -181,6 +181,9 @@ Patch04: 0004-Ticket-50933-Update-2307compat.ldif.patch
|
|||
Patch05: 0005-Issue-50933-Fix-OID-change-between-10rfc2307-and-10r.patch
|
||||
Patch06: 0006-Ticket-51131-improve-mutex-alloc-in-conntable.patch
|
||||
Patch07: 0007-Issue-4297-2nd-fix-for-on-ADD-replication-URP-issue-.patch
|
||||
Patch08: 0008-Issue-3657-Add-options-to-dsctl-for-dsrc-file.patch
|
||||
Patch09: 0009-Issue-4440-BUG-ldifgen-with-start-idx-option-fails-w.patch
|
||||
|
||||
|
||||
%description
|
||||
389 Directory Server is an LDAPv3 compliant server. The base package includes
|
||||
|
@ -798,6 +801,12 @@ exit 0
|
|||
%doc README.md
|
||||
|
||||
%changelog
|
||||
* Thu Dec 3 2020 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.16-4
|
||||
- Bump version to 1.4.3.16-4
|
||||
- Resolves: Bug 1843517 - Using ldifgen with --start-idx option fails with unsupported operand
|
||||
- Resolves: Bug 1801086 - [RFE] Generate dsrc file using dsconf
|
||||
- Resolves: Bug 1843838 - heap-use-after-free in slapi_be_getsuffix
|
||||
|
||||
* Wed Nov 25 2020 Mark Reynolds <mreynolds@redhat.com> - 1.4.3.16-3
|
||||
- Bump version to 1.4.3.16-3
|
||||
- Resolves: Bug 1859219 - rfc2307 and rfc2307bis compat schema
|
||||
|
|
Loading…
Add table
Reference in a new issue