PnP – Modern Site Provisioning
Das automatische Erstellen von Websitesammlungen ist seit je her ein wichtiger Anwendungsfall im SharePoint Umfeld. Auch mit den modernen Team- und Communication Sites im SharePoint Online ändert sich das nicht. Aus diesem Grund hat das SharePoint Pattern & Practise Team eine moderne Provisioning Engine geschaffen.
Inspiriert von dem Beispiel unter https://github.com/SharePoint/PnP/tree/master/Samples/Provisioning.Cloud.Modern.Async habe ich bereits in meinem vorherigen Blogartikel das Erstellen von Provisionierungsaufträgen mit Azure Funktions und den Azure Storage Emulator beschrieben: https://blog.hansevision.com/aus-der-praxis-azure-coding-lokale-workbench.
Nun kommen wir zu dem Teil im Scenario, in dem aus den Aufträgen neue SharePoint Online Sites erstellt und darin SharePoint Artefakte angelegt werden. Die PnP Provisioning Engine arbeitet mit einer XML-Definition, die praktischerweise aus einer vorkonfigurierten Site Collection extrahiert werden kann. Das erspart viel Schreibarbeit.
Im ersten Schritt generieren wir also ein XML Template aus einer bestehenden, konfigurierten Site Collection. Dies erfolgt mit Hilfe der PnP PowerShell.
1. Installation der PnP PowerShell
Mit folgendem Befehl wir die PnP Powershell installiert:
Install-Module SharePointPnPPowerShellOnline
2. Skript zum Extrahieren des Templates aufrufen
Mit dem nachfolgenden Skript wird nun aus einer konfigurierten Site Collection das Template my_template.xml extrahiert.
# Variables definition
$tenant = "hansevisiondev";
$sourceSite = "/sites/comsite1/";
$templateFile = "C:\templates\my_temnplate.xml";
# Login
$webUrl = "https://{0}.sharepoint.com{1}/" -f $tenant, $sourceSite;
Write-Output $("Connecting to {0}" -f $webUrl);
Connect-PnPOnline -Url $webUrl -Credentials WCMStoredCredentials;
# Save Template
Write-Output "Saving the template to XML file";
Get-PnPProvisioningTemplate -Out
$templateFile -PersistBrandingFiles -PersistPublishingFiles;
Der Fortschritt der Template Generierung wird ein einer Fortschrittsanzeige präsentiert. Das ist auch gut so, denn der Vorgang dauert etwas länger.
Anschließend kann die exportierte Template Definition aus dem Dateisystem für die weitere Verwendung entnommen werden.
Bei der Anwendung des Templates auf eine neue Site Collection werden die Konfigurationen und Inhalte entsprechend erstellt. (Hier bspw. eine angepasste Liste “My favorite Docs”)
Auf folgender Seite ist die neuste Version des PnP Provisioning Schemas detailliert beschrieben. https://github.com/SharePoint/PnP-Provisioning-Schema/blob/master/ProvisioningSchema-2018-01.md.
Der Umfang der berücksichtigten Artefakte ist schon beachtlich.
3. Template anwenden
Nach dem erfolgreichen Erstellen des Template kann nun eine neue Site Collection damit erstellt werden. Dazu nutze ich eine Website, die später in Azure gehostet werden kann und Aufträge in eine Queue schreibt.
Eine – derzeit lokale – Azure Function greift die Aufträge aus der Queue ab und erstellt die SharePoint Online Site Collection. Anschließend wird das Template darauf angewendet.
Dies geschieht mit folgendem Code.
using (var siteContext = authManager.GetAzureADAccessTokenAuthenticatedContext(
siteUrl, modernSite.UserAccessToken))
{
var web = siteContext.Web;
siteContext.Load(web);
siteContext.ExecuteQueryRetry();
logInfo?.Invoke($"Getting templates from path: {templatesPath}");
try
{
XMLTemplateProvider provider =
new XMLFileSystemTemplateProvider(templatesPath, "Templates");
var template = provider.GetTemplate(modernSite.PnPTemplate);
template.Connector = provider.Connector;
var ptai = new ProvisioningTemplateApplyingInformation();
ptai.MessagesDelegate += delegate (
string message, ProvisioningMessageType messageType)
{
logInfo?.Invoke($"{messageType} - {message}");
};
ptai.ProgressDelegate += delegate (string message, int step, int total)
{
logInfo?.Invoke($"{step:00}/{total:00} - {message}");
};
logInfo?.Invoke($"Provisioning Started: {DateTime.Now:hh.mm.ss}");
web.ApplyProvisioningTemplate(template, ptai);
logInfo?.Invoke($"Provisioning Completed: {DateTime.Now:hh.mm.ss}");
}
catch (Exception ex)
{
logError?.Invoke($"Error on getting template {ex.ToString()}!");
}
}
Es ist gut zu erkennen, wie die Engine beim Start und nach der Fertigstellung eines Provisioning Schrittes eine Meldung ausgibt.
Ich wünsche Euch viel Spaß beim ausprobieren!