<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Aaron Friel</title><link>https://www.pulumi.com/blog/author/aaron-friel/</link><description>Pulumi blog posts: Aaron Friel.</description><language>en-us</language><pubDate>Wed, 20 Dec 2023 15:00:00 -0800</pubDate><item><title>Deploy Cloud Infrastructure in 30 Seconds with Pulumi AI</title><link>https://www.pulumi.com/blog/pulumi-ai-new/</link><pubDate>Wed, 20 Dec 2023 15:00:00 -0800</pubDate><guid>https://www.pulumi.com/blog/pulumi-ai-new/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-ai-new/index.png" /&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Note: This post discusses Pulumi Copilot, which Pulumi Neo has replaced. &lt;a href="https://www.pulumi.com/docs/ai/"&gt;Learn about Neo →&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;There are new intelligent cloud management capabilities available in &lt;strong&gt;Pulumi Copilot&lt;/strong&gt;. &lt;a href="https://www.pulumi.com/blog/pulumi-copilot"&gt;Learn More&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Earlier this year we launched &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt;, a purpose-built AI assistant that can create &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;Infrastructure as Code (IaC)&lt;/a&gt; from natural language prompts using Pulumi. Since launch, we’ve seen incredible adoption of Pulumi AI, with over 200,000 questions asked so far and growing fast. Pulumi AI is popular with users new to Pulumi and/or new to the Cloud, but also heavily used by many of the most advanced IaC users and organizations to quickly discover solutions to new problems they need to solve. Over the last few months, we’ve driven major improvements to Pulumi AI through the recently launched Pulumi AI Answers pages with thousands of AI generated answers to common questions, improvements to code generation correctness and performance, and expansion of the languages supported by Pulumi AI.&lt;/p&gt;
&lt;p&gt;Today, we are taking the next big step, introducing support for &lt;strong&gt;deploying cloud infrastructure directly from Pulumi AI&lt;/strong&gt;. Going from idea to running cloud infrastructure is just a natural language prompt away!&lt;/p&gt;
&lt;p&gt;This is accomplished through two new features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;pulumi new&lt;/code&gt; command now offers the option to provide a Pulumi AI prompt instead of selecting a template. It then generates a template from your prompt, and lets you iterate on this before choosing to create a project and deploy it to the cloud.&lt;/li&gt;
&lt;li&gt;Every Pulumi AI and Pulumi AI Answers page now has a &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/pulumi-button/"&gt;Deploy with Pulumi&lt;/a&gt; button on it, which lets you click through a few prompts to deploy the given infrastructure into your cloud account using Pulumi Deployments and Pulumi ESC in Pulumi Cloud or the &lt;code&gt;pulumi new&lt;/code&gt; command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Check out &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; or &lt;code&gt;pulumi new&lt;/code&gt; in the CLI today.&lt;/p&gt;
&lt;h2 id="hope-pulumi-ai-works-with-pulumi-new"&gt;Hope Pulumi AI Works with &lt;code&gt;pulumi new&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;pulumi new&lt;/code&gt; command is the starting point for almost every new Pulumi project today, offering users a choice from hundreds of templates across various cloud providers, languages and architectures.&lt;/p&gt;
&lt;p&gt;Now, &lt;code&gt;pulumi new&lt;/code&gt; users working with the Pulumi Cloud backend have the additional option to use Pulumi AI to generate a template on demand instead of selecting from one of the pre-defined templates.&lt;/p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Using pulumi new with the new AI option"
autoplay muted playsinline
loop &gt;
&lt;source src="https://www.pulumi.com/uploads/pulumi-new-ai.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;p&gt;The Pulumi AI response is streamed back directly into the CLI, and if Pulumi AI didn’t get it quite right, you can request to “revise” the question to ask Pulumi AI to adjust it’s answer with a follow-up prompt. When the results look good, you can hit “yes” to deploy the template, generating the source code in your chosen language and installing dependencies for the target cloud providers. With a simple &lt;code&gt;pulumi up&lt;/code&gt; your new cloud infrastructure is deployed and running in the cloud.&lt;/p&gt;
&lt;p&gt;There’s also a new &amp;ndash;ai flag to pulumi new, so you can create a new project from an AI prompt with a command like one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pulumi new --ai &amp;quot;run NGINX in EC2 with a public port&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pulumi new --ai &amp;quot;a static website in Azure with a CDN in front&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pulumi new --ai &amp;quot;managed postgres database and Fargate compute for a containerized app&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Going from natural language idea to running cloud infrastructure in just seconds!&lt;/p&gt;
&lt;h2 id="deploying-cloud-infrastructure-with-pulumi-ai"&gt;Deploying Cloud Infrastructure with Pulumi AI&lt;/h2&gt;
&lt;p&gt;Thousands of developers are already discovering answers to their questions via Pulumi AI, and we’ve been expanding on this with links to Pulumi AI from the Pulumi Registry API docs and with the archive of high quality questions and answers as part of Pulumi AI Answers. To date, users have used these answers to then copy/paste code snippets into their own Pulumi programs, presenting something of a small but meaningful barrier to entry to quickly experimenting with the resulting infrastructure.&lt;/p&gt;
&lt;p&gt;Now, every Pulumi AI and Pulumi AI Answers page includes its own Deploy with Pulumi button. The Deploy with Pulumi button can be used along with any template or Pulumi code example to deploy that code using Pulumi Cloud via the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/new-project-wizard"&gt;New Project Wizard&lt;/a&gt;. We’ve extended that to support deploying projects defined by a Pulumi AI answer. This includes the code snippet, but also the project dependencies, a useful description, and language-specific project files.&lt;/p&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="Deploy with Pulumi button in Pulumi AI"
autoplay muted playsinline
loop &gt;
&lt;source src="https://www.pulumi.com/uploads/dwp.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;p&gt;Recently, we introduced many &lt;a href="https://www.pulumi.com/blog/building-developer-portals/"&gt;improvements to the New Project Wizard in Pulumi Cloud&lt;/a&gt;, including the ability to deploy a template with just a few clicks using Pulumi Deployments to do the deployments, the Pulumi GitHub app to template the code into a repo for you, and Pulumi ESC to provide access to short-lived credentials for your cloud environment. Once these are configured for users in an organization, any template can be deployed via the New Project Wizard and the Deploy with Pulumi button in just a few clicks.&lt;/p&gt;
&lt;p&gt;These same features and New Project experience are now available from every Pulumi AI page. Let&amp;rsquo;s see what that looks like.&lt;/p&gt;
&lt;h3 id="step-by-step-guide-deploying-with-pulumi-ai"&gt;Step-by-Step Guide: Deploying with Pulumi AI&lt;/h3&gt;
&lt;p&gt;After clicking on the Deploy with Pulumi button on any Pulumi AI page, you can choose the ESC Environment to use for configuration and credentials for your environment (here I use the dev-sandbox environment which provides short-lived &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html"&gt;OIDC credentials&lt;/a&gt; to a development sandbox AWS account), a name for your project and stack, and the repository and folder to generate the code into.&lt;/p&gt;
&lt;p&gt;&lt;img src="npw.png" alt="New Project Wizard for Pulumi AI project"&gt;&lt;/p&gt;
&lt;p&gt;When I click Create Project, this adds the code to the repository and kicks off a Pulumi Deployments run to deploy this new infrastructure to the cloud.&lt;/p&gt;
&lt;p&gt;&lt;img src="deploy2.png" alt="Pulumi Deployments for a Pulumi AI project"&gt;&lt;/p&gt;
&lt;p&gt;A few moments later, once that deployment completes, I see I have a Pulumi stack with the expected outputs defined by the Pulumi AI answer - the IP address of the running instance in the cloud.&lt;/p&gt;
&lt;p&gt;&lt;img src="stack.png" alt="The Stack created for a Pulumi AI project"&gt;&lt;/p&gt;
&lt;p&gt;And navigating there shows me my new EC2 instance serving NGINX on the Internet.&lt;/p&gt;
&lt;p&gt;&lt;img src="nginx.png" alt="A running instance of the NGINX server created by Pulumi AI"&gt;&lt;/p&gt;
&lt;p&gt;We can now continue to iterate on our infrastructure by making changes in the new Git repo folder.&lt;/p&gt;
&lt;p&gt;With just a few clicks, we went from a natural language idea to running cloud infrastructure, checked into a Git repo, with Pulumi Deployments configured!&lt;/p&gt;
&lt;h2 id="faqs-pulumi-ai-and-cloud-deployment"&gt;FAQs: Pulumi AI and Cloud Deployment&lt;/h2&gt;
&lt;h3 id="what-is-pulumi-ai"&gt;What is Pulumi AI?&lt;/h3&gt;
&lt;p&gt;Pulumi AI is an AI-powered assistant that generates Infrastructure as Code (IaC) from natural language prompts.&lt;/p&gt;
&lt;h3 id="how-does-pulumi-new-ai-work"&gt;How does pulumi new &amp;ndash;ai work?&lt;/h3&gt;
&lt;p&gt;The pulumi new &amp;ndash;ai command allows you to generate and deploy cloud infrastructure using a natural language description instead of selecting a pre-defined template.&lt;/p&gt;
&lt;h3 id="which-cloud-providers-does-pulumi-ai-support"&gt;Which cloud providers does Pulumi AI support?&lt;/h3&gt;
&lt;p&gt;Pulumi AI supports AWS, Azure, Google Cloud, and other major platforms.&lt;/p&gt;
&lt;h3 id="can-i-modify-the-ai-generated-infrastructure-before-deployment"&gt;Can I modify the AI-generated infrastructure before deployment?&lt;/h3&gt;
&lt;p&gt;Yes! You can revise the AI-generated code before deployment to match your needs.&lt;/p&gt;
&lt;h3 id="where-can-i-provide-feedback-on-pulumi-ai"&gt;Where can I provide feedback on Pulumi AI?&lt;/h3&gt;
&lt;p&gt;Join the &lt;a href="https://slack.pulumi.com/"&gt;Pulumi Community Slack&lt;/a&gt; or join the &lt;a href="https://github.com/pulumi/pulumi/discussions"&gt;GitHub Discussions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="looking-ahead-the-future-of-pulumi-ai"&gt;Looking Ahead: The Future of Pulumi AI&lt;/h2&gt;
&lt;p&gt;Pulumi AI has already transformed how cloud engineers discover and solve their cloud infrastructure development problems. And yet, we still see incredible opportunity ahead of us. We’ve made rapid strides on improving the accuracy of AI answers, and continue to invest in further improvements. We’ve made it significantly faster to go from idea to deployed infrastructure with the &lt;code&gt;pulumi new&lt;/code&gt; and Deploy with Pulumi button integrations, but we also see the opportunity to make these experiences even more interactive going forward. And of course, we continue to integrate Pulumi AI even more broadly throughout our product experiences, lighting up AI assistance across the cloud engineering journey.&lt;/p&gt;
&lt;p&gt;Try it out yourself today at &lt;a href="https://www.pulumi.com/product/neo/"&gt;pulumi.com/neo&lt;/a&gt;!&lt;/p&gt;</description><author>Luke Hoban</author><author>Aaron Friel</author><category>features</category><category>ai</category><category>llm</category></item><item><title>Leveling up Pulumi AI with the Pulumi Registry</title><link>https://www.pulumi.com/blog/leveling-up-pulumi-ai-with-the-pulumi-registry/</link><pubDate>Mon, 22 May 2023 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/leveling-up-pulumi-ai-with-the-pulumi-registry/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/leveling-up-pulumi-ai-with-the-pulumi-registry/index.png" /&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/ai"&gt;Pulumi AI&lt;/a&gt; harnesses a form of generative AI, known as large language models, to help you discover, learn, and use new cloud infrastructure APIs with ease. Think of Pulumi AI as a sophisticated compass, guiding you through the ever-changing landscape of cloud infrastructure and pointing you in the direction of the most suitable solutions for your unique requirements.&lt;/p&gt;
&lt;p&gt;In this blog post, we&amp;rsquo;ll explore our recent enhancements to Pulumi AI, focusing on how we&amp;rsquo;ve integrated Pulumi Package schema data to generate more accurate and relevant Pulumi programs. We&amp;rsquo;ll also share examples showcasing the improvements and how they can benefit your infrastructure as code journey.&lt;/p&gt;
&lt;h2 id="overcoming-the-challenges-in-pulumi-ai"&gt;Overcoming the Challenges in Pulumi AI&lt;/h2&gt;
&lt;p&gt;As powerful as Pulumi AI may seem, it was initially limited by the training cutoff of the model. Pulumi AI wasn&amp;rsquo;t aware of new providers or changes to resources after late 2021. Additionally, the limitations in generative AI made it difficult for the model to reproduce all the input properties and relevant details of the resources it was trained on from &amp;ldquo;memory.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;These factors led to a phenomenon researchers call &amp;ldquo;hallucination.&amp;rdquo; Pulumi AI would sometimes generate an API for a non-existent provider when asked to produce a Pulumi program. To overcome these challenges, we turned to the rich &lt;a href="https://www.pulumi.com/docs/guides/pulumi-packages/schema/"&gt;Pulumi Package schema&lt;/a&gt; data and CrossCode technology that powers the &lt;a href="https://www.pulumi.com/registry/"&gt;Pulumi Registry&lt;/a&gt; docs, our code conversion tools, and other Pulumi enhancements.&lt;/p&gt;
&lt;h3 id="integrating-pulumi-package-schema-data"&gt;Integrating Pulumi Package Schema Data&lt;/h3&gt;
&lt;p&gt;Think of the Pulumi Package schema as a treasure trove of information about our providers. It&amp;rsquo;s a well-organized, comprehensive library that holds the keys to unlocking the full potential of Pulumi AI. However, we faced a challenge: these schemas were much larger than any current generative AI system could handle.&lt;/p&gt;
&lt;p&gt;What puts the &amp;ldquo;large&amp;rdquo; in large language model is the volume of data required to train and the number of parameters in the model, typically in the trillions of tokens and billions of parameters, respectively. Unfortunately, these models aren&amp;rsquo;t capable of handling that much information in their context window. The context window is the thread of conversation or the &amp;ldquo;short-term memory&amp;rdquo; of the system. It&amp;rsquo;s how one can enhance a model trained a year ago with today&amp;rsquo;s data.&lt;/p&gt;
&lt;p&gt;To better understand the limitations, let&amp;rsquo;s talk about tokens. Instead of operating on Unicode text, these models operate on token arrays, mapping many sequences of characters (words or parts of words) to 16-bit integers. For example, &amp;ldquo;Script&amp;rdquo; is one token, and &amp;ldquo;JavaScript&amp;rdquo; is typically two tokens. We found that despite this compression of words to tokens, the latest schemas for all of our providers would use on the order of one billion tokens.&lt;/p&gt;
&lt;p&gt;The most powerful systems to date support at most 32,000 tokens in their prompt – enough to fit a novella! That should be enough, right?&lt;/p&gt;
&lt;p&gt;We did the math: one billion minus 32,000&amp;hellip; And we&amp;rsquo;re still about a billion tokens over the limit.&lt;/p&gt;
&lt;h3 id="the-right-information-at-the-right-time"&gt;The right information, at the right time&lt;/h3&gt;
&lt;p&gt;To work around this limitation, we need to carefully select and inject the right schema information into the context window, ensuring that the model could understand, process, and generate the best possible solutions for users.&lt;/p&gt;
&lt;p&gt;We cracked open our college textbooks on information storage &amp;amp; retrieval, evaluated the latest vector databases and embedding systems, and perused the literature. One internal demo we did used a technique similar to &lt;a href="https://arxiv.org/abs/2212.10496"&gt;Hypothetical Document Embeddings (HyDE)&lt;/a&gt;. While this did improve accuracy and reduce hallucinations, that approach also requires pre-processing the user&amp;rsquo;s query. That additional step results in a much higher time-to-first-token (TTFT) latency, negatively impacting user experience.&lt;/p&gt;
&lt;p&gt;After iterating on these approaches in the weeks after launch, we&amp;rsquo;ve implemented a method that yields comparable results to HyDE without slowing the system down. Our current approach allowed us to maintain an engaging and responsive interface while still enhancing Pulumi AI&amp;rsquo;s accuracy.&lt;/p&gt;
&lt;p&gt;We continue to follow the latest research in this space to improve Pulumi AI, and we hope we can contribute our learnings back in this exciting field of research!&lt;/p&gt;
&lt;h2 id="improved-user-experience-and-examples"&gt;Improved User Experience and Examples&lt;/h2&gt;
&lt;p&gt;With the integration of Pulumi Package schema data, Pulumi AI now generates more accurate and relevant Pulumi programs, favoring our high-level components and the generally available providers we recommend, such as the &lt;code&gt;awsx&lt;/code&gt;, &lt;code&gt;eks&lt;/code&gt;, and &lt;code&gt;azure-native&lt;/code&gt; packages.&lt;/p&gt;
&lt;h3 id="powerful-components"&gt;Powerful components&lt;/h3&gt;
&lt;p&gt;For EKS clusters, Pulumi AI now typically recommends our &lt;code&gt;eks&lt;/code&gt; provider&amp;rsquo;s high level component when asked for &amp;ldquo;an eks cluster&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To achieve your goal of creating an EKS cluster, I recommend using the &lt;a href="https://www.pulumi.com/registry/packages/eks/api-docs/cluster/"&gt;&lt;code&gt;eks.Cluster&lt;/code&gt;&lt;/a&gt; Pulumi resource, which is a higher-level component encapsulating the necessary AWS and Kubernetes resources. This resource makes it easy to provision, scale, and manage EKS clusters in a Pulumi Python program.&lt;/p&gt;
&lt;p&gt;To proceed, you&amp;rsquo;ll need to have the pulumi-eks package installed:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pip install pulumi-eks
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here&amp;rsquo;s a simple Pulumi Python program that creates an EKS cluster:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_eks&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Cluster&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create an EKS cluster.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;my_cluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Cluster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Export the cluster kubeconfig.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kubeconfig&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;my_cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubeconfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;h3 id="simple-building-blocks"&gt;Simple building blocks&lt;/h3&gt;
&lt;p&gt;Pulumi AI now offers a more succinct solution for common queries such as &amp;ldquo;a static website on Azure&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To accomplish your goal, I will generate a Pulumi TypeScript program using the &lt;a href="https://www.pulumi.com/registry/packages/azure-static-website/api-docs/website/"&gt;&lt;code&gt;azure-static-website.Website&lt;/code&gt;&lt;/a&gt; resource from the Pulumi Registry. This resource is designed specifically for hosting static websites on Azure.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a Pulumi TypeScript program to deploy a static website on Azure using the &lt;code&gt;azure-static-website.Website&lt;/code&gt; resource.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;azure&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/azure&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;staticWebsites&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/azure-static-website&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;staticWebsites&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Website&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;website&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;sitePath&lt;/span&gt;: &lt;span class="kt"&gt;websitePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;resourceGroupName&lt;/span&gt;: &lt;span class="kt"&gt;resourceGroup.name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;withCDN&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;h3 id="new-products"&gt;New products&lt;/h3&gt;
&lt;p&gt;When asked for modern resources such as &lt;a href="https://cloud.google.com/alloydb"&gt;Google AlloyDB&lt;/a&gt;, launched six weeks ago, Pulumi AI now references Registry documentation to answer &amp;ldquo;google alloydb with an automatic backup policy&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Based on the Pulumi Registry results and trying to accomplish your goal of creating an AlloyDB cluster with an automatic backup policy, we can create a Google Cloud Platform (GCP) AlloyDB cluster using the &lt;a href="https://www.pulumi.com/registry/packages/gcp/api-docs/alloydb/cluster/"&gt;&lt;code&gt;gcp.alloydb.Cluster&lt;/code&gt;&lt;/a&gt; resource. You can set the &lt;code&gt;automatedBackupPolicy&lt;/code&gt; property with the necessary configuration to enable automatic backups.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a Pulumi program in TypeScript that creates an AlloyDB Cluster with an automatic backup policy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;gcp&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/gcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;projectId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;us-central1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;gcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Network&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;alloydb-network&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;autoCreateSubnetworks&lt;/span&gt;: &lt;span class="kt"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alloydbCluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;gcp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alloydb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cluster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;alloydbCluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;clusterId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;my-alloydb-cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;project&lt;/span&gt;: &lt;span class="kt"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;network&lt;/span&gt;: &lt;span class="kt"&gt;network.selfLink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;automatedBackupPolicy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;enabled&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;backup-type&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;automated&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;us-central1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;quantityBasedRetention&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;count&lt;/span&gt;: &lt;span class="kt"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;timeBasedRetention&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;retentionPeriod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;7d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;weeklySchedule&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;daysOfWeeks&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;MONDAY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;WEDNESDAY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;FRIDAY&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;startTimes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;04:00:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alloyDBClusterName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alloydbCluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;h2 id="getting-started-with-the-enhanced-pulumi-ai"&gt;Getting Started with the Enhanced Pulumi AI&lt;/h2&gt;
&lt;p&gt;Our enhancements to Pulumi AI have made it an even more useful tool for generating accurate and relevant cloud infrastructure solutions. We&amp;rsquo;re excited about the future of Pulumi AI as we continue to integrate it into &lt;a href="https://app.pulumi.com/signin"&gt;Pulumi Cloud&lt;/a&gt; and empower everyone to become a cloud engineer.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve also added new ways to reach Pulumi AI. In the Pulumi Registry, &amp;ldquo;Explore with Pulumi AI&amp;rdquo; links provide interactive documentation. And after you&amp;rsquo;ve had a conversation with Pulumi AI, you can share it via a &amp;ldquo;Share conversation&amp;rdquo; link in the bottom right corner of the message box:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/ai/"&gt;&lt;img src="./pulumi-ai-sharing.png" alt="Pulumi AI Sharing" style="width: 760px; max-width: 100%; display: block; margin-left: auto; margin-right: auto;"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Try out &lt;a href="https://www.pulumi.com/ai/"&gt;Pulumi AI&lt;/a&gt; today, and happy coding!&lt;/p&gt;</description><author>Aaron Friel</author><category>features</category><category>ai</category><category>packages</category><category>registry</category></item><item><title>Enabling Rapid Pulumi Prototyping with Rust</title><link>https://www.pulumi.com/blog/pulumi-watch-mode-with-rust/</link><pubDate>Wed, 21 Sep 2022 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumi-watch-mode-with-rust/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-watch-mode-with-rust/index.png" /&gt;
&lt;p&gt;Pulumi enables engineers to employ the best practices of their field to &lt;a href="https://www.pulumi.com/what-is/what-is-infrastructure-as-code/"&gt;infrastructure as code&lt;/a&gt;. The
&lt;code&gt;pulumi watch&lt;/code&gt; command is an example of this, enabling rapid prototyping and a &amp;ldquo;hot reload&amp;rdquo; style
developer experience for prototyping Pulumi programs. In this post you&amp;rsquo;ll see what watch mode
enables, the challenges encountered in maintaining the feature, and how we were able to use Rust to
bring that feature to more of our users.&lt;/p&gt;
&lt;p&gt;When developing a web application, hot reload frameworks enable quickly iterating and confirming the
divs are centered. When implementing new features, a test runner with a watch mode makes test-driven
development a breeze. In languages with an interactive shell, it&amp;rsquo;s natural to use that to experiment
with new APIs. In each of these cases, engineers find value in being able to focus on writing code,
not typing console commands.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why &lt;a href="https://www.pulumi.com/blog/pulumi-watch-mode-fast-inner-loop-development-for-cloud-infrastructure/"&gt;Pulumi Watch Mode&lt;/a&gt;
exists and is one of my favorite features, and it&amp;rsquo;s why I was disappointed to learn this feature was
not available to users on Apple Silicon Macs. As a Windows and Linux user, I discovered this while
root causing a Pulumi provider&amp;rsquo;s failing build to the library used to implement watch mode. Thus
began a deep dive into cgo, file-watching libraries in Go, operating system event APIs, and finding
a solution for our build issues and missing feature.&lt;/p&gt;
&lt;p&gt;To close this feature gap for one of our most important platforms, Pulumi v3.39.0 includes a binary
built with Rust to implement file-watching. &lt;code&gt;pulumi watch&lt;/code&gt; works as it
always has. And as the first component to use the Rust language, it validated Pulumi&amp;rsquo;s approach to
engineering of using the best languages and tools available.&lt;/p&gt;
&lt;h2 id="but-first-what-is-and-why-use-watch-mode"&gt;But first, what is and why use watch mode?&lt;/h2&gt;
&lt;p&gt;Watch mode monitors a project folder and automatically runs an equivalent to &lt;code&gt;pulumi up&lt;/code&gt; with the
appropriate flags to skip prompts and displays simplified output. To see how quickly this can work,
I wrote a Pulumi TypeScript program to deploy an S3 bucket and bucket object &amp;ldquo;test.txt&amp;rdquo; before
writing a timestamp to the same file. That allows me to measure the inner loop with &lt;code&gt;pulumi watch&lt;/code&gt;
or using an external program to run &lt;code&gt;pulumi up&lt;/code&gt;. On each deployment, the program changes one of the
files in the directory kicking off the next deployment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/aws&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;fs/promises&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucketObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BucketObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-bucket-object&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;: &lt;span class="kt"&gt;bucket.id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;test.txt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;source&lt;/span&gt;: &lt;span class="kt"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FileAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;test.txt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;bucketObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;test.txt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="sb"&gt;n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On a laptop with this simple program, &lt;code&gt;pulumi watch&lt;/code&gt; consistently completed up to 50% faster, at 2.1
seconds per iteration than when using an external tool. Watch mode was more consistent, too: the
standard deviation over 50 samples was reduced to 46ms from 216ms. It does this while being easier
to remember and therefore use correctly, and with more terse output tuned for the use case of
quickly iterating on changes to a stack.&lt;/p&gt;
&lt;p&gt;Watch mode has changed how I write infrastructure as code, and it brings that benefit to everyone
without needing to install and learn third-party tools for file-watching.&lt;/p&gt;
&lt;h2 id="the-challenges-of-file-watching-in-go"&gt;The Challenges of File-Watching in Go&lt;/h2&gt;
&lt;p&gt;Returning to the cross-compilation issue, the team found builds failed after updating
the Pulumi library dependency. Root causing this, I found that through a chain of Go package
dependencies, the file-watching library became a compilation unit in provider binaries. That library
had several reported issues with cross-compilation, with users reporting that it required enabling
cgo and building on macOS to target macOS.&lt;/p&gt;
&lt;p&gt;That raised two flags. First, &lt;a href="https://dave.cheney.net/2016/01/18/cgo-is-not-go"&gt;cgo is not Go&lt;/a&gt;.
Using cgo entails wide-ranging side effects and results in a more complex build, packaging, and
support lifecycle. Second, continuous integration tools that support macOS runners are limited and
typically much higher cost. It was unacceptable to allow unintentional changes in a provider or the
Pulumi repository to impose those requirements on providers.&lt;/p&gt;
&lt;p&gt;Why did the &lt;a href="https://github.com/rjeczalik/notify"&gt;notify library&lt;/a&gt; have these constraints? This
library depended on C library support for a macOS API called FSEvents, and its Go source files
required a complex set of build tags. While this didn&amp;rsquo;t seem impossible to work around, the library
remains unmaintained and would require us to maintain a fork to address these deficiencies. With no
recent contributions to the library to address this or a path to removing the cgo dependency, I had
to find another library.&lt;/p&gt;
&lt;p&gt;The strongest candidate was the &lt;a href="https://github.com/fsnotify/fsnotify"&gt;fsnotify library&lt;/a&gt;. This library supported
the platforms required, did not require cgo, and supported cross-compilation. It did lack recursive
directory watching, though the repository listed it as a planned feature. However, in August the
maintainer archived the repository and stepped down from maintenance. Though contributors stepped up
to take over ownership of the repo, it left the state of the project in doubt. Without features like
recursive file watching, the team would have to maintain a fork. The search continued.&lt;/p&gt;
&lt;p&gt;The last candidate looked at was the &lt;a href="https://github.com/radovskyb/watcher/"&gt;watcher library&lt;/a&gt;, which supported
recursive file watching across all platforms without cgo. Was this a panacea? Unfortunately, no. It
did this by falling back to the simplest method of file-watching: polling. This method works well
enough that the library has not changed in four years. The downside to polling is substantially
higher CPU usage and battery drain. It would also require workarounds for projects that contain
large folders of dependencies, such as a node.js node_modules or python venv directory. In spiking
on this, I was unsurprised to see that watching a folder with vendored dependencies was orders of
magnitude slower.&lt;/p&gt;
&lt;p&gt;The Go language ecosystem lacks libraries that meet our needs. It was possible to watch only one
directory, or only support one operating system, or to be insensitive to performance concerns. I
needed an option that didn&amp;rsquo;t make any of these sacrifices and, ideally, was also actively
maintained.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Prototype infrastructure with watch mode&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Run &lt;code&gt;pulumi watch&lt;/code&gt; to get a hot-reload inner loop that applies changes to your stack as you save files.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.4a9ac1016b9d8a688a5e7e867f96bdf80115a0739af8c688ba04791e15f64461.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="from-library-to-binary-and-the-carcinization-of-pulumi"&gt;From library to binary and the carcinization of Pulumi&lt;/h2&gt;
&lt;p&gt;One doesn&amp;rsquo;t have to look hard to find CLIs that tackle this problem, many of which were at the top
of search results while looking for libraries. Using one of these as a plugin and reading stdout for
events instead would avoid any link-time dependency for providers. With this in mind, I considered
building a one-off binary using the previous utilities but ruled them out. The team would become de
facto maintainers of a fork of a complex library, in addition to needing to solve the deficiencies
identified above. That wasn&amp;rsquo;t an innovation token I could spend.&lt;/p&gt;
&lt;p&gt;I evaluated the complexity of building on the &lt;a href="https://github.com/facebook/watchman"&gt;watchman service&lt;/a&gt;, an
excellent file-watching CLI open-sourced by Facebook. Unfortunately, it would be costly to maintain
a wrapper with watchman as a dependency. While C++ isn&amp;rsquo;t inaccessible, it does impose a complex
build system and a higher barrier to entry for engineers to contribute to it. And as both a client
and server application, it wouldn&amp;rsquo;t be as simple as packaging a single binary and shelling out to
it.&lt;/p&gt;
&lt;p&gt;Finally, I spiked on a library written in Rust, using the library underpinning the
&lt;a href="https://github.com/watchexec/watchexec"&gt;watchexec CLI&lt;/a&gt;. All-in, this worked out to just over 100
lines of code to maintain on top of the actively maintained watchexec libraries, with a similarly
small patch to the Pulumi CLI. And importantly, building the binary is a simple &lt;code&gt;cargo build&lt;/code&gt; command that
the team can run on any platform. The
&lt;a href="https://github.com/pulumi/watchutil-rs"&gt;watchutil-rs implementation&lt;/a&gt; lives in GitHub and is packaged as
pulumi-watch, a single-purpose binary that logs on stdout when files change.&lt;/p&gt;
&lt;p&gt;Pulumi&amp;rsquo;s mission is to enable everyone to apply the best programming languages and tools to
infrastructure as code. Implementing watch mode in Rust applied that principle to watch mode while
maintaining performance, moving the feature to a well-maintained footing, and expanding support to
every platform Pulumi supports.&lt;/p&gt;
&lt;p&gt;Give &lt;a href="https://www.pulumi.com/docs/iac/cli/commands/pulumi_watch"&gt;&lt;code&gt;pulumi watch&lt;/code&gt;&lt;/a&gt; a try with our
&lt;a href="https://www.pulumi.com/docs/get-started/"&gt;getting started guide&lt;/a&gt;!&lt;/p&gt;</description><author>Aaron Friel</author><category>features</category><category>watch</category><category>rust</category></item></channel></rss>