Skip to content

Commit

Permalink
Consistency update: fixing proposed shadow functionality (MID-3603)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Jul 23, 2018
1 parent 3280e9a commit fd6da71
Show file tree
Hide file tree
Showing 13 changed files with 378 additions and 209 deletions.
Expand Up @@ -864,24 +864,6 @@ private ResourceOperationDescription createSuccessOperationDescription(Provision
return operationDescription;
}

public Collection<? extends ItemDelta> beforeModifyOnResource(PrismObject<ShadowType> shadow, ProvisioningOperationOptions options, Collection<? extends ItemDelta> modifications) throws SchemaException {

// TODO: error handling
//do not merge deltas when complete postponed operation is set to false, because it can cause some unexpected behavior..
if (!ProvisioningOperationOptions.isCompletePostponed(options)) {
return modifications;
}

ObjectDelta mergedDelta = mergeDeltas(shadow, modifications);

if (mergedDelta != null) {
modifications = mergedDelta.getModifications();
}

return modifications;

}

public String modifyShadow(PrismObject<ShadowType> repoShadow,
Collection<? extends ItemDelta> modifications, OperationProvisioningScriptsType scripts,
ProvisioningOperationOptions options, Task task, OperationResult parentResult)
Expand Down Expand Up @@ -923,7 +905,7 @@ private String modifyShadowAttempt(ProvisioningContext ctx,

PrismObject<ShadowType> repoShadow = opState.getRepoShadow();

PendingOperationType duplicateOperation = shadowManager.checkAndRecordPendingModifyOperationBeforeExecution(ctx, repoShadow, modifications, task, parentResult);
PendingOperationType duplicateOperation = shadowManager.checkAndRecordPendingModifyOperationBeforeExecution(ctx, repoShadow, modifications, opState, task, parentResult);
if (duplicateOperation != null) {
parentResult.recordInProgress();
return repoShadow.getOid();
Expand All @@ -935,8 +917,6 @@ private String modifyShadowAttempt(ProvisioningContext ctx,
ctx.getObjectClassDefinition(), parentResult);

XMLGregorianCalendar now = clock.currentTimeXMLGregorianCalendar();

modifications = beforeModifyOnResource(repoShadow, options, modifications);

preprocessEntitlements(ctx, modifications, "delta for shadow " + repoShadow.getOid(), parentResult);

Expand Down Expand Up @@ -1115,7 +1095,7 @@ private void deleteShadowAttempt(ProvisioningContext ctx,
PrismObject<ShadowType> repoShadow = opState.getRepoShadow();
shadowCaretaker.applyAttributesDefinition(ctx, repoShadow);

PendingOperationType duplicateOperation = shadowManager.checkAndRecordPendingDeleteOperationBeforeExecution(ctx, repoShadow, task, parentResult);
PendingOperationType duplicateOperation = shadowManager.checkAndRecordPendingDeleteOperationBeforeExecution(ctx, repoShadow, opState, task, parentResult);
if (duplicateOperation != null) {
parentResult.recordInProgress();
return;
Expand Down Expand Up @@ -3069,29 +3049,6 @@ private PasswordCompareStrategyType getPasswordCompareStrategy(RefinedObjectClas
return passwordDefinition.getCompareStrategy();
}

@SuppressWarnings({ "unchecked", "rawtypes" })
protected ObjectDelta mergeDeltas(PrismObject<ShadowType> shadow, Collection<? extends ItemDelta> modifications)
throws SchemaException {
ShadowType shadowType = shadow.asObjectable();
if (shadowType.getObjectChange() != null) {

ObjectDeltaType deltaType = shadowType.getObjectChange();
Collection<? extends ItemDelta> pendingModifications = DeltaConvertor.toModifications(
deltaType.getItemDelta(), shadow.getDefinition());

// pendingModifications must come before modifications, otherwise REPLACE of value X (pending),
// followed by ADD of value Y (current) would become "REPLACE X", which is obviously wrong.
// See e.g. MID-1709.
return ObjectDelta.summarize(
ObjectDelta.createModifyDelta(shadow.getOid(), pendingModifications,
ShadowType.class, getPrismContext()),
ObjectDelta.createModifyDelta(shadow.getOid(), modifications,
ShadowType.class, getPrismContext()));
}
return null;
}


// ----------------------- LEGACY ------ to be removed later (MID-4780)

private void cleanLegacyShadowInRepository(PrismObject<ShadowType> shadow, OperationResult parentResult) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException{
Expand Down

Large diffs are not rendered by default.

Expand Up @@ -24,6 +24,7 @@
import static org.testng.AssertJUnit.assertTrue;

import java.io.File;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
Expand All @@ -38,6 +39,9 @@
import com.evolveum.midpoint.provisioning.impl.dummy.TestDummyResourceAndSchemaCaching;
import com.evolveum.midpoint.provisioning.impl.mock.SynchornizationServiceMock;
import com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.PointInTimeType;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.internals.InternalCounters;
import com.evolveum.midpoint.schema.internals.InternalMonitor;
import com.evolveum.midpoint.schema.internals.InternalsConfig;
Expand All @@ -48,15 +52,19 @@
import com.evolveum.midpoint.schema.util.ResourceTypeUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.AbstractIntegrationTest;
import com.evolveum.midpoint.test.asserter.ShadowAsserter;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CachingMetadataType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.XmlSchemaType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ReadCapabilityType;

Expand Down Expand Up @@ -233,4 +241,51 @@ protected void assertSteadyResource() throws ObjectNotFoundException, SchemaExce
protected PrismObject<ResourceType> getResource() {
return null;
}

protected void assertProvisioningNotFound(String oid) throws CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
Task task = createTask("assertProvisioningNotFound");
OperationResult result = task.getResult();
try {
provisioningService.getObject(ShadowType.class, oid, null, task, result);
assertNotReached();
} catch (ObjectNotFoundException e) {
// expected
}
assertFailure(result);
}

protected ShadowAsserter assertShadowProvisioning(String oid) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
Task task = createTask("assertShadowProvisioning");
OperationResult result = task.getResult();
PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class, oid, null, task, result);
assertSuccess(result);
ShadowAsserter asserter = ShadowAsserter.forShadow(shadow, "provisioning");
asserter
.display();
return asserter;
}

protected ShadowAsserter assertShadowNoFetch(String oid) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
Task task = createTask("assertShadowProvisioning");
OperationResult result = task.getResult();
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch());
PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class, oid, options, task, result);
assertSuccess(result);
ShadowAsserter asserter = ShadowAsserter.forShadow(shadow, "noFetch");
asserter
.display();
return asserter;
}

