eolas/neuron/d0ed26d0-cdc8-4643-8c09-445408195f9b/.neuron/output/SAM.html
2024-10-20 19:00:04 +01:00

111 lines
No EOL
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type" /><meta content="width=device-width, initial-scale=1" name="viewport" /><!--replace-start-0--><!--replace-start-5--><!--replace-start-8--><title>AWS SAM - My Zettelkasten</title><!--replace-end-8--><!--replace-end-5--><!--replace-end-0--><link href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.7/dist/semantic.min.css" rel="stylesheet" /><link href="https://fonts.googleapis.com/css?family=Merriweather|Libre+Franklin|Roboto+Mono&amp;display=swap" rel="stylesheet" /><!--replace-start-1--><!--replace-start-4--><!--replace-start-7--><link href="https://raw.githubusercontent.com/srid/neuron/master/assets/neuron.svg" rel="icon" /><meta content="SAM stands for serverless application model. It is a framework developed by AWS to simplify the process of building, deploying and managing serverless applications. It provides a concise syntax for defining the components of a serverless application, such as Lambda functions, API gateway and databas" name="description" /><meta content="AWS SAM" property="og:title" /><meta content="My Zettelkasten" property="og:site_name" /><meta content="article" property="og:type" /><meta content="SAM" property="neuron:zettel-id" /><meta content="SAM" property="neuron:zettel-slug" /><meta content="AWS" property="neuron:zettel-tag" /><script type="application/ld+json">[]</script><style type="text/css">body{background-color:#eeeeee !important;font-family:"Libre Franklin", serif !important}body .ui.container{font-family:"Libre Franklin", serif !important}body h1, h2, h3, h4, h5, h6, .ui.header, .headerFont{font-family:"Merriweather", sans-serif !important}body code, pre, tt, .monoFont{font-family:"Roboto Mono","SFMono-Regular","Menlo","Monaco","Consolas","Liberation Mono","Courier New", monospace !important}body div.z-index p.info{color:#808080}body div.z-index ul{list-style-type:square;padding-left:1.5em}body div.z-index .uplinks{margin-left:0.29999em}body .zettel-content h1#title-h1{background-color:rgba(33,133,208,0.1)}body nav.bottomPane{background-color:rgba(33,133,208,2.0e-2)}body div#footnotes{border-top-color:#2185d0}body p{line-height:150%}body img{max-width:100%}body .deemphasized{font-size:0.94999em}body .deemphasized:hover{opacity:1}body .deemphasized:not(:hover){opacity:0.69999}body .deemphasized:not(:hover) a{color:#808080 !important}body div.container.universe{padding-top:1em}body div.zettel-view ul{padding-left:1.5em;list-style-type:square}body div.zettel-view .pandoc .highlight{background-color:#ffff00}body div.zettel-view .pandoc .ui.disabled.fitted.checkbox{margin-right:0.29999em;vertical-align:middle}body div.zettel-view .zettel-content .metadata{margin-top:1em}body div.zettel-view .zettel-content .metadata div.date{text-align:center;color:#808080}body div.zettel-view .zettel-content h1{padding-top:0.2em;padding-bottom:0.2em;text-align:center}body div.zettel-view .zettel-content h2{border-bottom:solid 1px #4682b4;margin-bottom:0.5em}body div.zettel-view .zettel-content h3{margin:0px 0px 0.4em 0px}body div.zettel-view .zettel-content h4{opacity:0.8}body div.zettel-view .zettel-content div#footnotes{margin-top:4em;border-top-style:groove;border-top-width:2px;font-size:0.9em}body div.zettel-view .zettel-content div#footnotes ol > li > p:only-of-type{display:inline;margin-right:0.5em}body div.zettel-view .zettel-content aside.footnote-inline{width:30%;padding-left:15px;margin-left:15px;float:right;background-color:#d3d3d3}body div.zettel-view .zettel-content .overflows{overflow:auto}body div.zettel-view .zettel-content code{margin:auto auto auto auto;font-size:100%}body div.zettel-view .zettel-content p code, li code, ol code{padding:0.2em 0.2em 0.2em 0.2em;background-color:#f5f2f0}body div.zettel-view .zettel-content pre{overflow:auto}body div.zettel-view .zettel-content dl dt{font-weight:bold}body div.zettel-view .zettel-content blockquote{background-color:#f9f9f9;border-left:solid 10px #cccccc;margin:1.5em 0px 1.5em 0px;padding:0.5em 10px 0.5em 10px}body div.zettel-view .zettel-content.raw{background-color:#dddddd}body .ui.label.zettel-tag{color:#000000}body .ui.label.zettel-tag a{color:#000000}body nav.bottomPane ul.backlinks > li{padding-bottom:0.4em;list-style-type:disc}body nav.bottomPane ul.context-list > li{list-style-type:lower-roman}body .footer-version img{-webkit-filter:grayscale(100%);-moz-filter:grayscale(100%);-ms-filter:grayscale(100%);-o-filter:grayscale(100%);filter:grayscale(100%)}body .footer-version img:hover{-webkit-filter:grayscale(0%);-moz-filter:grayscale(0%);-ms-filter:grayscale(0%);-o-filter:grayscale(0%);filter:grayscale(0%)}body .footer-version, .footer-version a, .footer-version a:visited{color:#808080}body .footer-version a{font-weight:bold}body .footer-version{margin-top:1em !important;font-size:0.69999em}@media only screen and (max-width: 768px){body div#zettel-container{margin-left:0.4em !important;margin-right:0.4em !important}}body span.zettel-link-container span.zettel-link a{color:#2185d0;font-weight:bold;text-decoration:none}body span.zettel-link-container span.zettel-link a:hover{background-color:rgba(33,133,208,0.1)}body span.zettel-link-container span.extra{color:auto}body span.zettel-link-container.errors{border:solid 1px #ff0000}body span.zettel-link-container.errors span.zettel-link a:hover{text-decoration:none !important;cursor:not-allowed}body [data-tooltip]:after{font-size:0.69999em}body div.tag-tree div.node{font-weight:bold}body div.tag-tree div.node a.inactive{color:#555555}body .tree.flipped{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}body .tree{overflow:auto}body .tree ul.root{padding-top:0px;margin-top:0px}body .tree ul{position:relative;padding:1em 0px 0px 0px;white-space:nowrap;margin:0px auto 0px auto;text-align:center}body .tree ul::after{content:"";display:table;clear:both}body .tree ul:last-child{padding-bottom:0.1em}body .tree li{display:inline-block;vertical-align:top;text-align:center;list-style-type:none;position:relative;padding:1em 0.5em 0em 0.5em}body .tree li::before{content:"";position:absolute;top:0px;right:50%;border-top:solid 2px #cccccc;width:50%;height:1.19999em}body .tree li::after{content:"";position:absolute;top:0px;right:50%;border-top:solid 2px #cccccc;width:50%;height:1.19999em}body .tree li::after{right:auto;left:50%;border-left:solid 2px #cccccc}body .tree li:only-child{padding-top:0em}body .tree li:only-child::after{display:none}body .tree li:only-child::before{display:none}body .tree li:first-child::before{border-style:none;border-width:0px}body .tree li:first-child::after{border-radius:5px 0px 0px 0px}body .tree li:last-child::after{border-style:none;border-width:0px}body .tree li:last-child::before{border-right:solid 2px #cccccc;border-radius:0px 5px 0px 0px}body .tree ul ul::before{content:"";position:absolute;top:0px;left:50%;border-left:solid 2px #cccccc;width:0px;height:1.19999em}body .tree li div.forest-link{border:solid 2px #cccccc;padding:0.2em 0.29999em 0.2em 0.29999em;text-decoration:none;display:inline-block;border-radius:5px 5px 5px 5px;color:#333333;position:relative;top:2px}body .tree.flipped li div.forest-link{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}</style><script
async=""
id="MathJax-script"
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
></script>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/themes/prism.min.css"
rel="stylesheet"
/><link rel="preconnect" href="https://fonts.googleapis.com" /><link
rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin
/><link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=IBM+Plex+Sans+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=IBM+Plex+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=IBM+Plex+Serif:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
rel="stylesheet"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/components/prism-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/autoloader/prism-autoloader.min.js"></script>
<style>
body .ui.container,
body ul {
font-family: "IBM Plex Sans" !important;
}
body blockquote {
border-left-width: 3px !important;
font-style: italic;
}
.headerFont,
.ui.header,
body h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "IBM Plex Sans Condensed" !important;
}
body p {
line-height: 1.4;
}
.monoFont,
body code,
pre,
tt {
font-family: "IBM Plex Mono" !important;
font-size: 12px !important;
line-height: 1.4 !important;
}
</style>
<!--replace-end-7--><!--replace-end-4--><!--replace-end-1--></head><body><div class="ui fluid container universe"><!--replace-start-2--><!--replace-start-3--><!--replace-start-6--><div class="ui text container" id="zettel-container" style="position: relative"><div class="zettel-view"><article class="ui raised attached segment zettel-content"><div class="pandoc"><h1 id="title-h1">AWS SAM</h1><p>SAM stands for <strong>serverless application model</strong>. It is a framework developed by AWS to simplify the process of building, deploying and managing serverless applications. It provides a concise syntax for defining the components of a serverless application, such as <a href="zk/Lambda_programming_model.md">Lambda functions</a>, <a href="/zk/AWS_API_Gateway.md">API gateway</a> and database tables.</p><p>The SAM infrastructure is defined in a YAML file which is then deployed to AWS. SAM syntax gets transformed into CloudFormation during the deployment process. (CloudFormation is a broader and more robust AWS tool for large, highly scaleable infrastructures).</p><h2 id="key-features-of-sam">Key features of SAM</h2><ul><li>Single deployment configuration</li><li>Integration with development tools</li><li>Local testing and debugging</li><li>Built on AWS CloudFormation</li></ul><h2 id="main-technologies-required">Main technologies required</h2><h3 id="docker">Docker</h3><p>Whilst SAM can be used to create a deployable file for AWS it can also be run as a container for local development with Docker.</p><h3 id="aws-cli">AWS CLI</h3><p>This is installed using Python and allows you to interact directly with AWS via the command-line.</p><h3 id="aws-sam-cli">AWS SAM CLI</h3><p>See <a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html"><a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html">https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html</a></a></p><h2 id="setting-up-credentials-for-the-aws-cli">Setting up credentials for the AWS CLI</h2><p>You require an access key for the given <a href="zk/AWS_User_management_and_roles.md#iam">IAM user</a>. You should create an IAM account specific to the project with bounded permissions.</p><pre><code class="language-none">aws configure
AWS Access Key ID [None]: AK*******
AWS Secret Access Key [None]: ukp******
Default region name [None]:
Default output format [None]:</code></pre><p>This information can be found in the Security Credentials section of the given <a href="zk/AWS_User_management_and_roles.md#iam">IAM</a> user:</p><p><img src="/static/access-key-aws.png" /></p><h3 id="switching-between-credentials">Switching between credentials</h3><p>You should set up a different IAM user for each project.</p><p>You can do this with:</p><pre><code class="sh language-sh">aws configure --profile &lt;profile-name&gt;</code></pre><p>This will then ask you to add the credentials for the user.</p><p>You can switch between different credentials for the user as follows:</p><pre><code class="sh language-sh">AWS_PROFILE=&lt;profile-name&gt; sam build
</code></pre><h2 id="starting-a-sam-project">Starting a SAM project</h2><p>First create a directory for your project which will serve as the repository:</p><pre><code class="sh language-sh">mkdir aws-sam-learning
cd aws-sam-learning</code></pre><p>Then we can use the <code>sam</code> cli to bootstrap the project:</p><pre><code class="sh language-sh">sam init --runtime nodejs16.x</code></pre><p>We can just click through and accept the basic HelloWorld Lambda.</p><p>This will create the Lambda as well as an API Gateway trigger URL.</p><h3 id="templateyaml"><code>template.yaml</code></h3><p>This is autogenerated and details the main constituents of the project. There are lots of fields but the most important are the following:</p><pre><code class="yaml language-yaml">HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs16.x
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get</code></pre><p>This details the location of the <a href="/Lambda_handler_function.md">handler function</a> which is contained at the path <code>hello-world/app.js</code>:</p><pre><code class="js language-js">exports.lambdaHandler = async (event, context) =&gt; {
try {
// const ret = await axios(url);
response = {
statusCode: 200,
body: JSON.stringify({
message: &quot;hello world&quot;,
// location: ret.data.trim()
}),
};
} catch (err) {
console.log(err);
return err;
}
return response;
};</code></pre><p>It also lists the <code>get</code> event that we can use to call API Gateway and trigger the Lambda.</p><p>The full template is below:</p><p><img src="/static/sam-template-yaml.png" /></p><h2 id="adding-our-own-code">Adding our own code</h2><p>We will create our own function and API Gateway trigger.</p><p>We will place our function after the existing <code>HelloWorldFunction</code></p><pre><code class="yaml language-yaml">ClockFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: clock/
Handler: handler.clock
Runtime: nodejs16.x
Events:
ClockApi:
Type: Api
Properties:
Path: /clock
Method: get</code></pre><p>We can test the syntax with:</p><pre><code class="sh language-sh">sam validate</code></pre><p>Just like with <code>HelloWorld</code>, we will create a directory for this function: <code>clock</code> and we will initialise it as an <code>npm</code> project.</p><pre><code class="sh language-sh">mkdir clock
cd clock
npm init</code></pre><p>We will use <code>handler.js</code> as our root, handler function.</p><p>We have said in the template file that our <code>Handler: handler.clock</code>, therefore the main function in the <code>handler</code> module should be <code>clock</code>:</p><pre><code class="js language-js">const moment = require(&quot;moment&quot;);
exports.clock = async (event) =&gt; {
console.log(&quot;Clock function run&quot;);
const message = moment().format();
const response = {
statusCode: 200,
body: JSON.stringify(message),
};
return response;
};</code></pre><p>The directory structure is as follows:</p><p><img src="/static/sam-directory.png" /></p><p>When we call the API Gateway path <code>/clock</code> with <code>GET</code>, our function will be triggered.</p><h2 id="deploying-the-project">Deploying the project</h2><p>We will now deploy our project to AWS from the local environment.</p><p>The process is as follows:</p><ol><li>Build</li><li>Package</li><li>Deploy</li></ol><h3 id="build">Build</h3><p>We need to install the runtime dependencies for the function. We do this by running <code>sam build</code>. This ignores test files and development dependencies and installs the project dependencies and source files to a temporary subdirectory.</p><p><img src="/static/sam-build.png" /></p><p>The build directory is <code>.aws-sam/build/</code>. There will be a subdirectory for each of our files.</p><h3 id="package">Package</h3><p>As noted, CloudFront handles the deployment of the application. It can only receive one file as an input. The packaging process consists in creating that single file.</p><p>The packaging proces will first archive all of the project artefacts into a zip file and then upload that to <a href="zk/AWS_S3.md">S3</a>. A reference to this S3 entity is then provided to CloudFormation.</p><p><img src="/static/s3-package-again.svg" /></p><p>The command is as follows:</p><pre><code class="sh language-sh">sam package
--template-file template.yaml
--output-template-file pkg.yml
--region eu-west-1</code></pre><p>This will automatically create a hashed bucket name for you in S3 (I have tried to add my own naming but it doesnt comply.)</p><h3 id="local-development-with-docker">Local development with Docker</h3><p>In order to work with your application locally without actually sending requests to AWS and using credit, you can run a local instance.</p><p>See <a href="zk/Local_AWS_development_with_SAM.md">Local AWS Development with SAM</a>.</p><h3 id="deploy">Deploy</h3><p>Once you have packaged the app you can deploy with <code>sam deploy --guided</code>. This will talk you through the defaults and will deploy the package to CloudFormation. In CloudFormation each individual project is called a <strong>stack</strong>.</p><p>If we then go to Cloud Formation we will see the deployed application.</p><p><img src="/static/cloud-formation-stack.png" /></p><h2 id="call-the-endpoint">Call the endpoint</h2><p>If we now go to the Lambda console, we will see our function listed, and the API Gateway endpoint under <code>triggers</code>:</p><p><img src="/static/gateway-trigger.png" /></p><p>We can then call this from Postman to check everything is working as it should:</p><p><img src="/static/postman-aws-output.png" /></p></div></article><nav class="ui attached segment deemphasized bottomPane" id="neuron-tags-pane"><div><span class="ui basic label zettel-tag" title="Tag">AWS</span></div></nav><nav class="ui bottom attached icon compact inverted menu blue" id="neuron-nav-bar"><!--replace-start-9--><!--replace-end-9--><a class="right item" href="impulse.html" title="Open Impulse"><i class="wave square icon"></i></a></nav></div></div><!--replace-end-6--><!--replace-end-3--><!--replace-end-2--><div class="ui center aligned container footer-version"><div class="ui tiny image"><a href="https://neuron.zettel.page"><img alt="logo" src="https://raw.githubusercontent.com/srid/neuron/master/assets/neuron.svg" title="Generated by Neuron 1.9.35.3" /></a></div></div></div></body></html>