<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>The Pulumi Book | Blog</title><description>Learn Pulumi from the ground up by building and deploying real applications on AWS with TypeScript.</description><link>https://pulumibook.com/</link><language>en</language><item><title>The book has a new home</title><link>https://pulumibook.com/blog/the-book-has-a-new-home/</link><guid isPermaLink="true">https://pulumibook.com/blog/the-book-has-a-new-home/</guid><description>A quick note on the new Pulumi Book website — built with Astro Starlight, generated straight from the manuscript, and with this blog for updates as the book grows.

</description><pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to the new home of &lt;em&gt;The Pulumi Book&lt;/em&gt;! If you’ve been here before, things
look a little different — and quite a bit more like a book.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-new&quot;&gt;What’s new&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The site is now built with &lt;a href=&quot;https://starlight.astro.build/&quot;&gt;Astro Starlight&lt;/a&gt;, the
same documentation framework used by a growing number of open-source projects. A
few things come along for the ride:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The whole book is here.&lt;/strong&gt; Every chapter, section, and subsection is navigable
from the sidebar, with a table of contents on each page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The examples are one click away.&lt;/strong&gt; There’s a dedicated &lt;a href=&quot;https://pulumibook.com/examples/&quot;&gt;examples&lt;/a&gt;
page listing every runnable Pulumi program from the book.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;This blog.&lt;/strong&gt; A place for me to post updates as the book grows — new chapters,
reworked examples, errata, and the occasional aside.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;generated-straight-from-the-manuscript&quot;&gt;Generated straight from the manuscript&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Here’s the part I’m most pleased about: the entire book section of this site is
&lt;strong&gt;generated automatically from the manuscript&lt;/strong&gt;. I write the book in
&lt;a href=&quot;https://leanpub.com/markua/read&quot;&gt;Markua&lt;/a&gt; for Leanpub, and a small converter
turns those chapters into the pages you’re reading now — code listings, figures,
cross-references, and all. When I push an update to the manuscript, the website
rebuilds itself.&lt;/p&gt;
&lt;p&gt;That means there’s no separate “web version” of the book to keep in sync. There’s
just the book, and this is one of the ways you can read it.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;More chapters, for one. I’ll post here as new material lands, so check back — or
grab the &lt;a href=&quot;https://pulumibook.com/blog/rss.xml&quot;&gt;RSS feed&lt;/a&gt; if that’s more your speed.&lt;/p&gt;
&lt;p&gt;Thanks for reading, and as always, you can find me
&lt;a href=&quot;https://twitter.com/cnunciato&quot;&gt;on Twitter / X&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy Pulumifying!&lt;/p&gt;</content:encoded><category>announcements</category><category>meta</category></item><item><title>Serverless on AWS #1: A serverless video converter</title><link>https://pulumibook.com/blog/serverless-architectures-aws-1-video-encoder/</link><guid isPermaLink="true">https://pulumibook.com/blog/serverless-architectures-aws-1-video-encoder/</guid><description>The first in a series on serverless on AWS: building a serverless video-encoding pipeline with Pulumi and AWS Elemental MediaConvert.

