Scripts/Install-BizTalkApplication.ps1

#region Copyright & License

# Copyright © 2012 - 2022 François Chabot
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#endregion

<#
.SYNOPSIS
   Deploys the resources declared by a given Microsoft BizTalk Server® application deployment manifest.
.DESCRIPTION
   This command will entrust Invoke-Build to carry on all the tasks necessary to deploy the resources declared by a given Microsoft BizTalk Server® application
   deployment manifest, which manifest is a HashTable created with the Resource.Manifest PowerShell module.
.PARAMETER Manifest
   The application deployment manifest instance.
.PARAMETER Path
   The path to the application deployment manifest.
.PARAMETER TargetEnvironment
   The target deployment environment, which can be any string value, but also supports the target environments defined by BizTalk.Factory, i.e. 'DEV' for
   development, 'BLD' for build, 'INT' for integration, 'ACC' for acceptance, 'PRE' for preproduction, or 'PRD' for production.
.PARAMETER Task
   User defined tasks that the manifest depends on to complete its deployment. Tasks can either be new ones or override existing ones. See Invoke-Build
   documentation, How to assemble builds using script blocks, https://github.com/nightroman/Invoke-Build/tree/master/Tasks/Inline, and Script block as File,
   https://github.com/nightroman/Invoke-Build/issues/78, for some explanation.
   Notice that BizTalk.Deployment provides customization/injection points by defining Enter-/Exit-<ResourceScope> tasks, e.g. Enter-DatabaseDeployment and
   Exit-DatabaseDeployment that allows to inject pre- or post-processing tasks surrounding the database deployment tasks.
.PARAMETER ExcludeResourceGroup
   The wildcard pattern determining the names of the resources or pseudo resources to ignore during the deployment. Notice that even though the tasks related to
   these resources will still be executed, they will proceed as if these resources had not been declared and will thus have no effect. All the resources of a
   manifest can be excluded at once by passing the wildcard * character.
.PARAMETER ExcludeTask
   The wildcard pattern determining the names of the tasks to skip during the deployment. Skipping a task also skips all its dependant tasks, e.g. skipping the
   'Deploy' task will skip the whole deployment, as well as passing the wildcard * character.
.PARAMETER FileUser
   The names of the users or groups, local or not, to be granted full access control over the folders declared by both inbound and outbound Microsoft BizTalk
   Server® file adapters. It defaults to both local groups 'BizTalk Application Users' and 'Users'. This parameter has effect provided the 'SkipFileAdapterFolders'
   switch parameter is not passed.
.PARAMETER InitializationOption
   The set of Microsoft BizTalk Server® services, or artifacts, to start after deployment is complete. This is bitmask enumeration defining the following values:
   - None, when no services at all have to be started,
   - Orchestrations, when only the orchestrations have to be started,
   - ReceiveLocations, when only the receive locations have to be enabled,
   - SendPorts, when only the send ports have to be started,
   - All, when all of the above services have to started. It is the default value and is equivalent to passing the following array of values: Orchestrations,
     ReceiveLocations, SendPorts.
.PARAMETER Isolated
   Whether to execute the tasks that load the application binding assembly written in BizTalk.Factory's Binding DSL in another local process via PowerShell
   remoting. It is particularly handy for the developer who is fine tuning the binding assembly and constantly needs to recompile and redeploy it without having it
   being locked by the PowerShell process. As a .NET assembly, once loaded, cannot be unloaded, and unlocked, unless the process that has loaded it is terminated,
   this switch parameter prevents the developer from constantly having to kill his shell and start a new one. For this reason, it defaults to true when the
   TargetEnvironment parameter is given the value 'DEV'.
.PARAMETER SkipFileAdapterFolders
   Whether to skip creating the folders declared by both inbound and outbound Microsoft BizTalk Server® file adapters, as well as modifying their ACLs. The same
   effect could be achieved by excluding the pseudo resource group FileAdapterFolders.
