├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ └── config.yml └── workflows │ ├── CI.yaml │ ├── Release.yaml │ └── RunTests.yaml ├── .gitignore ├── AL-Go ├── New-ALGoAppSourceContext.ps1 ├── New-ALGoAuthContext.ps1 ├── New-ALGoNugetContext.ps1 ├── New-ALGoRepo.ps1 ├── New-ALGoRepoWizard.ps1 └── New-ALGoStorageContext.ps1 ├── Api ├── Get-NavContainerApiCompanyId.ps1 └── Invoke-NavContainerApi.ps1 ├── AppHandling ├── Add-GitToAlProjectFolder.ps1 ├── BCPTLogEntryAPI │ ├── BCPTLogEntryAPI.Page.al │ └── app.json ├── Clean-BcContainerDatabase.ps1 ├── ClientContext.ps1 ├── Compile-AppInNavContainer.ps1 ├── Convert-ALCOutputToAzureDevOps.ps1 ├── Convert-BcAppsToRuntimePackages.ps1 ├── Copy-AlSourceFiles.ps1 ├── Copy-AppFilesToFolder.ps1 ├── Create-AlProjectFolderFromNavContainer.ps1 ├── Create-SymbolsFileFromAppFile.ps1 ├── Extract-AppFileToFolder.ps1 ├── Get-AppJsonFromAppFile.ps1 ├── Get-NavContainerApp.ps1 ├── Get-NavContainerAppInfo.ps1 ├── Get-NavContainerAppRuntimePackage.ps1 ├── Get-TestsFromNavContainer.ps1 ├── Install-NAVSipCryptoProviderFromNavContainer.ps1 ├── Install-NavContainerApp.ps1 ├── Microsoft_PSTestToolPage_15.0.0.0.app ├── PsTestFunctions.ps1 ├── Publish-NavContainerApp.ps1 ├── Publish-NewApplicationToNavContainer.ps1 ├── Repair-NavContainerApp.ps1 ├── Replace-DependenciesInAppFile.ps1 ├── Run-AlCops.ps1 ├── Run-AlPipeline.ps1 ├── Run-AlValidation.ps1 ├── Run-BCPTTestsInBcContainer.ps1 ├── Run-ConnectionTestToNavContainer.ps1 ├── Run-TestsInNavContainer.ps1 ├── Sign-NavContainerApp.ps1 ├── Sort-AppFilesByDependencies.ps1 ├── Sort-AppFoldersByDependencies.ps1 ├── Start-NavContainerAppDataUpgrade.ps1 ├── Sync-NavContainerApp.ps1 ├── UnInstall-NavContainerApp.ps1 ├── UnPublish-NavContainerApp.ps1 ├── appsource.default.ruleset.json ├── pstesttoolpage.fob ├── pstesttoolpage10.fob └── pstesttoolpage9.fob ├── AppSource ├── Cancel-AppSourceSubmission.ps1 ├── Get-AppSourceProduct.ps1 ├── Get-AppSourceSubmission.ps1 ├── Invoke-IngestionAPI.ps1 ├── New-AppSourceSubmission.ps1 └── Promote-AppSourceSubmission.ps1 ├── Artifacts ├── Download-Artifacts.ps1 ├── Get-BCArtifactUrl.ps1 └── Get-NavArtifactUrl.ps1 ├── Auth ├── New-BcAuthContext.ps1 └── Renew-BcAuthContext.ps1 ├── AzureAD ├── Create-AadAppsForNav.ps1 ├── Create-AadUsersInNavContainer.ps1 ├── New-AadAppsForBc.ps1 └── Remove-AadAppsForBc.ps1 ├── AzureVM ├── New-LetsEncryptCertificate.ps1 ├── Renew-LetsEncryptCertificate.ps1 └── Replace-NavServerContainer.ps1 ├── BC.ALGoHelper.module.json ├── BC.ALGoHelper.ps1 ├── BC.ALGoHelper.psd1 ├── BC.ALGoHelper.psm1 ├── BC.AppSourceHelper.module.json ├── BC.AppSourceHelper.ps1 ├── BC.AppSourceHelper.psd1 ├── BC.AppSourceHelper.psm1 ├── BC.ArtifactsHelper.module.json ├── BC.ArtifactsHelper.ps1 ├── BC.ArtifactsHelper.psd1 ├── BC.ArtifactsHelper.psm1 ├── BC.HelperFunctions.module.json ├── BC.HelperFunctions.ps1 ├── BC.HelperFunctions.psd1 ├── BC.HelperFunctions.psm1 ├── BC.NuGetHelper.module.json ├── BC.NuGetHelper.ps1 ├── BC.NuGetHelper.psd1 ├── BC.NuGetHelper.psm1 ├── BC.SaasHelper.module.json ├── BC.SaasHelper.ps1 ├── BC.SaasHelper.psd1 ├── BC.SaasHelper.psm1 ├── BC.module.json ├── BC.psd1 ├── BC.psm1 ├── Bacpac ├── Backup-NavContainerDatabases.ps1 ├── Export-NavContainerDatabasesAsBacpac.ps1 ├── Remove-BcDatabase.ps1 ├── Restore-BcDatabaseFromArtifacts.ps1 └── Restore-DatabasesInNavContainer.ps1 ├── BcContainerHelper.module.json ├── BcContainerHelper.ps1 ├── BcContainerHelper.psd1 ├── BcContainerHelper.psm1 ├── CI_CD_Workshop.md ├── CODEOWNERS ├── Check-BcContainerHelperPermissions.ps1 ├── Common ├── ConvertTo-HashTable.ps1 ├── ConvertTo-OrderedDictionary.ps1 ├── Download-File.ps1 ├── Get-PlainText.ps1 ├── Invoke-gh.ps1 ├── Invoke-git.ps1 ├── New-DesktopShortcut.ps1 └── Remove-DesktopShortcut.ps1 ├── CompanyHandling ├── Copy-CompanyInNavContainer.ps1 ├── Get-CompanyInNavContainer.ps1 ├── New-CompanyInNavContainer.ps1 └── Remove-CompanyInNavContainer.ps1 ├── CompilerFolderHandling ├── Compile-AppWithBcCompilerFolder.ps1 ├── Copy-AppFilesToCompilerFolder.ps1 ├── New-BcCompilerFolder.ps1 └── Remove-BcCompilerFolder.ps1 ├── ConfigPackageHandling ├── Get-PackageInfoFromRapidStartFile.ps1 ├── Import-ConfigPackageInNavContainer.ps1 ├── Remove-ConfigPackageInNavContainer.ps1 └── UploadImportAndApply-ConfigPackageInBcContainer.ps1 ├── ContainerHandling ├── Enter-NavContainer.ps1 ├── Extract-FilesFromNavContainerImage.ps1 ├── Extract-FilesFromStoppedNavContainer.ps1 ├── Flush-ContainerHelperCache.ps1 ├── Get-AlLanguageExtensionFromArtifacts.ps1 ├── Get-BestGenericImageName.ps1 ├── Get-BestNavContainerImageName.ps1 ├── Get-LatestAlLanguageExtensionUrl.ps1 ├── Get-NavContainerSession.ps1 ├── Import-NavContainerLicense.ps1 ├── Invoke-ScriptInNavContainer.ps1 ├── New-NavContainer.ps1 ├── New-NavContainerWizard.ps1 ├── New-NavImage.ps1 ├── Open-NavContainer.ps1 ├── Remove-NavContainer.ps1 ├── Remove-NavContainerSession.ps1 ├── Restart-BcContainerServiceTier.ps1 ├── Restart-NavContainer.ps1 ├── Set-BcContainerKeyVaultAadAppAndCertificate.ps1 ├── Set-BcContainerServerConfiguration.ps1 ├── Setup-TraefikContainerForNavContainers.ps1 ├── Start-NavContainer.ps1 ├── Stop-NavContainer.ps1 ├── Wait-NavContainerReady.ps1 ├── traefik │ ├── Add-DomainToTraefikConfig.ps1 │ ├── CheckHealth.ps1 │ ├── CheckHealth_https.ps1 │ ├── Create-CustomTraefikImage.ps1 │ ├── template_traefik.toml │ ├── template_traefik_https.toml │ ├── template_traefik_https_own.toml │ └── template_traefik_own.toml └── updatehosts.ps1 ├── ContainerInfo ├── Get-NavContainerArtifactUrl.ps1 ├── Get-NavContainerCountry.ps1 ├── Get-NavContainerDebugInfo.ps1 ├── Get-NavContainerEula.ps1 ├── Get-NavContainerEventLog.ps1 ├── Get-NavContainerGenericTag.ps1 ├── Get-NavContainerId.ps1 ├── Get-NavContainerImageLabels.ps1 ├── Get-NavContainerImageName.ps1 ├── Get-NavContainerImageTags.ps1 ├── Get-NavContainerIpAddress.ps1 ├── Get-NavContainerLegal.ps1 ├── Get-NavContainerLicenseInformation.ps1 ├── Get-NavContainerName.ps1 ├── Get-NavContainerNavVersion.ps1 ├── Get-NavContainerOsVersion.ps1 ├── Get-NavContainerPath.ps1 ├── Get-NavContainerPlatformVersion.ps1 ├── Get-NavContainerServerConfiguration.ps1 ├── Get-NavContainerSharedFolders.ps1 ├── Get-NavContainers.ps1 └── Test-NavContainer.ps1 ├── CreateALGoRepo.ps1 ├── CreateScript.ps1 ├── HelperFunctions.ps1 ├── Import-BC.ps1 ├── Import-BcContainerHelper.ps1 ├── InitializeModule.ps1 ├── LICENSE ├── LatestGenericTagVersion.txt ├── LinuxTests ├── Auth.Tests.ps1 ├── Saas.Tests.ps1 └── _TestHelperFunctions.ps1 ├── Microsoft.ApplicationInsights.dll ├── Misc ├── Add-FontsToNavContainer.ps1 ├── Copy-FileFromNavContainer.ps1 ├── Copy-FileToNavContainer.ps1 ├── Copy-ItemFromBcContainer.ps1 ├── Copy-ItemToBcContainer.ps1 ├── Get-LocaleFromCountry.ps1 ├── Get-NavVersionFromVersionInfo.ps1 ├── Import-CertificateToNavContainer.ps1 ├── Import-PfxCertificateToNavContainer.ps1 ├── Set-BcContainerFeatureKeys.ps1 └── Write-NavContainerHelperWelcomeText.ps1 ├── NavContainerHelper.md ├── NuGet ├── Download-BcNuGetPackageToFolder.ps1 ├── Find-BcNuGetPackage.ps1 ├── Get-BcNuGetPackage.ps1 ├── Get-BcNuGetPackageId.ps1 ├── New-BcNuGetPackage.ps1 ├── NuGetFeedClass.ps1 ├── Publish-BcNuGetPackageToContainer.ps1 └── Push-BcNuGetPackage.ps1 ├── ObjectHandling ├── Compile-ObjectsInNavContainer.ps1 ├── Convert-ModifiedObjectsToAl.ps1 ├── Convert-Txt2Al.ps1 ├── Create-MyDeltaFolder.ps1 ├── Create-MyOriginalFolder.ps1 ├── Export-ModifiedObjectsAsDeltas.ps1 ├── Export-NavContainerObjects.ps1 ├── Import-DeltasToNavContainer.ps1 ├── Import-ObjectsToNavContainer.ps1 ├── Import-TestToolkitToNavContainer.ps1 ├── Invoke-NavContainerCodeunit.ps1 └── coredotnetaddins.al ├── PackageHandling ├── Get-AzureFeedWildcardVersion.ps1 ├── Install-AzDevops.ps1 ├── Publish-BuildOutputToAzureFeed.ps1 ├── Publish-BuildOutputToStorage.ps1 └── Resolve-DependenciesFromAzureFeed.ps1 ├── README.md ├── ReleaseNotes.txt ├── SECURITY.md ├── SaaSHelperFunctions.ps1 ├── Saas ├── Copy-BcEnvironment.ps1 ├── Download-BcEnvironmentInstalledExtensionToFolder.ps1 ├── Get-BcEnvironmentAvailableRestorePeriods.ps1 ├── Get-BcEnvironmentDatabaseExportHistory.ps1 ├── Get-BcEnvironmentInstalledExtensions.ps1 ├── Get-BcEnvironmentOperations.ps1 ├── Get-BcEnvironmentPublishedApps.ps1 ├── Get-BcEnvironmentScheduledUpgrade.ps1 ├── Get-BcEnvironmentUpdateWindow.ps1 ├── Get-BcEnvironmentUsedStorage.ps1 ├── Get-BcEnvironments.ps1 ├── Get-BcNotificationRecipients.ps1 ├── Install-BcAppFromAppSource.ps1 ├── New-BcEnvironment.ps1 ├── New-BcEnvironmentDatabaseExport.ps1 ├── New-BcNotificationRecipient.ps1 ├── Publish-PerTenantExtensionApps.ps1 ├── Remove-BcEnvironment.ps1 ├── Rename-BcEnvironment.ps1 ├── Reschedule-BcEnvironmentUpgrade.ps1 ├── Restore-BcEnvironment.ps1 ├── Set-BcEnvironmentApplicationInsightsKey.ps1 ├── Set-BcEnvironmentUpdateWindow.ps1 └── Wait-BcEnvironmentReady.ps1 ├── SymbolHandling └── Generate-SymbolsInNavContainer.ps1 ├── TelemetryHelper.ps1 ├── TenantHandling ├── Get-NavContainerTenants.ps1 ├── New-NavContainerTenant.ps1 └── Remove-NavContainerTenant.ps1 ├── Tests ├── Api.Tests.ps1 ├── AppHandling (NAV).Tests.ps1 ├── AppHandling.Tests.ps1 ├── AzureAD.Tests.ps1 ├── AzureVM.Tests.ps1 ├── Bacpac (MT).Tests.ps1 ├── Bacpac (NAV).Tests.ps1 ├── Bacpac.Tests.ps1 ├── CompanyHandling.Tests.ps1 ├── ConfigPackageHandling.Tests.ps1 ├── ContainerHandling.Tests.ps1 ├── ContainerInfo.Tests.ps1 ├── GetAndRunTests (Windows Auth).Tests.ps1 ├── GetAndRunTests (latest).Tests.ps1 ├── GetAndRunTests (version 10).Tests.ps1 ├── GetAndRunTests (version 11).Tests.ps1 ├── GetAndRunTests (version 14).Tests.ps1 ├── GetAndRunTests (version 15).Tests.ps1 ├── GetAndRunTests (version 16).Tests.ps1 ├── GetAndRunTests (version 17).Tests.ps1 ├── GetAndRunTests (version 18).Tests.ps1 ├── GetAndRunTests (version 19).Tests.ps1 ├── GetAndRunTests (version 20).Tests.ps1 ├── GetAndRunTests (version 21).Tests.ps1 ├── GetAndRunTests (version 22).Tests.ps1 ├── GetAndRunTests (version 23).Tests.ps1 ├── GetAndRunTests (version 24).Tests.ps1 ├── GetAndRunTests (version 9).Tests.ps1 ├── Misc.Tests.ps1 ├── ObjectHandling (NAV).Tests.ps1 ├── ObjectHandling-Objects.txt ├── PackageHandling.Tests.ps1 ├── Run-AlPipeline (Windows Auth).Tests.ps1 ├── Run-AlPipeline.Tests.ps1 ├── SymbolHandling.Tests.ps1 ├── TenantHandling.Tests.ps1 ├── UserHandling.Tests.ps1 ├── _CreateBcContainer.ps1 ├── _CreateNavContainer.ps1 ├── _DoRunOne.ps1 ├── _RemoveBcContainer.ps1 ├── _RemoveNavContainer.ps1 ├── _TestHelperFunctions.ps1 ├── _TestRunOne.ps1 ├── _TestRunner.ps1 ├── bc-app │ ├── .vscode │ │ └── launch.json │ ├── CustomerCardExtension.al │ ├── GreetingsManagement.al │ ├── HelloWorld.al │ ├── Install.al │ ├── Tests.al │ └── app.json ├── bc2-app │ ├── .vscode │ │ └── launch.json │ ├── HelloWorld.al │ └── app.json ├── helloworld-previousapps.zip ├── helloworld │ ├── app │ │ ├── .vscode │ │ │ └── launch.json │ │ ├── HelloWorld.al │ │ └── app.json │ ├── base │ │ ├── .vscode │ │ │ └── launch.json │ │ ├── Codeunit 50130 - Hello Base.al │ │ └── app.json │ └── test │ │ ├── .vscode │ │ └── launch.json │ │ ├── Codeunit 50133 - HelloWorld Test.al │ │ ├── app.json │ │ └── disabledTests.json ├── inserttests.txt ├── inserttests │ ├── .vscode │ │ └── launch.json │ ├── Codeunit 50130 - Test Suite.al │ ├── Codeunit 50131 - Insert Testsl.al │ └── app.json └── nav-app │ ├── .vscode │ └── launch.json │ ├── CustomerCardExtension.al │ ├── GreetingsManagement.al │ ├── HelloWorld.al │ ├── Install.al │ ├── Tests.al │ └── app.json ├── UserHandling ├── Get-NavContainerNavUser.ps1 ├── New-NavContainerNavUser.ps1 ├── New-NavContainerWindowsUser.ps1 └── Setup-NavContainerTestUsers.ps1 ├── Version.txt └── addfonts.ps1 /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | settings.ps1 2 | 3 | -------------------------------------------------------------------------------- /AL-Go/New-ALGoAppSourceContext.ps1: -------------------------------------------------------------------------------- 1 | function New-ALGoAppSourceContext { 2 | Param( 3 | [Parameter(Mandatory=$true, ValueFromPipeline)] 4 | [HashTable] $authContext, 5 | [switch] $skipTest 6 | ) 7 | 8 | if ($authContext.scopes -ne "https://api.partner.microsoft.com/.default" -and $authContext.scopes -ne "https://api.partner.microsoft.com/" -and $authContext.scopes -ne "https://api.partner.microsoft.com/user_impersonation offline_access") { 9 | Write-Host -ForegroundColor Red "WARNING: AuthContext.Scopes is '$($authContext.Scopes)', should have been 'https://api.partner.microsoft.com/.default' or 'https://api.partner.microsoft.com/user_impersonation offline_access'" 10 | } 11 | 12 | if ($authContext.ClientSecret) { 13 | $appSourceContext = [ordered]@{ 14 | "clientID" = $authContext.clientID 15 | "clientSecret" = $authContext.ClientSecret | Get-PlainText 16 | "tenantID" = $authContext.tenantID 17 | "scopes" = $authContext.scopes 18 | } 19 | } 20 | else { 21 | $appSourceContext = [ordered]@{ 22 | "refreshToken" = $authContext.RefreshToken 23 | "tenantID" = $authContext.tenantID 24 | "scopes" = $authContext.scopes 25 | } 26 | } 27 | 28 | if (!$skipTest) { 29 | Write-Host "Testing AppSourceContext" 30 | try { 31 | $newAuthContext = New-BcAuthContext @appSourceContext 32 | } 33 | catch { 34 | Write-Host -ForegroundColor Red "Unable to use specified authContext" 35 | throw 36 | } 37 | try { 38 | $products = Get-AppSourceProduct -authContext $newAuthContext -silent 39 | } 40 | catch { 41 | Write-Host -ForegroundColor Red "Unable to get AppSource Products from ingestion API using the specified authContext" 42 | throw 43 | } 44 | Write-Host -ForegroundColor Green "AppSourceContext successfully validated" 45 | } 46 | $appSourceContext | ConvertTo-Json -Depth 99 -Compress 47 | } 48 | Export-ModuleMember -Function New-ALGoAppSourceContext 49 | -------------------------------------------------------------------------------- /AL-Go/New-ALGoNugetContext.ps1: -------------------------------------------------------------------------------- 1 | function New-ALGoNugetContext { 2 | Param( 3 | [Parameter(Mandatory=$true)] 4 | [string] $serverUrl, 5 | [Parameter(Mandatory=$true)] 6 | [string] $token, 7 | [switch] $skipTest 8 | ) 9 | 10 | $nuGetContext = @{ 11 | "serverUrl" = $serverUrl 12 | "token" = $token 13 | } 14 | 15 | if (!$skipTest) { 16 | Write-Host "Testing NuGetContext" 17 | 18 | try { 19 | $headers = @{ 20 | "Content-Type" = "application/json; charset=utf-8" 21 | "Authorization" = "Basic $([Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("user:$token")))" 22 | } 23 | 24 | $capabilities = Invoke-RestMethod -UseBasicParsing -Method GET -Headers $headers -Uri $serverUrl 25 | $searchResource = $capabilities.resources | Where-Object { $_.'@type' -eq 'SearchQueryService' -or $_.'@type' -eq 'SearchQueryService/3.0.0-beta' } 26 | $publishResource = $capabilities.resources | Where-Object { $_."@type" -eq 'PackagePublish/2.0.0' } 27 | } 28 | catch { 29 | throw "Error trying to download NuGet Server capabilities. Error was: $($_.Message)" 30 | } 31 | 32 | if (-not $searchResource) { 33 | throw "NuGet Server does not support SearchQueryService API (or SearchQueryService/3.0.0-beta), which is needed for BcContainerHelper NuGet functions to work" 34 | } 35 | 36 | if (-not $publishResource) { 37 | throw "NuGet Server does not support PackagePublish/2.0.0 API, which is needed for BcContainerHelper NuGet functions to work" 38 | } 39 | 40 | Write-Host -ForegroundColor Green "NuGetContext successfully validated" 41 | } 42 | 43 | $nuGetContext | ConvertTo-Json -Depth 99 -Compress 44 | } 45 | Export-ModuleMember -Function New-ALGoNuGetContext 46 | -------------------------------------------------------------------------------- /AL-Go/New-ALGoRepoWizard.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Runs a poor mans wizard to generate an AL-Go for GitHub repo 4 | .Description 5 | Ask a number of questions to determine the parameters for a new AL-Go for GitHub repo 6 | #> 7 | function New-ALGoRepoWizard { 8 | 9 | $pslink = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\Windows PowerShell\Windows PowerShell.lnk" 10 | if (!(Test-Path $pslink)) { 11 | $pslink = "powershell.exe" 12 | } 13 | 14 | $script = (Get-Item -Path (Join-Path $PSScriptRoot "..\CreateALGoRepo.ps1")).FullName 15 | 16 | $module = Get-InstalledModule -Name "BcContainerHelper" -ErrorAction SilentlyContinue 17 | 18 | Write-Host "Launching $script" 19 | 20 | if ($module) { 21 | Start-Process $pslink @("-File ""$script""", "") 22 | } 23 | else { 24 | . $script 25 | } 26 | 27 | 28 | } 29 | Export-ModuleMember -Function New-ALGoRepoWizard 30 | -------------------------------------------------------------------------------- /AppHandling/Add-GitToAlProjectFolder.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Adds GIT to an Al Project Folder 4 | .Description 5 | This function will create a .gitignore file, initialize a git repo, add and commit all files in the folder 6 | The GIT repo will NOT have any remote defined 7 | .Parameter alProjectFolder 8 | Path of the folder in which to add a GIT repo 9 | .Parameter commitMessage 10 | Message of initial commit to the repo 11 | .Example 12 | Add-GitToAlProjectFolder 13 | #> 14 | function Add-GitToAlProjectFolder { 15 | Param ( 16 | [Parameter(Mandatory=$true)] 17 | [string] $alProjectFolder, 18 | [Parameter(Mandatory=$true)] 19 | [string] $commitMessage 20 | ) 21 | 22 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 23 | try { 24 | 25 | Write-Host "Initializing Git repository" 26 | 27 | $gitIgnoreFile = Join-Path $AlProjectFolder ".gitignore" 28 | Set-Content -Path $gitIgnoreFile -Value ".vscode`r`n*.app" 29 | 30 | $oldLocation = Get-Location 31 | Set-Location $AlProjectFolder 32 | & git init 33 | Write-Host "Adding files" 34 | & git add . 35 | & git gc --quiet 36 | Write-Host "Committing files" 37 | & git commit -m $commitMessage --quiet 38 | Set-Location $oldLocation 39 | 40 | } 41 | catch { 42 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 43 | throw 44 | } 45 | finally { 46 | TrackTrace -telemetryScope $telemetryScope 47 | } 48 | } 49 | Export-ModuleMember -Function Add-GitToAlProjectFolder 50 | -------------------------------------------------------------------------------- /AppHandling/BCPTLogEntryAPI/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "7948b639-3865-4e08-b04c-3a9db52e9ac2", 3 | "name": "BCPTLogEntryAPI", 4 | "publisher": "BcContainerHelper", 5 | "brief": "", 6 | "description": "", 7 | "version": "1.0.0.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "dependencies": [ 13 | { 14 | "id": "75f1590f-55c5-4501-ae63-bada5534e852", 15 | "name": "Performance Toolkit", 16 | "publisher": "Microsoft", 17 | "version": "18.0.0.0" 18 | } 19 | ], 20 | "screenshots": [], 21 | "platform": "18.0.0.0", 22 | "application": "18.0.0.0", 23 | "idRanges": [ 24 | { 25 | "from": 88123, 26 | "to": 88123 27 | } 28 | ], 29 | "target": "Cloud", 30 | "supportedLocales": [ 31 | "en-US" 32 | ], 33 | "runtime": "7.0" 34 | } -------------------------------------------------------------------------------- /AppHandling/Copy-AppFilesToFolder.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Copy App Files to Folder (supporting urls, .zip files and .app files) 4 | .Description 5 | .Parameter appFiles 6 | Can be an array of appfiles, urls or zip files 7 | .Parameter folder 8 | Folder to copy the app files to 9 | .Example 10 | Copy-AppFilesToFolder -appFiles @("c:\temp\apps.zip", "c:\temp\app2.app", "https://github.com/org/repo/releases/download/2.0.200/project-branch-Apps-1.0.0.0.zip") -folder "c:\temp\appfiles" 11 | #> 12 | function Copy-AppFilesToFolder { 13 | Param( 14 | [Parameter(Mandatory=$true)] 15 | $appFiles, 16 | [Parameter(Mandatory=$true)] 17 | [string] $folder 18 | ) 19 | CopyAppFilesToFolder -appFiles $appFiles -folder $folder 20 | } 21 | Export-ModuleMember -Function Copy-AppFilesToFolder 22 | -------------------------------------------------------------------------------- /AppHandling/Create-SymbolsFileFromAppFile.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Create a Symbols only .app file from an .app file 4 | .Description 5 | .Parameter AppFile 6 | Path of the application file which should be converted to symbols 7 | .Parameter symbolsFile 8 | Path of the symbols file which should be created 9 | .Example 10 | Create-SymbolsFileFromAppFile -appFile c:\temp\baseapp.app -symbolsFile c:\temp\baseapp.symbols.app 11 | #> 12 | function Create-SymbolsFileFromAppFile { 13 | Param( 14 | [Parameter(Mandatory=$true)] 15 | [string] $appFile, 16 | [Parameter(Mandatory=$true)] 17 | [string] $symbolsFile 18 | ) 19 | RunAlTool -arguments @('CreateSymbolPackage', """$appFile""", """$symbolsFile""") 20 | } 21 | Export-ModuleMember -Function Create-SymbolsFileFromAppFile 22 | -------------------------------------------------------------------------------- /AppHandling/Get-AppJsonFromAppFile.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Extract the app.json file from an app (also from runtime packages) 4 | .Description 5 | .Parameter AppFile 6 | Path of the application file from which to extract the app.json 7 | .Example 8 | Get-AppJsonFromAppFile -appFile c:\temp\baseapp.app 9 | #> 10 | function Get-AppJsonFromAppFile { 11 | Param( 12 | [Parameter(Mandatory=$true)] 13 | [string] $appFile 14 | ) 15 | $appJson = RunAlTool -arguments @('GetPackageManifest', """$appFile""") | ConvertFrom-Json 16 | if (!($appJson.PSObject.Properties.Name -eq "description")) { Add-Member -InputObject $appJson -MemberType NoteProperty -Name "description" -Value "" } 17 | if (!($appJson.PSObject.Properties.Name -eq "dependencies")) { Add-Member -InputObject $appJson -MemberType NoteProperty -Name "dependencies" -Value @() } 18 | return $appJson 19 | } 20 | Export-ModuleMember -Function Get-AppJsonFromAppFile 21 | -------------------------------------------------------------------------------- /AppHandling/Microsoft_PSTestToolPage_15.0.0.0.app: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/AppHandling/Microsoft_PSTestToolPage_15.0.0.0.app -------------------------------------------------------------------------------- /AppHandling/Repair-NavContainerApp.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Repairs App in a NAV/BC Container 4 | .Description 5 | Repairs a Business Central App by recompiling it against the current base application. Use this cmdlet if the base application has changed since publishing the Business Central App. 6 | It is recommended that the Business Central Server instance is restarted after running the repair. 7 | .Parameter containerName 8 | Name of the container in which you want to repair an app 9 | .Parameter appName 10 | Name of app you want to repair in the container 11 | .Parameter appVersion 12 | Version of app you want to repair in the container 13 | .Example 14 | Repair-BcContainerApp -containerName test2 -appName myapp 15 | #> 16 | function Repair-BcContainerApp { 17 | Param ( 18 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 19 | [Parameter(Mandatory=$true)] 20 | [string] $appName, 21 | [Parameter()] 22 | [string] $appVersion 23 | ) 24 | 25 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 26 | try { 27 | 28 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($appName, $appVersion) 29 | Write-Host "Repairing $appName" 30 | $parameters = @{ 31 | "ServerInstance" = $ServerInstance; 32 | "Name" = $appName 33 | } 34 | if ($appVersion) 35 | { 36 | $parameters += @{ "Version" = $appVersion } 37 | } 38 | Repair-NavApp @parameters 39 | } -ArgumentList $appName, $appVersion 40 | } 41 | catch { 42 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 43 | throw 44 | } 45 | finally { 46 | TrackTrace -telemetryScope $telemetryScope 47 | } 48 | } 49 | Set-Alias -Name Repair-NavContainerApp -Value Repair-BcContainerApp 50 | Export-ModuleMember -Function Repair-BcContainerApp -Alias Repair-NavContainerApp 51 | -------------------------------------------------------------------------------- /AppHandling/appsource.default.ruleset.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Default AppSource ruleset.", 3 | "name": "AppSource rules", 4 | "rules": [ 5 | { 6 | "id": "AS0075", 7 | "action": "Hidden", 8 | "justification": "Specifying the Obsolete Reason is a good practice, but the usage of obsolete tags isn't enforced in AppSource submissions." 9 | }, 10 | { 11 | "id": "AS0089", 12 | "action": "Warning", 13 | "justification": "[Evergreen] Removing a page customization, an entitlement, or a control add-in is allowed because AL currently does not support obsoleting them." 14 | }, 15 | { 16 | "id": "AS0099", 17 | "action": "Hidden", 18 | "justification": "This is an Info diagnostic about IDs being out of range, mainly for enum extension values (which is often due to constraints from dataverse integration)." 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /AppHandling/pstesttoolpage.fob: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/AppHandling/pstesttoolpage.fob -------------------------------------------------------------------------------- /AppHandling/pstesttoolpage10.fob: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/AppHandling/pstesttoolpage10.fob -------------------------------------------------------------------------------- /AppHandling/pstesttoolpage9.fob: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/AppHandling/pstesttoolpage9.fob -------------------------------------------------------------------------------- /AppSource/Promote-AppSourceSubmission.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Promote AppSource Submission from Preview to Production (aka. press the Go Live button) 4 | The Submission must be ReadyToPublish in order for this function to work 5 | You cannot cancel the promote - once promoted - you cannot re-submit or cancel until submission is live 6 | .Description 7 | Returns a PSCustomObject with submission details 8 | .Parameter authContext 9 | Authentication Context from New-BcAuthContext 10 | .Parameter productId 11 | Id of the product for which you want to promote a submission 12 | .Parameter submissionId 13 | Id of the submission you want to promote or leave empty for latest submission 14 | .Parameter silent 15 | Include this switch if you do not want the method to display URLs etc. 16 | .Example 17 | $submission = Promote-AppSourceSubmission -authContext $authcontext -productId $productId -silent 18 | #> 19 | function Promote-AppSourceSubmission { 20 | Param( 21 | [Parameter(Mandatory=$true)] 22 | [HashTable] $authContext, 23 | [Parameter(Mandatory=$true)] 24 | [string] $productId, 25 | [Parameter(Mandatory=$false)] 26 | [string] $submissionId = '', 27 | [switch] $silent 28 | ) 29 | 30 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 31 | try { 32 | $authContext = Renew-BcAuthContext -bcAuthContext $authContext 33 | $submission = Get-AppSourceSubmission -authContext $authContext -productId $productId -submissionId $submissionId -silent:($silent.IsPresent) 34 | if ($submission.state -eq "Published" -and $submission.substate -eq "ReadyToPublish") { 35 | Invoke-IngestionApiPost -authContext $authContext -path "/products/$productId/submissions/$($submission.id)/promote" -silent:($silent.IsPresent) 36 | } 37 | else { 38 | throw "Submission $($submission.id) is not ready to publish" 39 | } 40 | } 41 | catch { 42 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 43 | throw 44 | } 45 | finally { 46 | TrackTrace -telemetryScope $telemetryScope 47 | } 48 | } 49 | Export-ModuleMember -Function Promote-AppSourceSubmission -------------------------------------------------------------------------------- /Artifacts/Get-NavArtifactUrl.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get a list of available artifact URLs 4 | .Description 5 | Get a list of available artifact URLs. It can be used to create a new instance of a Container. 6 | .Parameter nav 7 | The requested version of NAV (2016,2017,2018) 8 | .Parameter cu 9 | The requested Cumulative update 10 | .Parameter country 11 | the requested localization of Business Central 12 | .Parameter select 13 | All or only the latest (Default Latest): 14 | - All: will return all possible urls in the selection 15 | - Latest: will sort on version, and return latest version 16 | .Example 17 | Get NAV 2017 CU30 URL for Belgium: 18 | Get-NavArtifactUrl -Nav 2017 -cu cu30 -Select Latest -language be 19 | 20 | Get all available Artifact URLs for NAV 2018: 21 | Get-NAVArtifactUrl -Select All 22 | #> 23 | function Get-NavArtifactUrl { 24 | [CmdletBinding()] 25 | param ( 26 | [ValidateSet('2016','2017','2018')] 27 | [String] $nav = '2018', 28 | [String] $cu, 29 | [String] $country, 30 | [ValidateSet('All', 'Latest')] 31 | [String] $select = 'Latest' 32 | ) 33 | 34 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @("nav","cu","country","select") 35 | try { 36 | 37 | $version = (@{ "2016" = "9.0"; "2017" = "10.0"; "2018" = "11.0" })[$nav] 38 | 39 | if ($cu) { 40 | $w1artifactUrls = Get-BCArtifactUrl -type OnPrem -country w1 -version $version -select All 41 | if ($cu -eq "rtm") { 42 | $idx = 0 43 | } 44 | else { 45 | $idx = [int]::Parse($cu.TrimStart('cu')) 46 | } 47 | $version = $w1artifactUrls[$idx].Substring($w1artifactUrls[$idx].IndexOf('/onprem/')).Split('/')[2] 48 | Get-BCArtifactUrl -type OnPrem -country $country -version $version -select $select 49 | } 50 | else { 51 | Get-BCArtifactUrl -type OnPrem -country $country -version $version -select $select 52 | } 53 | } 54 | catch { 55 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 56 | throw 57 | } 58 | finally { 59 | TrackTrace -telemetryScope $telemetryScope 60 | } 61 | } 62 | Export-ModuleMember -Function Get-NAVArtifactUrl 63 | -------------------------------------------------------------------------------- /BC.ALGoHelper.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "fa5f4d08-53be-4ca0-bf16-26da89afa20f", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "PowerShell module with AL-Go helper functions for Business Central Development", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "RequiredModules": [ 12 | "BC.HelperFunctions" 13 | ], 14 | "files": [ 15 | "InitializeModule.ps1", 16 | "HelperFunctions.ps1", 17 | "BC.ALGoHelper.ps1", 18 | "AL-Go\\*" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /BC.ALGoHelper.ps1: -------------------------------------------------------------------------------- 1 | # AL-Go for GitHub functions 2 | . (Join-Path $PSScriptRoot "AL-Go\New-ALGoAuthContext.ps1") 3 | . (Join-Path $PSScriptRoot "AL-Go\New-ALGoAppSourceContext.ps1") 4 | . (Join-Path $PSScriptRoot "AL-Go\New-ALGoStorageContext.ps1") 5 | . (Join-Path $PSScriptRoot "AL-Go\New-ALGoNugetContext.ps1") 6 | . (Join-Path $PSScriptRoot "AL-Go\New-ALGoRepo.ps1") 7 | #. (Join-Path $PSScriptRoot "AL-Go\New-ALGoRepoWizard.ps1") 8 | -------------------------------------------------------------------------------- /BC.ALGoHelper.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/BC.ALGoHelper.psd1 -------------------------------------------------------------------------------- /BC.ALGoHelper.psm1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [string[]] $bcContainerHelperConfigFile = @() 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot "InitializeModule.ps1") ` 7 | -Silent:$Silent ` 8 | -bcContainerHelperConfigFile $bcContainerHelperConfigFile ` 9 | -moduleName $MyInvocation.MyCommand.Name ` 10 | -moduleDependencies @( 'BC.HelperFunctions' ) 11 | 12 | . (Join-Path $PSScriptRoot "HelperFunctions.ps1") 13 | . (Join-Path $PSScriptRoot "BC.ALGoHelper.ps1") 14 | 15 | -------------------------------------------------------------------------------- /BC.AppSourceHelper.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "325e1f63-e3d3-43d5-954d-2ac74f59bc7d", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "PowerShell module with AppSource helper functions for Business Central Development", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "RequiredModules": [ 12 | "BC.HelperFunctions" 13 | ], 14 | "files": [ 15 | "InitializeModule.ps1", 16 | "HelperFunctions.ps1", 17 | "BC.AppSourceHelper.ps1", 18 | "AppSource\\*" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /BC.AppSourceHelper.ps1: -------------------------------------------------------------------------------- 1 | # AppSource specific functions 2 | . (Join-Path $PSScriptRoot "AppSource\Invoke-IngestionAPI.ps1") 3 | . (Join-Path $PSScriptRoot "AppSource\Get-AppSourceProduct.ps1") 4 | . (Join-Path $PSScriptRoot "AppSource\Get-AppSourceSubmission.ps1") 5 | . (Join-Path $PSScriptRoot "AppSource\New-AppSourceSubmission.ps1") 6 | . (Join-Path $PSScriptRoot "AppSource\Promote-AppSourceSubmission.ps1") 7 | . (Join-Path $PSScriptRoot "AppSource\Cancel-AppSourceSubmission.ps1") 8 | -------------------------------------------------------------------------------- /BC.AppSourceHelper.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/BC.AppSourceHelper.psd1 -------------------------------------------------------------------------------- /BC.AppSourceHelper.psm1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [string[]] $bcContainerHelperConfigFile = @() 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot "InitializeModule.ps1") ` 7 | -Silent:$Silent ` 8 | -bcContainerHelperConfigFile $bcContainerHelperConfigFile ` 9 | -moduleName $MyInvocation.MyCommand.Name ` 10 | -moduleDependencies @( 'BC.HelperFunctions' ) 11 | 12 | . (Join-Path $PSScriptRoot "HelperFunctions.ps1") 13 | . (Join-Path $PSScriptRoot "BC.AppSourceHelper.ps1") 14 | -------------------------------------------------------------------------------- /BC.ArtifactsHelper.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "2262fadf-b661-4818-aec8-4502802bbf42", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "PowerShell module with Business Central artifacts helper functions for Business Central Development", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "RequiredModules": [ 12 | "BC.HelperFunctions" 13 | ], 14 | "files": [ 15 | "InitializeModule.ps1", 16 | "HelperFunctions.ps1", 17 | "BC.ArtifactsHelper.ps1", 18 | "Artifacts\\*" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /BC.ArtifactsHelper.ps1: -------------------------------------------------------------------------------- 1 | # Artifacts functions 2 | . (Join-Path $PSScriptRoot "Artifacts\Download-Artifacts.ps1") 3 | . (Join-Path $PSScriptRoot "Artifacts\Get-BCArtifactUrl.ps1") 4 | . (Join-Path $PSScriptRoot "Artifacts\Get-NavArtifactUrl.ps1") 5 | -------------------------------------------------------------------------------- /BC.ArtifactsHelper.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/BC.ArtifactsHelper.psd1 -------------------------------------------------------------------------------- /BC.ArtifactsHelper.psm1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [string[]] $bcContainerHelperConfigFile = @() 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot "InitializeModule.ps1") ` 7 | -Silent:$Silent ` 8 | -bcContainerHelperConfigFile $bcContainerHelperConfigFile ` 9 | -moduleName $MyInvocation.MyCommand.Name ` 10 | -moduleDependencies @( 'BC.HelperFunctions' ) 11 | 12 | . (Join-Path $PSScriptRoot "HelperFunctions.ps1") 13 | . (Join-Path $PSScriptRoot "BC.ArtifactsHelper.ps1") 14 | -------------------------------------------------------------------------------- /BC.HelperFunctions.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "25a65b43-3a76-4782-8515-06de2d4bae21", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "Base PowerShell module for BC.* modules", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "files": [ 12 | "InitializeModule.ps1", 13 | "HelperFunctions.ps1", 14 | "BC.HelperFunctions.ps1", 15 | "TelemetryHelper.ps1", 16 | "Microsoft.ApplicationInsights.dll", 17 | "Common\\*", 18 | "Auth\\*" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /BC.HelperFunctions.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/BC.HelperFunctions.psd1 -------------------------------------------------------------------------------- /BC.HelperFunctions.psm1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [string[]] $bcContainerHelperConfigFile = @() 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot "InitializeModule.ps1") ` 7 | -Silent:$Silent ` 8 | -bcContainerHelperConfigFile $bcContainerHelperConfigFile ` 9 | -moduleName $MyInvocation.MyCommand.Name 10 | 11 | . (Join-Path $PSScriptRoot "HelperFunctions.ps1") 12 | . (Join-Path $PSScriptRoot "BC.HelperFunctions.ps1") 13 | -------------------------------------------------------------------------------- /BC.NuGetHelper.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "5ef27830-ae76-422f-8439-db8db89e9ece", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "PowerShell module with NuGet helper functions for Business Central Development", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "RequiredModules": [ 12 | "BC.HelperFunctions" 13 | ], 14 | "files": [ 15 | "InitializeModule.ps1", 16 | "HelperFunctions.ps1", 17 | "BC.NuGetHelper.ps1", 18 | "NuGet\\*" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /BC.NuGetHelper.ps1: -------------------------------------------------------------------------------- 1 | # NuGet specific functions 2 | if (-not (([System.Management.Automation.PSTypeName]"NuGetFeed").Type)) { 3 | . (Join-Path $PSScriptRoot "NuGet\NuGetFeedClass.ps1") 4 | } 5 | . (Join-Path $PSScriptRoot "NuGet\New-BcNuGetPackage.ps1") 6 | . (Join-Path $PSScriptRoot "NuGet\Find-BcNuGetPackage.ps1") 7 | . (Join-Path $PSScriptRoot "NuGet\Get-BcNuGetPackage.ps1") 8 | . (Join-Path $PSScriptRoot "NuGet\Get-BcNuGetPackageId.ps1") 9 | . (Join-Path $PSScriptRoot "NuGet\Push-BcNuGetPackage.ps1") 10 | . (Join-Path $PSScriptRoot "NuGet\Publish-BcNuGetPackageToContainer.ps1") 11 | . (Join-Path $PSScriptRoot "NuGet\Download-BcNuGetPackageToFolder.ps1") 12 | -------------------------------------------------------------------------------- /BC.NuGetHelper.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/BC.NuGetHelper.psd1 -------------------------------------------------------------------------------- /BC.NuGetHelper.psm1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [string[]] $bcContainerHelperConfigFile = @() 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot "InitializeModule.ps1") ` 7 | -Silent:$Silent ` 8 | -bcContainerHelperConfigFile $bcContainerHelperConfigFile ` 9 | -moduleName $MyInvocation.MyCommand.Name ` 10 | -moduleDependencies @( 'BC.HelperFunctions' ) 11 | 12 | . (Join-Path $PSScriptRoot "HelperFunctions.ps1") 13 | . (Join-Path $PSScriptRoot "SaaSHelperFunctions.ps1") 14 | . (Join-Path $PSScriptRoot "BC.NuGetHelper.ps1") 15 | -------------------------------------------------------------------------------- /BC.SaasHelper.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "e7f1ba7d-b7f1-4c7d-ad19-d24491fbbd19", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "PowerShell module with Business Central online helper functions for Business Central Development", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "RequiredModules": [ 12 | "BC.HelperFunctions" 13 | ], 14 | "files": [ 15 | "InitializeModule.ps1", 16 | "HelperFunctions.ps1", 17 | "SaaSHelperFunctions.ps1", 18 | "BC.SaasHelper.ps1", 19 | "Saas\\*" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /BC.SaasHelper.ps1: -------------------------------------------------------------------------------- 1 | # SaaS specific functions 2 | . (Join-Path $PSScriptRoot "Saas\Copy-BcEnvironment.ps1") 3 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentDatabaseExportHistory.ps1") 4 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironments.ps1") 5 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentAvailableRestorePeriods.ps1") 6 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentOperations.ps1") 7 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentUsedStorage.ps1") 8 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentUpdateWindow") 9 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentInstalledExtensions.ps1") 10 | . (Join-Path $PSScriptRoot "Saas\Get-BcNotificationRecipients.ps1") 11 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentPublishedApps.ps1") 12 | . (Join-Path $PSScriptRoot "Saas\Get-BcEnvironmentScheduledUpgrade.ps1") 13 | . (Join-Path $PSScriptRoot "Saas\Install-BcAppFromAppSource.ps1") 14 | . (Join-Path $PSScriptRoot "Saas\New-BcEnvironmentDatabaseExport.ps1") 15 | . (Join-Path $PSScriptRoot "Saas\New-BcEnvironment.ps1") 16 | . (Join-Path $PSScriptRoot "Saas\New-BcNotificationRecipient.ps1") 17 | . (Join-Path $PSScriptRoot "Saas\Publish-PerTenantExtensionApps.ps1") 18 | . (Join-Path $PSScriptRoot "Saas\Remove-BcEnvironment.ps1") 19 | . (Join-Path $PSScriptRoot "Saas\Rename-BcEnvironment.ps1") 20 | . (Join-Path $PSScriptRoot "Saas\Reschedule-BcEnvironmentUpgrade.ps1") 21 | . (Join-Path $PSScriptRoot "Saas\Restore-BcEnvironment.ps1") 22 | . (Join-Path $PSScriptRoot "Saas\Set-BcEnvironmentApplicationInsightsKey.ps1") 23 | . (Join-Path $PSScriptRoot "Saas\Set-BcEnvironmentUpdateWindow.ps1") 24 | . (Join-Path $PSScriptRoot "Saas\Wait-BcEnvironmentReady.ps1") 25 | . (Join-Path $PSScriptRoot "Saas\Download-BcEnvironmentInstalledExtensionToFolder.ps1") -------------------------------------------------------------------------------- /BC.SaasHelper.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/BC.SaasHelper.psd1 -------------------------------------------------------------------------------- /BC.SaasHelper.psm1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [string[]] $bcContainerHelperConfigFile = @() 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot "InitializeModule.ps1") ` 7 | -Silent:$Silent ` 8 | -bcContainerHelperConfigFile $bcContainerHelperConfigFile ` 9 | -moduleName $MyInvocation.MyCommand.Name ` 10 | -moduleDependencies @( 'BC.HelperFunctions' ) 11 | 12 | . (Join-Path $PSScriptRoot "HelperFunctions.ps1") 13 | . (Join-Path $PSScriptRoot "SaaSHelperFunctions.ps1") 14 | . (Join-Path $PSScriptRoot "BC.SaasHelper.ps1") 15 | -------------------------------------------------------------------------------- /BC.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "e7f1ba7d-b7f1-4c7d-ad19-d24491fbbd19", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "PowerShell module with Business Central online helper functions for Business Central Development", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "RequiredModules": [ 12 | "BC.HelperFunctions", 13 | "BC.ArtifactsHelper", 14 | "BC.AppSourceHelper", 15 | "BC.ALGoHelper", 16 | "BC.SaasHelper", 17 | "BC.NuGetHelper" 18 | ], 19 | "files": [ 20 | "InitializeModule.ps1" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /BC.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/BC.psd1 -------------------------------------------------------------------------------- /BC.psm1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [string[]] $bcContainerHelperConfigFile = @() 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot "InitializeModule.ps1") ` 7 | -Silent:$Silent ` 8 | -bcContainerHelperConfigFile $bcContainerHelperConfigFile ` 9 | -moduleName $MyInvocation.MyCommand.Name ` 10 | -moduleDependencies @( 11 | "BC.HelperFunctions", 12 | "BC.ArtifactsHelper", 13 | "BC.AppSourceHelper", 14 | "BC.ALGoHelper", 15 | "BC.SaasHelper", 16 | "BC.NuGetHelper" 17 | ) 18 | -------------------------------------------------------------------------------- /BcContainerHelper.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "GUID": "8e034fbc-8c30-446d-bbc3-5b3be5392491", 3 | "Author": "Freddy Kristiansen", 4 | "Copyright": "(c) 2022 Microsoft. All rights reserved.", 5 | "Description": "PowerShell module, which makes it easier to work with Business Central Containers on Docker.", 6 | "CompanyName": "Microsoft", 7 | "CompatiblePSEditions": [ 8 | "Core", 9 | "Desktop" 10 | ], 11 | "RequiredModules": [ 12 | ], 13 | "files": [ 14 | "AL-Go\\*", 15 | "Api\\*", 16 | "AppHandling\\*", 17 | "AppSource\\*", 18 | "Artifacts\\*", 19 | "Auth\\*", 20 | "AzureAD\\*", 21 | "AzureVM\\*", 22 | "Bacpac\\*", 23 | "Common\\*", 24 | "CompanyHandling\\*", 25 | "ConfigPackageHandling\\*", 26 | "CompilerFolderHandling\\*", 27 | "ContainerHandling\\*", 28 | "ContainerInfo\\*", 29 | "Misc\\*", 30 | "NuGet\\*", 31 | "ObjectHandling\\*", 32 | "PackageHandling\\*", 33 | "Saas\\*", 34 | "SymbolHandling\\*", 35 | "TenantHandling\\*", 36 | "UserHandling\\*", 37 | "addfonts.ps1", 38 | "BcContainerHelper.ps1", 39 | "BcContainerHelper.psm1", 40 | "Check-BcContainerHelperPermissions.ps1", 41 | "CreateALGoRepo.ps1", 42 | "CreateScript.ps1", 43 | "HelperFunctions.ps1", 44 | "InitializeModule.ps1", 45 | "Microsoft.ApplicationInsights.dll", 46 | "TelemetryHelper.ps1", 47 | "BC.*.ps1" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /BcContainerHelper.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [switch] $ExportTelemetryFunctions, 4 | [string[]] $bcContainerHelperConfigFile = @(), 5 | [switch] $useVolumes 6 | ) 7 | 8 | . (Join-Path $PSScriptRoot 'Import-BcContainerHelper.ps1') -Silent:$silent -ExportTelemetryFunctions:$ExportTelemetryFunctions -bcContainerHelperConfigFile $bcContainerHelperConfigFile -useVolumes:$useVolumes 9 | -------------------------------------------------------------------------------- /CI_CD_Workshop.md: -------------------------------------------------------------------------------- 1 | # CI/CD Workshop 2 | 3 | The recommended way of doing CI/CD today for AppSource apps or PTEs is to use [AL-Go for GitHub](https://github.com/microsoft/AL-Go#readme). The documentation will take you through how to do things. 4 | 5 | You can access the "old" CI/CD Workshop [here](https://github.com/microsoft/AL-Go/blob/main/Scenarios/old/CI_CD_Workshop.md). 6 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @microsoft/d365-bc-engineering-systems 2 | -------------------------------------------------------------------------------- /Common/ConvertTo-HashTable.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Convert PSCustomObject to HashTable 4 | .Description 5 | Convert PSCustomObject to HashTable 6 | .Example 7 | Get-Content "test.json" | ConvertFrom-Json | ConvertTo-HashTable 8 | #> 9 | function ConvertTo-HashTable() { 10 | [CmdletBinding()] 11 | Param( 12 | [parameter(ValueFromPipeline)] 13 | $object, 14 | [switch] $recurse 15 | ) 16 | 17 | function AddValueToHashTable { 18 | Param( 19 | [hashtable] $ht, 20 | [string] $name, 21 | $value, 22 | [switch] $recurse 23 | ) 24 | 25 | if ($ht.Contains($name)) { 26 | throw "Duplicate key $name" 27 | } 28 | if ($recurse -and ($value -is [System.Collections.Specialized.OrderedDictionary] -or $value -is [hashtable] -or $value -is [System.Management.Automation.PSCustomObject])) { 29 | $ht[$name] = ConvertTo-HashTable $value -recurse 30 | } 31 | elseif ($recurse -and $value -is [array]) { 32 | $ht[$name] = @($value | ForEach-Object { 33 | if (($_ -is [System.Collections.Specialized.OrderedDictionary]) -or ($_ -is [hashtable]) -or ($_ -is [System.Management.Automation.PSCustomObject])) { 34 | ConvertTo-HashTable $_ -recurse 35 | } 36 | else { 37 | $_ 38 | } 39 | }) 40 | } 41 | else { 42 | $ht[$name] = $value 43 | } 44 | } 45 | 46 | $ht = @{} 47 | if ($object -is [System.Collections.Specialized.OrderedDictionary] -or $object -is [hashtable]) { 48 | $object.Keys | ForEach-Object { 49 | AddValueToHashTable -ht $ht -name $_ -value $object."$_" -recurse:$recurse 50 | } 51 | } 52 | elseif ($object -is [System.Management.Automation.PSCustomObject]) { 53 | $object.PSObject.Properties | ForEach-Object { 54 | AddValueToHashTable -ht $ht -name $_.Name -value $_.Value -recurse:$recurse 55 | } 56 | } 57 | $ht 58 | } 59 | Export-ModuleMember -Function ConvertTo-HashTable 60 | -------------------------------------------------------------------------------- /Common/ConvertTo-OrderedDictionary.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Convert PSCustomObject to OrderedDictionary 4 | .Description 5 | Convert PSCustomObject to OrderedDictionary 6 | .Example 7 | Get-Content "test.json" | ConvertFrom-Json | ConvertTo-HashTable 8 | #> 9 | function ConvertTo-OrderedDictionary() { 10 | [CmdletBinding()] 11 | Param( 12 | [parameter(ValueFromPipeline)] 13 | [PSCustomObject] $object, 14 | [switch] $sort 15 | ) 16 | $ht = [ordered]@{} 17 | if ($object) { 18 | if ($sort) { 19 | $object.PSObject.Properties | Sort-Object -Property Name -Culture "iv-iv" | Foreach { $ht[$_.Name] = $_.Value } 20 | } 21 | else { 22 | $object.PSObject.Properties | Foreach { $ht[$_.Name] = $_.Value } 23 | } 24 | } 25 | $ht 26 | } 27 | Export-ModuleMember -Function ConvertTo-OrderedDictionary 28 | -------------------------------------------------------------------------------- /Common/Get-PlainText.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Convert SecureString to Plain Text 4 | .Description 5 | Convert SecureString to Plain Text 6 | .Parameter secureString 7 | Secure String to convert to plain text 8 | .Example 9 | Get-PlainText -secureString $credential.Password 10 | #> 11 | function Get-PlainText() { 12 | [CmdletBinding()] 13 | Param( 14 | [parameter(ValueFromPipeline, Mandatory = $true)] 15 | [System.Security.SecureString] $SecureString 16 | ) 17 | $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString) 18 | try { 19 | return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) 20 | } 21 | finally { 22 | [Runtime.InteropServices.Marshal]::FreeBSTR($bstr) 23 | } 24 | } 25 | Export-ModuleMember -Function Get-PlainText 26 | -------------------------------------------------------------------------------- /Common/Invoke-gh.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Invoke gh command with parameters 4 | .Description 5 | Requires Github CLI installed 6 | #> 7 | function invoke-gh { 8 | Param( 9 | [parameter(mandatory = $false, ValueFromPipeline = $true)] 10 | [string] $inputStr = "", 11 | [switch] $silent, 12 | [switch] $returnValue, 13 | [parameter(mandatory = $true, position = 0)][string] $command, 14 | [parameter(mandatory = $false, position = 1, ValueFromRemainingArguments = $true)] $remaining 15 | ) 16 | 17 | Process { 18 | $arguments = "$command " 19 | foreach($parameter in $remaining) { 20 | if ("$parameter".IndexOf(" ") -ge 0 -or "$parameter".IndexOf('"') -ge 0) { 21 | if ($parameter.length -gt 15000) { 22 | $parameter = "$($parameter.Substring(0,15000))...`n`n**Truncated due to size limits!**" 23 | } 24 | $arguments += """$($parameter.Replace('"','\"'))"" " 25 | } 26 | else { 27 | $arguments += "$parameter " 28 | } 29 | } 30 | cmdDo -command gh -arguments $arguments -silent:$silent -returnValue:$returnValue -inputStr $inputStr -messageIfCmdNotFound "Github CLI not found. Please install it from https://cli.github.com/" 31 | } 32 | } 33 | 34 | Export-ModuleMember -Function Invoke-gh 35 | -------------------------------------------------------------------------------- /Common/Invoke-git.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Invoke git command with parameters 4 | .Description 5 | Requires Git installed 6 | #> 7 | function invoke-git { 8 | Param( 9 | [parameter(mandatory = $false, ValueFromPipeline = $true)] 10 | [string] $inputStr = "", 11 | [switch] $silent, 12 | [switch] $returnValue, 13 | [parameter(mandatory = $true, position = 0)][string] $command, 14 | [parameter(mandatory = $false, position = 1, ValueFromRemainingArguments = $true)] $remaining 15 | ) 16 | 17 | Process { 18 | $arguments = "$command " 19 | foreach($parameter in $remaining) { 20 | if ("$parameter".IndexOf(" ") -ge 0 -or "$parameter".IndexOf('"') -ge 0) { 21 | $arguments += """$($parameter.Replace('"','\"'))"" " 22 | } 23 | else { 24 | $arguments += "$parameter " 25 | } 26 | } 27 | cmdDo -command git -arguments $arguments -silent:$silent -returnValue:$returnValue -inputStr $inputStr -messageIfCmdNotFound "Git not found. Please install it from https://git-scm.com/downloads" 28 | } 29 | } 30 | Export-ModuleMember -Function Invoke-git 31 | -------------------------------------------------------------------------------- /Common/Remove-DesktopShortcut.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Remove a shortcut 4 | .Description 5 | Remove a shortcut 6 | .Parameter Name 7 | Name of shortcut to remove from all locations 8 | #> 9 | function Remove-DesktopShortcut { 10 | Param ( 11 | [Parameter(Mandatory=$true)] 12 | [string] $Name 13 | ) 14 | "Desktop","CommonDesktop" | % { 15 | $environmentPath = [Environment]::GetFolderPath($_) 16 | If ($environmentPath -ne "") { 17 | $filename = Join-Path $environmentPath "$Name.lnk" 18 | if (Test-Path -Path $filename -PathType Leaf) { 19 | Remove-Item $filename -force 20 | } 21 | else { 22 | $folderName = $Name.Split(' ')[0] 23 | $shortcutName = $name.Substring($folderName.Length).TrimStart(' ') 24 | $folderName = Join-Path $environmentPath $folderName 25 | $filename = Join-Path $foldername "$shortcutName.lnk" 26 | if (Test-Path -Path $filename -PathType leaf) { 27 | Remove-Item $filename -Force 28 | try { 29 | Remove-Item $folderName -Recurse -force 30 | } catch {} 31 | } 32 | } 33 | } 34 | } 35 | "StartMenu","CommonStartMenu" | % { 36 | $environmentPath = [Environment]::GetFolderPath($_) 37 | if ($environmentPath -ne "") { 38 | $filename = Join-Path $environmentPath "BcContainerHelper\$Name.lnk" 39 | if (Test-Path -Path $filename) { 40 | Remove-Item $filename -force 41 | } 42 | } 43 | } 44 | } 45 | Export-ModuleMember -Function Remove-DesktopShortcut 46 | -------------------------------------------------------------------------------- /CompanyHandling/Copy-CompanyInNavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Copy company in a NAV/BC Container 4 | .Description 5 | Create a session to a container and run Copy-NavCompany 6 | .Parameter containerName 7 | Name of the container in which you want to create the company 8 | .Parameter tenant 9 | Name of tenant you want to create the commpany for in the container 10 | .Parameter sourceCompanyName 11 | Name of the source company 12 | .Parameter destinationCompanyName 13 | Name of the destination company 14 | .Example 15 | Copy-CompanyInBcContainer -containerName test2 -sourceCompanyName 'Cronus International Ltd.' -destinationCompanyName 'Cronus Subsidiary' -tenant mytenant 16 | #> 17 | function Copy-CompanyInBcContainer { 18 | Param ( 19 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 20 | [string] $tenant = "default", 21 | [Parameter(Mandatory=$true)] 22 | [string] $sourceCompanyName, 23 | [Parameter(Mandatory=$true)] 24 | [string] $destinationCompanyName 25 | ) 26 | 27 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 28 | try { 29 | 30 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($sourceCompanyName, $destinationCompanyName, $tenant) 31 | Write-Host "Copying company from $sourceCompanyName to $destinationCompanyName in $tenant" 32 | Copy-NAVCompany -ServerInstance $ServerInstance -Tenant $tenant -SourceCompanyName $sourceCompanyName -DestinationCompanyName $destinationCompanyName 33 | } -ArgumentList $sourceCompanyName, $destinationCompanyName, $tenant 34 | Write-Host -ForegroundColor Green "Company successfully copied" 35 | } 36 | catch { 37 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 38 | throw 39 | } 40 | finally { 41 | TrackTrace -telemetryScope $telemetryScope 42 | } 43 | } 44 | Set-Alias -Name Copy-CompanyInNavContainer -Value Copy-CompanyInBcContainer 45 | Export-ModuleMember -Function Copy-CompanyInBcContainer -Alias Copy-CompanyInNavContainer 46 | -------------------------------------------------------------------------------- /CompanyHandling/Get-CompanyInNavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get a list of companies in the NAV/BC Container 4 | .Description 5 | Create a session to a container and run Get-NavCompany 6 | .Parameter containerName 7 | Name of the container in which you want to get the companies 8 | .Parameter tenant 9 | Name of tenant you want to get the commpanies for in the container 10 | .Example 11 | Get-CompanyInBcContainer -containerName bcserver 12 | #> 13 | function Get-CompanyInBcContainer { 14 | Param ( 15 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 16 | [string] $tenant = "default" 17 | ) 18 | 19 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 20 | try { 21 | 22 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($tenant) 23 | Get-NavCompany -ServerInstance $ServerInstance -Tenant $tenant 24 | } -ArgumentList $tenant | Where-Object {$_ -isnot [System.String]} 25 | } 26 | catch { 27 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 28 | throw 29 | } 30 | finally { 31 | TrackTrace -telemetryScope $telemetryScope 32 | } 33 | } 34 | Set-Alias -Name Get-CompanyInNavContainer -Value Get-CompanyInBcContainer 35 | Export-ModuleMember -Function Get-CompanyInBcContainer -Alias Get-CompanyInNavContainer 36 | -------------------------------------------------------------------------------- /CompanyHandling/New-CompanyInNavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Create a new company in the NAV/BC Container 4 | .Description 5 | Create a session to a container and run New-NavCompany 6 | .Parameter containerName 7 | Name of the container in which you want to create the company 8 | .Parameter tenant 9 | Name of tenant you want to create the commpany for in the container 10 | .Parameter companyName 11 | Name of the new company 12 | .Parameter evaluationCompany 13 | Specifies whether the company that you want to create is an evaluation company 14 | .Example 15 | New-CompanyInBcContainer -containerName test2 -companyName 'My Company' -tenant mytenant 16 | #> 17 | function New-CompanyInBcContainer { 18 | Param ( 19 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 20 | [string] $tenant = "default", 21 | [Parameter(Mandatory=$true)] 22 | [string] $companyName, 23 | [switch] $evaluationCompany 24 | ) 25 | 26 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 27 | try { 28 | 29 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($companyName, $evaluationCompany, $tenant) 30 | Write-Host "Creating company $companyName in $tenant" 31 | New-NavCompany -ServerInstance $ServerInstance -Tenant $tenant -CompanyName $companyName -EvaluationCompany:$evaluationCompany 32 | } -ArgumentList $companyName, $evaluationCompany, $tenant 33 | Write-Host -ForegroundColor Green "Company successfully created" 34 | } 35 | catch { 36 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 37 | throw 38 | } 39 | finally { 40 | TrackTrace -telemetryScope $telemetryScope 41 | } 42 | } 43 | Set-Alias -Name New-CompanyInNavContainer -Value New-CompanyInBcContainer 44 | Export-ModuleMember -Function New-CompanyInBcContainer -Alias New-CompanyInNavContainer 45 | -------------------------------------------------------------------------------- /CompanyHandling/Remove-CompanyInNavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Remove a company from the NAV/BC Container 4 | .Description 5 | Create a session to a container and run Remove-NavCompany 6 | .Parameter containerName 7 | Name of the container from which you want to remove the company 8 | .Parameter tenant 9 | Name of tenant you want to remove the commpany from in the container 10 | .Parameter companyName 11 | Name of the company you want to remove 12 | .Example 13 | Remove-CompanyInBcContainer -containerName test2 -companyName 'My Company' -tenant mytenant 14 | #> 15 | function Remove-CompanyInBcContainer { 16 | Param ( 17 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 18 | [string] $tenant = "default", 19 | [Parameter(Mandatory=$true)] 20 | [string] $companyName 21 | ) 22 | 23 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 24 | try { 25 | 26 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($companyName, $tenant) 27 | Write-Host "Removing company $companyName from $tenant" 28 | Remove-NavCompany -ServerInstance $ServerInstance -Tenant $tenant -CompanyName $companyName -ForceImmediateDataDeletion -Force 29 | } -ArgumentList $companyName, $tenant 30 | Write-Host -ForegroundColor Green "Company successfully removed" 31 | } 32 | catch { 33 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 34 | throw 35 | } 36 | finally { 37 | TrackTrace -telemetryScope $telemetryScope 38 | } 39 | } 40 | Set-Alias -Name Remove-CompanyInNavContainer -Value Remove-CompanyInBcContainer 41 | Export-ModuleMember -Function Remove-CompanyInBcContainer -Alias Remove-CompanyInNavContainer 42 | -------------------------------------------------------------------------------- /CompilerFolderHandling/Remove-BcCompilerFolder.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Remove a compilerFolder 4 | .DESCRIPTION 5 | This is used for cleaning up and removing a compiler folder 6 | .PARAMETER compilerFolder 7 | Folder to remove (must reside under the hostHelperFolder/compiler folder) 8 | .EXAMPLE 9 | Remove-BcCompilerFolder -compilerFolder $compilerFolder 10 | #> 11 | function Remove-BcCompilerFolder { 12 | Param( 13 | [string] $compilerFolder 14 | ) 15 | 16 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 17 | try { 18 | if ($compilerFolder -like (Join-Path $bcContainerHelperConfig.hostHelperFolder "compiler\*")) { 19 | Remove-Item -Path $compilerFolder -Force -Recurse -ErrorAction Ignore 20 | } 21 | else { 22 | throw "$compilerFolder is not a ContainerHelper Compiler Folder" 23 | } 24 | } 25 | catch { 26 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 27 | throw 28 | } 29 | finally { 30 | TrackTrace -telemetryScope $telemetryScope 31 | } 32 | } 33 | Export-ModuleMember -Function Remove-BcCompilerFolder -------------------------------------------------------------------------------- /ConfigPackageHandling/Get-PackageInfoFromRapidStartFile.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get a configuration package information from package file 4 | .Description 5 | Get a configuration package information from package file. 6 | Output: 7 | ExcludeConfigTables : 1 8 | LanguageID : 1033 9 | ProductVersion : W1_21.0.7.0 10 | PackageName : My package Setup 11 | Code : MYPACKAGE_SETUP 12 | .Parameter path 13 | Path to RapidStart package file 14 | .Example 15 | Get-PackageInfoFromRapidStartFile -path 'C:\temp\package.rapidstart' 16 | #> 17 | function Get-PackageInfoFromRapidStartFile { 18 | Param ( 19 | [string] $path 20 | ) 21 | 22 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 23 | try { 24 | $packageFile = $null 25 | $gzipStream = $null 26 | $buffer = $null 27 | $packageInfo = $null 28 | $packageFile = New-Object System.IO.FileStream $path, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) 29 | $gzipStream = New-Object System.IO.Compression.GzipStream $packageFile, ([IO.Compression.CompressionMode]::Decompress) 30 | $buffer = New-Object byte[](1024) 31 | while ($true) { 32 | $read = $gzipstream.Read($buffer, 0, 1024) 33 | if ($read -le 0) { break } 34 | $readText = [System.Text.Encoding]::Unicode.GetString($buffer) 35 | $readText.Split([Environment]::NewLine) | ForEach-Object { 36 | if ($_.IndexOf('DataList') -ne -1 ) { 37 | [xml]$package = ($_ + '') 38 | $packageInfo = $package.'DataList' 39 | break 40 | } 41 | } 42 | } 43 | return $packageInfo 44 | } 45 | catch { 46 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 47 | throw 48 | } 49 | finally { 50 | if ($gzipStream) { 51 | $gzipStream.Close() 52 | } 53 | if ($packageFile) { 54 | $packageFile.Close() 55 | } 56 | TrackTrace -telemetryScope $telemetryScope 57 | } 58 | } 59 | Export-ModuleMember -Function Get-PackageInfoFromRapidStartFile 60 | -------------------------------------------------------------------------------- /ConfigPackageHandling/Import-ConfigPackageInNavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Imports a configuration package into the application database in a NAV/BC Container 4 | .Description 5 | Create a session to a container and run Import-NAVConfigurationPackageFile 6 | .Parameter containerName 7 | Name of the container in which you want to import the configuration package to 8 | .Parameter configPackageFile 9 | Path to the configuration package file you want to import 10 | .Example 11 | Import-ConfigPackageInBcContainer -containerName test2 -configPackage 'c:\temp\configPackage.rapidstart' 12 | #> 13 | function Import-ConfigPackageInBcContainer { 14 | Param ( 15 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 16 | [Parameter(Mandatory=$true)] 17 | [string] $configPackageFile 18 | ) 19 | 20 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 21 | try { 22 | 23 | $containerConfigPackageFile = Get-BcContainerPath -containerName $containerName -path $configPackageFile -throw 24 | 25 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($configPackageFile) 26 | Write-Host "Importing configuration package from $configPackageFile (container path)" 27 | Import-NAVConfigurationPackageFile -ServerInstance $ServerInstance -Path $configPackageFile 28 | } -ArgumentList $containerConfigPackageFile 29 | Write-Host -ForegroundColor Green "Configuration package imported" 30 | } 31 | catch { 32 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 33 | throw 34 | } 35 | finally { 36 | TrackTrace -telemetryScope $telemetryScope 37 | } 38 | } 39 | Set-Alias -Name Import-ConfigPackageInNavContainer -Value Import-ConfigPackageInBcContainer 40 | Export-ModuleMember -Function Import-ConfigPackageInBcContainer -Alias Import-ConfigPackageInNavContainer 41 | -------------------------------------------------------------------------------- /ConfigPackageHandling/Remove-ConfigPackageInNavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Removes a configuration package from the application database in a NAV/BC Container 4 | .Description 5 | Create a session to a container and run Remove-NAVConfigurationPackageFile 6 | .Parameter containerName 7 | Name of the container in which you want to remove the configuration package from 8 | .Parameter configPackageCode 9 | The code of the configuration package you want to remove 10 | .Example 11 | Remove-ConfigPackageInBcContainer -containerName test2 -configPackageCode 'US.ENU.EXTENDED' 12 | #> 13 | function Remove-ConfigPackageInBcContainer { 14 | Param ( 15 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 16 | [Parameter(Mandatory=$true)] 17 | [string] $configPackageCode 18 | ) 19 | 20 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 21 | try { 22 | 23 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($configPackageCode) 24 | Write-Host "Removing configuration package $configPackageCode" 25 | Remove-NAVConfigurationPackageFile -ServerInstance $ServerInstance -Code $configPackageCode -Force 26 | } -ArgumentList $configPackageCode 27 | Write-Host -ForegroundColor Green "Configuration package removed" 28 | } 29 | catch { 30 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 31 | throw 32 | } 33 | finally { 34 | TrackTrace -telemetryScope $telemetryScope 35 | } 36 | } 37 | Set-Alias -Name Remove-ConfigPackageInNavContainer -Value Remove-ConfigPackageInBcContainer 38 | Export-ModuleMember -Function Remove-ConfigPackageInBcContainer -Alias Remove-ConfigPackageInNavContainer 39 | -------------------------------------------------------------------------------- /ContainerHandling/Enter-NavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Enter PowerShell session in a NAV/BC Container 4 | .Description 5 | Use the current PowerShell prompt to enter a PowerShell session in a Container. 6 | Especially useful in PowerShell ISE, where you after entering a session, can use PSEdit to edit files inside the container. 7 | The PowerShell session will have the PowerShell modules pre-loaded, meaning that you can use most PowerShell CmdLets. 8 | .Parameter containerName 9 | Name of the container for which you want to enter a session 10 | .Example 11 | Enter-BcContainer -containerName 12 | [64b6ca872aefc93529bdfc7ec0a4eb7a2f0c022942000c63586a48c27b4e7b2d]: PS C:\run>psedit c:\run\navstart.ps1 13 | #> 14 | function Enter-BcContainer { 15 | [CmdletBinding()] 16 | Param ( 17 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName 18 | ) 19 | 20 | Process { 21 | if ($bcContainerHelperConfig.usePsSession) { 22 | try { 23 | $session = Get-BcContainerSession -containerName $containerName -silent 24 | } 25 | catch { 26 | $session = $null 27 | } 28 | } 29 | if ($session) { 30 | Enter-PSSession -Session $session 31 | if ($session.ComputerType -eq 'Container') { 32 | Invoke-Command -Session $session -ScriptBlock { 33 | function prompt {"[$env:COMPUTERNAME]: PS5 $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "} 34 | } 35 | } 36 | } 37 | else { 38 | Write-Host "Could not create a session, running Open-BcContainer instead" 39 | Open-BcContainer $containerName 40 | } 41 | } 42 | } 43 | Set-Alias -Name Enter-NavContainer -Value Enter-BcContainer 44 | Export-ModuleMember -Function Enter-BcContainer -Alias Enter-NavContainer 45 | -------------------------------------------------------------------------------- /ContainerHandling/Extract-FilesFromNavContainerImage.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Extract Files From NAV/BC Container Image 4 | .Description 5 | Extract all files from a Container Image necessary to start a generic container with these files 6 | .Parameter imageName 7 | Name of the Container Image from which you want to extract the files 8 | .Parameter path 9 | Location where you want the files to be placed 10 | .Parameter extract 11 | Determine what you need to extract (default is all) 12 | .Parameter force 13 | Specify -force if you want to automatically remove the destination folder if it exists 14 | .Example 15 | Extract-FilesFromBcContainerImage -ImageName microsoft/bcsandbox:us -Path "c:\programdata\bccontainerhelper\extensions\acontainer\afolder" 16 | #> 17 | function Extract-FilesFromBcContainerImage { 18 | [CmdletBinding()] 19 | Param ( 20 | [string] $imageName, 21 | [string] $path, 22 | [ValidateSet('all','vsix','database')] 23 | [string] $extract = "all", 24 | [switch] $force 25 | ) 26 | 27 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 28 | try { 29 | 30 | $ErrorActionPreference = 'Continue' 31 | 32 | Write-Host "Creating temp container from $imagename and extract necessary files" 33 | $containerName = "bccontainerhelper-temp" 34 | docker rm $containerName 2>$null | Out-null 35 | docker create --name $containerName $imagename | Out-Null 36 | 37 | $ErrorActionPreference = 'Stop' 38 | 39 | Extract-FilesFromStoppedBcContainer -containerName $containerName -path $path -extract $extract -force:$force 40 | 41 | $ErrorActionPreference = 'Continue' 42 | 43 | Write-Host "Removing temp container" 44 | docker rm $containerName 2>$null | Out-null 45 | 46 | $ErrorActionPreference = 'Stop' 47 | } 48 | catch { 49 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 50 | throw 51 | } 52 | finally { 53 | TrackTrace -telemetryScope $telemetryScope 54 | } 55 | } 56 | Set-Alias -Name Extract-FilesFromNavContainerImage -Value Extract-FilesFromBcContainerImage 57 | Export-ModuleMember -Function Extract-FilesFromBcContainerImage -Alias Extract-FilesFromNavContainerImage 58 | -------------------------------------------------------------------------------- /ContainerHandling/Get-AlLanguageExtensionFromArtifacts.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the path of the AL Language Extension from an artifactUrl 4 | .Description 5 | Downloads artifacts and return the path of the .vsix file within the artifacts 6 | .Example 7 | New-BcContainer ... -vsixFile (Get-AlLanguageExtensionFromArtifacts -artifactUrl $artifactUrl) ... 8 | #> 9 | function Get-AlLanguageExtensionFromArtifacts { 10 | Param( 11 | [string] $artifactUrl 12 | ) 13 | 14 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 15 | try { 16 | 17 | $paths = Download-Artifacts $artifactUrl -includePlatform 18 | $vsixFile = Get-Item -Path (Join-Path $paths[1] "ModernDev\*\Microsoft Dynamics NAV\*\AL Development Environment\*.vsix") 19 | if ($vsixFile) { 20 | $vsixFile.FullName 21 | } 22 | else { 23 | throw "Unable to locate AL Language Extension from artifacts $($artifactUrl.Split('?')[0])" 24 | } 25 | } 26 | catch { 27 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 28 | throw 29 | } 30 | finally { 31 | TrackTrace -telemetryScope $telemetryScope 32 | } 33 | } 34 | Export-ModuleMember -Function Get-AlLanguageExtensionFromArtifacts 35 | -------------------------------------------------------------------------------- /ContainerHandling/Get-LatestAlLanguageExtensionUrl.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the URL of the latest AL Language Extension from VS Code Marketplace 4 | .Description 5 | Get the URL of the latest AL Language Extension from VS Code Marketplace 6 | .Parameter allowPrerelease 7 | If specified, will return the URL of the latest version (including pre-release versions) of the AL Language Extension 8 | .Example 9 | New-BcContainer ... -vsixFile (Get-LatestAlLanguageExtensionUrl) ... 10 | .Example 11 | Download-File -SourceUrl (Get-LatestAlLanguageExtensionUrl) -DestinationFile "c:\temp\al.vsix" 12 | #> 13 | function Get-LatestAlLanguageExtensionUrl { 14 | Param( 15 | [switch] $allowPrerelease 16 | ) 17 | 18 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 19 | try { 20 | $version, $url = GetLatestAlLanguageExtensionVersionAndUrl -allowPrerelease:$allowPrerelease 21 | return $url 22 | } 23 | catch { 24 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 25 | throw 26 | } 27 | finally { 28 | TrackTrace -telemetryScope $telemetryScope 29 | } 30 | } 31 | Export-ModuleMember -Function Get-LatestAlLanguageExtensionUrl 32 | -------------------------------------------------------------------------------- /ContainerHandling/New-NavContainerWizard.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Runs a poor mans wizard to generate a container 4 | .Description 5 | Ask a number of questions to determine the parameters for a new container 6 | #> 7 | function New-BcContainerWizard { 8 | 9 | $pslink = Join-Path $env:APPDATA "Microsoft\Windows\Start Menu\Programs\Windows PowerShell\Windows PowerShell.lnk" 10 | if (!(Test-Path $pslink)) { 11 | $pslink = "powershell.exe" 12 | } 13 | 14 | $script = (Get-Item -Path (Join-Path $PSScriptRoot "..\CreateScript.ps1")).FullName 15 | 16 | $module = Get-InstalledModule -Name "BcContainerHelper" -ErrorAction SilentlyContinue 17 | 18 | Write-Host "Launching $script" 19 | 20 | if ($module) { 21 | Start-Process $pslink @("-File ""$script""", "-skipContainerHelperCheck") 22 | } 23 | else { 24 | . $script -skipContainerHelperCheck 25 | } 26 | 27 | 28 | } 29 | Set-Alias -Name New-NavContainerWizard -Value New-BcContainerWizard 30 | Export-ModuleMember -Function New-BcContainerWizard -Alias New-NavContainerWizard 31 | -------------------------------------------------------------------------------- /ContainerHandling/Restart-BcContainerServiceTier.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Restarts a Business Central Server instance inside of an Business Central Container. 4 | .Description 5 | The Restart-BcContainerServiceTier cmldet stops a server instance, and then starts it again. 6 | You will typically use the Restart-BcContainerServiceTier cmdlet after you make changes to the 7 | server instance configuration using the Set-BcContainerServerConfiguration cmdlet, because most 8 | configuration changes will not take effect until the server instance is restarted. 9 | 10 | Be aware that when you restart the server instance, all client connections to the server instance are terminated. 11 | .Parameter containerName 12 | Name of container which Business Central Server you want to restart 13 | .Example 14 | Restart-BcContainerServiceTier -containerName "MyContainer" 15 | #> 16 | function Restart-BcContainerServiceTier { 17 | Param ( 18 | [String] $ContainerName = $bcContainerHelperConfig.defaultContainerName 19 | ) 20 | 21 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 22 | try { 23 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock{ 24 | Get-NavServerInstance | Restart-NAVServerInstance 25 | } | Out-Null 26 | } 27 | catch { 28 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 29 | throw 30 | } 31 | finally { 32 | TrackTrace -telemetryScope $telemetryScope 33 | } 34 | } 35 | Export-ModuleMember -Function Restart-BcContainerServiceTier 36 | -------------------------------------------------------------------------------- /ContainerHandling/Set-BcContainerServerConfiguration.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Configures settings for a Business Central Server instance. 4 | .Description 5 | Use the Set-BcContainerServerConfiguration cmdlet to configure settings for a Business Central Server instance. 6 | Changes to just the configuration file will first take effect when the server instance is restarted. 7 | .Parameter containerName 8 | Name of the container for which you want to get the server configuration 9 | .Parameter KeyName 10 | Key of the container for which you want to get the server configuration 11 | .Parameter KeyValue 12 | Value of the container for which you want to get the server configuration 13 | .Example 14 | Set-BcContainerServerConfiguration -ContainerName "MyContainer" -KeyName "EnableTaskScheduler" -KeyValue "true" 15 | #> 16 | Function Set-BcContainerServerConfiguration { 17 | Param ( 18 | [String] $containerName = $bcContainerHelperConfig.defaultContainerName, 19 | [Parameter(Mandatory=$true)] 20 | [string] $keyName, 21 | [Parameter(Mandatory=$true)] 22 | [string] $keyValue 23 | ) 24 | 25 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 26 | try { 27 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock{ 28 | Param($keyName, $keyValue) 29 | Get-NavServerInstance | Set-NAVServerConfiguration -KeyName $keyName -KeyValue $keyValue 30 | } -argumentList $keyName, $keyValue | Out-Null 31 | } 32 | catch { 33 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 34 | throw 35 | } 36 | finally { 37 | TrackTrace -telemetryScope $telemetryScope 38 | } 39 | } 40 | Export-ModuleMember -Function Set-BcContainerServerConfiguration 41 | -------------------------------------------------------------------------------- /ContainerHandling/Start-NavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Start a NAV/BC Container 4 | .Description 5 | Start a Container 6 | .Parameter containerName 7 | Name of the container you want to start 8 | .Parameter timeout 9 | Specify the number of seconds to wait for activity. Default is 1800 (30 min.), -1 means wait forever, 0 means don't wait. 10 | .Example 11 | Start-BcContainer -containerName test 12 | #> 13 | function Start-BcContainer { 14 | [CmdletBinding()] 15 | Param ( 16 | [Parameter(Mandatory=$false, ValueFromPipeline)] 17 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 18 | [int] $timeout = 1800 19 | ) 20 | 21 | if ((docker inspect -f '{{.State.Running}}' $containerName) -eq "true") { 22 | Write-Host "Container $containerName is already running" 23 | return 24 | } 25 | 26 | $logs = @(docker logs $containerName) 27 | $startlog = [string]::Join("`r`n",$logs) 28 | 29 | if (!(DockerDo -command start -imageName $containerName)) { 30 | return 31 | } 32 | if ($timeout -ne 0) { 33 | Wait-BcContainerReady -containerName $containerName -timeout $timeout -startlog $startlog 34 | } 35 | } 36 | Set-Alias -Name Start-NavContainer -Value Start-BcContainer 37 | Export-ModuleMember -Function Start-BcContainer -Alias Start-NavContainer 38 | -------------------------------------------------------------------------------- /ContainerHandling/Stop-NavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Stop a NAV/BC Container 4 | .Description 5 | Stop a Container 6 | .Parameter containerName 7 | Name of the container you want to stop 8 | .Example 9 | Stop-BcContainer -containerName devServer 10 | #> 11 | function Stop-BcContainer { 12 | [CmdletBinding()] 13 | Param ( 14 | [Parameter(Mandatory=$false, ValueFromPipeline)] 15 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName 16 | ) 17 | 18 | Write-Host "Removing Session $containerName" 19 | Remove-BcContainerSession $containerName 20 | 21 | if (!(DockerDo -command stop -imageName $containerName)) { 22 | return 23 | } 24 | } 25 | Set-Alias -Name Stop-NavContainer -Value Stop-BcContainer 26 | Export-ModuleMember -Function Stop-BcContainer -Alias Stop-NavContainer 27 | -------------------------------------------------------------------------------- /ContainerHandling/traefik/CheckHealth.ps1: -------------------------------------------------------------------------------- 1 | $healthcheckurl = ("http://localhost/" + $env:webserverinstance + "/") 2 | try { 3 | $result = Invoke-WebRequest -Uri "$($healthcheckurl)Health/System" -UseBasicParsing -TimeoutSec 10 4 | if ($result.StatusCode -eq 200 -and ((ConvertFrom-Json $result.Content).result)) { 5 | # Web Client Health Check Endpoint will test Web Client, Service Tier and Database Connection 6 | exit 0 7 | } 8 | } catch { 9 | } 10 | exit 1 -------------------------------------------------------------------------------- /ContainerHandling/traefik/CheckHealth_https.ps1: -------------------------------------------------------------------------------- 1 | if (-not("dummy" -as [type])) { 2 | add-type -TypeDefinition @" 3 | using System; 4 | using System.Net; 5 | using System.Net.Security; 6 | using System.Security.Cryptography.X509Certificates; 7 | public static class Dummy { 8 | public static bool ReturnTrue(object sender, 9 | X509Certificate certificate, 10 | X509Chain chain, 11 | SslPolicyErrors sslPolicyErrors) { return true; } 12 | public static RemoteCertificateValidationCallback GetDelegate() { 13 | return new RemoteCertificateValidationCallback(Dummy.ReturnTrue); 14 | } 15 | } 16 | "@ 17 | } 18 | 19 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [dummy]::GetDelegate() 20 | 21 | $healthcheckurl = ("https://localhost/" + $env:webserverinstance + "/") 22 | try { 23 | $result = Invoke-WebRequest -Uri "$($healthcheckurl)Health/System" -UseBasicParsing -TimeoutSec 10 24 | if ($result.StatusCode -eq 200 -and ((ConvertFrom-Json $result.Content).result)) { 25 | # Web Client Health Check Endpoint will test Web Client, Service Tier and Database Connection 26 | exit 0 27 | } 28 | } catch { 29 | } 30 | exit 1 -------------------------------------------------------------------------------- /ContainerHandling/traefik/template_traefik.toml: -------------------------------------------------------------------------------- 1 | debug = false 2 | defaultEntryPoints = ["https","http"] 3 | 4 | [api] 5 | # Check https://docs.traefik.io/v1.7/configuration/api/#security 6 | # to enable authentication on the dashboard for extra security 7 | 8 | [docker] 9 | domain = "$PublicDnsName" 10 | watch = true 11 | endpoint = "npipe:////./pipe/docker_engine" 12 | 13 | [entryPoints] 14 | [entryPoints.http] 15 | address = ":80" 16 | [entryPoints.http.redirect] 17 | entryPoint = "https" 18 | [entryPoints.https] 19 | address = ":443" 20 | [entryPoints.https.tls] 21 | minVersion = "VersionTLS12" 22 | 23 | [acme] 24 | email = "$ContactEMailForLetsEncrypt" 25 | storage = "c:/etc/traefik/acme.json" 26 | entryPoint = "https" 27 | [acme.httpChallenge] 28 | entryPoint = "http" 29 | [[acme.domains]] 30 | main = "$PublicDnsName" 31 | 32 | [file] 33 | [backends] 34 | [backends.host] 35 | [backends.host.servers.server1] 36 | url = "http://${IP}:8180" 37 | 38 | [frontends] 39 | [frontends.host] 40 | backend = "host" 41 | [frontends.host.routes.route1] 42 | rule = "PathPrefix:/" -------------------------------------------------------------------------------- /ContainerHandling/traefik/template_traefik_https.toml: -------------------------------------------------------------------------------- 1 | debug = false 2 | defaultEntryPoints = ["https","http"] 3 | insecureSkipVerify = true 4 | 5 | [api] 6 | # Check https://docs.traefik.io/v1.7/configuration/api/#security 7 | # to enable authentication on the dashboard for extra security 8 | 9 | [docker] 10 | domain = "$PublicDnsName" 11 | watch = true 12 | endpoint = "npipe:////./pipe/docker_engine" 13 | 14 | [entryPoints] 15 | [entryPoints.http] 16 | address = ":80" 17 | [entryPoints.http.redirect] 18 | entryPoint = "https" 19 | [entryPoints.https] 20 | address = ":443" 21 | [entryPoints.https.tls] 22 | minVersion = "VersionTLS12" 23 | 24 | [acme] 25 | email = "$ContactEMailForLetsEncrypt" 26 | storage = "c:/etc/traefik/acme.json" 27 | entryPoint = "https" 28 | [acme.httpChallenge] 29 | entryPoint = "http" 30 | [[acme.domains]] 31 | main = "$PublicDnsName" 32 | 33 | [file] 34 | [backends] 35 | [backends.host] 36 | [backends.host.servers.server1] 37 | url = "http://${IP}:8180" 38 | 39 | [frontends] 40 | [frontends.host] 41 | backend = "host" 42 | [frontends.host.routes.route1] 43 | rule = "PathPrefix:/" -------------------------------------------------------------------------------- /ContainerHandling/traefik/template_traefik_https_own.toml: -------------------------------------------------------------------------------- 1 | debug = false 2 | defaultEntryPoints = ["https","http"] 3 | insecureSkipVerify = true 4 | 5 | [api] 6 | # Check https://docs.traefik.io/v1.7/configuration/api/#security 7 | # to enable authentication on the dashboard for extra security 8 | 9 | [docker] 10 | domain = "$PublicDnsName" 11 | watch = true 12 | endpoint = "npipe:////./pipe/docker_engine" 13 | 14 | [entryPoints] 15 | [entryPoints.http] 16 | address = ":80" 17 | [entryPoints.http.redirect] 18 | entryPoint = "https" 19 | [entryPoints.https] 20 | address = ":443" 21 | [entryPoints.https.tls] 22 | minVersion = "VersionTLS12" 23 | [[entryPoints.https.tls.certificates]] 24 | certFile = "c:/etc/traefik/certificate.crt" 25 | keyFile = "c:/etc/traefik/certificate.key" 26 | 27 | [file] 28 | [backends] 29 | [backends.host] 30 | [backends.host.servers.server1] 31 | url = "http://${IP}:8180" 32 | 33 | [frontends] 34 | [frontends.host] 35 | backend = "host" 36 | [frontends.host.routes.route1] 37 | rule = "PathPrefix:/" -------------------------------------------------------------------------------- /ContainerHandling/traefik/template_traefik_own.toml: -------------------------------------------------------------------------------- 1 | debug = false 2 | defaultEntryPoints = ["https","http"] 3 | 4 | [api] 5 | # Check https://docs.traefik.io/v1.7/configuration/api/#security 6 | # to enable authentication on the dashboard for extra security 7 | 8 | [docker] 9 | domain = "$PublicDnsName" 10 | watch = true 11 | endpoint = "npipe:////./pipe/docker_engine" 12 | 13 | [entryPoints] 14 | [entryPoints.http] 15 | address = ":80" 16 | [entryPoints.http.redirect] 17 | entryPoint = "https" 18 | [entryPoints.https] 19 | address = ":443" 20 | [entryPoints.https.tls] 21 | minVersion = "VersionTLS12" 22 | [[entryPoints.https.tls.certificates]] 23 | certFile = "c:/etc/traefik/certificate.crt" 24 | keyFile = "c:/etc/traefik/certificate.key" 25 | 26 | [file] 27 | [backends] 28 | [backends.host] 29 | [backends.host.servers.server1] 30 | url = "http://${IP}:8180" 31 | 32 | [frontends] 33 | [frontends.host] 34 | backend = "host" 35 | [frontends.host.routes.route1] 36 | rule = "PathPrefix:/" -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerArtifactUrl.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the artifactUrl used to run a NAV/BC Container (or blank if artifacts wasn't used) 4 | .Description 5 | Get the artifactUrl used to run a NAV/BC Container (or blank if artifacts wasn't used) 6 | The artifactUrl can be used to run a new instance of a Container with the same version of NAV/BC 7 | .Parameter containerName 8 | Name of the container for which you want to get the image name 9 | .Example 10 | $artifactUrl = Get-BcContainerArtifactUrl -containerName bcserver 11 | PS C:\>New-BcContainer -accept_eula -artifactUrl $artifactUrl -containerName test 12 | #> 13 | function Get-BcContainerArtifactUrl { 14 | [CmdletBinding()] 15 | Param ( 16 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName 17 | ) 18 | 19 | $inspect = docker inspect $containerName | ConvertFrom-Json 20 | $artifactUrlEnv = $inspect.config.Env | Where-Object { $_ -like "artifactUrl=*" } 21 | if ($artifactUrlEnv) { 22 | return $artifactUrlEnv.SubString("artifactUrl=".Length) 23 | } 24 | else { 25 | return "" 26 | } 27 | } 28 | Set-Alias -Name Get-NavContainerArtifactUrl -Value Get-BcContainerArtifactUrl 29 | Export-ModuleMember -Function Get-BcContainerArtifactUrl -Alias Get-NavContainerArtifactUrl 30 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerCountry.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the country version from a NAV/BC Ccontainer or a NAV/BC Container image 4 | .Description 5 | Returns the country version (localization) for the version of NAV or Business Central in the Container or ContainerImage 6 | .Parameter containerOrImageName 7 | Name of the container or container image for which you want to get the country version 8 | .Example 9 | Get-BcContainerCountry -containerOrImageName bcserver 10 | .Example 11 | Get-BcContainerCountry -containerOrImageName myimage:mytag 12 | #> 13 | function Get-BcContainerCountry { 14 | [CmdletBinding()] 15 | Param ( 16 | [Parameter(Mandatory=$true)] 17 | [string] $containerOrImageName 18 | ) 19 | 20 | $inspect = docker inspect $containerOrImageName | ConvertFrom-Json 21 | if ($inspect.Config.Labels.psobject.Properties.Match('maintainer').Count -eq 0 -or $inspect.Config.Labels.maintainer -ne "Dynamics SMB") { 22 | throw "Container $containerOrImageName is not a NAV/BC container" 23 | } 24 | return "$($inspect.Config.Labels.country)" 25 | } 26 | Set-Alias -Name Get-NavContainerCountry -Value Get-BcContainerCountry 27 | Export-ModuleMember -Function Get-BcContainerCountry -Alias Get-NavContainerCountry 28 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerEula.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the Eula Link for for a NAV/BC Container or a NAV/BC Container image 4 | .Description 5 | Returns the Eula link for the version of NAV or Business Central in the Container or Container Image 6 | This is the Eula, which you accept when running the Container using -e accept_eula=Y 7 | .Parameter containerOrImageName 8 | Name of the container or container image for which you want to get the Eula link 9 | .Example 10 | Get-BcContainerEula -containerOrImageName bcserver 11 | .Example 12 | Get-BcContainerEula -containerOrImageName microsoft/dynamics-nav:2017 13 | #> 14 | function Get-BcContainerEula { 15 | [CmdletBinding()] 16 | Param ( 17 | [Parameter(Mandatory=$true)] 18 | [string] $containerOrImageName 19 | ) 20 | 21 | $inspect = docker inspect $containerOrImageName | ConvertFrom-Json 22 | if ($inspect.Config.Labels.psobject.Properties.Match('maintainer').Count -eq 0 -or $inspect.Config.Labels.maintainer -ne "Dynamics SMB") { 23 | throw "Container $containerOrImageName is not a NAV/BC container" 24 | } 25 | return "$($inspect.Config.Labels.Eula)" 26 | } 27 | Set-Alias -Name Get-NavContainerEula -Value Get-BcContainerEula 28 | Export-ModuleMember -Function Get-BcContainerEula -Alias Get-NavContainerEula 29 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerEventLog.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the Event log from a NAV/BC Container as an .evtx file 4 | .Description 5 | Get a copy of the current Event Log from a continer and open it in the local event viewer 6 | .Parameter containerName 7 | Name of the container for which you want to get the Event log 8 | .Parameter logName 9 | Name of the log you want to get (default is Application) 10 | .Parameter doNotOpen 11 | Obtain a copy of the event log, but do not open the event log in the event viewer 12 | .Example 13 | Get-BcContainerEventLog -containerName bcserver 14 | .Example 15 | Get-BcContainerEventLog -containerName bcserver -logname Security -doNotOpen 16 | #> 17 | function Get-BcContainerEventLog { 18 | [CmdletBinding()] 19 | Param ( 20 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 21 | [Parameter(Mandatory=$false)] 22 | [string] $logname = "Application", 23 | [switch] $doNotOpen 24 | ) 25 | 26 | Write-Host "Getting event log for $containername" 27 | 28 | $eventLogFolder = Join-Path $bcContainerHelperConfig.hostHelperFolder "EventLogs" 29 | if (!(Test-Path $eventLogFolder)) { 30 | New-Item $eventLogFolder -ItemType Directory | Out-Null 31 | } 32 | $eventLogName = Join-Path $eventLogFolder ($containerName + ' ' + [DateTime]::Now.ToString("yyyy-MM-dd HH.mm.ss") + ".evtx") 33 | $locale = (Get-WinSystemLocale).Name 34 | 35 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param([string]$path, [string]$logname, [string]$locale) 36 | wevtutil epl $logname "$path" 37 | wevtutil al "$path" /locale:$locale 38 | } -ArgumentList (Get-BcContainerPath -containerName $containerName -Path $eventLogName), $logname, $locale 39 | 40 | if ($doNotOpen) { 41 | $eventLogName 42 | } 43 | else { 44 | Start-Process -FilePath $eventLogName | Out-Null 45 | } 46 | } 47 | Set-Alias -Name Get-NavContainerEventLog -Value Get-BcContainerEventLog 48 | Export-ModuleMember -Function Get-BcContainerEventLog -Alias Get-NavContainerEventLog 49 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerGenericTag.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the generic tag for a NAV/BC Container or a NAV/BC Container image 4 | .Description 5 | Returns the generic Tag version referring to a release from http://www.github.com/microsoft/nav-docker 6 | .Parameter containerOrImageName 7 | Name of the container or container image for which you want to get the generic tag 8 | .Example 9 | Get-BcContainerGenericTag -containerOrImageName bcserver 10 | .Example 11 | Get-BcContainerGenericTag -containerOrImageName microsoft/dynamics-nav:2017 12 | #> 13 | function Get-BcContainerGenericTag { 14 | [CmdletBinding()] 15 | Param ( 16 | [Parameter(Mandatory=$true)] 17 | [string] $containerOrImageName 18 | ) 19 | 20 | $inspect = docker inspect $containerOrImageName | ConvertFrom-Json 21 | if ($inspect.Config.Labels.psobject.Properties.Match('tag').Count -eq 0) { 22 | throw "Container $containerOrImageName is not a NAV/BC container" 23 | } 24 | return "$($inspect.Config.Labels.tag)" 25 | } 26 | Set-Alias -Name Get-NavContainerGenericTag -Value Get-BcContainerGenericTag 27 | Export-ModuleMember -Function Get-BcContainerGenericTag -Alias Get-NavContainerGenericTag 28 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerId.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the Id of a NAV/BC Container 4 | .Description 5 | Returns the Id of a Container based on the container name 6 | The Id returned is the full 64 digit container Id and the name must match 7 | .Parameter containerName 8 | Name of the container for which you want the Id 9 | .Example 10 | Get-BcContainerId -containerId bcserver 11 | #> 12 | function Get-BcContainerId { 13 | [CmdletBinding()] 14 | Param ( 15 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName 16 | ) 17 | 18 | $id = "" 19 | docker ps --format "{{.ID}}:{{.Names}}" -a --no-trunc | ForEach-Object { 20 | $ps = $_.split(':') 21 | if ($containerName -eq $ps[1]) { 22 | $id = $ps[0] 23 | } 24 | if ($ps[0].StartsWith($containerName)) { 25 | if ($id) { 26 | throw "Unambiguous container ID specified" 27 | } 28 | $id = $ps[0] 29 | } 30 | } 31 | if (!($id)) { 32 | throw "Container $containerName does not exist" 33 | } 34 | $id 35 | } 36 | Set-Alias -Name Get-NavContainerId -Value Get-BcContainerId 37 | Export-ModuleMember -Function Get-BcContainerId -Alias Get-NavContainerId 38 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerImageName.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the name of the image used to run a NAV/BC Container 4 | .Description 5 | Get the name of the image used to run a Container 6 | The image name can be used to run a new instance of a Container with the same version of NAV/BC 7 | .Parameter containerName 8 | Name of the container for which you want to get the image name 9 | .Example 10 | $imageName = Get-BcContainerImageName -containerName bcserver 11 | PS C:\>Docker run -e accept_eula=Y $imageName 12 | #> 13 | function Get-BcContainerImageName { 14 | [CmdletBinding()] 15 | Param ( 16 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName 17 | ) 18 | 19 | $inspect = docker inspect $containerName | ConvertFrom-Json 20 | return "$($inspect.Config.Image)" 21 | } 22 | Set-Alias -Name Get-NavContainerImageName -Value Get-BcContainerImageName 23 | Export-ModuleMember -Function Get-BcContainerImageName -Alias Get-NavContainerImageName 24 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerIpAddress.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the IP Address of a NAV/BC Container 4 | .Description 5 | Inspect the Container and return the IP Address of the first network. 6 | .Parameter containerName 7 | Name of the container for which you want to get the IP Address 8 | .Parameter networkName 9 | Specify network name if you want to get the IP Address for a specific network 10 | .Example 11 | Get-BcContainerIpAddress -containerName bcserver 12 | #> 13 | function Get-BcContainerIpAddress { 14 | [CmdletBinding()] 15 | Param ( 16 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 17 | [Parameter(Mandatory=$false)] 18 | [string] $networkName = "" 19 | ) 20 | 21 | $ip = Invoke-ScriptInBcContainer -containerName $containerName -scriptblock { 22 | $ip = "" 23 | $ips = Get-NetIPAddress | Where-Object { $_.AddressFamily -eq "IPv4" -and $_.IPAddress -ne "127.0.0.1" } 24 | if ($ips) { 25 | $ips | ForEach-Object { 26 | if ("$ip" -eq "") { 27 | $ip = $_.IPAddress 28 | } 29 | } 30 | } 31 | $ip 32 | } 33 | 34 | if ("$ip" -eq "") { 35 | $inspect = docker inspect $containerName | ConvertFrom-Json 36 | $networks = $inspect.NetworkSettings.Networks 37 | $networks | get-member -MemberType NoteProperty | Select-Object Name | % { 38 | $name = $_.Name 39 | if (("$ip" -eq "") -and ("$networkName" -eq "" -or "$networkName" -eq "$name")) { 40 | $network = $networks | Select-Object -ExpandProperty $name 41 | $ip = $network.IPAddress 42 | } 43 | } 44 | } 45 | return $ip 46 | } 47 | Set-Alias -Name Get-NavContainerIpAddress -Value Get-BcContainerIpAddress 48 | Export-ModuleMember -Function Get-BcContainerIpAddress -Alias Get-NavContainerIpAddress 49 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerLegal.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the Legal Link for for a NAV/BC Container or a NAV/BC Container image 4 | .Description 5 | Returns the Legal link for the version of NAV or Business Central in the Container or Container Image 6 | This is the legal agreement for running this version of NAV or Business Central 7 | .Parameter containerOrImageName 8 | Name of the container or container image for which you want to get the legal link 9 | .Example 10 | Get-BcContainerLegal -containerOrImageName bcserver 11 | .Example 12 | Get-BcContainerLegal -containerOrImageName microsoft/dynamics-nav:2017 13 | #> 14 | function Get-BcContainerLegal { 15 | [CmdletBinding()] 16 | Param ( 17 | [Parameter(Mandatory=$true)] 18 | [string] $containerOrImageName 19 | ) 20 | 21 | $inspect = docker inspect $containerOrImageName | ConvertFrom-Json 22 | if ($inspect.Config.Labels.psobject.Properties.Match('maintainer').Count -eq 0 -or $inspect.Config.Labels.maintainer -ne "Dynamics SMB") { 23 | throw "Container $containerOrImageName is not a NAV/BC container" 24 | } 25 | return "$($inspect.Config.Labels.legal)" 26 | } 27 | Set-Alias -Name Get-NavContainerLegal -Value Get-BcContainerLegal 28 | Export-ModuleMember -Function Get-BcContainerLegal -Alias Get-NavContainerLegal 29 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerLicenseInformation.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Retrieve the Business Central license information from a NAV/BC Container 4 | .Description 5 | Returns the license information used on the Business Central service in the container. 6 | .Parameter containerName 7 | Name of the container for which you want to get the license information 8 | .Example 9 | Get-BcContainerLicenseInformation -ContainerName "MyContainer" 10 | #> 11 | Function Get-BcContainerLicenseInformation { 12 | Param ( 13 | [String] $ContainerName = $bcContainerHelperConfig.defaultContainerName 14 | ) 15 | 16 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { 17 | Get-NavServerInstance | Export-NAVServerLicenseInformation 18 | } 19 | } 20 | Set-Alias -Name Get-NavContainerLicenseInformation -Value Get-BcContainerLicenseInformation 21 | Export-ModuleMember -Function Get-BcContainerLicenseInformation -Alias Get-NavContainerLicenseInformation -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerName.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the name of a NAV/BC Container 4 | .Description 5 | Returns the name of a Container based on the container Id 6 | You need to specify enought characters of the Id to make it unambiguous 7 | .Parameter containerId 8 | Id (or part of the Id) of the container for which you want to get the name 9 | .Example 10 | Get-BcContainerName -containerId 7d 11 | #> 12 | function Get-BcContainerName { 13 | Param ( 14 | [Parameter(Mandatory=$true)] 15 | [string] $containerId 16 | ) 17 | 18 | docker ps --format='{{.Names}}' -a --filter "id=$containerId" 19 | } 20 | Set-Alias -Name Get-NavContainerName -Value Get-BcContainerName 21 | Export-ModuleMember -Function Get-BcContainerName -Alias Get-NavContainerName 22 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerNavVersion.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the application version from a NAV/BC Container or a NAV/BC Container image 4 | .Description 5 | Returns the version of NAV/BC in the format major.minor.build.release-country 6 | .Parameter containerOrImageName 7 | Name of the container or container image for which you want to get the version 8 | .Example 9 | Get-BcContainerNavVersion -containerOrImageName bcserver 10 | .Example 11 | Get-BcContainerNavVersion -containerOrImageName microsoft/dynamics-nav:2017 12 | #> 13 | function Get-BcContainerNavVersion { 14 | [CmdletBinding()] 15 | Param ( 16 | [Parameter(Mandatory=$true)] 17 | [string] $containerOrImageName 18 | ) 19 | 20 | $inspect = docker inspect $containerOrImageName | ConvertFrom-Json 21 | if ($inspect.Config.Labels.psobject.Properties.Match('maintainer').Count -eq 0 -or $inspect.Config.Labels.maintainer -ne "Dynamics SMB") { 22 | throw "Container $containerOrImageName is not a NAV/BC container" 23 | } 24 | return "$($inspect.Config.Labels.version)-$($inspect.Config.Labels.country)" 25 | } 26 | Set-Alias -Name Get-NavContainerNavVersion -Value Get-BcContainerNavVersion 27 | Export-ModuleMember -Function Get-BcContainerNavVersion -Alias Get-NavContainerNavVersion 28 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerOsVersion.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the OS Version for a NAV/BC Container or a NAV/BC Container image 4 | .Description 5 | Returns the version of the WindowsServerCore image used to build the Container or ContainerImage 6 | .Parameter containerOrImageName 7 | Name of the container or container image for which you want to get the OS Version 8 | .Example 9 | Get-BcContainerOsVersion -containerOrImageName bcserver 10 | .Example 11 | Get-BcContainerOsVersion -containerOrImageName microsoft/dynamics-nav:2017 12 | #> 13 | function Get-BcContainerOsVersion { 14 | [CmdletBinding()] 15 | Param ( 16 | [Parameter(Mandatory=$true)] 17 | [string] $containerOrImageName 18 | ) 19 | 20 | $inspect = docker inspect $containerOrImageName | ConvertFrom-Json 21 | return "$($inspect.Config.Labels.osversion)" 22 | } 23 | Set-Alias -Name Get-NavContainerOsVersion -Value Get-BcContainerOsVersion 24 | Export-ModuleMember -Function Get-BcContainerOsVersion -Alias Get-NavContainerOsVersion 25 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerPath.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the container file system path of a host file 4 | .Description 5 | Enumerates the shared folders with the container and returns the container file system path for a file shared with the container. 6 | .Parameter containerName 7 | Name of the container for which you want to find the filepath 8 | .Parameter path 9 | Path of a file in the host file system 10 | .Parameter throw 11 | Include the throw switch to throw an exception if the folder isn't shared with the container 12 | .Example 13 | $containerPath = Get-BcContainerPath -containerName bcserver -path c:\programdata\bccontainerhelper\extensions\test2\my 14 | #> 15 | function Get-BcContainerPath { 16 | [CmdletBinding()] 17 | Param ( 18 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 19 | [Parameter(Mandatory=$true)] 20 | [string] $path, 21 | [switch] $throw 22 | ) 23 | 24 | $containerPath = "" 25 | if ($path.StartsWith(":")) { 26 | $path =$path.Substring(1) 27 | $exist = Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { Param($path) 28 | Test-Path $path 29 | } -ArgumentList $path 30 | if ($exist) { 31 | $containerPath = $path 32 | } 33 | if ($throw -and "$containerPath" -eq "") { 34 | throw "The path $path does not exist in the container $containerName" 35 | } 36 | } else { 37 | $sharedFolders = Get-BcContainerSharedFolders -containerName $containerName 38 | $sharedFolders.GetEnumerator() | ForEach-Object { 39 | $Name = $_.Name.TrimEnd('\') 40 | $Value = $_.Value.TrimEnd('\') 41 | if ($path -eq $Name -or ($containerPath -eq "" -and $path.StartsWith($Name+"\", "OrdinalIgnoreCase"))) { 42 | $containerPath = ($Value + $path.Substring($Name.Length)) 43 | } 44 | } 45 | if ($throw -and "$containerPath" -eq "") { 46 | throw "The path $path is not shared with the container $containerName (nor is any of it's parent folders)" 47 | } 48 | } 49 | return $containerPath 50 | } 51 | Set-Alias -Name Get-NavContainerPath -Value Get-BcContainerPath 52 | Export-ModuleMember -Function Get-BcContainerPath -Alias Get-NavContainerPath 53 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerPlatformVersion.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the Platform Version from a Business Central container or Business Central container image 4 | The function will return blank for NAV Containers 5 | .Description 6 | Returns the platform version of Business Central in the format major.minor.build.release 7 | .Parameter containerOrImageName 8 | Name of the container or container image for which you want to get the platform version 9 | .Example 10 | Get-BcContainerPlatformVersion -containerOrImageName bcserver 11 | .Example 12 | Get-BcContainerPlatformVersion -containerOrImageName myimage:mytag 13 | #> 14 | function Get-BcContainerPlatformVersion { 15 | [CmdletBinding()] 16 | Param ( 17 | [Parameter(Mandatory=$true)] 18 | [string] $containerOrImageName 19 | ) 20 | 21 | $inspect = docker inspect $containerOrImageName | ConvertFrom-Json 22 | if ($inspect.Config.Labels.psobject.Properties.Match('maintainer').Count -eq 0 -or $inspect.Config.Labels.maintainer -ne "Dynamics SMB") { 23 | throw "Container $containerOrImageName is not a NAV/BC container" 24 | } 25 | if ($inspect.Config.Labels.psobject.Properties.Name -eq 'platform') { 26 | return "$($inspect.Config.Labels.platform)" 27 | } else { 28 | return "" 29 | } 30 | } 31 | Set-Alias -Name Get-NavContainerPlatformVersion -Value Get-BcContainerPlatformVersion 32 | Export-ModuleMember -Function Get-BcContainerPlatformVersion -Alias Get-NavContainerPlatformVersion 33 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerServerConfiguration.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Retrieve the Server configuration from a NAV/BC Container as a powershell object 4 | .Description 5 | Returns all the settings of the middletier from a container. 6 | .Parameter containerName 7 | Name of the container for which you want to get the server configuration 8 | .Example 9 | Get-BcContainerServerConfiguration -ContainerName "MyContainer" 10 | #> 11 | Function Get-BcContainerServerConfiguration { 12 | Param ( 13 | [String] $ContainerName = $bcContainerHelperConfig.defaultContainerName 14 | ) 15 | 16 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock{ Param($ContainerName) 17 | $config = Get-NavServerInstance | Get-NAVServerConfiguration -AsXml 18 | $object = [ordered]@{ "ContainerName" = $ContainerName } 19 | if ($config) { 20 | $Config.configuration.appSettings.add | ForEach-Object{ 21 | $object += @{ "$($_.Key)" = $_.Value } 22 | } 23 | } 24 | else { 25 | $object += @{ "ServerInstance" = "" } 26 | } 27 | $object | ConvertTo-Json -Depth 99 -compress 28 | } -argumentList $containerName | ConvertFrom-Json 29 | } 30 | Set-Alias -Name Get-NavContainerServerConfiguration -Value Get-BcContainerServerConfiguration 31 | Export-ModuleMember -Function Get-BcContainerServerConfiguration -Alias Get-NavContainerServerConfiguration 32 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainerSharedFolders.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get a list of folders shared with a NAV/BC Container 4 | .Description 5 | Returns a hastable of folders shared with the container. 6 | The name in the hashtable is the local folder, the value is the folder inside the container 7 | .Parameter containerName 8 | Name of the container for which you want to get the shared folder list 9 | .Example 10 | Get-BcContainerSharedFolders -containerName bcserver 11 | .Example 12 | (Get-BcContainerSharedFolders -containerName bcserver)["c:\programdata\bccontainerhelper"] 13 | .Example 14 | ((Get-BcContainerSharedFolders -containerName bcserver).GetEnumerator() | Where-Object { $_.Value -eq "c:\run\my" }).Key 15 | #> 16 | function Get-BcContainerSharedFolders { 17 | [CmdletBinding()] 18 | Param ( 19 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName 20 | ) 21 | 22 | $inspect = docker inspect $containerName | ConvertFrom-Json 23 | $sharedFolders = @{} 24 | if ($inspect.HostConfig.Binds) { 25 | $inspect.HostConfig.Binds | ForEach-Object { 26 | $idx = $_.IndexOf(':', 2) 27 | $src = $_.Substring(0, $idx).TrimEnd('\') 28 | $dst = $_.SubString($idx+1) 29 | $idx = $dst.IndexOf(':', 2) 30 | if ($idx -gt 0) { 31 | $dst = $dst.SubString(0,$idx) 32 | } 33 | if (-not ($sharedFolders[$src])) { 34 | $sharedFolders += @{ $src = $dst } 35 | } 36 | } 37 | } 38 | 39 | if ($inspect.Mounts) { 40 | $inspect.Mounts | ForEach-Object { 41 | $src = $_.Source 42 | $dst = $_.Destination 43 | if (-not ($sharedFolders[$src])) { 44 | $sharedFolders += @{ $src = $dst } 45 | } 46 | } 47 | } 48 | return $sharedFolders 49 | } 50 | Set-Alias -Name Get-NavContainerSharedFolders -Value Get-BcContainerSharedFolders 51 | Export-ModuleMember -Function Get-BcContainerSharedFolders -Alias Get-NavContainerSharedFolders 52 | -------------------------------------------------------------------------------- /ContainerInfo/Get-NavContainers.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get a list of all NAV/BC Containers 4 | .Description 5 | Returns the names of all NAV/BC Containers 6 | .Example 7 | Get-BcContainers | Remove-BcContainer 8 | #> 9 | function Get-BcContainers { 10 | Param ( 11 | [switch] $includeLabels 12 | ) 13 | 14 | if ($includeLabels) { 15 | $containers = @() 16 | docker ps --filter "label=nav" -a --no-trunc --format 'name={{.Names}},id={{.ID}},image={{.Image}},createdat={{.CreatedAt}},runningfor={{.RunningFor}},size={{.Size}},status={{.Status}},{{.Labels}}' | % { 17 | $labels = [PSCustomObject]@{} 18 | $_.Split(',') | % { 19 | $name = $_.Split('=')[0] 20 | $value = $_.SubString($name.length+1) 21 | $labels | Add-Member -NotePropertyName $name -NotePropertyValue $value 22 | } 23 | $containers += $labels 24 | } 25 | } 26 | else { 27 | $containers = docker ps --filter "label=nav" -a --format '{{.Names}}' 28 | } 29 | $containers 30 | } 31 | Set-Alias -Name Get-NavContainers -Value Get-BcContainers 32 | Export-ModuleMember -Function Get-BcContainers -Alias Get-NavContainers 33 | -------------------------------------------------------------------------------- /ContainerInfo/Test-NavContainer.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Test whether a NAV/BC Container exists 4 | .Description 5 | Returns $true if a NAV/BC Container with the specified name exists 6 | .Parameter containerName 7 | Name of the container which you want to check for existence 8 | .Parameter doNotIncludeStoppedContainers 9 | Specify this parameter if you only want to test running containers 10 | .Example 11 | if (Test-BcContainer -containerName devcontainer) { dosomething } 12 | #> 13 | function Test-BcContainer { 14 | Param ( 15 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 16 | [switch] $doNotIncludeStoppedContainers 17 | ) 18 | 19 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 20 | try { 21 | 22 | if ($containerName) { 23 | $id = "" 24 | $a = "-a" 25 | if ($doNotIncludeStoppedContainers) { 26 | $a = $null 27 | } 28 | 29 | $id = docker ps $a --no-trunc --format "{{.ID}}/{{.Names}}" | Where-Object { $containerName -eq $_.split('/')[1] } | ForEach-Object { $_.split('/')[0] } 30 | if (!($id)) { 31 | $id = docker ps $a -q --no-trunc --filter "id=$containerName" 32 | } 33 | if ($id) { 34 | $inspect = docker inspect $id | ConvertFrom-Json 35 | ($inspect.Config.Labels.psobject.Properties.Match('maintainer').Count -ne 0 -and $inspect.Config.Labels.maintainer -eq "Dynamics SMB") 36 | } else { 37 | $false 38 | } 39 | } 40 | else { 41 | $false 42 | } 43 | } 44 | catch { 45 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 46 | throw 47 | } 48 | finally { 49 | TrackTrace -telemetryScope $telemetryScope 50 | } 51 | } 52 | Set-Alias -Name Test-NavContainer -Value Test-BcContainer 53 | Export-ModuleMember -Function Test-BcContainer -Alias Test-NavContainer 54 | -------------------------------------------------------------------------------- /Import-BC.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [switch] $ExportTelemetryFunctions, 4 | [string[]] $bcContainerHelperConfigFile = @(), 5 | [switch] $useVolumes 6 | ) 7 | 8 | if (($PSVersionTable.PSVersion -lt "6.0.0") -or $isWindows) { 9 | Get-ChildItem -Path $PSScriptRoot -Recurse | ForEach-Object { Unblock-File -Path $_.FullName } 10 | } 11 | 12 | $modules = @( 13 | "BcContainerHelper" 14 | "BC.HelperFunctions", 15 | "BC.ArtifactsHelper", 16 | "BC.AppSourceHelper", 17 | "BC.ALGoHelper", 18 | "BC.SaasHelper", 19 | "BC.NuGetHelper", 20 | "BC" 21 | ) 22 | 23 | [Array]::Reverse($modules) 24 | $modules | ForEach-Object { 25 | Remove-Module $_ -ErrorAction SilentlyContinue 26 | } 27 | [Array]::Reverse($modules) 28 | 29 | $modules | Select-Object -Skip 1 | ForEach-Object { 30 | $modulePath = Join-Path $PSScriptRoot "$_.psd1" 31 | Import-Module $modulePath -DisableNameChecking -ArgumentList $Silent, $ExportTelemetryFunctions, $bcContainerHelperConfigFile, $useVolumes 32 | } 33 | -------------------------------------------------------------------------------- /Import-BcContainerHelper.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [switch] $Silent, 3 | [switch] $ExportTelemetryFunctions, 4 | [string[]] $bcContainerHelperConfigFile = @(), 5 | [switch] $useVolumes 6 | ) 7 | 8 | if (($PSVersionTable.PSVersion -lt "6.0.0") -or $isWindows) { 9 | Get-ChildItem -Path $PSScriptRoot -Recurse | ForEach-Object { Unblock-File -Path $_.FullName } 10 | } 11 | 12 | $modules = @( 13 | "BcContainerHelper" 14 | "BC.HelperFunctions", 15 | "BC.ArtifactsHelper", 16 | "BC.AppSourceHelper", 17 | "BC.ALGoHelper", 18 | "BC.SaasHelper", 19 | "BC.NuGetHelper", 20 | "BC" 21 | ) 22 | 23 | [Array]::Reverse($modules) 24 | $modules | ForEach-Object { 25 | Remove-Module $_ -ErrorAction SilentlyContinue 26 | } 27 | [Array]::Reverse($modules) 28 | 29 | $modulePath = Join-Path $PSScriptRoot "$($modules[0]).psd1" 30 | Import-Module $modulePath -DisableNameChecking -ArgumentList $Silent, $ExportTelemetryFunctions, $bcContainerHelperConfigFile, $useVolumes 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /LatestGenericTagVersion.txt: -------------------------------------------------------------------------------- 1 | 0.0.0.0 -------------------------------------------------------------------------------- /LinuxTests/Auth.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | 12 | } 13 | 14 | Describe 'Api' { 15 | It 'Get-NavContainerApiCompanyId' { 16 | #TODO 17 | } 18 | It 'Invoke-NavContainerApi' { 19 | #TODO 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LinuxTests/Saas.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | 12 | } 13 | 14 | Describe 'Api' { 15 | It 'Get-NavContainerApiCompanyId' { 16 | #TODO 17 | } 18 | It 'Invoke-NavContainerApi' { 19 | #TODO 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /LinuxTests/_TestHelperFunctions.ps1: -------------------------------------------------------------------------------- 1 | $modulePath = Join-Path $PSScriptRoot "..\BcContainerHelper.psd1" 2 | Remove-Module BcContainerHelper -ErrorAction Ignore 3 | Import-Module $modulePath -DisableNameChecking 4 | 5 | $modulePath = Join-Path $PSScriptRoot "..\BcContainerHelper.psm1" 6 | Remove-Module BcContainerHelper -ErrorAction Ignore 7 | Import-Module $modulePath -DisableNameChecking 8 | -------------------------------------------------------------------------------- /Microsoft.ApplicationInsights.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/Microsoft.ApplicationInsights.dll -------------------------------------------------------------------------------- /Misc/Get-LocaleFromCountry.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get locale from NAV/BC country code 4 | .Description 5 | Get default locale based on country code used for NAV/BC 6 | .Parameter country 7 | A NAV/BC supported country code 8 | .Example 9 | $locale = Get-LocaleFromCountry -country "dk" 10 | #> 11 | function Get-LocaleFromCountry { 12 | Param ( 13 | [Parameter(Mandatory=$true)] 14 | [string] $country 15 | ) 16 | 17 | $country = $country.ToLowerInvariant() 18 | if ($country.StartsWith("fin")) { $country = $country.Substring(3) } 19 | 20 | $locales = @{ 21 | "at" = "de-AT" 22 | "au" = "en-AU" 23 | "be" = "nl-BE" 24 | "ch" = "de-CH" 25 | "cz" = "cs-CZ" 26 | "de" = "de-DE" 27 | "dk" = "da-DK" 28 | "es" = "es-ES" 29 | "fi" = "fi-FI" 30 | "fr" = "fr-FR" 31 | "gb" = "en-GB" 32 | "in" = "en-IN" 33 | "is" = "is-IS" 34 | "it" = "it-IT" 35 | "na" = "en-US" 36 | "nl" = "nl-NL" 37 | "no" = "nb-NO" 38 | "nz" = "en-NZ" 39 | "ru" = "ru-RU" 40 | "se" = "sv-SE" 41 | "w1" = "en-US" 42 | "us" = "en-US" 43 | "mx" = "es-MX" 44 | "ca" = "en-CA" 45 | "dech" = "de-CH" 46 | "frbe" = "fr-BE" 47 | "frca" = "fr-CA" 48 | "frch" = "fr-CH" 49 | "itch" = "it-CH" 50 | "nlbe" = "nl-BE" 51 | } 52 | 53 | return $locales[$country] 54 | } 55 | Export-ModuleMember -Function Get-LocaleFromCountry 56 | -------------------------------------------------------------------------------- /Misc/Get-NavVersionFromVersionInfo.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get NAV Version based on version info 4 | .Description 5 | Return NAV Version (like 2017, 2013r2 etc.) based on version number 6 | .Parameter versionInfo 7 | Version Info like (11.0.45332.0) 8 | .Example 9 | $mynav = "NAV $(Get-MavVersionFromVersionInfo -versionInfo $version) - build $version" 10 | #> 11 | function Get-NavVersionFromVersionInfo { 12 | Param ( 13 | [Parameter(Mandatory=$true)] 14 | [string] $versionInfo 15 | ) 16 | 17 | $versionInfoArr = $versionInfo.Split(".") 18 | $verno = ($versionInfoArr[0]+$versionInfoArr[1]) 19 | 20 | $versions = @{ 21 | "70" = "2013" 22 | "71" = "2013r2" 23 | "80" = "2015" 24 | "90" = "2016" 25 | "100" = "2017" 26 | "110" = "2018" 27 | } 28 | 29 | return $versions[$verno] 30 | } 31 | Export-ModuleMember -Function Get-NavVersionFromVersionInfo 32 | -------------------------------------------------------------------------------- /NuGet/Push-BcNuGetPackage.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | PROOF OF CONCEPT PREVIEW: Push Business Central NuGet Package to NuGet Server 4 | .Description 5 | Push Business Central NuGet Package to NuGet Server 6 | .PARAMETER nuGetServerUrl 7 | NuGet Server URL 8 | .PARAMETER nuGetToken 9 | NuGet Token for authenticated access to the NuGet Server 10 | .PARAMETER bcNuGetPackage 11 | Path to BcNuGetPackage to push. This is the value returned by New-BcNuGetPackage. 12 | .EXAMPLE 13 | $package = New-BcNuGetPackage -appfile $appFileName 14 | Push-BcNuGetPackage -nuGetServerUrl $nuGetServerUrl -nuGetToken $nuGetToken -bcNuGetPackage $package 15 | #> 16 | Function Push-BcNuGetPackage { 17 | Param( 18 | [Parameter(Mandatory=$true)] 19 | [string] $nuGetServerUrl, 20 | [Parameter(Mandatory=$true)] 21 | [string] $nuGetToken, 22 | [Parameter(Mandatory=$true)] 23 | [string] $bcNuGetPackage 24 | ) 25 | 26 | $nuGetFeed = [NuGetFeed]::Create($nuGetServerUrl, $nuGetToken, @(), @()) 27 | $nuGetFeed.PushPackage($bcNuGetPackage) 28 | } 29 | Export-ModuleMember -Function Push-BcNuGetPackage 30 | -------------------------------------------------------------------------------- /PackageHandling/Get-AzureFeedWildcardVersion.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Function for transforming appVersion to wildcard appVersion 4 | .Description 5 | Function for transforming appVersion to wildcard appVersion. 6 | 0s in the appVersion will be replaced with * to be able to resolve min version dependencies 7 | .Parameter appVerison 8 | appVersion to be transfromed. 9 | #> 10 | function Get-AzureFeedWildcardVersion { 11 | param ( 12 | [Parameter(Mandatory=$true)] 13 | [string] $appVersion 14 | ) 15 | 16 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 17 | try { 18 | 19 | $version = $appVersion.split('.') 20 | 21 | $major = $version[0] 22 | $minor = $version[1] 23 | $patch = $version[2] 24 | 25 | if($major -eq '0') { 26 | $major = '*'; 27 | } 28 | 29 | if(($minor -eq '0') -and ($patch -eq '0')) { 30 | $minor = '*'; 31 | } 32 | 33 | if($patch -eq '0') { 34 | $patch = '*'; 35 | } 36 | 37 | return ($major + '.' + $minor + '.' + $patch) 38 | } 39 | catch { 40 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 41 | throw 42 | } 43 | finally { 44 | TrackTrace -telemetryScope $telemetryScope 45 | } 46 | } 47 | Export-ModuleMember -Function Get-AzureFeedWildcardVersion 48 | -------------------------------------------------------------------------------- /PackageHandling/Install-AzDevops.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Function to install Az Cli and enable Devops extension 4 | .Description 5 | Function to install Az Cli and enable Devops extension. If az cli is installed, an update will be done. Otherwise the installation will be performed. 6 | #> 7 | function Install-AzDevops { 8 | Param( 9 | ) 10 | 11 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 12 | try { 13 | 14 | Try { 15 | $az_upgrade = Write-Output n | az upgrade 2>&1 16 | } catch { 17 | $az_upgrade = "Latest version available" 18 | } 19 | 20 | if (@($az_upgrade | Select-String "Latest version available").Count -ne 0) { 21 | $ProgressPreference = 'SilentlyContinue' 22 | Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'; Remove-Item .\AzureCLI.msi 23 | } 24 | 25 | $extensions = az extension list -o json | ConvertFrom-Json 26 | 27 | $devopsFound = $False 28 | foreach($extension in $extensions) 29 | { 30 | if($extension.name -eq 'azure-devops'){ 31 | $devopsFound = $True 32 | } 33 | } 34 | 35 | if ($devopsFound -eq $False){ 36 | az extension add -n azure-devops 37 | } 38 | } 39 | catch { 40 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 41 | throw 42 | } 43 | finally { 44 | TrackTrace -telemetryScope $telemetryScope 45 | } 46 | } 47 | Export-ModuleMember -Function Install-AzDevops 48 | -------------------------------------------------------------------------------- /SaaSHelperFunctions.ps1: -------------------------------------------------------------------------------- 1 | function Create-SaasUrl { 2 | Param( 3 | [Parameter(Mandatory = $true)] 4 | [Hashtable] $bcAuthContext, 5 | [string] $applicationFamily = "", 6 | [string] $environment = "", 7 | [string] $apiVersion = "", 8 | [string] $endPoint = "" 9 | ) 10 | 11 | $bcAuthContext = Renew-BcAuthContext -bcAuthContext $bcAuthContext 12 | $bearerAuthValue = "Bearer $($bcAuthContext.AccessToken)" 13 | $headers = @{ "Authorization" = $bearerAuthValue } 14 | 15 | $endPointURL = "$($bcContainerHelperConfig.apiBaseUrl.TrimEnd('/'))/admin/$apiVersion" 16 | if ($applicationFamily) { 17 | $endPointURL += "/applications/$applicationFamily" 18 | } 19 | if ($environment) { 20 | $endPointURL += "/environments/$environment" 21 | } 22 | else { 23 | $endPointURL += "/environments" 24 | } 25 | if ($endPoint) { 26 | $endPointURL += "/$endPoint" 27 | } 28 | 29 | return $bcAuthContext, $headers, $endPointURL 30 | } 31 | -------------------------------------------------------------------------------- /Saas/Get-BcEnvironmentPublishedApps.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Function for retrieving Published AppSource Apps from an online Business Central environment 4 | .Description 5 | Function for retrieving Published AppSource Apps from an online Business Central environment 6 | Wrapper for https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/administration-center-api#get-installed-apps 7 | .Parameter bcAuthContext 8 | Authorization Context created by New-BcAuthContext. 9 | .Parameter applicationFamily 10 | Application Family in which the environment is located. Default is BusinessCentral. 11 | .Parameter environment 12 | Environment from which you want to return the published Apps. 13 | .Parameter apiVersion 14 | API version. Default is v2.6. 15 | .Example 16 | $authContext = New-BcAuthContext -includeDeviceLogin 17 | Get-BcEnvironmentPublishedApps -bcAuthContext $authContext -environment "Sandbox" 18 | #> 19 | function Get-BcEnvironmentPublishedApps { 20 | Param( 21 | [Parameter(Mandatory = $true)] 22 | [Hashtable] $bcAuthContext, 23 | [string] $applicationFamily = "BusinessCentral", 24 | [Parameter(Mandatory = $true)] 25 | [string] $environment, 26 | [string] $apiVersion = "v2.6" 27 | ) 28 | 29 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 30 | try { 31 | 32 | $bcAuthContext = Renew-BcAuthContext -bcAuthContext $bcAuthContext 33 | $bearerAuthValue = "Bearer $($bcAuthContext.AccessToken)" 34 | $headers = @{ "Authorization" = $bearerAuthValue } 35 | try { 36 | (Invoke-RestMethod -Method Get -UseBasicParsing -Uri "$($bcContainerHelperConfig.apiBaseUrl.TrimEnd('/'))/admin/$apiVersion/applications/$applicationFamily/environments/$environment/apps" -Headers $headers).Value 37 | } 38 | catch { 39 | throw (GetExtendedErrorMessage $_) 40 | } 41 | } 42 | catch { 43 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 44 | throw 45 | } 46 | finally { 47 | TrackTrace -telemetryScope $telemetryScope 48 | } 49 | } 50 | Set-Alias -Name Get-BcPublishedApps -Value Get-BcEnvironmentPublishedApps 51 | Export-ModuleMember -Function Get-BcEnvironmentPublishedApps -Alias Get-BcPublishedApps 52 | -------------------------------------------------------------------------------- /Saas/Get-BcEnvironmentScheduledUpgrade.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get information about updates that have already been scheduled for a specific environment. 4 | .Description 5 | Get information about updates that have already been scheduled for a specific environment. 6 | Wrapper for https://docs.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/administration-center-api_reschedule_updates#get-scheduled-update 7 | .Parameter bcAuthContext 8 | Authorization Context created by New-BcAuthContext. 9 | .Parameter applicationFamily 10 | Application Family in which the environment is located. Default is BusinessCentral. 11 | .Parameter environment 12 | Environment from which you want to return the scheduled upgrade information. 13 | .Parameter apiVersion 14 | API version. Default is v2.3. 15 | .Example 16 | $authContext = New-BcAuthContext -includeDeviceLogin 17 | Get-BcEnvironmentScheduledUpgrade -bcAuthContext $authContext -environment "Sandbox" 18 | #> 19 | 20 | function Get-BcEnvironmentScheduledUpgrade { 21 | Param( 22 | [Parameter(Mandatory = $true)] 23 | [Hashtable] $bcAuthContext, 24 | [string] $applicationFamily = "BusinessCentral", 25 | [Parameter(Mandatory = $true)] 26 | [string] $environment, 27 | [string] $apiVersion = "v2.3" 28 | ) 29 | 30 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 31 | try { 32 | $bcAuthContext = Renew-BcAuthContext -bcAuthContext $bcAuthContext 33 | $bearerAuthValue = "Bearer $($bcAuthContext.AccessToken)" 34 | $headers = @{ "Authorization" = $bearerAuthValue } 35 | try { 36 | Invoke-RestMethod -Method Get -UseBasicParsing -Uri "$($bcContainerHelperConfig.apiBaseUrl.TrimEnd('/'))/admin/$apiVersion/applications/$applicationFamily/environments/$environment/upgrade" -Headers $headers 37 | } 38 | catch { 39 | throw (GetExtendedErrorMessage $_) 40 | } 41 | } 42 | catch { 43 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 44 | throw 45 | } 46 | finally { 47 | TrackTrace -telemetryScope $telemetryScope 48 | } 49 | } 50 | Set-Alias -Name Get-BcScheduledUpgrade -Value Get-BcEnvironmentScheduledUpgrade 51 | Export-ModuleMember -Function Get-BcEnvironmentScheduledUpgrade -Alias Get-BcScheduledUpgrade 52 | -------------------------------------------------------------------------------- /Saas/Get-BcEnvironmentUpdateWindow.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Function for getting Update Window on a Business Central online environment 4 | .Description 5 | Function for getting Update Window on a Business Central online environment. 6 | .Parameter bcAuthContext 7 | Authorization Context created by New-BcAuthContext. 8 | .Parameter applicationFamily 9 | Application Family in which the environment is located. Default is BusinessCentral. 10 | .Parameter environment 11 | Name of the environment which you want to get the Update Window from 12 | .Parameter apiVersion 13 | API version. Default is v2.18. 14 | .Example 15 | $bcauthContext = New-BcAuthContext -includeDeviceLogin 16 | Get-BcEnvironmentUpdateWindow -bcAuthContext $bcAuthContext -environment "Sandbox" 17 | #> 18 | function Get-BcEnvironmentUpdateWindow { 19 | Param( 20 | [Parameter(Mandatory = $true)] 21 | [Hashtable] $bcAuthContext, 22 | [string] $applicationFamily = "BusinessCentral", 23 | [Parameter(Mandatory = $true)] 24 | [string] $environment, 25 | [string] $apiversion = "v2.19" 26 | ) 27 | 28 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 29 | try { 30 | $bcAuthContext, $headers, $endPointURL = Create-SaasUrl -bcAuthContext $bcAuthContext -applicationFamily $applicationFamily -apiVersion $apiVersion -environment $environment -endPoint 'settings/upgrade' 31 | try { 32 | Invoke-RestMethod -Method Get -UseBasicParsing -Uri $endPointURL -Headers $headers 33 | } 34 | catch { 35 | throw (GetExtendedErrorMessage $_) 36 | } 37 | } 38 | catch { 39 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 40 | throw 41 | } 42 | finally { 43 | TrackTrace -telemetryScope $telemetryScope 44 | } 45 | } 46 | Set-Alias -Name Get-BcUpdateWindow -Value Get-BcEnvironmentUpdateWindow 47 | Export-ModuleMember -Function Get-BcEnvironmentUpdateWindow -Alias Get-BcUpdateWindow 48 | -------------------------------------------------------------------------------- /Saas/Get-BcEnvironments.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Function for retrieving a list of all environments or one selected environment from an online Business Central tenant 4 | .Description 5 | Function for retrieving a list of all environments or one selected environment from an online Business Central tenant 6 | Wrapper for https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/administration-center-api_environments#get-environment-by-application-family-and-name 7 | .Parameter bcAuthContext 8 | Authorization Context created by New-BcAuthContext. 9 | .Parameter applicationFamily 10 | Application Family in which the environment is located. Default is BusinessCentral. 11 | .Parameter environment 12 | Name of the environment 13 | .Parameter apiVersion 14 | API version. Default is v2.15. 15 | .Example 16 | $authContext = New-BcAuthContext -includeDeviceLogin 17 | Get-BcEnvironments -bcAuthContext $authContext 18 | .Example 19 | $authContext = New-BcAuthContext -includeDeviceLogin 20 | Get-BcEnvironments -bcAuthContext $authContext -environment "MySandbox" 21 | #> 22 | function Get-BcEnvironments { 23 | Param( 24 | [Parameter(Mandatory = $true)] 25 | [Hashtable] $bcAuthContext, 26 | [string] $applicationFamily = "BusinessCentral", 27 | [string] $environment = "", 28 | [string] $apiversion = "v2.19" 29 | ) 30 | 31 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 32 | try { 33 | $bcAuthContext, $headers, $endPointURL = Create-SaasUrl -bcAuthContext $bcAuthContext -environment $environment -applicationFamily $applicationFamily -apiVersion $apiVersion 34 | try { 35 | $Result = (Invoke-RestMethod -Method Get -UseBasicParsing -Uri $endPointURL -Headers $headers) 36 | if ($Result.PSObject.Properties.Name -eq 'Value') { 37 | $Result.Value 38 | } 39 | else { 40 | $Result 41 | } 42 | } 43 | catch { 44 | throw (GetExtendedErrorMessage $_) 45 | } 46 | } 47 | catch { 48 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 49 | throw 50 | } 51 | finally { 52 | TrackTrace -telemetryScope $telemetryScope 53 | } 54 | } 55 | Export-ModuleMember -Function Get-BcEnvironments 56 | -------------------------------------------------------------------------------- /Saas/Get-BcNotificationRecipients.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Function for retrieving the notification recipients configured for a Business Central tenant. 4 | .Description 5 | Function for retrieving the notification recipients configured for a Business Central tenant. 6 | Returns Id, Email and Name configured for each notification recipient. 7 | Wrapper for https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/administration-center-api_notifications#get-notification-recipients 8 | .Parameter bcAuthContext 9 | Authorization Context created by New-BcAuthContext. 10 | .Parameter apiVersion 11 | API version. Default is v2.15. 12 | .Example 13 | $bcauthContext = New-BcAuthContext -includeDeviceLogin 14 | Get-BcNotificationRecipients -bcAuthContext $bcauthContext 15 | #> 16 | 17 | function Get-BcNotificationRecipients { 18 | Param( 19 | [Parameter(Mandatory = $true)] 20 | [Hashtable] 21 | $bcAuthContext, 22 | [string] 23 | $apiVersion = "v2.6", 24 | [string] 25 | $applicationFamily = "BusinessCentral" 26 | ) 27 | 28 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 29 | try { 30 | $bcAuthContext, $headers, $endPointURL = Create-SaasUrl -bcAuthContext $bcAuthContext -applicationFamily $applicationFamily -apiVersion $apiVersion 31 | try { 32 | (Invoke-RestMethod -Method Get -UseBasicParsing -Uri "$($bcContainerHelperConfig.apiBaseUrl.TrimEnd('/'))/admin/$apiVersion/settings/notification/recipients" -Headers $headers).Value 33 | } 34 | catch { 35 | throw (GetExtendedErrorMessage $_) 36 | } 37 | } 38 | catch { 39 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 40 | throw 41 | } 42 | finally { 43 | TrackTrace -telemetryScope $telemetryScope 44 | } 45 | } 46 | Export-ModuleMember -Function Get-BcNotificationRecipients -------------------------------------------------------------------------------- /Saas/New-BcNotificationRecipient.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Function for creatig a notification recipient for a Business Central tenant. 4 | .Description 5 | Function for creating a notification recipient for a Business Central tenant. 6 | Submit Email and Name. 7 | Wrapper for https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/administration/administration-center-api_notifications#create-notification-recipient 8 | .Parameter bcAuthContext 9 | Authorization Context created by New-BcAuthContext. 10 | .Parameter apiVersion 11 | API version. Default is v2.15. 12 | .Example 13 | $bcauthContext = New-BcAuthContext -includeDeviceLogin 14 | New-BcNotificationRecipient -bcAuthContext $bcAuthContext -NotificationRecipientMail $Email -NotificationRecipientName $Name 15 | #> 16 | 17 | function New-BcNotificationRecipient { 18 | Param( 19 | [Parameter(Mandatory = $true)] 20 | [Hashtable] 21 | $bcAuthContext, 22 | [string] 23 | $apiVersion = "v2.6", 24 | [string] 25 | $applicationFamily = "BusinessCentral", 26 | [Parameter(Mandatory = $true)] 27 | [String] 28 | $NotificationRecipientMail, 29 | [Parameter(Mandatory = $true)] 30 | [String] 31 | $NotificationRecipientName 32 | ) 33 | 34 | $body = @{ "Name" = $NotificationRecipientName } 35 | $body += @{ "Email" = $NotificationRecipientMail } 36 | 37 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 38 | try { 39 | $bcAuthContext, $headers, $endPointURL = Create-SaasUrl -bcAuthContext $bcAuthContext -applicationFamily $applicationFamily -apiVersion $apiVersion 40 | try { 41 | Invoke-RestMethod -Method Put -UseBasicParsing -Uri "$($bcContainerHelperConfig.apiBaseUrl.TrimEnd('/'))/admin/$apiVersion/settings/notification/recipients" -Headers $headers -ContentType "application/json" -Body ($body | ConvertTo-Json) 42 | } 43 | catch { 44 | throw (GetExtendedErrorMessage $_) 45 | } 46 | } 47 | catch { 48 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 49 | throw 50 | } 51 | finally { 52 | TrackTrace -telemetryScope $telemetryScope 53 | } 54 | } 55 | Export-ModuleMember -Function New-BcNotificationRecipient -------------------------------------------------------------------------------- /TenantHandling/Get-NavContainerTenants.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Retrieve Tenants in a multitenant NAV/BC Container 4 | .Description 5 | Get information about tenants in the Container 6 | .Parameter containerName 7 | Name of the container from which you want to get the tenant information 8 | .Parameter Tenant 9 | Specifies the ID of the specific tenant that you want to get information about, such as Tenant1. Shows all if not specified. 10 | .Parameter forceRefresh 11 | Specifies to update a tenant's state and data version based, in part, on the data version of the tenant database that contains the tenant. 12 | .Parameter force 13 | Forces the command to run without asking for user confirmation. 14 | .Example 15 | Get-BcContainerTenants -containerName test 16 | #> 17 | function Get-BcContainerTenants { 18 | [CmdletBinding(DefaultParameterSetName = 'UseContainerName')] 19 | Param ( 20 | [ValidateNotNullorEmpty()] 21 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 22 | 23 | [Parameter(Mandatory = $true, ParameterSetName = 'ForceRefreshTenantState')] 24 | [switch] $ForceRefresh, 25 | 26 | [string] $Tenant = "", 27 | 28 | [switch] $Force 29 | ) 30 | 31 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 32 | try { 33 | 34 | $Params = @{ "Force" = $Force } 35 | If ($ForceRefresh) { 36 | $Params += @{ "ForceRefresh" = $ForceRefresh } 37 | if (-not $tenant) { 38 | $tenant = "Default" 39 | } 40 | } 41 | if ($Tenant) { 42 | $Params += @{ "Tenant" = $Tenant } 43 | } 44 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { 45 | Param( [PsCustomObject] $Params) 46 | Get-NavTenant -ServerInstance $ServerInstance @Params 47 | } -argumentList $Params 48 | } 49 | catch { 50 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 51 | throw 52 | } 53 | finally { 54 | TrackTrace -telemetryScope $telemetryScope 55 | } 56 | } 57 | Set-Alias -Name Get-NavContainerTenants -Value Get-BcContainerTenants 58 | Export-ModuleMember -Function Get-BcContainerTenants -Alias Get-NavContainerTenants 59 | -------------------------------------------------------------------------------- /Tests/Api.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | 12 | } 13 | 14 | Describe 'Api' { 15 | It 'Get-NavContainerApiCompanyId' { 16 | #TODO 17 | } 18 | It 'Invoke-NavContainerApi' { 19 | #TODO 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Tests/AzureAD.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | } 12 | 13 | Describe 'AzureAD' { 14 | 15 | It 'Create-AadAppsForNav' { 16 | #TODO 17 | } 18 | It 'Create-AadUsersInNavContainer' { 19 | #TODO 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Tests/AzureVM.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | } 12 | 13 | Describe 'AzureVM' { 14 | 15 | It 'New-LetsEncryptCertificate' { 16 | #TODO 17 | } 18 | It 'Renew-LetsEncryptCertificate' { 19 | #TODO 20 | } 21 | It 'Replace-NavServerContainer' { 22 | #TODO 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Tests/Bacpac (MT).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | . (Join-Path $PSScriptRoot '_CreateBcContainer.ps1') -sandbox 9 | } 10 | 11 | AfterAll { 12 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 13 | } 14 | 15 | Describe 'Bacpac' { 16 | 17 | It 'Export-NavContainerDatabasesAsBacpac (multitenant)' { 18 | 19 | $bacpacFolder = Join-Path $bcContainerHelperConfig.hostHelperFolder "bacpac" 20 | $appBacpacFile = "$bacpacFolder\app.bacpac" 21 | $tenant = "default" 22 | $tenantBacpacFile = "$bacpacFolder\$tenant.bacpac" 23 | Export-NavContainerDatabasesAsBacpac -containerName $bcContainerName -sqlCredential $credential -bacpacFolder $bacpacFolder -tenant $tenant -doNotCheckEntitlements 24 | 25 | $appBacpacFile | Should -Exist 26 | $tenantBacpacFile | Should -Exist 27 | 28 | $containerAppBacpacFile = Join-Path $bcContainerHelperConfig.containerHelperFolder "bacpac\app.bacpac" 29 | $containerTenantBacpacFile = Join-Path $bcContainerHelperConfig.containerHelperFolder "bacpac\default.bacpac" 30 | 31 | New-NavContainer -accept_eula ` 32 | -accept_outdated ` 33 | -imageName $bcImageName ` 34 | -containerName $bcContainerName ` 35 | -auth "NavUserPassword" ` 36 | -Credential $Credential ` 37 | -updateHosts ` 38 | -additionalParameters @("--env appBacpac=$containerAppBacpacFile","--env tenantBacpac=$containerTenantBacpacFile") 39 | 40 | New-NavContainerTenant -containerName $bcContainerName -tenantId "test" 41 | 42 | (Get-NavContainerTenants -containerName $bcContainerName).Count | Should -be 2 43 | 44 | Remove-Item -Path $bacpacFolder -Recurse -Force 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/Bacpac (NAV).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | . (Join-Path $PSScriptRoot '_CreateNavContainer.ps1') 9 | } 10 | 11 | AfterAll { 12 | . (Join-Path $PSScriptRoot '_RemoveNavContainer.ps1') 13 | } 14 | 15 | Describe 'Bacpac' { 16 | 17 | It 'Backup-NavContainerDatabases' { 18 | 19 | $bakFolder = Join-Path $bcContainerHelperConfig.hostHelperFolder ([GUID]::NewGuid().ToString()) 20 | $bakFile = "$bakFolder\database.bak" 21 | Backup-NavContainerDatabases -containerName $navContainerName ` 22 | -sqlCredential $credential ` 23 | -bakFolder $bakFolder 24 | 25 | $bakFile | Should -Exist 26 | 27 | New-NavContainer -accept_eula ` 28 | -accept_outdated ` 29 | -artifactUrl $navArtifactUrl ` 30 | -containerName $navContainerName ` 31 | -auth "NavUserPassword" ` 32 | -Credential $Credential ` 33 | -updateHosts ` 34 | -bakFile $bakFile 35 | 36 | . (Join-Path $PSScriptRoot '_RemoveNavContainer.ps1') 37 | 38 | Remove-Item -Path $bakFolder -Recurse -Force 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Tests/Bacpac.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | . (Join-Path $PSScriptRoot '_CreateBcContainer.ps1') 9 | } 10 | 11 | AfterAll { 12 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 13 | } 14 | 15 | Describe 'Bacpac' { 16 | 17 | It 'Backup-BcContainerDatabases' { 18 | 19 | $bakFolder = Join-Path $bcContainerHelperConfig.hostHelperFolder ([GUID]::NewGuid().ToString()) 20 | $bakFile = "$bakFolder\database.bak" 21 | Backup-NavContainerDatabases -containerName $bcContainerName ` 22 | -sqlCredential $credential ` 23 | -bakFolder $bakFolder 24 | 25 | $bakFile | Should -Exist 26 | 27 | New-NavContainer -accept_eula ` 28 | -accept_outdated ` 29 | -artifactUrl $bcArtifactUrl ` 30 | -containerName $bcContainerName ` 31 | -auth "NavUserPassword" ` 32 | -Credential $credential ` 33 | -updateHosts ` 34 | -bakFile $bakFile 35 | 36 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 37 | 38 | Remove-Item -Path $bakFolder -Recurse -Force 39 | 40 | . (Join-Path $PSScriptRoot '_CreateBcContainer.ps1') 41 | } 42 | It 'Export-NavContainerDatabasesAsBacpac' { 43 | 44 | $bacpacFolder = Join-Path $bcContainerHelperConfig.hostHelperFolder "bacpac" 45 | $bacpacFile = "$bacpacFolder\database.bacpac" 46 | Export-NavContainerDatabasesAsBacpac -containerName $bcContainerName -sqlCredential $credential -bacpacFolder $bacpacFolder -doNotCheckEntitlements 47 | 48 | $bacpacFile | Should -Exist 49 | 50 | Remove-Item -Path $bacpacFolder -Recurse -Force 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tests/CompanyHandling.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | } 12 | 13 | Describe 'CompanyHandling' { 14 | 15 | It 'Copy-CompanyInNavContainer' { 16 | #TODO 17 | } 18 | It 'Get-CompanyInNavContainer' { 19 | #TODO 20 | } 21 | It 'New-CompanyInNavContainer' { 22 | #TODO 23 | } 24 | It 'Remove-CompanyInNavContainer' { 25 | #TODO 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Tests/ConfigPackageHandling.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | } 12 | 13 | Describe 'ConfigPackageHandling' { 14 | 15 | It 'Import-ConfigPackageInNavContainer' { 16 | #TODO 17 | } 18 | It 'Remove-ConfigPackageInNavContainer' { 19 | #TODO 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Tests/ContainerHandling.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | . (Join-Path $PSScriptRoot '_CreateBcContainer.ps1') 9 | } 10 | 11 | AfterAll { 12 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 13 | } 14 | 15 | Describe 'ContainerHandling' { 16 | 17 | It 'Enter-BcContainer' { 18 | #TODO 19 | } 20 | It 'Extract-FilesFromBcContainerImage' { 21 | #TODO 22 | } 23 | It 'Extract-FilesFromStoppedBcContainer' { 24 | #TODO 25 | } 26 | It 'Get-BestBcContainerImageName' { 27 | #TODO 28 | } 29 | It 'Get-BcContainerSession' { 30 | #TODO 31 | } 32 | It 'Import-BcContainerLicense' { 33 | #TODO 34 | } 35 | It 'Invoke-ScriptInBcContainer' { 36 | #TODO 37 | } 38 | It 'New-BcContainer' { 39 | #TODO 40 | } 41 | It 'Open-BcContainer' { 42 | #TODO 43 | } 44 | It 'Remove-BcContainer' { 45 | #TODO 46 | } 47 | It 'Remove-BcContainerSession' { 48 | #TODO 49 | } 50 | It 'Restart-BcContainer' { 51 | Restart-BcContainer -containerName $bcContainerName 52 | $json = docker inspect $bcContainerName | ConvertFrom-Json 53 | $json.State.Status | Should -Be 'running' 54 | } 55 | It 'Setup-TraefikContainerForBcContainers' { 56 | #TODO 57 | } 58 | It 'Stop/Start-BcContainer' { 59 | Stop-BcContainer -containerName $bcContainerName 60 | $json = docker inspect $bcContainerName | ConvertFrom-Json 61 | $json.State.Status | Should -Be 'exited' 62 | Start-BcContainer -containerName $bcContainerName 63 | $json = docker inspect $bcContainerName | ConvertFrom-Json 64 | $json.State.Status | Should -Be 'running' 65 | } 66 | It 'Wait-BcContainerReady' { 67 | #TODO 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /Tests/GetAndRunTests (Windows Auth).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 21 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth 'Windows' ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $buildLicenseFile ` 32 | -includeTestToolkit ` 33 | -multitenant:$false ` 34 | -runSandboxAsOnPrem ` 35 | -myscripts @( @{ "SetupNavUsers.ps1" = "Write-Host 'Skipping user creation'" } ) 36 | 37 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 38 | $tests.Count | Should -be 2 39 | 40 | $first = $true 41 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 42 | $tests | ForEach-Object { 43 | Run-TestsInBcContainer -containerName $bcContainerName ` 44 | -credential $credential ` 45 | -XUnitResultFileName $resultsFile ` 46 | -AppendToXUnitResultFile:(!$first) ` 47 | -detailed ` 48 | -testCodeunit $_.Id ` 49 | -returnTrueIfAllPassed | Out-Null 50 | $first = $false 51 | } 52 | $resultsFile | Should -Exist 53 | } 54 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (latest).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 24 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type Sandbox -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -includeTestToolkit 32 | 33 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 34 | $tests.Count | Should -be 2 35 | 36 | $first = $true 37 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 38 | $tests | ForEach-Object { 39 | Run-TestsInBcContainer -containerName $bcContainerName ` 40 | -credential $credential ` 41 | -XUnitResultFileName $resultsFile ` 42 | -AppendToXUnitResultFile:(!$first) ` 43 | -detailed ` 44 | -testCodeunit $_.Id ` 45 | -returnTrueIfAllPassed | Out-Null 46 | $first = $false 47 | } 48 | $resultsFile | Should -Exist 49 | } 50 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 15).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 15 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $licenseFile ` 32 | -includeTestToolkit 33 | 34 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 35 | $tests.Count | Should -be 2 36 | 37 | $first = $true 38 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 39 | $tests | ForEach-Object { 40 | Run-TestsInBcContainer -containerName $bcContainerName ` 41 | -credential $credential ` 42 | -XUnitResultFileName $resultsFile ` 43 | -AppendToXUnitResultFile:(!$first) ` 44 | -detailed ` 45 | -testCodeunit $_.Id ` 46 | -returnTrueIfAllPassed | Out-Null 47 | $first = $false 48 | } 49 | $resultsFile | Should -Exist 50 | } 51 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 16).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 16 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $licenseFile ` 32 | -includeTestToolkit 33 | 34 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 35 | $tests.Count | Should -be 2 36 | 37 | $first = $true 38 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 39 | $tests | ForEach-Object { 40 | Run-TestsInBcContainer -containerName $bcContainerName ` 41 | -credential $credential ` 42 | -XUnitResultFileName $resultsFile ` 43 | -AppendToXUnitResultFile:(!$first) ` 44 | -detailed ` 45 | -testCodeunit $_.Id ` 46 | -returnTrueIfAllPassed | Out-Null 47 | $first = $false 48 | } 49 | $resultsFile | Should -Exist 50 | } 51 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 17).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 17 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $licenseFile ` 32 | -includeTestToolkit 33 | 34 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 35 | $tests.Count | Should -be 2 36 | 37 | $first = $true 38 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 39 | $tests | ForEach-Object { 40 | Run-TestsInBcContainer -containerName $bcContainerName ` 41 | -credential $credential ` 42 | -XUnitResultFileName $resultsFile ` 43 | -AppendToXUnitResultFile:(!$first) ` 44 | -detailed ` 45 | -testCodeunit $_.Id ` 46 | -returnTrueIfAllPassed | Out-Null 47 | $first = $false 48 | } 49 | $resultsFile | Should -Exist 50 | } 51 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 18).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 18 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $buildLicenseFile ` 32 | -includeTestToolkit 33 | 34 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 35 | $tests.Count | Should -be 2 36 | 37 | $first = $true 38 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 39 | $tests | ForEach-Object { 40 | Run-TestsInBcContainer -containerName $bcContainerName ` 41 | -credential $credential ` 42 | -XUnitResultFileName $resultsFile ` 43 | -AppendToXUnitResultFile:(!$first) ` 44 | -detailed ` 45 | -testCodeunit $_.Id ` 46 | -returnTrueIfAllPassed | Out-Null 47 | $first = $false 48 | } 49 | $resultsFile | Should -Exist 50 | } 51 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 19).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 19 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $buildLicenseFile ` 32 | -includeTestToolkit 33 | 34 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 35 | $tests.Count | Should -be 2 36 | 37 | $first = $true 38 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 39 | $tests | ForEach-Object { 40 | Run-TestsInBcContainer -containerName $bcContainerName ` 41 | -credential $credential ` 42 | -XUnitResultFileName $resultsFile ` 43 | -AppendToXUnitResultFile:(!$first) ` 44 | -detailed ` 45 | -testCodeunit $_.Id ` 46 | -returnTrueIfAllPassed | Out-Null 47 | $first = $false 48 | } 49 | $resultsFile | Should -Exist 50 | } 51 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 20).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 20 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $buildLicenseFile ` 32 | -includeTestToolkit 33 | 34 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 35 | $tests.Count | Should -be 2 36 | 37 | $first = $true 38 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 39 | $tests | ForEach-Object { 40 | Run-TestsInBcContainer -containerName $bcContainerName ` 41 | -credential $credential ` 42 | -XUnitResultFileName $resultsFile ` 43 | -AppendToXUnitResultFile:(!$first) ` 44 | -detailed ` 45 | -testCodeunit $_.Id ` 46 | -returnTrueIfAllPassed | Out-Null 47 | $first = $false 48 | } 49 | $resultsFile | Should -Exist 50 | } 51 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 21).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 21 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -licenseFile $buildLicenseFile ` 32 | -includeTestToolkit 33 | 34 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 35 | $tests.Count | Should -be 2 36 | 37 | $first = $true 38 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 39 | $tests | ForEach-Object { 40 | Run-TestsInBcContainer -containerName $bcContainerName ` 41 | -credential $credential ` 42 | -XUnitResultFileName $resultsFile ` 43 | -AppendToXUnitResultFile:(!$first) ` 44 | -detailed ` 45 | -testCodeunit $_.Id ` 46 | -returnTrueIfAllPassed | Out-Null 47 | $first = $false 48 | } 49 | $resultsFile | Should -Exist 50 | } 51 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 22).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 22 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -includeTestToolkit 32 | 33 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 34 | $tests.Count | Should -be 2 35 | 36 | $first = $true 37 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 38 | $tests | ForEach-Object { 39 | Run-TestsInBcContainer -containerName $bcContainerName ` 40 | -credential $credential ` 41 | -XUnitResultFileName $resultsFile ` 42 | -AppendToXUnitResultFile:(!$first) ` 43 | -detailed ` 44 | -testCodeunit $_.Id ` 45 | -returnTrueIfAllPassed | Out-Null 46 | $first = $false 47 | } 48 | $resultsFile | Should -Exist 49 | } 50 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 23).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 23 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -includeTestToolkit 32 | 33 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 34 | $tests.Count | Should -be 2 35 | 36 | $first = $true 37 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 38 | $tests | ForEach-Object { 39 | Run-TestsInBcContainer -containerName $bcContainerName ` 40 | -credential $credential ` 41 | -XUnitResultFileName $resultsFile ` 42 | -AppendToXUnitResultFile:(!$first) ` 43 | -detailed ` 44 | -testCodeunit $_.Id ` 45 | -returnTrueIfAllPassed | Out-Null 46 | $first = $false 47 | } 48 | $resultsFile | Should -Exist 49 | } 50 | } -------------------------------------------------------------------------------- /Tests/GetAndRunTests (version 24).Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $appPublisher = "Cronus Denmark A/S" 9 | $appName = "Hello ÆØÅ" 10 | $appVersion = "1.0.0.0" 11 | $bcAppId = "cb99d78b-f9db-4a1e-822a-0c9c444535df" 12 | $runTestsInVersion = 24 13 | $bcContainerName = "bcserver" 14 | } 15 | 16 | AfterAll { 17 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 18 | } 19 | 20 | Describe 'AppHandling' { 21 | 22 | It 'Get/RunTests' { 23 | $artifactUrl = Get-BCArtifactUrl -type OnPrem -version "$runTestsInVersion" -country "w1" -select Latest 24 | New-BcContainer -accept_eula ` 25 | -accept_outdated ` 26 | -containerName $bcContainerName ` 27 | -artifactUrl $artifactUrl ` 28 | -auth NavUserPassword ` 29 | -Credential $credential ` 30 | -updateHosts ` 31 | -includeTestToolkit 32 | 33 | $tests = (Get-TestsFromBCContainer -containerName $bcContainerName -credential $credential -extensionId "fa3e2564-a39e-417f-9be6-c0dbe3d94069") | Where-Object { $_.id -eq 134006 -or $_.id -eq 134007 } 34 | $tests.Count | Should -be 2 35 | 36 | $first = $true 37 | $resultsFile = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName\result.xml" 38 | $tests | ForEach-Object { 39 | Run-TestsInBcContainer -containerName $bcContainerName ` 40 | -credential $credential ` 41 | -XUnitResultFileName $resultsFile ` 42 | -AppendToXUnitResultFile:(!$first) ` 43 | -detailed ` 44 | -testCodeunit $_.Id ` 45 | -returnTrueIfAllPassed | Out-Null 46 | $first = $false 47 | } 48 | $resultsFile | Should -Exist 49 | } 50 | } -------------------------------------------------------------------------------- /Tests/ObjectHandling-Objects.txt: -------------------------------------------------------------------------------- 1 | OBJECT Codeunit 50101 Test 2 | { 3 | OBJECT-PROPERTIES 4 | { 5 | Modified=Yes; 6 | } 7 | PROPERTIES 8 | { 9 | TableNo=18; 10 | OnRun=BEGIN 11 | MESSAGE(Rec.Name); 12 | END; 13 | 14 | } 15 | CODE 16 | { 17 | 18 | BEGIN 19 | END. 20 | } 21 | } 22 | 23 | OBJECT Page 50101 Test 24 | { 25 | OBJECT-PROPERTIES 26 | { 27 | Modified=Yes; 28 | } 29 | PROPERTIES 30 | { 31 | SourceTable=Table18; 32 | PageType=Card; 33 | } 34 | CONTROLS 35 | { 36 | { 1 ;0 ;Container ; 37 | ContainerType=ContentArea } 38 | 39 | { 2 ;1 ;Group ; 40 | Name=General; 41 | GroupType=Group } 42 | 43 | { 3 ;2 ;Field ; 44 | SourceExpr="No." } 45 | 46 | { 4 ;2 ;Field ; 47 | SourceExpr=Name } 48 | 49 | } 50 | CODE 51 | { 52 | 53 | BEGIN 54 | END. 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /Tests/PackageHandling.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | } 12 | 13 | Describe 'PackageHandling' { 14 | It 'Get-AzureFeedWildcardVersion' { 15 | (Get-AzureFeedWildcardVersion -appVersion "1.0.0") | Should -be "1.*.*" 16 | (Get-AzureFeedWildcardVersion -appVersion "1.0.0") | Should -not -be "1.0.*" 17 | (Get-AzureFeedWildcardVersion -appVersion "1.0.319") | Should -be "1.0.319" 18 | (Get-AzureFeedWildcardVersion -appVersion "1.0.319") | Should -not -be "1.*.319" 19 | } 20 | It 'Resolve-DependenciesFromAzureFeed' { 21 | Resolve-DependenciesFromAzureFeed -organization "https://dev.azure.com/TEST/" -feed "BCApps" -appsFolder (Join-Path $PSScriptRoot ".\helloworld") 22 | } 23 | } -------------------------------------------------------------------------------- /Tests/Run-AlPipeline.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | $bccontainerName = "bcserver" 9 | } 10 | 11 | AfterAll { 12 | } 13 | 14 | Describe 'Run-AlPipeline' { 15 | It 'Run-AlPipeline' { 16 | $baseFolder = Join-Path $PSScriptRoot "helloworld" 17 | $resultsFile = Join-Path $baseFolder "result.xml" 18 | $buildArtifactFolder = Join-Path $baseFolder "buildArtifactFolder" 19 | $outputFolder = Join-Path $baseFolder "output" 20 | Remove-Item $resultsFile -Force -ErrorAction SilentlyContinue 21 | Remove-Item $buildArtifactFolder -Recurse -Force -ErrorAction SilentlyContinue 22 | Remove-Item $outputFolder -Recurse -Force -ErrorAction SilentlyContinue 23 | 24 | Run-AlPipeline ` 25 | -pipelineName nch ` 26 | -baseFolder $baseFolder ` 27 | -containerName $bccontainerName ` 28 | -credential $credential ` 29 | -installApps @("https://github.com/microsoft/bcsamples-bingmaps.pte/releases/download/24.0.0/bcsamples-bingmaps.pte-main-Apps-24.0.169.0.zip") ` 30 | -appFolders "app,base" ` 31 | -testFolders @("test") ` 32 | -previousApps @((Join-Path $PSScriptRoot 'helloworld-previousapps.zip')) ` 33 | -additionalCountries "dk,de" ` 34 | -appBuild ([int32]::MaxValue) ` 35 | -appRevision 0 ` 36 | -testResultsFile $resultsFile ` 37 | -testResultsFormat JUnit ` 38 | -artifact "///us/Current" ` 39 | -imageName '' ` 40 | -outputFolder $outputFolder ` 41 | -buildArtifactFolder $buildArtifactFolder ` 42 | -createRuntimePackages ` 43 | -installTestFramework ` 44 | -gitHubActions ` 45 | -enablePerTenantExtensionCop 46 | 47 | Remove-Item $resultsFile -Force -ErrorAction SilentlyContinue 48 | Remove-Item $buildArtifactFolder -Recurse -Force -ErrorAction SilentlyContinue 49 | Remove-Item $outputFolder -Recurse -Force -ErrorAction SilentlyContinue 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Tests/SymbolHandling.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | } 9 | 10 | AfterAll { 11 | } 12 | 13 | Describe 'SymbolHandling' { 14 | 15 | It 'Generate-SymbolsInNavContainer' { 16 | #TODO 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Tests/TenantHandling.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | . (Join-Path $PSScriptRoot '_CreateBcContainer.ps1') -sandbox 9 | } 10 | 11 | AfterAll { 12 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 13 | } 14 | 15 | Describe 'TenantHandling' { 16 | 17 | It 'Get-BcContainerTenants' { 18 | Get-BcContainerTenants -containerName $bcContainerName | Should -Not -BeNullOrEmpty 19 | (@(Get-BcContainerTenants -containerName $bcContainerName)).Count | should -Be 1 20 | } 21 | It 'New-BcContainerTenant' { 22 | New-BcContainerTenant -containerName $bcContainerName -tenantId "extra" -alternateId "mytenant" 23 | (@(Get-BcContainerTenants -containerName $bcContainerName)).Count | should -Be 2 24 | $hosts = [string]::Join(' ',(Get-Content -Path "c:\windows\system32\drivers\etc\hosts")) 25 | $hosts | Should -BeLike "*$bcContainerName-extra*" 26 | $hosts | Should -Not -BeLike "*$bcContainerName-mytenant*" 27 | } 28 | It 'Remove-BcContainerTenant' { 29 | Remove-BcContainerTenant -containerName $bcContainerName -tenantId "extra" 30 | (@(Get-BcContainerTenants -containerName $bcContainerName)).Count | should -Be 1 31 | $hosts = [string]::Join(' ',(Get-Content -Path "c:\windows\system32\drivers\etc\hosts")) 32 | $hosts | Should -Not -BeLike "*$bcContainerName-extra*" 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Tests/UserHandling.Tests.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile, 3 | [string] $buildlicenseFile 4 | ) 5 | 6 | BeforeAll { 7 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 8 | . (Join-Path $PSScriptRoot '_CreateBcContainer.ps1') 9 | $extraUser = New-Object pscredential -ArgumentList 'extrauser', $credential.Password 10 | } 11 | 12 | AfterAll { 13 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 14 | } 15 | 16 | Describe 'UserHandling' { 17 | 18 | It 'Get-BcContainerBcUser' { 19 | Get-BcContainerBcUser -containerName $bcContainerName | Where-Object { $_.UserName -eq $credential.Username } | Should -Not -BeNullOrEmpty 20 | } 21 | It 'New-BcContainerBcUser' { 22 | New-BcContainerBcUser -containerName $bcContainerName -Credential $extraUser -tenant default -PermissionSetId SUPER 23 | } 24 | It 'New-BcContainerWindowsUser' { 25 | New-BcContainerWindowsUser -containerName $bcContainerName -Credential $extraUser -group 'Administrators' 26 | } 27 | It 'Setup-BcContainerTestUsers' { 28 | Setup-BcContainerTestUsers -containerName $bcContainerName -tenant default -Password $credential.Password -credential $credential 29 | Get-BcContainerBcUser -containerName $bcContainerName | Where-Object { $_.UserName -eq 'ESSENTIAL' } | Should -Not -BeNullOrEmpty 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Tests/_CreateBcContainer.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [switch] $sandbox 3 | ) 4 | 5 | $bcContainerName = 'bcs' 6 | $bcContainerPath = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$bcContainerName" 7 | $bcMyPath = Join-Path $bcContainerPath "my" 8 | 9 | if ($sandbox) { 10 | $bcArtifactUrl = Get-BCArtifactUrl -type "Sandbox" -version "17.1.18256.30573" -country "us" -select 'Closest' 11 | $bcImageName = New-BcImage -artifactUrl $bcArtifactUrl -skipIfImageAlreadyExists 12 | $bcContainerPlatformVersion = "17.0.18204.30560" 13 | New-BCContainer -accept_eula ` 14 | -accept_outdated ` 15 | -containerName $bcContainerName ` 16 | -artifactUrl $bcArtifactUrl ` 17 | -imageName $bcImageName ` 18 | -auth UserPassword ` 19 | -Credential $credential ` 20 | -updateHosts ` 21 | -memoryLimit 8g ` 22 | -licenseFile $buildLicenseFile ` 23 | -includeTestToolkit ` 24 | -includeTestLibrariesOnly 25 | } 26 | else { 27 | $bcArtifactUrl = Get-BCArtifactUrl -type OnPrem -version "17.0" -country w1 28 | $bcImageName = New-BcImage -artifactUrl $bcArtifactUrl -skipIfImageAlreadyExists 29 | $bcContainerPlatformVersion = '17.0.16974.0' 30 | New-BCContainer -accept_eula ` 31 | -accept_outdated ` 32 | -containerName $bcContainerName ` 33 | -artifactUrl $bcArtifactUrl ` 34 | -imageName $bcImageName ` 35 | -auth UserPassword ` 36 | -Credential $credential ` 37 | -updateHosts ` 38 | -memoryLimit 16g ` 39 | -licenseFile $buildLicenseFile ` 40 | -includeAL ` 41 | -includeTestToolkit ` 42 | -includeTestLibrariesOnly 43 | } 44 | -------------------------------------------------------------------------------- /Tests/_CreateNavContainer.ps1: -------------------------------------------------------------------------------- 1 | $navArtifactUrl = Get-NavArtifactUrl -nav 2018 -cu 17 -country w1 2 | $navImageName = New-BcImage -artifactUrl $navArtifactUrl -skipIfImageAlreadyExists 3 | $navContainerName = 'nav' 4 | $navContainerPlatformVersion = '11.0.31747.0' 5 | $navContainerPath = Join-Path $bcContainerHelperConfig.hostHelperFolder "Extensions\$navContainerName" 6 | $navMyPath = Join-Path $navContainerPath "my" 7 | New-NavContainer -accept_eula ` 8 | -accept_outdated ` 9 | -containerName $navContainerName ` 10 | -artifactUrl $navArtifactUrl ` 11 | -imagename $navImageName ` 12 | -auth UserPassword ` 13 | -Credential $credential ` 14 | -updateHosts ` 15 | -memoryLimit 8g ` 16 | -licenseFile $licenseFile ` 17 | -includeCSide ` 18 | -includeTestToolkit ` 19 | -includeTestLibrariesOnly -------------------------------------------------------------------------------- /Tests/_DoRunOne.ps1: -------------------------------------------------------------------------------- 1 | Invoke-Pester -Script @{ "Path" = Join-Path $PSScriptRoot "_TestRunOne.ps1"; "Parameters" = @{ "licenseFile" = 'c:\temp\nchlicense.flf' } } 2 | -------------------------------------------------------------------------------- /Tests/_RemoveBcContainer.ps1: -------------------------------------------------------------------------------- 1 | Remove-BCContainer -containerName $bcContainerName 2 | -------------------------------------------------------------------------------- /Tests/_RemoveNavContainer.ps1: -------------------------------------------------------------------------------- 1 | Remove-NavContainer -containerName $navContainerName 2 | -------------------------------------------------------------------------------- /Tests/_TestHelperFunctions.ps1: -------------------------------------------------------------------------------- 1 | $modulePath = Join-Path $PSScriptRoot "..\BcContainerHelper.psd1" 2 | Remove-Module BcContainerHelper -ErrorAction Ignore 3 | Import-Module $modulePath -DisableNameChecking 4 | 5 | $modulePath = Join-Path $PSScriptRoot "..\BcContainerHelper.psm1" 6 | Remove-Module BcContainerHelper -ErrorAction Ignore 7 | Import-Module $modulePath -DisableNameChecking 8 | 9 | $bcContainerHelperConfig.killPsSessionProcess = $true 10 | 11 | function randomchar([string]$str) 12 | { 13 | $rnd = Get-Random -Maximum $str.length 14 | [string]$str[$rnd] 15 | } 16 | 17 | function Get-RandomPassword { 18 | $cons = 'bcdfghjklmnpqrstvwxz' 19 | $voc = 'aeiouy' 20 | $numbers = '0123456789' 21 | $special = '!*.:-$#@%' 22 | 23 | $password = (randomchar $cons).ToUpper() + ` 24 | (randomchar $voc) + ` 25 | (randomchar $cons) + ` 26 | (randomchar $voc) + ` 27 | (randomchar $special) + ` 28 | (randomchar $numbers) + ` 29 | (randomchar $numbers) + ` 30 | (randomchar $numbers) + ` 31 | (randomchar $numbers) + ` 32 | (randomchar $special) 33 | $password 34 | } 35 | 36 | function Get-RandomPasswordAsSecureString { 37 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", Justification="Get Random password as secure string.")] 38 | Param() 39 | 40 | ConvertTo-SecureString -String (Get-RandomPassword) -AsPlainText -Force 41 | } 42 | 43 | $credential = [PSCredential]::new("admin", (Get-RandomPasswordAsSecureString)) 44 | -------------------------------------------------------------------------------- /Tests/_TestRunOne.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile = ($nchLicensefileSecret.secretValue | Get-PlainText), 3 | [string] $buildlicenseFile = ($LicensefileSecret.secretValue | Get-PlainText), 4 | [string] $testScript = "AppHandling.Tests.ps1" 5 | ) 6 | 7 | try { 8 | Write-Host $buildlicenseFile 9 | 10 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 11 | 12 | $modulePath = Join-Path $PSScriptRoot "..\BcContainerHelper.psm1" 13 | Remove-Module BcContainerHelper -ErrorAction Ignore 14 | Import-Module $modulePath -DisableNameChecking 15 | 16 | . (Join-Path $PSScriptRoot $testScript) -licenseFile $licenseFile -buildlicenseFile $buildlicenseFile 17 | } 18 | catch { 19 | Write-Host "::Error::$($_.Exception.Message)" 20 | } 21 | -------------------------------------------------------------------------------- /Tests/_TestRunner.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $licenseFile = "c:\temp\nchlicense.flf", 3 | [string] $buildlicenseFile = "c:\temp\build.flf" 4 | ) 5 | 6 | . (Join-Path $PSScriptRoot '_TestHelperFunctions.ps1') 7 | 8 | $modulePath = Join-Path $PSScriptRoot "..\BcContainerHelper.psm1" 9 | Remove-Module BcContainerHelper -ErrorAction Ignore 10 | Import-Module $modulePath -DisableNameChecking 11 | 12 | $credential = [PSCredential]::new("admin", (Get-RandomPasswordAsSecureString)) 13 | 14 | Get-BcContainers | Remove-BCContainer 15 | #Flush-ContainerHelperCache 16 | 17 | . (Join-Path $PSScriptRoot '_CreateNavContainer.ps1') 18 | . (Join-Path $PSScriptRoot '_CreateBcContainer.ps1') 19 | 20 | try { 21 | Get-ChildItem -Path (Join-Path $PSScriptRoot '*.ps1') -Exclude @("_*.ps1") | % { 22 | . $_.FullName 23 | } 24 | } 25 | finally { 26 | . (Join-Path $PSScriptRoot '_RemoveBcContainer.ps1') 27 | . (Join-Path $PSScriptRoot '_RemoveNavContainer.ps1') 28 | } 29 | -------------------------------------------------------------------------------- /Tests/bc-app/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Your own server", 6 | "type": "al", 7 | "request": "launch", 8 | "server": "http://helloworld-ci", 9 | "serverInstance": "BC", 10 | "tenant": "default", 11 | "authentication": "UserPassword", 12 | "startupObjectId": 22, 13 | "breakOnError": true, 14 | "breakOnRecordWrite": false, 15 | "launchBrowser": true 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /Tests/bc-app/CustomerCardExtension.al: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information. 4 | // ------------------------------------------------------------------------------------------------ 5 | 6 | pageextension 50112 CustomerCardExtension extends "Customer Card" 7 | { 8 | 9 | layout 10 | { 11 | // Add changes to page layout here 12 | } 13 | 14 | actions 15 | { 16 | addlast("&Customer") 17 | { 18 | action("Show Greeting") 19 | { 20 | RunObject = codeunit HelloWorld; 21 | RunPageOnRec = True; 22 | Image = CheckDuplicates; 23 | PromotedCategory = Category8; 24 | Promoted = true; 25 | ApplicationArea = All; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tests/bc-app/HelloWorld.al: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information. 4 | // ------------------------------------------------------------------------------------------------ 5 | 6 | codeunit 50111 HelloWorld 7 | { 8 | TableNo = Customer; 9 | 10 | trigger OnRun(); 11 | var 12 | HelloText : Codeunit GreetingsManagement; 13 | begin 14 | Message('%1, %2', HelloText.GetRandomGreeting(), Rec.Name); 15 | end; 16 | } -------------------------------------------------------------------------------- /Tests/bc-app/Install.al: -------------------------------------------------------------------------------- 1 | codeunit 50114 "HelloWorld Test Install" 2 | { 3 | Subtype = Install; 4 | 5 | trigger OnInstallAppPerCompany() 6 | var 7 | CALTestSuite: Record "CAL Test Suite"; 8 | CALTestLine: Record "CAL Test Line"; 9 | CALTestMgmt: Codeunit "CAL Test Management"; 10 | begin 11 | if CALTestSuite.Get('DEFAULT') then 12 | exit; 13 | 14 | with CALTestSuite do begin 15 | init; 16 | 17 | validate(Name, 'DEFAULT'); 18 | validate(Description, 'DEFAULT'); 19 | validate(Export, false); 20 | insert(true); 21 | end; 22 | 23 | with CALTestLine do begin 24 | init; 25 | validate("Test Suite", 'DEFAULT'); 26 | validate("Line No.", 1); 27 | validate("Line Type", "Line Type"::Codeunit); 28 | validate("Test Codeunit", Codeunit::"HelloWorld Tests"); 29 | validate(Run, true); 30 | 31 | insert(true); 32 | 33 | CALTestMgmt.SETPUBLISHMODE; 34 | SETRECFILTER; 35 | CODEUNIT.RUN(CODEUNIT::"CAL Test Runner", CALTestLine); 36 | end; 37 | end; 38 | } -------------------------------------------------------------------------------- /Tests/bc-app/Tests.al: -------------------------------------------------------------------------------- 1 | codeunit 50113 "HelloWorld Tests" 2 | { 3 | Subtype = Test; 4 | TestPermissions = Disabled; 5 | 6 | var 7 | Assert: Codeunit "Library Assert"; 8 | 9 | [Test] 10 | procedure WorkingTest(); 11 | begin 12 | Assert.AreEqual(2, 2, '2 should be 2'); 13 | end; 14 | } -------------------------------------------------------------------------------- /Tests/bc-app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "cb99d78b-f9db-4a1e-822a-0c9c444535df", 3 | "name": "Hello ÆØÅ", 4 | "publisher": "Cronus Denmark A/S", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | { 15 | "id": "dd0be2ea-f733-4d65-bb34-a28f4624fb14", 16 | "publisher": "Microsoft", 17 | "name": "Library Assert", 18 | "version": "17.0.0.0" 19 | }, 20 | { 21 | "id": "e7320ebb-08b3-4406-b1ec-b4927d3e280b", 22 | "publisher": "Microsoft", 23 | "name": "Any", 24 | "version": "17.0.0.0" 25 | }, 26 | { 27 | "id": "23de40a6-dfe8-4f80-80db-d70f83ce8caf", 28 | "publisher": "Microsoft", 29 | "name": "Test Runner", 30 | "version": "17.0.0.0" 31 | } 32 | ], 33 | "screenshots": [], 34 | "platform": "17.0.0.0", 35 | "application": "17.0.0.0", 36 | "idRanges": [ 37 | { 38 | "from": 50100, 39 | "to": 50149 40 | } 41 | ], 42 | "contextSensitiveHelpUrl": "https://ALProject21.com/help/", 43 | "showMyCode": true, 44 | "runtime": "6.0" 45 | } -------------------------------------------------------------------------------- /Tests/bc2-app/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "al", 6 | "request": "launch", 7 | "name": "Your own server", 8 | "server": "http://helloworld-ci", 9 | "serverInstance": "BC", 10 | "tenant": "default", 11 | "authentication": "UserPassword", 12 | "startupObjectId": 22, 13 | "startupObjectType": "Page", 14 | "breakOnError": true, 15 | "launchBrowser": true, 16 | "enableLongRunningSqlStatements": true, 17 | "enableSqlInformationDebugger": true 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /Tests/bc2-app/HelloWorld.al: -------------------------------------------------------------------------------- 1 | // Welcome to your new AL extension. 2 | // Remember that object names and IDs should be unique across all extensions. 3 | // AL snippets start with t*, like tpageext - give them a try and happy coding! 4 | 5 | pageextension 50113 CustomerListExt extends "Customer List" 6 | { 7 | trigger OnOpenPage(); 8 | var 9 | HelloText: Codeunit GreetingsManagement; 10 | begin 11 | Message('%1, %2', HelloText.GetRandomGreeting(), Rec.Name); 12 | end; 13 | } -------------------------------------------------------------------------------- /Tests/bc2-app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "25e71a28-8a6f-485f-b58a-39d9f3faf5dd", 3 | "name": "Test app", 4 | "publisher": "Cronus Denmark A/S", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | { 15 | "id": "cb99d78b-f9db-4a1e-822a-0c9c444535df", 16 | "name": "Hello ÆØÅ", 17 | "publisher": "Cronus Denmark A/S", 18 | "version": "1.0.0.0" 19 | } 20 | ], 21 | "screenshots": [], 22 | "platform": "17.0.0.0", 23 | "application": "17.0.0.0", 24 | "idRanges": [ 25 | { 26 | "from": 50100, 27 | "to": 50149 28 | } 29 | ], 30 | "contextSensitiveHelpUrl": "https://bc2-app.com/help/", 31 | "showMyCode": true, 32 | "runtime": "6.0" 33 | } -------------------------------------------------------------------------------- /Tests/helloworld-previousapps.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/navcontainerhelper/df270f9e3ed96260221f918f2deb0fd7af941f07/Tests/helloworld-previousapps.zip -------------------------------------------------------------------------------- /Tests/helloworld/app/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "al", 6 | "request": "launch", 7 | "name": "Local Sandbox", 8 | "server": "http://helloworld-current", 9 | "serverInstance": "BC", 10 | "port": 7049, 11 | "tenant": "default", 12 | "authentication": "UserPassword", 13 | "startupObjectId": 22, 14 | "startupObjectType": "Page", 15 | "breakOnError": true 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Tests/helloworld/app/HelloWorld.al: -------------------------------------------------------------------------------- 1 | // Welcome to your new AL extension. 2 | // Remember that object names and IDs should be unique across all extensions. 3 | // AL snippets start with t*, like tpageext - give them a try and happy coding! 4 | 5 | pageextension 50101 CustomerListExt extends "Customer List" 6 | { 7 | trigger OnOpenPage(); 8 | var 9 | hellobase: Codeunit "Hello Base"; 10 | begin 11 | Message(hellobase.GetText()); 12 | end; 13 | } -------------------------------------------------------------------------------- /Tests/helloworld/app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "00000000-0000-0000-0000-000000000001", 3 | "name": "Default App Name", 4 | "publisher": "Default Publisher", 5 | "brief": "", 6 | "description": "", 7 | "version": "2.0.2147483647.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | { 15 | "id": "00000000-0000-0000-0000-000000000003", 16 | "publisher": "Default Publisher", 17 | "name": "Default Base App Name", 18 | "version": "2.0.0.0" 19 | } 20 | ], 21 | "screenshots": [], 22 | "application": "17.0.0.0", 23 | "platform": "17.0.0.0", 24 | "idRanges": [ 25 | { 26 | "from": 50100, 27 | "to": 50149 28 | } 29 | ], 30 | "showMyCode": true, 31 | "runtime": "6.0" 32 | } 33 | -------------------------------------------------------------------------------- /Tests/helloworld/base/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "al", 6 | "request": "launch", 7 | "name": "Local Sandbox", 8 | "server": "http://nchbuild", 9 | "serverInstance": "BC", 10 | "port": 7049, 11 | "tenant": "default", 12 | "authentication": "UserPassword", 13 | "startupObjectId": 22, 14 | "startupObjectType": "Page", 15 | "breakOnError": true 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Tests/helloworld/base/Codeunit 50130 - Hello Base.al: -------------------------------------------------------------------------------- 1 | codeunit 50130 "Hello Base" 2 | { 3 | trigger OnRun() 4 | begin 5 | 6 | end; 7 | 8 | procedure GetText() returnvalue: Text; 9 | begin 10 | returnvalue := 'App Published: Hello World Base!'; 11 | end; 12 | } -------------------------------------------------------------------------------- /Tests/helloworld/base/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "00000000-0000-0000-0000-000000000003", 3 | "name": "Default Base App Name", 4 | "publisher": "Default Publisher", 5 | "brief": "", 6 | "description": "", 7 | "version": "2.0.2147483647.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | 15 | ], 16 | "screenshots": [ 17 | 18 | ], 19 | "application": "17.0.0.0", 20 | "platform": "17.0.0.0", 21 | "idRanges": [ 22 | { 23 | "from": 50100, 24 | "to": 50149 25 | } 26 | ], 27 | "showMyCode": true, 28 | "runtime": "6.0" 29 | } 30 | -------------------------------------------------------------------------------- /Tests/helloworld/test/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "al", 6 | "request": "launch", 7 | "name": "Local Sandbox", 8 | "server": "http://helloworld-current", 9 | "serverInstance": "BC", 10 | "port": 7049, 11 | "tenant": "default", 12 | "authentication": "UserPassword", 13 | "startupObjectId": 130451, 14 | "startupObjectType": "Page", 15 | "breakOnError": true 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Tests/helloworld/test/Codeunit 50133 - HelloWorld Test.al: -------------------------------------------------------------------------------- 1 | codeunit 50133 "HelloWorld Test" 2 | { 3 | Subtype = Test; 4 | 5 | // Test kindly donated by Gunnar Gestsson:-) 6 | 7 | [Test] 8 | [HandlerFunctions('HelloWorldMessageHandler')] 9 | procedure TestHelloWorldMessage() 10 | var 11 | CustList: TestPage "Customer List"; 12 | begin 13 | CustList.OpenView(); 14 | CustList.Close(); 15 | Assert.IsTrue(MessageDisplayed, 'Message was not displayed!'); 16 | end; 17 | 18 | [MessageHandler] 19 | procedure HelloWorldMessageHandler(Message: Text[1024]) 20 | begin 21 | MessageDisplayed := Message = 'App Published: Hello World Base!'; 22 | end; 23 | 24 | var 25 | Assert: Codeunit "Library Assert"; 26 | MessageDisplayed: Boolean; 27 | } -------------------------------------------------------------------------------- /Tests/helloworld/test/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "00000000-0000-0000-0000-000000000002", 3 | "name": "Default Test App Name", 4 | "publisher": "Default Publisher", 5 | "brief": "", 6 | "description": "", 7 | "version": "2.0.2147483647.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [ 14 | { 15 | "id": "dd0be2ea-f733-4d65-bb34-a28f4624fb14", 16 | "publisher": "Microsoft", 17 | "name": "Library Assert", 18 | "version": "16.0.0.0" 19 | }, 20 | { 21 | "id": "e7320ebb-08b3-4406-b1ec-b4927d3e280b", 22 | "publisher": "Microsoft", 23 | "name": "Any", 24 | "version": "16.0.0.0" 25 | }, 26 | { 27 | "id": "23de40a6-dfe8-4f80-80db-d70f83ce8caf", 28 | "publisher": "Microsoft", 29 | "name": "Test Runner", 30 | "version": "16.0.0.0" 31 | }, 32 | { 33 | "name": "Default App Name", 34 | "publisher": "Default Publisher", 35 | "version": "2.0.0.0", 36 | "id": "00000000-0000-0000-0000-000000000001" 37 | } 38 | ], 39 | "screenshots": [], 40 | "application": "17.0.0.0", 41 | "platform": "17.0.0.0", 42 | "idRanges": [ 43 | { 44 | "from": 50100, 45 | "to": 50149 46 | } 47 | ], 48 | "runtime": "6.0", 49 | "showMyCode": true, 50 | "target": "OnPrem" 51 | } 52 | -------------------------------------------------------------------------------- /Tests/helloworld/test/disabledTests.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "codeunitName": "CodeunitName", 4 | "method" : "Method" 5 | } 6 | ] -------------------------------------------------------------------------------- /Tests/inserttests/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "al", 6 | "request": "launch", 7 | "name": "Your own server", 8 | "server": "http://test1810", 9 | "serverInstance": "NAV", 10 | "authentication": "UserPassword", 11 | "startupObjectId": 22, 12 | "startupObjectType": "Page", 13 | "breakOnError": true, 14 | "launchBrowser": true 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /Tests/inserttests/Codeunit 50131 - Insert Testsl.al: -------------------------------------------------------------------------------- 1 | codeunit 50131 "Insert Tests" 2 | { 3 | Subtype = Install; 4 | 5 | trigger OnInstallAppPerCompany() 6 | var 7 | TestSuite: Codeunit "Test Suite"; 8 | begin 9 | TestSuite.Create('DEFAULT', '134006..134007', false); 10 | end; 11 | } -------------------------------------------------------------------------------- /Tests/inserttests/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "b20833f6-1ae6-416c-ac3a-c7cad91fa07a", 3 | "name": "inserttests", 4 | "publisher": "Freddy Kristiansen", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "dependencies": [], 14 | "screenshots": [], 15 | "platform": "13.0.0.0", 16 | "application": "13.0.0.0", 17 | "test": "13.0.0.0", 18 | "idRange": { 19 | "from": 50100, 20 | "to": 50149 21 | }, 22 | "showMyCode": true, 23 | "runtime": "2.4" 24 | } -------------------------------------------------------------------------------- /Tests/nav-app/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "al", 6 | "request": "launch", 7 | "name": "Publish", 8 | "server": "https://..cloudapp.azure.com", 9 | "serverInstance": "NAV", 10 | "authentication": "UserPassword" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /Tests/nav-app/CustomerCardExtension.al: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information. 4 | // ------------------------------------------------------------------------------------------------ 5 | 6 | pageextension 50112 CustomerCardExtension extends "Customer Card" 7 | { 8 | 9 | layout 10 | { 11 | // Add changes to page layout here 12 | } 13 | 14 | actions 15 | { 16 | addlast("&Customer") 17 | { 18 | action("Show Greeting") 19 | { 20 | RunObject = codeunit HelloWorld; 21 | RunPageOnRec = True; 22 | Image = CheckDuplicates; 23 | PromotedCategory = Category8; 24 | Promoted = true; 25 | ApplicationArea = All; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tests/nav-app/HelloWorld.al: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License. See License.txt in the project root for license information. 4 | // ------------------------------------------------------------------------------------------------ 5 | 6 | codeunit 50111 HelloWorld 7 | { 8 | TableNo = Customer; 9 | 10 | trigger OnRun(); 11 | var 12 | HelloText : Codeunit GreetingsManagement; 13 | begin 14 | Message('%1, %2', HelloText.GetRandomGreeting(), Rec.Name); 15 | end; 16 | } -------------------------------------------------------------------------------- /Tests/nav-app/Install.al: -------------------------------------------------------------------------------- 1 | codeunit 50114 "HelloWorld Test Install" 2 | { 3 | Subtype = Install; 4 | 5 | trigger OnInstallAppPerCompany() 6 | var 7 | CALTestSuite: Record "CAL Test Suite"; 8 | CALTestLine: Record "CAL Test Line"; 9 | CALTestMgmt: Codeunit "CAL Test Management"; 10 | begin 11 | if CALTestSuite.Get('DEFAULT') then 12 | exit; 13 | 14 | with CALTestSuite do begin 15 | init; 16 | 17 | validate(Name, 'DEFAULT'); 18 | validate(Description, 'DEFAULT'); 19 | validate(Export, false); 20 | insert(true); 21 | end; 22 | 23 | with CALTestLine do begin 24 | init; 25 | validate("Test Suite", 'DEFAULT'); 26 | validate("Line No.", 1); 27 | validate("Line Type", "Line Type"::Codeunit); 28 | validate("Test Codeunit", Codeunit::"HelloWorld Tests"); 29 | validate(Run, true); 30 | 31 | insert(true); 32 | 33 | CALTestMgmt.SETPUBLISHMODE; 34 | SETRECFILTER; 35 | CODEUNIT.RUN(CODEUNIT::"CAL Test Runner", CALTestLine); 36 | end; 37 | end; 38 | } -------------------------------------------------------------------------------- /Tests/nav-app/Tests.al: -------------------------------------------------------------------------------- 1 | codeunit 50113 "HelloWorld Tests" 2 | { 3 | Subtype = Test; 4 | TestPermissions = Disabled; 5 | 6 | var 7 | Assert: Codeunit Assert; 8 | 9 | [Test] 10 | procedure WorkingTest(); 11 | begin 12 | Assert.AreEqual(2, 2, '2 should be 2'); 13 | end; 14 | } -------------------------------------------------------------------------------- /Tests/nav-app/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "a7a49c61-7712-400a-9fc5-bc35f8e02aa0", 3 | "name": "Hello ÆØÅ", 4 | "publisher": "Cronus Denmark A/S", 5 | "brief": "The ability to greet your customers ", 6 | "description": "The ability to greet your customers in multiple languages.", 7 | "version": "1.0.0.0", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "", 12 | "logo": "", 13 | "capabilities": [], 14 | "platform": "11.0.0.0", 15 | "application": "11.0.0.0", 16 | "test": "11.0.0.0", 17 | "target": "Internal", 18 | "screenshots": [], 19 | "idRange": { 20 | "from": 50100, 21 | "to": 50149 22 | } 23 | } -------------------------------------------------------------------------------- /UserHandling/Get-NavContainerNavUser.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get list of users from NAV/BC Container 4 | .Description 5 | Retrieve the list of user objects from a tenant in a NAV/BC Container 6 | .Parameter containerName 7 | Name of the container from which you want to get the users 8 | .Parameter tenant 9 | Name of tenant from which you want to get the users 10 | .Example 11 | Get-BcContainerBcUser 12 | .Example 13 | Get-BcContainerBcUser -containerName test -tenant mytenant 14 | #> 15 | function Get-BcContainerBcUser { 16 | Param ( 17 | [Parameter(Mandatory=$false)] 18 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 19 | [Parameter(Mandatory=$false)] 20 | [string] $tenant = "default" 21 | ) 22 | 23 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 24 | try { 25 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { param($tenant) 26 | Get-NavServerUser -ServerInstance $ServerInstance -tenant $tenant 27 | } -ArgumentList $tenant | Where-Object {$_ -isnot [System.String]} 28 | } 29 | catch { 30 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 31 | throw 32 | } 33 | finally { 34 | TrackTrace -telemetryScope $telemetryScope 35 | } 36 | } 37 | Set-Alias -Name Get-NavContainerNavUser -Value Get-BcContainerBcUser 38 | Export-ModuleMember -Function Get-BcContainerBcUser -Alias Get-NavContainerNavUser 39 | -------------------------------------------------------------------------------- /UserHandling/New-NavContainerWindowsUser.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Creates a new Winodws User in a NAV/BC Container 4 | .Description 5 | Creates a new Windows user in a NAV/BC Container. 6 | .Parameter containerName 7 | Name of the container in which you want to create a windows user 8 | .Parameter Credential 9 | Credentials of the new Winodws user 10 | .Parameter group 11 | Name of the local group to add the user to (default is administrators) 12 | .Example 13 | New-BcContainerWindowsUser -containerName test -tenantId mytenant -username freddyk -password $password 14 | #> 15 | function New-BcContainerWindowsUser { 16 | Param ( 17 | [Parameter(Mandatory=$false)] 18 | [string] $containerName = $bcContainerHelperConfig.defaultContainerName, 19 | [Parameter(Mandatory=$true)] 20 | [PSCredential] $Credential, 21 | [parameter(Mandatory=$false)] 22 | [string] $group = "administrators" 23 | ) 24 | 25 | $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @() 26 | try { 27 | Invoke-ScriptInBcContainer -containerName $containerName -ScriptBlock { param([System.Management.Automation.PSCredential]$Credential, [string]$group) 28 | 29 | Write-Host "Creating Windows user $($Credential.username)" 30 | New-LocalUser -AccountNeverExpires -FullName $Credential.username -Name $Credential.username -Password $Credential.Password | Out-Null 31 | Write-Host "Adding Windows user $($Credential.username) to $group" 32 | Add-LocalGroupMember -Group $group -Member $Credential.username -ErrorAction Ignore 33 | 34 | } ` 35 | -ArgumentList $Credential, $group 36 | } 37 | catch { 38 | TrackException -telemetryScope $telemetryScope -errorRecord $_ 39 | throw 40 | } 41 | finally { 42 | TrackTrace -telemetryScope $telemetryScope 43 | } 44 | } 45 | Set-Alias -Name New-NavContainerWindowsUser -Value New-BcContainerWindowsUser 46 | Export-ModuleMember -Function New-BcContainerWindowsUser -Alias New-NavContainerWindowsUser 47 | -------------------------------------------------------------------------------- /Version.txt: -------------------------------------------------------------------------------- 1 | 6.1.7-dev --------------------------------------------------------------------------------