OctopusDeploy / Library

| Public | A repository of step templates and other community-contributed extensions to Octopus Deploy
Other
171 stars 504 forks source link

SQL - Deploy DACPAC using SqlPackage - Lost functionality when updating from legacy package #1407

Closed grexican closed 9 months ago

grexican commented 1 year ago

The prior version of the step required you to work in two parts: First having a step to retrieve the DACPAC package; and then to use the legacy SQL - Deploy DACPAC step template. This new version allows you to do it all-in-one.

The issue with this is that functionality from the first part is lost.

My publish.xml file in my dacpac has octopus variables in it that I need replaced at runtime.

I'm trying to follow this guide to do the update https://help.octopus.com/t/dacpac-deployment-failures-hresult-0x80131018/28950/3 but using the updated package means I lose the required functionality (and my deployments fail). My only option is to get the workarounds to work, which so far I haven't been successful at.

I recommend going back to the old way of doing it, whereby I can choose a step to pull the package from instead of pulling it directly from the server. That would allow me the flexibility to manipulate the package before sending it into the deployment step.

Thanks

twerthi commented 1 year ago

Greetings @grexican! I have a customized version of this template that might work for you. I've enabled the Structured Configuration Variables feature to perform replacement on the Publish profile file name input. Is that something you'd be willing to test?

grexican commented 1 year ago

@twerthi just so I'm following -- it's to replace the profile file name using config variables? If so, that's not what I mean.

I mean inside publish.xml I have

#{SomeVariable#

So before publish.xml gets processed, the publish.xml file itself needs to be transformed.

If this is what you're offering, then yes I'd be happy to test.

twerthi commented 1 year ago

Hey there @grexican :) Not quite, it uses the Structured Configuration Variable feature (https://octopus.com/docs/projects/steps/configuration-features/structured-configuration-variables-feature) to enable value replacement within a file, in your case it would use XPath to find the XML node to update. This allows the file to be valid XML syntax for things like local testing, but have the values replaced at deploy time, does that make sense?

twerthi commented 1 year ago

@grexican Please let me know if you wanted to give this version a go :)

twerthi commented 1 year ago

It was easy enough to add the Substitute Variables in Templates feature to the template as well to support how you're currently doing it. Let me know if you wanted to give it a try :)

grexican commented 1 year ago

Sounds good, I'll give it a shot, thanks!

twerthi commented 1 year ago

Cool, import this and give it a go

