Skip to content

Commit

Permalink
Issue 50041 - Add CLI functionality for special plugins
Browse files Browse the repository at this point in the history
Description: Add the functionality for
account-policy, attr-uniq, automember, dna, linked-attr,
managed-entries, memberof, pass-through-auth, refer-init,
retro-changelog, root-dn, usn commands.
Make DSLdapObject create an entry with only DN and attributes
(cases when RDN is not specified).
Fix two small typos in pwpolicy CLI's arguments.
Port test for DNA plugin.

https://pagure.io/389-ds-base/issue/50041

Reviewed by: wibrown, mreynolds, mhonek (Thanks!)
  • Loading branch information
droideck committed Mar 8, 2019
1 parent 118f8a2 commit 46e28cb
Show file tree
Hide file tree
Showing 30 changed files with 1,586 additions and 791 deletions.
84 changes: 84 additions & 0 deletions dirsrvtests/tests/suites/plugins/dna_test.py
@@ -0,0 +1,84 @@
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2019 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
# See LICENSE for details.
# --- END COPYRIGHT BLOCK ---
#
"""Test DNA plugin functionality"""

import logging
import pytest
from lib389._constants import DEFAULT_SUFFIX
from lib389.plugins import DNAPlugin, DNAPluginSharedConfigs, DNAPluginConfigs
from lib389.idm.organizationalunit import OrganizationalUnits
from lib389.idm.user import UserAccounts
from lib389.topologies import topology_st
import ldap

log = logging.getLogger(__name__)


@pytest.mark.ds47937
def test_dnatype_only_valid(topology_st):
"""Test that DNA plugin only accepts valid attributes for "dnaType"
:id: 0878ecff-5fdc-47d7-8c8f-edf4556f9746
:setup: Standalone Instance
:steps:
1. Create a use entry
2. Create DNA shared config entry container
3. Create DNA shared config entry
4. Add DNA plugin config entry
5. Enable DNA plugin
6. Restart the instance
7. Replace dnaType with invalid value
:expectedresults:
1. Successful
2. Successful
3. Successful
4. Successful
5. Successful
6. Successful
7. Unwilling to perform exception should be raised
"""

inst = topology_st.standalone
plugin = DNAPlugin(inst)

log.info("Creating an entry...")
users = UserAccounts(inst, DEFAULT_SUFFIX)
users.create_test_user(uid=1)

log.info("Creating \"ou=ranges\"...")
ous = OrganizationalUnits(inst, DEFAULT_SUFFIX)
ou_ranges = ous.create(properties={'ou': 'ranges'})
ou_people = ous.get("People")

log.info("Creating DNA shared config entry...")
shared_configs = DNAPluginSharedConfigs(inst, ou_ranges.dn)
shared_configs.create(properties={'dnaHostName': str(inst.host),
'dnaPortNum': str(inst.port),
'dnaRemainingValues': '9501'})

log.info("Add dna plugin config entry...")
configs = DNAPluginConfigs(inst, plugin.dn)
config = configs.create(properties={'cn': 'dna config',
'dnaType': 'description',
'dnaMaxValue': '10000',
'dnaMagicRegen': '0',
'dnaFilter': '(objectclass=top)',
'dnaScope': ou_people.dn,
'dnaNextValue': '500',
'dnaSharedCfgDN': ou_ranges.dn})

log.info("Enable the DNA plugin...")
plugin.enable()

log.info("Restarting the server...")
inst.restart()

log.info("Apply an invalid attribute to the DNA config(dnaType: foo)...")
with pytest.raises(ldap.UNWILLING_TO_PERFORM):
config.replace('dnaType', 'foo')
122 changes: 0 additions & 122 deletions dirsrvtests/tests/tickets/ticket47937_test.py

This file was deleted.

