Developing lambdas - AWS SAM with VSCode and Linux

From EnigmaGuy Wiki
Jump to navigation Jump to search

Developing lambdas with AWS SAM, Linux, and VS Code

Screenshots

Why this solution

When I first started to develop a lambda functions it was a small one. I mostly developed them from a web console and exported files which I saved into a git repository. Soon I started to work on more complex functions that contained several files, lambda layers, and connection to other services such as Amazon Aurora. Soon development in web console becomes a headache. A small window with no debugging and autocomplete facilities where on every iteration I had to export function and save into a git repository. At the end of development, I had to write the Cloudformation template, test it, and deploy it. Every small change meant exporting code, saving into a git repository, zipping files, and deploying with test stack into a cloud.

Soon I decided to try AWS SAM. It got me a little excited. I have got a code in Visual Studio Code with all functionalities like access to a git repository, Python Linter, Python debugger, autocomplete, access to local MySQL database with integrated PHPMyAdmin, and deploying an application into AWS was a matter of one click.

Why Windows VSCode with Ubuntu Linux in HyperV?

To be honest I love Linux. It is so powerful tool where you can customize everything. I worked as Linux admin for more than ten years so I feel pretty much at home. But at the same time, I hate Linux for its graphical interface and working functionality on the computer. Linux is great on the server or command line but has major shortcomings as the main operating system at desktop computer or laptop. Let's name a few - not well functioning sleep mode on laptops, sometimes trouble with a clipboard in GUI, terrible remote access in GUI (Remote Desktop in Windows is one hundred times better than VNC) and the worst - missing a large number of productivity apps (Office 365, etc...)

For the desktop I strongly prefer Windows and I changed my opinion about Microsoft since it started to support open source a lot. I have tried Windows Subsystem for Linux (WSL) and I cannot recommend it for this scenario. The trouble with WSL is not only that it is terribly slow (that does not matter so much for app development, just installing tools takes too long). The main trouble is that WSL is a container service.

That means you cannot install Docker into WSL and have to install it into Windows. You also cannot install any other service such as MySQL. For these reasons, I have decided to use HyperV with Ubuntu 20.04. I also do not recommend using VirtualBox because HyperV offers you the functionality to start your virtual machine during boot without any modifications.

And reasons for the Visual Studio Code? I love it, simply. I used to be a fan of VIM but VIM is just an editor, not a complete IDE. I found that the main benefit of Visual Studio Code lays in the number of available extensions, particularly in one I like most - Remote SSH development. It is so easy to connect your Visual Studio Code editor with Linux not mentioning you can very easily use an integrated terminal window for your Linux server in HyperV.

Let's start with installing Linux into HyperV

I prefer Ubuntu Linux. Because we are going to just use command line recommended distribution is Ubuntu Linux Server Edition 20.04. For using HyperV the Windows 10 Pro edition is needed. You can install HyperV by simply searching "Programs and Features" in START Menu and clicking on "Turn Windows Features on and off" and selecting HyperV.

Network settings

Default installation use default network. The trouble with default network in HyperV is that you are unable to connect to machine from host computer through IP. Only thing which is activated is NAT. I have tried to create only one internal network and install routing tools to Windows and route all traffic through NAT on hypervisor but the trouble was when using VPN service to company network. It just did not work. I was unable to connect to Cisco VPN. For this reason I am using two network cards, one use default HyperV NAT and second just internal network without internet access used only to access HyperV host.

When you are configuring second network adapter it is necessary to manually configure IP address. You can use any free network range, in my case I use 192.168.200.0/24 with hypervisor address 192.168.200.1 and host address 192.168.200.10. You should configure hypervisor address in network adapter settings in Windows and host IP address during Ubuntu installation (that's most convenient way).

If you need to modify configuration after installation use NETPLAN.

Visual Studio Code Extensions

  • Visual Studio Code Remote - SSH: Editing Configuration Files
  • Visual Studio Code Remote - SSH
  • AWS Toolkit
  • CloudFormation Linter
  • Python

Visual Studio SSH connection

1. Install all extensions

2. Generate and save private key with Puttygen (I recommend without password, more about it later)

3. In Windows set rights more permissive

4. Import OpenSSH key to Linux - https://www.cyberciti.biz/faq/how-to-set-up-ssh-keys-on-linux-unix/

5. Set config key and connect (use icon in left down corner of Visual Studio Code)

Disable SUDO password

Add NOPASSWD for sudo group

sudo visudo
%sudo   ALL=(ALL:ALL) NOPASSWD:ALL

SSH agent for all user sessions

There are many tutorials how to make ssh agent working, one of main problems is that they are usually valid only for one bash session. This is not really usable for VS Code because every new terminal start with a new bash session and you do not want to reenter password every time.

Furthermore because you have locally stored SSH key without password to access your linux machine you should also have a real private key on your linux machine to e.g. commit changes to a GIT repository. For this purpose I have a tutorial with background SSH agent service which will run as a daemon and ssh agent will be valid for all user sessions.

/etc/rc.local

#!/bin/bash
sudo -umkonicek ssh-agent > /home/mkonicek/.ssh-agent

/etc/systemd/system/rc-local.service

[Unit]
 Description=/etc/rc.local Compatibility
 ConditionPathExists=/etc/rc.local

[Service]
 Type=forking
 ExecStart=/etc/rc.local start
 TimeoutSec=0
 StandardOutput=tty
 RemainAfterExit=yes
 SysVStartPriority=99

[Install]
 WantedBy=multi-user.target

Enable service

systemctl start rc-local
systemctl enable rc-local

~/.bashrc

. ~/.ssh-agent

Debugging lambda

For debugging Lambda I use Visual Studio Code with Remote SSH plug-in and AWS SAM - you should install it first. Once you will install AWS SAM it is necessary to update Visual Studio Code launch configuration. Launch configuration map path between docker image code (AWS SAM) and VS Code. Path is relative the file you want to debug has to be opened.

VS Code Launch configuration

{
    "version": "0.2.0",
    "configurations": [
        {
           "name": "SAM CLI Python Hello World",
           "type": "python",
           "request": "attach",
           "port": 5890,
           "host": "localhost",
           "pathMappings": [
               {
                   
                   "localRoot": "${fileDirname}",
                   "remoteRoot": "/var/task"
               }
           ]
       }
   ]
 }

Add to Python code

import ptvsd
print("Waiting for attach on port 5890")
ptvsd.enable_attach(address=('0.0.0.0', 5890), redirect_output=True)
ptvsd.wait_for_attach()

Invoke

sam local invoke --profile default --region us-east-1  NameOfApp -d 5890

Debugging

Once you open a file which you want to debug, add python code for debug, launch "sam local invoke" and click on debugging icon in VS Code. If you have your breakpoints selected you should be fine. Only thing which does not worked correctly for me is stopping on uncaught exceptions - Ticket I opened with AWS, still unresolved

Working with SAM

Install following documentation https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html

Installing homebrew on Ubuntu

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

Edit ~/.profile

test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile

Install awscli

sudo apt install python3-pip
sudo pip3 install awscli
aws configure