protected ShadowAsserter assertShadowFuture(String oid) throws ObjectNotFoundException, CommunicationException, SchemaException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
Task task = createTask("assertShadowProvisioning");
OperationResult result = task.getResult();
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE));
PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class, oid, options, task, result);
assertSuccess(result);
ShadowAsserter asserter = ShadowAsserter.forShadow(shadow, "future");
asserter
.display();
return asserter;
}
}
Expand Up @@ -1096,6 +1096,7 @@ public void test100AddAccountWill() throws Exception {
} else {
assertNull("Activation sneaked in (repo)", activationRepo);
}
assertWillRepoShadowAfterCreate(accountRepo);

syncServiceMock.assertNotifySuccessOnly();

Expand Down Expand Up @@ -1154,6 +1155,10 @@ public void test100AddAccountWill() throws Exception {
assertSteadyResource();
}

protected void assertWillRepoShadowAfterCreate(PrismObject<ShadowType> repoShadow) {
// for the subclasses
}

protected void checkRepoAccountShadowWillBasic(PrismObject<ShadowType> accountRepo,
XMLGregorianCalendar start, XMLGregorianCalendar end, Integer expectedNumberOfAttributes) {
display("Will account repo", accountRepo);
Expand Down
Expand Up @@ -58,6 +58,7 @@
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.DummyResourceContoller;
import com.evolveum.midpoint.test.IntegrationTestTools;
import com.evolveum.midpoint.test.asserter.DummyAccountAsserter;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
Expand Down Expand Up @@ -280,7 +281,6 @@ protected void assertSchemaSanity(ResourceSchema resourceSchema, ResourceType re
}

protected DummyAccount getDummyAccount(String icfName, String icfUid) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
// if (isNameUnique()) {
if (isIcfNameUidSame()) {
return dummyResource.getAccountByUsername(icfName);
} else {
Expand All @@ -289,7 +289,6 @@ protected DummyAccount getDummyAccount(String icfName, String icfUid) throws Con
}

protected DummyAccount getDummyAccountAssert(String icfName, String icfUid) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
// if (isNameUnique()) {
if (isIcfNameUidSame()) {
return dummyResource.getAccountByUsername(icfName);
} else {
Expand All @@ -299,6 +298,14 @@ protected DummyAccount getDummyAccountAssert(String icfName, String icfUid) thro
return account;
}
}

protected DummyAccountAsserter assertDummyAccount(String icfName, String icfUid) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
if (isIcfNameUidSame()) {
return dummyResourceCtl.assertAccountByUsername(icfName);
} else {
return dummyResourceCtl.assertAccountById(icfUid);
}
}

protected void assertNoDummyAccount(String icfName, String icfUid) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
DummyAccount account;
Expand Down
Expand Up @@ -905,8 +905,8 @@ public void test119SearchAllAccountsMaxStaleness() throws Exception {
}

@Test
public void test120ModifyObjectReplace() throws Exception {
final String TEST_NAME = "test120ModifyObjectReplace";
public void test120ModifyWillReplaceFullname() throws Exception {
final String TEST_NAME = "test120ModifyWillReplaceFullname";
displayTestTitle(TEST_NAME);

Task task = createTask(TEST_NAME);
Expand All @@ -928,8 +928,8 @@ public void test120ModifyObjectReplace() throws Exception {
assertSuccess(result);

delta.checkConsistence();
assertDummyAccountAttributeValues(transformNameFromResource(ACCOUNT_WILL_USERNAME), willIcfUid,
DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Pirate Will Turner");
assertDummyAccount(transformNameFromResource(ACCOUNT_WILL_USERNAME), willIcfUid)
.assertAttribute(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Pirate Will Turner");

syncServiceMock.assertNotifySuccessOnly();

Expand Down

0 comments on commit fd6da71

Please sign in to comment.