Public/FlyExchangeApi.ps1

<#
.SYNOPSIS
 
Add mappings into the specified Exchange project.
 
.DESCRIPTION
 
Add mappings into the specified Exchange project.
 
.PARAMETER Project
Specify the name of the project to import mappings.
 
.PARAMETER Path
Specify the csv file path of the project mappings to import.
 
.OUTPUTS
 
None
#>

function Import-FlyExchangeMappings {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [String]
        ${Project},
        [Parameter(Mandatory = $true)]
        [String]
        ${Path}
    )

    Process {
        'Calling method: Import-FlyExchangeMappings' | Write-Debug
        $PSBoundParameters | Out-DebugParameter | Write-Debug
        Try {
            $targetProject = Get-FlyProjectByName -ProjectName $Project
            $mappings = New-Object System.Collections.ArrayList;
            $importedMappings = Get-FlyMappingsFromCsv -Path $Path
            #Construct the project mapping list to import
            foreach ($mapping in $importedMappings) {
                $item = [PSCustomObject]@{
                    "sourceIdentity"      = $mapping.Source
                    "sourceType"          = Get-FlyDataType $mapping.'Source type'
                    "destinationIdentity" = $mapping.Destination
                    "destinationType"     = Get-FlyDataType $mapping.'Destination type'
                }
                [void]$mappings.Add($item);
            }
            #Import project mapping list to the project
            [System.Net.HttpWebRequest]::DefaultMaximumErrorResponseLength = -1
            $result = Add-FlyExchangeMappings -ProjectId $targetProject.Id -ExchangeMappingCreationModel $mappings.ToArray()
            if ($result) {
                Write-Host 'Successfully added the mappings to the project.' -ForegroundColor Green
            }
        }
        Catch {
            Write-Host 'Failed to add the mappings to the project.' -ForegroundColor Red
            if ($_.ErrorDetails.Message) {
                $errorModel = ConvertFrom-Json $_.ErrorDetails.Message
                if ($errorModel.ErrorCode -eq 'ProjectMappingDuplicated') {
                    Write-Host 'ErrorDetail : ProjectMappingDuplicated' -ForegroundColor Red
                    $errorDetails = ConvertFrom-Json $errorModel.ErrorMessage
                    $errorDetails | Select-Object SourceIdentity, DestinationIdentity, ProjectName | Format-Table
                }
                else {
                    Write-Host $_.ErrorDetails.Message -ForegroundColor Red
                }
            }
            Write-Error $_.Exception
            throw
        }
    }
}

<#
.SYNOPSIS
 
Export the Exchange migration mapping status to a csv file.
 
.DESCRIPTION
 
Export the Exchange migration mapping status to a csv file.
 
.PARAMETER Project
Specify the name of the project to export mappings.
 
.PARAMETER OutFile
Specify the csv file path of the project mappings to export.
 
.PARAMETER Filter
Specify the csv file to filter specific project mappings to export, export all mappings of the project if not specified.
 
.OUTPUTS
 
None
#>

