FIMDelta automation

FIMDelta is a great tool for comparing 2 configurations and showing the differences so you can pick and choose the differences. However, extracting the configurations and putting them into the correct folders so that FIMDelta can make a comparison is cumbersome. So in true ninja fashion I have automated it! The following script extracts the configurations, creates folders and places the configs appropriately. It then downloads a copy of FIMDelta and places it in each folder, all you have to do is run FIMDelta!

$schemaFiles = @{}
$schemaFiles.Add("http://dev.mim.ninja:5725/ResourceManagementService","dev.xml")
$schemaFiles.Add("http://prod.mim.ninja:5725/ResourceManagementService","prod.xml")
$folder = (Get-Item -Path ".\" -Verbose).FullName
New-Item "$folder\Schema" -ItemType directory
New-Item "$folder\Policy" -ItemType directory
$creds = Get-Credential
if(@(get-pssnapin | where-object {$_.Name -eq "FIMAutomation"} ).count -eq 0) {add-pssnapin FIMAutomation}

foreach($schemaFile in $schemaFiles.GetEnumerator())
{
$schema_filename = "$folder\Schema\$($schemaFile.Value)"
Write-Host "Exporting configuration objects from pilot."
# Please note that SynchronizationFilter Resources inform the FIM MA.
$schema = Export-FIMConfig -schemaConfig -customConfig "/SynchronizationFilter" -Uri $schemaFile.Name -Credential $creds
if ($schema -eq $null)
{
    Write-Host "Export did not successfully retrieve configuration from FIM.  Please review any error messages and ensure that the arguments to Export-FIMConfig are correct."
}
else
{
    Write-Host "Exported " $schema.Count " objects."
    $schema | ConvertFrom-FIMResource -file $schema_filename
    Write-Host "Schema file is saved as " $schema_filename "."
}
}
foreach($schemaFile in $schemaFiles.GetEnumerator())
{
$policy_filename = "$folder\Policy\$($schemaFile.Value)"
Write-Host "Exporting configuration objects from pilot."
# In many production environments, some Set resources are larger than the default message size of 10 MB.
$policy = Export-FIMConfig -policyConfig -portalConfig -MessageSize 9999999 -Uri $schemaFile.Name -Credential $creds
if ($policy -eq $null)
{
    Write-Host "Export did not successfully retrieve configuration from FIM.  Please review any error messages and ensure that the arguments to Export-FIMConfig are correct."
}
else
{
    Write-Host "Exported $($policy.Count) objects from pilot."
    $policy | ConvertFrom-FIMResource -file $policy_filename
    Write-Host "Policy file is saved as " $policy_filename "."
}
}


#######SYNC SCHEMA###########

$pilot_filename = "$folder\Schema\dev.xml"
$production_filename = "$folder\Schema\prod.xml"
$changes_filename = "$folder\Schema\changes.xml"
$joinrules = @{
    # === Schema configuration ===
    # This is based on the system names of attributes and objects
    # Notice that BindingDescription is joined using its reference attributes.
    ObjectTypeDescription = "Name";
    AttributeTypeDescription = "Name";
    BindingDescription = "BoundObjectType BoundAttributeType";
}

Write-Host "Loading production file " $production_filename "."
$production = ConvertTo-FIMResource -file $production_filename
if($production -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Production Schema is null.  Check that the production file has data.")
}

Write-Host "Loaded file " $production_filename "." $production.Count " objects loaded."

Write-Host "Loading pilot file " $pilot_filename "."
$pilot = ConvertTo-FIMResource -file $pilot_filename
if($pilot -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Pilot Schema is null.  Check that the pilot file has data.")
}

Write-Host "Loaded file " $pilot_filename "." $pilot.Count " objects loaded."
Write-Host
Write-Host "Executing join between pilot and production."
Write-Host 
$matches = Join-FIMConfig -source $pilot -target $production -join $joinrules -defaultJoin DisplayName
if($matches -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Matches is null.  Check that the join succeeded and join criteria is correct for your environment.")
}
Write-Host "Executing compare between matched objects in pilot and production."
$changes = $matches | Compare-FIMConfig
if($changes -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Changes is null.  Check that no errors occurred while generating changes.")
}
Write-Host "Identified " $changes.Count " changes to apply to production."
Write-Host "Saving changes to " $changes_filename "."
$changes | ConvertFrom-FIMResource -file $changes_filename
Write-Host
Write-Host "Sync Schema complete.."

#################SYNC POLICY#######################

$pilot_filename = "$folder\Policy\dev.xml"
$production_filename = "$folder\Policy\prod.xml"
$changes_filename = "$folder\Policy\changes.xml"
$joinrules = @{
    # === Customer-dependent join rules ===
    # Person and Group objects are not configuration will not be migrated.
    # However, some configuration objects like Sets may refer to these objects.
    # For this reason, we need to know how to join Person objects between
    # systems so that configuration objects have the same semantic meaning.
    Person = "MailNickname DisplayName";
    Group = "DisplayName";
    
    # === Policy configuration ===
    # Sets, MPRs, Workflow Definitions, and so on. are best identified by DisplayName
    # DisplayName is set as the default join criteria and applied to all object
    # types not listed here.
    
    # === Schema configuration ===
    # This is based on the system names of attributes and objects
    # Notice that BindingDescription is joined using its reference attributes.
    ObjectTypeDescription = "Name";
    AttributeTypeDescription = "Name";
    BindingDescription = "BoundObjectType BoundAttributeType";
    
    # === Portal configuration ===
    ConstantSpecifier = "BoundObjectType BoundAttributeType ConstantValueKey";
    SearchScopeConfiguration = "DisplayName SearchScopeResultObjectType Order";
    ObjectVisualizationConfiguration = "DisplayName AppliesToCreate AppliesToEdit AppliesToView"
}

Write-Host "Loading production file " $production_filename "."
$production = ConvertTo-FIMResource -file $production_filename
if($production -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Production Schema is null.  Check that the production file has data.")
}

Write-Host "Loaded file " $production_filename "." $production.Count " objects loaded."

Write-Host "Loading pilot file " $pilot_filename "."
$pilot = ConvertTo-FIMResource -file $pilot_filename
if($pilot -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Pilot Schema is null.  Check that the pilot file has data.")
}

Write-Host "Loaded file " $pilot_filename "." $pilot.Count " objects loaded."
Write-Host
Write-Host "Executing join between pilot and production."
Write-Host 
$matches = Join-FIMConfig -source $pilot -target $production -join $joinrules -defaultJoin DisplayName
if($matches -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Matches is null.  Check that the join succeeded and join criteria is correct for your environment.")
}
Write-Host "Executing compare between matched objects in pilot and production."
$changes = $matches | Compare-FIMConfig
if($changes -eq $null)
{
    throw (new-object NullReferenceException -ArgumentList "Changes is null.  Check that no errors occurred while generating changes.")
}
Write-Host "Identified " $changes.Count " changes to apply to production."
Write-Host "Saving changes to " $changes_filename "."
$changes | ConvertFrom-FIMResource -file $changes_filename
Write-Host
Write-Host "Policy Sync complete. ....."
Write-Host "Sync and Policy export and comparison complete....Will download FIMDELTA if required"
##Download FIMDELTA and copy to both folders
$url = "https://github.com/pieceofsummer/FIMDelta/raw/master/build/FimDelta.exe"
if(-not(Test-Path "$folder\Schema\FimDelta.exe"))
{
Write-Host "Starting download of FIMDELTA......"
Start-BitsTransfer -Source $url -Destination "$folder\Schema\FimDelta.exe"
Copy-Item -Path "$folder\Schema\FimDelta.exe" -Destination "$folder\Policy\FimDelta.exe"
Write-Host "Download succesfull......Script End"
}
else
{
Write-Host "FIMDELTA already present aborting........"
}

The astute of you will notice its mostly just a butcher of the existing sync scripts with a little bit of ninjaness added.

Leave a Reply

Your email address will not be published. Required fields are marked *