{
  "Id": "5459e948-e72d-4b5d-80c0-e84764892411",
  "Name": "Deploy ispac SSIS project from a Package parameter Copy",
  "Description": "This step template will deploy SSIS ispac projects to SQL Server Integration Services Catalog.  The template uses a referenced package and is Worker compatible.\n\nThis template will install the Nuget package provider if it is not present on the machine it is running on.",
  "ActionType": "Octopus.Script",
  "Version": 1,
  "CommunityActionTemplateId": null,
  "Packages": [
    {
      "Id": "5ce9da08-a4ed-4b69-92d1-ab88c705cf08",
      "Name": "SSIS.Template.ssisPackageId",
      "PackageId": null,
      "FeedId": null,
      "AcquisitionLocation": "Server",
      "Properties": {
        "Extract": "True",
        "SelectionMode": "deferred",
        "PackageParameterName": "SSIS.Template.ssisPackageId"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "#region Functions\n\n# Define functions\nfunction Get-SqlModuleInstalled\n{\n    # Define parameters\n    param(\n        $PowerShellModuleName\n    )\n\n    # Check to see if the module is installed\n    if ($null -ne (Get-Module -ListAvailable -Name $PowerShellModuleName))\n    {\n        # It is installed\n        return $true\n    }\n    else\n    {\n        # Module not installed\n        return $false\n    }\n}\n\nfunction Get-NugetPackageProviderNotInstalled\n{\n\t# See if the nuget package provider has been installed\n    return ($null -eq (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue))\n}\n\nfunction Install-SqlServerPowerShellModule\n{\n    # Define parameters\n    param(\n        $PowerShellModuleName,\n        $LocalModulesPath\n    )\n\n\t# Check to see if the package provider has been installed\n    if ((Get-NugetPackageProviderNotInstalled) -ne $false)\n    {\n    \t# Display that we need the nuget package provider\n        Write-Host \"Nuget package provider not found, installing ...\"\n        \n        # Install Nuget package provider\n        Install-PackageProvider -Name Nuget -Force\n    }\n\n\t# Save the module in the temporary location\n    Save-Module -Name $PowerShellModuleName -Path $LocalModulesPath -Force #-RequiredVersion \"21.1.18256\"\n\n\t# Display\n    Write-Output \"Importing module $PowerShellModuleName ...\"\n\n    # Import the module\n    Import-Module -Name $PowerShellModuleName\n}\n\nFunction Load-SqlServerAssmblies\n{\n\t# Check the GAC for the assembly files\n    Write-Host \"Checking GAC for required assemblies ...\"\n    $integrationServicesAssembly = (Get-ChildItem -Path \"C:\\Windows\\Microsoft.Net\\assembly\" -Recurse | Where-Object {$_.Name -eq \"Microsoft.SqlServer.Management.IntegrationServices.dll\"})\n    #$diagnosticsAssembly = (Get-ChildItem -Path \"C:\\Windows\\Microsoft.Net\\assembly\" -Recurse | Where-Object {$_.Name -eq \"Microsoft.SqlServer.Diagnostics.STrace.dll\"})\n    \n    # Check for null\n    if ($null -eq $integrationServicesAssembly)\n    {\n    \t# Check for SSMS\n        Write-Host \"Require assmeblies not found in GAC, checking to see if SSMS is installed ...\"\n        $ssms = (Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -eq \"SQL Server Management Studio\"})\n        \n        # Check for null\n        if ($null -ne $ssms)\n        {\n        \t# Get the installation location to find the assemblies in\n            Write-Host \"SSMS is installed, retrieving installation location for assemblies ...\"\n            \n            # Get the location in which SSMS is installed\n            $registryEntries = Get-ChildItem -Path \"HKLM:\\SOFTWARE\\Classes\\ssms*\"\n            \n            # Check for null\n            if ($null -ne $registryEntries)\n            {\n            \t# Use the first key in the list, that's all we need\n                $registryEntry = $registryEntries[0]\n                \n                # Get the subkeys\n                $subKeys = Get-ChildItem -Path Registry::$($registryEntry)\n                \n                # Get properties from first subkey\n                $keyValues = Get-ItemProperty -Path Registry::$($subKeys[0])\n                \n                # Get the value of the default property\n                $dllPath = $keyValues.'(default)'.SubString(0, $keyValues.'(default)'.LastIndexOf(\"\\\"))\n                \n                # Load the required assemblies\n                #[Reflection.Assembly]::LoadFile(\"$dllPath\\Microsoft.SqlServer.Management.Sdk.Sfc.dll\")\n                Add-Type -Path \"$dllPath\\Microsoft.SqlServer.Management.Sdk.Sfc.dll\"\n                Add-Type -Path \"$dllPath\\Microsoft.SqlServer.Dmf.Common.dll\"\n                [Reflection.Assembly]::LoadFile(\"$dllPath\\Extensions\\Application\\Microsoft.Identity.Client.dll\")\n                [Reflection.Assembly]::LoadFile(\"$dllPath\\System.Threading.Tasks.Extensions.dll\")\n                [Reflection.Assembly]::LoadFile(\"$dllPath\\Microsoft.IdentityModel.Abstractions.dll\")\n                #[Reflection.Assembly]::LoadFile(\"$dllPath\\Microsoft.SqlServer.Diagnostics.STrace.dll\")\n                \n                [Reflection.Assembly]::LoadFile(\"$dllPath\\Microsoft.Data.SqlClient.dll\")\n                [Reflection.Assembly]::LoadFile(\"$dllPath\\Microsoft.SqlServer.Smo.dll\")\n                [Reflection.Assembly]::LoadFile(\"$dllPath\\Microsoft.SqlServer.SqlEnum.dll\")\n                #[Reflection.Assembly]::LoadFile(\"$dllPath\\CommonExtensions\\Microsoft\\SSIS\\Microsoft.SqlServer.Management.IntegrationServices.dll\")\n                Add-Type -Path \"$dllPath\\CommonExtensions\\Microsoft\\SSIS\\Microsoft.SqlServer.Management.IntegrationServices.dll\"\n                \n                try {\n                Add-Type -Path \"$dllPath\\Microsoft.SqlServer.Diagnostics.STrace.dll\"\n                <#Add-Type -Path \"$dllPath\\Microsoft.SqlServer.Management.Sdk.Sfc.dll\"\n                Add-Type -Path \"$dllPath\\System.Threading.Tasks.Extensions.dll\"\n                Add-Type -Path \"$dllPath\\Microsoft.IdentityModel.Abstractions.dll\"\n                Add-Type -Path \"$dllPath\\Extensions\\Application\\Microsoft.Identity.Client.dll\"\n                Add-Type -Path \"$dllPath\\Microsoft.Data.SqlClient.dll\"\n                Add-Type -Path \"$dllPath\\Microsoft.SqlServer.Smo.dll\"\n                Add-Type -Path \"$dllPath\\Microsoft.SqlServer.SqlEnum.dll\"             \n                Add-Type -Path \"$dllPath\\CommonExtensions\\Microsoft\\SSIS\\Microsoft.SqlServer.Management.IntegrationServices.dll\"#>\n                }\n                catch { $_.Exception.LoaderExceptions } #>\n            }\n        }\n    }\n    else\n    {\n    \t# Load the assembly from the GAC\n        [Reflection.Assembly]::LoadFile($integrationServicesAssembly.FullName)\n    }\n    \n    #[Reflection.Assembly]::LoadWithPartialName(\"Microsoft.SqlServer.Management.IntegrationServices\")\n    #[Reflection.Assembly]::LoadWithPartialName(\"Microsoft.SqlServer.Diagnostics.STrace\")\n    \n    #[Reflection.Assembly]::LoadFile($diagnosticsAssembly.FullName)\n}\n\n#region Get-Catalog\nFunction Get-Catalog\n{\n     # define parameters\n    Param ($CatalogName)\n    # NOTE: using $integrationServices variable defined in main\n    \n    # define working varaibles\n    $Catalog = $null\n    # check to see if there are any catalogs\n    if($integrationServices.Catalogs.Count -gt 0 -and $integrationServices.Catalogs[$CatalogName])\n    {\n    \t# get reference to catalog\n    \t$Catalog = $integrationServices.Catalogs[$CatalogName]\n    }\n    else\n    {\n    \tif((Get-CLREnabled) -eq 0)\n    \t{\n    \t\tif(-not $EnableCLR)\n    \t\t{\n    \t\t\t# throw error\n    \t\t\tthrow \"SQL CLR is not enabled.\"\n    \t\t}\n    \t\telse\n    \t\t{\n    \t\t\t# display sql clr isn't enabled\n    \t\t\tWrite-Warning \"SQL CLR is not enabled on $($sqlConnection.DataSource).  This feature must be enabled for SSIS catalogs.\"\n    \n    \t\t\t# enablign SQLCLR\n    \t\t\tWrite-Host \"Enabling SQL CLR ...\"\n    \t\t\tEnable-SQLCLR\n    \t\t\tWrite-Host \"SQL CLR enabled\"\n    \t\t}\n    \t}\n    \n    \t# Provision a new SSIS Catalog\n    \tWrite-Host \"Creating SSIS Catalog ...\"\n    \n    \t$Catalog = New-Object \"$ISNamespace.Catalog\" ($integrationServices, $CatalogName, $OctopusParameters['SSIS.Template.CatalogPwd'])\n    \t$Catalog.Create()\n    \n    \n    }\n    \n    # return the catalog\n    return $Catalog\n}\n#endregion\n\n#region Get-CLREnabled\nFunction Get-CLREnabled\n{\n    # define parameters\n    # Not using any parameters, but am using $sqlConnection defined in main\n    \n    # define working variables\n    $Query = \"SELECT * FROM sys.configurations WHERE name = 'clr enabled'\"\n    \n    # execute script\n    $CLREnabled = Invoke-Sqlcmd -ServerInstance $sqlConnection.DataSource -Database \"master\" -Query $Query | Select value\n    \n    # return value\n    return $CLREnabled.Value\n}\n#endregion\n\n#region Enable-SQLCLR\nFunction Enable-SQLCLR\n{\n    $QueryArray = \"sp_configure 'show advanced options', 1\", \"RECONFIGURE\", \"sp_configure 'clr enabled', 1\", \"RECONFIGURE \"\n    # execute script\n    \n    foreach($Query in $QueryArray)\n    {\n    \tInvoke-Sqlcmd -ServerInstance $sqlConnection.DataSource -Database \"master\" -Query $Query\n    }\n    \n    # check that it's enabled\n    if((Get-CLREnabled) -ne 1)\n    {\n    \t# throw error\n    \tthrow \"Failed to enable SQL CLR\"\n    }\n}\n#endregion\n\n#region Get-Folder\nFunction Get-Folder\n{\n # parameters\n    Param($FolderName, $Catalog)\n    \n    $Folder = $null\n    # try to get reference to folder\n    \n    if(!($Catalog.Folders -eq $null))\n    {\n    \t$Folder = $Catalog.Folders[$FolderName]\n    }\n    \n    # check to see if $Folder has a value\n    if($Folder -eq $null)\n    {\n    \t# display\n    \tWrite-Host \"Folder $FolderName doesn't exist, creating folder...\"\n    \n    \t# create the folder\n    \t$Folder = New-Object \"$ISNamespace.CatalogFolder\" ($Catalog, $FolderName, $FolderName) \n    \t$Folder.Create() \n    }\n    \n    # return the folde reference\n    return $Folder\n}\n#endregion\n\n#region Get-Environment\nFunction Get-Environment\n{\n     # define parameters\n    Param($Folder, $EnvironmentName)\n    \n    $Environment = $null\n    # get reference to Environment\n    if(!($Folder.Environments -eq $null) -and $Folder.Environments.Count -gt 0)\n    {\n    \t$Environment = $Folder.Environments[$EnvironmentName]\n    }\n    \n    # check to see if it's a null reference\n    if($Environment -eq $null)\n    {\n    \t# display\n    \tWrite-Host \"Environment $EnvironmentName doesn't exist, creating environment...\"\n    \n    \t# create environment\n    \t$Environment = New-Object \"$ISNamespace.EnvironmentInfo\" ($Folder, $EnvironmentName, $EnvironmentName)\n    \t$Environment.Create() \n    }\n    \n    # return the environment\n    return $Environment\n}\n#endregion\n\n#region Set-EnvironmentReference\nFunction Set-EnvironmentReference\n{\n     # define parameters\n    Param($Project, $Environment, $Folder)\n    \n    # get reference\n    $Reference = $null\n    \n    if(!($Project.References -eq $null))\n    {\n    \t$Reference = $Project.References[$Environment.Name, $Folder.Name]\n    \n    }\n    \n    # check to see if it's a null reference\n    if($Reference -eq $null)\n    {\n    \t# display\n    \tWrite-Host \"Project does not reference environment $($Environment.Name), creating reference...\"\n    \n    \t# create reference\n    \t$Project.References.Add($Environment.Name, $Folder.Name)\n    \t$Project.Alter() \n    }\n}\n#endregion\n\n#region Set-ProjectParametersToEnvironmentVariablesReference\nFunction Set-ProjectParametersToEnvironmentVariablesReference\n{\n     # define parameters\n    Param($Project, $Environment)\n    \n    $UpsertedVariables = @()\n\n    if($Project.Parameters -eq $null)\n    {\n        Write-Host \"No project parameters exist\"\n        return\n    }\n\n    # loop through project parameters\n    foreach($Parameter in $Project.Parameters)\n    {\n        # skip if the parameter is included in custom filters\n        if ($UseCustomFilter) \n        {\n            if ($Parameter.Name -match $CustomFilter)\n            {\n                Write-Host \"- $($Parameter.Name) skipped due to CustomFilters.\"            \n                continue\n            }\n        }\n\n        # Add variable to list of variable\n        $UpsertedVariables += $Parameter.Name\n\n        $Variable = $null\n        if(!($Environment.Variables -eq $null))\n        {\n    \t    # get reference to variable\n    \t    $Variable = $Environment.Variables[$Parameter.Name]\n        }\n    \n    \t# check to see if variable exists\n    \tif($Variable -eq $null)\n    \t{\n    \t\t# add the environment variable\n    \t\tAdd-EnvironmentVariable -Environment $Environment -Parameter $Parameter -ParameterName $Parameter.Name\n    \n    \t\t# get reference to the newly created variable\n    \t\t$Variable = $Environment.Variables[$Parameter.Name]\n    \t}\n    \n    \t# set the environment variable value\n    \tSet-EnvironmentVariableValue -Variable $Variable -Parameter $Parameter -ParameterName $Parameter.Name\n    }\n    \n    # alter the environment\n    $Environment.Alter()\n    $Project.Alter()\n\n    return $UpsertedVariables\n}\n#endregion\n\nFunction Set-PackageVariablesToEnvironmentVariablesReference\n{\n    # define parameters\n    Param($Project, $Environment)\n\n    $Variables = @()\n    $UpsertedVariables = @()\n\n    # loop through packages in project in order to store a temp collection of variables\n    foreach($Package in $Project.Packages)\n    {\n    \t# loop through parameters of package\n    \tforeach($Parameter in $Package.Parameters)\n    \t{\n    \t\t# add to the temporary variable collection\n    \t\t$Variables += $Parameter.Name\n    \t}\n    }\n\n    # loop through packages in project\n    foreach($Package in $Project.Packages)\n    {\n    \t# loop through parameters of package\n    \tforeach($Parameter in $Package.Parameters)\n    \t{\n            if ($UseFullyQualifiedVariableNames)\n            {\n                # Set fully qualified variable name\n                $ParameterName = $Parameter.ObjectName.Replace(\".dtsx\", \"\")+\".\"+$Parameter.Name\n            }\n            else\n            {\n                # check if exists a variable with the same name\n                $VariableNameOccurrences = $($Variables | Where-Object { $_ -eq $Parameter.Name }).count\n                $ParameterName = $Parameter.Name\n                \n                if ($VariableNameOccurrences -gt 1)\n                {\n                    $ParameterName = $Parameter.ObjectName.Replace(\".dtsx\", \"\")+\".\"+$Parameter.Name\n                }\n            }\n            \n            if ($UseCustomFilter)\n            {\n                if ($ParameterName -match $CustomFilter)\n                {\n                    Write-Host \"- $($Parameter.Name) skipped due to CustomFilters.\"            \n                    continue\n                }\n            }\n\n            # get reference to variable\n    \t\t$Variable = $Environment.Variables[$ParameterName]\n\n            # Add variable to list of variable\n            $UpsertedVariables += $ParameterName\n\n            # check to see if the parameter exists\n    \t\tif(!$Variable)\n    \t\t{\n    \t\t\t# add the environment variable\n    \t\t\tAdd-EnvironmentVariable -Environment $Environment -Parameter $Parameter -ParameterName $ParameterName\n    \n    \t\t\t# get reference to the newly created variable\n    \t\t\t$Variable = $Environment.Variables[$ParameterName]\n    \t\t}\n    \n    \t\t# set the environment variable value\n    \t\tSet-EnvironmentVariableValue -Variable $Variable -Parameter $Parameter -ParameterName $ParameterName\n    \t}\n    \n    \t# alter the package\n    \t$Package.Alter()\n    }\n    \n    # alter the environment\n    $Environment.Alter()\n\n    return $UpsertedVariables\n}\n\nFunction Sync-EnvironmentVariables\n{\n    # define parameters\n    Param($Environment, $VariablesToPreserveInEnvironment)\n\n    foreach($VariableToEvaluate in $Environment.Variables)\n    {\n        if ($VariablesToPreserveInEnvironment -notcontains $VariableToEvaluate.Name)\n        {\n            Write-Host \"- Removing environment variable: $($VariableToEvaluate.Name)\"\n            $VariableToRemove = $Environment.Variables[$VariableToEvaluate.Name]\n            $Environment.Variables.Remove($VariableToRemove) | Out-Null\n        }\n    }\n\n    # alter the environment\n    $Environment.Alter()\n}\n\n#region Add-EnvironmentVariable\nFunction Add-EnvironmentVariable\n{\n    # define parameters\n    Param($Environment, $Parameter, $ParameterName)\n    \n    # display \n    Write-Host \"- Adding environment variable $($ParameterName)\"\n    \n    # check to see if design default value is emtpy or null\n    if([string]::IsNullOrEmpty($Parameter.DesignDefaultValue))\n    {\n    \t# give it something\n    \t$DefaultValue = \"\" # sensitive variables will not return anything so when trying to use the property of $Parameter.DesignDefaultValue, the Alter method will fail.\n    }\n    else\n    {\n    \t# take the design\n    \t$DefaultValue = $Parameter.DesignDefaultValue\n    }\n    \n    # add variable with an initial value\n    $Environment.Variables.Add($ParameterName, $Parameter.DataType, $DefaultValue, $Parameter.Sensitive, $Parameter.Description)\n}\n#endregion\n\n#region Set-EnvironmentVariableValue\nFunction Set-EnvironmentVariableValue\n{\n     # define parameters\n    Param($Variable, $Parameter, $ParameterName)\n\n    # check to make sure variable value is available\n    if($OctopusParameters -and $OctopusParameters.ContainsKey($ParameterName))\n    {\n        # display \n        Write-Host \"- Updating environment variable $($ParameterName)\"\n\n    \t# set the variable value\n    \t$Variable.Value = $OctopusParameters[\"$($ParameterName)\"]\n    }\n    else\n    {\n    \t# warning\n    \tWrite-Host \"**- OctopusParameters collection is empty or $($ParameterName) not in the collection -**\"\n    }\n    \n    # Set reference\n    $Parameter.Set([Microsoft.SqlServer.Management.IntegrationServices.ParameterInfo+ParameterValueType]::Referenced, \"$($ParameterName)\")\n}\n#endregion\n\n# Define PowerShell Modules path\n$LocalModules = (New-Item \"$PSScriptRoot\\Modules\" -ItemType Directory -Force).FullName\n$env:PSModulePath = \"$LocalModules;$env:PSModulePath\"\n\n#region Dependent assemblies\nLoad-SqlServerAssmblies    \n\n#endregion\n\n# Store the IntegrationServices Assembly namespace to avoid typing it every time\n$ISNamespace = \"Microsoft.SqlServer.Management.IntegrationServices\"\n\n#endregion\n\n#region Main\n\n# C:\\Program Files (x86)\\Microsoft SQL Server Management Studio 19\\Common7\\IDE\\Microsoft.SqlServer.Diagnostics.STrace.dll\n$sqlTraceDll = [System.Reflection.Assembly]::LoadFrom(\"C:\\Program Files (x86)\\Microsoft SQL Server Management Studio 19\\Common7\\IDE\\Microsoft.SqlServer.Diagnostics.STrace.dll\")\n$onAssemblyResolveEventHandler = [System.ResolveEventHandler] {\n  param($sender, $e)\n  \n  if ($e.Name.Contains(\"STrace\")) {\n    return $sqlTraceDll\n  }\n  foreach ($assmembly in [System.AppDomain]::CurrentDomain.GetAssemblies()) {\n   if ($assembly.FullName -eq $e.Name) {\n    return $assembly\n   }\n  }\n  \n  return $null\n}\n\n[System.AppDomain]::CurrentDomain.add_AssemblyResolve($onAssemblyResolveEventHandler)\n\ntry\n{   \n    # ensure all boolean variables are true booleans\n    $EnableCLR = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.EnableCLR'])\")\n    $UseEnvironment = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.UseEnvironment'])\")\n    $ReferenceProjectParametersToEnvironmentVairables = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.ReferenceProjectParametersToEnvironmentVairables'])\")\n    \n    $ReferencePackageParametersToEnvironmentVairables = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.ReferencePackageParametersToEnvironmentVairables'])\")\n    $UseFullyQualifiedVariableNames = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.UseFullyQualifiedVariableNames'])\")\n    $SyncEnvironment = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.SyncEnvironment'])\")\n    # custom names for filtering out the excluded variables by design\n    $UseCustomFilter = [System.Convert]::ToBoolean(\"$($OctopusParameters['SSIS.Template.UseCustomFilter'])\")\n    $CustomFilter = [System.Convert]::ToString(\"$($OctopusParameters['SSIS.Template.CustomFilter'])\")\n    # list of variables names to keep in target environment\n    $VariablesToPreserveInEnvironment = @()\n    $ssisPackageId = $OctopusParameters['SSIS.Template.ssisPackageId']\n        \n\t# Get the extracted path\n\t$DeployedPath = $OctopusParameters[\"Octopus.Action.Package[$ssisPackageId].ExtractedPath\"]\n    \n\t# Get all .ispac files from the deployed path\n\t$IsPacFiles = Get-ChildItem -Recurse -Path $DeployedPath | Where {$_.Extension.ToLower() -eq \".ispac\"}\n\n\t# display number of files\n\tWrite-Host \"$($IsPacFiles.Count) .ispac file(s) found.\"\n\n\tWrite-Host \"Connecting to server ...\"\n\n\t# Create a connection to the server\n    $sqlConnectionString = \"Data Source=$($OctopusParameters['SSIS.Template.ServerName']);Initial Catalog=SSISDB;TrustServerCertificate=True;\"\n    \n    if (![string]::IsNullOrEmpty($OctopusParameters['SSIS.Template.sqlAccountUsername']) -and ![string]::IsNullOrEmpty($OctopusParameters['SSIS.Template.sqlAccountPassword']))\n    {\n    \t# Add username and password to connection string\n        #$sqlConnectionString += \"User ID=$($OctopusParameters['SSIS.Template.sqlAccountUsername']); Password=$($OctopusParameters['SSIS.Template.sqlAccountPassword']);\"\n        $sqlConnectionString += \"User ID=sa; Password=GrassGrows2!;\"\n    }\n    else\n    {\n    \t# Use integrated\n        $sqlConnectionString += \"Integrated Security=SSPI;\"\n    }\n    \n    Write-Host \"It is $sqlConnectionString\"\n    # Create new connection object with connection string\n    #$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $sqlConnectionString\n    $sqlConnection = New-Object Microsoft.Data.SqlClient.SqlConnection $sqlConnectionString\n    $sqlStoreConnection = New-Object Microsoft.SqlServer.Management.Sdk.Sfc.SqlStoreConnection $sqlConnection\n    \n\t# create integration services object\n\t#$integrationServices = New-Object \"$ISNamespace.IntegrationServices\" $sqlConnection\n    $integrationServices = New-Object \"$ISNamespace.IntegrationServices\" $sqlStoreConnection\n    \n\t# get reference to the catalog\n\tWrite-Host \"Getting reference to catalog $($OctopusParameters['SSIS.Template.CataLogName'])\"\n\t$Catalog = Get-Catalog -CatalogName $OctopusParameters['SSIS.Template.CataLogName']\n\n\t# get folder reference\n\t$Folder = Get-Folder -FolderName $OctopusParameters['SSIS.Template.FolderName'] -Catalog $Catalog\n\n\t# loop through ispac files\n\tforeach($IsPacFile in $IsPacFiles)\n\t{\n\t\t# read project file\n\t\t$ProjectFile = [System.IO.File]::ReadAllBytes($IsPacFile.FullName)\n        $ProjectName = $IsPacFile.Name.SubString(0, $IsPacFile.Name.LastIndexOf(\".\"))\n\n\t\t# deploy project\n\t\tWrite-Host \"Deploying project $($IsPacFile.Name)...\"\n\t\t$Folder.DeployProject($ProjectName, $ProjectFile) | Out-Null\n\n\t\t# get reference to deployed project\n\t\t$Project = $Folder.Projects[$ProjectName]\n\n\t\t# check to see if they want to use environments\n\t\tif($UseEnvironment)\n\t\t{\n\t\t\t# get environment reference\n\t\t\t$Environment = Get-Environment -Folder $Folder -EnvironmentName $OctopusParameters['SSIS.Template.EnvironmentName']\n\n\t\t\t# set environment reference\n\t\t\tSet-EnvironmentReference -Project $Project -Environment $Environment -Folder $Folder\n\n\t\t\t# check to see if the user wants to convert project parameters to environment variables\n\t\t\tif($ReferenceProjectParametersToEnvironmentVairables)\n\t\t\t{\n\t\t\t\t# set environment variables\n\t\t\t\tWrite-Host \"Referencing Project Parameters to Environment Variables...\"\n\t\t\t\t$VariablesToPreserveInEnvironment += Set-ProjectParametersToEnvironmentVariablesReference -Project $Project -Environment $Environment\n\t\t\t}\n\n\t\t\t# check to see if the user wants to convert the package parameters to environment variables\n\t\t\tif($ReferencePackageParametersToEnvironmentVairables)\n\t\t\t{\n\t\t\t\t# set package variables\n\t\t\t\tWrite-Host \"Referencing Package Parameters to Environment Variables...\"\n\t\t\t\t$VariablesToPreserveInEnvironment += Set-PackageVariablesToEnvironmentVariablesReference -Project $Project -Environment $Environment\n\t\t\t}\n            \n            # Removes all unused variables from the environment\n            if ($SyncEnvironment)\n            {\n                Write-Host \"Sync package environment variables...\"\n                Sync-EnvironmentVariables -Environment $Environment -VariablesToPreserveInEnvironment $VariablesToPreserveInEnvironment\n            }\n\t\t}\n\t}\n}\n\nfinally\n{\n\t# check to make sure sqlconnection isn't null\n\tif($sqlConnection)\n\t{\n\t\t# check state of sqlconnection\n\t\tif($sqlConnection.State -eq [System.Data.ConnectionState]::Open)\n\t\t{\n\t\t\t# close the connection\n\t\t\t$sqlConnection.Close()\n\t\t}\n\n\t\t# cleanup\n\t\t$sqlConnection.Dispose()\n\t}\n    \n    [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($onAssemblyResolveEventHandler)\n}\n#endregion\n",
    "Octopus.Action.Script.ScriptSource": "Inline"
  },
  "Parameters": [
    {
      "Id": "0289cdc8-16b6-41f0-a1e2-b22c946dd5a6",
      "Name": "SSIS.Template.ServerName",
      "Label": "Database server name (\\instance)",
      "HelpText": "Name of the SQL Server you are deploying to.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "21537935-5eac-4312-ad81-810ab30ac19a",
      "Name": "SSIS.Template.sqlAccountUsername",
      "Label": "SQL Authentication Username",
      "HelpText": "(Optional) Username of the SQL Authentication account.  Use this approach when deploying to Azure Databases with SSIS configured.  If SQL Authentication Username and Password are blank, Integrated Authentication is used.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "a1003ea0-5ece-4cfa-9692-70f5b4339520",
      "Name": "SSIS.Template.sqlAccountPassword",
      "Label": "SQL Authentication Password",
      "HelpText": "(Optional) Password of the SQL Authentication account.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "d5b54767-602a-433b-ad2c-6a8d51e04f7b",
      "Name": "SSIS.Template.EnableCLR",
      "Label": "Enable SQL CLR",
      "HelpText": "This will reconfigure SQL Server to enable the SQL CLR.  It is highly recommended that this be previously authorized by your Database Administrator.",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "948a785a-6b8d-4bbf-bb73-1b9223ebdba4",
      "Name": "SSIS.Template.CatalogName",
      "Label": "Catalog name",
      "HelpText": "Name of the catalog to create in Integration Services Catalogs on SQL Server.  When using the GUI, this value gets hardcoded to SSISDB and cannot be changed.  It is recommended that you do not change the default value.",
      "DefaultValue": "SSISDB",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "01341f21-e292-4e20-99a7-5124133684de",
      "Name": "SSIS.Template.CatalogPwd",
      "Label": "Catalog password",
      "HelpText": "Password to the Integration Services Catalog.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "e13d1aee-cd1d-4074-a404-3ed166836cfb",
      "Name": "SSIS.Template.FolderName",
      "Label": "Folder name",
      "HelpText": "Name of the folder to use within the Integration Services Catalog",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "7ba3857d-4a2c-405c-b1be-6a39ee3eb8e2",
      "Name": "SSIS.Template.UseEnvironment",
      "Label": "Use environment",
      "HelpText": "This will make a project reference to the defined environment.",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "6c5bcfee-1321-4a13-8348-e9e62f1bef77",
      "Name": "SSIS.Template.EnvironmentName",
      "Label": "Environment name",
      "HelpText": "Name of the environment to reference the project to. If the environment doesn't exist, it will create it.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "6644ad68-0bbb-440d-9ea4-a915767b9fd6",
      "Name": "SSIS.Template.ReferenceProjectParametersToEnvironmentVairables",
      "Label": "Reference project parameters to environment variables",
      "HelpText": "Checking this box will make Project Parameters reference Environment Variables.  If the Environment Variable doesn't exist, it will create it.  This expects that an Octopus variable of the same name exists.",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "ee42deb7-fe88-4ce7-b113-c311b98d0350",
      "Name": "SSIS.Template.ReferencePackageParametersToEnvironmentVairables",
      "Label": "Reference package parameters to environment variables",
      "HelpText": "Checking this box will make Package Parameters reference Environment Variables.  If the Environment Variable doesn't exist, it will create it.  This expects than an Octopus variable of the same name exists.",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "59256775-760b-45bf-b418-68caeb3c486d",
      "Name": "SSIS.Template.UseFullyQualifiedVariableNames",
      "Label": "Use Fully Qualified Variable Names",
      "HelpText": "When true the package variables names must be represented in `dtsx_name_without_extension.variable_name`",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "5e5a4494-320b-418f-844d-81f90ca1a1ea",
      "Name": "SSIS.Template.UseCustomFilter",
      "Label": "Use Custom Filter for connection manager properties",
      "HelpText": "Custom filter should contain the regular expression for ignoring properties when setting will occur during the auto-mapping",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "d9d5f32c-afc0-47cf-8334-a346876f3809",
      "Name": "SSIS.Template.CustomFilter",
      "Label": "Custom Filter for connection manager properties",
      "HelpText": "Regular expression for filtering out the connection manager properties during the auto-mapping process. This string is used when `UseCustomFilter` is set to true",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "e793c89d-9c63-4dfb-b363-08b127fa1da5",
      "Name": "SSIS.Template.SyncEnvironment",
      "Label": "Clean obsolete variables from environment",
      "HelpText": "When `true` synchronizes the environment:\n- Removes obsolete variables\n- Removes renamed variables\n- Replaces values of valid variables (also when `false`)",
      "DefaultValue": "False",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "fc1b202d-e670-4a8e-931e-b25d9adac98e",
      "Name": "SSIS.Template.ssisPackageId",
      "Label": "Package Id",
      "HelpText": "Id of the package to deploy, used to support deployment with Workers.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Package"
      }
    }
  ],
  "StepPackageId": "Octopus.Script",
  "$Meta": {
    "ExportedAt": "2023-10-23T14:36:46.455Z",
    "OctopusVersion": "2023.3.13118",
    "Type": "ActionTemplate"
  },
  "LastModifiedBy": "Your GitHub Username",
  "Category": "other"
}
twerthi commented 12 months ago

@grexican Did that version work for you?

twerthi commented 11 months ago

@grexican Did that customized version work for you?

twerthi commented 9 months ago

Closing due to inactivity.