Last active
September 30, 2022 14:30
-
-
Save techthoughts2/d5d994d6d2d336b4ad397fc5f99c0f1a to your computer and use it in GitHub Desktop.
## Synopsis This helper script can be used to bootstrap a CDK project for deploying PowerShell Lambdas using the custom PowerShell Runtime via Lambda Layers. ## Description - Quickly bootstraps a CDK project for deploying lambdas using the custom
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region settings | |
#! Enter all required modules you want to bootstrap for use in your PowerShell lambda layers | |
$requiredModules = @( | |
@{ | |
ModuleName = 'AWS.Tools.Common' | |
ModuleVersion = '4.1.175' | |
}, | |
@{ | |
ModuleName = 'PoshGram' | |
ModuleVersion = '2.2.2' | |
} | |
) | |
#endregion | |
#region example notes | |
<# | |
# 0 - (Optional) create a basic CDK project if you don't already have one | |
mkdir my-cdk-project | |
cd my-cdk-project | |
cdk init app --language typescript | |
# 1 - edit settings section of cdk_pwsh_runtime_bootstrap.ps1 to include all Required Modules for your project | |
# 2 - Load cdk_pwsh_runtime_bootstrap.ps1 into memory | |
. ./cdk_pwsh_runtime_bootstrap.ps1 | |
# 3 - Bootstrap CDK project for using custom PowerShell Runtime for AWS Lambda | |
# you can remove the HelloWorld switch if you don't need a sample lambda created | |
Invoke-BootStrapCDKProject -RequiredModules $requiredModules -HelloWorld | |
# 4 - (Optional) Get CDK typescript example snippet to paste into your CDK construct | |
# basic CDK snippet examples to incorporate into existing Construct: | |
Get-CDKPwshLayerSnippet -RequiredModules $requiredModules | Set-Clipboard | |
# full Construct example: | |
Get-CDKPwshLayerSnippet -RequiredModules $requiredModules -FullConstruct | Set-Clipboard | |
# 5 - Deploy your CDK project | |
cdk deploy --profile profilename | |
#> | |
#endregion | |
#region supporting functions | |
function Invoke-GetPowerShell { | |
<# | |
.SYNOPSIS | |
Retrieves PowerShell from Github | |
.DESCRIPTION | |
Downloads specified version of PowerShell from Github | |
Extracts PowerShell tar to specified path in CDK project | |
Removes temporary downloaded PowerShell tar | |
.EXAMPLE | |
Invoke-GetPowerShell -PwshVersion '7.2.6' -PwshArchitecture 'x64' | |
Downloads and extracts the specified version of PowerShell from Github and extracts to the default lambda layer path in the CDK project. | |
.PARAMETER PwshVersion | |
Version of PowerShell to download | |
.PARAMETER PwshArchitecture | |
Architecture version of PowerShell to download | |
.PARAMETER Path | |
Path in your CDK project where you want to store your Lambda layers | |
.PARAMETER Force | |
Skip Confirmation | |
.NOTES | |
Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ | |
.COMPONENT | |
cdk_pwsh_runtime_bootstrap.ps1 | |
.LINK | |
https://aws.amazon.com/blogs/compute/introducing-the-powershell-custom-runtime-for-aws-lambda/ | |
.LINK | |
https://github.com/awslabs/aws-lambda-powershell-runtime | |
#> | |
[CmdletBinding(ConfirmImpact = 'Low', | |
SupportsShouldProcess = $true)] | |
param( | |
[Parameter(Mandatory = $true, | |
HelpMessage = 'Version of PowerShell to download')] | |
[string] | |
$PwshVersion, | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Architecture version of PowerShell to download')] | |
[ValidateSet('x64', 'arm64')] | |
[string] | |
$PwshArchitecture = 'x64', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Path in your CDK project where you want to store your Lambda layers')] | |
[string] | |
$Path = 'src/lambda/layers/', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Skip confirmation')] | |
[switch]$Force | |
) | |
begin { | |
if (-not $PSBoundParameters.ContainsKey('Verbose')) { | |
$VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('Confirm')) { | |
$ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('WhatIf')) { | |
$WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') | |
} | |
Write-Verbose -Message ('[{0}] Confirm={1} ConfirmPreference={2} WhatIf={3} WhatIfPreference={4}' -f $MyInvocation.MyCommand, $Confirm, $ConfirmPreference, $WhatIf, $WhatIfPreference) | |
} #begin | |
process { | |
$runTimePath = '{0}/pwsh-runtime/powershell' -f $Path | |
if ($Force -or $PSCmdlet.ShouldProcess('Download an extract PowerShell to {0}' -f $runTimePath)) { | |
Write-Verbose -Message ('[{0}] Reached command' -f $MyInvocation.MyCommand) | |
Write-Verbose -Message ('Testing if path present: {0}' -f $runTimePath) | |
if (-not(Test-Path $runTimePath)) { | |
Write-Verbose -Message 'Path not found. Creating directory.' | |
$newItemSplat = @{ | |
ItemType = 'Directory' | |
Force = $true | |
Path = '{0}\pwsh-runtime\powershell' -f $Path | |
} | |
New-Item @newItemSplat | Out-Null | |
} | |
Write-Verbose -Message ('Downloading Powershell for PwshRuntimeLayer to: {0}' -f $Path) | |
$invokeWebRequestSplat = @{ | |
Uri = 'https://github.com/PowerShell/PowerShell/releases/download/v{0}/powershell-{1}-linux-{2}.tar.gz' -f $PwshVersion, $PwshVersion, $PwshArchitecture | |
OutFile = '{0}\powershell-{1}-{2}.tar.gz' -f $Path, $PwshVersion, $PwshArchitecture | |
} | |
Invoke-WebRequest @invokeWebRequestSplat | |
Write-Verbose -Message ('Extracting Powershell {0} for {1} to: {2}/powershell' -f $PwshVersion, $PwshArchitecture, $Path) | |
tar zxf $Path/powershell-$PwshVersion-$PwshArchitecture.tar.gz -C $Path/pwsh-runtime/powershell | |
Write-Verbose -Message 'Deleting PowerShell tar download' | |
$removeItemSplat = @{ | |
Path = '{0}/powershell-{1}-{2}.tar.gz' -f $Path, $PwshVersion, $PwshArchitecture | |
Force = $true | |
} | |
Remove-Item @removeItemSplat | |
} #if_shouldprocess | |
} #process | |
} #Invoke-GetPowerShell | |
function Test-PowerShellRuntimePresent { | |
<# | |
.SYNOPSIS | |
Evaluates if specified version of PowerShell has already been bootstrapped for the CDK project | |
.DESCRIPTION | |
Evaluates if specified version of PowerShell is already bootstrapped in the CDK project | |
by inspecting the manifest to determine if it is a match. | |
.EXAMPLE | |
Test-PwshRuntimePresent -PowerShellVersion 7.2.6 | |
Evaluates if the specified version of PowerShell is already bootstrapped at the default layer path location of the CDK project | |
.PARAMETER PwshVersion | |
Version of PowerShell to download | |
.PARAMETER Path | |
Path in your CDK project where you want to store your Lambda layers | |
.OUTPUTS | |
System.Boolean | |
.NOTES | |
Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ | |
.COMPONENT | |
cdk_pwsh_runtime_bootstrap.ps1 | |
#> | |
[CmdletBinding()] | |
[OutputType([bool])] | |
param( | |
[Parameter(Mandatory = $true, | |
HelpMessage = 'Version of PowerShell to download')] | |
[string] | |
$PowerShellVersion, | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Path in your CDK project where you want to store your Lambda layers')] | |
[string] | |
$Path = 'src/lambda/layers/' | |
) | |
$result = $false #assume the worst | |
[version]$desiredVersion = $PowerShellVersion | |
$manifestPath = '{0}/pwsh-runtime\powershell\_manifest\spdx_2.2\manifest.spdx.json' -f $Path | |
Write-Verbose -Message ('Testing if manifest is present at {0}' -f $manifestPath) | |
if (Test-Path -Path $manifestPath) { | |
Write-Verbose -Message 'Manifest file found. Evaluating PowerShell version...' | |
$manifestJSON = Get-Content -Path $manifestPath -Raw | ConvertFrom-Json | |
$psInfo = $manifestJSON.packages | Where-Object { $_.name -eq 'PowerShell Linux' } | |
[version]$pwshVersion = $psInfo.versionInfo | |
if ($pwshVersion -eq $desiredVersion) { | |
Write-Verbose -Message ('MATCH. Desired Version: {0} | PowerShell Version: {1}' -f $PowerShellVersion, $psInfo.versionInfo) | |
$result = $true | |
} | |
else { | |
Write-Verbose -Message ('NO MATCH. Desired Version: {0} | PowerShell Version: {1}' -f $PowerShellVersion, $psInfo.versionInfo) | |
} | |
} | |
else { | |
Write-Verbose -Message 'Manifest not found' | |
} | |
return $result | |
} #Test-PowerShellRuntimePresent | |
function Invoke-GetAWSLambdaPowerShellRuntime { | |
<# | |
.SYNOPSIS | |
Retrieves required AWS Lambda PowerShell runtime files to bootstrap CDK lambda layers | |
.DESCRIPTION | |
Downloads the aws-lambda-powershell-runtime zip from GitHub | |
Extracts the repo zip | |
Copies the required AWS Lambda PowerShell runtime files needed for PowerShell lambda layers | |
Removes the repo zip | |
.EXAMPLE | |
Invoke-GetAWSLambdaPowerShellRuntime | |
Downloads and extracts the AWS Lambda PowerShell runtime files to the default lambda layer path in the CDK project. | |
.PARAMETER Path | |
Path in your CDK project where you want to store your Lambda layers | |
.PARAMETER Force | |
Skip Confirmation | |
.NOTES | |
Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ | |
.COMPONENT | |
cdk_pwsh_runtime_bootstrap.ps1 | |
.LINK | |
https://aws.amazon.com/blogs/compute/introducing-the-powershell-custom-runtime-for-aws-lambda/ | |
.LINK | |
https://github.com/awslabs/aws-lambda-powershell-runtime | |
#> | |
[CmdletBinding(ConfirmImpact = 'Low', | |
SupportsShouldProcess = $true)] | |
param( | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Path in your CDK project where you want to store your Lambda layers')] | |
[string] | |
$Path = 'src/lambda/layers/', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Skip confirmation')] | |
[switch]$Force | |
) | |
begin { | |
if (-not $PSBoundParameters.ContainsKey('Verbose')) { | |
$VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('Confirm')) { | |
$ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('WhatIf')) { | |
$WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') | |
} | |
Write-Verbose -Message ('[{0}] Confirm={1} ConfirmPreference={2} WhatIf={3} WhatIfPreference={4}' -f $MyInvocation.MyCommand, $Confirm, $ConfirmPreference, $WhatIf, $WhatIfPreference) | |
} #begin | |
process { | |
$tempDir = '{0}pwsh-runtime/temp' -f $Path | |
$zipFile = '{0}runtime.zip' -f $tempDir | |
if ($Force -or $PSCmdlet.ShouldProcess('Download and extract pwsh runtime to {0}' -f $zipFile)) { | |
Write-Verbose -Message ('[{0}] Reached command' -f $MyInvocation.MyCommand) | |
Write-Verbose -Message ('Verifying if temp dir is present: {0}' -f $tempDir) | |
if (-not(Test-Path $tempDir)) { | |
Write-Verbose -Message 'Creating temp dir...' | |
New-Item -ItemType Directory -Force -Path $tempDir | Out-Null | |
} | |
else { | |
Write-Verbose 'dir Verified.' | |
} | |
Write-Verbose -Message ('Downloading aws-lambda-powershell-runtime zip to {0}' -f $zipFile) | |
$repoZIP = 'https://github.com/awslabs/aws-lambda-powershell-runtime/archive/refs/heads/main.zip' | |
$invokeWebRequestSplat = @{ | |
Uri = $repoZIP | |
OutFile = $zipFile | |
ErrorAction = 'Stop' | |
} | |
Invoke-WebRequest @invokeWebRequestSplat | |
Write-Verbose 'Expanding aws-lambda-powershell-runtime...' | |
$expandArchiveSplat = @{ | |
Path = $zipFile | |
DestinationPath = $tempDir | |
Verbose = $false | |
} | |
Expand-Archive @expandArchiveSplat | |
Write-Verbose ('Copying pwsh-runtime to layer path {0}' -f $Path) | |
$copyItemSplat = @{ | |
Path = '{0}/aws-lambda-powershell-runtime-main/powershell-runtime/pwsh-runtime/*' -f $tempDir | |
Destination = '{0}/pwsh-runtime' -f $Path | |
Recurse = $true | |
Force = $true | |
} | |
Copy-Item @copyItemSplat | |
Write-Verbose -Message 'Removing temp directory and files...' | |
$removeItemSplat = @{ | |
Path = $tempDir | |
Recurse = $true | |
Force = $true | |
} | |
Remove-Item @removeItemSplat | |
} #if_shouldprocess | |
} #process | |
} #Invoke-GetAWSLambdaPowerShellRuntime | |
function Invoke-GetRequiredModule { | |
<# | |
.SYNOPSIS | |
Downloads all indicated PowerShell modules to the provided Lambda layers path location in the CDK project | |
.DESCRIPTION | |
Downloads all indicated PowerShell modules from the PSGallery to the provided Lambda layers path location in the CDK project using Save-Module | |
.EXAMPLE | |
$requiredModules = @( | |
@{ | |
ModuleName = 'AWS.Tools.Common' | |
ModuleVersion = '4.1.175' | |
}, | |
@{ | |
ModuleName = 'PoshGram' | |
ModuleVersion = '2.2.2' | |
} | |
) | |
Invoke-GetRequiredModule -RequiredModules $RequiredModules | |
Downloads all indicated PowerShell modules to the default lambda layer path in the CDK project. | |
.PARAMETER RequiredModules | |
Array of Hashtable(s) containing ModuleName and ModuleVersion for each required module | |
.PARAMETER Path | |
Path in your CDK project where you want to store your Lambda layers | |
.PARAMETER Force | |
Skip Confirmation | |
.NOTES | |
Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ | |
.COMPONENT | |
cdk_pwsh_runtime_bootstrap.ps1 | |
#> | |
[CmdletBinding(ConfirmImpact = 'Low', | |
SupportsShouldProcess = $true)] | |
param( | |
[Parameter(Mandatory = $true, | |
HelpMessage = 'Array of Hashtable(s) containing ModuleName and ModuleVersion for each required module')] | |
[array] | |
$RequiredModules, | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Path in your CDK project where you want to store your Lambda layers')] | |
[string] | |
$Path = 'src/lambda/layers/', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Skip confirmation')] | |
[switch]$Force | |
) | |
begin { | |
if (-not $PSBoundParameters.ContainsKey('Verbose')) { | |
$VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('Confirm')) { | |
$ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('WhatIf')) { | |
$WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') | |
} | |
Write-Verbose -Message ('[{0}] Confirm={1} ConfirmPreference={2} WhatIf={3} WhatIfPreference={4}' -f $MyInvocation.MyCommand, $Confirm, $ConfirmPreference, $WhatIf, $WhatIfPreference) | |
} #begin | |
process { | |
if ($Force -or $PSCmdlet.ShouldProcess('Bootstrap CDK project lambda layers with all specified PowerShell modules.')) { | |
Write-Verbose -Message ('[{0}] Reached command' -f $MyInvocation.MyCommand) | |
foreach ($module in $RequiredModules) { | |
$moduleCheck = Test-Path -Path ('{0}{1}/modules/{2}/{3}' -f $Path, $module.ModuleName, $module.ModuleName, $module.ModuleVersion) | |
if (-not $moduleCheck) { | |
$modulePath = '{0}{1}/modules' -f $Path, $module.ModuleName | |
if (-not (Test-Path $modulePath)) { | |
Write-Verbose -Message ('Creating {0}' -f $modulePath) | |
New-Item -ItemType Directory -Path $modulePath -Force | Out-Null | |
} | |
Write-Verbose -Message ('Saving {0} - v{1} from PSGallery to {2}' -f $module.ModuleName, $module.ModuleVersion, $modulePath ) | |
$saveModuleSplat = @{ | |
Name = $module.ModuleName | |
RequiredVersion = $module.ModuleVersion | |
Repository = 'PSGallery' | |
Path = $modulePath | |
ErrorAction = 'Stop' | |
} | |
Save-Module @saveModuleSplat | |
} | |
else { | |
Write-Verbose -Message ('{0} - v{1} already present. No action taken.' -f $module.ModuleName, $module.ModuleVersion) | |
} | |
} #foreach | |
} #if_shouldprocess | |
} #process | |
} #Invoke-GetRequiredModules | |
function Get-CDKPwshLayerSnippet { | |
<# | |
.SYNOPSIS | |
Generates basic CDK Typescript snippet examples for deploying lambda layers using PowerShell Runtime for AWS Lambda | |
.DESCRIPTION | |
Generates basic CDK Typescript snippet examples | |
One layer for the PowerShell Runtime for AWS Lambda | |
One layer for each provided PowerShell module | |
Basic Hello World lambda function with all included layers | |
.EXAMPLE | |
Get-CDKPwshLayerSnippet -RequiredModules $requiredModules | |
Generates basic CDK snippet examples to incorporate into existing Construct. | |
.EXAMPLE | |
Get-CDKPwshLayerSnippet -RequiredModules $requiredModules -FullConstruct | Set-Clipboard | |
Generates full CDK construct example and sends to clipboard. | |
.EXAMPLE | |
$requiredModules = @( | |
@{ | |
ModuleName = 'AWS.Tools.Common' | |
ModuleVersion = '4.1.175' | |
}, | |
@{ | |
ModuleName = 'PoshGram' | |
ModuleVersion = '2.2.2' | |
} | |
) | |
Get-CDKPwshLayerSnippet -RequiredModules $requiredModules | |
Generates basic CDK snippet examples to incorporate into existing Construct. | |
.EXAMPLE | |
$requiredModules = @( | |
@{ | |
ModuleName = 'AWS.Tools.Common' | |
ModuleVersion = '4.1.175' | |
}, | |
@{ | |
ModuleName = 'PoshGram' | |
ModuleVersion = '2.2.2' | |
} | |
) | |
Get-CDKPwshLayerSnippet -RequiredModules $requiredModules | Set-Clipboard | |
Generates basic CDK snippet examples to incorporate into existing Construct and sends to clipboard. | |
.PARAMETER RequiredModules | |
Array of Hashtable(s) containing ModuleName and ModuleVersion for each required module | |
.PARAMETER Path | |
Path in your CDK project where you want to store your Lambda layers | |
.PARAMETER FullConstruct | |
If specified returns a complete Construct example | |
.NOTES | |
Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ | |
This is just a snippet example helper function. | |
It is not a replacement for reading the CDK API reference. | |
.COMPONENT | |
cdk_pwsh_runtime_bootstrap.ps1 | |
.LINK | |
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.LayerVersion.html | |
.LINK | |
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html | |
#> | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory = $true, | |
HelpMessage = 'Array of Hashtable(s) containing ModuleName and ModuleVersion for each required module')] | |
[array] | |
$RequiredModules, | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Path in your CDK project where you want to store your Lambda layers')] | |
[string] | |
$Path = 'src/lambda/layers/', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'If specified returns a complete Construct example')] | |
[switch]$FullConstruct | |
) | |
$importsReminder = @' | |
//--add to imports-- | |
//import * as lambda from 'aws-cdk-lib/aws-lambda' | |
//------------------ | |
'@ | |
$powershellLayer = @' | |
// PowerShell layer | |
const powershellLayer = new lambda.LayerVersion(this, 'pwsh-layer', { | |
compatibleRuntimes: [ | |
lambda.Runtime.PROVIDED_AL2 | |
], | |
code: lambda.Code.fromAsset('replace_path/pwsh-runtime'), | |
description: 'PowerShell 7 runtime', | |
}); | |
'@ | |
$baseModuleLayer = @' | |
// replace_modulename layer | |
const replace_module1 = new lambda.LayerVersion(this, 'replace_modulename-layer', { | |
compatibleRuntimes: [ | |
lambda.Runtime.PROVIDED_AL2 | |
], | |
code: lambda.Code.fromAsset('replace_path/replace_modulename'), | |
description: 'replace_modulename', | |
}); | |
'@ | |
$lambdaFunction = @' | |
new lambda.Function(this, 'my-function', { | |
code: lambda.Code.fromAsset('src/lambda/PowerShellLambda/HelloWorld/'), // replace with path your lambda code | |
memorySize: 1024, | |
timeout: cdk.Duration.seconds(5), | |
runtime: lambda.Runtime.PROVIDED_AL2, | |
handler: 'HelloWorld.ps1::handler', // replace with your lambda script | |
layers: [replace_modulenames], | |
}); | |
'@ | |
$finalPowershellLayer = $powershellLayer.Replace('replace_path/', $Path) | |
$finalModuleLayers = New-Object System.Collections.Generic.List[string] | |
$moduleNames = New-Object System.Collections.Generic.List[string] | |
$moduleNames.Add('powershellLayer') | |
$i = 0 | |
foreach ($module in $RequiredModules) { | |
$moduleLayer = $baseModuleLayer.Replace('replace_modulename', $module.ModuleName) | |
$moduleLayer = $moduleLayer.Replace('replace_path/', $Path) | |
$moduleLayer = $moduleLayer.Replace('replace_module1', "layer$i") | |
$finalModuleLayers.Add($moduleLayer) | |
$moduleNames.Add("layer$i") | |
$i++ | |
} #foreach | |
$finalLambdaFunction = $lambdaFunction.Replace('replace_modulenames', ($moduleNames -join ',')) | |
if ($FullConstruct) { | |
$construct = @" | |
import * as cdk from 'aws-cdk-lib'; | |
import { Construct } from 'constructs'; | |
import * as lambda from 'aws-cdk-lib/aws-lambda' | |
// import * as sqs from 'aws-cdk-lib/aws-sqs'; | |
export class PSLambdaCDKTestStack extends cdk.Stack { | |
constructor(scope: Construct, id: string, props?: cdk.StackProps) { | |
super(scope, id, props); | |
// The code that defines your stack goes here | |
$finalPowershellLayer | |
$finalModuleLayers | |
$finalLambdaFunction | |
} | |
} | |
"@ | |
$finalSnippet = $construct | |
} | |
else { | |
$finalSnippet = $importsReminder + $finalPowershellLayer + $finalModuleLayers + $finalLambdaFunction | |
} | |
return $finalSnippet | |
} #Get-CDKPwshLayerSnippet | |
#endregion | |
#region main | |
function Invoke-BootStrapCDKProject { | |
<# | |
.SYNOPSIS | |
Bootstraps a CDK project for deploying lambdas with lambda layers using PowerShell Runtime for AWS Lambda | |
.DESCRIPTION | |
Quickly bootstraps a CDK project for deploying lambdas using the custom PowerShell runtime. | |
Retrieves PowerShell from Github | |
Retrieves required AWS Lambda PowerShell runtime files to bootstrap CDK lambda layers | |
Downloads all indicated PowerShell modules to the provided Lambda layers path location in the CDK project | |
If HelloWorld switch specified - scaffolds a basic HelloWorld PowerShell lambda | |
.EXAMPLE | |
Invoke-BootStrapCDKProject -RequiredModules $requiredModules | |
Bootstraps a CDK project with all components needed to deploy PowerShell lambdas using PowerShell custom runtime. | |
.EXAMPLE | |
$requiredModules = @( | |
@{ | |
ModuleName = 'AWS.Tools.Common' | |
ModuleVersion = '4.1.175' | |
}, | |
@{ | |
ModuleName = 'PoshGram' | |
ModuleVersion = '2.2.2' | |
} | |
) | |
Invoke-BootStrapCDKProject -RequiredModules $requiredModules -HelloWorld -Verbose | |
Bootstraps a CDK project with all components needed to deploy PowerShell lambdas using PowerShell custom runtime. | |
Also creates a basic HelloWorld lambda. | |
.EXAMPLE | |
$requiredModules = @( | |
@{ | |
ModuleName = 'AWS.Tools.Common' | |
ModuleVersion = '4.1.175' | |
} | |
) | |
Invoke-BootStrapCDKProject -CDKProjectPath 'C:\dev\cdkproject1' -PwshVersion '7.2.4' -PwshArchitecture x64 -RequiredModules $requiredModules -HelloWorld | |
Bootstraps a CDK project with all components needed to deploy PowerShell lambdas using PowerShell custom runtime. | |
Also creates a basic HelloWorld lambda. | |
.PARAMETER CDKProjectPath | |
File path to the root of CDK project | |
.PARAMETER PwshVersion | |
Version of PowerShell to download | |
.PARAMETER PwshArchitecture | |
Architecture version of PowerShell to download | |
.PARAMETER Path | |
Path in your CDK project where you want to store your Lambda layers | |
.PARAMETER HelloWorld | |
If specified a basic HelloWorld AWS Lambda PowerShell file is created | |
.PARAMETER Force | |
Skip Confirmation | |
.NOTES | |
Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ | |
PowerShell and PowerShell modules are checked to see if the desired version is already downloaded. | |
If found, they are not re-downloaded. | |
Currently, the PowerShell custom runtime is downloaded every time the function is run. | |
.COMPONENT | |
cdk_pwsh_runtime_bootstrap.ps1 | |
.LINK | |
https://aws.amazon.com/blogs/compute/introducing-the-powershell-custom-runtime-for-aws-lambda/ | |
.LINK | |
https://github.com/awslabs/aws-lambda-powershell-runtime | |
#> | |
[CmdletBinding(ConfirmImpact = 'Low', | |
SupportsShouldProcess = $true)] | |
param( | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'File path to the root of CDK project')] | |
[string] | |
$CDKProjectPath = '.', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Version of PowerShell to download')] | |
[string] | |
$PwshVersion = '7.2.6', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Architecture version of PowerShell to download')] | |
[ValidateSet('x64', 'arm64')] | |
[string] | |
$PwshArchitecture = 'x64', | |
[Parameter(Mandatory = $true, | |
HelpMessage = 'Array of Hashtable(s) containing ModuleName and ModuleVersion for each required module')] | |
[array] | |
$RequiredModules, | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Path in your CDK project where you want to store your Lambda layers')] | |
[string] | |
$Path = 'src/lambda/layers/', | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Creates a HelloWorld AWS Lambda PowerShell file')] | |
[switch]$HelloWorld, | |
[Parameter(Mandatory = $false, | |
HelpMessage = 'Skip confirmation')] | |
[switch]$Force | |
) | |
begin { | |
if (-not $PSBoundParameters.ContainsKey('Verbose')) { | |
$VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('Confirm')) { | |
$ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') | |
} | |
if (-not $PSBoundParameters.ContainsKey('WhatIf')) { | |
$WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') | |
} | |
Write-Verbose -Message ('[{0}] Confirm={1} ConfirmPreference={2} WhatIf={3} WhatIfPreference={4}' -f $MyInvocation.MyCommand, $Confirm, $ConfirmPreference, $WhatIf, $WhatIfPreference) | |
} #begin | |
process { | |
if (-not((Test-Path -Path "$CDKProjectPath/cdk.json") -and (Test-Path -Path "$CDKProjectPath/package.json"))) { | |
throw ('{0} does not contain expected CDK project files. Specify the root of the CDK project.' -f $CDKProjectPath) | |
} | |
if ($Force -or $PSCmdlet.ShouldProcess('Bootstrap CDK project with PowerShell lambda layer')) { | |
Write-Verbose -Message ('[{0}] Reached command' -f $MyInvocation.MyCommand) | |
$powerShellLayerCheck = Test-PowerShellRuntimePresent -PowerShellVersion $PwshVersion -Path $Path | |
if (-not $powerShellLayerCheck) { | |
Write-Verbose 'Retrieving raw pwsh files from PowerShell GitHub' | |
$invokeGetPowerShellSplat = @{ | |
PwshVersion = $PwshVersion | |
PwshArchitecture = $PwshArchitecture | |
Path = $Path | |
Force = $true | |
} | |
Invoke-GetPowerShell @invokeGetPowerShellSplat | |
} | |
else { | |
Write-Verbose 'PowerShell version verified. No action taken' | |
} | |
Write-Verbose 'Retrieving raw PowerShell runtime files from aws-lambda-powershell-runtime GitHub' | |
Invoke-GetAWSLambdaPowerShellRuntime -Path $Path -Force | |
Write-Verbose 'Retrieving all specified modules from PSGallery' | |
Invoke-GetRequiredModule $RequiredModules -Path $Path -Force | |
if ($HelloWorld) { | |
Write-Verbose 'Creating basic HelloWorld PowerShell lambda example' | |
$TargetDir = 'src/lambda/PowerShellLambda/HelloWorld' | |
if (-not(Test-Path -Path $TargetDir -ErrorAction Stop )) { | |
Write-Verbose -Message ('Output directory {0} not found. Creating...' -f $TargetDir) | |
$newItemSplat = @{ | |
ItemType = 'Directory' | |
Path = $TargetDir | |
ErrorAction = 'Stop' | |
} | |
try { | |
New-Item @newItemSplat | Out-Null | |
Write-Verbose -Message 'Created.' | |
} | |
catch { | |
Write-Warning -Message 'An error was encountered creating the output directory:' | |
Write-Error $_ | |
return | |
} | |
} | |
else { | |
Write-Verbose -Message 'Output directory verified.' | |
} | |
$lambdaExample = @' | |
#$VerbosePreference = 'Continue' | |
#$VerbosePreference = 'SilentlyContinue' | |
Write-Verbose -Message 'Run script init tasks before handler' | |
Write-Verbose -Message 'Importing Modules' | |
Import-Module 'AWS.Tools.Common' | |
function handler { | |
[CmdletBinding()] | |
param( | |
[Parameter()] | |
$LambdaInput, | |
[Parameter()] | |
$LambdaContext | |
) | |
Write-Verbose -Message 'Run handler function from HelloWorld script' | |
Write-Verbose -Message ('Function Remaining Time: {0}' -f $LambdaContext.GetRemainingTimeInMillis()) | |
Get-AWSRegion | |
Write-Host 'Hello World! ^ Those are the current AWS Regions!' | |
} | |
'@ | |
$lambdaExamplePath = '{0}/HelloWorld.ps1' -f $TargetDir | |
Write-Verbose -Message ('Creating HelloWorld PowerShell Lambda at: {0}' -f $lambdaExamplePath) | |
$lambdaExample | Out-File -FilePath $lambdaExamplePath -Encoding utf8 -Force | |
} | |
} | |
} #process | |
} #Invoke-BootStrapCDKProject | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment