use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance in project midpoint by Evolveum.
the class EntitlementConverter method postProcessEntitlementEntitlementToSubject.
private <S extends ShadowType, T> void postProcessEntitlementEntitlementToSubject(ProvisioningContext subjectCtx, final PrismObject<S> resourceObject, RefinedAssociationDefinition assocDefType, final ProvisioningContext entitlementCtx, ResourceAttributeContainer attributesContainer, final PrismContainer<ShadowAssociationType> associationContainer, OperationResult parentResult) throws SchemaException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
ResourceType resourceType = subjectCtx.getResource();
final QName associationName = assocDefType.getName();
final RefinedObjectClassDefinition entitlementDef = entitlementCtx.getObjectClassDefinition();
if (associationName == null) {
throw new SchemaException("No name in entitlement association " + assocDefType + " in " + resourceType);
}
QName associationAuxiliaryObjectClass = assocDefType.getAuxiliaryObjectClass();
if (associationAuxiliaryObjectClass != null && associationAuxiliaryObjectClass.getNamespaceURI() != null && !associationAuxiliaryObjectClass.getNamespaceURI().equals(ResourceTypeUtil.getResourceNamespace(resourceType))) {
LOGGER.warn("Auxiliary object class {} in association {} does not have namespace that matches {}", associationAuxiliaryObjectClass, assocDefType.getName(), resourceType);
}
if (associationAuxiliaryObjectClass != null && !subjectCtx.getObjectClassDefinition().hasAuxiliaryObjectClass(associationAuxiliaryObjectClass)) {
LOGGER.trace("Ignoring association {} because subject does not have auxiliary object class {}, it has {}", associationName, associationAuxiliaryObjectClass, subjectCtx.getObjectClassDefinition().getAuxiliaryObjectClassDefinitions());
return;
}
QName assocAttrName = assocDefType.getResourceObjectAssociationType().getAssociationAttribute();
if (assocAttrName == null) {
throw new SchemaException("No association attribute defined in entitlement association '" + associationName + "' in " + resourceType);
}
RefinedAttributeDefinition assocAttrDef = entitlementDef.findAttributeDefinition(assocAttrName);
if (assocAttrDef == null) {
throw new SchemaException("Association attribute '" + assocAttrName + "'defined in entitlement association '" + associationName + "' was not found in schema for " + resourceType);
}
QName valueAttrName = assocDefType.getResourceObjectAssociationType().getValueAttribute();
if (valueAttrName == null) {
throw new SchemaException("No value attribute defined in entitlement association '" + associationName + "' in " + resourceType);
}
ResourceAttribute<T> valueAttr = attributesContainer.findAttribute(valueAttrName);
if (valueAttr == null || valueAttr.isEmpty()) {
LOGGER.trace("Ignoring association {} because subject does not have any value in attribute {}", associationName, valueAttrName);
return;
}
if (valueAttr.size() > 1) {
throw new SchemaException("Value attribute " + valueAttrName + " has no more than one value; attribute defined in entitlement association '" + associationName + "' in " + resourceType);
}
ObjectQuery query = createQuery(assocDefType, assocAttrDef, valueAttr);
AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(entitlementCtx);
SearchHierarchyConstraints searchHierarchyConstraints = null;
ResourceObjectReferenceType baseContextRef = entitlementDef.getBaseContext();
if (baseContextRef != null) {
// TODO: this should be done once per search. Not in every run of postProcessEntitlementEntitlementToSubject
// this has to go outside of this method
PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(subjectCtx, baseContextRef, null, "base context specification in " + entitlementDef, parentResult);
RefinedObjectClassDefinition baseContextObjectClassDefinition = subjectCtx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
}
ResultHandler<ShadowType> handler = new ResultHandler<ShadowType>() {
@Override
public boolean handle(PrismObject<ShadowType> entitlementShadow) {
PrismContainerValue<ShadowAssociationType> associationCVal = associationContainer.createNewValue();
associationCVal.asContainerable().setName(associationName);
Collection<ResourceAttribute<?>> entitlementIdentifiers = ShadowUtil.getAllIdentifiers(entitlementShadow);
try {
ResourceAttributeContainer identifiersContainer = new ResourceAttributeContainer(ShadowAssociationType.F_IDENTIFIERS, entitlementDef.toResourceAttributeContainerDefinition(), prismContext);
associationCVal.add(identifiersContainer);
identifiersContainer.getValue().addAll(ResourceAttribute.cloneCollection(entitlementIdentifiers));
// Remember the full shadow in user data. This is used later as an optimization to create the shadow in repo
identifiersContainer.setUserData(ResourceObjectConverter.FULL_SHADOW_KEY, entitlementShadow);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Processed entitlement-to-subject association for account {} and entitlement {}", ShadowUtil.getHumanReadableName(resourceObject), ShadowUtil.getHumanReadableName(entitlementShadow));
}
} catch (SchemaException e) {
throw new TunnelException(e);
}
return true;
}
};
ConnectorInstance connector = subjectCtx.getConnector(ReadCapabilityType.class, parentResult);
try {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Processed entitlement-to-subject association for account {}: query {}", ShadowUtil.getHumanReadableName(resourceObject), query);
}
try {
connector.search(entitlementDef, query, handler, attributesToReturn, null, searchHierarchyConstraints, subjectCtx, parentResult);
} catch (GenericFrameworkException e) {
throw new GenericConnectorException("Generic error in the connector " + connector + ". Reason: " + e.getMessage(), e);
}
} catch (TunnelException e) {
throw (SchemaException) e.getCause();
}
}
use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance in project midpoint by Evolveum.
the class AbstractBasicDummyTest method test034ResourceAndConnectorCachingForceFresh.
@Test
public void test034ResourceAndConnectorCachingForceFresh() throws Exception {
// GIVEN
Task task = getTestTask();
OperationResult result = createOperationResult();
ConnectorInstance configuredConnectorInstance = resourceManager.getConfiguredConnectorInstance(resource, ReadCapabilityType.class, false, result);
assertNotNull("No configuredConnectorInstance", configuredConnectorInstance);
ResourceSchema resourceSchema = ResourceSchemaFactory.getRawSchema(resource);
assertNotNull("No resource schema", resourceSchema);
// WHEN
PrismObject<ResourceType> resourceAgain = provisioningService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, task, result);
// THEN
assertSuccess(result);
ResourceType resourceTypeAgain = resourceAgain.asObjectable();
assertNotNull("No connector ref", resourceTypeAgain.getConnectorRef());
assertNotNull("No connector ref OID", resourceTypeAgain.getConnectorRef().getOid());
PrismContainer<Containerable> configurationContainer = resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION);
PrismContainer<Containerable> configurationContainerAgain = resourceAgain.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION);
assertTrue("Configurations not equivalent", configurationContainer.equivalent(configurationContainerAgain));
ResourceSchema resourceSchemaAgain = ResourceSchemaFactory.getRawSchema(resourceAgain);
assertNotNull("No resource schema (again)", resourceSchemaAgain);
assertTrue("Resource schema was not cached", resourceSchema == resourceSchemaAgain);
// Now we stick our nose deep inside the provisioning impl. But we need
// to make sure that the configured connector is properly refreshed
// forceFresh = true
ConnectorInstance configuredConnectorInstanceAgain = resourceManager.getConfiguredConnectorInstance(resourceAgain, ReadCapabilityType.class, true, result);
assertNotNull("No configuredConnectorInstance (again)", configuredConnectorInstanceAgain);
// Connector instance should NOT be changed at this point. It should be only re-configured.
assertTrue("Connector instance was changed", configuredConnectorInstance == configuredConnectorInstanceAgain);
// Check if the connector still works
OperationResult testResult = createOperationResult("test");
configuredConnectorInstanceAgain.test(testResult);
testResult.computeStatus();
TestUtil.assertSuccess("Connector test failed", testResult);
assertCounterIncrement(InternalCounters.CONNECTOR_INSTANCE_INITIALIZATION_COUNT, 0);
assertCounterIncrement(InternalCounters.CONNECTOR_INSTANCE_CONFIGURATION_COUNT, 1);
rememberConnectorInstance(configuredConnectorInstanceAgain);
assertSteadyResource();
}
use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance in project midpoint by Evolveum.
the class ResourceManager method testConnectionConnector.
private void testConnectionConnector(ConnectorSpec connectorSpec, Map<String, Collection<Object>> capabilityMap, Task task, OperationResult parentResult) throws ObjectNotFoundException {
// === test INITIALIZATION ===
OperationResult initResult = parentResult.createSubresult(ConnectorTestOperation.CONNECTOR_INITIALIZATION.getOperation());
LOGGER.debug("Testing connection using {}", connectorSpec);
String resourceOid = connectorSpec.getResource().getOid();
String operationCtx = "testing connection using " + connectorSpec;
ConfiguredConnectorInstanceEntry connectorInstanceCacheEntry;
try {
// Make sure we are getting non-configured instance.
connectorInstanceCacheEntry = connectorManager.getOrCreateConnectorInstanceCacheEntry(connectorSpec, initResult);
initResult.recordSuccess();
} catch (ObjectNotFoundException e) {
// The connector was not found. The resource definition is either
// wrong or the connector is not installed.
String msg = "The connector was not found: " + e.getMessage();
operationCtx += " failed while getting connector instance. " + msg;
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
initResult.recordFatalError(msg, e);
return;
} catch (SchemaException e) {
String msg = "Schema error while dealing with the connector definition: " + e.getMessage();
operationCtx += " failed while getting connector instance. " + msg;
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
initResult.recordFatalError(msg, e);
return;
} catch (RuntimeException | Error e) {
String msg = "Unexpected runtime error: " + e.getMessage();
operationCtx += " failed while getting connector instance. " + msg;
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
initResult.recordFatalError(msg, e);
return;
}
ConnectorInstance connector = connectorInstanceCacheEntry.getConnectorInstance();
// === test CONFIGURATION ===
OperationResult configResult = parentResult.createSubresult(ConnectorTestOperation.CONNECTOR_CONFIGURATION.getOperation());
try {
PrismObject<ResourceType> resource = connectorSpec.getResource();
PrismObjectDefinition<ResourceType> newResourceDefinition = resource.getDefinition().clone();
applyConnectorSchemaToResource(connectorSpec, newResourceDefinition, resource, task, configResult);
PrismContainerValue<ConnectorConfigurationType> connectorConfiguration = connectorSpec.getConnectorConfiguration().getValue();
InternalMonitor.recordCount(InternalCounters.CONNECTOR_INSTANCE_CONFIGURATION_COUNT);
connector.configure(connectorConfiguration, ResourceTypeUtil.getSchemaGenerationConstraints(resource), configResult);
// We need to explicitly initialize the instance, e.g. in case that the schema and capabilities
// cannot be detected by the connector and therefore are provided in the resource
//
// NOTE: the capabilities and schema that are used here are NOT necessarily those that are detected by the resource.
// The detected schema will come later. The schema here is the one that is stored in the resource
// definition (ResourceType). This may be schema that was detected previously. But it may also be a schema
// that was manually defined. This is needed to be passed to the connector in case that the connector
// cannot detect the schema and needs schema/capabilities definition to establish a connection.
// Most connectors will just ignore the schema and capabilities that are provided here.
// But some connectors may need it (e.g. CSV connector working with CSV file without a header).
//
ResourceSchema previousResourceSchema = ResourceSchemaFactory.getRawSchema(connectorSpec.getResource());
Collection<Object> previousCapabilities = ResourceTypeUtil.getNativeCapabilitiesCollection(connectorSpec.getResource().asObjectable());
connector.initialize(previousResourceSchema, previousCapabilities, ResourceTypeUtil.isCaseIgnoreAttributeNames(connectorSpec.getResource().asObjectable()), configResult);
configResult.recordSuccess();
} catch (CommunicationException e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Communication error", e);
return;
} catch (GenericFrameworkException e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Generic error", e);
return;
} catch (SchemaException e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Schema error", e);
return;
} catch (ConfigurationException e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Configuration error", e);
return;
} catch (ObjectNotFoundException e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Object not found", e);
return;
} catch (ExpressionEvaluationException e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Expression error", e);
return;
} catch (SecurityViolationException e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Security violation", e);
return;
} catch (RuntimeException | Error e) {
operationCtx += " failed while testing configuration: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
configResult.recordFatalError("Unexpected runtime error", e);
return;
}
// === test CONNECTION ===
// delegate the main part of the test to the connector
connector.test(parentResult);
parentResult.computeStatus();
if (!parentResult.isAcceptable()) {
operationCtx += ". Connector test failed: " + parentResult.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true);
// messages.
return;
} else {
operationCtx += ". Connector test successful.";
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.UP, operationCtx, task, parentResult, false);
}
// === test CAPABILITIES ===
OperationResult capabilitiesResult = parentResult.createSubresult(ConnectorTestOperation.CONNECTOR_CAPABILITIES.getOperation());
try {
InternalMonitor.recordCount(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT);
Collection<Object> retrievedCapabilities = connector.fetchCapabilities(capabilitiesResult);
capabilityMap.put(connectorSpec.getConnectorName(), retrievedCapabilities);
capabilitiesResult.recordSuccess();
} catch (CommunicationException e) {
operationCtx += " failed while testing capabilities: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true);
capabilitiesResult.recordFatalError("Communication error", e);
return;
} catch (GenericFrameworkException e) {
operationCtx += " failed while testing capabilities: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
capabilitiesResult.recordFatalError("Generic error", e);
return;
} catch (ConfigurationException e) {
operationCtx += " failed while testing capabilities: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
capabilitiesResult.recordFatalError("Configuration error", e);
return;
} catch (SchemaException e) {
operationCtx += " failed while testing capabilities: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
capabilitiesResult.recordFatalError("Schema error", e);
return;
} catch (RuntimeException | Error e) {
operationCtx += " failed while testing capabilities: " + e.getMessage();
modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true);
capabilitiesResult.recordFatalError("Unexpected runtime error", e);
return;
}
// Connector instance is fully configured at this point.
// But the connector cache entry may not be set up properly and it is not yet placed into the cache.
// Therefore make sure the caching bit is completed.
// Place the connector to cache even if it was configured at the beginning. The connector is reconfigured now.
connectorManager.cacheConfiguredConnector(connectorInstanceCacheEntry, connectorSpec);
}
use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance in project midpoint by Evolveum.
the class SearchHelper method countObjects.
public Integer countObjects(ObjectQuery query, Task task, final OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
ObjectFilter filter = query != null ? query.getFilter() : null;
ResourceShadowDiscriminator coordinates = ObjectQueryUtil.getCoordinates(filter);
// otherwise coordinates couldn't be found
assert query != null;
ProvisioningContext ctx = ctxFactory.createForCoordinates(coordinates, task, result);
ctx.assertDefinition();
definitionsHelper.applyDefinition(ctx, query);
ResourceObjectDefinition objectClassDef = ctx.getObjectDefinitionRequired();
ResourceType resourceType = ctx.getResource();
CountObjectsCapabilityType countObjectsCapabilityType = objectClassDef.getEffectiveCapability(CountObjectsCapabilityType.class, resourceType);
if (countObjectsCapabilityType == null) {
// Unable to count. Return null which means "I do not know"
LOGGER.trace("countObjects: cannot count (no counting capability)");
result.recordNotApplicableIfUnknown();
return null;
} else {
CountObjectsSimulateType simulate = countObjectsCapabilityType.getSimulate();
if (simulate == null) {
// We have native capability
LOGGER.trace("countObjects: counting with native count capability");
ConnectorInstance connector = ctx.getConnector(ReadCapabilityType.class, result);
try {
ObjectQuery attributeQuery = createAttributeQuery(query);
int count;
try {
count = connector.count(objectClassDef.getObjectClassDefinition(), attributeQuery, objectClassDef.getPagedSearches(resourceType), ctx.getUcfExecutionContext(), result);
} catch (CommunicationException | GenericFrameworkException | SchemaException | UnsupportedOperationException e) {
result.recordFatalError(e);
throw e;
}
result.computeStatus();
result.cleanupResult();
return count;
} catch (GenericFrameworkException | UnsupportedOperationException e) {
SystemException ex = new SystemException("Couldn't count objects on resource " + resourceType + ": " + e.getMessage(), e);
result.recordFatalError(ex);
throw ex;
}
} else if (simulate == CountObjectsSimulateType.PAGED_SEARCH_ESTIMATE) {
LOGGER.trace("countObjects: simulating counting with paged search estimate");
if (!objectClassDef.isPagedSearchEnabled(resourceType)) {
throw new ConfigurationException("Configured count object capability to be simulated using a paged search but paged search capability is not present");
}
query = query.clone();
ObjectPaging paging = prismContext.queryFactory().createPaging();
// Explicitly set offset. This makes a difference for some resources.
// E.g. LDAP connector will detect presence of an offset and it will initiate VLV search which
// can estimate number of results. If no offset is specified then continuous/linear search is
// assumed (e.g. Simple Paged Results search). Such search does not have ability to estimate
// number of results.
paging.setOffset(0);
paging.setMaxSize(1);
query.setPaging(paging);
Collection<SelectorOptions<GetOperationOptions>> options = schemaService.getOperationOptionsBuilder().item(ShadowType.F_ASSOCIATION).dontRetrieve().build();
int count;
try {
count = countObjects(query, options, CountMethod.METADATA, task, result);
} catch (SchemaException | ObjectNotFoundException | ConfigurationException | SecurityViolationException e) {
result.recordFatalError(e);
throw e;
}
result.computeStatus();
result.cleanupResult();
return count;
} else if (simulate == CountObjectsSimulateType.SEQUENTIAL_SEARCH) {
// fix for MID-5204. as sequentialSearch option causes to fetch all resource objects,
// query paging is senseless here
query = query.clone();
query.setPaging(null);
LOGGER.trace("countObjects: simulating counting with sequential search (likely performance impact)");
Collection<SelectorOptions<GetOperationOptions>> options = schemaService.getOperationOptionsBuilder().item(ShadowType.F_ASSOCIATION).dontRetrieve().build();
int count = countObjects(query, options, CountMethod.COUNTING, task, result);
// TODO: better error handling
result.computeStatus();
result.cleanupResult();
return count;
} else {
throw new IllegalArgumentException("Unknown count capability simulate type " + simulate);
}
}
}
use of com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance in project midpoint by Evolveum.
the class ConnectorManager method getConfiguredConnectorInstance.
ConnectorInstance getConfiguredConnectorInstance(ConnectorSpec connectorSpec, boolean forceFresh, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException {
ConfiguredConnectorInstanceEntry connectorCacheEntry = getOrCreateConnectorInstanceCacheEntry(connectorSpec, result);
ConnectorInstance connectorInstance = connectorCacheEntry.getConnectorInstance();
if (forceFresh && connectorCacheEntry.isConfigured()) {
LOGGER.debug("FORCE in connector cache: reconfiguring cached connector {}", connectorSpec);
configureConnector(connectorInstance, connectorSpec, result);
// Connector is cached already. No need to put it into cache.
return connectorInstance;
}
if (connectorCacheEntry.isConfigured() && !isFresh(connectorCacheEntry, connectorSpec)) {
LOGGER.trace("Reconfiguring connector {} because the configuration is not fresh", connectorSpec);
configureConnector(connectorInstance, connectorSpec, result);
// Connector is cached already. No need to put it into cache. We just need to update the configuration.
connectorCacheEntry.setConfiguration(connectorSpec.getConnectorConfiguration());
return connectorInstance;
}
if (!connectorCacheEntry.isConfigured()) {
LOGGER.trace("Configuring new connector {}", connectorSpec);
configureConnector(connectorInstance, connectorSpec, result);
cacheConfiguredConnector(connectorCacheEntry, connectorSpec);
}
return connectorInstance;
}
Aggregations