1 00:00:11,960 --> 00:00:17,070 Welcome back to BackSpace Academy. In this lab we're going to be creating a NodeJS 2 00:00:17,070 --> 00:00:22,680 application using the serverless application model or SAM for short. 3 00:00:22,680 --> 00:00:29,039 Now the AWS documentation can be quite a bit confusing on how to actually use SAM 4 00:00:29,039 --> 00:00:33,450 so what I'm going to do is show you a process that I use and it's very simple 5 00:00:33,450 --> 00:00:40,110 all I do is I have a github repository which has two files in it, one file will 6 00:00:40,110 --> 00:00:44,460 be your SAM template and that will define where your code for your Lambda 7 00:00:44,460 --> 00:00:50,280 functions is and also will define any other services that you require such 8 00:00:50,280 --> 00:00:57,600 as an s3 bucket and it will also have the code which will be an index.js 9 00:00:57,600 --> 00:01:03,149 file which will have your nodejs code for your Lambda application. So all 10 00:01:03,149 --> 00:01:09,000 we need to do is bring that into the ec2 environment within Cloud9 and we just 11 00:01:09,000 --> 00:01:14,189 need to create our package.JSON file which will reference any additional 12 00:01:14,189 --> 00:01:19,680 packages that our application requires and from there we can just use SAM build 13 00:01:19,680 --> 00:01:24,960 to prepare it for deployment and then use SAM deploy to deploy our application. 14 00:01:24,960 --> 00:01:32,340 So let's get into it. Now all of the code is located in this Github repository 15 00:01:32,340 --> 00:01:37,770 here so the the link for this is in the lab notes of course so the first thing 16 00:01:37,770 --> 00:01:41,520 that you need to do is make sure that you star this repository that way you 17 00:01:41,520 --> 00:01:45,420 can find it easy enough again if you need to and also so that other people 18 00:01:45,420 --> 00:01:50,729 can find it as well so once we've done that we can have a look at our code so 19 00:01:50,729 --> 00:01:57,570 we've got here our template.yml and that is going to define our Sam template and 20 00:01:57,570 --> 00:02:02,189 so let's have a look at that so we've got a transform function or a transform 21 00:02:02,189 --> 00:02:07,469 statement here and that is required so that tells us that word tells 22 00:02:07,469 --> 00:02:13,859 cloudformation to use the service application model. Next we're creating 23 00:02:13,859 --> 00:02:20,069 called create thumbnail and that is a lambda function now the properties for 24 00:02:20,069 --> 00:02:26,579 this lambda function the code will be located in a folder called code and the 25 00:02:26,579 --> 00:02:33,659 handler will be in an index.js file within code and that will have an 26 00:02:33,659 --> 00:02:39,569 exports module called handler the runtime will be Nodejs the timout will be 27 00:02:39,569 --> 00:02:45,389 60 seconds and the policy that we're going to use is the AWS managed Lambda 28 00:02:45,389 --> 00:02:51,299 policy called AWS lambda execute and we're going to associate this with 29 00:02:51,299 --> 00:02:59,819 an event so when something happens to an s3 bucket this event will be created and 30 00:02:59,819 --> 00:03:06,810 that will invoke this Lambda function so the type of event is an s3 event and the 31 00:03:06,810 --> 00:03:11,250 bucket is going to be referencing a bucket called sauce bucket which is down 32 00:03:11,250 --> 00:03:18,150 here and the event is going to be s3 object created so whenever an object or 33 00:03:18,150 --> 00:03:22,949 an image or whatever is put into this sauce bucket an event will be created 34 00:03:22,949 --> 00:03:27,599 which will invoke this lambda function so let's have a look at this source 35 00:03:27,599 --> 00:03:35,370 bucket so it it simply has type source or type AWS s3 bucket so what that will 36 00:03:35,370 --> 00:03:40,799 do is it will automatically create an s3 bucket and it will name it with a unique 37 00:03:40,799 --> 00:03:45,540 name so we also need to have a destination bucket so what this 38 00:03:45,540 --> 00:03:51,090 application is going to be doing is that we are going to be uploading a file to a 39 00:03:51,090 --> 00:03:57,449 source bucket and that will invoke this lambda function to process that image in 40 00:03:57,449 --> 00:04:01,859 that source bucket and make a thumbnail of that image and put it into a 41 00:04:01,859 --> 00:04:07,889 destination bucket so what we also need is a destination bucket and we would 42 00:04:07,889 --> 00:04:13,709 like that destination bucket to have the same name as our source bucket but going 43 00:04:13,709 --> 00:04:19,949 to have - resized on the end of it so what we've got here is at our 44 00:04:19,949 --> 00:04:24,779 destination bucket it depends on our sauce bucket so we can't create this 45 00:04:24,779 --> 00:04:27,570 destination bucket until this sauce bucket 46 00:04:27,570 --> 00:04:32,400 exists and then we're going to give it a bucket name and that is going to be 47 00:04:32,400 --> 00:04:40,380 joining the name of our source bucket with - resized on the end so what we use 48 00:04:40,380 --> 00:04:45,240 is we use a cloudformation join function and the way that works is that 49 00:04:45,240 --> 00:04:49,890 first off we define what is the character that we're going to put in 50 00:04:49,890 --> 00:04:54,780 between these text strings so we're not going to have anything between them 51 00:04:54,780 --> 00:04:59,880 we're just going to have the source bucket and then -resized so what 52 00:04:59,880 --> 00:05:05,670 we're going to do there is just have two inverted commas with a dash in there and 53 00:05:05,670 --> 00:05:10,710 we're going to define then what the two text strings are and so it's going 54 00:05:10,710 --> 00:05:15,960 to be referencing our source bucket name and then we're going to have - resized 55 00:05:15,960 --> 00:05:21,240 so the bucket name will be the join of a resource bucket name with - resized on 56 00:05:21,240 --> 00:05:24,900 the end so we're going to have two buckets and when we drop an image into 57 00:05:24,900 --> 00:05:30,330 this source bucket that will create an event which will invoke our lambda 58 00:05:30,330 --> 00:05:39,420 function so let's go back to the cloud9 console and get this happening okay 59 00:05:39,420 --> 00:05:44,130 starting off here in the cloud9 IDE we're going to be using the ec2 60 00:05:44,130 --> 00:05:49,020 environment of cloud 9 to build our application so what the first thing we 61 00:05:49,020 --> 00:05:57,330 need to do is we need to clone our repository so git clone and then the URL 62 00:05:57,330 --> 00:06:00,450 of our repository again this is all in the lab notes make sure you download 63 00:06:00,450 --> 00:06:06,720 those so that's done that for us and if we look at our directory tree we can see 64 00:06:06,720 --> 00:06:11,310 that we've got our template demo and I've got a code in there so let's take a 65 00:06:11,310 --> 00:06:15,900 look at our template demo and what we can see here is that it's referencing 66 00:06:15,900 --> 00:06:20,520 our runtime so we need to make sure that the runtime that we're referencing here 67 00:06:20,520 --> 00:06:24,540 for Lambda to run is going to be the same as a runtime that we're going to be 68 00:06:24,540 --> 00:06:30,570 using to build this so let's just check what our node version is on our ec2 69 00:06:30,570 --> 00:06:33,770 environment here in cloud 9 70 00:06:35,770 --> 00:06:40,039 so there we can see we're running version 10 in cloud 9 71 00:06:40,039 --> 00:06:45,710 whereas our template is referencing version 12 of node and that's pretty 72 00:06:45,710 --> 00:06:49,129 common for some reason I don't know why cloud 9 seem to be a bit slow with 73 00:06:49,129 --> 00:06:54,470 updating its version so we just go into here and change that to version 10 so 74 00:06:54,470 --> 00:07:01,310 that wiill be nodejs10.x and we just do ctrl s to make sure that we save that 75 00:07:01,310 --> 00:07:05,840 and we just get out of that now and just close that might as well just leave that 76 00:07:05,840 --> 00:07:09,949 open for now and let's have a look at our code here so we've got our index.js 77 00:07:09,949 --> 00:07:15,680 and we'll open that up and have a look at that so we can see here it's 78 00:07:15,680 --> 00:07:20,150 going to require the AWS software development kit that is not a problem 79 00:07:20,150 --> 00:07:25,370 for us land that includes it and you tools is also included with the Lambda 80 00:07:25,370 --> 00:07:31,940 service when it is invoked but sharp is not so we need to install sharp on this 81 00:07:31,940 --> 00:07:36,560 environment and that we need to do that with a package.json that references that 82 00:07:36,560 --> 00:07:42,680 sharp that sharp package so what we're going to do is is we're going to change 83 00:07:42,680 --> 00:07:47,210 into our code directory and again just copying from the lab notes it says the 84 00:07:47,210 --> 00:07:53,090 easiest way to do it and what we need to do now is that we need to create a 85 00:07:53,090 --> 00:08:01,460 package JSON file so NPM in it and we're just going to call the code package code 86 00:08:01,460 --> 00:08:05,810 that's fine leave everything as it is everything looks and our entry point is 87 00:08:05,810 --> 00:08:15,740 going to be indexed which is which we've got there and ok yes ok so that has 88 00:08:15,740 --> 00:08:20,690 created a package JSON so we open it up there it's pretty well got no 89 00:08:20,690 --> 00:08:26,719 dependencies there whatsoever so what we need to do now is that we need to do or 90 00:08:26,719 --> 00:08:30,830 we need to install sharp and that will put that reference that in our package 91 00:08:30,830 --> 00:08:38,649 JSON as well as installing sharp so we do NPM installed and sharp 92 00:08:42,639 --> 00:08:47,379 so now if we open up our package.json 93 00:08:49,870 --> 00:08:55,759 and then we can see it's put the dependency of Sharp in there so we 94 00:08:55,759 --> 00:08:59,300 don't need any of these new modules now because Sam bill doesn't need that will 95 00:08:59,300 --> 00:09:02,149 create all those so we can keep this quite small now so all I need to do is 96 00:09:02,149 --> 00:09:07,339 just delete that so it's going to select it press Delete and that has gone so 97 00:09:07,339 --> 00:09:10,850 we've got everything we need now we've got our template which is going to 98 00:09:10,850 --> 00:09:17,089 define our Sam and how Sam is going to package and deploy our application we've 99 00:09:17,089 --> 00:09:22,189 got our index which index J s and we've also got our package JSON which is going 100 00:09:22,189 --> 00:09:28,910 to list all of the packages that our application requires so all with all 101 00:09:28,910 --> 00:09:36,230 that we need to do now is to go back up to the main folder there which has got 102 00:09:36,230 --> 00:09:41,439 our template.yml file in there and so now we can just do a Sam build and 103 00:09:41,439 --> 00:09:47,870 that will build this application for you and it will prepare everything force and deploy 104 00:09:47,870 --> 00:09:59,689 so we do Sam build so that has successfully built our application so 105 00:09:59,689 --> 00:10:05,089 with three files only which is our template.YML our package JSON and our 106 00:10:05,089 --> 00:10:10,639 index.js is all that we needed to build our application it's a very simple 107 00:10:10,639 --> 00:10:14,689 process to follow this so once we've done that all we can do now all you need 108 00:10:14,689 --> 00:10:25,220 to do now is just SAM deploy. So Sam deploy - - guided. Okay and that 109 00:10:25,220 --> 00:10:30,500 will guide us through the deployment process so we'll give this would just 110 00:10:30,500 --> 00:10:35,480 leave it with the stack name of Sam app but easy enough to remember and the 111 00:10:35,480 --> 00:10:41,889 region is us east one confirmed changes to port before deploying yes we will and 112 00:10:41,889 --> 00:10:49,730 allows the CLI or the Sam CLI to create a role yes and save arguments 113 00:10:49,730 --> 00:10:54,570 to Sam configure it's fine so now it will be preparing that 114 00:10:54,570 --> 00:11:06,030 changeset for us and asking us whether we want to deploy that ok so what it's 115 00:11:06,030 --> 00:11:13,890 doing here is it is going to be creating some Lambda permissions and then it's 116 00:11:13,890 --> 00:11:18,810 going to use those permissions to create an IAM role for lambda and then it's 117 00:11:18,810 --> 00:11:22,320 going to be creating that Lambda function it's also going to be creating 118 00:11:22,320 --> 00:11:27,290 a destination bucket and a source bucket 119 00:11:28,610 --> 00:11:34,260 ok so after a few minutes all of these resources have been created for us quite 120 00:11:34,260 --> 00:11:38,610 successfully so what we can do now is that we can go into the s3 management 121 00:11:38,610 --> 00:11:41,820 console and we should see those two buckets that were created so if you look 122 00:11:41,820 --> 00:11:46,710 at our template ml and we can see that we did create a source and destination 123 00:11:46,710 --> 00:11:52,050 buckets and the destination bucket will be the same name as a source bucket but 124 00:11:52,050 --> 00:11:55,740 with -resized on the end of it so let's have a look at that we'll just 125 00:11:55,740 --> 00:11:58,190 refresh 126 00:11:58,340 --> 00:12:03,780 so there we can see our Sam app source bucket and a bit of a hash string there 127 00:12:03,780 --> 00:12:09,390 - resized and the or that's the source bucket there and then - resized is our 128 00:12:09,390 --> 00:12:14,400 destination bucket so if we go into this will open both of them up so we go into 129 00:12:14,400 --> 00:12:23,090 our source bucket and what I'm going to do is just upload an image 130 00:12:25,880 --> 00:12:32,329 and just to get that through accept all the defaults if that's fine okay so 131 00:12:32,329 --> 00:12:37,910 that's uploaded that that object that JPEG file so what's going to happen now 132 00:12:37,910 --> 00:12:44,540 is that that world trigger and s3 event that s3 event will invoke that Lambda 133 00:12:44,540 --> 00:12:50,509 function which will then grab this data JPEG file it will create a thumbnail 134 00:12:50,509 --> 00:12:55,910 image of that and it will store it into our destination source or a destination 135 00:12:55,910 --> 00:13:00,709 bucket so let's go to that destination bucket now and we're just going to 136 00:13:00,709 --> 00:13:06,079 refresh that and there we can see so resize data JPEGs so let's have a look 137 00:13:06,079 --> 00:13:12,259 at that original one where's 150 K and the next one is 9.8 K 138 00:13:12,259 --> 00:13:17,449 so it's created a thumbnail of that not a problem so that has worked what I want 139 00:13:17,449 --> 00:13:20,779 to do now is actually have a look at this code and see how it everything 140 00:13:20,779 --> 00:13:27,290 actually worked so let's open up our index page is and have a look at it so 141 00:13:27,290 --> 00:13:34,149 first of all we have our exports handler so that is going to be our index.js 142 00:13:34,149 --> 00:13:38,060 well when we reference that in our template.yml it's going to be our 143 00:13:38,060 --> 00:13:43,459 index.js and then what that module that we're exporting and here are going to be 144 00:13:43,459 --> 00:13:48,139 calling it handler so the first thing we're going to do is that we're going to 145 00:13:48,139 --> 00:13:51,350 get the source bucket and that is going to become is 146 00:13:51,350 --> 00:13:57,350 going to come from the event that triggered this s3 bucket name so how do 147 00:13:57,350 --> 00:14:05,329 we know that so why we do that as we go to the two the s3 documentation so here 148 00:14:05,329 --> 00:14:12,139 we are in the s3 developer guide so we just go down to notifications and then 149 00:14:12,139 --> 00:14:15,980 we can see event message structure so let's just scroll down and see what it 150 00:14:15,980 --> 00:14:22,550 looks like so it's going to be an array called records and having a few objects 151 00:14:22,550 --> 00:14:28,790 in there so what we've got here is s3 bucket and name so go back to our cloud 152 00:14:28,790 --> 00:14:36,019 9 we can see that we've got s3 bucket and name and we also need to know what 153 00:14:36,019 --> 00:14:39,710 the source keys so what the actual name of that image file 154 00:14:39,710 --> 00:14:45,200 all that we uploaded is and so again we'll go back to the event structure and 155 00:14:45,200 --> 00:14:55,070 we can see here we've got s3 object and key so if we go back to our code we can 156 00:14:55,070 --> 00:15:00,800 see there we've got its three object and key so now we we know what the source 157 00:15:00,800 --> 00:15:06,650 bucket is we know what the file name is and from there we can create our 158 00:15:06,650 --> 00:15:10,130 destination bucket which will be the same as the source bucket or we can 159 00:15:10,130 --> 00:15:14,420 reference our destination bucket it's already been created and that will have 160 00:15:14,420 --> 00:15:20,360 the name sort of their source bucket with - resized on the end of it and our 161 00:15:20,360 --> 00:15:23,810 destination key and that's what we're going to use there which is going to be 162 00:15:23,810 --> 00:15:30,440 based upon our source key as well so then what we need to do is to infer our 163 00:15:30,440 --> 00:15:36,500 image type and make sure that is either a JPEG or a PNG type file so once 164 00:15:36,500 --> 00:15:41,240 everything is fine we've got a jpg or PNG file in there we can download that 165 00:15:41,240 --> 00:15:45,740 image so we need to get the parameters which will be the bucket source bucket 166 00:15:45,740 --> 00:15:51,050 and the source key for that image and so then we're going to download that using 167 00:15:51,050 --> 00:15:57,260 the get objects command from the AWS software development kit and so once 168 00:15:57,260 --> 00:16:03,740 we've got that image we can then apply sharp to that image so sharp will get 169 00:16:03,740 --> 00:16:09,020 the original image which which we've got here and it's going to resize it to a 170 00:16:09,020 --> 00:16:13,910 width of 200 and it's going to put it into a buffer so that you will have 171 00:16:13,910 --> 00:16:19,310 temporary storage of that file for us if there's an error it will lock 172 00:16:19,310 --> 00:16:24,470 console.log out that error so once we've got the original image and we've got it 173 00:16:24,470 --> 00:16:32,020 stored in a buffer we can now get it back use it or we can now upload it to 174 00:16:32,020 --> 00:16:38,690 the destination file or the destination folder with that thumbnail image so we 175 00:16:38,690 --> 00:16:42,860 have our destination parameters which will be our destination bucket and our 176 00:16:42,860 --> 00:16:48,470 destination key and what is going to be going in there will be in our buffer so 177 00:16:48,470 --> 00:16:53,570 the buffer will contain the thumbnail image that we created using 178 00:16:53,570 --> 00:16:59,209 which will be 200 pixels wide and the content type will be image so once we've 179 00:16:59,209 --> 00:17:04,280 created those parameters we can pass those parameters to a put object command 180 00:17:04,280 --> 00:17:09,860 and once that's successfully done that will be fine and our object our 181 00:17:09,860 --> 00:17:15,079 thumbnail image of our original image will be uploaded to that bucket so quite 182 00:17:15,079 --> 00:17:20,510 straightforward we're simply just getting that image from the event s3 183 00:17:20,510 --> 00:17:26,839 bucket name and the name of the image from s3 object key and then we're using 184 00:17:26,839 --> 00:17:35,140 sharp to resize it to 200 and putting it into a buffer and then we're just 185 00:17:35,140 --> 00:17:40,370 getting put objects to put it into our destination bucket into that destination 186 00:17:40,370 --> 00:17:49,040 key from the buffer so let's now jump into lambda and have a look at how it 187 00:17:49,040 --> 00:17:53,990 all worked so just going to the lambda management console and this time we're 188 00:17:53,990 --> 00:17:57,679 going to look at the application we actually created a application that 189 00:17:57,679 --> 00:18:01,730 consisted of multiple parts not just a lambda function so there's our 190 00:18:01,730 --> 00:18:04,340 application Sam - app if we click on that 191 00:18:04,340 --> 00:18:12,320 and we can see that it's created or it's made up of a lambda function and - s3 192 00:18:12,320 --> 00:18:17,750 buckets and so there will be a link to the s3 buckets and here is a link to our 193 00:18:17,750 --> 00:18:25,010 Lambda function so there's our lambda function and what we can do is we can go 194 00:18:25,010 --> 00:18:32,299 to monitoring and view the logs in cloud watch and see what was produced through 195 00:18:32,299 --> 00:18:40,520 the console dot log so scroll down there's our log stream so let's have a 196 00:18:40,520 --> 00:18:45,980 look here so we've got the first one here so it received again at that event 197 00:18:45,980 --> 00:18:55,250 record and within that event record we had s3 bucket and bucket name and we 198 00:18:55,250 --> 00:19:01,549 also had the key which is data dot JPEG so that file that I uploaded and then 199 00:19:01,549 --> 00:19:07,070 what happened next was it successfully resized 200 00:19:07,070 --> 00:19:12,980 Sam app sauce bucket data JPEG and uploaded it to Sam app source bucket 201 00:19:12,980 --> 00:19:19,250 resize JPEG so that's pretty cool everything worked fine so I think I've 202 00:19:19,250 --> 00:19:23,300 shown you everything that you need to really know about this same process and 203 00:19:23,300 --> 00:19:27,800 I hope you in I hope you got a lot out of it and I I hope you enjoyed it and I 204 00:19:27,800 --> 00:19:30,950 look forward to seeing you in the next one but before we do that we'll just 205 00:19:30,950 --> 00:19:35,630 clean this up so we need to first off empty our buckets so we'll get this 206 00:19:35,630 --> 00:19:38,440 bucket and empty it 207 00:19:42,130 --> 00:19:50,170 we'll go to the next bucket or resize bucket well empty that as well 208 00:19:57,900 --> 00:20:03,390 so now that our buckets are empty we can just go into cloud formation and delete 209 00:20:03,390 --> 00:20:07,490 our Sam apps we're just going to refresh this make sure it's all okay yep and 210 00:20:07,490 --> 00:20:11,730 delete our Sam app make sure you don't delete these other two just delete the 211 00:20:11,730 --> 00:20:18,210 Sam app and delete that stack so after a certain amount of time that will delete 212 00:20:18,210 --> 00:20:24,180 all of those Lambda resources those s3 resources and that that that app if you 213 00:20:24,180 --> 00:20:28,740 want we can go into here also in to delete our code as well so just delete 214 00:20:28,740 --> 00:20:34,650 that and there we go that's done so I look forward to seeing you in the next 215 00:20:34,650 --> 00:20:36,920 one