What you’ll learn
  • what is Pulumi
  • how is Webiny utilizing Pulumi with your project applications
  • what are state files
  • what are backends

Why Pulumi?
anchor

For defining and deploying necessary cloud infrastructure for your project applications, by default, Webiny relies on Pulumi external link, a modern infrastructure as code (IaC) external link solution.

Webiny chose Pulumi as its default IaC solution for a couple of reasons:

  • cloud infrastructure is defined via code (TypeScript)
  • it supports multiple cloud providers (AWS, Azure, Google Cloud Platform, …)
  • it provides multiple solutions for storing infrastructure state
  • a vibrant and rising community

Note that Pulumi is the default solution Webiny relies on, which means it doesn’t have to be the only one. If you have a need to bring your own IaC solution (like CloudFormation or Terraform), you certainly can. Feel free to message us external link if that’s the case, we’d be glad to assist.

A Closer Look
anchor

In the following folder structure, we are looking at three applications that are set up by default in a new Webiny project. These are the API (./api), Admin Area (./apps/admin), and Website (./apps/website), which are shown in the following directory structure (code folder omitted for brevity):

.
├── api
│   ├── pulumi
│   ├── Pulumi.yaml
│   ├── Pulumi.dev.yaml
│   └── index.ts
├── apps
│   ├── admin
│   │   ├── pulumi
│   │   ├── Pulumi.yaml
│   │   ├── Pulumi.dev.yaml
│   │   └── index.ts
│   └── website
│       ├── pulumi
│       ├── Pulumi.dev.yaml
│       ├── Pulumi.yaml
│       └── index.ts
│  
└── (...)

Let’s examine how these applications are utilizing Pulumi in order to define and deploy needed cloud infrastructure resources.

Three key Pulumi related concepts, that we’re using in the following text, are: Pulumi project external link, program external link, and stack external link. Check out their Programming Model external link article to learn more.

Each of these applications are standalone Pulumi projects external link, which essentially means two things:

  • every application contains its own infrastructure-related code (Pulumi program external link), configuration, meta, and state files
  • every application is deployed separately (you cannot deploy two applications in a single operation)

Note that, by default, Webiny CLI does provide a convenient deploy method which deploys multiple project applications for you. And although it may seem you are completely deploying your Webiny project with a single command, internally, the command is just deploying project applications, one by one.

Read more about the deploy command in the Deploy your project guide.

It’s also important to know you can have multiple instances of your application’s cloud infrastructure up and running at the same time. This is achieved via Pulumi stacks external link:

Every Pulumi program is deployed to a stack. A stack is an isolated, independently configurable instance of a Pulumi program. Stacks are commonly used to denote different phases of development (such as development, staging and production) or feature branches (such as feature-x-dev, jane-feature-x-dev).

In the following section, we briefly cover the key files that form a Pulumi project, that can be found in your application folders. Note that if you want to dive deeper, you’re certainly encouraged to visit the official documentation external link which explains these concepts in more detail.

Project Files
anchor

The following are the key files of every Pulumi project.

Pulumi.yaml
anchor

The Pulumi.yaml project file specifies metadata about the Pulumi project. There can only be one project file per Pulumi project.

A Pulumi.yaml file might look something like the following:

name: api
runtime: nodejs
description: Cloud infrastructure needed by your project's (GraphQL) API.
backend:
  url: file://

One of the more important properties in this file is the backend property, which we cover in the following section.

Pulumi.stack-name.yaml
anchor

The Pulumi.{stack-name}.yaml file is a Pulumi stack settings external link file. There can be more than one stack settings files, for example, for a couple of different environments. For example, it’s possible to have Pulumi.dev.yaml, Pulumi.staging.yaml, Pulumi.production.yaml, and so on.

Environments are explained in more detail in the following Environments key topic.

index.ts
anchor

This is the entry point file in which you start to define your infrastructure (the Pulumi program). You can organize the code in any way you like. For example, in the default API, Admin Area, and Public Website applications, the index.ts file just imports different classes, which encapsulate different cloud infrastructure segments. These classes can be found in the pulumi folder.

State Files
anchor

Except for the files we mentioned in the previous section, there is also one other group of files the Pulumi solution produces. These are Pulumi project’s state files.

These files describe at what state your cloud infrastructure is currently at. For example, it contains a list of all deployed resources, various metadata, configuration, and so on. State files are stored per Pulumi program stack, and by default, they are stored in the .pulumi folder, located in your project root.

.pulumi (folder located in your project root)
.
├── api
│   ├── .pulumi
│   │   ├── backups
│   │   ├── history
│   │   └── stacks
├── apps
│   ├── admin
│   │   ├── .pulumi
│   │   │   ├── backups
│   │   │   ├── history
│   │   │   └── stacks
│   └── website
│       ├── .pulumi
│       │   ├── backups
│       │   ├── history
│       │   └── stacks
│  
└── (...)

Notice how state files are organized per project application:

  • api - API project application’s cloud infrastructure state files
  • apps/admin - Admin Area project application’s cloud infrastructure state files
  • apps/website - Website project application’s cloud infrastructure state files
Learn more about how to store cloud in state in CI/CD in the Cloud Infrastructure State Files key topic.

Different Backends
anchor

As mentioned, by default, Pulumi state files are stored in your project application folder, inside the .pulumi folder. While in some cases, storing them locally may work for you, in others, you may want to store these in a controlled, centralized, remote storage.

This is where the concept of Pulumi backends external link comes into play, which represent different storage services, that you can use for storing your state files.

For example, you can create a simple S3 bucket, and choose to store your files in it. You can also use the Pulumi Service, which, in addition to storing state files, also provides a couple of other cool features.

Read more about different backends in the following official documentation article external link.

FAQ
anchor

Are You Using Pulumi's Automation API?
anchor

Currently, Webiny is not using the Automation API external link. It’s actually using its own Pulumi SDK external link package, which is just a tiny wrapper over Pulumi CLI. Essentially, it enables programmatic use of the Pulumi CLI, which is similar to what the Automation API is also doing.

Is It Possible to Use a Different Infrastructure-as-Code Solution?
anchor

Yes, you can certainly use a different solution (for example CloudFormation external link or Terraform external link). Feel free to message us external link if you have this type of need. We’d be glad to assist in that regard.

What Is Stack Output?
anchor

Stack output represents values that are exported from your Pulumi program. For example, at the end of your index.ts file (located in root of your project application folder), you might have something like the following:

const cognitoUserPoolId = cognito.userPool.id;
const cognitoAppClientId = cognito.userPoolClient.id;
const updatePbSettingsFunction = pageBuilder.functions.updateSettings.arn;

Doing this can be useful if, for example, one, or more applications depend on these values.

Is It Possible to Read Stack Output From Another Stack?
anchor

It’s possible to read output from another stack. This is definitely useful if one or more of your current stack’s infrastructure resources are depending on one or more resources from another stack. To learn more, check out the Reading stack output article.