function Export-FlyExchangeMappingStatus {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [String]
        ${Project},
        [Parameter(Mandatory = $true)]
        [String]
        ${OutFile},
        [Parameter(Mandatory = $false)]
        [String]
        ${Mappings}
    )

    Process {
        'Calling method: Export-FlyExchangeMappingStatus' | Write-Debug
        $PSBoundParameters | Out-DebugParameter | Write-Debug
        Try {
            $targetProject = Get-FlyProjectByName -ProjectName $Project -PlatformType 'Exchange'
            $result = New-Object System.Collections.ArrayList;
            #Retrieve the project mappings from the specified project
            $allMappings = Get-FlyAllProjectMappings -ProjectId $targetProject.Id
            #Match the project mapping list between csv file and specified project
            if ($Mappings) {
                $targetMappings = Get-FlyMappingsFromCsv -Path $Mappings
                foreach ($target in $targetMappings) {
                    foreach ($mapping in $allMappings) {
                        $sourceIdentity = [System.Web.HttpUtility]::UrlDecode($target.'Source')
                        $destinationIdentity = [System.Web.HttpUtility]::UrlDecode($target.'Destination')
                        if ($mapping.SourceIdentity -eq $sourceIdentity -and $mapping.DestinationIdentity -eq $destinationIdentity) {
                            [void]$result.Add($mapping);
                            break;
                        }
                    }
                }
            }
            else {
                $result = @($allMappings)
            }
            if ($result.Count -gt 0) {
                $folderPath = [System.IO.Path]::GetDirectoryName($OutFile)
                If (-not (Test-Path $folderPath)) {
                    # Folder does not exist, create it
                    [void](New-Item -Path $folderPath -ItemType Directory)
                }
                #Output the matched project mappings to specified file path in csv format
                $result | ForEach-Object {
                    Convert-FlyMappingStatus -Mapping $_
                } | Export-Csv -Path $OutFile -NoTypeInformation
                Write-Host 'Successfully retrieved the migration mappings. File path:' $OutFile -ForegroundColor Green
            }
            else {
                throw 'No mapping in the CSV file matches the existing migration mappings in this project.'
            }
        }
        Catch {
            Write-Host 'Failed to retrieve the migration mappings.' -ForegroundColor Red
            ErrorDetail -Error $_
            throw
        }
    }
}

<#
.SYNOPSIS
 
Generate migration report for the specified project mappings.
 
.DESCRIPTION
 
Generate migration report for the specified project mappings.
 
.PARAMETER Project
Specify the name of the project to generate their migration report.
 
.PARAMETER OutFolder
Specify the folder path of migration report file to download.
 
.PARAMETER FileType
Specify the format of the generated report file, CSV or Excel, optional for CSV type.
 
.PARAMETER Mappings
Specify the csv file to filter specific project mappings to generate report, for all mappings of the project if not specified.
 
.PARAMETER TimeZoneOffset
Specify the UTC time offset of current browser. This value will be used to adjust time values when generating the report file, optional for UTC timezone.
 
.PARAMETER Include
Specify a list of objects to be included in the migration report, use Tab for available values, optional if you do not export object details.
 
.OUTPUTS
 
None
#>