.PARAMETER SkipHostInstanceRestart
   Whether to skip restarting the Microsoft BizTalk Server® host instances concerned by the application being deployed.
.PARAMETER SkipSharedResources
   Whether to skip all the resources that need to be deployed only once in a Microsoft BizTalk Server® group. Indeed, resources such as Microsoft BizTalk Server®
   application bindings and other artifacts like orchestrations, schemas, or maps need to be imported in the Microsoft BizTalk Server®'s management database only
   once, that is to say on only one of the machines belonging to the same Microsoft BizTalk Server® group. While resources such as assembly, windows services,
   event log sources, or xml configurations need to deployed on every machine belonging to the same Microsoft BizTalk Server® group.
   To summarize, this switch parameter needs to passed for every machine belonging to the same Microsoft BizTalk Server® group but the one playing the role of the
   management server.
.PARAMETER SkipUninstall
   Whether to skip the undeployment of the resources declared by the manifest before trying to deploy them. Notice that by default, an uninstall will be triggered
   when the TargetEnvironment is 'DEV' but will always be skipped for other TargetEnvironment values unless this switch parameter is explicitly passed. Care should
   be taken as to whether this switch should be used for target environments such as acceptance or production.
.PARAMETER TerminateServiceInstances
   Whether to terminate any running or suspended Microsoft BizTalk Server® service instances related to the application being uninstalled.
.EXAMPLE
   PS> Install-BizTalkApplication -Manifest $m -TargetEnvironment DEV
.EXAMPLE
   PS> Install-BizTalkApplication -Manifest $m -TargetEnvironment PRD -InitializationOption Orchestrations, SendPorts
.EXAMPLE
   PS> Install-BizTalkApplication -Manifest $m -TargetEnvironment DEV -ExcludeResourceGroup * -Verbose
 
   As all the resources are excluded, this command outputs the tasks that would have carried on.
.EXAMPLE
   PS> Install-BizTalkApplication -Manifest $m -TargetEnvironment DEV -Task { task Deploy { Write-Host 'I hijacked the whole deployment process.' } }
.LINK
   https://www.stateless.be/PowerShell/Module/BizTalk/Deployment/
.NOTES
   © 2022 be.stateless.
#>

[CmdletBinding(DefaultParameterSetName = 'manifest-path')]
[OutputType([void])]
param(
   [Parameter(Mandatory = $true, ParameterSetName = 'manifest-object')]
   [ValidateNotNullOrEmpty()]
   [ValidateScript( { $_.Properties.Type -eq 'Application' } )]
   [HashTable[]]
   $Manifest,

   [Parameter(Mandatory = $true, ParameterSetName = 'manifest-path')]
   [ValidateNotNullOrEmpty()]
   [ValidateScript( { Test-Path -Path $_ -PathType Leaf } )]
   [string[]]
   $Path,

   [Parameter(Mandatory = $true, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $true, ParameterSetName = 'manifest-path')]
   [ValidateNotNullOrEmpty()]
   [string]
   $TargetEnvironment,

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [scriptblock[]]
   $Task = ([scriptblock] { }),

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [ValidateNotNullOrEmpty()]
   [string[]]
   $ExcludeResourceGroup = @(),

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [ValidateNotNullOrEmpty()]
   [string[]]
   $ExcludeTask = @(),

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [ValidateNotNullOrEmpty()]
   [string[]]
   $FileUser = @("$($env:COMPUTERNAME)\BizTalk Application Users", 'BUILTIN\Users'),

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [Be.Stateless.BizTalk.Dsl.Binding.Visitor.BizTalkServiceInitializationOptions]
   $InitializationOption = 'All',

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [switch]
   $Isolated = ($TargetEnvironment -eq 'DEV'),

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [switch]
   $SkipFileAdapterFolders,

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [switch]
   $SkipHostInstanceRestart,

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [switch]
   $SkipSharedResources,

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [switch]
   $SkipUninstall = ($TargetEnvironment -ne 'DEV'),

   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-object')]
   [Parameter(Mandatory = $false, ParameterSetName = 'manifest-path')]
   [switch]
   $TerminateServiceInstances
)
begin {
   Set-StrictMode -Version Latest
   Resolve-ActionPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
}
process {
   $script:Manifest = switch ($PsCmdlet.ParameterSetName) {
      'manifest-object' { $Manifest }
      'manifest-path' { & $Path }
   }
   if ($script:Manifest.Properties.Type -ne 'Application') {
      throw "This command does not support this type of manifest '$($script:Manifest.Properties.Type)'."
   }

   # https://github.com/nightroman/Invoke-Build/issues/78, Script block as `File`
   # https://github.com/nightroman/Invoke-Build/tree/master/Tasks/Inline
   try {
      $taskBlockList = $Task # don't clash with InvokeBuild's $Task variable
      Invoke-Build Deploy {
         . BizTalk.Deployment.Tasks
         foreach ($taskBlock in $taskBlockList) {
            . $taskBlock
         }
      }
   } catch {
      Write-Error $_.Exception.ToString()
      throw
   }
}

