Skip to content

Commit

Permalink
Update ldap-diff to support legacy exit codes
Browse files Browse the repository at this point in the history
Updated the ldap-diff to add support for a --useLegacyExitCode
argument that can be used to indicate that the tool should use the
same exit codes as a legacy version of the tool.  These legacy exit
codes are:

* 0 -- Success with no differences identified (the same as the
       non-legacy exit code).
* 3 -- Success with one or more differences identified (as opposed
       to a non-legacy exit code of 5, which corresponds to the
       LDAP compareFalse result code).
* 2 -- An argument parsing error occurred (as opposed to a
       non-legacy exit code of 89, which corresponds to the LDAP
       paramError result code).
* 1 -- An unknown error occurred (as opposed to a non-legacy exit
       code that corresponds to the LDAP result code that most
       closely reflects the error that occurred).
  • Loading branch information
dirmgr committed Sep 1, 2021
1 parent 5078e5e commit ca9bd06
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 1 deletion.
13 changes: 13 additions & 0 deletions messages/unboundid-ldapsdk-tools.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4244,6 +4244,19 @@ INFO_LDAP_DIFF_ARG_DESC_MISSING_ONLY=Only report on entries that are present \
in one of the servers but not in the other. If this option is used, then \
entries that exist in both servers will not be compared for differences. \
This can significantly reduce the length of time required to run the tool.
INFO_LDAP_DIFF_ARG_DESC_USE_LEGACY_EXIT_CODE=Use the same exit codes as a \
legacy version of this tool. If all processing completes successfully and \
no differences are identified, then a legacy exit code of 0 will be used \
(which is the same in legacy and non-legacy modes). If all processing \
completes successfully but one or more differences are identified, then a \
legacy exit code of 3 will be used (rather than the default of 5, which \
corresponds to the compareFalse LDAP result code). If an error occurs \
while processing the command-line arguments, then a legacy exit code of 2 \
will be used (rather than the default of 89, which corresponds to the \
paramError LDAP result code). If any other error occurs, then a legacy \
exit code of 1 will be used (rather than the default behavior of using the \
integer value that corresponds to the LDAP result code that most closely \
reflects the error that occurred).
ERR_LDAP_DIFF_EMPTY_BASE_DN=The base DN must not be empty.
ERR_LDAP_DIFF_CANNOT_SET_DEFAULT_BIND_DN=An error occurred while attempting \
to set a default value of ''{0}'' for argument ''{1}'': {2}
Expand Down
78 changes: 77 additions & 1 deletion src/com/unboundid/ldap/sdk/unboundidds/tools/LDAPDiff.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,44 @@ public final class LDAPDiff



/**
* The legacy version of the result code that will be used to indicate that
* an error occurred while processing command-line arguments for the tool.
*/
@NotNull private static final ResultCode LEGACY_EXIT_CODE_ARG_PARSING_ERROR =
ResultCode.PROTOCOL_ERROR;



/**
* The legacy version of the result code that will be used to indicate that
* all processing completed successfully, but that one or more differences
* were identified between the source and target servers.
*/
@NotNull private static final ResultCode LEGACY_EXIT_CODE_OUT_OF_SYNC =
ResultCode.TIME_LIMIT_EXCEEDED;



/**
* The legacy version of the result code that will be used to indicate that
* all processing completed successfully and no differences were identified
* between the source and target servers.
*/
@NotNull private static final ResultCode LEGACY_EXIT_CODE_SUCCESS =
ResultCode.SUCCESS;



/**
* The legacy version of the result code that will be used to indicate that
* an unexpected error occurred during processing.
*/
@NotNull private static final ResultCode LEGACY_EXIT_CODE_UNEXPECTED_ERROR =
ResultCode.OPERATIONS_ERROR;



// A reference to the tool completion message for this tool.
@NotNull private final AtomicReference<String> toolCompletionMessageRef;

