diff --git a/d365fo.tools/bin/d365fo.tools-index.json b/d365fo.tools/bin/d365fo.tools-index.json index 445115f7..5e1f0819 100644 --- a/d365fo.tools/bin/d365fo.tools-index.json +++ b/d365fo.tools/bin/d365fo.tools-index.json @@ -8980,7 +8980,7 @@ }, { "CommandName": "Invoke-D365SDPInstall", - "Description": "A cmdlet that wraps some of the cumbersome work into a streamlined process.\nThe process are detailed in the Microsoft documentation here:\nhttps://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/deployment/install-deployable-package", + "Description": "A cmdlet that wraps some of the cumbersome work into a streamlined process.\nThe process for a legacy (i.e. non unified) environment are detailed in the Microsoft documentation here:\nhttps://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/deployment/install-deployable-package", "Params": [ [ "Path", @@ -9077,15 +9077,60 @@ false, "false", "False" + ], + [ + "UnifiedDevelopmentEnvironment", + "Use this switch to install the package in a Unified Development Environment (UDE).", + "", + false, + "false", + "False" ] ], "Alias": "", "Author": "Tommy Skaue (@skaue)", - "Synopsis": "Invoke the AxUpdateInstaller.exe file from Software Deployable Package (SDP)", + "Synopsis": "Install a Software Deployable Package (SDP)", "Name": "Invoke-D365SDPInstall", "Links": null, - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\package.zip\" -QuickInstallAll\nThis will install the package contained in the c:\\temp\\package.zip file using a runbook in memory while executing.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -DevInstall\nThis will install the extracted package in c:\\temp\\ using a runbook in memory while executing.\nThis command is to be used on Microsoft Hosted Tier1 development environment, where you don\u0027t have access to the administrator user account on the vm.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetTopology\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Generate -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Import -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Execute -RunbookId \u0027MyRunbook\u0027\nManual operations that first create Topology XML from current environment, then generate runbook with id \u0027MyRunbook\u0027, then import it and finally execute it.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RunAll\nCreate Topology XML from current environment. Using default runbook id \u0027Runbook\u0027 and run all the operations from generate, to import to execute.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RerunStep -Step 18 -RunbookId \u0027MyRunbook\u0027\nRerun runbook with id \u0027MyRunbook\u0027 from step 18.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetStepComplete -Step 24 -RunbookId \u0027MyRunbook\u0027\nMark step 24 complete in runbook with id \u0027MyRunbook\u0027 and continue the runbook from the next step.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetTopology -TopologyFile \"c:\\temp\\MyTopology.xml\"\nUpdate the MyTopology.xml file with all the installed services on the machine.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RunAll -TopologyFile \"c:\\temp\\MyTopology.xml\" -UseExistingTopologyFile\nRun all manual steps in one single operation using the MyTopology.xml file. The topology file is not updated.", - "Syntax": "Invoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-QuickInstallAll]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-DevInstall]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [-Command] \u003cString\u003e [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\package.zip\" -QuickInstallAll\nThis will install the package contained in the c:\\temp\\package.zip file using a runbook in memory while executing.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -DevInstall\nThis will install the extracted package in c:\\temp\\ using a runbook in memory while executing.\nThis command is to be used on Microsoft Hosted Tier1 development environment, where you don\u0027t have access to the administrator user account on the vm.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetTopology\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Generate -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Import -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Execute -RunbookId \u0027MyRunbook\u0027\nManual operations that first create Topology XML from current environment, then generate runbook with id \u0027MyRunbook\u0027, then import it and finally execute it.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RunAll\nCreate Topology XML from current environment. Using default runbook id \u0027Runbook\u0027 and run all the operations from generate, to import to execute.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RerunStep -Step 18 -RunbookId \u0027MyRunbook\u0027\nRerun runbook with id \u0027MyRunbook\u0027 from step 18.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetStepComplete -Step 24 -RunbookId \u0027MyRunbook\u0027\nMark step 24 complete in runbook with id \u0027MyRunbook\u0027 and continue the runbook from the next step.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetTopology -TopologyFile \"c:\\temp\\MyTopology.xml\"\nUpdate the MyTopology.xml file with all the installed services on the machine.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RunAll -TopologyFile \"c:\\temp\\MyTopology.xml\" -UseExistingTopologyFile\nRun all manual steps in one single operation using the MyTopology.xml file. The topology file is not updated.\n-------------------------- EXAMPLE 9 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -MetaDataDir \"c:\\MyRepository\\Metadata\" -UnifiedDevelopmentEnvironment\nInstall the modules contained in the c:\\temp\\ directory into the c:\\MyRepository\\Metadata directory.", + "Syntax": "Invoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-QuickInstallAll]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-DevInstall]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [-Command] \u003cString\u003e [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [-UnifiedDevelopmentEnvironment] [\u003cCommonParameters\u003e]" + }, + { + "CommandName": "Invoke-D365SDPInstallUDE", + "Description": "A cmdlet that wraps some of the cumbersome work into a streamlined process.\nIt first checks if the package is a zip file and extracts it if necessary.\nThen it checks if the package contains the necessary files and modules.\nFinally, it extracts the module zip files into the metadata directory.", + "Params": [ + [ + "Path", + "Path to the package that you want to install into the environment\nThe cmdlet supports a path to a zip-file or directory with the unpacked contents.", + "File,Hotfix", + true, + "false", + "" + ], + [ + "MetaDataDir", + "The path to the meta data directory for the environment", + "", + true, + "false", + "" + ], + [ + "LogPath", + "The path where the log file(s) will be saved", + "LogDir", + false, + "false", + "$(Join-Path -Path $Script:DefaultTempPath -ChildPath \"Logs\\SdpInstall\")" + ] + ], + "Alias": "", + "Author": "Florian Hopfner (@FH-Inway)", + "Synopsis": "Install a Software Deployable Package (SDP) in a unified development environment", + "Name": "Invoke-D365SDPInstallUDE", + "Links": null, + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstallUDE -Path \"c:\\temp\\package.zip\" -MetaDataDir \"c:\\MyRepository\\Metadata\"\nThis will install the modules contained in the c:\\temp\\package.zip file into the c:\\MyRepository\\Metadata directory.", + "Syntax": "Invoke-D365SDPInstallUDE [-Path] \u003cString\u003e [-MetaDataDir] \u003cString\u003e [-LogPath \u003cString\u003e] [\u003cCommonParameters\u003e]" }, { "CommandName": "Invoke-D365SeleniumDownload", diff --git a/d365fo.tools/d365fo.tools.psd1 b/d365fo.tools/d365fo.tools.psd1 index 3563d5e7..42054bbb 100644 --- a/d365fo.tools/d365fo.tools.psd1 +++ b/d365fo.tools/d365fo.tools.psd1 @@ -241,6 +241,7 @@ 'Invoke-D365RunbookAnalyzer', 'Invoke-D365SDPInstall', + 'Invoke-D365SDPInstallUDE', 'Invoke-D365SCDPBundleInstall', 'Invoke-D365SeleniumDownload', 'Invoke-D365SysFlushAodCache', diff --git a/d365fo.tools/functions/get-d365sdpdetails.ps1 b/d365fo.tools/functions/get-d365sdpdetails.ps1 index 425c1a63..f325b1c4 100644 --- a/d365fo.tools/functions/get-d365sdpdetails.ps1 +++ b/d365fo.tools/functions/get-d365sdpdetails.ps1 @@ -91,7 +91,7 @@ function Get-D365SDPDetails { [System.IO.Compression.ZipFileExtensions]::ExtractToFile($zipEntry, $pathHotfix, $true) - foreach ($nuget in $($zipArch.Entries | Where-Object Fullname -like "AOSService\Packages\*.nupkg")) { + foreach ($nuget in $($zipArch.Entries | Where-Object Fullname -like "AOSService[\/]Packages[\/]*.nupkg")) { $pathNuget = "$pathWorkDirectory\$($nuget.name).zip" # The nuget file contains module name in correct casing @@ -144,16 +144,16 @@ function Get-D365SDPDetails { Version = $moduleSpec.package.metadata.version } ) - } - # Clear out any inner zip archive objects from memory - if ($zipNuget) { - $zipArch.Dispose() - } - - if ($fileNuget) { - $file.Close() - $file.Dispose() + # Clear out any inner zip archive objects from memory + if ($zipNuget) { + $zipNuget.Dispose() + } + + if ($fileNuget) { + $fileNuget.Close() + $fileNuget.Dispose() + } } [xml] $hotfix = Get-Content -Path "$pathWorkDirectory\HotfixInstallationInfo.xml" -Raw diff --git a/d365fo.tools/functions/invoke-d365sdpinstall.ps1 b/d365fo.tools/functions/invoke-d365sdpinstall.ps1 index 9b3f28d1..18afa5ea 100644 --- a/d365fo.tools/functions/invoke-d365sdpinstall.ps1 +++ b/d365fo.tools/functions/invoke-d365sdpinstall.ps1 @@ -1,11 +1,11 @@  <# .SYNOPSIS - Invoke the AxUpdateInstaller.exe file from Software Deployable Package (SDP) + Install a Software Deployable Package (SDP) .DESCRIPTION A cmdlet that wraps some of the cumbersome work into a streamlined process. - The process are detailed in the Microsoft documentation here: + The process for a legacy (i.e. non unified) environment are detailed in the Microsoft documentation here: https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/deployment/install-deployable-package .PARAMETER Path @@ -69,6 +69,9 @@ .PARAMETER UseExistingTopologyFile Use this switch to indicate that the topology file is already updated and should not be updated again. + .PARAMETER UnifiedDevelopmentEnvironment + Use this switch to install the package in a Unified Development Environment (UDE). + .EXAMPLE PS C:\> Invoke-D365SDPInstall -Path "c:\temp\package.zip" -QuickInstallAll @@ -114,12 +117,20 @@ Run all manual steps in one single operation using the MyTopology.xml file. The topology file is not updated. + .EXAMPLE + PS C:\> Invoke-D365SDPInstall -Path "c:\temp\" -MetaDataDir "c:\MyRepository\Metadata" -UnifiedDevelopmentEnvironment + + Install the modules contained in the c:\temp\ directory into the c:\MyRepository\Metadata directory. + .NOTES Author: Tommy Skaue (@skaue) Author: Mötz Jensen (@Splaxi) Inspired by blogpost http://dev.goshoom.net/en/2016/11/installing-deployable-packages-with-powershell/ + .LINK + Invoke-D365SDPInstallUDE + #> function Invoke-D365SDPInstall { [CmdletBinding(DefaultParameterSetName = 'QuickInstall')] @@ -157,8 +168,16 @@ function Invoke-D365SDPInstall { [string] $TopologyFile = "DefaultTopologyData.xml", - [switch] $UseExistingTopologyFile + [switch] $UseExistingTopologyFile, + + [Parameter(ParameterSetName = 'UDEInstall')] + [switch] $UnifiedDevelopmentEnvironment ) + + if ($UnifiedDevelopmentEnvironment) { + Invoke-D365SDPInstallUDE -Path $Path -MetaDataDir $MetaDataDir -LogPath $LogPath + return + } if ((Get-Process -Name "devenv" -ErrorAction SilentlyContinue).Count -gt 0) { Write-PSFMessage -Level Host -Message "It seems that you have a Visual Studio running. Please ensure exit Visual Studio and run the cmdlet again." diff --git a/d365fo.tools/functions/invoke-d365sdpinstallude.ps1 b/d365fo.tools/functions/invoke-d365sdpinstallude.ps1 new file mode 100644 index 00000000..8417052f --- /dev/null +++ b/d365fo.tools/functions/invoke-d365sdpinstallude.ps1 @@ -0,0 +1,117 @@ + +<# + .SYNOPSIS + Install a Software Deployable Package (SDP) in a unified development environment + + .DESCRIPTION + A cmdlet that wraps some of the cumbersome work into a streamlined process. + It first checks if the package is a zip file and extracts it if necessary. + Then it checks if the package contains the necessary files and modules. + Finally, it extracts the module zip files into the metadata directory. + + .PARAMETER Path + Path to the package that you want to install into the environment + + The cmdlet supports a path to a zip-file or directory with the unpacked contents. + + .PARAMETER MetaDataDir + The path to the meta data directory for the environment + + .PARAMETER LogPath + The path where the log file(s) will be saved + + .EXAMPLE + PS C:\> Invoke-D365SDPInstallUDE -Path "c:\temp\package.zip" -MetaDataDir "c:\MyRepository\Metadata" + + This will install the modules contained in the c:\temp\package.zip file into the c:\MyRepository\Metadata directory. + + .NOTES + Author: Florian Hopfner (@FH-Inway) + +#> +function Invoke-D365SDPInstallUDE { + param ( + [Parameter(Mandatory = $True, Position = 1 )] + [Alias('Hotfix')] + [Alias('File')] + [string] $Path, + + [Parameter(Mandatory = $true, Position = 2 )] + [string] $MetaDataDir, + + [Alias('LogDir')] + [string] $LogPath = $(Join-Path -Path $Script:DefaultTempPath -ChildPath "Logs\SdpInstall") + ) + + if ((Get-Process -Name "devenv" -ErrorAction SilentlyContinue).Count -gt 0) { + Write-PSFMessage -Level Host -Message "It seems that you have a Visual Studio running. Please ensure exit Visual Studio and run the cmdlet again." + Stop-PSFFunction -Message "Stopping because of running Visual Studio." + return + } + + Invoke-TimeSignal -Start + + + #Test if input is a zipFile that needs to be extracted first + if ($Path.EndsWith(".zip")) { + Unblock-File -Path $Path + + $extractedPath = $path.Remove($path.Length - 4) + if (!(Test-Path $extractedPath)) { + Expand-Archive -Path $Path -DestinationPath $extractedPath + + #lets work with the extracted directory from now on + $Path = $extractedPath + } + } + + # Input is a relative path which needs to be converted to an absolute path. + # see https://powershellmagazine.com/2013/01/16/pstip-check-if-the-path-is-relative-or-absolute/ + if (-not ([System.IO.Path]::IsPathRooted($Path) -or (Split-Path -Path $Path -IsAbsolute))) { + $currentPath = Get-Location + # https://stackoverflow.com/a/13847304/2720554 + $absolutePath = Join-Path -Path $currentPath -ChildPath $Path + $absolutePath = [System.IO.Path]::GetFullPath($absolutePath) + Write-PSFMessage -Level Verbose "Updating path to '$absolutePath' as relative paths are not supported" + $Path = $absolutePath + } + + Get-ChildItem -Path $Path -Recurse | Unblock-File + $packageDetails = Get-D365SDPDetails -Path $Path + + $packagesFolder = "$Path\AOSService\Packages" + $filesFolder = Get-ChildItem -Path $packagesFolder -Directory -Filter "files" + if ($filesFolder.Count -eq 0) { + Write-PSFMessage -Level Host -Message "No /AOSService/Packages/files folder found in the package. Please ensure that the package is extracted correctly." + Stop-PSFFunction -Message "Stopping because of missing files folder." + return + } + + $zipFiles = Get-ChildItem -Path $filesFolder.FullName -File -Filter "*.zip" + if ($zipFiles.Count -eq 0) { + Write-PSFMessage -Level Host -Message "No module zip files found in the package. Please ensure that the package is extracted correctly." + Stop-PSFFunction -Message "Stopping because of missing zip files." + return + } + + $numberOfInstalledModules = 0 + $packageDetails.Modules | ForEach-Object { + $moduleZip = $zipFiles | Where-Object Name -eq "dynamicsax-$($_.Name).$($_.Version).zip" + if (-not $moduleZip) { + Write-PSFMessage -Level Host -Message "No module zip file found for module $($_.Name). Please ensure that the package is extracted correctly." + Stop-PSFFunction -Message "Stopping because of missing module zip file." + return + } + + # Unzip to $MetaDataDir + $moduleZipPath = Join-Path -Path $MetaDataDir -ChildPath $($_.Name) + Expand-Archive -Path $moduleZip.FullName -DestinationPath $moduleZipPath + Write-PSFMessage -Level Verbose -Message "Unzipped module $($_.Name) to $moduleZipPath" + $numberOfInstalledModules++ + } + + Write-PSFMessage -Level Host -Message "Installed $numberOfInstalledModules module(s) into $MetaDataDir" + + Invoke-TimeSignal -End + +} \ No newline at end of file diff --git a/d365fo.tools/tests/functions/Invoke-D365SDPInstall.Tests.ps1 b/d365fo.tools/tests/functions/Invoke-D365SDPInstall.Tests.ps1 index d36341f9..5e0e1e3b 100644 --- a/d365fo.tools/tests/functions/Invoke-D365SDPInstall.Tests.ps1 +++ b/d365fo.tools/tests/functions/Invoke-D365SDPInstall.Tests.ps1 @@ -8,7 +8,7 @@ Describe "Ensuring unchanged command signature" { It "should have the expected parameter sets" { - (Get-Command Invoke-D365SDPInstall).ParameterSets.Name | Should -Be 'QuickInstall', 'DevInstall', 'Manual' + (Get-Command Invoke-D365SDPInstall).ParameterSets.Name | Should -Be 'QuickInstall', 'DevInstall', 'Manual', 'UDEInstall' } It 'Should have the expected parameter Path' { @@ -167,6 +167,19 @@ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False } + It 'Should have the expected parameter UnifiedDevelopmentEnvironment' { + $parameter = (Get-Command Invoke-D365SDPInstall).Parameters['UnifiedDevelopmentEnvironment'] + $parameter.Name | Should -Be 'UnifiedDevelopmentEnvironment' + $parameter.ParameterType.ToString() | Should -Be System.Management.Automation.SwitchParameter + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be 'UDEInstall' + $parameter.ParameterSets.Keys | Should -Contain 'UDEInstall' + $parameter.ParameterSets['UDEInstall'].IsMandatory | Should -Be $False + $parameter.ParameterSets['UDEInstall'].Position | Should -Be -2147483648 + $parameter.ParameterSets['UDEInstall'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['UDEInstall'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['UDEInstall'].ValueFromRemainingArguments | Should -Be $False + } } Describe "Testing parameterset QuickInstall" { @@ -187,5 +200,11 @@ Manual -Path -MetaDataDir -Command -Step -RunbookId -LogPath -ShowOriginalProgress -OutputCommandOnly -TopologyFile -UseExistingTopologyFile #> } + Describe "Testing parameterset UDEInstall" { + <# + UDEInstall -Path + UDEInstall -Path -MetaDataDir -Step -RunbookId -LogPath -ShowOriginalProgress -OutputCommandOnly -TopologyFile -UseExistingTopologyFile -UnifiedDevelopmentEnvironment + #> + } } \ No newline at end of file diff --git a/d365fo.tools/tests/functions/Invoke-D365SDPInstallUDE.Tests.ps1 b/d365fo.tools/tests/functions/Invoke-D365SDPInstallUDE.Tests.ps1 new file mode 100644 index 00000000..105d3d16 --- /dev/null +++ b/d365fo.tools/tests/functions/Invoke-D365SDPInstallUDE.Tests.ps1 @@ -0,0 +1,62 @@ +Describe "Invoke-D365SDPInstallUDE Unit Tests" -Tag "Unit" { + BeforeAll { + # Place here all things needed to prepare for the tests + } + AfterAll { + # Here is where all the cleanup tasks go + } + + Describe "Ensuring unchanged command signature" { + It "should have the expected parameter sets" { + (Get-Command Invoke-D365SDPInstallUDE).ParameterSets.Name | Should -Be '__AllParameterSets' + } + + It 'Should have the expected parameter Path' { + $parameter = (Get-Command Invoke-D365SDPInstallUDE).Parameters['Path'] + $parameter.Name | Should -Be 'Path' + $parameter.ParameterType.ToString() | Should -Be System.String + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' + $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' + $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $True + $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 1 + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False + } + It 'Should have the expected parameter MetaDataDir' { + $parameter = (Get-Command Invoke-D365SDPInstallUDE).Parameters['MetaDataDir'] + $parameter.Name | Should -Be 'MetaDataDir' + $parameter.ParameterType.ToString() | Should -Be System.String + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' + $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' + $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $True + $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 2 + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False + } + It 'Should have the expected parameter LogPath' { + $parameter = (Get-Command Invoke-D365SDPInstallUDE).Parameters['LogPath'] + $parameter.Name | Should -Be 'LogPath' + $parameter.ParameterType.ToString() | Should -Be System.String + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' + $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' + $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be -2147483648 + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False + } + } + + Describe "Testing parameterset __AllParameterSets" { + <# + __AllParameterSets -Path -MetaDataDir + __AllParameterSets -Path -MetaDataDir -LogPath + #> + } + +} \ No newline at end of file diff --git a/docs/Invoke-D365SDPInstall.md b/docs/Invoke-D365SDPInstall.md index d7f14ebc..ce3158f4 100644 --- a/docs/Invoke-D365SDPInstall.md +++ b/docs/Invoke-D365SDPInstall.md @@ -8,7 +8,7 @@ schema: 2.0.0 # Invoke-D365SDPInstall ## SYNOPSIS -Invoke the AxUpdateInstaller.exe file from Software Deployable Package (SDP) +Install a Software Deployable Package (SDP) ## SYNTAX @@ -33,9 +33,17 @@ Invoke-D365SDPInstall [-Path] [[-MetaDataDir] ] [-Command] ] [-UseExistingTopologyFile] [] ``` +### UDEInstall +``` +Invoke-D365SDPInstall [-Path] [[-MetaDataDir] ] [[-Step] ] [[-RunbookId] ] + [-LogPath ] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile ] + [-UseExistingTopologyFile] [-UnifiedDevelopmentEnvironment] [] +``` + ## DESCRIPTION A cmdlet that wraps some of the cumbersome work into a streamlined process. -The process are detailed in the Microsoft documentation here: +The process for a legacy (i.e. +non unified) environment are detailed in the Microsoft documentation here: https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/deployment/install-deployable-package ## EXAMPLES @@ -104,6 +112,13 @@ Invoke-D365SDPInstall -Path "c:\temp\" -Command RunAll -TopologyFile "c:\temp\My Run all manual steps in one single operation using the MyTopology.xml file. The topology file is not updated. +### EXAMPLE 9 +``` +Invoke-D365SDPInstall -Path "c:\temp\" -MetaDataDir "c:\MyRepository\Metadata" -UnifiedDevelopmentEnvironment +``` + +Install the modules contained in the c:\temp\ directory into the c:\MyRepository\Metadata directory. + ## PARAMETERS ### -Path @@ -313,6 +328,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -UnifiedDevelopmentEnvironment +Use this switch to install the package in a Unified Development Environment (UDE). + +```yaml +Type: SwitchParameter +Parameter Sets: UDEInstall +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). @@ -327,3 +357,6 @@ Author: Mötz Jensen (@Splaxi) Inspired by blogpost http://dev.goshoom.net/en/2016/11/installing-deployable-packages-with-powershell/ ## RELATED LINKS + +[Invoke-D365SDPInstallUDE]() + diff --git a/docs/Invoke-D365SDPInstallUDE.md b/docs/Invoke-D365SDPInstallUDE.md new file mode 100644 index 00000000..5be0796e --- /dev/null +++ b/docs/Invoke-D365SDPInstallUDE.md @@ -0,0 +1,93 @@ +--- +external help file: d365fo.tools-help.xml +Module Name: d365fo.tools +online version: +schema: 2.0.0 +--- + +# Invoke-D365SDPInstallUDE + +## SYNOPSIS +Install a Software Deployable Package (SDP) in a unified development environment + +## SYNTAX + +``` +Invoke-D365SDPInstallUDE [-Path] [-MetaDataDir] [-LogPath ] [] +``` + +## DESCRIPTION +A cmdlet that wraps some of the cumbersome work into a streamlined process. +It first checks if the package is a zip file and extracts it if necessary. +Then it checks if the package contains the necessary files and modules. +Finally, it extracts the module zip files into the metadata directory. + +## EXAMPLES + +### EXAMPLE 1 +``` +Invoke-D365SDPInstallUDE -Path "c:\temp\package.zip" -MetaDataDir "c:\MyRepository\Metadata" +``` + +This will install the modules contained in the c:\temp\package.zip file into the c:\MyRepository\Metadata directory. + +## PARAMETERS + +### -Path +Path to the package that you want to install into the environment + +The cmdlet supports a path to a zip-file or directory with the unpacked contents. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: File, Hotfix + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MetaDataDir +The path to the meta data directory for the environment + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -LogPath +The path where the log file(s) will be saved + +```yaml +Type: String +Parameter Sets: (All) +Aliases: LogDir + +Required: False +Position: Named +Default value: $(Join-Path -Path $Script:DefaultTempPath -ChildPath "Logs\SdpInstall") +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +Author: Florian Hopfner (@FH-Inway) + +## RELATED LINKS