functions/Invoke-BapEnvironmentInstallD365App.ps1
<# .SYNOPSIS Invoke the installation of a D365 App in a given environment .DESCRIPTION Enables the invocation of the installation process against the PowerPlatform API (https://api.powerplatform.com) The cmdlet will keep requesting the status of all invoked installations, until they all have a NON "Running" state It will request this status every 60 seconds .PARAMETER EnvironmentId The id of the environment that you want to work against This can be obtained from the Get-BapEnvironment cmdlet .PARAMETER PackageId The id of the package(s) that you want to have Installed It supports id of current packages, with updates available and new D365 apps It support an array as input, so it can invoke multiple D365 App installations .EXAMPLE PS C:\> Invoke-BapEnvironmentInstallD365App -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -PackageId 'be69fc64-7393-4c3c-8908-2a1c2e53aef9','6defa8de-87f9-4478-8f9a-a7d685394e24' This will install the 2 x D365 Apps, based on the Ids supplied. It will run the cmdlet and have it get the status of the installation progress until all D365 Apps have been fully installed. Sample output (Install initialized): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Running 02/03/2024 13.42.07 02/03/2024 13.42.16 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Running 02/03/2024 13.42.09 02/03/2024 13.42.12 6885e0f4-639f-4ebc-b21e-49ce5d5e920d Sample output (Partly succeeded installation): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Succeeded 02/03/2024 13.42.07 02/03/2024 13.44.48 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Running 02/03/2024 13.42.09 02/03/2024 13.45.55 6885e0f4-639f-4ebc-b21e-49ce5d5e920d Sample output (Completely succeeded installation): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Succeeded 02/03/2024 13.42.07 02/03/2024 13.44.48 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Succeeded 02/03/2024 13.42.09 02/03/2024 13.48.26 6885e0f4-639f-4ebc-b21e-49ce5d5e920d .EXAMPLE PS C:\> $appIds = @(Get-BapEnvironmentD365App -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -InstallState Installed -UpdatesOnly | Select-Object -ExpandProperty PackageId) PS C:\> Invoke-BapEnvironmentInstallD365App -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -PackageId $appIds This will find all D365 Apps that has a pending update available. It will gather the Ids into an array. It will run the cmdlet and have it get the status of the installation progress until all D365 Apps have been fully installed. Sample output (Install initialized): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Running 02/03/2024 13.42.07 02/03/2024 13.42.16 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Running 02/03/2024 13.42.09 02/03/2024 13.42.12 6885e0f4-639f-4ebc-b21e-49ce5d5e920d Sample output (Partly succeeded installation): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Succeeded 02/03/2024 13.42.07 02/03/2024 13.44.48 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Running 02/03/2024 13.42.09 02/03/2024 13.45.55 6885e0f4-639f-4ebc-b21e-49ce5d5e920d Sample output (Completely succeeded installation): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Succeeded 02/03/2024 13.42.07 02/03/2024 13.44.48 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Succeeded 02/03/2024 13.42.09 02/03/2024 13.48.26 6885e0f4-639f-4ebc-b21e-49ce5d5e920d .EXAMPLE PS C:\> $apps = @(Get-BapEnvironmentD365App -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -InstallState Installed -UpdatesOnly) PS C:\> Invoke-BapEnvironmentInstallD365App -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -PackageId $apps.PackageId This will find all D365 Apps that has a pending update available. It will gather the Ids into an array. It will run the cmdlet and have it get the status of the installation progress until all D365 Apps have been fully installed. Sample output (Install initialized): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Running 02/03/2024 13.42.07 02/03/2024 13.42.16 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Running 02/03/2024 13.42.09 02/03/2024 13.42.12 6885e0f4-639f-4ebc-b21e-49ce5d5e920d Sample output (Partly succeeded installation): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Succeeded 02/03/2024 13.42.07 02/03/2024 13.44.48 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Running 02/03/2024 13.42.09 02/03/2024 13.45.55 6885e0f4-639f-4ebc-b21e-49ce5d5e920d Sample output (Completely succeeded installation): status createdDateTime lastActionDateTime error statusMessage operationId ------ --------------- ------------------ ----- ------------- ----------- Succeeded 02/03/2024 13.42.07 02/03/2024 13.44.48 5c80df7f-d89e-42bd-abeb-98e577ae49f4 Succeeded 02/03/2024 13.42.09 02/03/2024 13.48.26 6885e0f4-639f-4ebc-b21e-49ce5d5e920d .NOTES Author: Mötz Jensen (@Splaxi) #> function Invoke-BapEnvironmentInstallD365App { [CmdletBinding()] param ( [parameter (mandatory = $true)] [string] $EnvironmentId, [parameter (mandatory = $true)] [string[]] $PackageId ) begin { # Make sure all *BapEnvironment* cmdlets will validate that the environment exists prior running anything. $envObj = Get-BapEnvironment -EnvironmentId $EnvironmentId | Select-Object -First 1 if ($null -eq $envObj) { $messageString = "The supplied EnvironmentId: <c='em'>$EnvironmentId</c> didn't return any matching environment details. Please verify that the EnvironmentId is correct - try running the <c='em'>Get-BapEnvironment</c> cmdlet." Write-PSFMessage -Level Host -Message $messageString Stop-PSFFunction -Message "Stopping because environment found based on the id." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } if (Test-PSFFunctionInterrupt) { return } # First we will fetch ALL available apps for the environment $tokenPowerApi = Get-AzAccessToken -ResourceUrl "https://api.powerplatform.com/" $headersPowerApi = @{ "Authorization" = "Bearer $($tokenPowerApi.Token)" } $appsAvailable = Get-BapEnvironmentD365App -EnvironmentId $EnvironmentId } process { if (Test-PSFFunctionInterrupt) { return } [System.Collections.Generic.List[System.Object]] $arrInstallStarted = @() [System.Collections.Generic.List[System.Object]] $arrStatus = @() [System.Collections.Generic.List[System.Object]] $arrFailedStarts = @() $headersPowerApi."Content-Type" = "application/json;charset=utf-8" foreach ($pgkId in $PackageId) { $appToBeInstalled = $appsAvailable | Where-Object Id -eq $pgkId | Select-Object -First 1 if ($null -eq $appToBeInstalled) { $messageString = "The combination of the supplied EnvironmentId: <c='em'>$EnvironmentId</c> and PackageId: <c='em'>$PackageId</c> didn't return any matching D365App. Please verify that the EnvironmentId & PackageId is correct - try running the <c='em'>Get-BapEnvironmentD365App</c> cmdlet." Write-PSFMessage -Level Host -Message $messageString Stop-PSFFunction -Message "Stopping because environment and d365app combination was NOT found based on the supplied parameters." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) } $body = $appToBeInstalled | ConvertTo-Json try { $resIntall = Invoke-RestMethod -Method Post -Uri "https://api.powerplatform.com/appmanagement/environments/$EnvironmentId/applicationPackages/$($appToBeInstalled.uniqueName)/install?api-version=2022-03-01-preview" -Headers $headersPowerApi -Body $body $arrInstallStarted.Add($resIntall) } catch { $arrFailedStarts.Add($appToBeInstalled) } } if ($arrFailedStarts.Count -gt 0) { $messageString = "The following packages <c='em'>failed to start</c>:" Write-PSFMessage -Level Host -Message $messageString $arrFailedStarts.ToArray() } do { $tokenPowerApi = Get-AzAccessToken -ResourceUrl "https://api.powerplatform.com/" $headersPowerApi = @{ "Authorization" = "Bearer $($tokenPowerApi.Token)" } Start-Sleep -Seconds 60 # Write-PSFMessage -Level Host -Message "Checking for running operations" $arrStatus = @() foreach ($operation in $arrInstallStarted) { $resInstallOperation = Invoke-RestMethod -Method Get -Uri "https://api.powerplatform.com/appmanagement/environments/$EnvironmentId/operations/$($operation.lastOperation.operationId)?api-version=2022-03-01-preview" -Headers $headersPowerApi $arrStatus.Add($resInstallOperation) } $arrStatus | Format-Table } while ("Running" -in $arrStatus.status) } end { } } |