Powershell Connector: Force multiple fields to be passed to a function

I am creating a custom PowerShell connector.  Within Identity Manager, we have the departments arranged in a hierarchy.  Level 1 departments is divisions in the target system, and level 2 departments are departments in the target system.  The target system stores the department and divisions through separate endpoints.  I initially created two PowerShell schemas for Division and Department but could not filter successfully to do what I want so looking at an alternative.

I am now trying another approach, is having a wrapper function that calls the respective backend function as required.  To do this, I am wanting Identity Manager to pass through the treelevel parameter on each call.  This is where I am failing.

My XML file is this:

<?xml version="1.0" encoding="utf-8"?>
<PowershellConnectorDefinition Id="XyzConnector" Description="Xyz connector" Version="1.0">
    <PluginAssemblies/>
    <ConnectionParameters>
        <ConnectionParameter Name="Module"   Description="Module"/>
        <ConnectionParameter Name="JsonFile" Description="Data file"/>
    </ConnectionParameters>
    <Initialization>
        <PredefinedCommands>
            <Command Name="Connect-Xyz"/>
            <Command Name="Disconnect-Xyz"/>
			<Command Name="Get-XyzDeptDivisions" />
			<Command Name="Get-XyzDeptDivision" />
			<Command Name="New-XyzDeptDivision" />
			<Command Name="Set-XyzDeptDivision" />
			<Command Name="Remove-XyzDeptDivision" />
         </PredefinedCommands>
        <CustomCommands>
            <CustomCommand Name="Import-ConnectorModule">
                <![CDATA[
                    param($Module)
                    Import-Module -Force $Module
                ]]>
            </CustomCommand>
            <CustomCommand Name="Connect-TargetSystem">
                <![CDATA[
                    param($JsonFile)
                    Connect-Xyz $JsonFile
                ]]>
            </CustomCommand>
            <CustomCommand Name="Disconnect-TargetSystem">
                <![CDATA[
                    Disconnect-Xyz
                ]]>
            </CustomCommand>
        </CustomCommands>
        <EnvironmentInitialization>
            <Connect>
                <CommandSequence>
                    <Item Command="Import-ConnectorModule" Order="1">
                        <SetParameter Param="Module" Source="ConnectionParameter" Value="Module"/>
                    </Item>
                    <Item Command="Connect-TargetSystem" Order="2">
                        <SetParameter Param="JsonFile" Source="ConnectionParameter" Value="JsonFile"/>
                    </Item>
                </CommandSequence>
            </Connect>
            <Disconnect>
                <CommandSequence>
                    <Item Command="Disconnect-TargetSystem" Order="1"/>
                </CommandSequence>
            </Disconnect>
        </EnvironmentInitialization>
    </Initialization>
    <Schema>
		<Class Name="XYZDeptDivisions">
				<Properties>
					<Property Name="ID" DataType="String" IsUniqueKey="true" IsMandatory="true" AccessConstraint="ReadOnly">							
						<ReturnBindings>
							<Bind CommandResultOf="Get-XyzDeptDivisions" Path="id" />
							<Bind CommandResultOf="Get-XyzDeptDivision" Path="id" />	
							<Bind CommandResultOf="New-XyzDeptDivision" Path="id" />							
						</ReturnBindings>
						<CommandMappings>
							<Map ToCommand="Get-XyzDeptDivision" 		 Parameter="id"/>
							<Map ToCommand="New-XyzDeptDivision"         Parameter="id"/>
							<Map ToCommand="Set-XyzDeptDivision"         Parameter="id"/>
							<Map ToCommand="Remove-XyzDeptDivision"      Parameter="id"/>
						</CommandMappings>							
					</Property>				
					<Property Name="Name" DataType="String" AccessConstraint="None">
						<ReturnBindings>
							<Bind CommandResultOf="Get-XyzDeptDivisions" Path="Name" />
							<Bind CommandResultOf="Get-XyzDeptDivision" Path="Name" />
						</ReturnBindings>
						<CommandMappings>
							<Map ToCommand="New-XyzDeptDivision"  Parameter="Name"/>
							<Map ToCommand="Set-XyzDeptDivision"  Parameter="Name"/>
						</CommandMappings>	
						<ModifiedBy>
							<ModBy Command="Set-XyzDeptDivision"/>
						</ModifiedBy>						
					</Property>			
					<Property Name="TreeLevel" DataType="Int" IsMandatory="true" AccessConstraint="None">
						<ReturnBindings>
							<Bind CommandResultOf="Get-XyzDeptDivisions" Path="treelevel" />
							<Bind CommandResultOf="Get-XyzDeptDivision" Path="treelevel" />
						</ReturnBindings>
						<CommandMappings>
							<Map ToCommand="Get-XyzDeptDivision" 		 Parameter="treelevel"/>
							<Map ToCommand="New-XyzDeptDivision"         Parameter="treelevel"/>
							<Map ToCommand="Set-XyzDeptDivision"         Parameter="treelevel"/>
							<Map ToCommand="Remove-XyzDeptDivision"      Parameter="treelevel"/>
						</CommandMappings>							
					</Property>					
				</Properties>
				<ReadConfiguration>
					<ListingCommand Command="Get-XyzDeptDivisions"/>
					<CommandSequence>
						<Item Command="Get-XyzDeptDivision" Order="1"/>
					</CommandSequence>
				</ReadConfiguration>
				<MethodConfiguration>
					<Method Name="Insert">
						<CommandSequence>
							<Item Command="New-XyzDeptDivision" Order="1"/>
						</CommandSequence>
					</Method>
					<Method Name="Update">
						<CommandSequence>
							<Item Command="Set-XyzDeptDivision" Order="1" Condition="ModificationExists">
								<SetParameter Param="con" Source="GlobalVariable" Value="con"/>
							</Item>
						</CommandSequence>
					</Method>
					<Method Name="Delete">
						<CommandSequence>
							<Item Command="Remove-XyzDeptDivision" Order="1"/>
						</CommandSequence>
					</Method>
				</MethodConfiguration>
			</Class>			
    </Schema>
