Remediation/Consolidation/CON-SITES.ps1
|
# UNTESTED: this script has never been run on a real tenant. Read it, try it on a test tenant first, and use it at your own risk. <# .SYNOPSIS Gives each site of the sources a prefixed target address, with no duplicate between sources (procedure CON-SITES). .DESCRIPTION Prefixes all the addresses with the prefix of the source, even those not in conflict. Sets aside the technical sites that are not copied: host, search, catalog, redirect, publishing and channels (they follow their team). Read only: no connection. Writes decisions\CON-SITES.csv, which feeds the mapping plan of the copy tool and that CMP-SITE-URLS, SPO-LARGE-SITES and TMS-GUESTS read. The sites excluded by SPO-INACTIVE keep a row there, marked Excluded. Limits: the site address of a team follows from the group alias, to coordinate with CON-ALIASES. The rule is validated during the POC. #> $c = Open-TcRemediation $TechnicalSites = '^(SPSMSITEHOST|SRCHCEN|APPCATALOG|POINTPUBLISHING|REDIRECTSITE|TEAMCHANNEL)' $InactiveFile = 'SPO-INACTIVE' $excludedItems = @{} if (Test-TcDecisionFile $InactiveFile) { foreach ($l in Read-TcDecisionRow $InactiveFile) { if ((Get-TcMember $l 'Decision') -in 'Read only', 'Archive', 'Delete') { $excludedItems[((Get-TcText $l 'Site')).TrimEnd('/').ToLowerInvariant()] = 1 } } } function ConvertTo-TargetSegment { <# Last segment of the address, with no accent or space, prefixed once only. #> param([string]$Url, [string]$Prefix) $pathValue = [uri]::UnescapeDataString(($Url.TrimEnd('/') -replace '^https://[^/]+', '')) $segment = ($pathValue -split '/')[-1] if (-not $segment) { $segment = 'Root' } $segment = (($segment -replace '[\p{Cs}\p{Cn}]', ' ').Normalize([System.Text.NormalizationForm]::FormD) -replace '\p{Mn}', '') -replace '[^A-Za-z0-9_.-]+', '-' return ('{0}-{1}' -f $Prefix, ($segment.Trim('-') -ireplace "^$Prefix-", '')) } $TargetHost = (Get-TcMember (Get-TcRemediationTenant 'Target') 'InitialDomain') -replace '\.onmicrosoft\.com$', '' $sources = @($c.Tenants | Where-Object { $_ -ne 'Target' }) $rows = [System.Collections.Generic.List[object]]::new() foreach ($t in $sources) { Write-TcRemediationTenant $t if (-not (Test-TcCollectionComplete $t 'sites')) { Write-TcRemediationAlert 'Incomplete site collection: the list may be partial' } $i = Get-TcRemediationTenant $t $everyone = @(Get-TcRemediationTable $t 'sites') $useful = @($everyone | Where-Object { $_['Template'] -notmatch $TechnicalSites }) Write-TcRemediationNote ("{0} site(s) to copy out of {1} read, prefix {2}-" -f $useful.Count, $everyone.Count, (Get-TcMember $i 'Prefix')) foreach ($s in $useful) { $segment = ConvertTo-TargetSegment $s['Url'] (Get-TcMember $i 'Prefix') $rows.Add([pscustomobject]@{ Tenant = $t; 'Source site' = $s['Url']; Title = $s['Title']; 'Template' = $s['Template']; 'Group site' = $(if ($s['Group']) { 'Yes' } else { 'No' }) 'Target address' = ('https://{0}.sharepoint.com/sites/{1}' -f $TargetHost, $segment); Alias = $segment Excluded = $(if ($excludedItems[([string]$s['Url']).TrimEnd('/').ToLowerInvariant()]) { 'Yes' } else { 'No' }) }) } } $shared = @(Get-TcRemediationPlanAction -Procedure 'CON-SITES' | ForEach-Object { (Get-TcMember $_ 'items') }) if ('Target' -in $c.Tenants) { Write-TcRemediationTenant 'Target' } Write-TcRemediationNote ("{0} path(s) identical in several sources according to the plan" -f $shared.Count) $duplicates = @($rows | Group-Object 'Target address' | Where-Object { (Get-TcCount $_) -gt 1 }) foreach ($g in $duplicates) { Write-TcRemediationAlert ("Duplicate target address: {0} ({1})" -f (Get-TcMember $g 'Name'), (((Get-TcMember $g 'Group') | ForEach-Object { (Get-TcMember $_ 'Source site') }) -join ' ; ')) } if (-not $duplicates.Count) { Write-TcRemediationNote ("No duplicate target address in {0}" -f $rows.Count) } Export-TcRemediationReport -Name 'site-target-addresses' -Rows @($rows) | Out-Null $decisionFolder = Get-TcDecisionFolder New-Item -ItemType Directory -Force -Path $decisionFolder | Out-Null $stable = Join-Path $decisionFolder 'CON-SITES.csv' $rows | Export-Csv -LiteralPath $stable -Encoding utf8BOM -NoTypeInformation Write-TcRemediationNote "File for the copy tool: $stable" Invoke-TcRemediationPlan Close-TcRemediation |