Expand All @@ -225,6 +263,7 @@ public final class LDAPDiff
// Legacy arguments used only to provide compatibility with an older version
// of this tool.
@Nullable private BooleanArgument legacyTrustAllArg;
@Nullable private BooleanArgument useLegacyExitCodeArg;
@Nullable private DNArgument legacySourceBindDNArg;
@Nullable private FileArgument legacyKeyStorePathArg;
@Nullable private FileArgument legacyKeyStorePasswordFileArg;
Expand Down Expand Up @@ -285,7 +324,29 @@ public static ResultCode main(@Nullable final OutputStream out,
@NotNull final String... args)
{
final LDAPDiff ldapDiff = new LDAPDiff(out, err);
return ldapDiff.runTool(args);

ResultCode resultCode = ldapDiff.runTool(args);
if ((ldapDiff.useLegacyExitCodeArg != null) &&
(ldapDiff.useLegacyExitCodeArg.isPresent()))
{
switch (resultCode.intValue())
{
case ResultCode.SUCCESS_INT_VALUE:
resultCode = LEGACY_EXIT_CODE_SUCCESS;
break;
case ResultCode.COMPARE_FALSE_INT_VALUE:
resultCode = LEGACY_EXIT_CODE_OUT_OF_SYNC;
break;
case ResultCode.PARAM_ERROR_INT_VALUE:
resultCode = LEGACY_EXIT_CODE_ARG_PARSING_ERROR;
break;
default:
resultCode = LEGACY_EXIT_CODE_UNEXPECTED_ERROR;
break;
}
}

return resultCode;
}