function Export-FlyExchangeMigrationReport {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [String]
        ${Project},
        [Parameter(Mandatory = $true)]
        [String]
        ${OutFolder},
        [Parameter(Mandatory = $false)]
        [String]
        ${Mappings},
        [Parameter(Mandatory = $false)]
        [ValidateSet('CSV', 'Excel')]
        [String]
        ${FileType} = [ReportFileType]::CSV,
        [Parameter(Mandatory = $false)]
        [Int32]
        ${TimeZoneOffset},
        [Parameter(Mandatory = $false)]
        [ValidateSet('FailedObjects', 'WarningObjects', 'SuccessfulObjects', 'SkippedObjects', 'FilterOutObjects', 'NotFoundObjects', 'ErrorIgnoredObjects')]
        [String[]]
        ${Include}
    )

    Process {
        'Calling method: Export-FlyExchangeMigrationReport' | Write-Debug
        $PSBoundParameters | Out-DebugParameter | Write-Debug
        Try {
            $targetProject = Get-FlyProjectByName -ProjectName $Project -PlatformType 'Exchange'
            $targetMappings = Get-FlyExchangeMappings -ProjectId $targetProject.Id -Mappings $Mappings
            #Construct the settings of report job
            $reportSetting = [PSCustomObject]@{
                "includeMappingSummary" = $true
                "includeDetails"        = $false
                "reportItemStatus"      = @()
                "reportFileType"        = $FileType
                "isSelectAll"           = $true
                "mappingIds"            = @()
                "timeZone"              = $TimeZoneOffset
            }
            if ($Include -and $Include.Count -gt 0) {
                $reportSetting.includeDetails = $true
                $reportSetting.reportItemStatus = $Include
            }
            if ($targetMappings -and @($targetMappings).Count -gt 0) {
                $mappingIds = $targetMappings | Select-Object -Property Id | ForEach-Object { "$($_.Id)" }
                $reportSetting.mappingIds = @($mappingIds)
                $reportSetting.isSelectAll = $false
            }
            #Trigger the migration report job and get the job id
            $jobId = Start-FlyExchangeReportJob -ProjectId $targetProject.Id -GenerateReportSettingsModel $reportSetting
            #Monitor the job status and download the report file when job is finished
            while ($true) {
                Write-Host 'The report generation job is running.' -ForegroundColor Green
                Start-Sleep -Seconds 60
                $job = Get-FlyReportJobs -RequestBody @($jobId)
                $jobStatus = $job.data[0].Status
                if ($jobStatus -eq [MappingJobStatus]::Finished -or $jobStatus -eq [MappingJobStatus]::FinishedWithException) {
                    Write-Host 'The report generation job is finished.' -ForegroundColor Green
                    $result = Get-FlyReportUrl -JobId $jobId
                    if ($null -ne $result.ReportUrl) {
                        $fileName = Split-Path $([uri]$result.ReportUrl).AbsolutePath -Leaf
                        $filePath = Join-Path -Path $OutFolder -ChildPath $fileName
                        If (-not (Test-Path $OutFolder)) {
                            # Folder does not exist, create it
                            [void](New-Item -Path $OutFolder -ItemType Directory)
                        }
                        Invoke-WebRequest -URI $result.ReportUrl -OutFile $filePath -UseBasicParsing
                        Write-Host 'Successfully downloaded the job report. Report path:' $filePath -ForegroundColor Green
                    }
                    break;
                }
                elseif ($jobStatus -eq [MappingJobStatus]::Failed -or $jobStatus -eq [MappingJobStatus]::Stopped) {
                    throw ('The report generation job is {0} with id {1}' -f [MappingJobStatus].GetEnumName($jobStatus), $job.data[0].JobName)
                }
            }
        }
        Catch {
            Write-Host 'Failed to generate the migration report.' -ForegroundColor Red
            ErrorDetail -Error $_
            throw
        }
    }
}

<#
.SYNOPSIS
 
Start a pre-scan job against the selected project mappings.
 
.DESCRIPTION
 
Start a pre-scan job against the selected project mappings.
 
.PARAMETER Project
Specify the name of the project to run job.
 
.PARAMETER Mappings
Specify the csv file to filter specific project mappings to run job, for all mappings of the project if not specified.
 
.OUTPUTS
 
A Boolean value indicates whether the work has started successfully
#>

function Start-FlyExchangePreScan {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [String]
        ${Project},
        [Parameter(Mandatory = $false)]
        [String]
        ${Mappings}
    )

    Process {
        'Calling method: Start-FlyExchangePreScan' | Write-Debug
        $PSBoundParameters | Out-DebugParameter | Write-Debug
        Try {
            $targetProject = Get-FlyProjectByName -ProjectName $Project
            $targetMappings = Get-FlyExchangeMappings -ProjectId $targetProject.Id -Mappings $Mappings
            #Construct the settings of the migration job
            $jobSettings = [PSCustomObject]@{
                "type"        = [MappingJobType]::Assessment
                "isSelectAll" = $true
                "mappingIds"  = @()
            }
            if ($targetMappings -and @($targetMappings).Count -gt 0) {
                $mappingIds = $targetMappings | Select-Object -Property Id | ForEach-Object { "$($_.Id)" }
                $jobSettings.mappingIds = @($mappingIds)
                $jobSettings.isSelectAll = $false
            }
            $result = Start-FlyExchangePreScanJob -ProjectId $targetProject.Id -ProjectMappingOperationModel $jobSettings
            if ($result) {
                Write-Host 'The job has started.' -ForegroundColor Green
            }
        }
        Catch {
            Write-Host 'Failed to start the job.' -ForegroundColor Red
            ErrorDetail -Error $_
            throw
        }
    }
}

<#
.SYNOPSIS
 
Start a verify job against the selected project mappings.
 
.DESCRIPTION
 
Start a verify job against the selected project mappings.
 
.PARAMETER Project
Specify the name of the project to run job.
 
