Migrate SQLPrompt Snippets to VSCode

 I love snippets; love em. And I have a whole bunch in RedGate SQL Prompt. Now I want to be able to use those in VSCode as well, but boy do I dread having to retype all of them. Solution? Python! First arg is the path where your SQLPrompt snippets are Second arg is the directory where you want it to spit out a "sql.json" file with all your snippets. """ A script to translate sqlprompt snippet files to vscode formatted snippets """ import os import json import glob import io import argparse class SQLPromptPlaceholder :     """Represents the values of a SQLPrompt placeholder"""     def __init__ ( self , name , default_value ):         self . name = name         self . default_value = default_value class SQLPromptSnippet :     """Represents the content of a SQLPrompt snippet"""     @ staticmethod     def from_file ( filename ):         """Generates an instance fr

Custom AWS Lambda Layer using NodeJS

AWS Lambda is awesome, and conceptually, layers are awesome too. Layers are a way to share code between lambdas. However I found the documentation on them a little spartan, and some very core use cases were barely documented at all. What I'm going to do in this blog post is walk you through how to:

  1. Create a NodeJS Layer with a custom function in it
  2. Create a NodeJS Lambda which consumes that layer
And I'm going to do it using SAM.

Prerequisites:
- VSCode
- SAM CLI

Creating your Project

We're going to make a simple app which contains a layer we wish to reuse across a number of lambda functions (even though we'll just do one here). The layer will export a function which reverses a string provided.

We'll then create a lambda function which uses that lambda function and passes data form its input event to the function exported by the layer.

I'm going to use SAM CLI for this, but really the only thing I'm gaining from that is to stub out a SAM template for me. You could just as easily do this from scratch yourself.

SAM CLI

Find a folder you like, and do sam init. Select "AWS Quick Start Templates", "Zip (artifact is a zip uploaded to S3", "nodejs14.x", then name it "palindrome-app". Finally, select "Quick Start: From Scratch". Now open that folder in VSCode. You should see a folder that looks basically like this.
  • Delete the src folder.
  • Delete the __tests__ folder
  • Create a folder called "functions" and another folder called "layers"

From Scratch

  • Create a folder called "palindrome-app".
  • Create folders named "functions" and "layers"
  • Create a file at the root of the folder named "template.yml"
    • This will be your SAM template

Stub SAM Template

Whichever way you created the project, replace the contents of "template.yml" with 
AWSTemplateFormatVersion: 2010-09-09
Description>-
  palindrome-app
Transform:
AWS::Serverless-2016-10-31
Resources:


Create Layer

Create a folder under the "layers" folder named "palindrome-layer\nodejs". In that folder, add a file named "palindrome.js". This is the file you'll put your custom reusable code in, and the name of the file (palindrome) is going to be what you'll need to require in your lambda function.

In palindrome.js add:
module.exports = function (phrase) {
    return phrase.split('').reverse().join('');
};

Also, add a package.json file (you can do npm init, or just copy paste a simple file). SAM requires you to have a package.json file in the folder, even if it aint doing diddly squat.

Create Function

Create a folder under the "functions" folder named "palindrome-function". Add a file named "app.js" (can be whatever you want it to be named, but this is what our sam template will look for.

Skipping ahead a little bit, how SAM uses layers is that at run time, it downloads the content of the layer (which will have been packaged into a ZIP archive by the SAM template) and plops it in a directory in the environment called "/opt/nodejs/palindrome". Each runtime uses a different location, so if you're not using NodeJS, make sure to look it up in the SAM Working with Layers Documentation.

Add the following code to app.js

const palindrome = require('/opt/nodejs/palindrome');

exports.handler = async (event=> {
    const val = palindrome(event.value);
    console.log(val);
    return val;
}


Note, the "/opt/nodejs" folder doesn't actually exist locally; just when SAM builds it, so as such you'll have to do "sam build" and "sam local invoke" to get it to be testable. Also, remember that "palindrome" is the name of the layer file. If you'd named the layer file "oogieboogie.js", you would instead require "/opt/nodejs/oogieboogie".

Also, add a package.json file (you can do npm init, or just copy paste a simple file). SAM requires you to have a package.json file in the folder, even if it aint doing diddly squat.

Building Sam Template


Create a folder named "events", and create a file in it called "event.json"
{
    "value""go hang a salami im a lasagna hog"
}

So now we've got the code for a layer, and code for a lambda function, and your palindrome-app folder should look roughly like this:



 Now we're going to build out the SAM template to point to each of these locations and build them appropriately. We're going to add two resources: a AWS::Serverless::Function and an AWS::Serverless::LayerVersion

PalindromeLayer

Add the following under the Resources: key. The critical things here is to set the contentUri to the nodejs folder of your layer. also, set the Metadata/BuildMethod to nodejs14.x or it will yell at you.
  PalindromeLayer:
    TypeAWS::Serverless::LayerVersion
    Properties:
      ContentUrilayers/palindrome-layer/nodejs/.
      CompatibleRuntimes:
        - nodejs14.x
      RetentionPolicyretain
    Metadata:
      BuildMethodnodejs14.x

PalindromeFunction

Add the following under the Resources: key. Notice we are referencing the layer in the Layers: key by getting a reference to the PalindromeLayer (-Ref: PalindromeLayer). That makes it so we dont have to hard-code the ARN for the layer.
  PalindromeFunction:
    TypeAWS::Serverless::Function
    Properties:
      CodeUrifunctions/palindrome-function/
      Handlerapp.handler
      Runtimenodejs14.x
      MemorySize128
      Timeout100
      Policies:
        - AWSLambdaBasicExecutionRole
      Layers:
        - RefPalindromeLayer

Build Stuff

Now change directories to the base directory "palindrome-app" and run "sam build". This will create your layer and function and put them in ".aws-sam".

If you didn't create the events\event.json earlier, scroll up and do so now.
Now run

sam local invoke PalindromeFunction -e events\event.json

You should see an output of "goh angasal a mi imalas a gnah og"

Summary

What we did was create a lambda layer with a function we can import and use in other lambda functions, by specifying it in the "Layers" section of the SAM template. We then imported that layer, and built our sam template and proved that our function correctly made use of the layer function.

I've glossed over most of the background on layers, sam, and lambdas for the sake of illustrating how to create a useful layer. If you're lost, I'd recommend looking at the documentation for each of these, even though, as I said from the outset, there are times where it's somewhat inadequate.

You can view the code for this project on my github: palindrome-app

Comments

Popular posts from this blog

Migrate SQLPrompt Snippets to VSCode

Fixing Git "Unexpected Disconnect while reading sideband packet"

Left-Padding Zeroes