</PowershellConnectorDefinition>

What I am wanting is for the TreeLevel and ID to passed through to every transaction.

An example of the PowerShell function that is called is thus:

function Set-XyzDeptDivision($id, $Name, $treelevel) {
    $Log.Info("Set-DeptDivision id=$id treelevel=$treelevel Name=$Name")
    $Log.Debug("  * parameters = {0}" -f ($PSBoundParameters | ConvertTo-Json -Compress))
	switch ($treelevel) {
		# Division
		$cDivisionLevel { 
			$res = Set-XyzDivision -id $id -Division_Name $Name
		}
		$cDepartmentLevel {
			$res = Set-XyzDepartment -id $id -Department_Name $Name
		}
		default {
			$log.Debug("Why are we even here - we should never get here!")
		}
		
	}
	
}

As can be seen, depending upon the value of tree level will determine what function will perform the work.

Looking at the log file I get this:

2024-01-12 15:54:46.8529 WARN (SystemConnector Posh-03EBEE Job 4d29d931-ee60-4e09-9a91-0845e4455b00) : Returned PSObject was $null or result was empty. If calling a custom cmdlet consider throwing an exception instead of returning $null. 
2024-01-12 15:54:46.8529 INFO (XyzConnectorLog  Job 4d29d931-ee60-4e09-9a91-0845e4455b00) : Set-DeptDivision id=9b13ad76-102e-4c4b-bcdd-10bfcc8aaf04 treelevel= Name=98765 - Security Division 
2024-01-12 15:54:46.8675 INFO (XyzConnectorLog  Job 4d29d931-ee60-4e09-9a91-0845e4455b00) : Get-DeptDivision id=9b13ad76-102e-4c4b-bcdd-10bfcc8aaf04  treelevel=

This is one using version 9.

Within mappings in Identity Manager I have treelevel from the department table mapped to the PowerShell schema. 

Is this possible, or what am I missing?

Parents
  • Thanks Niels

    I tried to reply to your message and caught in requiring a moderator to approve - so your message was there until I replied to your message.  Option1 worked a treat.  Option 2 is not an option for me, as I need treelevel parameter to determine what endpoint I need to speak to on the target system.  I did look through the forum, and skipped that thread as I did not think it applied to me.  Thank you for your prompt answer as well.  Looking at that thread you mention, it appears that while it is recognised as a "feature", there is no fix likely to come along, as it is still there in 9.1.1.  Be good if this was documented within the documentation somewhere.

Reply
  • Thanks Niels

    I tried to reply to your message and caught in requiring a moderator to approve - so your message was there until I replied to your message.  Option1 worked a treat.  Option 2 is not an option for me, as I need treelevel parameter to determine what endpoint I need to speak to on the target system.  I did look through the forum, and skipped that thread as I did not think it applied to me.  Thank you for your prompt answer as well.  Looking at that thread you mention, it appears that while it is recognised as a "feature", there is no fix likely to come along, as it is still there in 9.1.1.  Be good if this was documented within the documentation somewhere.

Children
No Data