2 changes: 1 addition & 1 deletion src/cockpit/389-console/src/lib/plugins/accountPolicy.jsx
Expand Up @@ -13,7 +13,7 @@ class AccountPolicy extends React.Component {
serverId={this.props.serverId}
cn="Account Policy Plugin"
pluginName="Account Policy"
cmdName="accountpolicy"
cmdName="account-policy"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
Expand Up @@ -13,7 +13,7 @@ class AttributeUniqueness extends React.Component {
serverId={this.props.serverId}
cn="attribute uniqueness"
pluginName="Attribute Uniqueness"
cmdName="attruniq"
cmdName="attr-uniq"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
Expand Up @@ -13,7 +13,7 @@ class LinkedAttributes extends React.Component {
serverId={this.props.serverId}
cn="Linked Attributes"
pluginName="Linked Attributes"
cmdName="linkedattr"
cmdName="linked-attr"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
2 changes: 1 addition & 1 deletion src/cockpit/389-console/src/lib/plugins/managedEntries.jsx
Expand Up @@ -13,7 +13,7 @@ class ManagedEntries extends React.Component {
serverId={this.props.serverId}
cn="Managed Entries"
pluginName="Managed Entries"
cmdName="managedentries"
cmdName="managed-entries"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
4 changes: 2 additions & 2 deletions src/cockpit/389-console/src/lib/plugins/memberOf.jsx
Expand Up @@ -369,7 +369,7 @@ class MemberOf extends React.Component {
}

editConfig() {
this.cmdOperation("edit");
this.cmdOperation("set");
}

handleCheckboxChange(e) {
Expand Down Expand Up @@ -473,7 +473,7 @@ class MemberOf extends React.Component {
"ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
"plugin",
"memberof",
"edit",
"set",
"--scope",
memberOfEntryScope || "delete",
"--exclude",
Expand Down
Expand Up @@ -13,7 +13,7 @@ class PassthroughAuthentication extends React.Component {
serverId={this.props.serverId}
cn="Pass Through Authentication"
pluginName="Pass Through Authentication"
cmdName="passthroughauth"
cmdName="pass-through-auth"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
Expand Up @@ -13,7 +13,7 @@ class ReferentialIntegrity extends React.Component {
serverId={this.props.serverId}
cn="referential integrity postoperation"
pluginName="Referential Integrity"
cmdName="referint"
cmdName="referential-integrity"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
2 changes: 1 addition & 1 deletion src/cockpit/389-console/src/lib/plugins/retroChangelog.jsx
Expand Up @@ -13,7 +13,7 @@ class RetroChangelog extends React.Component {
serverId={this.props.serverId}
cn="Retro Changelog Plugin"
pluginName="Retro Changelog"
cmdName="retrochangelog"
cmdName="retro-changelog"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
Expand Up @@ -13,7 +13,7 @@ class RootDNAccessControl extends React.Component {
serverId={this.props.serverId}
cn="RootDN Access Control"
pluginName="RootDN Access Control"
cmdName="rootdn"
cmdName="root-dn"
savePluginHandler={this.props.savePluginHandler}
pluginListHandler={this.props.pluginListHandler}
addNotification={this.props.addNotification}
Expand Down
2 changes: 1 addition & 1 deletion src/cockpit/389-console/src/plugins.jsx
Expand Up @@ -196,7 +196,7 @@ export class Plugins extends React.Component {
"-j",
"ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",
"plugin",
"edit",
"set",
data.name,
"--type",
data.type || "delete",
Expand Down
6 changes: 5 additions & 1 deletion src/lib389/lib389/_mapped_object.py
Expand Up @@ -705,7 +705,11 @@ def _validate(self, rdn, properties, basedn):
if self._must_attributes is not None:
for attr in self._must_attributes:
if properties.get(attr, None) is None:
raise ldap.UNWILLING_TO_PERFORM('Attribute %s must not be None' % attr)
# Put RDN to properties
if attr == self._rdn_attribute and rdn is not None:
properties[self._rdn_attribute] = ldap.dn.str2dn(rdn)[0][0][1]
else:
raise ldap.UNWILLING_TO_PERFORM('Attribute %s must not be None' % attr)

# Make sure the naming attribute is present
if properties.get(self._rdn_attribute, None) is None and rdn is None:
Expand Down
23 changes: 17 additions & 6 deletions src/lib389/lib389/cli_conf/__init__.py
@@ -1,5 +1,5 @@
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2018 Red Hat, Inc.
# Copyright (C) 2019 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
Expand All @@ -23,19 +23,30 @@ def _args_to_attrs(args, arg_to_attr):
return attrs


def generic_object_add(dsldap_object, log, args, arg_to_attr, props={}):
"""Create an entry using DSLdapObject interface
def generic_object_add(dsldap_objects_class, inst, log, args, arg_to_attr, dn=None, basedn=None, props={}):
"""Create an entry using DSLdapObjects interface
dsldap_object should be a single instance of DSLdapObject with a set dn
dsldap_objects should be a class inherited from the DSLdapObjects class
"""

log = log.getChild('generic_object_add')
# Gather the attributes
attrs = _args_to_attrs(args, arg_to_attr)
# Update the parameters (which should have at least 'cn') with arg attributes
props.update({attr: value for (attr, value) in attrs.items() if value != ""})
new_object = dsldap_object.create(properties=props)

# Get RDN attribute and Base DN from the DN if Base DN is not specified
if dn is not None and basedn is None:
dn_parts = ldap.dn.explode_dn(dn)

rdn = dn_parts[0]
basedn = ",".join(dn_parts[1:])
else:
raise ValueError('If Base DN is not specified - DN parameter should be')

new_object = dsldap_objects_class(inst, dn=dn)
new_object.create(rdn=rdn, basedn=basedn, properties=props)
log.info("Successfully created the %s", new_object.dn)
return new_object


def generic_object_edit(dsldap_object, log, args, arg_to_attr):
Expand Down

0 comments on commit 46e28cb

Please sign in to comment.