</description><pubDate>Sat, 19 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A year or so ago, with great enthusiasm, I ordered a copy of the second edition of &lt;a href=&quot;https://www.manning.com/books/serverless-architectures-on-aws-second-edition&quot;&gt;Serverless Architectures on AWS&lt;/a&gt; — and when it finally arrived, I promptly set it aside, and almost forgot about it entirely.&lt;/p&gt;
&lt;p&gt;Life, as it happens, has a way of getting in the way. Last week, though, I finally managed to pick it back up, and I’m excited to start working through it chapter by chapter. &lt;a href=&quot;https://en.wikipedia.org/wiki/Serverless_computing&quot;&gt;Serverless&lt;/a&gt;, once you manage to get your head around it, really does change the way you think about cloud computing in fundamental ways — and I happen to be one of those people who’s about as bought into it philosophically as one could be. Whenever possible, if I can solve a problem serverlessly, I’m going to give that a try first.&lt;/p&gt;
&lt;p&gt;As of now, I’m only a couple of chapters into the book, but I’m enjoying it so far — and I love that it covers such a broad range of material. Flipping through the upcoming sections, though (each of which covers a particular serverless use case and architecture), it occurred to me that it might be fun to work through all of the book’s examples using &lt;a href=&quot;https://www.pulumi.com/&quot;&gt;Pulumi&lt;/a&gt;. (Most of the examples seem to use some combination of &lt;a href=&quot;https://www.serverless.com/&quot;&gt;Serverless Framework&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com/serverless/sam/&quot;&gt;SAM&lt;/a&gt;, and the AWS CLI and/or console, but serverless architectures in general lend themselves surprisingly well to Pulumi — especially when your language of choice, like mine, happens to be JavaScript.)&lt;/p&gt;
&lt;p&gt;So in this post, I’ll kick off this little series-to-be by jumping right into the first architecture covered in the book: a simple serverless video-conversion pipeline.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;setting-the-stage&quot;&gt;Setting the stage&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The hypothetical scenario is simple: You’ve got a video file somewhere, maybe something you shot with your phone, but it’s big — several gigs, say, so much too large to just throw up onto the web or drop into a blog post. To make use of this giant raw video file, you need a way to compress and resize it into a web-friendly format — which, these days, probably means converting it into an H.264 encoded MP4.&lt;/p&gt;
&lt;p&gt;Of course, you could easily do this with something like iMovie. But let’s assume that for whatever reason, you can’t; maybe you don’t have an iPhone or a Mac, or you do, but you actually need to transcode like a thousand videos for work, or something, or you’ve found yourself in some other such situation that truly requires a bit of cloud automation. How do you do it? And more importantly, how do you do it serverlessly on AWS?&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;serverless-architectures-to-the-rescue&quot;&gt;&lt;em&gt;Serverless Architectures&lt;/em&gt; to the rescue&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Serverless Architectures on AWS offers a clear and ostensibly simple solution: Wire together a few high-level Amazon services and call it a day. The fundamental idea is that you should be able start with a large video file, throw it at AWS, and wait patiently for the transcoded version (or versions) to emerge through the magic of AWS (and perhaps a little coding on your part).&lt;/p&gt;
&lt;p&gt;Turns out that’s totally doable, and there really isn’t all that much to it — architecturally at least. The book proposes the following simple setup:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://pulumibook.com/media/images/serverless-architectures-diagram.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here, the user — e.g., you — begins by uploading a video to an S3 bucket. A Lambda function configured to respond to file uploads handles the event by parsing its metadata (for the name of the file, its location, etc.) and then contacting an AWS managed service called &lt;a href=&quot;https://aws.amazon.com/mediaconvert/&quot;&gt;Elemental MediaConvert&lt;/a&gt; to request a new conversion job, passing along a few details like the desired file format, bit rate, and name of the bucket where the transcoded files ultimately should be stored. MediaConvert then does its thing, converting the file according to your specs and writing the new video to S3.&lt;/p&gt;
&lt;p&gt;And that’s pretty much it. And of course, because it’s all serverless, it scales automatically (meaning you can throw as many videos at the pipeline as you like), and you only pay for the time it takes AWS to run your Lambdas and convert each video file.&lt;/p&gt;
&lt;p&gt;But the approach the book takes to implement this design — as an example of infrastructure as code — is a surprisingly awkward and laborious one. Here’s how it’s done:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, in the AWS console, navigate to the S3 dashboard and create a new bucket for your transcoded video files — the ones MediaConvert will eventually create for you. Be sure to come up with a unique name for this bucket because no two S3 buckets can ever share the same name anywhere in the known universe. And remember the name you choose. You’ll need it later.&lt;/li&gt;
&lt;li&gt;Then, navigate to the AWS IAM dashboard and create a new role to grant AWS Lambda permission to make calls on the MediaConvert service. Make sure you copy the new role’s Amazon Resource Name (ARN) as well — you’ll need that later, too.&lt;/li&gt;
&lt;li&gt;Next, make another new IAM role, this one to grant MediaConvert permission to write video files to S3. Copy this role’s ARN somewhere also.&lt;/li&gt;
&lt;li&gt;Navigate to the MediaConvert dashboard and locate your AWS account’s assigned MediaConvert API endpoint. (AWS assigns these automatically.) As you do this, doublecheck that the currently selected region (as shown in the upper-right corner of the console) is the same one you’re planning to deploy into later, as MediaConvert API URLs are region-specific. Copy the endpoint’s unique URL. The Lambda function will need it to submit conversion requests.&lt;/li&gt;
&lt;li&gt;Install the Serverless Framework CLI and generate a new &lt;code dir=&quot;auto&quot;&gt;aws-nodejs&lt;/code&gt; project.&lt;/li&gt;
&lt;li&gt;Open the generated YAML file and paste these four strings — destination bucket, Lambda role ARN, MediaConvert role ARN, and MediaConvert API endpoint — into their proper positions in the file. Add a few lines to expose these values as environment variables (so the Lambda can use them at runtime), then fill out the generated JavaScript function to complete the Lambda itself.&lt;/li&gt;
&lt;li&gt;Finally, run &lt;code dir=&quot;auto&quot;&gt;serverless deploy&lt;/code&gt; to provision the upload bucket and Lambda resources (because you’ve already created everything else by hand).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Easy, right?&lt;/p&gt;
&lt;p&gt;So, here’s the thing. This totally works, and the architecture is fine; it’s definitely the right set of AWS resources to use for an app like this one. All of the ingredients — buckets, IAM roles, function code — are necessary; Lamba needs permission to talk to MediaConvert, MediaConvert needs permission to write to S3, and so on. As far as the architecture itself is concerned, given the various product offerings and technical constraints of AWS, what’s presented here makes total sense, design-wise.&lt;/p&gt;
&lt;p&gt;But man — all this clicking around in the AWS console, hard-coding of thought-up bucket names, copy-pasting of URLs and ARNs — all of it makes this simple job way more complicated and cumbersome than it needs to be. To me, this is very much not what infrastructure as code is supposed to look like.&lt;/p&gt;
&lt;p&gt;Infrastructure-as-code, to me, is all about hands-off automation. The moment you, as practitioner of IaC, find yourself filling out web forms and clicking buttons to make resources or hard-coding or copying and pasting anything should be the moment your brain tells you that something is wrong. All of this stuff should be expressible in code, not just a sliver of it — and all of it within the scope of a single program. On top of that, you — and perhaps more importantly, anyone else — should be able to look at your program code and easily grasp how it all hangs together; you shouldn’t have to toggle between your IDE and the AWS console to assemble a mental picture of how an application does its job — particularly an application as simple as this one. And finally, you should also be able to stand up and easily switch between multiple deployment environments (think dev, staging, production) to target whichever environment you need, without having to change anything (like hard-coded S3 bucket names or resource IDs) in the code itself.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;how-its-done-with-pulumi&quot;&gt;How it’s done with Pulumi&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now let’s see how you might go about implementing this same architecture with Pulumi.&lt;/p&gt;
&lt;p&gt;For starters, you’ll need a new project. So if you haven’t already (assuming you’re interested in actually doing this yourself), install Pulumi and configure it for AWS. You can read all about how to do both &lt;a href=&quot;https://www.pulumi.com/docs/clouds/aws/get-started/&quot;&gt;in the getting-started guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Create the project using a starter template. There are &lt;a href=&quot;https://github.com/pulumi/templates&quot;&gt;many such templates&lt;/a&gt; to choose from, but for applications like this one (and for most serverless apps in general), I usually start with the &lt;code dir=&quot;auto&quot;&gt;aws-typescript&lt;/code&gt; template, as it gives you access (by way of the Node.js SDK) to Pulumi’s built-in support for &lt;a href=&quot;https://www.pulumi.com/docs/concepts/inputs-outputs/function-serialization/&quot;&gt;function serialization&lt;/a&gt;, which is incredibly handy for wiring up JavaScript Lambda functions (as you’ll see in a moment). Start with this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws-typescript&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The template will prompt you for a handful of properties like the project name, stack name, and the AWS region to deploy into. Step through them, then open the project in your editor of choice.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-quick-look-at-what-well-be-building&quot;&gt;A quick look at what we’ll be building&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The biggest differences between the program you’re about to build and the implementation described in Serverless Architectures are these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the Pulumi version, there’s no need to create anything manually&lt;/li&gt;
&lt;li&gt;You can do it all within the scope of a single 100-line Node.js program&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every component required by the program can be created or obtained by program itself: buckets, globally unique bucket names, IAM roles, service endpoints, all of it. No visits to the AWS console (or hard-coding of strings) required.&lt;/p&gt;
&lt;p&gt;Secondly, the whole application can be written in one language — TypeScript (or if you like, plain ol’ JavaScript) — and expressed in a single TypeScript file. Thanks to the magic of Pulumi’s Node.js SDK, you can code both application and infrastructure in the same program — a huge advantage that makes writing, debugging, testing, refactoring, reviewing, and most importantly understanding the code way easier than having it all managed in multiple places by hand.&lt;/p&gt;
&lt;p&gt;The infrastructure requirements, however, are the same. You’ll still need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A bucket for uploads&lt;/li&gt;
&lt;li&gt;Another bucket for transcodes&lt;/li&gt;
&lt;li&gt;A Lambda function to invoke MediaConvert when a video is uploaded&lt;/li&gt;
&lt;li&gt;A couple of IAM roles to grant Lambda and MediaConvert the permissions they need to do the work they need to do&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At some point, it might be nice to have AWS tell you when a transcoding job is complete — but we can figure that out later. For now, this is fine; we should have all we need in terms of requirements to get going.&lt;/p&gt;
&lt;p&gt;Now let’s do some actual building.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;begin-by-declaring-the-source-and-destination-buckets&quot;&gt;Begin by declaring the source and destination buckets&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Open &lt;code dir=&quot;auto&quot;&gt;index.ts&lt;/code&gt; and clear out the boilerplate code that was generated by the new-project wizard, replacing it with the following lines:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; pulumi &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/pulumi&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; aws &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, { forceDestroy: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;outputBucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, { forceDestroy: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I’ll explain what each line does as we go.&lt;/p&gt;
&lt;p&gt;Lines one and two just import the &lt;code dir=&quot;auto&quot;&gt;@pulumi/pulumi&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;@pulumi/aws&lt;/code&gt; libraries — nothing too exciting there. (The former contains general-purpose Pulumi APIs for things like configuration, outputs, and stacks; the latter for working with AWS resources specifically.) The two lines that follow declare the program’s input and output buckets. Notice that for both buckets, we include the optional &lt;code dir=&quot;auto&quot;&gt;forceDestroy&lt;/code&gt; argument, which tells Pulumi to delete the bucket even when it’s not empty. In real-world scenarios, you might not want to use this setting (it’s &lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; by default), as it’s there to keep you from accidentally deleting your data, but for us, it’s better to use it, as it’ll make make things easier to clean up when we’re done. If we didn’t set this to &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pulumi destroy&lt;/code&gt; would fail loudly with a complaint about the buckets being non-empty. Since we want to be able to clean everything up (videos and all) in one step, &lt;code dir=&quot;auto&quot;&gt;forceDestroy&lt;/code&gt; is the way to go.&lt;/p&gt;
&lt;p&gt;Notice as well that we didn’t have to think up any globally unique names for the S3 buckets. Pulumi’s &lt;a href=&quot;https://www.pulumi.com/docs/concepts/resources/names/#autonaming&quot;&gt;auto-naming&lt;/a&gt; feature takes care of that for us. (As an aside, I must say that I’m a huge and unabashed fan of auto-naming; if you’re using Pulumi and not using auto-naming, you almost surely should be. Yes, I get that the random naming can look a bit strange at first — but the quality-of-life improvements you get in exchange for these quirky appearances is so much more than worth it, I promise.)&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;grant-mediaconvert-permission-to-write-to-s3&quot;&gt;Grant MediaConvert permission to write to S3&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With the buckets defined, create an IAM role to grant MediaConvert permission to write new videos to the output bucket. Add the following lines to the program:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;convertRole&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;iam&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Role&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;convert-role&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;assumeRolePolicy: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;2012-10-17&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Statement:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Effect: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Allow&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Action: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;sts:AssumeRole&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Principal: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Service: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;mediaconvert.amazonaws.com&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;managedPolicyArns:&lt;/span&gt;&lt;span&gt; [aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;iam&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ManagedPolicy&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AmazonS3FullAccess&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This &lt;code dir=&quot;auto&quot;&gt;aws.iam.Role&lt;/code&gt; gives full (i.e., write) S3 access to any MediaConvert job that &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html&quot;&gt;assumes it&lt;/a&gt;. Next, you’ll see how to use this role to post a new transcoding job to the MediaConvert service from AWS Lambda.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;write-the-lambda-upload-handler&quot;&gt;Write the Lambda upload handler&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now it’s time to write the function that’ll be run when a file shows up in the &lt;code dir=&quot;auto&quot;&gt;input&lt;/code&gt; bucket. This function is essentially where your program logic lives: It’s where you codify this: &lt;em&gt;When I upload a video, transcode it with these settings and put the result in this bucket&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There are a few things this function needs to do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, it needs to extract the name of the uploaded file from the Lambda’s &lt;code dir=&quot;auto&quot;&gt;event&lt;/code&gt; argument. (It needs this to tell MediaConvert which video file to convert.)&lt;/li&gt;
&lt;li&gt;Once it has the name, it can use the AWS SDK for JavaScript (which Pulumi bundles with &lt;code dir=&quot;auto&quot;&gt;@pulumi/aws&lt;/code&gt;) to instantiate a MediaConv&lt;code dir=&quot;auto&quot;&gt;e&lt;/code&gt;rt object and call &lt;code dir=&quot;auto&quot;&gt;createJob()&lt;/code&gt; — but it’ll need a couple of values first. One is the &lt;code dir=&quot;auto&quot;&gt;region&lt;/code&gt; of the MediaConvert service to use. (Recall that MediaConvert APIs are all region-specific.) The other is the URL of the region’s MediaConvert endpoint. Both can be read by the function at runtime — the region by reading the value currently configured on the Pulumi stack (which you set a moment ago when you ran &lt;code dir=&quot;auto&quot;&gt;pulumi new&lt;/code&gt;) and the URL by using that region to look up the endpoint with a call to &lt;code dir=&quot;auto&quot;&gt;describeEndpoints()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In addition to those two values, the function also needs the ARN of the IAM role you just defined (the one MediaConvert will assume when it runs) and the name of the &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; bucket to write to. Both can be read similarly using the &lt;code dir=&quot;auto&quot;&gt;.get()&lt;/code&gt; method available on all Pulumi &lt;a href=&quot;https://www.pulumi.com/docs/concepts/inputs-outputs/#outputs&quot;&gt;outputs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It needs need to specify the settings to use for the transcoding job itself. These, as you might imagine, can get pretty complex, but thankfully AWS provides a few shortcuts for the most common ones. (See &lt;a href=&quot;https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html&quot;&gt;Supported Output Codecs and Containers&lt;/a&gt; and &lt;a href=&quot;https://docs.aws.amazon.com/mediaconvert/latest/ug/working-with-presets.html&quot;&gt;Working with Output Presets&lt;/a&gt; in the AWS docs for details.)&lt;/li&gt;
&lt;li&gt;Finally, it needs to be granted permission to make calls on the MediaConvert service. You can do this with the preconfigured IAM policy &lt;code dir=&quot;auto&quot;&gt;AWSElementalMediaConvertFullAccess&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s the whole block, with comments. Go ahead and add this to &lt;code dir=&quot;auto&quot;&gt;index.ts&lt;/code&gt; now:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Config&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onObjectCreated&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;lambda&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CallbackFunction&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;policies: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;iam&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ManagedPolicy&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AWSLambdaExecute&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;arn:aws:iam::aws:policy/AWSElementalMediaConvertFullAccess&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;callback&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;event&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;BucketEvent&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Get the name of the file that was uploaded.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;event&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Records&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Look up the region-specific MediaConvert endpoint.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sdk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;MediaConvert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{ &lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;endpoints&lt;/span&gt;&lt;span&gt; = await &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;describeEndpoints&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;promise&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;endpoint&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;endpoints&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Endpoints&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Url&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Submit a new MediaConvert job request.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;jobRequest&lt;/span&gt;&lt;span&gt; = await &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sdk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;MediaConvert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{ &lt;/span&gt;&lt;span&gt;endpoint&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createJob&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Role: convertRole&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;arn&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Settings: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Inputs: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;FileInput: &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;s3://&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;AudioSelectors: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Audio Selector 1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;SelectorType: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;TRACK&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Tracks: [&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OutputGroups: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;File Group&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Outputs: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Extension: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;mp4&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Preset: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;System-Generic_Hd_Mp4_Avc_Aac_16x9_1280x720p_24Hz_4.5Mbps&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OutputGroupSettings: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Type: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;FILE_GROUP_SETTINGS&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;FileGroupSettings: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Destination: &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;s3://&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;outputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;promise&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Log the request result.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;({ jobRequest });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A few things to note about what’s going on here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first line just reads the AWS region from the stack configuration, as mentioned above.&lt;/li&gt;
&lt;li&gt;The next line uses a couple of Pulumi resources to create a Lambda event handler known as a &lt;a href=&quot;https://www.pulumi.com/docs/clouds/aws/guides/lambda/#register-an-event-handler-using-a-magic-lambda-function&quot;&gt;magic function&lt;/a&gt;. The Pulumi docs explain how magic functions work in more detail, but the gist is that when they’re expressed in this way, Pulumi is able to package up Lambda functions for you (along with their dependencies and any closed-over variables) and create the &lt;a href=&quot;https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html&quot;&gt;S3 triggers&lt;/a&gt; to invoke the function in response to interesting events — e.g., uploads.&lt;/li&gt;
&lt;li&gt;The IAM &lt;code dir=&quot;auto&quot;&gt;policies&lt;/code&gt; to apply to the Lambda are passed as an array of strings — one of which, sadly, lacks a TypeScript constant of its own. At deploy-time, Pulumi will use these policies to create an IAM role for the Lambda to assume when it runs in response to an upload event.&lt;/li&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;event&lt;/code&gt; passed into the function is exposed as a typed &lt;code dir=&quot;auto&quot;&gt;aws.s3.BucketEvent&lt;/code&gt; — a useful thing for figuring out (with the help of your IDE’s built-in type hinting) how to unwrap that event to get at its most useful parts.&lt;/li&gt;
&lt;li&gt;Because we’re working with Node.js, we can also use the syntactic sweetness of &lt;code dir=&quot;auto&quot;&gt;async&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;await&lt;/code&gt; to make working with the promise-based AWS SDK a little nicer.&lt;/li&gt;
&lt;li&gt;The &lt;code dir=&quot;auto&quot;&gt;console.log()&lt;/code&gt; statement at the end writes an entry to Amazon CloudWatch logs for the function — a convenient way to debug runtime behavior when you need to. (In a moment you’ll see how convenient that can be.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the buckets, IAM role, and Lambda now written, you’re just about ready to deploy to AWS. All you need now are the names of your buckets-to-be.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;export-the-source-and-destination-bucket-names&quot;&gt;Export the source and destination bucket names&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Add the following two lines to finish the program:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export const &lt;/span&gt;&lt;span&gt;inputBucketID&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export const &lt;/span&gt;&lt;span&gt;outputBucketID&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;outputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;These last two lines expose the &lt;code dir=&quot;auto&quot;&gt;input&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; bucket names as Pulumi &lt;code dir=&quot;auto&quot;&gt;stack outputs&lt;/code&gt;. Technically, they aren’t programmatically necessary, but if we left them out, we’d have to do a little digging to find out what the generated (i.e., auto-named) input and output bucket names were in order to work with them. Exporting them as outputs will render them onscreen when the deployment completes — and also give us a handy way of referencing them (as you’ll see) without having to copy and paste anything on the command line.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;deploy&quot;&gt;Deploy!&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now it’s time to push this program out into the world and start using it. Here, for reference, is what you should now have for index.ts:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; pulumi &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/pulumi&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; aws &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Read the AWS region from the currently selected stack.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Config&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Provision two buckets: one for uploads, one for transcodes.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, { forceDestroy: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;outputBucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, { forceDestroy: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Define a role that grants MediaConvert permission to write to S3.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;convertRole&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;iam&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Role&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;convert-role&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;assumeRolePolicy: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Version: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;2012-10-17&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Statement:&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Effect: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Allow&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Action: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;sts:AssumeRole&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Principal: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Service: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;mediaconvert.amazonaws.com&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;managedPolicyArns:&lt;/span&gt;&lt;span&gt; [aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;iam&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ManagedPolicy&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AmazonS3FullAccess&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Handle uploads by extracting the video filename and creating a new MediaConvert job.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;onObjectCreated&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;lambda&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CallbackFunction&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;policies: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;iam&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ManagedPolicy&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AWSLambdaExecute&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;arn:aws:iam::aws:policy/AWSElementalMediaConvertFullAccess&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;callback&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;event&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;BucketEvent&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Get the name of the file that was uploaded.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;event&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Records&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Look up the region-specific MediaConvert endpoint.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sdk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;MediaConvert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{ &lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;endpoints&lt;/span&gt;&lt;span&gt; = await &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;describeEndpoints&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;promise&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;endpoint&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;endpoints&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Endpoints&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Url&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Submit a new MediaConvert job request.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;jobRequest&lt;/span&gt;&lt;span&gt; = await &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sdk&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;MediaConvert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{ &lt;/span&gt;&lt;span&gt;endpoint&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createJob&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Role: convertRole&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;arn&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Settings: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Inputs: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;FileInput: &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;s3://&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;AudioSelectors: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Audio Selector 1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;SelectorType: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;TRACK&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Tracks: [&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OutputGroups: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;File Group&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Outputs: [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Extension: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;mp4&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Preset: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;System-Generic_Hd_Mp4_Avc_Aac_16x9_1280x720p_24Hz_4.5Mbps&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;OutputGroupSettings: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Type: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;FILE_GROUP_SETTINGS&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;FileGroupSettings: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Destination: &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;s3://&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;outputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;promise&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;// Log the request result.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;console&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;({ jobRequest });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Export the input and output bucket IDs.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export const &lt;/span&gt;&lt;span&gt;inputBucketID&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;inputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export const &lt;/span&gt;&lt;span&gt;outputBucketID&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;outputBucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Deploy the program with a single pulumi up, checking the preview to make sure everything looks right:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Do&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;you&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;want&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;perform&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;update?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;yes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Updating&lt;/span&gt;&lt;span&gt; (dev)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;                                  &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;Status&lt;/span&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;Info&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;pulumi:pulumi:Stack&lt;/span&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;mediaconvert-dev&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (3s)        4 messages&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:Role&lt;/span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (0.93s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:Role&lt;/span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;span&gt;convert-role&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (1s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (1s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;             &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (1s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:BucketEventSubscription&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (0.40s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:lambda:Permission&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (0.35s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:BucketNotification&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (0.73s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:RolePolicyAttachment&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler-aadec3c3&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (0.34s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:RolePolicyAttachment&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler-2cc11edf&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (0.48s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:lambda:Function&lt;/span&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;span&gt; (13s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Outputs:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;inputBucketID&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;input-8a99139&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;outputBucketID:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;output-01cb7a4&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Resources:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Duration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;20s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;When the deployment completes (which should take only a few seconds), you’ll be left with your two uniquely named buckets.&lt;/p&gt;
&lt;p&gt;That’s it! Now let’s transcode some video.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;upload-a-video-to-convert&quot;&gt;Upload a video to convert&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Open a new terminal tab and navigate to the directory containing the project, then run the following command:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stack&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputBucketID&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In response, you should get the name of the auto-named input bucket. Here’s what I see when I run that command, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;input-8a99139&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now, back in the other terminal tab (the one where you just ran pulumi up), run pulumi logs to tail the CloudWatch logs for the Lambda you just created:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--follow&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Collecting&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stack&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;since&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2023-07-07T15:25:22.000-07:00.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Let that run, then switch over to the tab with the input bucket name and upload a video file from your computer with the AWS CLI. Use &lt;code dir=&quot;auto&quot;&gt;pulumi stack output&lt;/code&gt; to pass the name of the input bucket to &lt;code dir=&quot;auto&quot;&gt;aws s3 cp&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/Desktop/wailua-falls.mov&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3://&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stack&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputBucketID&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;upload:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;../../../Desktop/wailua-falls.mov&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3://input-8a99139/wailua-falls.mov&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In a few seconds, your still-running &lt;code dir=&quot;auto&quot;&gt;pulumi logs&lt;/code&gt; command should show you that the Lambda was invoked and the convert job created. Here’s what I see:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Collecting logs for stack dev since 2023-07-08T04:43:55.000-07:00.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;2023-07-08T05:53:52.739-07:00[               handler-6a8088f] INIT_START Runtime Version: nodejs:16.v15        Runtime Version ARN: arn:aws:lambda:us-west-2::runtime:ce158dcc19c42286fef86a8dfb67e1efd92d0de18828736a00f3698410aabcb3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2023-07-08T05:53:52.857-07:00[               handler-6a8088f] START RequestId: ee791b7f-c245-41bd-8a5e-d180847cf65a Version: $LATEST&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2023-07-08T05:54:01.170-07:00[               handler-6a8088f] 2023-07-08T12:54:01.170Z ee791b7f-c245-41bd-8a5e-d180847cf65a    INFO    {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;jobRequest: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Job: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;AccelerationSettings: [Object],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;AccelerationStatus: &apos;NOT_APPLICABLE&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Arn: &apos;arn:aws:mediaconvert:us-west-2:616138583583:jobs/1688820840907-0s24me&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ClientRequestToken: &apos;f477b33d-7913-4285-9ae4-23d36282601e&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CreatedAt: 2023-07-08T12:54:00.000Z,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Id: &apos;1688820840907-0s24me&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Messages: [Object],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Priority: 0,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Queue: &apos;arn:aws:mediaconvert:us-west-2:616138583583:queues/Default&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Role: &apos;arn:aws:iam::616138583583:role/convert-role-b765342&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Settings: [Object],&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Status: &apos;SUBMITTED&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;StatusUpdateInterval: &apos;SECONDS_60&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Timing: [Object]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2023-07-08T05:54:01.209-07:00[               handler-6a8088f] END RequestId: ee791b7f-c245-41bd-8a5e-d180847cf65a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2023-07-08T05:54:01.209-07:00[               handler-6a8088f] REPORT RequestId: ee791b7f-c245-41bd-8a5e-d180847cf65a   Duration: 8352.45 msBilled Duration: 8353 ms Memory Size: 128 MB     Max Memory Used: 86 MB  Init Duration: 117.12 ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Soon (depending on the length of the video you submitted), you should see a new transcoded video appear in the &lt;code dir=&quot;auto&quot;&gt;output&lt;/code&gt; bucket:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ls&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3://&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stack&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;outputBucketID&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;2023-07-08&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;05:54:10&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;7954412&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wailua-falls.mov.mp4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Copy that file from the output bucket to your computer:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3://&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stack&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;outputBucketID&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;/wailua-falls.mov.mp4&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;download:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3://output-01cb7a4/wailua-falls.mov.mp4&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./wailua-falls.mov.mp4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And behold — the delightfully web-friendly result:&lt;/p&gt;
&lt;p&gt;0:00/0:131×&lt;/p&gt;
&lt;p&gt;Feel free to submit a few others, fiddle with the conversion settings, etc., to get a feel for how everything works. There’s a ton you can with this service — way more than I could ever hope to cover in a post like this one. &lt;a href=&quot;https://docs.aws.amazon.com/mediaconvert/latest/ug/what-is.html&quot;&gt;See the MediaConvert docs&lt;/a&gt; for some creative inspiration, and when you’ve had enough fun for today, read on to learn about how to clean everything up.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;tidying-up&quot;&gt;Tidying up&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Just as you were able to stand up this whole stack with a single &lt;code dir=&quot;auto&quot;&gt;pulumi up&lt;/code&gt;, you can tear it all down with a single &lt;code dir=&quot;auto&quot;&gt;pulumi destroy&lt;/code&gt;. Doing so removes everything you created with the program in one go — the Lambda, IAM roles, and both buckets, along with their contents. As before, you’ll get a preview of the changes before Pulumi actually applies any of them:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;destroy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Previewing&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;destroy&lt;/span&gt;&lt;span&gt; (dev)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;                                  &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;Plan&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;pulumi:pulumi:Stack&lt;/span&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;mediaconvert-dev&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:RolePolicyAttachment&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler-aadec3c3&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:RolePolicyAttachment&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler-2cc11edf&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:lambda:Function&lt;/span&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:Role&lt;/span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;span&gt;convert-role&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;             &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:BucketNotification&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:BucketEventSubscription&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:lambda:Permission&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:Role&lt;/span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Outputs:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputBucketID&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;input-8a99139&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;outputBucketID:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;output-01cb7a4&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Resources:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Do&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;you&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;want&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;perform&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;destroy?&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; yes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;no&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;details&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Choose yes if it all looks right (which it should):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Do&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;you&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;want&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;perform&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;destroy?&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;yes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Destroying&lt;/span&gt;&lt;span&gt; (dev)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;View&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Browser&lt;/span&gt;&lt;span&gt; (Ctrl+O): https://app.pulumi.com/christian-pulumi-corp/mediaconvert/dev/updates/29&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;                                  &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;Status&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;pulumi:pulumi:Stack&lt;/span&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;mediaconvert-dev&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:RolePolicyAttachment&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler-aadec3c3&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (0.90s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:RolePolicyAttachment&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler-2cc11edf&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (0.79s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:lambda:Function&lt;/span&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (0.84s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt;             &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (0.81s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:BucketNotification&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (0.75s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:BucketEventSubscription&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;│&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:lambda:Permission&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (0.45s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (1s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:Role&lt;/span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (0.81s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:iam:Role&lt;/span&gt;&lt;span&gt;                       &lt;/span&gt;&lt;span&gt;convert-role&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt; (1s)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Outputs:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inputBucketID&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;input-8a99139&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;outputBucketID:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;output-01cb7a4&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Resources:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Duration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;6s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And there you have it.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I must admit, as an &lt;a href=&quot;https://chris.nunciato.org/&quot;&gt;amateur photographer and filmmaker&lt;/a&gt;, I tend to get pretty excited about this sort of thing; I love how easy these tools make solving these kinds of real-world media-management problems. Dealing with stuff like this can be a huge pain sometimes — especially when you’re drowning in terabytes of HD video and all you’re trying to do is share a few clips of your kids playing soccer with their grandparents.&lt;/p&gt;
&lt;p&gt;And as a developer, it kind of blows my mind how easily I can do this, and with so little operational overhead. It’s one thing to provision a virtual machine and throw files at it once a week while it sits there running (and costing you money) 24 hours a day, begging to be compromised. It’s quite another to deploy configuration like this that doesn’t really do anything at all until it’s asked, and then quietly shuts back down when it’s finished doing whatever it is you’ve asked it to do. Even if you aren’t quite as sold on serverless as I am (yet!), you’ve got to admit that it’s nice not having to think about — let alone pay for or manage — running infrastructure that you only need every once in a while.&lt;/p&gt;
&lt;p&gt;So I guess that’s it for this episode. Keep an eye out for more in the weeks ahead, subscribe if you like (&lt;a href=&quot;https://pulumibook.com/rss/&quot;&gt;right here if RSS is your jam&lt;/a&gt;), and check out the repo below for the code. Comments, questions, reach out anytime.&lt;/p&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;</content:encoded><category>serverless</category><category>aws</category></item><item><title>Sync a Folder to Any Cloud with Pulumi</title><link>https://pulumibook.com/blog/sync-a-folder-to-any-cloud-with-pulumi/</link><guid isPermaLink="true">https://pulumibook.com/blog/sync-a-folder-to-any-cloud-with-pulumi/</guid><description>Getting a folder of files into the cloud is fiddlier than it should be. Meet Synced Folder, a small multi-language Pulumi component that makes it a one-liner.

</description><pubDate>Sat, 22 Oct 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lately I’ve been hacking away on a handful of &lt;a href=&quot;https://pulumi.com/templates&quot;&gt;Pulumi templates&lt;/a&gt; to make it easier to deploy common cloud architectures --- static websites, serverless apps, containers, virtual machines, and the like. The idea with templates is that with a single run of &lt;code dir=&quot;auto&quot;&gt;pulumi new&lt;/code&gt;, you should be able to kick out a finished program, in your language of choice, that works out of the box and can handle the most common scenarios, while still leaving you plenty of room for expansion and customization. Templates, I think, are one of Pulumi’s most unsung (and unique) features; unlike &lt;a href=&quot;https://www.pulumi.com/docs/intro/concepts/resources/components/&quot;&gt;components&lt;/a&gt;, they’re open rather than closed, so they tend to be great not just for bootstrapping new projects, but also as tools for learning, as they’re pretty much made to be tinkered with.&lt;/p&gt;
&lt;p&gt;My first task was to build out a set of templates for &lt;a href=&quot;https://pulumi.com/templates/static-website&quot;&gt;static websites&lt;/a&gt;, which, as you probably know, are essentially just a bunch of HTML, CSS, and JavaScript files stuffed into a folder somewhere. This site, for example, is a static website built with &lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt;, one of the more popular static-site generators these days, and as of today, it clocks in at a little over a thousand pages. At work, we build &lt;a href=&quot;https://pulumi.com/&quot;&gt;pulumi.com&lt;/a&gt; with another popular static-site generator called &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;, and all up, that site comes in at a little over 20,000 pages. Static websites vary drsmatically in terms of size and complexity, but ultimately they all have that same thing in common: they’re all just a bunch of files in a folder on a computer connected to the internet --- a computer that likely belongs either to Amazon Web Service, Microsoft Azure, or Google Cloud Platform.&lt;/p&gt;
&lt;p&gt;But while building out the first set of these templates, I ran into a problem: getting files into the cloud isn’t always as easy as you’d think, at least not with declarative infrastucture-as-code tools like Pulumi.&lt;/p&gt;
&lt;p&gt;Here’s an example. Imagine you had a bunch of files in a folder on your computer that you wanted to get into the cloud. With Pulumi, the way to do that would be to begin by writing a program declaring some cloud storage, which, if you were using AWS, might look something like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; aws &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Easy enough, bucket created. Now, let’s upload some files!&lt;/p&gt;
&lt;p&gt;Here’s where things get tricky, though. Most of the examples you’ll find online (including several I’ve written myself) handle this by using the programming environment to fetch a list of files from the filesystem, then declare them, one by one, as individual cloud resources, like so:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; aws &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; fs &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;fs&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; mime &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;mime&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; glob &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;glob&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// List the files in `myFolder`, then for each one, declare an `s3.BucketObject`.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;glob&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;myFolder&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;/**/*&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;fs&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;lstatSync&lt;/span&gt;&lt;span&gt;(path)&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;isDirectory&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;let &lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;BucketObject&lt;/span&gt;&lt;span&gt;(path&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;replace&lt;/span&gt;&lt;span&gt;(siteDir&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bucket: &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;source: &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;asset&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;FileAsset&lt;/span&gt;&lt;span&gt;(path)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;contentType: &lt;/span&gt;&lt;span&gt;mime&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getType&lt;/span&gt;&lt;span&gt;(path)&lt;/span&gt;&lt;span&gt; || &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;text/plain&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And this works, to be sure. With Python, Go, C#, Java, things look a bit different of course, but in general, the approach is the same: make a bucket, then use the facilities of your chosen programming language to get the files into the bucket.&lt;/p&gt;
&lt;p&gt;But while being able to break out of the declarative box and write a little code when you need to is awesome --- indeed, it’s one of the other things that makes Pulumi so special --- there’s something about having to write code like this I also find a bit irritating. All I need to do point a push a folder into the cloud. Shouldn’t I be able to just say that? Why do I have to dig into the filesystem, generate and manipulate a bunch of file paths, programmatically deduce MIME types, and so on, just to move a bunch of stuff verbatim from one folder to another? I mean it’s great that you can do that, sure. But it’d also be great if you didn’t have to.&lt;/p&gt;
&lt;p&gt;And sometimes, you just can’t. Take YAML, for instance. I love our YAML support. It’s so tidy:&lt;/p&gt;
&lt;p&gt;resources:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;But there’s one little problem with YAML: It isn’t a programming language. Unlike with languages like TypeScript and others, you can’t break out of the box and reach into the filesystem with YAML --- and that’s by design. We built YAML to give our users the tersest, most statically declarative option we could, and we did: you literally can’t write code with Pulumi YAML, just &lt;a href=&quot;https://www.pulumi.com/docs/reference/yaml/#expressions&quot;&gt;expressions&lt;/a&gt;. Of course, you can always &lt;a href=&quot;https://www.pulumi.com/docs/reference/cli/pulumi_convert/&quot;&gt;convert your program to a different language&lt;/a&gt; if you find YAML too limiting, and that’s great, too --- but it’s also a pretty big thing to have consider when all you need to do is push a few files into the cloud.&lt;/p&gt;
&lt;p&gt;So I took a few days to figure this out, for all languages and all three major clouds. The result is a little &lt;a href=&quot;https://www.pulumi.com/docs/guides/pulumi-packages/&quot;&gt;Pulumi package&lt;/a&gt; called &lt;a href=&quot;https://www.pulumi.com/registry/packages/synced-folder/&quot;&gt;Synced Folder&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;introducing-synced-folder&quot;&gt;Introducing Synced Folder&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Synced Folder is a &lt;a href=&quot;https://www.pulumi.com/blog/pulumiup-pulumi-packages-multi-language-components/&quot;&gt;multi-language Pulumi component&lt;/a&gt; that you can install and use with any Pulumi-supported language. It’s deliberately simple and focused, and it works --- or at least it’s my hope that it works --- exactly as you’d imagine: make a bucket, sync a folder to that bucket, and be done. Here’s how it looks in TypeScript, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; aws &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; synced &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acl: &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;PublicReadAcl&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Sync the contents of `my-folder` to the bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;synced&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;S3BucketFolder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;path: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;./my-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bucketName: &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acl: &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;PublicReadAcl&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Here’s an example in Python:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pulumi_aws &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; s3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; pulumi_synced_folder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bucket &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; s3.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;acl&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;s3.CannedAcl.PUBLIC_READ&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;# Sync the contents of `my-folder` to the bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;folder &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; pulumi_synced_folder.&lt;/span&gt;&lt;span&gt;S3BucketFolder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;./my-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;bucket_name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;bucket.bucket&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;acl&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;s3.CannedAcl.PUBLIC_READ&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And in Go:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;github.com/pulumi/pulumi-aws/sdk/v5/go/aws/s3&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;synced&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;github.com/pulumi/pulumi-synced-folder/sdk/go/synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;github.com/pulumi/pulumi/sdk/v3/go/pulumi&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;pulumi.Context) &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;NewBucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt;s3.BucketArgs{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;Acl&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CannedAclPublicRead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// Sync the contents of `my-folder` to the bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;synced&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;NewS3BucketFolder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&amp;#x26;&lt;/span&gt;&lt;span&gt;synced.S3BucketFolderArgs{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;Path&lt;/span&gt;&lt;span&gt;:       &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;./my-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;BucketName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;Acl&lt;/span&gt;&lt;span&gt;:        &lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;CannedAclPublicRead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In C#:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Pulumi&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Pulumi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;S3&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Pulumi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SyncedFolder&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Deployment&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;RunAsync&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; bucket &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Bucket(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BucketArgs {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Acl &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CannedAcl&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;PublicRead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// Sync the contents of `my-folder` to the bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; folder &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; S3BucketFolder(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; S3BucketFolderArgs {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Path &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;./my-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;BucketName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;BucketName&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Acl &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;CannedAcl&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;PublicRead&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And finally, in YAML:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# Make a bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;acl&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;public-read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# Sync the contents of `my-folder` to the bucket.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;synced-folder&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;synced-folder:index:S3BucketFolder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;./my-folder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;bucketName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${my-bucket.bucket}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;acl&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;public-read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And if you’re targeting Microsoft Azure or Google Cloud, it’s just the same: make an Azure Blob Storage container or a Google Cloud Storage bucket, then drop in a reference to Synced Folder and call it a day. &lt;a href=&quot;https://www.pulumi.com/registry/packages/synced-folder/&quot;&gt;See the docs&lt;/a&gt; for examples with various languages and clouds.&lt;/p&gt;
&lt;p&gt;To deploy the contents of the folder, just run pulumi up in the usual way:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;When you make local changes to the files in your synced folder --- add new files, delete old ones, change existing ones, etc. --- simply deploy the changes again in the same way. (Changes, by the way, are synced one way only, folder to cloud, so deleting a file in the cloud will have no effect on the files on your local machine.)&lt;/p&gt;
&lt;p&gt;To remove the cloud bucket and all of its contents, run &lt;code dir=&quot;auto&quot;&gt;pulumi destroy&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;destroy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Pretty neat, IMHO --- and again, hopefully works just like you’d expect.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;bonus-feature-unmanaged-file-objects&quot;&gt;Bonus feature: Unmanaged file objects&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;One thing you’ll notice about the component’s default behavior is that it manages your files as individual cloud resources --- e.g., as discrete Amazon &lt;code dir=&quot;auto&quot;&gt;s3.BucketObject&lt;/code&gt;s or Azure &lt;code dir=&quot;auto&quot;&gt;storage.Blob&lt;/code&gt;s --- and not just as an abstract “folder” resource. For folders that contain only a few files, that’s probably fine, and indeed it’s sometimes nice to have Pulumi track changes to those files individually as well. But if your folder were to contain, say, a thousand files or more, you could end up waiting a long time for Pulumi to examine and reconcile the state of every last one of those file objects. Moreover, if you happen to be using Pulumi on a commercial plan, you might not love the idea of each one of those objects contributing to your monthly bill.&lt;/p&gt;
&lt;p&gt;So to address these two unpleasantries, I added an option to instruct Pulumi to ignore individual files and instead, delegate the work of synchronization to the cloud provider’s official CLI. By setting the optional property &lt;code dir=&quot;auto&quot;&gt;managedObjects&lt;/code&gt; to &lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt;, you can have Pulumi invoke the AWS, Azure, or Google Cloud CLI during an update to sync your files that way instead:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; aws &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; synced &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;my-bucket&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acl: &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;PublicReadAcl&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;synced&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;S3BucketFolder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;synced-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;path: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;./my-folder&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bucketName: &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;acl: &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;PublicReadAcl&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 👇 Set this property to false to manage files with `aws s3 sync`.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;managedObjects: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Synchronization-wise, the effect the same: files that exist locally but not remotely are uploaded, and those that exist remotely but not locally are deleted. But the upshot is that it’s much faster and less expensive than using Pulumi alone, so if you’re okay with Pulumi shelling out to the &lt;code dir=&quot;auto&quot;&gt;aws&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;az&lt;/code&gt;, or &lt;code dir=&quot;auto&quot;&gt;gcloud&lt;/code&gt; command-line tools, you might want to give it a try. Again, &lt;a href=&quot;https://www.pulumi.com/registry/packages/synced-folder/#managed-and-unmanaged-file-objects&quot;&gt;see the docs for details and examples&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy! And happy Pulumifying.&lt;/p&gt;</content:encoded><category>aws</category><category>azure</category><category>gcp</category><category>packages</category></item><item><title>Imperatively Declarative: How Pulumi Is Different</title><link>https://pulumibook.com/blog/imperatively-declarative-how-pulumi-is-different/</link><guid isPermaLink="true">https://pulumibook.com/blog/imperatively-declarative-how-pulumi-is-different/</guid><description>Pulumi often gets filed under “imperative” because you write it in real languages — but that misses what’s actually going on. A look at why Pulumi is declarative where it counts.

</description><pubDate>Mon, 09 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In conversations about &lt;a href=&quot;https://en.wikipedia.org/wiki/Infrastructure_as_code&quot;&gt;infrastructure as code&lt;/a&gt;, the debate over &lt;a href=&quot;https://en.wikipedia.org/wiki/Infrastructure_as_code#Types_of_approaches&quot;&gt;imperative versus declarative&lt;/a&gt; tools still comes up from time to time. Actually, there’s not much left to debate: declarative’s pretty much won. But somehow, the subject still manages to get people going, probably because what “declarative” means isn’t quite as clear as it used to be --- and that’s partly because of tools like Pulumi.&lt;/p&gt;
&lt;p&gt;When Pulumi comes up in one of these conversations, it usually gets placed on the imperative end of the spectrum; it’s an easy mistake to make, considering Pulumi programs are written in imperative languages like JavaScript. But it’s a mistake nonetheless. &lt;a href=&quot;https://twitter.com/brianleroux/status/1415310789167046657&quot;&gt;Here’s an example of such an exchange&lt;/a&gt; from a while back, for instance:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I will be very specific using my previous example. JS is imperative. JSON is declarative.&lt;/p&gt;
&lt;p&gt;--- Brian LeRoux (@brianleroux) &lt;a href=&quot;https://twitter.com/brianleroux/status/1415310789167046657&quot;&gt;July 14, 2021&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It’s worth mentioning that Brian is the creator of &lt;a href=&quot;https://arc.codes/docs/en/guides/get-started/quickstart&quot;&gt;arc.codes&lt;/a&gt;, a command-line tool that lets you write blocks of JSON or YAML to deploy serverless functions and other things on &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;AWS&lt;/a&gt;. Arc is a perfect example of simple, declarative infrastructure as code that’s focused on making the &lt;a href=&quot;https://www.google.com/books/edition/Programming_Perl/xx5JBSqcQzIC?hl=en&amp;#x26;gbpv=1&amp;#x26;bsq=%22easy%20things%20should%20be%20easy,%20and%20hard%20things%20should%20be%20possible%22&quot;&gt;easy things easy&lt;/a&gt;. Take a look at this terse little Arc file, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;hello-world&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;/thing1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;/thing2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In Arc, this bit of YAML states that at the end of an Arc run, two publicly accessible HTTP endpoints should exist in &lt;a href=&quot;https://aws.amazon.com&quot;&gt;AWS Lambda&lt;/a&gt; (at a URL dynamically assigned by AWS) at the paths &lt;code dir=&quot;auto&quot;&gt;/thing1&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;/thing2&lt;/code&gt;, and that both endpoints should be wired up to respond to HTTP &lt;code dir=&quot;auto&quot;&gt;GET&lt;/code&gt;s. When you run this file with the Arc CLI --- assuming you’ve stashed your AWS credentials in the right place, and put your JavaScript functions in a nearby subfolder --- that’ll indeed be the case: a minute or so later, those endpoints &lt;em&gt;will&lt;/em&gt; exist, and all will be right with the world. Easy.&lt;/p&gt;
&lt;p&gt;Moreover, if you were to run that code a &lt;em&gt;second&lt;/em&gt; time (having made no changes to the YAML or JavaScript), nothing would happen, because the “desired state” you’d expressed in the &lt;code dir=&quot;auto&quot;&gt;arc.yaml&lt;/code&gt; file would already have been achieved: with those two endpoints deployed and running in the AWS cloud, Arc (by way of &lt;a href=&quot;https://aws.amazon.com/cloudformation/&quot;&gt;CloudFormation&lt;/a&gt;) would have nothing more to do for you. That’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Declarative_programming&quot;&gt;declarative&lt;/a&gt; infrastructure-as-code (IaC) at work: you describe &lt;em&gt;what you want&lt;/em&gt; --- two HTTP endpoints --- and the IaC tool determines the &lt;em&gt;how&lt;/em&gt;, computing the work to be done and then making it happen for you.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Imperative_programming&quot;&gt;&lt;em&gt;Imperative&lt;/em&gt;&lt;/a&gt; IaC, on the other hand, is different. In imperative programming (e.g., in most JavaScript), the code that you write is all about control --- &lt;em&gt;do this, then that; if this, then that&lt;/em&gt;. A good example of the difference between declarative and imperative programming would be to compare the experience of building a web page statically with hand-crafted HTML (which is about as declarative as you can get):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;section&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;things&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;ol&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Thing 1&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Thing 2&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Thing 3&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;ol&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;section&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;… to building one dynamically by &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/How_to_create_a_DOM_tree&quot;&gt;scripting the DOM&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;let &lt;/span&gt;&lt;span&gt;ul&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;document&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createElement&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;ol&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;span&gt;++&gt;&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;let &lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;document&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createElement&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;textContent&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;Thing &lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ul&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;appendChild&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;document&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;querySelector&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;#things&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;appendChild&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ul&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Both yield the same result --- a three-item list --- but in fundamentally different ways. In HTML, the author says what they want, up front, and lets the browser handle the rest. In JavaScript, however, the author tells the browser &lt;em&gt;how&lt;/em&gt; to create that list, algorithmically, one element at a time before attaching it programmatically to the page at some point later.&lt;/p&gt;
&lt;p&gt;IaC tools vary similarly. Classically declarative tools like Arc, &lt;a href=&quot;https://aws.amazon.com/cloudformation/&quot;&gt;CloudFormation&lt;/a&gt;, &lt;a href=&quot;https://www.terraform.io/&quot;&gt;Terraform&lt;/a&gt;, and others have you type out what you want, usually in some sort of structured configuration, and handle the work of provisioning and updating for you. Imperative tools don’t do nearly as much; instead, they give &lt;em&gt;you&lt;/em&gt; the APIs to tell &lt;em&gt;them&lt;/em&gt; what to do and how to do it.&lt;/p&gt;
&lt;p&gt;As an example, imagine you wanted to create a couple of storage buckets on &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;Amazon S3&lt;/a&gt;. To do that imperatively, you might reach for Amazon’s &lt;a href=&quot;https://aws.amazon.com/sdk-for-javascript/&quot;&gt;SDK for JavaScript&lt;/a&gt; and tap out a small imperative program like this one:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const { &lt;/span&gt;&lt;span&gt;S3Client&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;CreateBucketCommand&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ListBucketsCommand&lt;/span&gt;&lt;span&gt; } = &lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@aws-sdk/client-s3&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;S3Client&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{ region: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;us-west-2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// Name a couple of buckets.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;desiredBuckets&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;bucket-1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;bucket-2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; =&gt; &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;some-interestingly-named-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// Imperatively create them, by calling the AWS S3 API directly.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;desiredBuckets&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;send&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CreateBucketCommand&lt;/span&gt;&lt;span&gt;&lt;span&gt;({ Bucket: &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; }));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// Finally, list all buckets, including the two you just created.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;console&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;send&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ListBucketsCommand&lt;/span&gt;&lt;span&gt;({})))&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Buckets&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You could run this program with Node.js (again, assuming your AWS creds were stashed &lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html&quot;&gt;in their proper locations&lt;/a&gt;), and in a few moments, produce the following result:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;node&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.js&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;some-interestingly-named-bucket-1&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CreationDate: 2021-03-08T18:00:04.000Z&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name: &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;some-interestingly-named-bucket-2&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CreationDate: 2021-03-08T18:00:04.000Z&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Nice, right? And easy enough --- assuming you’re comfortable with JavaScript.&lt;/p&gt;
&lt;p&gt;However, unlike the Arc example I shared earlier, running the program a second time would fail:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;node&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.js&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;UnhandledPromiseRejectionWarning:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BucketAlreadyOwnedByYou&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;… which is unfortunate, but makes sense, considering the buckets would already have been created. To keep repeated runs of the program from failing --- an important consideration, say, if the program were running as a part of an automated deployment process --- you’d have to write a bit more code to check for the existence of each bucket &lt;em&gt;before&lt;/em&gt; attempting to create it:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;desiredBuckets&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;bucket-1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;bucket-2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; =&gt; &lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;some-interestingly-named-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// First, fetch a list of all buckets.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;allBuckets&lt;/span&gt;&lt;span&gt; = await &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;send&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ListBucketsCommand&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{}&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;allBucketNames&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;allBuckets&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Buckets&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;/span&gt;&lt;span&gt; =&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// Create the new buckets...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;desiredBuckets&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// ...but only if they haven&apos;t been created already.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;allBucketNames&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;client&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;send&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CreateBucketCommand&lt;/span&gt;&lt;span&gt;&lt;span&gt;({ Bucket: &lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt; }));&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;})();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And that’d certainly work.&lt;/p&gt;
&lt;p&gt;But at the same time, all you really need is a couple of S3 buckets, here, and already you’ve begun to accumulate a good bit of code --- code that has to be debugged, tested, maintained, and all the rest. If you wanted to assemble something a little more complicated --- a couple of serverless endpoints, maybe, or the virtual infrastructure to run a typical web application --- you’d be looking at writing a lot &lt;em&gt;more&lt;/em&gt; code, and this pattern of checking &lt;em&gt;whether&lt;/em&gt; to do something before actually doing it (or doing something slightly different, maybe, under certain conditions) would continue to the point that it’d be hard for someone else (or even a future version of yourself) to look at the code and understand what was really going on --- certainly much harder than looking at a few lines of declarative YAML. Sometimes, of course, imperative code is just what you need. But for &lt;a href=&quot;https://en.wikipedia.org/wiki/Infrastructure_as_code#Added_value_and_advantages&quot;&gt;lots of reasons&lt;/a&gt;, declarative tools are usually the right way to go --- which is why, as I said, the debate’s pretty much over.&lt;/p&gt;
&lt;p&gt;Where does that leave Pulumi, though? If Pulumi programs really are written in imperative languages like JavaScript, doesn’t that make Pulumi itself an imperative tool, too, by extension?&lt;/p&gt;
&lt;p&gt;In a word, no --- but understanding &lt;em&gt;why&lt;/em&gt; the answer is no takes a bit more explanation.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;breakfast-as-code&quot;&gt;Breakfast as code&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I haven’t always been a big breakfast person, but these days, I am, and for me, breakfast usually means an egg, some toast, and a bit of orange juice, with an occasional bunch of leafy-green things thrown in for good measure. Represented as JSON, my usual breakfast looks something like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;breakfast&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;eggs&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;count&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;kind&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;scrambled&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;toast&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;count&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;kind&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;multi-grain&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;juice&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;count&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&quot;kind&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;orange&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It’s a fairly common choice, as breakfasts go --- so common that I could probably walk into any café, hand someone this snippet of JSON, and wait patiently for the result to show up on the table in front of me. In a way, this is declarative breakfast-as-code: I say what I want --- egg, toast, juice --- and a bunch of skilled humans conspire to make that happen for me.&lt;/p&gt;
&lt;p&gt;And while I certainly &lt;em&gt;know&lt;/em&gt; there’s an order in which these things tend to happen --- the eggs need scrambling, so the chef may prep them first; the toast goes quicker, so that’ll probably happen later, etc. --- that order isn’t important to &lt;em&gt;me&lt;/em&gt; as a customer. In the end, all I care about is that when breakfast is ready, it’s hot, and on my plate. The JSON document just describes my &lt;em&gt;desired&lt;/em&gt; breakfast; it doesn’t tell the chef or anyone else how to make it. That’s what makes it declarative.&lt;/p&gt;
&lt;p&gt;Static text like JSON and YAML aren’t the only ways to declare a desired breakfast, though. Here’s a little JavaScript program that allocates a similar set of breakfast objects and relationships. Again, notice there isn’t any &lt;em&gt;how&lt;/em&gt; going on, here --- we’re still firmly in &lt;em&gt;what&lt;/em&gt; territory:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; { Breakfast, Eggs, Toast, Juice } &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;some-menu-or-something&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;breakfast&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Breakfast&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;eggs: &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Eggs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;scrambled&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;toast: &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Toast&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;multi-grain&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;juice: &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Juice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;orange&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Here, &lt;code dir=&quot;auto&quot;&gt;breakfast&lt;/code&gt; still consists of three things --- object instances of &lt;code dir=&quot;auto&quot;&gt;Eggs&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Toast&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;Juice&lt;/code&gt; --- just as it did in the JSON representation. Assuming the constructors of these objects weren’t doing anything fancy under the hood (just allocating local instance properties of their own, say), you’d expect that running this program with Node.js would produce, for a moment, a &lt;code dir=&quot;auto&quot;&gt;breakfast&lt;/code&gt; variable referring to an instance of the &lt;code dir=&quot;auto&quot;&gt;Breakfast&lt;/code&gt; class, and that the &lt;code dir=&quot;auto&quot;&gt;breakfast&lt;/code&gt; instance would itself contain references to instances of each of its ingredients before the program finally exited. Without a doubt, this is imperative JavaScript &lt;em&gt;code&lt;/em&gt; --- but this particular expression is totally declarative; we’ve simply stated that &lt;code dir=&quot;auto&quot;&gt;breakfast&lt;/code&gt; &lt;em&gt;depends&lt;/em&gt; on three ingredients, and left it up to the JavaScript engine to handle the dependent allocations and the order in which to perform them.&lt;/p&gt;
&lt;p&gt;As it happens, this a lot like &lt;a href=&quot;https://www.pulumi.com/docs/intro/concepts/how-pulumi-works/&quot;&gt;how Pulumi works&lt;/a&gt;, too. A call to a Pulumi resource constructor (like &lt;a href=&quot;https://www.pulumi.com/docs/reference/pkg/aws/s3/bucket/&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;new aws.s3.Bucket()&lt;/code&gt;, for example&lt;/a&gt;) is just an object declaration like any other, an expression of your desire to have an S3 bucket exist --- not to &lt;em&gt;create&lt;/em&gt; the S3 bucket &lt;em&gt;in that moment&lt;/em&gt;, but to &lt;em&gt;have&lt;/em&gt; it exist when the program completes. At runtime, the Pulumi SDK and engine conspire to gather up all of the object allocations in your program, figure out their relationships (which objects depend on which, what values they need from each other, and so on), assemble a JSON-serializable &lt;a href=&quot;https://en.wikipedia.org/wiki/Object_graph&quot;&gt;object graph&lt;/a&gt; representing the full picture, and then use that graph to call on the cloud provider directly to produce the appropriate result. Just like with Arc and other &lt;em&gt;statically&lt;/em&gt; declarative tools, the code you write with Pulumi still says &lt;em&gt;what&lt;/em&gt;, not &lt;em&gt;how&lt;/em&gt;, and Pulumi takes care of delivering the outcome for you.&lt;/p&gt;
&lt;p&gt;Here’s what it looks like to make a couple of S3 buckets with Pulumi and JavaScript, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;bucket1&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;bucket1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;bucket2&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;bucket2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If you wanted, since you’re working with JavaScript, you could even get a bit fancier by declaring the buckets with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;Array#map&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Run the program once, and you get two buckets (along with a “&lt;a href=&quot;https://www.pulumi.com/docs/intro/concepts/stack/&quot;&gt;stack&lt;/a&gt;,” if you didn’t already have one):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Updating&lt;/span&gt;&lt;span&gt; (dev)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;Status&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;pulumi:pulumi:Stack&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;buckets-dev&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;bucket1&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;bucket2&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Resources:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Run it again, you get nothing, because the buckets you declared already exist:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Updating&lt;/span&gt;&lt;span&gt; (dev)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;pulumi:pulumi:Stack&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;buckets-dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Resources:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unchanged&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You could even reverse the sort order and still get the same result (since ultimately, it’s up to Pulumi to determine what needs to be done, and how):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;bucket&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;`&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;reverse&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Updating&lt;/span&gt;&lt;span&gt; (dev)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;pulumi:pulumi:Stack&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;buckets-dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Resources:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unchanged&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Again, that’s declarative (and &lt;a href=&quot;https://en.wikipedia.org/wiki/Idempotence&quot;&gt;idempotent!&lt;/a&gt;) infrastructure as code --- it just happens to have been written with an imperative programming language. You could modify this program to add a third bucket, remove a bucket, declare a JavaScript function to be invoked &lt;a href=&quot;https://www.pulumi.com/docs/guides/crosswalk/aws/lambda/&quot;&gt;in response to a bucket event&lt;/a&gt;, whatever you want, it’s always the same: Pulumi launches your chosen language runtime, listens for object allocations (by way of the &lt;code dir=&quot;auto&quot;&gt;@pulumi/aws&lt;/code&gt; SDK, for example), registers those allocations with the &lt;a href=&quot;https://www.pulumi.com/docs/intro/concepts/how-pulumi-works/&quot;&gt;engine&lt;/a&gt;, computes an in-memory graph of resources and relationships, and then calls on your cloud provider directly to issue the appropriate set of changes, in the right order.&lt;/p&gt;
&lt;p&gt;Great --- so now you know how Pulumi works.&lt;/p&gt;
&lt;p&gt;But it’s still worth asking: is all of this really &lt;em&gt;necessary?&lt;/em&gt; What kinds of problems does Pulumi actually solve? What makes this “imperatively declarative” approach to infrastructure worth the additional layers of indirection --- the language, runtime, dependencies, and the rest? Wouldn’t it be easier just to write a few lines of YAML and be done than to have to contend with all of this extra &lt;em&gt;stuff?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Sure --- for simple things, maybe. But software has a funny way of starting out simple and suddenly becoming annoyingly complex --- often a lot sooner than you think.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;when-breakfast-gets-complicated&quot;&gt;When breakfast gets complicated&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For me, thanks to my basic breakfast needs, getting what I want is usually no big deal. That’s because most cafés are going to have eggs, bread, and orange juice on hand and ready to make --- and also because I’m not all that fussy about the details.&lt;/p&gt;
&lt;p&gt;But for my family, it’s more complicated. I have three kids, for example, all of whom have mild food sensitivities, and a wife who rarely eats out because of how hard it is to find something she likes. None of them could walk into a diner with an order like mine, because they’d need to be able to ask certain questions first: &lt;em&gt;Are the eggs made with milk? Are the waffles gluten-free?&lt;/em&gt; Each of these questions needs to be answered, for real and important reasons, before our collective order can be submitted and fulfilled.&lt;/p&gt;
&lt;p&gt;It’d be impossible, in other words, to walk into a restaurant with a handwritten order for a family like ours expecting to have it accepted verbatim without some kind of interaction first. &lt;em&gt;Oh, the waffles aren’t gluten-free? Okay --- we’ll take an omelet instead.&lt;/em&gt; It’s always something, and I imagine it’s probably like that for most of us: we know what we want, and we’re usually able to get it, but not without a little negotiation during the process. At a high level, we know want “breakfast”, which is easy. But in practice, we almost always end up having to apply some sort of algorithm, however simple, during that process.&lt;/p&gt;
&lt;p&gt;In fact, that’s kind of how &lt;em&gt;everything&lt;/em&gt; works, software included --- and infrastructure (especially the cloud-based kind) is nothing not fundamentally software. If all you need is a couple of storage buckets or Lambdas or VMs, sure, you can kick out that stuff with a few lines of YAML and get on with your day --- and that’s awesome, to be sure. But more often, what you’ll find is that you’ll eventually need &lt;em&gt;something more&lt;/em&gt;, some tiny bit of customization or other that the simple tool can’t &lt;em&gt;quite&lt;/em&gt; give you out of the box --- and that’s when the trouble begins.&lt;/p&gt;
&lt;p&gt;When the problem is straightforward and well bounded, in other words, simple tools are great, and often more than enough to get the job done. But when the problem is even a little bit complicated, or when the problem &lt;em&gt;space&lt;/em&gt; expands beyond what those simple tools were originally designed for, the tools themselves will tend to bend and crack in the places that weren’t really made with complexity in mind.&lt;/p&gt;
&lt;p&gt;Take our two buckets, for example. If you knew how many buckets you wanted to create and how you wanted to name them, you could do that fairly easily with &lt;a href=&quot;https://www.terraform.io/docs/language/syntax/configuration.html&quot;&gt;HCL&lt;/a&gt;, the config language of Terraform:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;provider &lt;/span&gt;&lt;span&gt;&quot;aws&quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;region &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;us-west-2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;variable &lt;/span&gt;&lt;span&gt;&quot;buckets&quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;type &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;default &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;resource &lt;/span&gt;&lt;span&gt;&quot;aws_s3_bucket&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;bucket&quot;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;count &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; length&lt;/span&gt;&lt;span&gt;(var&lt;/span&gt;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;buckets&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bucket &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;some-interestingly-named-bucket-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;buckets&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If you’re not familiar with HCL, you might need to squint to figure out what’s going on here, but it’s a lot like our first bucket-provisioning example from earlier: we just loop through a list of strings (“1”, “2”, and “3”), creating a bucket for each one:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;terraform&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;aws_s3_bucket.bucket[1]:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Creating...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;aws_s3_bucket.bucket[2]:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Creating...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;aws_s3_bucket.bucket[0]:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Creating...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;aws_s3_bucket.bucket[0]:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Creation&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;complete&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;after&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3s&lt;/span&gt;&lt;span&gt; [id=some-interestingly-named-bucket-1]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;aws_s3_bucket.bucket[1]:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Creation&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;complete&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;after&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3s&lt;/span&gt;&lt;span&gt; [id=some-interestingly-named-bucket-2]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;aws_s3_bucket.bucket[2]:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Creation&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;complete&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;after&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3s&lt;/span&gt;&lt;span&gt; [id=some-interestingly-named-bucket-3]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Again, this totally works --- assuming the names you’ve chosen &lt;a href=&quot;https://www.pulumi.com/docs/intro/concepts/resources/#autonaming&quot;&gt;are globally unique&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now imagine you had to name those buckets in a slightly more complicated way --- using stringified date, perhaps. Naming a bucket dynamically with a format string like &lt;code dir=&quot;auto&quot;&gt;YYYY-MM-DD&lt;/code&gt; is maybe &lt;em&gt;possible&lt;/em&gt; with Terraform (or if not, maybe using a bit of &lt;a href=&quot;https://en.wikipedia.org/wiki/Shell_script&quot;&gt;shell scripting&lt;/a&gt; with and an HCL &lt;code dir=&quot;auto&quot;&gt;variable&lt;/code&gt;), but you’d definitely be running into the limits of what HCL is able to do on its own. That’s not a knock against HCL, either: every special-purpose language runs the risk of hitting these kinds of limitations eventually.&lt;/p&gt;
&lt;p&gt;With general-purpose languages like JavaScript, though, this kind of thing is trivially easy, either with the language alone or with the help of a third-party package to make things even easier --- one like &lt;a href=&quot;https://github.com/iamkun/dayjs&quot;&gt;Day.js&lt;/a&gt;, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; aws &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;@pulumi/aws&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; dayjs &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;dayjs&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Keep a bucket for each of the last 7 days.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;let &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;s3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Bucket&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;dayjs&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;subtract&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;day&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;YYYY-MM-DD&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pulumi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;up&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Updating&lt;/span&gt;&lt;span&gt; (dev)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;Name&lt;/span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;Status&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;pulumi:pulumi:Stack&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;buckets-dev&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;2021-03-24&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;2021-03-29&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;2021-03-28&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;2021-03-27&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;2021-03-25&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;├─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;2021-03-23&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;└─&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aws:s3:Bucket&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;2021-03-26&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Resources:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;created&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Duration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;9s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;When you carve away the language, Pulumi and Terraform are doing a lot of the same things: both work to assemble graphs of resources and dependencies, both use those graphs to communicate with cloud providers directly, and both manage state in conceptually similar ways. It’s at the language layer --- and up --- that they really start to diverge.&lt;/p&gt;
&lt;p&gt;Again, how much that matters is for you to decide. But as a developer, I’ll take a full programming language (especially one I know well) any day of the week, because it means I can do anything the language &lt;em&gt;and its ecosystem&lt;/em&gt; can do, and that I probably won’t end up in tears in six months when I’m faced with a problem that my tools can’t handle. Just yesterday, for example, I found myself wrestling with &lt;a href=&quot;https://www.gnu.org/software/bash/&quot;&gt;Bash&lt;/a&gt; trying to move a few files between Git repositories. After a frustrating couple of hours of hacking and Googling, I realized I could just use Node.js instead --- and when I did, I was done in a matter of minutes. An expert shell programmer might’ve made light work of what I was trying to do --- but I’m not an expert shell programmer, and Bash isn’t JavaScript. All it took was a couple of Node.js built-ins and libraries:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;$ yarn add glob micromatch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;… and eight lines of JavaScript later, I was done.&lt;/p&gt;
&lt;p&gt;For me, language --- and all that comes with it --- is ultimately what it’s all about.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;like-react-for-infrastructure&quot;&gt;Like React for infrastructure&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;All of this reminds me of the progression we’ve seen over the last two decades in web development.&lt;/p&gt;
&lt;p&gt;Think of &lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt;. Why do we have it? Because HTML alone isn’t enough, and imperative DOM scripting leads to reams of unmaintainable code. We got React because we, as developers, wanted to &lt;em&gt;think&lt;/em&gt; about, and compose, our front-end applications in declarative ways --- but we &lt;em&gt;needed&lt;/em&gt; to retain the flexibility of the JavaScript language. So we got React --- and with it, an imperatively declarative programming model for the web:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;// Imperative code...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;const &lt;/span&gt;&lt;span&gt;offices&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Akron&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Nashua&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Rochester&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Scranton&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Syracuse&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Utica&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DunderMifflinBranchOffices&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// ... declaratively rendered...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;ul&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;offices&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;office&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;office&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&lt;span&gt;office&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Scranton&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;← The best one&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;span&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;li&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;ul&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;aside&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;nav&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;&amp;#x3C;!-- ... and composed. --&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;DunderMifflinBranchOffices&lt;/span&gt;&lt;span&gt; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;nav&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;aside&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;#x3C;/&lt;/span&gt;&lt;span&gt;html&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It’s the same thing with infrastructure: we want a declarative mental model, but we need the control and composabilty of general-purpose languages. Hence tools like Pulumi.&lt;/p&gt;
&lt;p&gt;It’ll be interesting to see where things go from here; &lt;a href=&quot;https://pulumibook.com/about&quot;&gt;I’m&lt;/a&gt; &lt;a href=&quot;https://www.pulumi.com/about/&quot;&gt;certainly&lt;/a&gt; &lt;a href=&quot;https://pulumibook.com/&quot;&gt;biased&lt;/a&gt;, but also a fascinated observer. The trajectory is what interests me most, though --- that, and being able to manage my own infrastructure in ways that feel comfortable to me as a developer. (Which reminds me, I should probably write about how I manage &lt;em&gt;this&lt;/em&gt; site sometime…)&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Enjoy this post?&lt;/strong&gt; It’s reprinted from &lt;a href=&quot;https://pulumibook.com&quot;&gt;pulumibook.com&lt;/a&gt;, the companion site for the book I’m currently writing about using &lt;a href=&quot;https://pulumi.com&quot;&gt;Pulumi&lt;/a&gt; with TypeScript and Amazon Web Services. &lt;a href=&quot;https://pulumibook.com&quot;&gt;Check it out&lt;/a&gt;, or grab yourself a copy of the in-progress book today &lt;a href=&quot;https://leanpub.com/pulumi&quot;&gt;on Leanpub&lt;/a&gt;! 📚&lt;/p&gt;</content:encoded><category>concepts</category><category>infrastructure-as-code</category></item><item><title>Live Coding with Pulumi, Mapbox, and Leaflet</title><link>https://pulumibook.com/blog/live-coding-with-pulumi-mapbox-and-leaflet/</link><guid isPermaLink="true">https://pulumibook.com/blog/live-coding-with-pulumi-mapbox-and-leaflet/</guid><description>Building and deploying a little mapping app live, with Pulumi, Mapbox, and Leaflet — infrastructure and application code side by side.

</description><pubDate>Tue, 03 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This past weekend, I did a &lt;a href=&quot;https://twitch.tv/manningpublications&quot;&gt;Twitch session for Manning&lt;/a&gt; in which I built a little serverless app with &lt;a href=&quot;https://pulumi.com/&quot;&gt;Pulumi&lt;/a&gt; and &lt;a href=&quot;https://mapbox.com/&quot;&gt;Mapbox&lt;/a&gt; and deployed it on &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt;. It was the first time I’d ever done such a thing --- I’ve done many demos, but never a public live-coding session --- and surprisingly (to me, at least), I actually enjoyed it. In a little over an hour, I wrote an app with Pulumi and TypeScript that renders GPS-tagged photos on a map with AWS &lt;a href=&quot;https://docs.aws.amazon.com/s3/&quot;&gt;S3&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/lambda/&quot;&gt;Lambda&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/dynamodb/&quot;&gt;DynamoDB&lt;/a&gt; and &lt;a href=&quot;https://docs.aws.amazon.com/apigateway/&quot;&gt;API Gateway&lt;/a&gt;, and aside from a few little bumps, and my crazy-long COVID hair, everything worked out pretty well.&lt;/p&gt;
&lt;p&gt;The hardest part was definitely setting up &lt;a href=&quot;https://obsproject.com/&quot;&gt;OBS Studio&lt;/a&gt;, but now that that’s done, I plan to start doing more of these, as they’re (a) fun and (b) probably the best way to demonstrate how Pulumi really works and what makes it so awesome.&lt;/p&gt;
&lt;p&gt;You’ll find the &lt;a href=&quot;https://www.twitch.tv/videos/793943710&quot;&gt;full recording here&lt;/a&gt;, and the annotated code of the finished product’s &lt;a href=&quot;https://github.com/cnunciato/photomap&quot;&gt;up on GitHub&lt;/a&gt;. Enjoy!&lt;/p&gt;</content:encoded><category>serverless</category><category>aws</category><category>demo</category></item></channel></rss>