Skip to content

Commit

Permalink
Add shadow.simulated property
Browse files Browse the repository at this point in the history
It is to distinguish between production and non-production shadows.
(The exact form of the property is to be decided.)

Work in progress.
  • Loading branch information
mederly committed Nov 9, 2022
1 parent 08fefd7 commit 9144197
Show file tree
Hide file tree
Showing 31 changed files with 461 additions and 337 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ public SearchHierarchyScope getSearchHierarchyScope() {
return definition.getInbound().getDefaultEvaluationPhases();
}

@Override
public @Nullable String getLifecycleState() {
return definitionBean.getLifecycleState();
}

@Override
public ResourceObjectMultiplicityType getObjectMultiplicity() {
return definitionBean.getMultiplicity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ public SearchHierarchyScope getSearchHierarchyScope() {
return structuralDefinition.getDefaultInboundMappingEvaluationPhases();
}

@Override
public @Nullable String getLifecycleState() {
return structuralDefinition.getLifecycleState();
}

@Override
public ResourceObjectMultiplicityType getObjectMultiplicity() {
return structuralDefinition.getObjectMultiplicity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,14 @@ default ResourceBidirectionalMappingType getActivationBidirectionalMappingType(I
* @see ResourceObjectTypeDefinitionType#getMappingsEvaluation()
*/
@Nullable DefaultInboundMappingEvaluationPhasesType getDefaultInboundMappingEvaluationPhases();

/**
* What lifecycle state is the (refined) object class or object type definition?
* Raw object class definition should always return `null` here.
*
* @see ResourceObjectTypeDefinitionType#getLifecycleState()
*/
@Nullable String getLifecycleState();
//endregion

//region Creating artifacts (shadow, query, PCD, instances, ...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ default DefaultInboundMappingEvaluationPhasesType getDefaultInboundMappingEvalua
return delegate().getDefaultInboundMappingEvaluationPhases();
}

@Override
@Nullable
default String getLifecycleState() {
return delegate().getLifecycleState();
};

@Override
default Collection<QName> getConfiguredAuxiliaryObjectClassNames() {
return delegate().getConfiguredAuxiliaryObjectClassNames();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;

import javax.xml.namespace.QName;
Expand All @@ -36,6 +37,7 @@
import java.util.*;
import java.util.stream.Collectors;

import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.asObjectable;
import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.asPrismObject;
import static com.evolveum.midpoint.util.MiscUtil.stateCheck;

Expand Down Expand Up @@ -675,23 +677,23 @@ public static boolean isFullShadow(PrismObject<ShadowType> shadow) {
return shadowType.getCachingMetadata().getRetrievalTimestamp() != null;
}

public static PolyString determineShadowName(ShadowType shadow) throws SchemaException {
return determineShadowName(asPrismObject(shadow));
public static PolyString determineShadowName(PrismObject<ShadowType> shadow) throws SchemaException {
return determineShadowName(asObjectable(shadow));
}

public static <T extends ShadowType> PolyString determineShadowName(PrismObject<T> shadow) throws SchemaException {
public static PolyString determineShadowName(ShadowType shadow) throws SchemaException {
String stringName = determineShadowStringName(shadow);
return stringName != null ? PolyString.fromOrig(stringName) : null;
}

public static <T extends ShadowType> PolyString determineShadowNameRequired(PrismObject<T> shadow) throws SchemaException {
return PolyString.fromOrig(
public static PolyStringType determineShadowNameRequired(ShadowType shadow) throws SchemaException {
return PolyStringType.fromOrig(
MiscUtil.requireNonNull(
determineShadowStringName(shadow),
() -> "Name could not be determined for " + shadow));
}

private static <T extends ShadowType> String determineShadowStringName(PrismObject<T> shadow) throws SchemaException {
private static String determineShadowStringName(ShadowType shadow) throws SchemaException {
ResourceAttributeContainer attributesContainer = getAttributesContainer(shadow);
if (attributesContainer == null) {
return null;
Expand Down Expand Up @@ -1032,4 +1034,9 @@ public static void checkForPartialClassification(@NotNull ShadowType shadow) {
public static @NotNull String resolveDefault(String intent) {
return Objects.requireNonNullElse(intent, SchemaConstants.INTENT_DEFAULT);
}

// Temporary code
public static boolean isInProduction(@NotNull ShadowType shadow) {
return !Boolean.TRUE.equals(shadow.isSimulated());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4254,6 +4254,20 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="simulated" type="xsd:boolean" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Just a placeholder for the flag meaning "this shadow is a simulated one" (the term is not
stable yet). Will certainly be removed and replaced before merging the branch to master!
</xsd:documentation>
<xsd:appinfo>
<a:since>4.7</a:since>
<a:deprecatedSince>4.7</a:deprecatedSince>
<a:deprecated>true</a:deprecated>
<a:experimental>true</a:experimental>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.schema.CapabilityUtil;
import com.evolveum.midpoint.schema.util.*;

Expand Down Expand Up @@ -169,11 +171,14 @@ public void setPropagation(boolean value) {
this.propagation = value;
}

@NotNull
public ResourceType getResource() {
public @NotNull ResourceType getResource() {
return resource;
}

public @NotNull ObjectReferenceType getResourceRef() {
return ObjectTypeUtil.createObjectRef(resource);
}

public @NotNull ResourceSchema getResourceSchema() throws SchemaException, ConfigurationException {
if (resourceSchema == null) {
resourceSchema = ProvisioningUtil.getResourceSchema(resource);
Expand Down Expand Up @@ -452,17 +457,18 @@ public ItemPath path(Object... components) {
return ItemPath.create(components);
}

public CachingStrategyType getCachingStrategy() {
CachingPolicyType caching = resource.getCaching();
if (caching == null || caching.getCachingStrategy() == null) {
public @NotNull CachingStrategyType getCachingStrategy() {
CachingPolicyType cachingPolicy = resource.getCaching();
CachingStrategyType explicitCachingStrategy = cachingPolicy != null ? cachingPolicy.getCachingStrategy() : null;
if (explicitCachingStrategy != null) {
return explicitCachingStrategy;
} else {
ReadCapabilityType readCapability = getEnabledCapability(ReadCapabilityType.class);
if (readCapability != null && Boolean.TRUE.equals(readCapability.isCachingOnly())) {
return CachingStrategyType.PASSIVE;
} else {
return CachingStrategyType.NONE;
}
} else {
return caching.getCachingStrategy();
}
}

Expand All @@ -479,11 +485,20 @@ public boolean isInMaintenance() {
}

// Preliminary code
public boolean isInProduction() {
public boolean isResourceInProduction() {
return LifecycleUtil.isInProduction(
resource.getLifecycleState());
}

// Preliminary code
public boolean isObjectDefinitionInProduction() {
if (!isResourceInProduction()) {
return false; // We ignore any object class/type level settings here.
}
return resourceObjectDefinition == null
|| LifecycleUtil.isInProduction(resourceObjectDefinition.getLifecycleState());
}

public void checkNotInMaintenance() throws MaintenanceException {
ResourceTypeUtil.checkNotInMaintenance(resource);
}
Expand Down Expand Up @@ -572,18 +587,19 @@ public AttributesToReturn createAttributesToReturn() {

// Methods delegated to shadow caretaker (convenient to be here, but not sure if it's ok...)

public ProvisioningContext applyAttributesDefinition(@NotNull ShadowType shadow) throws SchemaException, ConfigurationException {
public ProvisioningContext applyAttributesDefinition(@NotNull PrismObject<ShadowType> shadow)
throws SchemaException, ConfigurationException {
return getCaretaker().applyAttributesDefinition(this, shadow);
}

public @NotNull ShadowType applyAttributesDefinitionConsideringImmutability(@NotNull ShadowType shadow)
public ProvisioningContext applyAttributesDefinition(@NotNull ShadowType shadow)
throws SchemaException, ConfigurationException {
if (shadow.isImmutable()) {
return getCaretaker().applyAttributesDefinitionToImmutable(this, shadow);
} else {
getCaretaker().applyAttributesDefinition(this, shadow.asPrismObject());
return shadow;
}
return getCaretaker().applyAttributesDefinition(this, shadow);
}

public void applyAttributesDefinition(@NotNull ObjectDelta<ShadowType> delta)
throws SchemaException, ConfigurationException {
getCaretaker().applyAttributesDefinition(this, delta);
}

private @NotNull ShadowCaretaker getCaretaker() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ public class ShadowCaretaker {
@Autowired private PrismContext prismContext;
@Autowired private Clock clock;

// Please use this method only via ProvisioningContext
public void applyAttributesDefinition(ProvisioningContext ctx, ObjectDelta<ShadowType> delta)
throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException {
throws SchemaException, ConfigurationException {
if (delta.isAdd()) {
applyAttributesDefinition(ctx, delta.getObjectToAdd());
} else if (delta.isModify()) {
Expand Down Expand Up @@ -135,18 +136,13 @@ private <V extends PrismValue, D extends ItemDefinition<?>> void applyAttributeD
}
}

@NotNull ShadowType applyAttributesDefinitionToImmutable(ProvisioningContext ctx, ShadowType shadow)
throws SchemaException, ConfigurationException {
ShadowType mutableShadow = shadow.clone();
applyAttributesDefinition(ctx, mutableShadow.asPrismObject());
return mutableShadow.asPrismObject().createImmutableClone().asObjectable();
}

// Please use this method only via ProvisioningContext
public ProvisioningContext applyAttributesDefinition(
@NotNull ProvisioningContext ctx, @NotNull ShadowType shadow) throws SchemaException, ConfigurationException {
return applyAttributesDefinition(ctx, shadow.asPrismObject());
}

// Please use this method only via ProvisioningContext
public ProvisioningContext applyAttributesDefinition(
@NotNull ProvisioningContext ctx, @NotNull PrismObject<ShadowType> shadow)
throws SchemaException, ConfigurationException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,21 @@ public class ResourceObjectAsyncChange extends ResourceObjectChange implements A
}

@Override
protected void processObjectAndDelta(OperationResult result) throws CommunicationException, ObjectNotFoundException,
NotApplicableException, SchemaException, SecurityViolationException, ConfigurationException,
ExpressionEvaluationException {
protected void processObjectAndDelta(OperationResult result)
throws CommunicationException, ObjectNotFoundException, SchemaException, SecurityViolationException,
ConfigurationException, ExpressionEvaluationException {
ResourceObjectConverter converter = beans.resourceObjectConverter;
if (resourceObject != null) {
// TODO why not in LS case? Probably because ConnId LS operation takes care of it?
converter.getShadowCaretaker().applyAttributesDefinition(context, resourceObject);
context.applyAttributesDefinition(resourceObject);
converter.postProcessResourceObjectRead(context, resourceObject, true, result);
} else {
// we will fetch current resource object later; TODO why the difference w.r.t. LS case?
}

if (objectDelta != null) {
// TODO why not in LS case? Probably there's no MODIFY delta there...
converter.getShadowCaretaker().applyAttributesDefinition(context, objectDelta);
context.applyAttributesDefinition(objectDelta);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ private Collection<? extends ResourceAttribute<?>> getIdentifiers(ProvisioningCo
throws SchemaException, ConfigurationException {
if (ShadowUtil.isAttributesContainerRaw(shadow)) {
// This could occur if shadow was re-read during op state processing
shadowCaretaker.applyAttributesDefinition(ctx, shadow);
ctx.applyAttributesDefinition(shadow);
}
return ShadowUtil.getAllIdentifiers(shadow);
}
Expand Down Expand Up @@ -953,8 +953,8 @@ private PrismObject<ShadowType> preReadShadow(
boolean fetchEntitlements,
PrismObject<ShadowType> repoShadow,
OperationResult parentResult)
throws ObjectNotFoundException, CommunicationException, SchemaException, SecurityViolationException, ConfigurationException, ExpressionEvaluationException {
PrismObject<ShadowType> currentShadow;
throws ObjectNotFoundException, CommunicationException, SchemaException, SecurityViolationException,
ConfigurationException, ExpressionEvaluationException {
List<ResourceAttributeDefinition<?>> neededExtraAttributes = new ArrayList<>();
for (Operation operation : operations) {
ResourceAttributeDefinition<?> rad = getAttributeDefinitionIfApplicable(operation, ctx.getObjectDefinition());
Expand All @@ -965,9 +965,11 @@ private PrismObject<ShadowType> preReadShadow(

AttributesToReturn attributesToReturn = new AttributesToReturn();
attributesToReturn.setAttributesToReturn(neededExtraAttributes);
ShadowType currentShadow;
try {
currentShadow = fetchResourceObject(ctx, identifiers,
attributesToReturn, repoShadow, fetchEntitlements, parentResult);
currentShadow =
fetchResourceObject(ctx, identifiers, attributesToReturn, repoShadow, fetchEntitlements, parentResult)
.asObjectable();
} catch (ObjectNotFoundException e) {
// This may happen for semi-manual connectors that are not yet up to date.
// No big deal. We will have to work without it.
Expand All @@ -977,10 +979,9 @@ private PrismObject<ShadowType> preReadShadow(
if (repoShadow != null) {
currentShadow.setOid(repoShadow.getOid());
}
currentShadow.asObjectable().setName(
new PolyStringType(
ShadowUtil.determineShadowNameRequired(currentShadow)));
return currentShadow;
currentShadow.setName(
ShadowUtil.determineShadowNameRequired(currentShadow));
return currentShadow.asPrismObject();
}

private Collection<ResourceAttributeDefinition<?>> determineReadReplace(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ String addShadowAttempt(ProvisioningContext ctx,
throw e;
}
if (!(attributesContainer instanceof ResourceAttributeContainer)) {
shadowCaretaker.applyAttributesDefinition(ctx, resourceObjectToAdd);
ctx.applyAttributesDefinition(resourceObjectToAdd);
}

preAddChecks(ctx, resourceObjectToAdd, opState, parentResult);
Expand All @@ -147,7 +147,7 @@ String addShadowAttempt(ProvisioningContext ctx,

entitlementsHelper.preprocessEntitlements(ctx, resourceObjectToAdd, parentResult);

shadowCaretaker.applyAttributesDefinition(ctx, resourceObjectToAdd);
ctx.applyAttributesDefinition(resourceObjectToAdd);
shadowManager.setKindIfNecessary(resourceObjectToAdd.asObjectable(), ctx);
accessChecker.checkAdd(ctx, resourceObjectToAdd, parentResult);
PrismObject<ShadowType> addedShadow = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.springframework.stereotype.Component;

import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.provisioning.api.ResourceObjectClassification;
import com.evolveum.midpoint.provisioning.impl.ProvisioningContext;
Expand Down Expand Up @@ -158,12 +157,18 @@ boolean shouldClassify(ProvisioningContext ctx, ShadowType repoShadow) {
if (!ShadowUtil.isClassified(repoShadow)) {
LOGGER.trace("Shadow is not classified -> we will do that");
return true;
} else if (ctx.isInProduction()) {
LOGGER.trace("Resource is in production and the shadow is already classified -> will not re-classify");
return false;
} else {
} else if (!ctx.isResourceInProduction()) {
// This is actually a subset of the following "if-else" case.
// But we keep it here for better code understanding and for more precise logging.
LOGGER.trace("Resource is NOT in production -> will re-classify the shadow");
return true;
} else if (!ctx.isObjectDefinitionInProduction()) {
LOGGER.trace("Current object definition is NOT in production -> will re-classify the shadow");
return true;
} else {
LOGGER.trace("Resource and the current object definition is in production and the shadow is already classified -> "
+ "will not re-classify");
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ ConnectorOperationOptions createConnectorOperationOptions(ProvisioningContext ct
throw new ConfigurationException("Requested non-existing 'runAs' shadow", e);
}
ProvisioningContext runAsCtx = ctxFactory.createForShadow(runAsShadow.asObjectable(), ctx.getResource(), ctx.getTask());
shadowCaretaker.applyAttributesDefinition(runAsCtx, runAsShadow);
runAsCtx.applyAttributesDefinition(runAsShadow);
ResourceObjectIdentification runAsIdentification =
ResourceObjectIdentification.createFromShadow(
runAsCtx.getObjectDefinitionRequired(), runAsShadow.asObjectable());
Expand Down

0 comments on commit 9144197

Please sign in to comment.