private static async Task <OrchestratorProjectCreateCommandResult> ProvisionAsync(IDurableOrchestrationContext functionContext, OrchestratorProjectCreateCommand command, ILogger log) { var teamCloud = await functionContext .GetTeamCloudAsync() .ConfigureAwait(true); var commandResult = command.CreateResult(); var project = commandResult.Result = command.Payload; project.Tags = teamCloud.Tags.Override(project.Tags); var projectUsers = project.Users.ToList(); var providers = await functionContext .ListProvidersAsync(project.Type.Providers.Select(p => p.Id).ToList()) .ConfigureAwait(true); var providerUserTasks = providers .Where(p => p.PrincipalId.HasValue) .Select(p => functionContext.GetUserAsync(p.PrincipalId.Value.ToString(), allowUnsafe: true)); var providerUsers = await Task.WhenAll(providerUserTasks) .ConfigureAwait(true); foreach (var u in providerUsers) { u.EnsureProjectMembership(project.Id, ProjectUserRole.Provider); } projectUsers.AddRange(providerUsers); using (await functionContext.LockContainerDocumentAsync(project).ConfigureAwait(true)) { functionContext.SetCustomStatus($"Creating project", log); project = commandResult.Result = await functionContext .CreateProjectAsync(project) .ConfigureAwait(true); functionContext.SetCustomStatus($"Adding users", log); project.Users = await Task .WhenAll(projectUsers.Select(user => functionContext.SetUserProjectMembershipAsync(user, project.Id, allowUnsafe: true))) .ConfigureAwait(true); } functionContext.SetCustomStatus($"Allocating subscription", log); var subscriptionId = await functionContext .CallActivityWithRetryAsync <Guid>(nameof(ProjectSubscriptionSelectActivity), project) .ConfigureAwait(true); functionContext.SetCustomStatus($"Initializing subscription", log); await functionContext .InitializeSubscriptionAsync(subscriptionId, waitFor : false) .ConfigureAwait(true); functionContext.SetCustomStatus($"Provisioning resources", log); var deploymentOutput = await functionContext .CallDeploymentAsync(nameof(ProjectResourcesCreateActivity), (project, subscriptionId)) .ConfigureAwait(true); using (await functionContext.LockContainerDocumentAsync(project).ConfigureAwait(true)) { functionContext.SetCustomStatus($"Provisioning identity", log); project.Identity = await functionContext .CallActivityWithRetryAsync <ProjectIdentity>(nameof(ProjectIdentityCreateActivity), project) .ConfigureAwait(true); project.ResourceGroup = new AzureResourceGroup() { SubscriptionId = subscriptionId, Region = project.Type.Region, Id = (string)deploymentOutput.GetValueOrDefault("resourceGroupId", default(string)), Name = (string)deploymentOutput.GetValueOrDefault("resourceGroupName", default(string)) }; project = commandResult.Result = await functionContext .SetProjectAsync(project) .ConfigureAwait(true); } functionContext.SetCustomStatus($"Tagging resources", log); await functionContext .CallActivityWithRetryAsync(nameof(ProjectResourcesTagActivity), project) .ConfigureAwait(true); functionContext.SetCustomStatus($"Registering required resource providers", log); await functionContext .RegisterResourceProvidersAsync(project) .ConfigureAwait(true); functionContext.SetCustomStatus($"Sending provider commands", log); var providerCommand = new ProviderProjectCreateCommand ( command.User.PopulateExternalModel(), project.PopulateExternalModel(), command.CommandId ); var providerResults = await functionContext .SendProviderCommandAsync <ProviderProjectCreateCommand, ProviderProjectCreateCommandResult>(providerCommand, project, failFast : true) .ConfigureAwait(true); var providerException = providerResults.Values? .SelectMany(result => result.Errors ?? new List <CommandError>()) .ToException(); if (providerException != null) { throw providerException; } return(commandResult); }