.PARAMETER Mappings
Specify the csv file to filter specific project mappings to run job, for all mappings of the project if not specified.
 
.OUTPUTS
 
A Boolean value indicates whether the job has started successfully
#>

function Start-FlyExchangeVerification {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [String]
        ${Project},
        [Parameter(Mandatory = $false)]
        [String]
        ${Mappings}
    )

    Process {
        'Calling method: Start-FlyExchangeVerification' | Write-Debug
        $PSBoundParameters | Out-DebugParameter | Write-Debug
        Try {
            $targetProject = Get-FlyProjectByName -ProjectName $Project
            $targetMappings = Get-FlyExchangeMappings -ProjectId $targetProject.Id -Mappings $Mappings
            #Construct the settings of the migration job
            $jobSettings = [PSCustomObject]@{
                "type"        = [MappingJobType]::Validation
                "isSelectAll" = $true
                "mappingIds"  = @()
            }
            if ($targetMappings -and @($targetMappings).Count -gt 0) {
                $mappingIds = $targetMappings | Select-Object -Property Id | ForEach-Object { "$($_.Id)" }
                $jobSettings.mappingIds = @($mappingIds)
                $jobSettings.isSelectAll = $false
            }
            $result = Start-FlyExchangeVerificationJob -ProjectId $targetProject.Id -ProjectMappingOperationModel $jobSettings
            if ($result) {
                Write-Host 'The job has started.' -ForegroundColor Green
            }
        }
        Catch {
            Write-Host 'Failed to start the job.' -ForegroundColor Red
            ErrorDetail -Error $_
            throw
        }
    }
}

<#
.SYNOPSIS
 
Start a migration job against the selected project mappings.
 
.DESCRIPTION
 
Start a migration job against the selected project mappings.
 
.PARAMETER Project
Specify the name of the project to run job.
 
.PARAMETER Mode
Specify the mode of the migration job, use Tab for available values.
 
.PARAMETER Mappings
Specify the csv file to filter specific project mappings to run job, for all mappings of the project if not specified.
 
.PARAMETER ScheduleTime
Specify the time when you want the job to be scheduled. By default the job will be executed as soon as possible, optional for no schedule.
 
.OUTPUTS
 
A Boolean value indicates whether the job has started successfully
#>

function Start-FlyExchangeMigration {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [String]
        ${Project},
        [Parameter(Mandatory = $true)]
        [ValidateSet('FullMigration', 'IncrementalMigration', 'ErrorOnly', 'PermissionOnly')]
        [String]
        ${Mode},
        [Parameter(Mandatory = $false)]
        [String]
        ${Mappings},
        [Parameter(Mandatory = $false)]
        [Datetime]
        ${ScheduleTime}
    )

    Process {
        'Calling method: Start-FlyExchangeMigration' | Write-Debug
        $PSBoundParameters | Out-DebugParameter | Write-Debug
        Try {
            $targetProject = Get-FlyProjectByName -ProjectName $Project
            $targetMappings = Get-FlyExchangeMappings -ProjectId $targetProject.Id -Mappings $Mappings
            #Construct the settings of the migration job
            $jobSettings = [PSCustomObject]@{
                "type"          = $Mode
                "scheduledTime" = 0
                "isSelectAll"   = $true
                "mappingIds"    = @()
            }
            if ($targetMappings -and @($targetMappings).Count -gt 0) {
                $mappingIds = $targetMappings | Select-Object -Property Id | ForEach-Object { "$($_.Id)" }
                $jobSettings.mappingIds = @($mappingIds)
                $jobSettings.isSelectAll = $false
            }
            if ($ScheduleTime) {
                $jobSettings.scheduledTime = $ScheduleTime.Ticks
            }
            $result = Start-FlyExchangeMigrationJob -ProjectId $targetProject.Id -MigrationJobSettingsModel $jobSettings
            if ($result) {
                Write-Host 'The job has started.' -ForegroundColor Green
            }
        }
        Catch {
            Write-Host 'Failed to start the job.' -ForegroundColor Red
            ErrorDetail -Error $_
            throw
        }
    }
}