# SIG # Begin signature block
# MIII0QYJKoZIhvcNAQcCoIIIwjCCCL4CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUjVePH5P/8Z2xKx4iqRYJI8fl
# XAagggVMMIIFSDCCAzCgAwIBAgIJAJkr3mJdTBkUMA0GCSqGSIb3DQEBCwUAMEEx
# PzA9BgNVBAMeNgBpAGMAcgBhAGYAdABzAG8AZgB0AHcAYQByAGUAQABzAHQAYQB0
# AGUAbABlAHMAcwAuAGIAZTAeFw0yMTA2MjUxNDEyMjNaFw00MTA2MjAxNDEyMjNa
# MEExPzA9BgNVBAMeNgBpAGMAcgBhAGYAdABzAG8AZgB0AHcAYQByAGUAQABzAHQA
# YQB0AGUAbABlAHMAcwAuAGIAZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAOeqdUHBv7sxSeX3aj6yPKj7PAvs8izpVXjyEBl5aR8mQneVcXuF53AH7EW1
# 6E5p4+Az5pJPGUD5c3tXhiGMF7vgLhQjO6hlaVBRIqiIYHikNLwMNy6YBMc/QQYM
# rPhqHEFsZ53dkBIIj3M8e3kFcTFA09n25yDtTPDab4nd9yUhc9Qc8+nfpIzfYsoP
# 1pZ3nCzhw6hN2/44v1dkQrG3dRYwt+px65p6NPNZWEJpt4VCJjIFh+lBYJdxm9d4
# X/rAnlHIkbv7liOavWDzgHVabS3hdAWtcDmynm+7+FcZDFqPWNCl3e4SS7xe4s/R
# CKFKA0IsfKkSk9YJlLgeSQIEXUOOWXJAGaLqnRD8xWLZsc4Oi9GZg7XV1mv/S88c
# oztXnwtAN3OOlRKBh2QbomMgxeMO0GvsLE/cq5Q/YKAoz+KGr/7LcZq9jzQ8IPus
# ZvWLeDXmxPiwJjpZc1koLgfGIEX2NStQTT3QmacWr9thrWcKvI+4uBmI4exS9B4a
# R3nV91w5EY+2RoYsHqej9LWwNamO96+jMX9pxprTX+EkLUuMAikw/po8sBC9MUUn
# 5pMWmUv7DCtQOLGGBDDMMMkn4ZcjpCEEdPGHRKfqNnD27ssGtDjiNzfQrsm67toU
# bBwUF+gyJq/YckWquYJhA9ZOFWEADuIwGnsOzsoRvuQyY+p9AgMBAAGjQzBBMA4G
# A1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzAXBgNVHREEEDAO
# ggxzdGF0ZWxlc3MuYmUwDQYJKoZIhvcNAQELBQADggIBACithYM3qckZRc9+Xbfu
# a6gWr3HwjrW+FHKgjfrcOm8ZnLVapb9xFqsqrRQqd3RXWQDINEGrtI2rSfrzyfoK
# UiTgldIfQNP1ZcGY229d++90t3hdo2mlt05hjYlbMENloJHpsEP0vQZmwOcEimCT
# ex1pymYM+P9pj3j8UD1PT1eIZot6or8fBRl63UybyDSrM7L4UOkkAOniKxWy5pW6
# 6duS8SR+SZpr3Bv44NyXPj0Nv+MIpLmsLrd7XPBFmnGxzY01ZO9vzi9KEhM2wT5i
# jPqHDNOvfPiADtAa+EyUBzdJiqy9heCz/TMZQgMWGwtfqJNxWZmsHcha2anW4Qt+
# mzrLO4GojWoVog9uVSAq+l0a+YQsd1u1kUmm4vgZCFyUA+lEp4LkI7ca2VBHkLPD
# w+u2DoDMRiqFPZjO7BCKjGc0jj9B/qGR3JVt+tqDdB621xXf2YGF2oFvxZQ/keGt
# 0ujfJ+JwN3nCulDAA4773q6KUnfykyrvAgITNbRJL6TngeRKtw9VIJBPxzqMzLpV
# 5ggXNituwLaD1CCBJ1oo9DZHpL9gplXp1wGrelJOTiJhh+pdNsPtRH7CrranWa5h
# LFLuigqin0eewQ5giJ1VaiBVEseOmiZog+27UpFIv40aDzgGL3YxB/Mu0ojwrQtp
# WLmqJCmWnR5qxOm0yK+zNWe0MYIC7zCCAusCAQEwTjBBMT8wPQYDVQQDHjYAaQBj
# AHIAYQBmAHQAcwBvAGYAdAB3AGEAcgBlAEAAcwB0AGEAdABlAGwAZQBzAHMALgBi
# AGUCCQCZK95iXUwZFDAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAA
# oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w
# DAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUHEqtsVnTOi+rX5BQBU2C1a/L
# uA4wDQYJKoZIhvcNAQEBBQAEggIApEVPusP1qvCipKbCumK0zOsF0yI967Ao1chL
# /w6FJqB1WqbkVFss2nxLGGN29+dQIsw40oqYHgPpgB6rQFC427l/2T/df1JkgiJu
# xKcbJSJgABYLUtW9V/1VplFwy8pws+mr/IQnLqOkILsFt1OKj+769TnWFpQ70vtQ
# RxgkDVPso3zRy6X19SC//QcUmpeviAg3kesxL9g5YdGg+5UMQClpJmjH2tpI1AY3
# 9CqsJ/tyhly38iuDcgS+wJ675ef6ZbFGN3Wgg7+h+ap/IGT2htYjUwIgoTMMsppc
# K43PbqBKzRsPR0Np5udn3a+jq+49ilb2j5hSPK3pX11svN0Te75OrHN4e+Oux8bO
# Sh+J9UzIdJJguLLiR6ByCysh0FJRsWvFQbcfjsI1dKxcENld7nlaEpgu/G932+2R
# V7QB3+aYbEq+Ipbe+lYyp62B2Th0lIueVem9k0QTXbrTUzPNySm4YyJgutXF8PuN
# ZkpryYKdYblqkrfstup6LFCu447irNG97TEpNXhgsmLVB+BZJQClSRBeDbEpD0fd
# 0D9AkycYZ6tGyu1QFPDK5CW26Ji1tvw/N9xOAJ82ckTyrVgb5AUI8wYKLbhm9Y9W
# DgCU1Mq3w0QD1X6pzq8uiphC1tLunpqKvxDnexI1CoLD329ttUpB/8sqykRJihuC
# dWe+ktU=
# SIG # End signature block