functions/library/init.ps1

param(
  [System.IO.DirectoryInfo] $StagingDir,
  [System.String]$Template = $null,
  [System.String]$Method = $null,
  [System.String]$Scope = $null,
  [System.String]$Pipeline = $null,
  [switch]$PipelineOnly
)

<#
////////////////////////////////////////////////////////////////////////////////
//// Deploy Method
 
#>


$deploymentMethods = [ordered]@{
  'Normal Deployment' = 'deploy'
  'Deployment Stack'  = 'stack'
}

if ([System.String]::IsNullOrEmpty($Method)) {
  Write-Host -ForegroundColor Magenta "`nSelect deployment method: "
  $Method = Select-UtilsUserOption -Options $deploymentMethods.Keys
} 

$selectedMethod = $deploymentMethods[$Method]

<#
////////////////////////////////////////////////////////////////////////////////
//// Select Deployment Scope
 
#>


$deploymentScopes = [ordered]@{
  'Resource Group' = 'resource_group'
  'Subscription'   = 'subscription'
  # 'Management Group' = 'management'
  # 'Tenant Level' = 'tenant'
}

if ([System.String]::IsNullOrEmpty($Scope)) {
  Write-Host -ForegroundColor Magenta "`nSelect deployment scope: "
  $Scope = Select-UtilsUserOption -Options $deploymentScopes.Keys
} 

$selectedScope = $deploymentScopes[$Scope]

<#
////////////////////////////////////////////////////////////////////////////////
//// Select Deployment Script
 
#>


# $deploymentScripts = [ordered]@{
# 'PowerShell' = 'pwsh'
# 'Azure CLI' = 'cli'
# }

# if ([System.String]::IsNullOrEmpty($Script)) {
# Write-Host -ForegroundColor Magenta "`nSelect deployment Script: "
# $Script = Select-UtilsUserOption -Options $deploymentScripts.Keys
# }

$selectedScript = 'pwsh'  # $deploymentScripts[$Script]

<#
////////////////////////////////////////////////////////////////////////////////
//// Select Deployment Pipeline
 
#>


$deploymentPipelines = [ordered]@{
  'Azure DevOps' = @{
    source = "devops_pipelines"
    target = '.devops'
  }
  'Github'       = @{
    source = "github_workflows"
    target = '.github'
  }
}

if ([System.String]::IsNullOrEmpty($Pipeline)) {
  Write-Host -ForegroundColor Magenta "`nSelect Pipeline Template: "
  $Pipeline = Select-UtilsUserOption -Options $deploymentPipelines.Keys
}

$selectedPipeline = $deploymentPipelines[$Pipeline]

# This is were all pipelines will be copied to
$targetPipelineFolder = [System.IO.DirectoryInfo]::new("$StagingDir/$($selectedPipeline.target)")
$targetPipelineFolder.Create()

<#
////////////////////////////////////////////////////////////////////////////////
//// Write to Write File
 
#>


# Where all template files are located.
$templateFiles = Get-Item -Path "$StagingDir/_selections"

if ($Template -EQ 'deployment') {
  $bicepMainTemplate = Get-Item -Path "$templateFiles/bicep/*.bicep.$selectedScope"
  $deployScriptTemplate = Get-Item -Path "$templateFiles/deploy/*.$selectedScope.$selectedMethod"

  $bicepMainFilePath = "$StagingDir/$($bicepMainTemplate.Name)".Replace(".$selectedScope", "")
  $deployScriptFilePath = "$StagingDir/$($deployScriptTemplate.Name)".Replace(".$selectedScope.$selectedMethod", "")

  $null = $deployScriptTemplate.CopyTo($deployScriptFilePath)
  $null = $bicepMainTemplate.CopyTo($bicepMainFilePath)
}

# Pipeline files

$pipelineTemplateFolder = Resolve-Path -Path "$templateFiles/$($selectedPipeline.source)"
$pipelineTemplates = Get-ChildItem -Path $pipelineTemplateFolder -Recurse -Depth 5

