protected override void ExecuteCmdlet() { var sitesProvisioned = new List <ProvisionedSite>(); var configuration = new ApplyConfiguration(); if (ParameterSpecified(nameof(Configuration))) { configuration = Configuration.GetConfiguration(SessionState.Path.CurrentFileSystemLocation.Path); } configuration.SiteProvisionedDelegate = (title, url) => { if (sitesProvisioned.FirstOrDefault(s => s.Url == url) == null) { sitesProvisioned.Add(new ProvisionedSite() { Title = title, Url = url }); } }; if (ParameterSpecified(nameof(Handlers))) { if (!Handlers.Has(Handlers.All)) { foreach (var enumValue in (Handlers[])Enum.GetValues(typeof(Handlers))) { if (Handlers.Has(enumValue)) { if (enumValue == Handlers.TermGroups) { configuration.Handlers.Add(ConfigurationHandler.Taxonomy); } else if (enumValue == Handlers.PageContents) { configuration.Handlers.Add(ConfigurationHandler.Pages); } else if (Enum.TryParse <ConfigurationHandler>(enumValue.ToString(), out ConfigurationHandler configHandler)) { configuration.Handlers.Add(configHandler); } } } } } if (ParameterSpecified(nameof(ExcludeHandlers))) { foreach (var handler in (Handlers[])Enum.GetValues(typeof(Handlers))) { if (!ExcludeHandlers.Has(handler) && handler != Handlers.All) { if (handler == Handlers.TermGroups) { if (configuration.Handlers.Contains(ConfigurationHandler.Taxonomy)) { configuration.Handlers.Remove(ConfigurationHandler.Taxonomy); } else if (Enum.TryParse <ConfigurationHandler>(handler.ToString(), out ConfigurationHandler configHandler)) { if (configuration.Handlers.Contains(configHandler)) { configuration.Handlers.Remove(configHandler); } } } } } } if (ExtensibilityHandlers != null) { configuration.Extensibility.Handlers = ExtensibilityHandlers.ToList(); } configuration.ProgressDelegate = (message, step, total) => { if (message != null) { var percentage = Convert.ToInt32((100 / Convert.ToDouble(total)) * Convert.ToDouble(step)); progressRecord.Activity = $"Applying template to tenant"; progressRecord.StatusDescription = message; progressRecord.PercentComplete = percentage; progressRecord.RecordType = ProgressRecordType.Processing; WriteProgress(progressRecord); } }; var warningsShown = new List <string>(); configuration.MessagesDelegate = (message, type) => { switch (type) { case ProvisioningMessageType.Warning: { if (!warningsShown.Contains(message)) { WriteWarning(message); warningsShown.Add(message); } break; } case ProvisioningMessageType.Progress: { if (message != null) { var activity = message; if (message.IndexOf("|") > -1) { var messageSplitted = message.Split('|'); if (messageSplitted.Length == 4) { var current = double.Parse(messageSplitted[2]); var total = double.Parse(messageSplitted[3]); subProgressRecord.RecordType = ProgressRecordType.Processing; subProgressRecord.Activity = string.IsNullOrEmpty(messageSplitted[0]) ? "-" : messageSplitted[0]; subProgressRecord.StatusDescription = string.IsNullOrEmpty(messageSplitted[1]) ? "-" : messageSplitted[1]; subProgressRecord.PercentComplete = Convert.ToInt32((100 / total) * current); WriteProgress(subProgressRecord); } else { subProgressRecord.Activity = "Processing"; subProgressRecord.RecordType = ProgressRecordType.Processing; subProgressRecord.StatusDescription = activity; subProgressRecord.PercentComplete = 0; WriteProgress(subProgressRecord); } } else { subProgressRecord.Activity = "Processing"; subProgressRecord.RecordType = ProgressRecordType.Processing; subProgressRecord.StatusDescription = activity; subProgressRecord.PercentComplete = 0; WriteProgress(subProgressRecord); } } break; } case ProvisioningMessageType.Completed: { WriteProgress(new ProgressRecord(1, message, " ") { RecordType = ProgressRecordType.Completed }); break; } } }; configuration.PropertyBag.OverwriteSystemValues = OverwriteSystemPropertyBagValues; configuration.Lists.IgnoreDuplicateDataRowErrors = IgnoreDuplicateDataRowErrors; configuration.Navigation.ClearNavigation = ClearNavigation; configuration.ContentTypes.ProvisionContentTypesToSubWebs = ProvisionContentTypesToSubWebs; configuration.Fields.ProvisionFieldsToSubWebs = ProvisionFieldsToSubWebs; ProvisioningHierarchy hierarchyToApply = null; switch (ParameterSetName) { case ParameterSet_PATH: { hierarchyToApply = GetHierarchy(); break; } case ParameterSet_OBJECT: { hierarchyToApply = Template; if (ResourceFolder != null) { var fileSystemConnector = new FileSystemConnector(ResourceFolder, ""); hierarchyToApply.Connector = fileSystemConnector; } else { if (Path != null) { if (!System.IO.Path.IsPathRooted(Path)) { Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path); } } else { Path = SessionState.Path.CurrentFileSystemLocation.Path; } var fileInfo = new FileInfo(Path); var fileConnector = new FileSystemConnector(fileInfo.DirectoryName, ""); hierarchyToApply.Connector = fileConnector; } break; } } if (Parameters != null) { foreach (var parameter in Parameters.Keys) { if (hierarchyToApply.Parameters.ContainsKey(parameter.ToString())) { hierarchyToApply.Parameters[parameter.ToString()] = Parameters[parameter].ToString(); } else { hierarchyToApply.Parameters.Add(parameter.ToString(), Parameters[parameter].ToString()); } } } #if !ONPREMISES // check if consent is needed and in place var consentRequired = false; if (hierarchyToApply.Teams != null) { consentRequired = true; } if (hierarchyToApply.AzureActiveDirectory != null) { consentRequired = true; } if (consentRequired) { // try to retrieve an access token for the Microsoft Graph: var accessToken = PnPConnection.CurrentConnection.TryGetAccessToken(Enums.TokenAudience.MicrosoftGraph); if (accessToken == null) { if (PnPConnection.CurrentConnection.PSCredential != null) { // Using normal credentials accessToken = TokenHandler.AcquireToken("graph.microsoft.com", null); } if (accessToken == null) { throw new PSInvalidOperationException("Your template contains artifacts that require an access token. Please provide consent to the PnP Management Shell application first by executing: Connect-PnPOnline -Graph -LaunchBrowser"); } } } using (var provisioningContext = new PnPProvisioningContext((resource, scope) => { if (resource.ToLower().StartsWith("https://")) { var uri = new Uri(resource); resource = uri.Authority; } // Get Azure AD Token if (PnPConnection.CurrentConnection != null) { if (resource.Equals("graph.microsoft.com", StringComparison.OrdinalIgnoreCase)) { var graphAccessToken = PnPConnection.CurrentConnection.TryGetAccessToken(Enums.TokenAudience.MicrosoftGraph); if (graphAccessToken != null) { // Authenticated using -Graph or using another way to retrieve the accesstoken with Connect-PnPOnline return(Task.FromResult(graphAccessToken)); } } } if (PnPConnection.CurrentConnection.PSCredential != null) { // Using normal credentials return(Task.FromResult(TokenHandler.AcquireToken(resource, null))); } else { // No token... throw new PSInvalidOperationException("Your template contains artifacts that require an access token. Please provide consent to the PnP Management Shell application first by executing: Connect-PnPOnline -Graph -LaunchBrowser"); } })) { #endif if (!string.IsNullOrEmpty(SequenceId)) { Tenant.ApplyTenantTemplate(hierarchyToApply, SequenceId, configuration); } else { if (hierarchyToApply.Sequences.Count > 0) { foreach (var sequence in hierarchyToApply.Sequences) { Tenant.ApplyTenantTemplate(hierarchyToApply, sequence.ID, configuration); } } else { Tenant.ApplyTenantTemplate(hierarchyToApply, null, configuration); } } #if !ONPREMISES } #endif WriteObject(sitesProvisioned, true); }
public void ProvisionTenantTemplate() { if (TestCommon.AppOnlyTesting()) { Assert.Inconclusive("This test does not yet work with app-only due to group connected site creation"); } string tenantNameParamValue = new Uri(TestCommon.DevSiteUrl).DnsSafeHost.Split('.')[0]; string accountDomainParamValue = TestCommon.O365AccountDomain; if (string.IsNullOrEmpty(accountDomainParamValue)) { accountDomainParamValue = "contoso.com"; } var resourceFolder = string.Format(@"{0}\..\..\..\Resources\Templates", AppDomain.CurrentDomain.BaseDirectory); XMLTemplateProvider provider = new XMLFileSystemTemplateProvider(resourceFolder, ""); var existingTemplate = provider.GetTemplate("ProvisioningSchema-2021-03-FullSample-01.xml"); Guid siteGuid = Guid.NewGuid(); int siteId = siteGuid.GetHashCode(); var template = new ProvisioningTemplate { Id = "TestTemplate" }; template.Lists.Add(new ListInstance() { Title = "Testlist", TemplateType = 100, Url = "lists/testlist" }); template.TermGroups.AddRange(existingTemplate.TermGroups); ProvisioningHierarchy hierarchy = new ProvisioningHierarchy(); hierarchy.Templates.Add(template); hierarchy.Parameters.Add("CompanyName", "Contoso"); if (!string.IsNullOrEmpty(tenantNameParamValue)) { hierarchy.Parameters.Add("O365TenantName", tenantNameParamValue); } if (!string.IsNullOrEmpty(accountDomainParamValue)) { hierarchy.Parameters.Add("O365AccountDomain", accountDomainParamValue); } var sequence = new ProvisioningSequence { ID = Guid.NewGuid().ToString(), TermStore = new ProvisioningTermStore() }; var termGroup = new TermGroup() { Name = "Contoso TermGroup" }; var termSet = new TermSet() { Name = "Projects", Id = Guid.NewGuid(), IsAvailableForTagging = true, Language = 1033 }; var term = new Term() { Name = "Contoso Term" }; termSet.Terms.Add(term); // termGroup.TermSets.Add(termSet); var existingTermSet = existingTemplate.TermGroups[0].TermSets[0]; termGroup.TermSets.Add(existingTermSet); // sequence.TermStore.TermGroups.Add(termGroup); var teamSite1 = new TeamSiteCollection() { Alias = $"prov-1-{siteId}", Description = "prov-1", DisplayName = "prov-1", IsHubSite = false, IsPublic = false, Title = "prov-1", }; teamSite1.Templates.Add("TestTemplate"); var subsite = new TeamNoGroupSubSite() { Description = "Test Sub", Url = "testsub1", Language = 1033, TimeZoneId = 4, Title = "Test Sub", UseSamePermissionsAsParentSite = true }; subsite.Templates.Add("TestTemplate"); teamSite1.Sites.Add(subsite); sequence.SiteCollections.Add(teamSite1); var teamSite2 = new TeamSiteCollection() { Alias = $"prov-2-{siteId}", Description = "prov-2", DisplayName = "prov-2", IsHubSite = false, IsPublic = false, Title = "prov-2" }; teamSite2.Templates.Add("TestTemplate"); sequence.SiteCollections.Add(teamSite2); hierarchy.Sequences.Add(sequence); using (var tenantContext = TestCommon.CreateTenantClientContext()) { var applyConfiguration = new ApplyConfiguration { ProgressDelegate = (message, step, total) => { if (message != null) { } } }; var tenant = new Tenant(tenantContext); tenant.ApplyTenantTemplate(hierarchy, sequence.ID, applyConfiguration); } }