Expand Down Expand Up @@ -322,6 +383,7 @@ public LDAPDiff(@Nullable final OutputStream out,
searchScopeArg = null;

legacyTrustAllArg = null;
useLegacyExitCodeArg = null;
legacySourceBindDNArg = null;
legacyKeyStorePathArg = null;
legacyKeyStorePasswordFileArg = null;
Expand Down Expand Up @@ -601,6 +663,20 @@ public void addNonLDAPArguments(@NotNull final ArgumentParser parser)

// Add legacy arguments that will be used to help provide compatibility with
// an older version of this tool.
useLegacyExitCodeArg = new BooleanArgument(null, "useLegacyExitCode", 1,
INFO_LDAP_DIFF_ARG_DESC_USE_LEGACY_EXIT_CODE.get());
useLegacyExitCodeArg.addLongIdentifier("use-legacy-exit-code", true);
useLegacyExitCodeArg.addLongIdentifier("useLegacyResultCode", true);
useLegacyExitCodeArg.addLongIdentifier("use-legacy-result-code", true);
useLegacyExitCodeArg.addLongIdentifier("legacyExitCode", true);
useLegacyExitCodeArg.addLongIdentifier("legacy-exit-code", true);
useLegacyExitCodeArg.addLongIdentifier("legacyResultCode", true);
useLegacyExitCodeArg.addLongIdentifier("legacy-result-code", true);
useLegacyExitCodeArg.setArgumentGroupName(
INFO_LDAP_DIFF_ARG_GROUP_PROCESSING_ARGS.get());
parser.addArgument(useLegacyExitCodeArg);


legacySourceHostArg = new StringArgument('h', null, false, 1, null, "");
legacySourceHostArg.setHidden(true);
parser.addArgument(legacySourceHostArg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,203 @@ public void testConnectAndAuthenticateFailures()



/**
* Tests to ensure that the appropriate exit code is used when processing
* is successful, no differences are identified, and legacy exit codes should
* be used.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testLegacyExitCodeSuccess()
throws Exception
{
try (InMemoryDirectoryServer sourceDS = createTestDS(false, false, 0);
InMemoryDirectoryServer targetDS = createTestDS(false, false, 0))
{
final File outputFile = createTempFile();
assertTrue(outputFile.delete());

final List<String> argsList = new ArrayList<>();
argsList.addAll(Arrays.asList(
"--sourceHostname", "localhost",
"--sourcePort", String.valueOf(sourceDS.getListenPort()),
"--sourceBindDN", "cn=Directory Manager",
"--sourceBindPassword", "password",
"--targetHostname", "localhost",
"--targetPort", String.valueOf(targetDS.getListenPort()),
"--targetBindDN", "cn=Directory Manager",
"--targetBindPassword", "password",
"--baseDN", "dc=example,dc=com",
"--secondsBetweenPasses", "0",
"--outputLDIF", outputFile.getAbsolutePath()));
String[] argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.SUCCESS);

assertTrue(outputFile.delete());
argsList.add("--useLegacyExitCode");
argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.SUCCESS);
}
}



/**
* Tests to ensure that the appropriate exit code is used when processing
* is successful, differences are identified, and legacy exit codes should
* be used.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testLegacyExitCodeOutOfSync()
throws Exception
{
try (InMemoryDirectoryServer sourceDS = createTestDS(false, false, 0);
InMemoryDirectoryServer targetDS = createTestDS(false, false, 0))
{
sourceDS.add(
"dn: dc=example,dc=com",
"objectClass: top",
"objectClass: domain",
"dc: example",
"description: source description");
targetDS.add(
"dn: dc=example,dc=com",
"objectClass: top",
"objectClass: domain",
"dc: example",
"description: target description");

final File outputFile = createTempFile();
assertTrue(outputFile.delete());

final List<String> argsList = new ArrayList<>();
argsList.addAll(Arrays.asList(
"--sourceHostname", "localhost",
"--sourcePort", String.valueOf(sourceDS.getListenPort()),
"--sourceBindDN", "cn=Directory Manager",
"--sourceBindPassword", "password",
"--targetHostname", "localhost",
"--targetPort", String.valueOf(targetDS.getListenPort()),
"--targetBindDN", "cn=Directory Manager",
"--targetBindPassword", "password",
"--baseDN", "dc=example,dc=com",
"--secondsBetweenPasses", "0",
"--outputLDIF", outputFile.getAbsolutePath()));
String[] argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.COMPARE_FALSE);

assertTrue(outputFile.delete());
argsList.add("--useLegacyExitCode");
argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.TIME_LIMIT_EXCEEDED);
}
}



/**
* Tests to ensure that the appropriate exit code is used when an argument
* processing error occurs and legacy exit codes should be used.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testLegacyExitCodeArgParsingError()
throws Exception
{
try (InMemoryDirectoryServer sourceDS = createTestDS(false, false, 0);
InMemoryDirectoryServer targetDS = createTestDS(false, false, 0))
{
final File outputFile = createTempFile();
assertTrue(outputFile.delete());

final List<String> argsList = new ArrayList<>();
argsList.addAll(Arrays.asList(
"--sourceHostname", "localhost",
"--sourcePort", String.valueOf(sourceDS.getListenPort()),
"--sourceBindDN", "cn=Directory Manager",
"--sourceBindPassword", "password",
"--targetHostname", "localhost",
"--targetPort", String.valueOf(targetDS.getListenPort()),
"--targetBindDN", "cn=Directory Manager",
"--targetBindPassword", "password",
"--baseDN", "",
"--secondsBetweenPasses", "0",
"--outputLDIF", outputFile.getAbsolutePath()));
String[] argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.PARAM_ERROR);

argsList.add("--useLegacyExitCode");
argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.PROTOCOL_ERROR);
}
}



/**
* Tests to ensure that the appropriate exit code is used when a
* non-argument-related error occurs during processing and legacy exit codes
* should be used.
*
* @throws Exception If an unexpected problem occurs.
*/
@Test()
public void testLegacyExitCodeUnknownError()
throws Exception
{
try (InMemoryDirectoryServer sourceDS = createTestDS(false, false, 0);
InMemoryDirectoryServer targetDS = createTestDS(false, false, 0))
{
final File outputFile = createTempFile();
assertTrue(outputFile.delete());

final List<String> argsList = new ArrayList<>();
argsList.addAll(Arrays.asList(
"--sourceHostname", "localhost",
"--sourcePort", String.valueOf(sourceDS.getListenPort()),
"--sourceBindDN", "cn=Directory Manager",
"--sourceBindPassword", "password",
"--targetHostname", "localhost",
"--targetPort", String.valueOf(targetDS.getListenPort()),
"--targetBindDN", "cn=Directory Manager",
"--targetBindPassword", "password",
"--baseDN", "dc=example,dc=com",
"--secondsBetweenPasses", "0",
"--outputLDIF", outputFile.getAbsolutePath()));
String[] argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

sourceDS.shutDown(true);
targetDS.shutDown(true);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.CONNECT_ERROR);

argsList.add("--useLegacyExitCode");
argsArray = argsList.toArray(StaticUtils.NO_STRINGS);

assertEquals(LDAPDiff.main(null, null, argsArray),
ResultCode.OPERATIONS_ERROR);
}
}



/**
* Creates a new in-memory directory server instance with the specified
* number of entries.
Expand Down

0 comments on commit ca9bd06

Please sign in to comment.