foreach ($tmpl in $pipelineTemplates) {
  if (
    $tmpl.Name -NOTLIKE "*.yaml" -AND
    $tmpl.Name -NOTLIKE "*.yaml.$selectedMethod" -AND 
    $tmpl.Name -NOTLIKE "*.yaml.$selectedScope" -AND 
    $tmpl.Name -NOTLIKE "*.yaml.$selectedMethod.$selectedScript" -AND 
    $tmpl.Name -NOTLIKE "*.yaml.$selectedScope.$selectedMethod"
  ) {
    continue
  }

  $relativePath = $tmpl.FullName.Replace($pipelineTemplateFolder, "") 
  $relativePath = $relativePath -split ".yaml"
  # Removes all meta identifiers after .yaml, like resource_group, deploy, etc.
  $relativePath = $relativePath[0] + ".yaml" 

  $pipelineFilePath = "$targetPipelineFolder/$relativePath"
  $directory = [System.IO.FileInfo]::new($pipelineFilePath).Directory

  if (-NOT $directory.Exists) {
    $null = New-Item -ItemType Directory -Path $directory.FullName -ErrorAction SilentlyContinue
  }

  $null = $tmpl.CopyTo($pipelineFilePath)
}


# Delete all templates in the staging directory and only keep selected.
# The selected ones were copied from %templateFiles to $pipelineFilePath at this point
[System.IO.DirectoryInfo]::new($templateFiles).Delete($true)

# Remove all non-pipeline files if -PipelineOnly is set.
if ($PipelineOnly.IsPresent) {
  $items = Get-ChildItem -Path $StagingDir
  $items += Get-ChildItem -Path $StagingDir -Hidden
  $items
  | Where-Object -Property Name -INE '.github'
  | Where-Object -Property Name -INE '.devops'
  | Remove-Item -Recurse -Force
}
else {

  $moduleDir = Get-Item -Path "$StagingDir/modules"

  if ($Template -EQ 'deployment') {
    $childItems = Get-ChildItem -Path $moduleDir.FullName -File -Recurse

    $childItems | Where-Object -Property FullName -LIKE "*version.json"
    | Remove-Item -Recurse -Force -ErrorAction Continue

    $childItems | Where-Object -Property FullName -LIKE "*schema*module.bicep"
    | Remove-Item -Recurse -Force -ErrorAction Continue

    
    $childItems = Get-ChildItem -Path $moduleDir.FullName -Directory -Recurse

    $childItems | Where-Object -Property FullName -LIKE "*schema*defaults*"
    | Remove-Item -Recurse -Force -ErrorAction Continue

    $childItems | Where-Object -Property FullName -LIKE "*example*"
    | Remove-Item -Recurse -Force -ErrorAction Continue
  }

}


Write-Host -ForegroundColor Magenta "`nPlease, Adjust the following in your templates:"

if ($selectedScope -IEQ 'subscription') {
  Write-Host -ForegroundColor Magenta "`n"
  Write-Host -ForegroundColor Magenta "Deployment location. Default is 'germanywestcentral'"
}
elseif ($selectedScope -IEQ 'resource_group') {
  Write-Host -ForegroundColor Magenta "`n"
  Write-Host -ForegroundColor Magenta "Resource group. Default is 'rg-sample-<environment>'"
}

# Provide instructions for Azure DevOps and Github pipelines
if ($Pipeline -IEQ 'Azure DevOps') {
  Write-Host -ForegroundColor Magenta "Service Connection in .devops/deploy.infrastructure.yaml"
  Write-Host -ForegroundColor Magenta "Create the necessary Azure DevOps environments and optionally add approvals to them"
}

if ($Pipeline -EQ 'Github') {
  Write-Host -ForegroundColor Magenta "`n"
  Write-Host -ForegroundColor Magenta @"
 
      Define following Secrets either:
      - in the environment
      - or repository scoped
      
      When Auth_type: OIDC (Workload Identity Federation)
      AZURE_AUTH = {
        "auth_type": "OIDC",
        "tenantId": "00000000-0000-0000-0000-000000000000",
        "subscriptionId": "00000000-0000-0000-0000-000000000000",
        "clientId": "00000000-0000-0000-0000-000000000000"
      }
      Either:
      - Federated Credential on User Managed Identity: https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust-user-assigned-managed-identity?pivots=identity-wif-mi-methods-azp#configure-a-federated-identity-credential-on-a-user-assigned-managed-identity
      - Federated Credential on App Registration: https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#github-actions
     
      
      When Auth_type: ClientSecret
      AZURE_AUTH = {
        "auth_type": "ClientSecret",
        "tenantId": "00000000-0000-0000-0000-000000000000",
        "subscriptionId": "00000000-0000-0000-0000-000000000000",
        "clientId": "00000000-0000-0000-0000-000000000000",
        "objectId": "00000000-0000-0000-0000-000000000000",
        "clientSecret": "00000000-0000-0000-0000-000000000000"
     }
"@

}